diff options
author | Sky <git@bunnies.cc> | 2013-10-21 18:24:29 +0100 |
---|---|---|
committer | Sky <git@bunnies.cc> | 2013-10-21 18:24:29 +0100 |
commit | aaf6fe894406ab8aa814de83692504493060e303 (patch) | |
tree | a7ac3a60534322f70cbdc34111228885e0606691 /gui | |
parent | 6892c11e9f287dcfb1e698f8f46233a01fb7abb6 (diff) | |
parent | 11813a0621dd7b500c2d7966a2671c0ab93be692 (diff) | |
download | MultiMC-aaf6fe894406ab8aa814de83692504493060e303.tar MultiMC-aaf6fe894406ab8aa814de83692504493060e303.tar.gz MultiMC-aaf6fe894406ab8aa814de83692504493060e303.tar.lz MultiMC-aaf6fe894406ab8aa814de83692504493060e303.tar.xz MultiMC-aaf6fe894406ab8aa814de83692504493060e303.zip |
Merge branch 'develop'
Diffstat (limited to 'gui')
43 files changed, 2068 insertions, 902 deletions
diff --git a/gui/EditNotesDialog.cpp b/gui/EditNotesDialog.cpp index 6cc389f6..535ca804 100644 --- a/gui/EditNotesDialog.cpp +++ b/gui/EditNotesDialog.cpp @@ -1,5 +1,6 @@ #include "EditNotesDialog.h" #include "ui_EditNotesDialog.h" +#include "gui/platform.h" #include <QIcon> #include <QApplication> @@ -10,9 +11,10 @@ EditNotesDialog::EditNotesDialog( QString notes, QString name, QWidget* parent ) QDialog(parent), ui(new Ui::EditNotesDialog) { + MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); ui->noteEditor->setText(notes); - setWindowTitle("Edit notes of " + m_instance_name); + setWindowTitle(tr("Edit notes of %1").arg(m_instance_name)); //connect(ui->closeButton, SIGNAL(clicked()), SLOT(close())); } diff --git a/gui/IconPickerDialog.cpp b/gui/IconPickerDialog.cpp index 2dd80292..ebacf87c 100644 --- a/gui/IconPickerDialog.cpp +++ b/gui/IconPickerDialog.cpp @@ -3,6 +3,7 @@ #include "instancedelegate.h" #include "ui_IconPickerDialog.h" #include "logic/lists/IconList.h" +#include "gui/platform.h" #include <QKeyEvent> #include <QPushButton> #include <QFileDialog> @@ -11,6 +12,7 @@ IconPickerDialog::IconPickerDialog(QWidget *parent) : QDialog(parent), ui(new Ui::IconPickerDialog) { + MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); setWindowModality(Qt::WindowModal); @@ -39,10 +41,10 @@ IconPickerDialog::IconPickerDialog(QWidget *parent) : contentsWidget->installEventFilter(this); - contentsWidget->setModel(MMC->icons()); + contentsWidget->setModel(MMC->icons().get()); - auto buttonAdd = ui->buttonBox->addButton("Add Icon",QDialogButtonBox::ResetRole); - auto buttonRemove = ui->buttonBox->addButton("Remove Icon",QDialogButtonBox::ResetRole); + auto buttonAdd = ui->buttonBox->addButton(tr("Add Icon"),QDialogButtonBox::ResetRole); + auto buttonRemove = ui->buttonBox->addButton(tr("Remove Icon"),QDialogButtonBox::ResetRole); connect(buttonAdd,SIGNAL(clicked(bool)),SLOT(addNewIcon())); @@ -87,7 +89,10 @@ bool IconPickerDialog::eventFilter ( QObject* obj, QEvent* evt) void IconPickerDialog::addNewIcon() { - QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Icons", QString(), "Icons (*.png *.jpg *.jpeg)"); + //: The title of the select icons open file dialog + QString selectIcons = tr("Select Icons"); + //: The type of icon files + QStringList fileNames = QFileDialog::getOpenFileNames(this, selectIcons, QString(), tr("Icons") + "(*.png *.jpg *.jpeg)"); MMC->icons()->installIcons(fileNames); } @@ -116,7 +121,7 @@ void IconPickerDialog::selectionChanged ( QItemSelection selected, QItemSelectio int IconPickerDialog::exec ( QString selection ) { - IconList * list = MMC->icons(); + auto list = MMC->icons(); auto contentsWidget = ui->iconView; selectedIconKey = selection; diff --git a/gui/LegacyModEditDialog.cpp b/gui/LegacyModEditDialog.cpp index 616fc050..b230193a 100644 --- a/gui/LegacyModEditDialog.cpp +++ b/gui/LegacyModEditDialog.cpp @@ -3,7 +3,7 @@ * 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 @@ -13,59 +13,74 @@ * limitations under the License. */ +#include "MultiMC.h" #include "LegacyModEditDialog.h" #include "ModEditDialogCommon.h" +#include "versionselectdialog.h" +#include "ProgressDialog.h" #include "ui_LegacyModEditDialog.h" -#include <logic/ModList.h> +#include "logic/ModList.h" +#include "logic/lists/ForgeVersionList.h" +#include "gui/platform.h" + #include <pathutils.h> #include <QFileDialog> +//#include <QMessageBox> #include <QDebug> #include <QEvent> #include <QKeyEvent> -LegacyModEditDialog::LegacyModEditDialog( LegacyInstance* inst, QWidget* parent ) : - m_inst(inst), - QDialog(parent), - ui(new Ui::LegacyModEditDialog) +LegacyModEditDialog::LegacyModEditDialog(LegacyInstance *inst, QWidget *parent) + : m_inst(inst), QDialog(parent), ui(new Ui::LegacyModEditDialog) { + MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); - + // Jar mods { ensureFolderPathExists(m_inst->jarModsDir()); m_jarmods = m_inst->jarModList(); - ui->jarModsTreeView->setModel(m_jarmods.data()); + ui->jarModsTreeView->setModel(m_jarmods.get()); #ifndef Q_OS_LINUX // FIXME: internal DnD causes segfaults later ui->jarModsTreeView->setDragDropMode(QAbstractItemView::DragDrop); // FIXME: DnD is glitched with contiguous (we move only first item in selection) ui->jarModsTreeView->setSelectionMode(QAbstractItemView::SingleSelection); #endif - ui->jarModsTreeView->installEventFilter( this ); + ui->jarModsTreeView->installEventFilter(this); m_jarmods->startWatching(); + auto smodel = ui->jarModsTreeView->selectionModel(); + connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), + SLOT(jarCurrent(QModelIndex, QModelIndex))); } // Core mods { ensureFolderPathExists(m_inst->coreModsDir()); m_coremods = m_inst->coreModList(); - ui->coreModsTreeView->setModel(m_coremods.data()); - ui->coreModsTreeView->installEventFilter( this ); + ui->coreModsTreeView->setModel(m_coremods.get()); + ui->coreModsTreeView->installEventFilter(this); m_coremods->startWatching(); + auto smodel = ui->coreModsTreeView->selectionModel(); + connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), + SLOT(coreCurrent(QModelIndex, QModelIndex))); } // Loader mods { ensureFolderPathExists(m_inst->loaderModsDir()); m_mods = m_inst->loaderModList(); - ui->loaderModTreeView->setModel(m_mods.data()); - ui->loaderModTreeView->installEventFilter( this ); + ui->loaderModTreeView->setModel(m_mods.get()); + ui->loaderModTreeView->installEventFilter(this); m_mods->startWatching(); + auto smodel = ui->loaderModTreeView->selectionModel(); + connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), + SLOT(loaderCurrent(QModelIndex, QModelIndex))); } // texture packs { ensureFolderPathExists(m_inst->texturePacksDir()); m_texturepacks = m_inst->texturePackList(); - ui->texPackTreeView->setModel(m_texturepacks.data()); - ui->texPackTreeView->installEventFilter( this ); + ui->texPackTreeView->setModel(m_texturepacks.get()); + ui->texPackTreeView->installEventFilter(this); m_texturepacks->startWatching(); } } @@ -79,112 +94,111 @@ LegacyModEditDialog::~LegacyModEditDialog() delete ui; } -bool LegacyModEditDialog::coreListFilter ( QKeyEvent* keyEvent ) +bool LegacyModEditDialog::coreListFilter(QKeyEvent *keyEvent) { - switch(keyEvent->key()) + switch (keyEvent->key()) { - case Qt::Key_Delete: - on_rmCoreBtn_clicked(); - return true; - case Qt::Key_Plus: - on_addCoreBtn_clicked(); - return true; - default: - break; + case Qt::Key_Delete: + on_rmCoreBtn_clicked(); + return true; + case Qt::Key_Plus: + on_addCoreBtn_clicked(); + return true; + default: + break; } - return QDialog::eventFilter( ui->coreModsTreeView, keyEvent ); + return QDialog::eventFilter(ui->coreModsTreeView, keyEvent); } -bool LegacyModEditDialog::jarListFilter ( QKeyEvent* keyEvent ) +bool LegacyModEditDialog::jarListFilter(QKeyEvent *keyEvent) { - switch(keyEvent->key()) + switch (keyEvent->key()) + { + case Qt::Key_Up: { - case Qt::Key_Up: + if (keyEvent->modifiers() & Qt::ControlModifier) { - if(keyEvent->modifiers() & Qt::ControlModifier) - { - on_moveJarUpBtn_clicked(); - return true; - } - break; + on_moveJarUpBtn_clicked(); + return true; } - case Qt::Key_Down: + break; + } + case Qt::Key_Down: + { + if (keyEvent->modifiers() & Qt::ControlModifier) { - if(keyEvent->modifiers() & Qt::ControlModifier) - { - on_moveJarDownBtn_clicked(); - return true; - } - break; - } - case Qt::Key_Delete: - on_rmJarBtn_clicked(); - return true; - case Qt::Key_Plus: - on_addJarBtn_clicked(); + on_moveJarDownBtn_clicked(); return true; - default: - break; + } + break; + } + case Qt::Key_Delete: + on_rmJarBtn_clicked(); + return true; + case Qt::Key_Plus: + on_addJarBtn_clicked(); + return true; + default: + break; } - return QDialog::eventFilter( ui->jarModsTreeView, keyEvent ); + return QDialog::eventFilter(ui->jarModsTreeView, keyEvent); } -bool LegacyModEditDialog::loaderListFilter ( QKeyEvent* keyEvent ) +bool LegacyModEditDialog::loaderListFilter(QKeyEvent *keyEvent) { - switch(keyEvent->key()) + switch (keyEvent->key()) { - case Qt::Key_Delete: - on_rmModBtn_clicked(); - return true; - case Qt::Key_Plus: - on_addModBtn_clicked(); - return true; - default: - break; + case Qt::Key_Delete: + on_rmModBtn_clicked(); + return true; + case Qt::Key_Plus: + on_addModBtn_clicked(); + return true; + default: + break; } - return QDialog::eventFilter( ui->loaderModTreeView, keyEvent ); + return QDialog::eventFilter(ui->loaderModTreeView, keyEvent); } -bool LegacyModEditDialog::texturePackListFilter ( QKeyEvent* keyEvent ) +bool LegacyModEditDialog::texturePackListFilter(QKeyEvent *keyEvent) { - switch(keyEvent->key()) + switch (keyEvent->key()) { - case Qt::Key_Delete: - on_rmTexPackBtn_clicked(); - return true; - case Qt::Key_Plus: - on_addTexPackBtn_clicked(); - return true; - default: - break; + case Qt::Key_Delete: + on_rmTexPackBtn_clicked(); + return true; + case Qt::Key_Plus: + on_addTexPackBtn_clicked(); + return true; + default: + break; } - return QDialog::eventFilter( ui->texPackTreeView, keyEvent ); + return QDialog::eventFilter(ui->texPackTreeView, keyEvent); } - -bool LegacyModEditDialog::eventFilter ( QObject* obj, QEvent* ev ) +bool LegacyModEditDialog::eventFilter(QObject *obj, QEvent *ev) { if (ev->type() != QEvent::KeyPress) { - return QDialog::eventFilter( obj, ev ); + return QDialog::eventFilter(obj, ev); } - QKeyEvent *keyEvent = static_cast<QKeyEvent*>(ev); - if(obj == ui->jarModsTreeView) + QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev); + if (obj == ui->jarModsTreeView) return jarListFilter(keyEvent); - if(obj == ui->coreModsTreeView) + if (obj == ui->coreModsTreeView) return coreListFilter(keyEvent); - if(obj == ui->loaderModTreeView) + if (obj == ui->loaderModTreeView) return loaderListFilter(keyEvent); - if(obj == ui->texPackTreeView) + if (obj == ui->texPackTreeView) return texturePackListFilter(keyEvent); - return QDialog::eventFilter( obj, ev ); + return QDialog::eventFilter(obj, ev); } - void LegacyModEditDialog::on_addCoreBtn_clicked() { - QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Core Mods"); - for(auto filename:fileNames) + //: Title of core mod selection dialog + QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select Core Mods")); + for (auto filename : fileNames) { m_coremods->stopWatching(); m_coremods->installMod(QFileInfo(filename)); @@ -193,12 +207,45 @@ void LegacyModEditDialog::on_addCoreBtn_clicked() } void LegacyModEditDialog::on_addForgeBtn_clicked() { - + VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this); + vselect.setFilter(1, m_inst->intendedVersionId()); + if (vselect.exec() && vselect.selectedVersion()) + { + ForgeVersionPtr forge = + std::dynamic_pointer_cast<ForgeVersion>(vselect.selectedVersion()); + if (!forge) + return; + auto entry = MMC->metacache()->resolveEntry("minecraftforge", forge->filename); + if (entry->stale) + { + DownloadJob *fjob = new DownloadJob("Forge download"); + fjob->addCacheDownload(forge->universal_url, entry); + ProgressDialog dlg(this); + dlg.exec(fjob); + if (dlg.result() == QDialog::Accepted) + { + m_jarmods->stopWatching(); + m_jarmods->installMod(QFileInfo(entry->getFullPath())); + m_jarmods->startWatching(); + } + else + { + // failed to download forge :/ + } + } + else + { + m_jarmods->stopWatching(); + m_jarmods->installMod(QFileInfo(entry->getFullPath())); + m_jarmods->startWatching(); + } + } } void LegacyModEditDialog::on_addJarBtn_clicked() { - QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Jar Mods"); - for(auto filename:fileNames) + //: Title of jar mod selection dialog + QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select Jar Mods")); + for (auto filename : fileNames) { m_jarmods->stopWatching(); m_jarmods->installMod(QFileInfo(filename)); @@ -207,8 +254,9 @@ void LegacyModEditDialog::on_addJarBtn_clicked() } void LegacyModEditDialog::on_addModBtn_clicked() { - QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Loader Mods"); - for(auto filename:fileNames) + //: Title of regular mod selection dialog + QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select Loader Mods")); + for (auto filename : fileNames) { m_mods->stopWatching(); m_mods->installMod(QFileInfo(filename)); @@ -217,8 +265,9 @@ void LegacyModEditDialog::on_addModBtn_clicked() } void LegacyModEditDialog::on_addTexPackBtn_clicked() { - QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Texture Packs"); - for(auto filename:fileNames) + //: Title of texture pack selection dialog + QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select Texture Packs")); + for (auto filename : fileNames) { m_texturepacks->stopWatching(); m_texturepacks->installMod(QFileInfo(filename)); @@ -230,8 +279,8 @@ void LegacyModEditDialog::on_moveJarDownBtn_clicked() { int first, last; auto list = ui->jarModsTreeView->selectionModel()->selectedRows(); - - if(!lastfirst(list, first, last)) + + if (!lastfirst(list, first, last)) return; m_jarmods->moveModsDown(first, last); @@ -240,8 +289,8 @@ void LegacyModEditDialog::on_moveJarUpBtn_clicked() { int first, last; auto list = ui->jarModsTreeView->selectionModel()->selectedRows(); - - if(!lastfirst(list, first, last)) + + if (!lastfirst(list, first, last)) return; m_jarmods->moveModsUp(first, last); } @@ -249,8 +298,8 @@ void LegacyModEditDialog::on_rmCoreBtn_clicked() { int first, last; auto list = ui->coreModsTreeView->selectionModel()->selectedRows(); - - if(!lastfirst(list, first, last)) + + if (!lastfirst(list, first, last)) return; m_coremods->stopWatching(); m_coremods->deleteMods(first, last); @@ -260,8 +309,8 @@ void LegacyModEditDialog::on_rmJarBtn_clicked() { int first, last; auto list = ui->jarModsTreeView->selectionModel()->selectedRows(); - - if(!lastfirst(list, first, last)) + + if (!lastfirst(list, first, last)) return; m_jarmods->stopWatching(); m_jarmods->deleteMods(first, last); @@ -271,8 +320,8 @@ void LegacyModEditDialog::on_rmModBtn_clicked() { int first, last; auto list = ui->loaderModTreeView->selectionModel()->selectedRows(); - - if(!lastfirst(list, first, last)) + + if (!lastfirst(list, first, last)) return; m_mods->stopWatching(); m_mods->deleteMods(first, last); @@ -282,8 +331,8 @@ void LegacyModEditDialog::on_rmTexPackBtn_clicked() { int first, last; auto list = ui->texPackTreeView->selectionModel()->selectedRows(); - - if(!lastfirst(list, first, last)) + + if (!lastfirst(list, first, last)) return; m_texturepacks->stopWatching(); m_texturepacks->deleteMods(first, last); @@ -302,8 +351,43 @@ void LegacyModEditDialog::on_viewTexPackBtn_clicked() openDirInDefaultProgram(m_inst->texturePacksDir(), true); } - void LegacyModEditDialog::on_buttonBox_rejected() { close(); -}
\ No newline at end of file +} + +void LegacyModEditDialog::jarCurrent(QModelIndex current, QModelIndex previous) +{ + if(!current.isValid()) + { + ui->jarMIFrame->clear(); + return; + } + int row = current.row(); + Mod &m = m_jarmods->operator[](row); + ui->jarMIFrame->updateWithMod(m); +} + +void LegacyModEditDialog::coreCurrent(QModelIndex current, QModelIndex previous) +{ + if(!current.isValid()) + { + ui->coreMIFrame->clear(); + return; + } + int row = current.row(); + Mod &m = m_coremods->operator[](row); + ui->coreMIFrame->updateWithMod(m); +} + +void LegacyModEditDialog::loaderCurrent(QModelIndex current, QModelIndex previous) +{ + if(!current.isValid()) + { + ui->loaderMIFrame->clear(); + return; + } + int row = current.row(); + Mod &m = m_mods->operator[](row); + ui->loaderMIFrame->updateWithMod(m); +} diff --git a/gui/LegacyModEditDialog.h b/gui/LegacyModEditDialog.h index bc9ebac0..fc3ea1e6 100644 --- a/gui/LegacyModEditDialog.h +++ b/gui/LegacyModEditDialog.h @@ -3,7 +3,7 @@ * 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 @@ -17,51 +17,62 @@ #include <QDialog> #include "logic/LegacyInstance.h" +#include <logic/net/DownloadJob.h> -namespace Ui { +namespace Ui +{ class LegacyModEditDialog; } class LegacyModEditDialog : public QDialog { Q_OBJECT - + public: - explicit LegacyModEditDialog(LegacyInstance* inst, QWidget *parent = 0); + explicit LegacyModEditDialog(LegacyInstance *inst, QWidget *parent = 0); ~LegacyModEditDialog(); - -private slots: - + +private +slots: + void on_addJarBtn_clicked(); void on_rmJarBtn_clicked(); void on_addForgeBtn_clicked(); void on_moveJarUpBtn_clicked(); void on_moveJarDownBtn_clicked(); - + void on_addCoreBtn_clicked(); void on_rmCoreBtn_clicked(); void on_viewCoreBtn_clicked(); - + void on_addModBtn_clicked(); void on_rmModBtn_clicked(); void on_viewModBtn_clicked(); - + void on_addTexPackBtn_clicked(); void on_rmTexPackBtn_clicked(); void on_viewTexPackBtn_clicked(); + // Questionable: SettingsDialog doesn't need this for some reason? void on_buttonBox_rejected(); + + void jarCurrent(QModelIndex current, QModelIndex previous); + void coreCurrent(QModelIndex current, QModelIndex previous); + void loaderCurrent(QModelIndex current, QModelIndex previous); + protected: bool eventFilter(QObject *obj, QEvent *ev); - bool jarListFilter( QKeyEvent* ev ); - bool coreListFilter( QKeyEvent* ev ); - bool loaderListFilter( QKeyEvent* ev ); - bool texturePackListFilter( QKeyEvent* ev ); + bool jarListFilter(QKeyEvent *ev); + bool coreListFilter(QKeyEvent *ev); + bool loaderListFilter(QKeyEvent *ev); + bool texturePackListFilter(QKeyEvent *ev); + private: Ui::LegacyModEditDialog *ui; - QSharedPointer<ModList> m_mods; - QSharedPointer<ModList> m_coremods; - QSharedPointer<ModList> m_jarmods; - QSharedPointer<ModList> m_texturepacks; - LegacyInstance * m_inst; + std::shared_ptr<ModList> m_mods; + std::shared_ptr<ModList> m_coremods; + std::shared_ptr<ModList> m_jarmods; + std::shared_ptr<ModList> m_texturepacks; + LegacyInstance *m_inst; + DownloadJobPtr forgeJob; }; diff --git a/gui/LegacyModEditDialog.ui b/gui/LegacyModEditDialog.ui index bd147c85..bb0d9ef2 100644 --- a/gui/LegacyModEditDialog.ui +++ b/gui/LegacyModEditDialog.ui @@ -23,179 +23,215 @@ <attribute name="title"> <string>Jar Mods</string> </attribute> - <layout class="QHBoxLayout" name="horizontalLayout"> + <layout class="QVBoxLayout" name="verticalLayout_2"> <item> - <widget class="ModListView" name="jarModsTreeView"> - <property name="verticalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOn</enum> - </property> - <property name="horizontalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOff</enum> - </property> - </widget> - </item> - <item> - <layout class="QVBoxLayout" name="jarModsButtonBox"> + <layout class="QHBoxLayout" name="horizontalLayout"> <item> - <widget class="QPushButton" name="addJarBtn"> - <property name="text"> - <string>&Add</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="rmJarBtn"> - <property name="text"> - <string>&Remove</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="addForgeBtn"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>MCForge</string> - </property> - </widget> - </item> - <item> - <spacer name="jarModsButtonSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> + <widget class="ModListView" name="jarModsTreeView"> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOn</enum> </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="moveJarUpBtn"> - <property name="text"> - <string>Move &Up</string> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> </property> </widget> </item> <item> - <widget class="QPushButton" name="moveJarDownBtn"> - <property name="text"> - <string>Move &Down</string> - </property> - </widget> + <layout class="QVBoxLayout" name="jarModsButtonBox"> + <item> + <widget class="QPushButton" name="addJarBtn"> + <property name="text"> + <string>&Add</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="rmJarBtn"> + <property name="text"> + <string>&Remove</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="addForgeBtn"> + <property name="text"> + <string>MCForge</string> + </property> + </widget> + </item> + <item> + <spacer name="jarModsButtonSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="moveJarUpBtn"> + <property name="text"> + <string>Move &Up</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="moveJarDownBtn"> + <property name="text"> + <string>Move &Down</string> + </property> + </widget> + </item> + </layout> </item> </layout> </item> + <item> + <widget class="MCModInfoFrame" name="jarMIFrame"> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + </widget> + </item> </layout> </widget> <widget class="QWidget" name="coreTab"> <attribute name="title"> <string>Core Mods</string> </attribute> - <layout class="QHBoxLayout" name="horizontalLayout_3"> + <layout class="QVBoxLayout" name="verticalLayout_3"> <item> - <widget class="ModListView" name="coreModsTreeView"> - <property name="dragDropMode"> - <enum>QAbstractItemView::DropOnly</enum> - </property> - </widget> - </item> - <item> - <layout class="QVBoxLayout" name="coreModsButtonBox"> - <item> - <widget class="QPushButton" name="addCoreBtn"> - <property name="text"> - <string>&Add</string> - </property> - </widget> - </item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> - <widget class="QPushButton" name="rmCoreBtn"> - <property name="text"> - <string>&Remove</string> + <widget class="ModListView" name="coreModsTreeView"> + <property name="dragDropMode"> + <enum>QAbstractItemView::DropOnly</enum> </property> </widget> </item> <item> - <spacer name="coreModsButtonSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="viewCoreBtn"> - <property name="text"> - <string>&View Folder</string> - </property> - </widget> + <layout class="QVBoxLayout" name="coreModsButtonBox"> + <item> + <widget class="QPushButton" name="addCoreBtn"> + <property name="text"> + <string>&Add</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="rmCoreBtn"> + <property name="text"> + <string>&Remove</string> + </property> + </widget> + </item> + <item> + <spacer name="coreModsButtonSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="viewCoreBtn"> + <property name="text"> + <string>&View Folder</string> + </property> + </widget> + </item> + </layout> </item> </layout> </item> + <item> + <widget class="MCModInfoFrame" name="coreMIFrame"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + </item> </layout> </widget> <widget class="QWidget" name="modTab"> <attribute name="title"> <string>Loader Mods</string> </attribute> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="ModListView" name="loaderModTreeView"> - <property name="acceptDrops"> - <bool>true</bool> - </property> - <property name="dragDropMode"> - <enum>QAbstractItemView::DropOnly</enum> - </property> - </widget> - </item> + <layout class="QVBoxLayout" name="verticalLayout_4"> <item> - <layout class="QVBoxLayout" name="mlModsButtonBox"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> - <widget class="QPushButton" name="addModBtn"> - <property name="text"> - <string>&Add</string> + <widget class="ModListView" name="loaderModTreeView"> + <property name="acceptDrops"> + <bool>true</bool> </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="rmModBtn"> - <property name="text"> - <string>&Remove</string> + <property name="dragDropMode"> + <enum>QAbstractItemView::DropOnly</enum> </property> </widget> </item> <item> - <spacer name="mlModsButtonSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="viewModBtn"> - <property name="text"> - <string>&View Folder</string> - </property> - </widget> + <layout class="QVBoxLayout" name="mlModsButtonBox"> + <item> + <widget class="QPushButton" name="addModBtn"> + <property name="text"> + <string>&Add</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="rmModBtn"> + <property name="text"> + <string>&Remove</string> + </property> + </widget> + </item> + <item> + <spacer name="mlModsButtonSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="viewModBtn"> + <property name="text"> + <string>&View Folder</string> + </property> + </widget> + </item> + </layout> </item> </layout> </item> + <item> + <widget class="MCModInfoFrame" name="loaderMIFrame"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + </item> </layout> </widget> <widget class="QWidget" name="texPackTab"> @@ -273,6 +309,12 @@ <extends>QTreeView</extends> <header>gui/ModListView.h</header> </customwidget> + <customwidget> + <class>MCModInfoFrame</class> + <extends>QFrame</extends> + <header>gui/MCModInfoFrame.h</header> + <container>1</container> + </customwidget> </customwidgets> <resources/> <connections/> diff --git a/gui/MCModInfoFrame.cpp b/gui/MCModInfoFrame.cpp new file mode 100644 index 00000000..b3f4ca5b --- /dev/null +++ b/gui/MCModInfoFrame.cpp @@ -0,0 +1,110 @@ +/* Copyright 2013 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MCModInfoFrame.h" +#include "ui_MCModInfoFrame.h" +#include <QMessageBox> +#include <QtGui> +void MCModInfoFrame::updateWithMod(Mod &m) +{ + if(m.type() == m.MOD_FOLDER) + { + clear(); + return; + } + + QString text = ""; + QString name = ""; + if(m.name().isEmpty()) name = m.id(); + else name = m.name(); + + if(m.homeurl().isEmpty()) text = name; + else text = "<a href=\"" + m.homeurl() + "\">" + name + "</a>"; + if(!m.authors().isEmpty()) text += " by " + m.authors(); + + setModText(text); + + if(m.description().isEmpty()) + { + setModDescription(tr("No description provided in mcmod.info")); + } + else + { + setModDescription(m.description()); + } +} + +void MCModInfoFrame::clear() +{ + setModText(tr("Select a mod to view title and authors...")); + setModDescription(tr("Select a mod to view description...")); +} + +MCModInfoFrame::MCModInfoFrame(QWidget *parent) : + QFrame(parent), + ui(new Ui::MCModInfoFrame) +{ + ui->setupUi(this); +} + +MCModInfoFrame::~MCModInfoFrame() +{ + delete ui; +} + +void MCModInfoFrame::setModText(QString text) +{ + ui->label_ModText->setText(text); +} + +void MCModInfoFrame::setModDescription(QString text) +{ + ui->label_ModDescription->setToolTip(""); + QString intermediatetext = text.trimmed(); + bool prev(false); + QChar rem('\n'); + QString finaltext; + finaltext.reserve(intermediatetext.size()); + foreach(const QChar& c, intermediatetext) + { + if(c == rem && prev){ + continue; + } + prev = c == rem; + finaltext += c; + } + QString labeltext; + labeltext.reserve(300); + if(finaltext.length() > 290) + { + ui->label_ModDescription->setOpenExternalLinks(false); + ui->label_ModDescription->setTextFormat(Qt::TextFormat::RichText); + desc = text; + labeltext.append("<html><body>" + finaltext.left(287) + "<a href=\"#mod_desc\">...</a></body></html>"); + QObject::connect(ui->label_ModDescription, &QLabel::linkActivated, this, &MCModInfoFrame::modDescEllipsisHandler); + } + else + { + ui->label_ModDescription->setTextFormat(Qt::TextFormat::PlainText); + labeltext.append(finaltext); + } + ui->label_ModDescription->setText(labeltext); +} +void MCModInfoFrame::modDescEllipsisHandler(const QString &link) +{ + QMessageBox msgbox; + msgbox.setText(desc); + msgbox.exec(); +} diff --git a/gui/MCModInfoFrame.h b/gui/MCModInfoFrame.h new file mode 100644 index 00000000..54c5d674 --- /dev/null +++ b/gui/MCModInfoFrame.h @@ -0,0 +1,46 @@ +/* Copyright 2013 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 <QFrame> +#include "logic/Mod.h" + +namespace Ui +{ +class MCModInfoFrame; +} + +class MCModInfoFrame : public QFrame +{ + Q_OBJECT + +public: + explicit MCModInfoFrame(QWidget *parent = 0); + ~MCModInfoFrame(); + + void setModText(QString text); + void setModDescription(QString text); + + void updateWithMod(Mod &m); + void clear(); + +public slots: + void modDescEllipsisHandler(const QString& link ); + +private: + Ui::MCModInfoFrame *ui; + QString desc; +}; diff --git a/gui/MCModInfoFrame.ui b/gui/MCModInfoFrame.ui new file mode 100644 index 00000000..60e0a65c --- /dev/null +++ b/gui/MCModInfoFrame.ui @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MCModInfoFrame</class> + <widget class="QFrame" name="MCModInfoFrame"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>527</width> + <height>113</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>120</height> + </size> + </property> + <property name="windowTitle"> + <string>Frame</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QLabel" name="label_ModText"> + <property name="text"> + <string>Select a mod to view title and authors...</string> + </property> + <property name="textFormat"> + <enum>Qt::RichText</enum> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_ModDescription"> + <property name="text"> + <string>Select a mod to view description...</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/gui/ModEditDialogCommon.cpp b/gui/ModEditDialogCommon.cpp index 5da0a039..692ac0c4 100644 --- a/gui/ModEditDialogCommon.cpp +++ b/gui/ModEditDialogCommon.cpp @@ -1,17 +1,40 @@ #include "ModEditDialogCommon.h" - -bool lastfirst (QModelIndexList & list, int & first, int & last) +#include <QDesktopServices> +#include <QMessageBox> +#include <QString> +#include <QUrl> +bool lastfirst(QModelIndexList &list, int &first, int &last) { - if(!list.size()) + if (!list.size()) return false; first = last = list[0].row(); - for(auto item: list) + for (auto item : list) { int row = item.row(); - if(row < first) + if (row < first) first = row; - if(row > last) + if (row > last) last = row; } return true; -}
\ No newline at end of file +} + +void showWebsiteForMod(QWidget *parentDlg, Mod &m) +{ + QString url = m.homeurl(); + if (url.size()) + { + // catch the cases where the protocol is missing + if(!url.startsWith("http")) + { + url = "http://" + url; + } + QDesktopServices::openUrl(url); + } + else + { + QMessageBox::warning( + parentDlg, parentDlg->tr("How sad!"), + parentDlg->tr("The mod author didn't provide a website link for this mod.")); + } +} diff --git a/gui/ModEditDialogCommon.h b/gui/ModEditDialogCommon.h index a27a8a82..bc8e223f 100644 --- a/gui/ModEditDialogCommon.h +++ b/gui/ModEditDialogCommon.h @@ -1,4 +1,7 @@ #pragma once #include <QAbstractItemModel> +#include <logic/Mod.h> -bool lastfirst (QModelIndexList & list, int & first, int & last);
\ No newline at end of file +bool lastfirst (QModelIndexList & list, int & first, int & last); + +void showWebsiteForMod(QWidget * parentDlg, Mod& m);
\ No newline at end of file diff --git a/gui/ModListView.cpp b/gui/ModListView.cpp index 34bd4af2..1d0e834c 100644 --- a/gui/ModListView.cpp +++ b/gui/ModListView.cpp @@ -30,6 +30,7 @@ void ModListView::setModel ( QAbstractItemModel* model ) auto head = header(); head->setStretchLastSection(false); head->setSectionResizeMode(0, QHeaderView::Stretch); - head->setSectionResizeMode(1, QHeaderView::ResizeToContents); + for(int i = 1; i < head->count(); i++) + head->setSectionResizeMode(i, QHeaderView::ResizeToContents); dropIndicatorPosition(); } diff --git a/gui/ModListView.h b/gui/ModListView.h index a9408fe7..69a26755 100644 --- a/gui/ModListView.h +++ b/gui/ModListView.h @@ -9,4 +9,5 @@ class ModListView: public QTreeView public: explicit ModListView ( QWidget* parent = 0 ); virtual void setModel ( QAbstractItemModel* model ); -};
\ No newline at end of file + +}; diff --git a/gui/OneSixModEditDialog.cpp b/gui/OneSixModEditDialog.cpp index 8e738fa1..88738938 100644 --- a/gui/OneSixModEditDialog.cpp +++ b/gui/OneSixModEditDialog.cpp @@ -1,9 +1,9 @@ /* Copyright 2013 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 @@ -12,41 +12,66 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#include "MultiMC.h" #include "OneSixModEditDialog.h" #include "ModEditDialogCommon.h" #include "ui_OneSixModEditDialog.h" -#include <logic/ModList.h> +#include "logic/ModList.h" +#include "logic/OneSixVersion.h" +#include "logic/EnabledItemFilter.h" +#include "logic/lists/ForgeVersionList.h" +#include "logic/ForgeInstaller.h" +#include "gui/versionselectdialog.h" +#include "gui/platform.h" +#include "ProgressDialog.h" + #include <pathutils.h> #include <QFileDialog> +#include <QMessageBox> #include <QDebug> #include <QEvent> #include <QKeyEvent> +#include <QDesktopServices> -OneSixModEditDialog::OneSixModEditDialog(OneSixInstance * inst, QWidget *parent): - m_inst(inst), - QDialog(parent), - ui(new Ui::OneSixModEditDialog) +OneSixModEditDialog::OneSixModEditDialog(OneSixInstance *inst, QWidget *parent) + : m_inst(inst), QDialog(parent), ui(new Ui::OneSixModEditDialog) { + MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); - //TODO: libraries! + // libraries! + + m_version = m_inst->getFullVersion(); + if (m_version) { - // yeah... here be the real dragons. + main_model = new EnabledItemFilter(this); + main_model->setActive(true); + main_model->setSourceModel(m_version.get()); + ui->libraryTreeView->setModel(main_model); + ui->libraryTreeView->installEventFilter(this); + ui->mainClassEdit->setText(m_version->mainClass); + updateVersionControls(); + } + else + { + disableVersionControls(); } // Loader mods { ensureFolderPathExists(m_inst->loaderModsDir()); m_mods = m_inst->loaderModList(); - ui->loaderModTreeView->setModel(m_mods.data()); - ui->loaderModTreeView->installEventFilter( this ); + ui->loaderModTreeView->setModel(m_mods.get()); + ui->loaderModTreeView->installEventFilter(this); m_mods->startWatching(); + auto smodel = ui->loaderModTreeView->selectionModel(); + connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), + SLOT(loaderCurrent(QModelIndex,QModelIndex))); } // resource packs { ensureFolderPathExists(m_inst->resourcePacksDir()); m_resourcepacks = m_inst->resourcePackList(); - ui->resPackTreeView->setModel(m_resourcepacks.data()); - ui->resPackTreeView->installEventFilter( this ); + ui->resPackTreeView->setModel(m_resourcepacks.get()); + ui->resPackTreeView->installEventFilter(this); m_resourcepacks->startWatching(); } } @@ -58,51 +83,165 @@ OneSixModEditDialog::~OneSixModEditDialog() delete ui; } -bool OneSixModEditDialog::loaderListFilter ( QKeyEvent* keyEvent ) +void OneSixModEditDialog::updateVersionControls() +{ + bool customVersion = m_inst->versionIsCustom(); + ui->customizeBtn->setEnabled(!customVersion); + ui->revertBtn->setEnabled(customVersion); + ui->forgeBtn->setEnabled(true); +} + +void OneSixModEditDialog::disableVersionControls() { - switch(keyEvent->key()) + ui->customizeBtn->setEnabled(false); + ui->revertBtn->setEnabled(false); + ui->forgeBtn->setEnabled(false); +} + +void OneSixModEditDialog::on_customizeBtn_clicked() +{ + if (m_inst->customizeVersion()) { - case Qt::Key_Delete: - on_rmModBtn_clicked(); - return true; - case Qt::Key_Plus: - on_addModBtn_clicked(); - return true; - default: - break; + m_version = m_inst->getFullVersion(); + main_model->setSourceModel(m_version.get()); + updateVersionControls(); } - return QDialog::eventFilter( ui->loaderModTreeView, keyEvent ); } -bool OneSixModEditDialog::resourcePackListFilter ( QKeyEvent* keyEvent ) +void OneSixModEditDialog::on_revertBtn_clicked() { - switch(keyEvent->key()) + auto reply = QMessageBox::question( + this, tr("Revert?"), tr("Do you want to revert the " + "version of this instance to its original configuration?"), + QMessageBox::Yes | QMessageBox::No); + if (reply == QMessageBox::Yes) { - case Qt::Key_Delete: - on_rmResPackBtn_clicked(); - return true; - case Qt::Key_Plus: - on_addResPackBtn_clicked(); - return true; - default: - break; + if (m_inst->revertCustomVersion()) + { + m_version = m_inst->getFullVersion(); + main_model->setSourceModel(m_version.get()); + updateVersionControls(); + } } - return QDialog::eventFilter( ui->resPackTreeView, keyEvent ); } +void OneSixModEditDialog::on_forgeBtn_clicked() +{ + VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this); + vselect.setFilter(1, m_inst->currentVersionId()); + if (vselect.exec() && vselect.selectedVersion()) + { + if (m_inst->versionIsCustom()) + { + auto reply = QMessageBox::question( + this, tr("Revert?"), + tr("This will revert any " + "changes you did to the version up to this point. Is that " + "OK?"), + QMessageBox::Yes | QMessageBox::No); + if (reply == QMessageBox::Yes) + { + m_inst->revertCustomVersion(); + m_inst->customizeVersion(); + { + m_version = m_inst->getFullVersion(); + main_model->setSourceModel(m_version.get()); + updateVersionControls(); + } + } + else + return; + } + else + { + m_inst->customizeVersion(); + m_version = m_inst->getFullVersion(); + main_model->setSourceModel(m_version.get()); + updateVersionControls(); + } + ForgeVersionPtr forgeVersion = + std::dynamic_pointer_cast<ForgeVersion>(vselect.selectedVersion()); + if (!forgeVersion) + return; + auto entry = MMC->metacache()->resolveEntry("minecraftforge", forgeVersion->filename); + if (entry->stale) + { + DownloadJob *fjob = new DownloadJob("Forge download"); + fjob->addCacheDownload(forgeVersion->installer_url, entry); + ProgressDialog dlg(this); + dlg.exec(fjob); + if (dlg.result() == QDialog::Accepted) + { + // install + QString forgePath = entry->getFullPath(); + ForgeInstaller forge(forgePath, forgeVersion->universal_url); + if (!forge.apply(m_version)) + { + // failure notice + } + } + else + { + // failed to download forge :/ + } + } + else + { + // install + QString forgePath = entry->getFullPath(); + ForgeInstaller forge(forgePath, forgeVersion->universal_url); + if (!forge.apply(m_version)) + { + // failure notice + } + } + } +} -bool OneSixModEditDialog::eventFilter ( QObject* obj, QEvent* ev ) +bool OneSixModEditDialog::loaderListFilter(QKeyEvent *keyEvent) +{ + switch (keyEvent->key()) + { + case Qt::Key_Delete: + on_rmModBtn_clicked(); + return true; + case Qt::Key_Plus: + on_addModBtn_clicked(); + return true; + default: + break; + } + return QDialog::eventFilter(ui->loaderModTreeView, keyEvent); +} + +bool OneSixModEditDialog::resourcePackListFilter(QKeyEvent *keyEvent) +{ + switch (keyEvent->key()) + { + case Qt::Key_Delete: + on_rmResPackBtn_clicked(); + return true; + case Qt::Key_Plus: + on_addResPackBtn_clicked(); + return true; + default: + break; + } + return QDialog::eventFilter(ui->resPackTreeView, keyEvent); +} + +bool OneSixModEditDialog::eventFilter(QObject *obj, QEvent *ev) { if (ev->type() != QEvent::KeyPress) { - return QDialog::eventFilter( obj, ev ); + return QDialog::eventFilter(obj, ev); } - QKeyEvent *keyEvent = static_cast<QKeyEvent*>(ev); - if(obj == ui->loaderModTreeView) + QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev); + if (obj == ui->loaderModTreeView) return loaderListFilter(keyEvent); - if(obj == ui->resPackTreeView) + if (obj == ui->resPackTreeView) return resourcePackListFilter(keyEvent); - return QDialog::eventFilter( obj, ev ); + return QDialog::eventFilter(obj, ev); } void OneSixModEditDialog::on_buttonBox_rejected() @@ -112,8 +251,9 @@ void OneSixModEditDialog::on_buttonBox_rejected() void OneSixModEditDialog::on_addModBtn_clicked() { - QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Loader Mods"); - for(auto filename:fileNames) + QStringList fileNames = QFileDialog::getOpenFileNames( + this, QApplication::translate("LegacyModEditDialog", "Select Loader Mods")); + for (auto filename : fileNames) { m_mods->stopWatching(); m_mods->installMod(QFileInfo(filename)); @@ -124,8 +264,8 @@ void OneSixModEditDialog::on_rmModBtn_clicked() { int first, last; auto list = ui->loaderModTreeView->selectionModel()->selectedRows(); - - if(!lastfirst(list, first, last)) + + if (!lastfirst(list, first, last)) return; m_mods->stopWatching(); m_mods->deleteMods(first, last); @@ -136,11 +276,11 @@ void OneSixModEditDialog::on_viewModBtn_clicked() openDirInDefaultProgram(m_inst->loaderModsDir(), true); } - void OneSixModEditDialog::on_addResPackBtn_clicked() { - QStringList fileNames = QFileDialog::getOpenFileNames(this, "Select Resource Packs"); - for(auto filename:fileNames) + QStringList fileNames = QFileDialog::getOpenFileNames( + this, QApplication::translate("LegacyModEditDialog", "Select Resource Packs")); + for (auto filename : fileNames) { m_resourcepacks->stopWatching(); m_resourcepacks->installMod(QFileInfo(filename)); @@ -151,8 +291,8 @@ void OneSixModEditDialog::on_rmResPackBtn_clicked() { int first, last; auto list = ui->resPackTreeView->selectionModel()->selectedRows(); - - if(!lastfirst(list, first, last)) + + if (!lastfirst(list, first, last)) return; m_resourcepacks->stopWatching(); m_resourcepacks->deleteMods(first, last); @@ -163,3 +303,14 @@ void OneSixModEditDialog::on_viewResPackBtn_clicked() openDirInDefaultProgram(m_inst->resourcePacksDir(), true); } +void OneSixModEditDialog::loaderCurrent(QModelIndex current, QModelIndex previous) +{ + if(!current.isValid()) + { + ui->frame->clear(); + return; + } + int row = current.row(); + Mod &m = m_mods->operator[](row); + ui->frame->updateWithMod(m); +} diff --git a/gui/OneSixModEditDialog.h b/gui/OneSixModEditDialog.h index 3430bd26..5376e526 100644 --- a/gui/OneSixModEditDialog.h +++ b/gui/OneSixModEditDialog.h @@ -1,9 +1,9 @@ /* Copyright 2013 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 @@ -18,35 +18,50 @@ #include <logic/OneSixInstance.h> -namespace Ui { - class OneSixModEditDialog; +class EnabledItemFilter; +namespace Ui +{ +class OneSixModEditDialog; } class OneSixModEditDialog : public QDialog { Q_OBJECT - + public: - explicit OneSixModEditDialog(OneSixInstance* inst, QWidget *parent = 0); + explicit OneSixModEditDialog(OneSixInstance *inst, QWidget *parent = 0); virtual ~OneSixModEditDialog(); - -private slots: + +private +slots: void on_addModBtn_clicked(); void on_rmModBtn_clicked(); void on_viewModBtn_clicked(); - + void on_addResPackBtn_clicked(); void on_rmResPackBtn_clicked(); void on_viewResPackBtn_clicked(); // Questionable: SettingsDialog doesn't need this for some reason? void on_buttonBox_rejected(); + void on_forgeBtn_clicked(); + void on_customizeBtn_clicked(); + void on_revertBtn_clicked(); + void updateVersionControls(); + void disableVersionControls(); + protected: bool eventFilter(QObject *obj, QEvent *ev); - bool loaderListFilter( QKeyEvent* ev ); - bool resourcePackListFilter( QKeyEvent* ev ); + bool loaderListFilter(QKeyEvent *ev); + bool resourcePackListFilter(QKeyEvent *ev); + private: Ui::OneSixModEditDialog *ui; - QSharedPointer<ModList> m_mods; - QSharedPointer<ModList> m_resourcepacks; - OneSixInstance * m_inst; + std::shared_ptr<OneSixVersion> m_version; + std::shared_ptr<ModList> m_mods; + std::shared_ptr<ModList> m_resourcepacks; + EnabledItemFilter *main_model; + OneSixInstance *m_inst; +public +slots: + void loaderCurrent(QModelIndex current, QModelIndex previous); }; diff --git a/gui/OneSixModEditDialog.ui b/gui/OneSixModEditDialog.ui index 3feca726..6d70200a 100644 --- a/gui/OneSixModEditDialog.ui +++ b/gui/OneSixModEditDialog.ui @@ -6,15 +6,15 @@ <rect> <x>0</x> <y>0</y> - <width>543</width> - <height>423</height> + <width>555</width> + <height>463</height> </rect> </property> <property name="windowTitle"> <string>Dialog</string> </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> <widget class="QTabWidget" name="tabWidget"> <property name="enabled"> <bool>true</bool> @@ -26,64 +26,118 @@ </size> </property> <property name="currentIndex"> - <number>0</number> - </property> - <property name="elideMode"> - <enum>Qt::ElideNone</enum> - </property> - <property name="tabsClosable"> - <bool>false</bool> + <number>1</number> </property> <widget class="QWidget" name="libTab"> <attribute name="title"> - <string>Library</string> + <string>Version</string> </attribute> <layout class="QHBoxLayout" name="horizontalLayout"> <item> - <widget class="ModListView" name="jarModsTreeView"> - <property name="verticalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOn</enum> - </property> - <property name="horizontalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOff</enum> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="modTab"> - <attribute name="title"> - <string>Loader Mods</string> - </attribute> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="ModListView" name="loaderModTreeView"> - <property name="acceptDrops"> - <bool>true</bool> - </property> - <property name="dragDropMode"> - <enum>QAbstractItemView::DropOnly</enum> - </property> - </widget> + <layout class="QVBoxLayout" name="verticalLayout_10"> + <item> + <widget class="ModListView" name="libraryTreeView"> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOn</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_7"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Main Class:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="mainClassEdit"> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + </layout> </item> <item> - <layout class="QVBoxLayout" name="verticalLayout_2"> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QPushButton" name="forgeBtn"> + <property name="toolTip"> + <string>Replace any current custom version with Minecraft Forge</string> + </property> + <property name="text"> + <string>Install Forge</string> + </property> + </widget> + </item> <item> - <widget class="QPushButton" name="addModBtn"> + <widget class="QPushButton" name="customizeBtn"> + <property name="toolTip"> + <string>Create an customized copy of the base version</string> + </property> + <property name="text"> + <string>Customize</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="revertBtn"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>Revert to original base version</string> + </property> + <property name="text"> + <string>Revert</string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line"> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="addLibraryBtn"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>Add new libraries</string> + </property> <property name="text"> <string>&Add</string> </property> </widget> </item> <item> - <widget class="QPushButton" name="rmModBtn"> + <widget class="QPushButton" name="removeLibraryBtn"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>Remove selected libraries</string> + </property> <property name="text"> <string>&Remove</string> </property> </widget> </item> <item> - <spacer name="verticalSpacer"> + <spacer name="verticalSpacer_7"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> @@ -95,15 +149,87 @@ </property> </spacer> </item> + </layout> + </item> + </layout> + </widget> + <widget class="QWidget" name="modTab"> + <attribute name="title"> + <string>Loader Mods</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_6"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> - <widget class="QPushButton" name="viewModBtn"> - <property name="text"> - <string>&View Folder</string> - </property> - </widget> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="ModListView" name="loaderModTreeView"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="acceptDrops"> + <bool>true</bool> + </property> + <property name="dragDropMode"> + <enum>QAbstractItemView::DropOnly</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QPushButton" name="addModBtn"> + <property name="text"> + <string>&Add</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="rmModBtn"> + <property name="text"> + <string>&Remove</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="viewModBtn"> + <property name="text"> + <string>&View Folder</string> + </property> + </widget> + </item> + </layout> </item> </layout> </item> + <item> + <widget class="MCModInfoFrame" name="frame"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> </layout> </widget> <widget class="QWidget" name="resPackTab"> @@ -163,7 +289,7 @@ </widget> </widget> </item> - <item> + <item row="1" column="0"> <widget class="QDialogButtonBox" name="buttonBox"> <property name="autoFillBackground"> <bool>false</bool> @@ -181,6 +307,12 @@ <extends>QTreeView</extends> <header>gui/ModListView.h</header> </customwidget> + <customwidget> + <class>MCModInfoFrame</class> + <extends>QFrame</extends> + <header>gui/MCModInfoFrame.h</header> + <container>1</container> + </customwidget> </customwidgets> <resources/> <connections/> diff --git a/gui/taskdialog.cpp b/gui/ProgressDialog.cpp index 8c745b38..2e5251a0 100644 --- a/gui/taskdialog.cpp +++ b/gui/ProgressDialog.cpp @@ -13,88 +13,91 @@ * limitations under the License. */ -#include "taskdialog.h" -#include "ui_taskdialog.h" +#include "ProgressDialog.h" +#include "ui_ProgressDialog.h" #include <QKeyEvent> #include "logic/tasks/Task.h" +#include "gui/platform.h" -TaskDialog::TaskDialog(QWidget *parent) : +ProgressDialog::ProgressDialog(QWidget *parent) : QDialog(parent), - ui(new Ui::TaskDialog) + ui(new Ui::ProgressDialog) { + MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); updateSize(); - changeProgress(0); + changeProgress(0,100); } -TaskDialog::~TaskDialog() +ProgressDialog::~ProgressDialog() { delete ui; } -void TaskDialog::updateSize() +void ProgressDialog::updateSize() { resize(QSize(480, minimumSizeHint().height())); } -void TaskDialog::exec(Task *task) +int ProgressDialog::exec(ProgressProvider *task) { this->task = task; // Connect signals. connect(task, SIGNAL(started()), SLOT(onTaskStarted())); - connect(task, SIGNAL(failed(QString)), SLOT(onTaskEnded())); - connect(task, SIGNAL(succeeded()), SLOT(onTaskEnded())); - connect(task, SIGNAL(statusChanged(const QString&)), SLOT(changeStatus(const QString&))); - connect(task, SIGNAL(progressChanged(int)), SLOT(changeProgress(int))); + connect(task, SIGNAL(failed(QString)), SLOT(onTaskFailed(QString))); + connect(task, SIGNAL(succeeded()), SLOT(onTaskSucceeded())); + connect(task, SIGNAL(status(QString)), SLOT(changeStatus(const QString&))); + connect(task, SIGNAL(progress(qint64,qint64)), SLOT(changeProgress(qint64,qint64))); // this makes sure that the task is started after the dialog is created - QMetaObject::invokeMethod(task, "startTask", Qt::QueuedConnection); - QDialog::exec(); + QMetaObject::invokeMethod(task, "start", Qt::QueuedConnection); + return QDialog::exec(); } -Task* TaskDialog::getTask() +ProgressProvider* ProgressDialog::getTask() { return task; } -void TaskDialog::onTaskStarted() +void ProgressDialog::onTaskStarted() { } -void TaskDialog::onTaskEnded() +void ProgressDialog::onTaskFailed(QString failure) { - close(); + reject(); } -void TaskDialog::changeStatus(const QString &status) +void ProgressDialog::onTaskSucceeded() +{ + accept(); +} + +void ProgressDialog::changeStatus(const QString &status) { ui->statusLabel->setText(status); updateSize(); } -void TaskDialog::changeProgress(int progress) +void ProgressDialog::changeProgress(qint64 current, qint64 total) { - if (progress < 0) - progress = 0; - else if (progress > 100) - progress = 100; - - ui->taskProgressBar->setValue(progress); + ui->taskProgressBar->setMaximum(total); + ui->taskProgressBar->setValue(current); } -void TaskDialog::keyPressEvent(QKeyEvent* e) +void ProgressDialog::keyPressEvent(QKeyEvent* e) { if (e->key() == Qt::Key_Escape) return; QDialog::keyPressEvent(e); } -void TaskDialog::closeEvent(QCloseEvent* e) +void ProgressDialog::closeEvent(QCloseEvent* e) { if (task && task->isRunning()) { diff --git a/gui/taskdialog.h b/gui/ProgressDialog.h index 3d31b7be..ac6bb412 100644 --- a/gui/taskdialog.h +++ b/gui/ProgressDialog.h @@ -18,32 +18,33 @@ #include <QDialog> -class Task; +class ProgressProvider; namespace Ui { -class TaskDialog; +class ProgressDialog; } -class TaskDialog : public QDialog +class ProgressDialog : public QDialog { Q_OBJECT public: - explicit TaskDialog(QWidget *parent = 0); - ~TaskDialog(); + explicit ProgressDialog(QWidget *parent = 0); + ~ProgressDialog(); void updateSize(); - void exec(Task* task); + int exec(ProgressProvider* task); - Task* getTask(); + ProgressProvider* getTask(); public slots: void onTaskStarted(); - void onTaskEnded(); + void onTaskFailed(QString failure); + void onTaskSucceeded(); void changeStatus(const QString& status); - void changeProgress(int progress); + void changeProgress(qint64 current, qint64 total); signals: @@ -53,9 +54,9 @@ protected: virtual void closeEvent(QCloseEvent* e); private: - Ui::TaskDialog *ui; + Ui::ProgressDialog *ui; - Task* task; + ProgressProvider* task; }; #endif // TASKDIALOG_H diff --git a/gui/taskdialog.ui b/gui/ProgressDialog.ui index 1cdf7978..a56d2a92 100644 --- a/gui/taskdialog.ui +++ b/gui/ProgressDialog.ui @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>TaskDialog</class> - <widget class="QDialog" name="TaskDialog"> + <class>ProgressDialog</class> + <widget class="QDialog" name="ProgressDialog"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>400</width> - <height>58</height> + <height>68</height> </rect> </property> <property name="minimumSize"> diff --git a/gui/aboutdialog.cpp b/gui/aboutdialog.cpp index 9792d4fe..7105446c 100644 --- a/gui/aboutdialog.cpp +++ b/gui/aboutdialog.cpp @@ -2,11 +2,13 @@ #include "ui_aboutdialog.h" #include <QIcon> #include <MultiMC.h> +#include "gui/platform.h" AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDialog) { + MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); ui->icon->setPixmap(QIcon(":/icons/multimc/scalable/apps/multimc.svg").pixmap(64)); diff --git a/gui/aboutdialog.ui b/gui/aboutdialog.ui index 6b8f906d..66b40036 100644 --- a/gui/aboutdialog.ui +++ b/gui/aboutdialog.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>450</width> - <height>400</height> + <height>429</height> </rect> </property> <property name="minimumSize"> @@ -58,6 +58,9 @@ <property name="text"> <string/> </property> + <property name="pixmap"> + <pixmap resource="../multimc.qrc">:/icons/multimc/scalable/apps/multimc.svg</pixmap> + </property> </widget> </item> <item> @@ -92,16 +95,13 @@ </item> <item> <widget class="QToolBox" name="toolBox"> - <property name="currentIndex"> - <number>0</number> - </property> <widget class="QWidget" name="aboutPage"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>432</width> - <height>153</height> + <height>191</height> </rect> </property> <attribute name="label"> @@ -111,7 +111,7 @@ <item> <widget class="QLabel" name="aboutLabel"> <property name="text"> - <string>MultiMC is a custom launcher that makes managing Minecraft easier by allowing you to have multiple installations of Minecraft at once.</string> + <string><html><head/><body><p>MultiMC is a custom launcher that makes managing Minecraft easier by allowing you to have multiple instances of Minecraft at once.</p></body></html></string> </property> <property name="alignment"> <set>Qt::AlignCenter</set> @@ -145,7 +145,7 @@ </font> </property> <property name="text"> - <string><html><head/><body><p><a href="http://github.com/Forkk/MultiMC5"><span style=" text-decoration: underline; color:#0000ff;">http://github.com/Forkk/MultiMC5</span></a></p></body></html></string> + <string><html><head/><body><p><a href="http://github.com/Forkk/MultiMC5"><span style=" text-decoration: underline; color:#0000ff;">http://github.com/MultiMC/MultiMC5</span></a></p></body></html></string> </property> <property name="alignment"> <set>Qt::AlignCenter</set> @@ -160,7 +160,7 @@ <x>0</x> <y>0</y> <width>432</width> - <height>153</height> + <height>191</height> </rect> </property> <attribute name="label"> @@ -176,16 +176,37 @@ <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Andrew Okin &lt;<a href="mailto:forkk@forkk.net"><span style=" text-decoration: underline; color:#0000ff;">forkk@forkk.net</span></a>&gt;</p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Petr Mrázek &lt;<a href="mailto:peterix@gmail.com"><span style=" text-decoration: underline; color:#0000ff;">peterix@gmail.com</span></a>&gt;</p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Orochimarufan &lt;<a href="mailto:orochimarufan.x3@gmail.com"><span style=" text-decoration: underline; color:#0000ff;">orochimarufan.x3@gmail.com</span></a>&gt;</p></body></html></string> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Andrew Okin &lt;</span><a href="mailto:forkk@forkk.net"><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#0000ff;">forkk@forkk.net</span></a><span style=" font-family:'Ubuntu'; font-size:11pt;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Petr Mrázek &lt;</span><a href="mailto:peterix@gmail.com"><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#0000ff;">peterix@gmail.com</span></a><span style=" font-family:'Ubuntu'; font-size:11pt;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Orochimarufan &lt;</span><a href="mailto:orochimarufan.x3@gmail.com"><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#0000ff;">orochimarufan.x3@gmail.com</span></a><span style=" font-family:'Ubuntu'; font-size:11pt;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">TakSuyu &lt;</span><a href="mailto:taksuyu@gmail.com"><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#0000ff;">taksuyu@gmail.com</span></a><span style=" font-family:'Ubuntu'; font-size:11pt;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Sky Welch &lt;</span><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#0000ff;">multimc@bunnies.cc</span><span style=" font-family:'Ubuntu'; font-size:11pt;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">Kilobyte &lt;</span><a href="mailto:stiepen22@gmx.de"><span style=" font-family:'Ubuntu'; font-size:11pt; text-decoration: underline; color:#0000ff;">stiepen22@gmx.de</span></a><span style=" font-family:'Ubuntu'; font-size:11pt;">&gt;</span></p></body></html></string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="translationInfo"> + <property name="text"> + <string extracomment="Hey, Translator, feel free to put credit to you here">No Language file loaded.</string> + </property> + <property name="readOnly"> + <bool>true</bool> </property> </widget> </item> </layout> </widget> <widget class="QWidget" name="licensePage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>432</width> + <height>191</height> + </rect> + </property> <attribute name="label"> <string>License</string> </attribute> @@ -205,44 +226,45 @@ p, li { white-space: pre-wrap; } <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Copyright 2012 MultiMC Contributors</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">you may not use this file except in compliance with the License.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">You may obtain a copy of the License at</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> http://www.apache.org/licenses/LICENSE-2.0</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Unless required by applicable law or agreed to in writing, software</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">See the License for the specific language governing permissions and</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">limitations under the License.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">MultiMC uses bspatch, </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Copyright 2003-2005 Colin Percival</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">All rights reserved</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Redistribution and use in source and binary forms, with or without</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">modification, are permitted providing that the following conditions</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">are met: </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">1. Redistributions of source code must retain the above copyright</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> notice, this list of conditions and the following disclaimer.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">2. Redistributions in binary form must reproduce the above copyright</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> notice, this list of conditions and the following disclaimer in the</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> documentation and/or other materials provided with the distribution.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">POSSIBILITY OF SUCH DAMAGE.</span></p></body></html></string> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">Copyright 2012 MultiMC Contributors</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">you may not use this file except in compliance with the License.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">You may obtain a copy of the License at</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;"> http://www.apache.org/licenses/LICENSE-2.0</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">Unless required by applicable law or agreed to in writing, software</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">See the License for the specific language governing permissions and</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">limitations under the License.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">MultiMC uses QSLog, </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">Copyright (c) 2010, Razvan Petru</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">All rights reserved.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">Redistribution and use in source and binary forms, with or without modification,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">are permitted provided that the following conditions are met:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">* Redistributions of source code must retain the above copyright notice, this</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;"> list of conditions and the following disclaimer.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">* Redistributions in binary form must reproduce the above copyright notice, this</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;"> list of conditions and the following disclaimer in the documentation and/or other</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;"> materials provided with the distribution.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">* The name of the contributors may not be used to endorse or promote products</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;"> derived from this software without specific prior written permission.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; AND</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">OF THE POSSIBILITY OF SUCH DAMAGE.</span></p></body></html></string> </property> </widget> </item> @@ -254,6 +276,9 @@ p, li { white-space: pre-wrap; } <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> <widget class="QPushButton" name="aboutQt"> + <property name="autoFillBackground"> + <bool>false</bool> + </property> <property name="text"> <string>About Qt</string> </property> @@ -283,6 +308,8 @@ p, li { white-space: pre-wrap; } </item> </layout> </widget> - <resources/> + <resources> + <include location="../multimc.qrc"/> + </resources> <connections/> </ui> diff --git a/gui/consolewindow.cpp b/gui/consolewindow.cpp index 811900a2..deeedd65 100644 --- a/gui/consolewindow.cpp +++ b/gui/consolewindow.cpp @@ -2,13 +2,19 @@ #include "ui_consolewindow.h" #include <QScrollBar> +#include <QMessageBox> -ConsoleWindow::ConsoleWindow(QWidget *parent) : +#include <gui/platform.h> + +ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent) : QDialog(parent), ui(new Ui::ConsoleWindow), - m_mayclose(true) + m_mayclose(true), + proc(mcproc) { + MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); + connect(mcproc, SIGNAL(ended()), this, SLOT(onEnded())); } ConsoleWindow::~ConsoleWindow() @@ -20,7 +26,7 @@ void ConsoleWindow::writeColor(QString text, const char *color) { // append a paragraph if (color != nullptr) - ui->text->appendHtml(QString("<font color=%1>%2</font>").arg(color).arg(text)); + ui->text->appendHtml(QString("<font color=\"%1\">%2</font>").arg(color).arg(text)); else ui->text->appendPlainText(text); // scroll down @@ -33,6 +39,11 @@ void ConsoleWindow::write(QString data, MessageLevel::Enum mode) if (data.endsWith('\n')) data = data.left(data.length()-1); QStringList paragraphs = data.split('\n'); + for(QString ¶graph : paragraphs) + { + paragraph = paragraph.trimmed(); + } + QListIterator<QString> iter(paragraphs); if (mode == MessageLevel::MultiMC) while(iter.hasNext()) @@ -40,6 +51,15 @@ void ConsoleWindow::write(QString data, MessageLevel::Enum mode) else if (mode == MessageLevel::Error) while(iter.hasNext()) writeColor(iter.next(), "red"); + else if (mode == MessageLevel::Warning) + while(iter.hasNext()) + writeColor(iter.next(), "orange"); + else if (mode == MessageLevel::Fatal) + while(iter.hasNext()) + writeColor(iter.next(), "pink"); + else if (mode == MessageLevel::Debug) + while(iter.hasNext()) + writeColor(iter.next(), "green"); // TODO: implement other MessageLevels else while(iter.hasNext()) @@ -72,3 +92,26 @@ void ConsoleWindow::closeEvent(QCloseEvent * event) else QDialog::closeEvent(event); } + +void ConsoleWindow::on_btnKillMinecraft_clicked() +{ + ui->btnKillMinecraft->setEnabled(false); + QMessageBox r_u_sure; + //: Main question of the kill confirmation dialog + r_u_sure.setText(tr("Kill Minecraft?")); + r_u_sure.setInformativeText(tr("This can cause the instance to get corrupted and should only be used if Minecraft is frozen for some reason")); + r_u_sure.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + r_u_sure.setDefaultButton(QMessageBox::Yes); + if (r_u_sure.exec() == QMessageBox::Yes) + proc->killMinecraft(); + else + ui->btnKillMinecraft->setEnabled(true); + r_u_sure.close(); +} + +void ConsoleWindow::onEnded() +{ + ui->btnKillMinecraft->setEnabled(false); + // TODO: Check why this doesn't work + if (!proc->exitCode()) this->close(); +} diff --git a/gui/consolewindow.h b/gui/consolewindow.h index 60bec69f..6a6c9e50 100644 --- a/gui/consolewindow.h +++ b/gui/consolewindow.h @@ -13,7 +13,7 @@ class ConsoleWindow : public QDialog Q_OBJECT public: - explicit ConsoleWindow(QWidget *parent = 0); + explicit ConsoleWindow(MinecraftProcess *proc, QWidget *parent = 0); ~ConsoleWindow(); /** @@ -48,12 +48,15 @@ public slots: private slots: void on_closeButton_clicked(); + void on_btnKillMinecraft_clicked(); + void onEnded(); protected: void closeEvent(QCloseEvent *); private: Ui::ConsoleWindow *ui; + MinecraftProcess *proc; bool m_mayclose; }; diff --git a/gui/consolewindow.ui b/gui/consolewindow.ui index 9a766543..8dc80015 100644 --- a/gui/consolewindow.ui +++ b/gui/consolewindow.ui @@ -63,6 +63,13 @@ </spacer> </item> <item> + <widget class="QPushButton" name="btnKillMinecraft"> + <property name="text"> + <string>Kill Minecraft</string> + </property> + </widget> + </item> + <item> <widget class="QPushButton" name="closeButton"> <property name="text"> <string>Close</string> diff --git a/gui/instancedelegate.h b/gui/instancedelegate.h index c80f95a5..56bc34ba 100644 --- a/gui/instancedelegate.h +++ b/gui/instancedelegate.h @@ -9,4 +9,4 @@ public: protected: void paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const; QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const; -};
\ No newline at end of file +}; diff --git a/gui/instancesettings.cpp b/gui/instancesettings.cpp index dfb04f3d..73eb6627 100644 --- a/gui/instancesettings.cpp +++ b/gui/instancesettings.cpp @@ -19,12 +19,14 @@ #include "instancesettings.h" #include "ui_instancesettings.h" +#include "gui/platform.h" InstanceSettings::InstanceSettings( SettingsObject * obj, QWidget *parent) : m_obj(obj), QDialog(parent), ui(new Ui::InstanceSettings) { + MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); loadSettings(); } diff --git a/gui/instancesettings.ui b/gui/instancesettings.ui index 49309f11..b536e9ff 100644 --- a/gui/instancesettings.ui +++ b/gui/instancesettings.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>477</width> + <width>526</width> <height>590</height> </rect> </property> @@ -249,7 +249,7 @@ <number>64</number> </property> <property name="maximum"> - <number>512</number> + <number>999999999</number> </property> <property name="singleStep"> <number>8</number> @@ -395,6 +395,7 @@ </widget> <tabstops> <tabstop>settingsTabs</tabstop> + <tabstop>buttonBox</tabstop> <tabstop>windowSizeGroupBox</tabstop> <tabstop>maximizedCheckBox</tabstop> <tabstop>windowWidthSpinBox</tabstop> @@ -407,6 +408,7 @@ <tabstop>memoryGroupBox</tabstop> <tabstop>minMemSpinBox</tabstop> <tabstop>maxMemSpinBox</tabstop> + <tabstop>permGenSpinBox</tabstop> <tabstop>javaSettingsGroupBox</tabstop> <tabstop>javaPathTextBox</tabstop> <tabstop>pushButton</tabstop> @@ -414,7 +416,6 @@ <tabstop>customCommandsGroupBox</tabstop> <tabstop>preLaunchCmdTextBox</tabstop> <tabstop>postExitCmdTextBox</tabstop> - <tabstop>buttonBox</tabstop> </tabstops> <resources/> <connections/> diff --git a/gui/logindialog.cpp b/gui/logindialog.cpp index a4dad1c1..aeaaaa9e 100644 --- a/gui/logindialog.cpp +++ b/gui/logindialog.cpp @@ -16,16 +16,25 @@ #include "logindialog.h" #include "ui_logindialog.h" #include "keyring.h" -#include <QDebug> +#include "gui/platform.h" +#include "MultiMC.h" + +#include <QFile> +#include <QJsonObject> +#include <QJsonArray> +#include <QJsonParseError> +#include "logic/net/HttpMetaCache.h" +#include <logger/QsLog.h> LoginDialog::LoginDialog(QWidget *parent, const QString& loginErrMsg) : QDialog(parent), ui(new Ui::LoginDialog) { + MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); - //TODO: make translateable - offlineButton = new QPushButton("Offline Once"); + //: Use offline mode one time + offlineButton = new QPushButton(tr("Offline Once")); ui->loginButtonBox->addButton(offlineButton, QDialogButtonBox::ActionRole); @@ -33,8 +42,8 @@ LoginDialog::LoginDialog(QWidget *parent, const QString& loginErrMsg) : isOnline_ = true; onlineForced = false; - //FIXME: translateable? - ui->usernameTextBox->lineEdit()->setPlaceholderText(QApplication::translate("LoginDialog", "Name", 0)); + //: The username during login (placeholder) + ui->usernameTextBox->lineEdit()->setPlaceholderText(tr("Name")); connect(ui->usernameTextBox, SIGNAL(currentTextChanged(QString)), this, SLOT(userTextChanged(QString))); connect(ui->forgetButton, SIGNAL(clicked(bool)), this, SLOT(forgetCurrentUser())); @@ -49,6 +58,8 @@ LoginDialog::LoginDialog(QWidget *parent, const QString& loginErrMsg) : arg(loginErrMsg)); } + ui->lblFace->setVisible(false); + resize(minimumSizeHint()); layout()->setSizeConstraint(QLayout::SetFixedSize); Keyring * k = Keyring::instance(); @@ -109,7 +120,7 @@ void LoginDialog::passwordToggled ( bool state ) blockToggles = true; if(!state) { - qDebug() << "password disabled"; + QLOG_DEBUG() << "password disabled"; } else { @@ -117,7 +128,7 @@ void LoginDialog::passwordToggled ( bool state ) { ui->rememberUsernameCheckbox->setChecked(true); } - qDebug() << "password enabled"; + QLOG_DEBUG() << "password enabled"; } blockToggles = false; } @@ -134,11 +145,11 @@ void LoginDialog::usernameToggled ( bool state ) { ui->rememberPasswordCheckbox->setChecked(false); } - qDebug() << "username disabled"; + QLOG_DEBUG() << "username disabled"; } else { - qDebug() << "username enabled"; + QLOG_DEBUG() << "username enabled"; } blockToggles = false; } @@ -149,13 +160,53 @@ void LoginDialog::userTextChanged ( const QString& user ) blockToggles = true; Keyring * k = Keyring::instance(); QStringList sl = k->getStoredAccounts("minecraft"); + bool gotFace = false; + if(sl.contains(user)) { ui->rememberUsernameCheckbox->setChecked(true); QString passwd = k->getPassword("minecraft",user); ui->rememberPasswordCheckbox->setChecked(!passwd.isEmpty()); ui->passwordTextBox->setText(passwd); + + QByteArray data; + { + auto filename = MMC->metacache()->resolveEntry("skins", "skins.json")->getFullPath(); + QFile listFile(filename); + if(!listFile.open(QIODevice::ReadOnly)) + return; + data = listFile.readAll(); + } + + QJsonParseError jsonError; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); + QJsonObject root = jsonDoc.object(); + QJsonObject mappings = root.value("mappings").toObject(); + + if(!mappings[user].isUndefined()) + { + QJsonArray usernames = mappings.value(user).toArray(); + if(!usernames.isEmpty()) + { + QString mapped_username = usernames[0].toString(); + + if(!mapped_username.isEmpty()) + { + QFile fskin(MMC->metacache()->resolveEntry("skins", mapped_username + ".png")->getFullPath()); + if(fskin.exists()) + { + QPixmap skin(MMC->metacache()->resolveEntry("skins", mapped_username + ".png")->getFullPath()); + QPixmap face = skin.copy(8, 8, 8, 8).scaled(48, 48, Qt::KeepAspectRatio); + + ui->lblFace->setPixmap(face); + gotFace = true; + } + } + } + } } + + ui->lblFace->setVisible(gotFace); blockToggles = false; } @@ -194,4 +245,4 @@ void LoginDialog::forceOnline() { onlineForced = true; offlineButton->setEnabled(false); -}
\ No newline at end of file +} diff --git a/gui/logindialog.ui b/gui/logindialog.ui index 0aaad52b..46965425 100644 --- a/gui/logindialog.ui +++ b/gui/logindialog.ui @@ -23,10 +23,34 @@ </item> <item> <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="usernameLabel"> + <item row="0" column="4" rowspan="2"> + <widget class="QLabel" name="lblFace"> + <property name="minimumSize"> + <size> + <width>48</width> + <height>48</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>48</width> + <height>48</height> + </size> + </property> + <property name="sizeIncrement"> + <size> + <width>1</width> + <height>1</height> + </size> + </property> <property name="text"> - <string>Username:</string> + <string/> + </property> + <property name="pixmap"> + <pixmap resource="../multimc.qrc">:/icons/instances/steve</pixmap> + </property> + <property name="scaledContents"> + <bool>true</bool> </property> </widget> </item> @@ -37,6 +61,13 @@ </property> </widget> </item> + <item row="0" column="0"> + <widget class="QLabel" name="usernameLabel"> + <property name="text"> + <string>Username:</string> + </property> + </widget> + </item> <item row="1" column="0"> <widget class="QLabel" name="passwordLabel"> <property name="text"> @@ -54,7 +85,7 @@ </property> </widget> </item> - <item row="0" column="2" rowspan="2"> + <item row="0" column="5" rowspan="2"> <widget class="QPushButton" name="forgetButton"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> @@ -111,7 +142,9 @@ </item> </layout> </widget> - <resources/> + <resources> + <include location="../multimc.qrc"/> + </resources> <connections> <connection> <sender>loginButtonBox</sender> diff --git a/gui/lwjglselectdialog.cpp b/gui/lwjglselectdialog.cpp index 9de92754..09963ce0 100644 --- a/gui/lwjglselectdialog.cpp +++ b/gui/lwjglselectdialog.cpp @@ -13,8 +13,10 @@ * limitations under the License. */ +#include "MultiMC.h" #include "lwjglselectdialog.h" #include "ui_lwjglselectdialog.h" +#include "gui/platform.h" #include "logic/lists/LwjglVersionList.h" @@ -22,13 +24,15 @@ LWJGLSelectDialog::LWJGLSelectDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LWJGLSelectDialog) { + MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); ui->labelStatus->setVisible(false); - ui->lwjglListView->setModel(&LWJGLVersionList::get()); + auto lwjgllist = MMC->lwjgllist(); + ui->lwjglListView->setModel(lwjgllist.get()); - connect(&LWJGLVersionList::get(), SIGNAL(loadingStateUpdated(bool)), SLOT(loadingStateUpdated(bool))); - connect(&LWJGLVersionList::get(), SIGNAL(loadListFailed(QString)), SLOT(loadingFailed(QString))); - loadingStateUpdated(LWJGLVersionList::get().isLoading()); + connect(lwjgllist.get(), SIGNAL(loadingStateUpdated(bool)), SLOT(loadingStateUpdated(bool))); + connect(lwjgllist.get(), SIGNAL(loadListFailed(QString)), SLOT(loadingFailed(QString))); + loadingStateUpdated(lwjgllist->isLoading()); } LWJGLSelectDialog::~LWJGLSelectDialog() @@ -38,15 +42,15 @@ LWJGLSelectDialog::~LWJGLSelectDialog() QString LWJGLSelectDialog::selectedVersion() const { - return LWJGLVersionList::get().data( + return MMC->lwjgllist()->data( ui->lwjglListView->selectionModel()->currentIndex(), Qt::DisplayRole).toString(); } void LWJGLSelectDialog::on_refreshButton_clicked() { - if (!LWJGLVersionList::get().isLoading()) - LWJGLVersionList::get().loadList(); + if (!MMC->lwjgllist()->isLoading()) + MMC->lwjgllist()->loadList(); } void LWJGLSelectDialog::loadingStateUpdated(bool loading) @@ -54,7 +58,7 @@ void LWJGLSelectDialog::loadingStateUpdated(bool loading) setEnabled(!loading); if (loading) { - ui->labelStatus->setText("Loading LWJGL version list..."); + ui->labelStatus->setText(tr("Loading LWJGL version list...")); ui->labelStatus->setStyleSheet("QLabel { color: black; }"); } ui->labelStatus->setVisible(loading); diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 82483bf2..ab718f98 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -42,24 +42,28 @@ #include "gui/settingsdialog.h" #include "gui/newinstancedialog.h" #include "gui/logindialog.h" -#include "gui/taskdialog.h" +#include "gui/ProgressDialog.h" #include "gui/aboutdialog.h" #include "gui/versionselectdialog.h" #include "gui/lwjglselectdialog.h" #include "gui/consolewindow.h" #include "gui/instancesettings.h" +#include "gui/platform.h" #include "logic/lists/InstanceList.h" #include "logic/lists/MinecraftVersionList.h" #include "logic/lists/LwjglVersionList.h" #include "logic/lists/IconList.h" +#include "logic/lists/JavaVersionList.h" + +#include "logic/net/LoginTask.h" -#include "logic/tasks/LoginTask.h" #include "logic/BaseInstance.h" #include "logic/InstanceFactory.h" #include "logic/MinecraftProcess.h" #include "logic/OneSixAssets.h" #include "logic/OneSixUpdate.h" +#include "logic/JavaUtils.h" #include "logic/LegacyInstance.h" @@ -68,20 +72,20 @@ #include "LabeledToolButton.h" #include "EditNotesDialog.h" -MainWindow::MainWindow ( QWidget *parent ) - :QMainWindow ( parent ), ui ( new Ui::MainWindow ) +MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { - ui->setupUi ( this ); - setWindowTitle ( QString ( "MultiMC %1" ).arg ( MMC->version().toString() ) ); - + MultiMCPlatform::fixWM_CLASS(this); + ui->setupUi(this); + setWindowTitle(QString("MultiMC %1").arg(MMC->version().toString())); + // Set the selected instance to null m_selectedInstance = nullptr; // Set active instance to null. m_activeInst = nullptr; - + // OSX magic. setUnifiedTitleAndToolBarOnMac(true); - + // The instance action toolbar customizations { ui->instanceToolBar->setEnabled(false); @@ -92,44 +96,45 @@ MainWindow::MainWindow ( QWidget *parent ) connect(renameButton, SIGNAL(clicked(bool)), SLOT(on_actionRenameInstance_triggered())); ui->instanceToolBar->insertWidget(ui->actionLaunchInstance, renameButton); ui->instanceToolBar->insertSeparator(ui->actionLaunchInstance); - renameButton->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); + renameButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); } - + // Create the instance list widget { - view = new KCategorizedView ( ui->centralWidget ); - drawer = new KCategoryDrawer ( view ); - - view->setSelectionMode ( QAbstractItemView::SingleSelection ); - view->setCategoryDrawer ( drawer ); - view->setCollapsibleBlocks ( true ); - view->setViewMode ( QListView::IconMode ); - view->setFlow ( QListView::LeftToRight ); + view = new KCategorizedView(ui->centralWidget); + drawer = new KCategoryDrawer(view); + + view->setSelectionMode(QAbstractItemView::SingleSelection); + view->setCategoryDrawer(drawer); + view->setCollapsibleBlocks(true); + view->setViewMode(QListView::IconMode); + view->setFlow(QListView::LeftToRight); view->setWordWrap(true); - view->setMouseTracking ( true ); - view->viewport()->setAttribute ( Qt::WA_Hover ); + view->setMouseTracking(true); + view->viewport()->setAttribute(Qt::WA_Hover); auto delegate = new ListViewDelegate(); view->setItemDelegate(delegate); view->setSpacing(10); view->setUniformItemWidths(true); - + // do not show ugly blue border on the mac view->setAttribute(Qt::WA_MacShowFocusRect, false); - + view->installEventFilter(this); - proxymodel = new InstanceProxyModel ( this ); - proxymodel->setSortRole ( KCategorizedSortFilterProxyModel::CategorySortRole ); - proxymodel->setFilterRole ( KCategorizedSortFilterProxyModel::CategorySortRole ); - //proxymodel->setDynamicSortFilter ( true ); - - // FIXME: instList should be global-ish, or at least not tied to the main window... maybe the application itself? - proxymodel->setSourceModel ( MMC->instances() ); - proxymodel->sort ( 0 ); - view->setFrameShape ( QFrame::NoFrame ); - view->setModel ( proxymodel ); - - ui->horizontalLayout->addWidget ( view ); + proxymodel = new InstanceProxyModel(this); + proxymodel->setSortRole(KCategorizedSortFilterProxyModel::CategorySortRole); + proxymodel->setFilterRole(KCategorizedSortFilterProxyModel::CategorySortRole); + // proxymodel->setDynamicSortFilter ( true ); + + // FIXME: instList should be global-ish, or at least not tied to the main window... + // maybe the application itself? + proxymodel->setSourceModel(MMC->instances().get()); + proxymodel->sort(0); + view->setFrameShape(QFrame::NoFrame); + view->setModel(proxymodel); + + ui->horizontalLayout->addWidget(view); } // The cat background { @@ -139,29 +144,27 @@ MainWindow::MainWindow ( QWidget *parent ) setCatBackground(cat_enable); } // start instance when double-clicked - connect(view, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(instanceActivated(const QModelIndex &))); + connect(view, SIGNAL(doubleClicked(const QModelIndex &)), this, + SLOT(instanceActivated(const QModelIndex &))); // track the selection -- update the instance toolbar - connect( - view->selectionModel(), - SIGNAL(currentChanged(const QModelIndex &,const QModelIndex &)), - this, - SLOT(instanceChanged(const QModelIndex &,const QModelIndex &)) - ); + connect(view->selectionModel(), + SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, + SLOT(instanceChanged(const QModelIndex &, const QModelIndex &))); // model reset -> selection is invalid. All the instance pointers are wrong. // FIXME: stop using POINTERS everywhere - connect(MMC->instances() ,SIGNAL(dataIsInvalid()),SLOT(selectionBad())); - + connect(MMC->instances().get(), SIGNAL(dataIsInvalid()), SLOT(selectionBad())); + // run the things that load and download other things... FIXME: this is NOT the place // FIXME: invisible actions in the background = NOPE. { - if (!MinecraftVersionList::getMainList().isLoaded()) + if (!MMC->minecraftlist()->isLoaded()) { - m_versionLoadTask = MinecraftVersionList::getMainList().getLoadTask(); + m_versionLoadTask = MMC->minecraftlist()->getLoadTask(); startTask(m_versionLoadTask); } - if (!LWJGLVersionList::get().isLoaded()) + if (!MMC->lwjgllist()->isLoaded()) { - LWJGLVersionList::get().loadList(); + MMC->lwjgllist()->loadList(); } assets_downloader = new OneSixAssets(); assets_downloader->start(); @@ -176,57 +179,55 @@ MainWindow::~MainWindow() delete assets_downloader; } -bool MainWindow::eventFilter ( QObject* obj, QEvent* ev ) +bool MainWindow::eventFilter(QObject *obj, QEvent *ev) { - if(obj == view) + if (obj == view) { if (ev->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast<QKeyEvent*>(ev); - switch(keyEvent->key()) + QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev); + switch (keyEvent->key()) { - case Qt::Key_Enter: - case Qt::Key_Return: - on_actionLaunchInstance_triggered(); - return true; - case Qt::Key_Delete: - on_actionDeleteInstance_triggered(); - return true; - case Qt::Key_F5: - on_actionRefresh_triggered(); - return true; - case Qt::Key_F2: - on_actionRenameInstance_triggered(); - return true; - default: - break; + case Qt::Key_Enter: + case Qt::Key_Return: + on_actionLaunchInstance_triggered(); + return true; + case Qt::Key_Delete: + on_actionDeleteInstance_triggered(); + return true; + case Qt::Key_F5: + on_actionRefresh_triggered(); + return true; + case Qt::Key_F2: + on_actionRenameInstance_triggered(); + return true; + default: + break; } } } - return QMainWindow::eventFilter ( obj, ev ); + return QMainWindow::eventFilter(obj, ev); } -void MainWindow::onCatToggled ( bool state ) +void MainWindow::onCatToggled(bool state) { setCatBackground(state); MMC->settings()->set("TheCat", state); } -void MainWindow::setCatBackground ( bool enabled ) +void MainWindow::setCatBackground(bool enabled) { - if(enabled) + if (enabled) { - view->setStyleSheet( - "QListView" - "{" - "background-image: url(:/backgrounds/kitteh);" - "background-attachment: fixed;" - "background-clip: padding;" - "background-position: top right;" - "background-repeat: none;" - "background-color:palette(base);" - "}" - ); + view->setStyleSheet("QListView" + "{" + "background-image: url(:/backgrounds/kitteh);" + "background-attachment: fixed;" + "background-clip: padding;" + "background-position: top right;" + "background-repeat: none;" + "background-color:palette(base);" + "}"); } else { @@ -234,37 +235,37 @@ void MainWindow::setCatBackground ( bool enabled ) } } - -void MainWindow::instanceActivated ( QModelIndex index ) +void MainWindow::instanceActivated(QModelIndex index) { - if(!index.isValid()) + if (!index.isValid()) return; - BaseInstance * inst = (BaseInstance *) index.data(InstanceList::InstancePointerRole).value<void *>(); + BaseInstance *inst = + (BaseInstance *)index.data(InstanceList::InstancePointerRole).value<void *>(); doLogin(); } void MainWindow::on_actionAddInstance_triggered() { - if (!MinecraftVersionList::getMainList().isLoaded() && - m_versionLoadTask && m_versionLoadTask->isRunning()) + if (!MMC->minecraftlist()->isLoaded() && m_versionLoadTask && + m_versionLoadTask->isRunning()) { QEventLoop waitLoop; waitLoop.connect(m_versionLoadTask, SIGNAL(failed(QString)), SLOT(quit())); waitLoop.connect(m_versionLoadTask, SIGNAL(succeeded()), SLOT(quit())); waitLoop.exec(); } - - NewInstanceDialog newInstDlg( this ); + + NewInstanceDialog newInstDlg(this); if (!newInstDlg.exec()) return; - + BaseInstance *newInstance = NULL; - + QString instDirName = DirNameFromString(newInstDlg.instName()); QString instDir = PathCombine(MMC->settings()->get("InstanceDir").toString(), instDirName); - + auto &loader = InstanceFactory::get(); - + auto error = loader.createInstance(newInstance, newInstDlg.selectedVersion(), instDir); QString errorMsg = QString("Failed to create instance %1: ").arg(instDirName); switch (error) @@ -274,17 +275,17 @@ void MainWindow::on_actionAddInstance_triggered() newInstance->setIconKey(newInstDlg.iconKey()); MMC->instances()->add(InstancePtr(newInstance)); return; - + case InstanceFactory::InstExists: errorMsg += "An instance with the given directory name already exists."; QMessageBox::warning(this, "Error", errorMsg); break; - + case InstanceFactory::CantCreateDir: errorMsg += "Failed to create the instance directory."; QMessageBox::warning(this, "Error", errorMsg); break; - + default: errorMsg += QString("Unknown instance loader error %1").arg(error); QMessageBox::warning(this, "Error", errorMsg); @@ -294,12 +295,12 @@ void MainWindow::on_actionAddInstance_triggered() void MainWindow::on_actionChangeInstIcon_triggered() { - if(!m_selectedInstance) + if (!m_selectedInstance) return; - + IconPickerDialog dlg(this); dlg.exec(m_selectedInstance->iconKey()); - if(dlg.result() == QDialog::Accepted) + if (dlg.result() == QDialog::Accepted) { m_selectedInstance->setIconKey(dlg.selectedIconKey); auto ico = MMC->icons()->getIcon(dlg.selectedIconKey); @@ -307,25 +308,23 @@ void MainWindow::on_actionChangeInstIcon_triggered() } } - void MainWindow::on_actionChangeInstGroup_triggered() { - if(!m_selectedInstance) + if (!m_selectedInstance) return; - + bool ok = false; - QString name ( m_selectedInstance->group() ); - name = QInputDialog::getText ( this, tr ( "Group name" ), tr ( "Enter a new group name." ), - QLineEdit::Normal, name, &ok ); - if(ok) + QString name(m_selectedInstance->group()); + name = QInputDialog::getText(this, tr("Group name"), tr("Enter a new group name."), + QLineEdit::Normal, name, &ok); + if (ok) m_selectedInstance->setGroupPost(name); } - void MainWindow::on_actionViewInstanceFolder_triggered() { - QString str = MMC->settings()->get ( "InstanceDir" ).toString(); - openDirInDefaultProgram ( str ); + QString str = MMC->settings()->get("InstanceDir").toString(); + openDirInDefaultProgram(str); } void MainWindow::on_actionRefresh_triggered() @@ -335,59 +334,58 @@ void MainWindow::on_actionRefresh_triggered() void MainWindow::on_actionViewCentralModsFolder_triggered() { - openDirInDefaultProgram ( MMC->settings()->get ( "CentralModsDir" ).toString() , true); + openDirInDefaultProgram(MMC->settings()->get("CentralModsDir").toString(), true); } void MainWindow::on_actionConfig_Folder_triggered() { - if(m_selectedInstance) + if (m_selectedInstance) { QString str = m_selectedInstance->instanceConfigFolder(); - openDirInDefaultProgram ( QDir(str).absolutePath() ); + openDirInDefaultProgram(QDir(str).absolutePath()); } } - void MainWindow::on_actionCheckUpdate_triggered() { - } void MainWindow::on_actionSettings_triggered() { - SettingsDialog dialog ( this ); + SettingsDialog dialog(this); dialog.exec(); } void MainWindow::on_actionReportBug_triggered() { - openWebPage ( QUrl ( "http://jira.forkk.net/browse/MMC" ) ); + openWebPage(QUrl("http://multimc.myjetbrains.com/youtrack/dashboard#newissue=yes")); } void MainWindow::on_actionNews_triggered() { - openWebPage ( QUrl ( "http://forkk.net/tag/multimc.html" ) ); + openWebPage(QUrl("http://multimc.org/posts.html")); } void MainWindow::on_actionAbout_triggered() { - AboutDialog dialog ( this ); + AboutDialog dialog(this); dialog.exec(); } -void MainWindow::on_mainToolBar_visibilityChanged ( bool ) +void MainWindow::on_mainToolBar_visibilityChanged(bool) { // Don't allow hiding the main toolbar. // This is the only way I could find to prevent it... :/ - ui->mainToolBar->setVisible ( true ); + ui->mainToolBar->setVisible(true); } void MainWindow::on_actionDeleteInstance_triggered() { if (m_selectedInstance) { - int response = QMessageBox::question(this, "CAREFUL", - QString("This is permanent! Are you sure?\nAbout to delete: ") + m_selectedInstance->name()); + int response = QMessageBox::question( + this, "CAREFUL", QString("This is permanent! Are you sure?\nAbout to delete: ") + + m_selectedInstance->name()); if (response == QMessageBox::Yes) { m_selectedInstance->nuke(); @@ -397,31 +395,31 @@ void MainWindow::on_actionDeleteInstance_triggered() void MainWindow::on_actionRenameInstance_triggered() { - if(m_selectedInstance) + if (m_selectedInstance) { bool ok = false; - QString name ( m_selectedInstance->name() ); - name = QInputDialog::getText ( this, tr ( "Instance name" ), tr ( "Enter a new instance name." ), - QLineEdit::Normal, name, &ok ); - + QString name(m_selectedInstance->name()); + name = + QInputDialog::getText(this, tr("Instance name"), tr("Enter a new instance name."), + QLineEdit::Normal, name, &ok); + if (name.length() > 0) { - if(ok && name.length()) + if (ok && name.length()) { m_selectedInstance->setName(name); renameButton->setText(name); } } - } } void MainWindow::on_actionViewSelectedInstFolder_triggered() { - if(m_selectedInstance) + if (m_selectedInstance) { QString str = m_selectedInstance->instanceRoot(); - openDirInDefaultProgram ( QDir(str).absolutePath() ); + openDirInDefaultProgram(QDir(str).absolutePath()); } } @@ -430,65 +428,70 @@ void MainWindow::on_actionEditInstMods_triggered() if (m_selectedInstance) { auto dialog = m_selectedInstance->createModEditDialog(this); - if(dialog) + if (dialog) dialog->exec(); dialog->deleteLater(); } } -void MainWindow::closeEvent ( QCloseEvent *event ) +void MainWindow::closeEvent(QCloseEvent *event) { // Save the window state and geometry. // TODO: Make this work with the new settings system. -// settings->getConfig().setValue("MainWindowGeometry", saveGeometry()); -// settings->getConfig().setValue("MainWindowState", saveState()); - QMainWindow::closeEvent ( event ); + // settings->getConfig().setValue("MainWindowGeometry", saveGeometry()); + // settings->getConfig().setValue("MainWindowState", saveState()); + QMainWindow::closeEvent(event); } - -void MainWindow::on_instanceView_customContextMenuRequested ( const QPoint &pos ) +/* +void MainWindow::on_instanceView_customContextMenuRequested(const QPoint &pos) { - QMenu *instContextMenu = new QMenu ( "Instance", this ); + QMenu *instContextMenu = new QMenu("Instance", this); // Add the actions from the toolbar to the context menu. - instContextMenu->addActions ( ui->instanceToolBar->actions() ); + instContextMenu->addActions(ui->instanceToolBar->actions()); - instContextMenu->exec ( view->mapToGlobal ( pos ) ); + instContextMenu->exec(view->mapToGlobal(pos)); } - +*/ void MainWindow::on_actionLaunchInstance_triggered() { - if(m_selectedInstance) + if (m_selectedInstance) { doLogin(); } } -void MainWindow::doLogin(const QString& errorMsg) +void MainWindow::doLogin(const QString &errorMsg) { if (!m_selectedInstance) return; - - LoginDialog* loginDlg = new LoginDialog(this, errorMsg); + + LoginDialog *loginDlg = new LoginDialog(this, errorMsg); if (!m_selectedInstance->lastLaunch()) loginDlg->forceOnline(); - + loginDlg->exec(); - if(loginDlg->result() == QDialog::Accepted) + if (loginDlg->result() == QDialog::Accepted) { - if (loginDlg->isOnline()) + if (loginDlg->isOnline()) { UserInfo uInfo{loginDlg->getUsername(), loginDlg->getPassword()}; - TaskDialog* tDialog = new TaskDialog(this); - LoginTask* loginTask = new LoginTask(uInfo, tDialog); - connect(loginTask, SIGNAL(succeeded()),SLOT(onLoginComplete()), Qt::QueuedConnection); - connect(loginTask, SIGNAL(failed(QString)), SLOT(doLogin(QString)), Qt::QueuedConnection); + ProgressDialog *tDialog = new ProgressDialog(this); + LoginTask *loginTask = new LoginTask(uInfo, tDialog); + connect(loginTask, SIGNAL(succeeded()), SLOT(onLoginComplete()), + Qt::QueuedConnection); + connect(loginTask, SIGNAL(failed(QString)), SLOT(doLogin(QString)), + Qt::QueuedConnection); m_activeInst = m_selectedInstance; tDialog->exec(loginTask); } else { - m_activeLogin = {loginDlg->getUsername(), QString("Offline"), qint64(-1)}; + QString user = loginDlg->getUsername(); + if (user.length() == 0) + user = QString("Player"); + m_activeLogin = {user, QString("Offline"), user, QString()}; m_activeInst = m_selectedInstance; launchInstance(m_activeInst, m_activeLogin); } @@ -497,22 +500,63 @@ void MainWindow::doLogin(const QString& errorMsg) void MainWindow::onLoginComplete() { - if(!m_activeInst) + if (!m_activeInst) return; - LoginTask * task = (LoginTask *) QObject::sender(); + LoginTask *task = (LoginTask *)QObject::sender(); m_activeLogin = task->getResult(); - + BaseUpdate *updateTask = m_activeInst->doUpdate(); - if(!updateTask) + if (!updateTask) { launchInstance(m_activeInst, m_activeLogin); } else { - TaskDialog *tDialog = new TaskDialog(this); - connect(updateTask, SIGNAL(succeeded()),SLOT(onGameUpdateComplete())); + ProgressDialog tDialog(this); + connect(updateTask, SIGNAL(succeeded()), SLOT(onGameUpdateComplete())); connect(updateTask, SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString))); - tDialog->exec(updateTask); + tDialog.exec(updateTask); + delete updateTask; + } + + auto job = new DownloadJob("Player skin: " + m_activeLogin.player_name); + + auto meta = MMC->metacache()->resolveEntry("skins", m_activeLogin.player_name + ".png"); + job->addCacheDownload(QUrl("http://skins.minecraft.net/MinecraftSkins/" + m_activeLogin.player_name + ".png"), meta); + meta->stale = true; + + job->start(); + auto filename = MMC->metacache()->resolveEntry("skins", "skins.json")->getFullPath(); + QFile listFile(filename); + + // Add skin mapping + QByteArray data; + { + if(!listFile.open(QIODevice::ReadWrite)) + { + QLOG_ERROR() << "Failed to open/make skins list JSON"; + return; + } + + data = listFile.readAll(); + } + + QJsonParseError jsonError; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); + QJsonObject root = jsonDoc.object(); + QJsonObject mappings = root.value("mappings").toObject(); + QJsonArray usernames = mappings.value(m_activeLogin.username).toArray(); + + if(!usernames.contains(m_activeLogin.player_name)) + { + usernames.prepend(m_activeLogin.player_name); + mappings[m_activeLogin.username] = usernames; + root["mappings"] = mappings; + jsonDoc.setObject(root); + + // QJson hack - shouldn't have to clear the file every time a save happens + listFile.resize(0); + listFile.write(jsonDoc.toJson()); } } @@ -529,15 +573,27 @@ void MainWindow::onGameUpdateError(QString error) void MainWindow::launchInstance(BaseInstance *instance, LoginResponse response) { Q_ASSERT_X(instance != NULL, "launchInstance", "instance is NULL"); - - proc = instance->prepareForLaunch(response.username, response.sessionID); - if(!proc) + + proc = instance->prepareForLaunch(response); + if (!proc) return; - - console = new ConsoleWindow(); + + // Prepare GUI: If it shall stay open disable the required parts + if (MMC->settings()->get("NoHide").toBool()) + { + ui->actionLaunchInstance->setEnabled(false); + } + else + { + this->hide(); + } + + console = new ConsoleWindow(proc); console->show(); - connect(proc, SIGNAL(log(QString, MessageLevel::Enum)), - console, SLOT(write(QString, MessageLevel::Enum))); + connect(proc, SIGNAL(log(QString, MessageLevel::Enum)), console, + SLOT(write(QString, MessageLevel::Enum))); + connect(proc, SIGNAL(ended()), this, SLOT(instanceEnded())); + proc->setLogin(response.username, response.session_id); proc->launch(); } @@ -551,7 +607,7 @@ void MainWindow::taskEnd() QObject *sender = QObject::sender(); if (sender == m_versionLoadTask) m_versionLoadTask = NULL; - + sender->deleteLater(); } @@ -560,23 +616,27 @@ void MainWindow::startTask(Task *task) connect(task, SIGNAL(started()), SLOT(taskStart())); connect(task, SIGNAL(succeeded()), SLOT(taskEnd())); connect(task, SIGNAL(failed(QString)), SLOT(taskEnd())); - task->startTask(); + task->start(); } - // Create A Desktop Shortcut void MainWindow::on_actionMakeDesktopShortcut_triggered() { - QString name ( "Test" ); - name = QInputDialog::getText ( this, tr ( "MultiMC Shortcut" ), tr ( "Enter a Shortcut Name." ), QLineEdit::Normal, name ); + QString name("Test"); + name = QInputDialog::getText(this, tr("MultiMC Shortcut"), tr("Enter a Shortcut Name."), + QLineEdit::Normal, name); - Util::createShortCut ( Util::getDesktopDir(), QApplication::instance()->applicationFilePath(), QStringList() << "-dl" << QDir::currentPath() << "test", name, "application-x-octet-stream" ); + Util::createShortCut(Util::getDesktopDir(), QApplication::instance()->applicationFilePath(), + QStringList() << "-dl" << QDir::currentPath() << "test", name, + "application-x-octet-stream"); - QMessageBox::warning ( this, "Not useful", "A Dummy Shortcut was created. it will not do anything productive" ); + QMessageBox::warning( + this, tr("Not useful"), + tr("A Dummy Shortcut was created. it will not do anything productive")); } // BrowserDialog -void MainWindow::openWebPage ( QUrl url ) +void MainWindow::openWebPage(QUrl url) { QDesktopServices::openUrl(url); } @@ -585,11 +645,23 @@ void MainWindow::on_actionChangeInstMCVersion_triggered() { if (view->selectionModel()->selectedIndexes().count() < 1) return; - - VersionSelectDialog vselect(m_selectedInstance->versionList(), this); + + VersionSelectDialog vselect(m_selectedInstance->versionList().get(), + tr("Change Minecraft version"), this); + vselect.setFilter(1, "OneSix"); if (vselect.exec() && vselect.selectedVersion()) { - m_selectedInstance->setIntendedVersionId(vselect.selectedVersion()->descriptor); + if (m_selectedInstance->versionIsCustom()) + { + auto result = QMessageBox::warning( + this, tr("Are you sure?"), + tr("This will remove any library/version customization you did previously. " + "This includes things like Forge install and similar."), + QMessageBox::Ok, QMessageBox::Abort); + if (result != QMessageBox::Ok) + return; + } + m_selectedInstance->setIntendedVersionId(vselect.selectedVersion()->descriptor()); } } @@ -597,12 +669,12 @@ void MainWindow::on_actionChangeInstLWJGLVersion_triggered() { if (!m_selectedInstance) return; - + LWJGLSelectDialog lselect(this); lselect.exec(); if (lselect.result() == QDialog::Accepted) { - LegacyInstance * linst = (LegacyInstance *) m_selectedInstance; + LegacyInstance *linst = (LegacyInstance *)m_selectedInstance; linst->setLWJGLVersion(lselect.selectedVersion()); } } @@ -617,18 +689,25 @@ void MainWindow::on_actionInstanceSettings_triggered() settings.exec(); } -void MainWindow::instanceChanged( const QModelIndex& current, const QModelIndex& previous ) +void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex &previous) { - if(current.isValid() && nullptr != (m_selectedInstance = (BaseInstance *) current.data(InstanceList::InstancePointerRole).value<void *>())) + if (current.isValid() && + nullptr != (m_selectedInstance = + (BaseInstance *)current.data(InstanceList::InstancePointerRole) + .value<void *>())) { ui->instanceToolBar->setEnabled(true); QString iconKey = m_selectedInstance->iconKey(); renameButton->setText(m_selectedInstance->name()); - ui->actionChangeInstLWJGLVersion->setEnabled(m_selectedInstance->menuActionEnabled("actionChangeInstLWJGLVersion")); - ui->actionEditInstMods->setEnabled(m_selectedInstance->menuActionEnabled("actionEditInstMods")); + ui->actionChangeInstLWJGLVersion->setEnabled( + m_selectedInstance->menuActionEnabled("actionChangeInstLWJGLVersion")); + ui->actionEditInstMods->setEnabled( + m_selectedInstance->menuActionEnabled("actionEditInstMods")); + ui->actionChangeInstMCVersion->setEnabled( + m_selectedInstance->menuActionEnabled("actionChangeInstMCVersion")); statusBar()->clearMessage(); statusBar()->showMessage(m_selectedInstance->getStatusbarDescription()); - auto ico =MMC->icons()->getIcon(iconKey); + auto ico = MMC->icons()->getIcon(iconKey); ui->actionChangeInstIcon->setIcon(ico); } else @@ -643,24 +722,76 @@ void MainWindow::selectionBad() QString iconKey = "infinity"; statusBar()->clearMessage(); ui->instanceToolBar->setEnabled(false); - renameButton->setText("Rename Instance"); + renameButton->setText(tr("Rename Instance")); auto ico = MMC->icons()->getIcon(iconKey); ui->actionChangeInstIcon->setIcon(ico); } - - void MainWindow::on_actionEditInstNotes_triggered() { if (!m_selectedInstance) return; - LegacyInstance * linst = (LegacyInstance *) m_selectedInstance; - + LegacyInstance *linst = (LegacyInstance *)m_selectedInstance; + EditNotesDialog noteedit(linst->notes(), linst->name(), this); noteedit.exec(); if (noteedit.result() == QDialog::Accepted) { - + linst->setNotes(noteedit.getText()); } } + +void MainWindow::instanceEnded() +{ + this->show(); + ui->actionLaunchInstance->setEnabled(m_selectedInstance); +} + +void MainWindow::checkSetDefaultJava() +{ + bool askForJava = false; + { + QString currentHostName = QHostInfo::localHostName(); + QString oldHostName = MMC->settings()->get("LastHostname").toString(); + if (currentHostName != oldHostName) + { + MMC->settings()->set("LastHostname", currentHostName); + askForJava = true; + } + } + + { + QString currentJavaPath = MMC->settings()->get("JavaPath").toString(); + if (currentJavaPath.isEmpty()) + { + askForJava = true; + } + } + + if (askForJava) + { + QLOG_DEBUG() << "Java path needs resetting, showing Java selection dialog..."; + + JavaVersionPtr java; + + VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, + false); + vselect.setResizeOn(2); + vselect.exec(); + + if (!vselect.selectedVersion()) + { + QMessageBox::warning(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.")); + + JavaUtils ju; + java = ju.GetDefaultJava(); + } + + java = std::dynamic_pointer_cast<JavaVersion>(vselect.selectedVersion()); + MMC->settings()->set("JavaPath", java->path); + } +} diff --git a/gui/mainwindow.h b/gui/mainwindow.h index 3612dd0c..dbf7c4c3 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -3,7 +3,7 @@ * 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 @@ -19,7 +19,7 @@ #include <QMainWindow> #include "logic/lists/InstanceList.h" -#include "logic/tasks/LoginTask.h" +#include "logic/net/LoginTask.h" #include "logic/BaseInstance.h" class LabeledToolButton; @@ -39,112 +39,114 @@ class MainWindow; class MainWindow : public QMainWindow { Q_OBJECT - + public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); - + void closeEvent(QCloseEvent *event); // Browser Dialog void openWebPage(QUrl url); - - + + void checkSetDefaultJava(); + private slots: void onCatToggled(bool); - + void on_actionAbout_triggered(); - + void on_actionAddInstance_triggered(); - + void on_actionChangeInstGroup_triggered(); - + void on_actionChangeInstIcon_triggered(); - + void on_actionViewInstanceFolder_triggered(); - + void on_actionConfig_Folder_triggered(); - + void on_actionViewSelectedInstFolder_triggered(); void on_actionRefresh_triggered(); - + void on_actionViewCentralModsFolder_triggered(); - + void on_actionCheckUpdate_triggered(); - + void on_actionSettings_triggered(); - + void on_actionReportBug_triggered(); - + void on_actionNews_triggered(); - + void on_mainToolBar_visibilityChanged(bool); - - void on_instanceView_customContextMenuRequested(const QPoint &pos); - + + // void on_instanceView_customContextMenuRequested(const QPoint &pos); + void on_actionLaunchInstance_triggered(); - + void on_actionDeleteInstance_triggered(); - + void on_actionRenameInstance_triggered(); - + void on_actionMakeDesktopShortcut_triggered(); - + void on_actionChangeInstMCVersion_triggered(); - + void on_actionEditInstMods_triggered(); - + void on_actionEditInstNotes_triggered(); - - void doLogin(const QString& errorMsg = ""); - - + + void doLogin(const QString &errorMsg = ""); + void onLoginComplete(); - - + void onGameUpdateComplete(); void onGameUpdateError(QString error); - + void taskStart(); void taskEnd(); void on_actionChangeInstLWJGLVersion_triggered(); - - void on_actionInstanceSettings_triggered(); + + void instanceEnded(); + + void on_actionInstanceSettings_triggered(); public slots: - void instanceActivated ( QModelIndex ); + void instanceActivated(QModelIndex); + + void instanceChanged(const QModelIndex ¤t, const QModelIndex &previous); - void instanceChanged (const QModelIndex & current,const QModelIndex & previous); - void selectionBad(); - + void startTask(Task *task); - + void launchInstance(BaseInstance *inst, LoginResponse response); protected: bool eventFilter(QObject *obj, QEvent *ev); void setCatBackground(bool enabled); + private: Ui::MainWindow *ui; - KCategoryDrawer * drawer; - KCategorizedView * view; - InstanceProxyModel * proxymodel; + KCategoryDrawer *drawer; + KCategorizedView *view; + InstanceProxyModel *proxymodel; MinecraftProcess *proc; ConsoleWindow *console; OneSixAssets *assets_downloader; - LabeledToolButton * renameButton; - + LabeledToolButton *renameButton; + BaseInstance *m_selectedInstance; - + // A pointer to the instance we are actively doing stuff with. // This is set when the user launches an instance and is used to refer to that // instance throughout the launching process. BaseInstance *m_activeInst; LoginResponse m_activeLogin; - + Task *m_versionLoadTask; }; diff --git a/gui/mainwindow.ui b/gui/mainwindow.ui index 4360f5f6..0f883d13 100644 --- a/gui/mainwindow.ui +++ b/gui/mainwindow.ui @@ -13,6 +13,10 @@ <property name="windowTitle"> <string>MultiMC 5</string> </property> + <property name="windowIcon"> + <iconset resource="../multimc.qrc"> + <normaloff>:/icons/multimc/scalable/apps/multimc.svg</normaloff>:/icons/multimc/scalable/apps/multimc.svg</iconset> + </property> <widget class="QWidget" name="centralWidget"> <layout class="QHBoxLayout" name="horizontalLayout"> <property name="spacing"> @@ -107,6 +111,7 @@ <addaction name="actionChangeInstGroup"/> <addaction name="separator"/> <addaction name="actionInstanceSettings"/> + <addaction name="actionChangeInstMCVersion"/> <addaction name="actionChangeInstLWJGLVersion"/> <addaction name="actionEditInstMods"/> <addaction name="actionViewSelectedInstFolder"/> @@ -371,9 +376,6 @@ </property> </action> <action name="actionChangeInstMCVersion"> - <property name="enabled"> - <bool>false</bool> - </property> <property name="text"> <string>Change Version</string> </property> @@ -440,7 +442,7 @@ <string>Meow</string> </property> <property name="toolTip"> - <string><html><head/><body><p align="center"><span style=" font-weight:600; color:#ff0004;">Catnatok!</span></p><p align="center">Or just a cat with a ball of yarn?</p><p align="center"><span style=" font-style:italic;">WHO KNOWS?!</span></p><p align="center"><img src=":/icons/instances/tnt"/></p></body></html></string> + <string><html><head/><body><p align="center"><span style=" font-weight:600; color:#ff0004;">Catnarok!</span></p><p align="center">Or just a cat with a ball of yarn?</p><p align="center"><span style=" font-style:italic;">WHO KNOWS?!</span></p><p align="center"><img src=":/icons/instances/tnt"/></p></body></html></string> </property> </action> </widget> diff --git a/gui/newinstancedialog.cpp b/gui/newinstancedialog.cpp index ac3bcd7d..c37db2ac 100644 --- a/gui/newinstancedialog.cpp +++ b/gui/newinstancedialog.cpp @@ -3,7 +3,7 @@ * 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 @@ -18,24 +18,23 @@ #include "ui_newinstancedialog.h" #include "logic/InstanceFactory.h" -#include "logic/InstanceVersion.h" +#include "logic/BaseVersion.h" #include "logic/lists/IconList.h" #include "logic/lists/MinecraftVersionList.h" #include "logic/tasks/Task.h" +#include "gui/platform.h" #include "versionselectdialog.h" -#include "taskdialog.h" +#include "ProgressDialog.h" #include "IconPickerDialog.h" #include <QLayout> #include <QPushButton> - - -NewInstanceDialog::NewInstanceDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::NewInstanceDialog) +NewInstanceDialog::NewInstanceDialog(QWidget *parent) + : QDialog(parent), ui(new Ui::NewInstanceDialog) { + MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); resize(minimumSizeHint()); layout()->setSizeConstraint(QLayout::SetFixedSize); @@ -48,7 +47,7 @@ NewInstanceDialog::NewInstanceDialog(QWidget *parent) : taskDlg->exec(loadTask); } */ - setSelectedVersion(MinecraftVersionList::getMainList().getLatestStable()); + setSelectedVersion(MMC->minecraftlist()->getLatestStable()); InstIconKey = "infinity"; ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey)); } @@ -60,22 +59,23 @@ NewInstanceDialog::~NewInstanceDialog() void NewInstanceDialog::updateDialogState() { - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!instName().isEmpty() && m_selectedVersion); + ui->buttonBox->button(QDialogButtonBox::Ok) + ->setEnabled(!instName().isEmpty() && m_selectedVersion); } -void NewInstanceDialog::setSelectedVersion(InstVersionPtr version) +void NewInstanceDialog::setSelectedVersion(BaseVersionPtr version) { m_selectedVersion = version; - + if (m_selectedVersion) { - ui->versionTextBox->setText(version->name); + ui->versionTextBox->setText(version->name()); } else { ui->versionTextBox->setText(""); } - + updateDialogState(); } @@ -89,18 +89,19 @@ QString NewInstanceDialog::iconKey() const return InstIconKey; } -InstVersionPtr NewInstanceDialog::selectedVersion() const +BaseVersionPtr NewInstanceDialog::selectedVersion() const { return m_selectedVersion; } void NewInstanceDialog::on_btnChangeVersion_clicked() { - VersionSelectDialog vselect(&MinecraftVersionList::getMainList(), this); + VersionSelectDialog vselect(MMC->minecraftlist().get(), tr("Change Minecraft version"), + this); vselect.exec(); if (vselect.result() == QDialog::Accepted) { - InstVersionPtr version = vselect.selectedVersion(); + BaseVersionPtr version = vselect.selectedVersion(); if (version) setSelectedVersion(version); } @@ -110,8 +111,8 @@ void NewInstanceDialog::on_iconButton_clicked() { IconPickerDialog dlg(this); dlg.exec(InstIconKey); - - if(dlg.result() == QDialog::Accepted) + + if (dlg.result() == QDialog::Accepted) { InstIconKey = dlg.selectedIconKey; ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey)); diff --git a/gui/newinstancedialog.h b/gui/newinstancedialog.h index e8c57024..408cf757 100644 --- a/gui/newinstancedialog.h +++ b/gui/newinstancedialog.h @@ -17,7 +17,7 @@ #define NEWINSTANCEDIALOG_H #include <QDialog> -#include "logic/InstanceVersion.h" +#include "logic/BaseVersion.h" namespace Ui { class NewInstanceDialog; @@ -33,13 +33,13 @@ public: void updateDialogState(); - void setSelectedVersion(InstVersionPtr version); + void setSelectedVersion(BaseVersionPtr version); void loadVersionList(); QString instName() const; QString iconKey() const; - InstVersionPtr selectedVersion() const; + BaseVersionPtr selectedVersion() const; private slots: void on_btnChangeVersion_clicked(); @@ -49,7 +49,7 @@ private slots: private: Ui::NewInstanceDialog *ui; - InstVersionPtr m_selectedVersion; + BaseVersionPtr m_selectedVersion; QString InstIconKey; }; diff --git a/gui/platform.h b/gui/platform.h new file mode 100644 index 00000000..5cf9ed80 --- /dev/null +++ b/gui/platform.h @@ -0,0 +1,35 @@ +/* Copyright 2013 MultiMC Contributors + * + * Authors: Orochimarufan <orochimarufan.x3@gmail.com> + * + * 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. + */ + +#ifndef PLATFORM_H +#define PLATFORM_H + +/** + * @file platform.h + * This file contains platform-specific functions, tweaks and fixes. + */ + +#include <QWidget> + +class MultiMCPlatform +{ +public: + // X11 WM_CLASS + static void fixWM_CLASS(QWidget *widget); +}; + +#endif // PLATFORM_H diff --git a/gui/platform_other.cpp b/gui/platform_other.cpp new file mode 100644 index 00000000..a41abe36 --- /dev/null +++ b/gui/platform_other.cpp @@ -0,0 +1,27 @@ +/* Copyright 2013 MultiMC Contributors + * + * Authors: Orochimarufan <orochimarufan.x3@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gui/platform.h> +/** + * Stub for non-X11 platforms + * @brief MultiMCPlatform::fixWM_CLASS + * @param widget + */ +void MultiMCPlatform::fixWM_CLASS(QWidget *widget) +{ + Q_UNUSED(widget); +} diff --git a/gui/platform_x11.cpp b/gui/platform_x11.cpp new file mode 100644 index 00000000..0401e8bf --- /dev/null +++ b/gui/platform_x11.cpp @@ -0,0 +1,62 @@ +/* Copyright 2013 MultiMC Contributors + * + * Authors: Orochimarufan <orochimarufan.x3@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gui/platform.h> +#include <QtX11Extras/QX11Info> +#include <xcb/xcb.h> + +static QByteArray WM_CLASS = "MultiMC5\0MultiMC5"; + +template <typename... ArgTypes, typename... ArgTypes2> +static inline unsigned int XcbCallVoid(xcb_void_cookie_t (*func)(xcb_connection_t *, ArgTypes...), ArgTypes2... args...) +{ + return func(QX11Info::connection(), args...).sequence; +} + +static void getAtoms(size_t n, xcb_atom_t *atoms, const char *const names[], bool create) +{ + xcb_connection_t *conn = QX11Info::connection(); + xcb_intern_atom_cookie_t *cookies = (xcb_intern_atom_cookie_t *)malloc(sizeof(xcb_intern_atom_cookie_t) * 2); + for (size_t i = 0; i < n; ++i) + cookies[i] = xcb_intern_atom(conn, create, strlen(names[i]), names[i]); + memset(atoms, 0, sizeof(xcb_atom_t) * n); + for (size_t i = 0; i < n; ++i) + { + xcb_intern_atom_reply_t *r = xcb_intern_atom_reply(conn, cookies[i], 0); + if (r) + { + atoms[i] = r->atom; + free(r); + } + } + free(cookies); +} + +static inline xcb_atom_t getAtom(const char *name, bool create=false) +{ + xcb_atom_t atom; + getAtoms(1, &atom, &name, create); + return atom; +} + +void MultiMCPlatform::fixWM_CLASS(QWidget *widget) +{ + static const xcb_atom_t atom = getAtom("WM_CLASS"); + XcbCallVoid(xcb_change_property, XCB_PROP_MODE_REPLACE, + widget->winId(), atom, XCB_ATOM_STRING, 8, WM_CLASS.count(), + WM_CLASS.constData()); +} diff --git a/gui/settingsdialog.cpp b/gui/settingsdialog.cpp index a1fbb8e7..14eba492 100644 --- a/gui/settingsdialog.cpp +++ b/gui/settingsdialog.cpp @@ -13,10 +13,14 @@ * limitations under the License. */ +#include <MultiMC.h> #include "settingsdialog.h" #include "ui_settingsdialog.h" +#include "logic/JavaUtils.h" +#include "gui/versionselectdialog.h" +#include "gui/platform.h" +#include "logic/lists/JavaVersionList.h" -#include <MultiMC.h> #include <settingsobject.h> #include <QFileDialog> #include <QMessageBox> @@ -25,9 +29,10 @@ SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::SettingsDialog) { + MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); - loadSettings(MMC->settings()); + loadSettings(MMC->settings().get()); updateCheckboxStuff(); } @@ -49,7 +54,7 @@ void SettingsDialog::updateCheckboxStuff() void SettingsDialog::on_instDirBrowseBtn_clicked() { - QString dir = QFileDialog::getExistingDirectory(this, "Instance Directory", + QString dir = QFileDialog::getExistingDirectory(this, tr("Instance Directory"), ui->instDirTextBox->text()); if (!dir.isEmpty()) ui->instDirTextBox->setText(dir); @@ -57,7 +62,7 @@ void SettingsDialog::on_instDirBrowseBtn_clicked() void SettingsDialog::on_modsDirBrowseBtn_clicked() { - QString dir = QFileDialog::getExistingDirectory(this, "Mods Directory", + QString dir = QFileDialog::getExistingDirectory(this, tr("Mods Directory"), ui->modsDirTextBox->text()); if (!dir.isEmpty()) ui->modsDirTextBox->setText(dir); @@ -65,7 +70,7 @@ void SettingsDialog::on_modsDirBrowseBtn_clicked() void SettingsDialog::on_lwjglDirBrowseBtn_clicked() { - QString dir = QFileDialog::getExistingDirectory(this, "LWJGL Directory", + QString dir = QFileDialog::getExistingDirectory(this, tr("LWJGL Directory"), ui->lwjglDirTextBox->text()); if (!dir.isEmpty()) ui->lwjglDirTextBox->setText(dir); @@ -85,7 +90,7 @@ void SettingsDialog::on_maximizedCheckBox_clicked(bool checked) void SettingsDialog::on_buttonBox_accepted() { - applySettings(MMC->settings()); + applySettings(MMC->settings().get()); } void SettingsDialog::applySettings(SettingsObject *s) @@ -99,9 +104,9 @@ void SettingsDialog::applySettings(SettingsObject *s) } else if (!s->get("UseDevBuilds").toBool()) { - int response = QMessageBox::question(this, "Development builds", - "Development builds contain experimental features " - "and may be unstable. Are you sure you want to enable them?"); + int response = QMessageBox::question(this, tr("Development builds"), + tr("Development builds contain experimental features " + "and may be unstable. Are you sure you want to enable them?")); if (response == QMessageBox::Yes) { s->set("UseDevBuilds", true); @@ -180,3 +185,27 @@ void SettingsDialog::loadSettings(SettingsObject *s) ui->preLaunchCmdTextBox->setText(s->get("PreLaunchCommand").toString()); ui->postExitCmdTextBox->setText(s->get("PostExitCommand").toString()); } + +void SettingsDialog::on_pushButton_clicked() +{ + JavaVersionPtr java; + + VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, true); + vselect.setResizeOn(2); + vselect.exec(); + + if (vselect.result() == QDialog::Accepted && vselect.selectedVersion()) + { + java = std::dynamic_pointer_cast<JavaVersion>(vselect.selectedVersion()); + ui->javaPathTextBox->setText(java->path); + } +} + +void SettingsDialog::on_btnBrowse_clicked() +{ + QString dir = QFileDialog::getOpenFileName(this, tr("Find Java executable")); + if(!dir.isNull()) + { + ui->javaPathTextBox->setText(dir); + } +} diff --git a/gui/settingsdialog.h b/gui/settingsdialog.h index b0a8c673..a8dfb1c6 100644 --- a/gui/settingsdialog.h +++ b/gui/settingsdialog.h @@ -53,6 +53,10 @@ private slots: void on_buttonBox_accepted(); + void on_pushButton_clicked(); + + void on_btnBrowse_clicked(); + private: Ui::SettingsDialog *ui; }; diff --git a/gui/settingsdialog.ui b/gui/settingsdialog.ui index 0d30e301..bf173b1b 100644 --- a/gui/settingsdialog.ui +++ b/gui/settingsdialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>453</width> - <height>550</height> + <width>502</width> + <height>599</height> </rect> </property> <property name="sizePolicy"> @@ -353,7 +353,7 @@ <number>64</number> </property> <property name="maximum"> - <number>512</number> + <number>999999999</number> </property> <property name="singleStep"> <number>8</number> @@ -374,29 +374,60 @@ <layout class="QGridLayout" name="gridLayout_3"> <item row="0" column="0"> <widget class="QLabel" name="labelJavaPath"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="text"> <string>Java path:</string> </property> </widget> </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="javaPathTextBox"/> - </item> - <item row="1" column="0"> + <item row="2" column="0"> <widget class="QLabel" name="labelJVMArgs"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="text"> <string>JVM arguments:</string> </property> </widget> </item> - <item row="0" column="2"> + <item row="1" column="3"> + <widget class="QPushButton" name="btnBrowse"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Browse...</string> + </property> + </widget> + </item> + <item row="0" column="1" colspan="3"> + <widget class="QLineEdit" name="javaPathTextBox"/> + </item> + <item row="1" column="2"> <widget class="QPushButton" name="pushButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="text"> - <string>Auto-detect</string> + <string>Auto-detect...</string> </property> </widget> </item> - <item row="1" column="1" colspan="2"> + <item row="2" column="1" colspan="3"> <widget class="QLineEdit" name="jvmArgsTextBox"/> </item> </layout> @@ -466,6 +497,35 @@ </item> </layout> </widget> + <tabstops> + <tabstop>settingsTabs</tabstop> + <tabstop>buttonBox</tabstop> + <tabstop>sortLastLaunchedBtn</tabstop> + <tabstop>sortByNameBtn</tabstop> + <tabstop>devBuildsCheckBox</tabstop> + <tabstop>autoUpdateCheckBox</tabstop> + <tabstop>instDirTextBox</tabstop> + <tabstop>modsDirTextBox</tabstop> + <tabstop>lwjglDirTextBox</tabstop> + <tabstop>instDirBrowseBtn</tabstop> + <tabstop>modsDirBrowseBtn</tabstop> + <tabstop>lwjglDirBrowseBtn</tabstop> + <tabstop>maximizedCheckBox</tabstop> + <tabstop>windowWidthSpinBox</tabstop> + <tabstop>windowHeightSpinBox</tabstop> + <tabstop>showConsoleCheck</tabstop> + <tabstop>autoCloseConsoleCheck</tabstop> + <tabstop>autoLoginCheckBox</tabstop> + <tabstop>minMemSpinBox</tabstop> + <tabstop>maxMemSpinBox</tabstop> + <tabstop>permGenSpinBox</tabstop> + <tabstop>javaPathTextBox</tabstop> + <tabstop>pushButton</tabstop> + <tabstop>btnBrowse</tabstop> + <tabstop>jvmArgsTextBox</tabstop> + <tabstop>preLaunchCmdTextBox</tabstop> + <tabstop>postExitCmdTextBox</tabstop> + </tabstops> <resources> <include location="../multimc.qrc"/> </resources> diff --git a/gui/versionselectdialog.cpp b/gui/versionselectdialog.cpp index 66d772b0..8fa62f75 100644 --- a/gui/versionselectdialog.cpp +++ b/gui/versionselectdialog.cpp @@ -3,7 +3,7 @@ * 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 @@ -20,32 +20,34 @@ #include <QDebug> -#include <gui/taskdialog.h> +#include <gui/ProgressDialog.h> +#include "gui/platform.h" -#include <logic/InstanceVersion.h> -#include <logic/lists/InstVersionList.h> +#include <logic/BaseVersion.h> +#include <logic/lists/BaseVersionList.h> #include <logic/tasks/Task.h> -VersionSelectDialog::VersionSelectDialog(InstVersionList *vlist, QWidget *parent) : - QDialog(parent), - ui(new Ui::VersionSelectDialog) +VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent, bool cancelable) + : QDialog(parent), ui(new Ui::VersionSelectDialog) { + MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); setWindowModality(Qt::WindowModal); - + setWindowTitle(title); + m_vlist = vlist; - + m_proxyModel = new QSortFilterProxyModel(this); m_proxyModel->setSourceModel(vlist); - + ui->listView->setModel(m_proxyModel); ui->listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); - ui->listView->header()->setSectionResizeMode(0, QHeaderView::Stretch); - - connect(ui->filterSnapshotsCheckbox, SIGNAL(clicked()), SLOT(updateFilterState())); - connect(ui->filterMCNostalgiaCheckbox, SIGNAL(clicked()), SLOT(updateFilterState())); - - updateFilterState(); + ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch); + + if(!cancelable) + { + ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); + } } VersionSelectDialog::~VersionSelectDialog() @@ -53,6 +55,13 @@ VersionSelectDialog::~VersionSelectDialog() delete ui; } +void VersionSelectDialog::setResizeOn(int column) +{ + ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::ResizeToContents); + resizeOnColumn = column; + ui->listView->header()->setSectionResizeMode(resizeOnColumn, QHeaderView::Stretch); +} + int VersionSelectDialog::exec() { QDialog::open(); @@ -63,17 +72,17 @@ int VersionSelectDialog::exec() void VersionSelectDialog::loadList() { - TaskDialog *taskDlg = new TaskDialog(this); + ProgressDialog *taskDlg = new ProgressDialog(this); Task *loadTask = m_vlist->getLoadTask(); loadTask->setParent(taskDlg); taskDlg->exec(loadTask); } -InstVersionPtr VersionSelectDialog::selectedVersion() const +BaseVersionPtr VersionSelectDialog::selectedVersion() const { auto currentIndex = ui->listView->selectionModel()->currentIndex(); - auto variant = m_proxyModel->data(currentIndex, InstVersionList::VersionPointerRole); - return variant.value<InstVersionPtr>(); + auto variant = m_proxyModel->data(currentIndex, BaseVersionList::VersionPointerRole); + return variant.value<BaseVersionPtr>(); } void VersionSelectDialog::on_refreshButton_clicked() @@ -81,21 +90,21 @@ void VersionSelectDialog::on_refreshButton_clicked() loadList(); } -void VersionSelectDialog::updateFilterState() +void VersionSelectDialog::setFilter(int column, QString filter) { - m_proxyModel->setFilterKeyColumn(InstVersionList::TypeColumn); - + m_proxyModel->setFilterKeyColumn(column); + m_proxyModel->setFilterFixedString(filter); + /* QStringList filteredTypes; if (!ui->filterSnapshotsCheckbox->isChecked()) filteredTypes += "Snapshot"; if (!ui->filterMCNostalgiaCheckbox->isChecked()) filteredTypes += "Nostalgia"; - + QString regexStr = "^.*$"; if (filteredTypes.length() > 0) regexStr = QString("^((?!%1).)*$").arg(filteredTypes.join('|')); - - qDebug() << "Filter:" << regexStr; - - m_proxyModel->setFilterRegExp(regexStr); + + QLOG_DEBUG() << "Filter:" << regexStr; + */ } diff --git a/gui/versionselectdialog.h b/gui/versionselectdialog.h index b864aee1..319caeca 100644 --- a/gui/versionselectdialog.h +++ b/gui/versionselectdialog.h @@ -19,9 +19,9 @@ #include <QDialog> #include <QSortFilterProxyModel> -#include "logic/InstanceVersion.h" +#include "logic/BaseVersion.h" -class InstVersionList; +class BaseVersionList; namespace Ui { @@ -33,7 +33,7 @@ class VersionSelectDialog : public QDialog Q_OBJECT public: - explicit VersionSelectDialog(InstVersionList *vlist, QWidget *parent = 0); + explicit VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent = 0, bool cancelable = true); ~VersionSelectDialog(); virtual int exec(); @@ -41,19 +41,21 @@ public: //! Starts a task that loads the list. void loadList(); - InstVersionPtr selectedVersion() const; + BaseVersionPtr selectedVersion() const; + + void setFilter(int column, QString filter); + void setResizeOn(int column); private slots: void on_refreshButton_clicked(); - - void updateFilterState(); - private: Ui::VersionSelectDialog *ui; - InstVersionList *m_vlist; + BaseVersionList *m_vlist; QSortFilterProxyModel *m_proxyModel; + + int resizeOnColumn = 0; }; #endif // VERSIONSELECTDIALOG_H diff --git a/gui/versionselectdialog.ui b/gui/versionselectdialog.ui index 02937794..222f29cf 100644 --- a/gui/versionselectdialog.ui +++ b/gui/versionselectdialog.ui @@ -40,75 +40,6 @@ </widget> </item> <item> - <layout class="QHBoxLayout" name="filterCheckboxLayout1"> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QCheckBox" name="filterSnapshotsCheckbox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Show &snapshots?</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QCheckBox" name="filterMCNostalgiaCheckbox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Show &Nostalgia?</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QPushButton" name="refreshButton"> |