diff options
Diffstat (limited to 'gui')
63 files changed, 3651 insertions, 2942 deletions
diff --git a/gui/ConsoleWindow.cpp b/gui/ConsoleWindow.cpp index ac3752c5..62908d29 100644 --- a/gui/ConsoleWindow.cpp +++ b/gui/ConsoleWindow.cpp @@ -14,29 +14,117 @@ */ #include "ConsoleWindow.h" -#include "ui_ConsoleWindow.h" #include "MultiMC.h" #include <QScrollBar> #include <QMessageBox> #include <QSystemTrayIcon> +#include <QHBoxLayout> +#include <QPushButton> +#include <qlayoutitem.h> #include <gui/Platform.h> #include <gui/dialogs/CustomMessageBox.h> #include <gui/dialogs/ProgressDialog.h> -#include "dialogs/ScreenshotDialog.h" +#include "widgets/PageContainer.h" +#include "pages/LogPage.h" -#include "logic/net/PasteUpload.h" #include "logic/icons/IconList.h" -#include <logic/screenshots/ScreenshotList.h> + +class LogPageProvider : public BasePageProvider +{ +public: + LogPageProvider(BasePageProviderPtr parent, BasePage * log_page) + { + m_parent = parent; + m_log_page = log_page; + } + virtual QString dialogTitle() {return "Fake";}; + virtual QList<BasePage *> getPages() + { + auto pages = m_parent->getPages(); + pages.prepend(m_log_page); + return pages; + } +private: + BasePageProviderPtr m_parent; + BasePage * m_log_page; +}; ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent) - : QMainWindow(parent), ui(new Ui::ConsoleWindow), proc(mcproc) + : QMainWindow(parent), m_proc(mcproc) { MultiMCPlatform::fixWM_CLASS(this); - ui->setupUi(this); - connect(mcproc, SIGNAL(log(QString, MessageLevel::Enum)), this, - SLOT(write(QString, MessageLevel::Enum))); + + auto instance = m_proc->instance(); + auto icon = MMC->icons()->getIcon(instance->iconKey()); + QString windowTitle = tr("Console window for ") + instance->name(); + + // Set window properties + { + setWindowIcon(icon); + setWindowTitle(windowTitle); + } + + // Add page container + { + auto mainLayout = new QVBoxLayout; + auto provider = std::dynamic_pointer_cast<BasePageProvider>(m_proc->instance()); + auto proxy_provider = std::make_shared<LogPageProvider>(provider, new LogPage(m_proc)); + m_container = new PageContainer(proxy_provider, "console", this); + mainLayout->addWidget(m_container); + mainLayout->setSpacing(0); + mainLayout->setContentsMargins(0,0,0,0); + setLayout(mainLayout); + setCentralWidget(m_container); + } + + // Add custom buttons to the page container layout. + { + auto horizontalLayout = new QHBoxLayout(); + horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); + horizontalLayout->setContentsMargins(6, -1, 6, -1); + + auto btnHelp = new QPushButton(); + btnHelp->setText(tr("Help")); + horizontalLayout->addWidget(btnHelp); + connect(btnHelp, SIGNAL(clicked(bool)), m_container, SLOT(help())); + + auto spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + horizontalLayout->addSpacerItem(spacer); + + m_killButton = new QPushButton(); + m_killButton->setText(tr("Kill Minecraft")); + horizontalLayout->addWidget(m_killButton); + connect(m_killButton, SIGNAL(clicked(bool)), SLOT(on_btnKillMinecraft_clicked())); + + m_closeButton = new QPushButton(); + m_closeButton->setText(tr("Close")); + horizontalLayout->addWidget(m_closeButton); + connect(m_closeButton, SIGNAL(clicked(bool)), SLOT(on_closeButton_clicked())); + + m_container->addButtons(horizontalLayout); + } + + // restore window state + { + auto base64State = MMC->settings()->get("ConsoleWindowState").toByteArray(); + restoreState(QByteArray::fromBase64(base64State)); + auto base64Geometry = MMC->settings()->get("ConsoleWindowGeometry").toByteArray(); + restoreGeometry(QByteArray::fromBase64(base64Geometry)); + } + + // Set up tray icon + { + m_trayIcon = new QSystemTrayIcon(icon, this); + m_trayIcon->setToolTip(windowTitle); + + connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), + SLOT(iconActivated(QSystemTrayIcon::ActivationReason))); + m_trayIcon->show(); + } + + // Set up signal connections connect(mcproc, SIGNAL(ended(InstancePtr, int, QProcess::ExitStatus)), this, SLOT(onEnded(InstancePtr, int, QProcess::ExitStatus))); connect(mcproc, SIGNAL(prelaunch_failed(InstancePtr, int, QProcess::ExitStatus)), this, @@ -44,34 +132,12 @@ ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent) connect(mcproc, SIGNAL(launch_failed(InstancePtr)), this, SLOT(onLaunchFailed(InstancePtr))); - restoreState( - QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowState").toByteArray())); - restoreGeometry( - QByteArray::fromBase64(MMC->settings()->get("ConsoleWindowGeometry").toByteArray())); - - QString iconKey = proc->instance()->iconKey(); - QString name = proc->instance()->name(); - auto icon = MMC->icons()->getIcon(iconKey); - setWindowIcon(icon); - m_trayIcon = new QSystemTrayIcon(icon, this); - // TODO add screenshot upload as a menu item in the tray icon - QString consoleTitle = tr("Console window for ") + name; - m_trayIcon->setToolTip(consoleTitle); - setWindowTitle(consoleTitle); + setMayClose(false); - connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), - SLOT(iconActivated(QSystemTrayIcon::ActivationReason))); - m_trayIcon->show(); if (mcproc->instance()->settings().get("ShowConsole").toBool()) { show(); } - setMayClose(false); -} - -ConsoleWindow::~ConsoleWindow() -{ - delete ui; } void ConsoleWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) @@ -87,123 +153,23 @@ void ConsoleWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) } } -void ConsoleWindow::writeColor(QString text, const char *color, const char * background) -{ - // append a paragraph - QString newtext; - newtext += "<span style=\""; - { - if (color) - newtext += QString("color:") + color + ";"; - if (background) - newtext += QString("background-color:") + background + ";"; - newtext += "font-family: monospace;"; - } - newtext += "\">"; - newtext += text.toHtmlEscaped(); - newtext += "</span>"; - ui->text->appendHtml(newtext); -} - -void ConsoleWindow::write(QString data, MessageLevel::Enum mode) -{ - QScrollBar *bar = ui->text->verticalScrollBar(); - int max_bar = bar->maximum(); - int val_bar = bar->value(); - if(isVisible()) - { - if (m_scroll_active) - { - m_scroll_active = (max_bar - val_bar) <= 1; - } - else - { - m_scroll_active = val_bar == max_bar; - } - } - 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()) - writeColor(iter.next(), "blue", 0); - else if (mode == MessageLevel::Error) - while (iter.hasNext()) - writeColor(iter.next(), "red", 0); - else if (mode == MessageLevel::Warning) - while (iter.hasNext()) - writeColor(iter.next(), "orange", 0); - else if (mode == MessageLevel::Fatal) - while (iter.hasNext()) - writeColor(iter.next(), "red", "black"); - else if (mode == MessageLevel::Debug) - while (iter.hasNext()) - writeColor(iter.next(), "green", 0); - else if (mode == MessageLevel::PrePost) - while (iter.hasNext()) - writeColor(iter.next(), "grey", 0); - // TODO: implement other MessageLevels - else - while (iter.hasNext()) - writeColor(iter.next(), 0, 0); - if(isVisible()) - { - if (m_scroll_active) - { - bar->setValue(bar->maximum()); - } - m_last_scroll_value = bar->value(); - } -} - -void ConsoleWindow::clear() -{ - ui->text->clear(); -} - void ConsoleWindow::on_closeButton_clicked() { close(); } -void ConsoleWindow::on_btnScreenshots_clicked() -{ - ScreenshotList *list = new ScreenshotList(proc->instance()); - Task *task = list->load(); - ProgressDialog prog(this); - prog.exec(task); - if (!task->successful()) - { - CustomMessageBox::selectable(this, tr("Failed to load screenshots!"), - task->failReason(), QMessageBox::Warning)->exec(); - return; - } - ScreenshotDialog dialog(list, this); - if (dialog.exec() == ScreenshotDialog::Accepted) - { - CustomMessageBox::selectable(this, tr("Done uploading!"), dialog.message(), - QMessageBox::Information)->exec(); - } -} - void ConsoleWindow::setMayClose(bool mayclose) { if(mayclose) - ui->closeButton->setText(tr("Close")); + m_closeButton->setText(tr("Close")); else - ui->closeButton->setText(tr("Hide")); + m_closeButton->setText(tr("Hide")); m_mayclose = mayclose; } void ConsoleWindow::toggleConsole() { - QScrollBar *bar = ui->text->verticalScrollBar(); + //QScrollBar *bar = ui->text->verticalScrollBar(); if (isVisible()) { if(!isActiveWindow()) @@ -211,15 +177,17 @@ void ConsoleWindow::toggleConsole() activateWindow(); return; } + /* int max_bar = bar->maximum(); int val_bar = m_last_scroll_value = bar->value(); m_scroll_active = (max_bar - val_bar) <= 1; + */ hide(); } else { show(); - isTopLevel(); + /* if (m_scroll_active) { bar->setValue(bar->maximum()); @@ -228,6 +196,7 @@ void ConsoleWindow::toggleConsole() { bar->setValue(m_last_scroll_value); } + */ } } @@ -250,25 +219,23 @@ void ConsoleWindow::closeEvent(QCloseEvent *event) void ConsoleWindow::on_btnKillMinecraft_clicked() { - ui->btnKillMinecraft->setEnabled(false); + m_killButton->setEnabled(false); auto response = CustomMessageBox::selectable( this, tr("Kill Minecraft?"), tr("This can cause the instance to get corrupted and should only be used if Minecraft " "is frozen for some reason"), QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec(); if (response == QMessageBox::Yes) - proc->killMinecraft(); + m_proc->killMinecraft(); else - ui->btnKillMinecraft->setEnabled(true); + m_killButton->setEnabled(true); } void ConsoleWindow::onEnded(InstancePtr instance, int code, QProcess::ExitStatus status) { bool peacefulExit = code == 0 && status != QProcess::CrashExit; - ui->btnKillMinecraft->setEnabled(false); - + m_killButton->setEnabled(false); setMayClose(true); - if (instance->settings().get("AutoCloseConsole").toBool()) { if (peacefulExit) @@ -277,15 +244,8 @@ void ConsoleWindow::onEnded(InstancePtr instance, int code, QProcess::ExitStatus return; } } - /* - if(!peacefulExit) - { - m_trayIcon->showMessage(tr("Oh no!"), tr("Minecraft crashed!"), QSystemTrayIcon::Critical); - } - */ if (!isVisible()) show(); - // Raise Window if (MMC->settings()->get("RaiseConsole").toBool()) { @@ -296,23 +256,10 @@ void ConsoleWindow::onEnded(InstancePtr instance, int code, QProcess::ExitStatus void ConsoleWindow::onLaunchFailed(InstancePtr instance) { - ui->btnKillMinecraft->setEnabled(false); + m_killButton->setEnabled(false); setMayClose(true); if (!isVisible()) show(); } - -void ConsoleWindow::on_btnPaste_clicked() -{ - auto text = ui->text->toPlainText(); - ProgressDialog dialog(this); - PasteUpload *paste = new PasteUpload(this, text); - dialog.exec(paste); - if (!paste->successful()) - { - CustomMessageBox::selectable(this, "Upload failed", paste->failReason(), - QMessageBox::Critical)->exec(); - } -} diff --git a/gui/ConsoleWindow.h b/gui/ConsoleWindow.h index 17c64392..97600baa 100644 --- a/gui/ConsoleWindow.h +++ b/gui/ConsoleWindow.h @@ -19,18 +19,15 @@ #include <QSystemTrayIcon> #include "logic/MinecraftProcess.h" -namespace Ui -{ -class ConsoleWindow; -} - +class QPushButton; +class PageContainer; class ConsoleWindow : public QMainWindow { Q_OBJECT public: explicit ConsoleWindow(MinecraftProcess *proc, QWidget *parent = 0); - ~ConsoleWindow(); + virtual ~ConsoleWindow() {}; /** * @brief specify if the window is allowed to close @@ -39,38 +36,12 @@ public: */ void setMayClose(bool mayclose); -private: - /** - * @brief write a colored paragraph - * @param data the string - * @param color the css color name - * this will only insert a single paragraph. - * \n are ignored. a real \n is always appended. - */ - void writeColor(QString text, const char *color, const char *background); - signals: void isClosing(); -public -slots: - /** - * @brief write a string - * @param data the string - * @param mode the WriteMode - * lines have to be put through this as a whole! - */ - void write(QString data, MessageLevel::Enum level = MessageLevel::MultiMC); - - /** - * @brief clear the text widget - */ - void clear(); - private slots: void on_closeButton_clicked(); - void on_btnScreenshots_clicked(); void on_btnKillMinecraft_clicked(); void onEnded(InstancePtr instance, int code, QProcess::ExitStatus status); @@ -79,18 +50,16 @@ slots: // FIXME: add handlers for the other MinecraftProcess signals (pre/post launch command // failures) - void on_btnPaste_clicked(); void iconActivated(QSystemTrayIcon::ActivationReason); void toggleConsole(); protected: void closeEvent(QCloseEvent *); private: - Ui::ConsoleWindow *ui = nullptr; - MinecraftProcess *proc = nullptr; + MinecraftProcess *m_proc = nullptr; bool m_mayclose = true; - int m_last_scroll_value = 0; - bool m_scroll_active = true; QSystemTrayIcon *m_trayIcon = nullptr; - int m_saved_offset = 0; + PageContainer *m_container = nullptr; + QPushButton *m_closeButton = nullptr; + QPushButton *m_killButton = nullptr; }; diff --git a/gui/ConsoleWindow.ui b/gui/ConsoleWindow.ui deleted file mode 100644 index 344cf74d..00000000 --- a/gui/ConsoleWindow.ui +++ /dev/null @@ -1,93 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>ConsoleWindow</class> - <widget class="QMainWindow" name="ConsoleWindow"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>640</width> - <height>440</height> - </rect> - </property> - <property name="windowTitle"> - <string>MultiMC Console</string> - </property> - <widget class="QWidget" name="centralwidget"> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QPlainTextEdit" name="text"> - <property name="undoRedoEnabled"> - <bool>false</bool> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - <property name="plainText"> - <string notr="true"/> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - <property name="centerOnScroll"> - <bool>false</bool> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <property name="leftMargin"> - <number>6</number> - </property> - <property name="rightMargin"> - <number>6</number> - </property> - <item> - <widget class="QPushButton" name="btnPaste"> - <property name="text"> - <string>Upload Log</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="btnScreenshots"> - <property name="text"> - <string>Manage Screenshots</string> - </property> - </widget> - </item> - <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="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> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </widget> - <resources/> - <connections/> -</ui> diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index 9661537a..bee250c4 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -56,9 +56,7 @@ #include "gui/dialogs/VersionSelectDialog.h" #include "gui/dialogs/CustomMessageBox.h" #include "gui/dialogs/LwjglSelectDialog.h" -#include "gui/dialogs/InstanceSettings.h" #include "gui/dialogs/IconPickerDialog.h" -#include "gui/dialogs/EditNotesDialog.h" #include "gui/dialogs/CopyInstanceDialog.h" #include "gui/dialogs/AccountListDialog.h" #include "gui/dialogs/AccountSelectDialog.h" @@ -67,12 +65,13 @@ #include "gui/dialogs/NotificationDialog.h" #include "gui/ConsoleWindow.h" +#include "pagedialog/PageDialog.h" -#include "logic/lists/InstanceList.h" -#include "logic/lists/MinecraftVersionList.h" -#include "logic/lists/LwjglVersionList.h" +#include "logic/InstanceList.h" +#include "logic/minecraft/MinecraftVersionList.h" +#include "logic/LwjglVersionList.h" #include "logic/icons/IconList.h" -#include "logic/lists/JavaVersionList.h" +#include "logic/java/JavaVersionList.h" #include "logic/auth/flows/AuthenticateTask.h" #include "logic/auth/flows/RefreshTask.h" @@ -90,7 +89,7 @@ #include "logic/InstanceFactory.h" #include "logic/MinecraftProcess.h" #include "logic/OneSixUpdate.h" -#include "logic/JavaUtils.h" +#include "logic/java/JavaUtils.h" #include "logic/NagUtils.h" #include "logic/SkinUtils.h" @@ -109,7 +108,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); - QString winTitle = QString("MultiMC 5 - Version %1").arg(BuildConfig.printableVersionString()); + QString winTitle = + QString("MultiMC 5 - Version %1").arg(BuildConfig.printableVersionString()); if (!BuildConfig.BUILD_PLATFORM.isEmpty()) winTitle += " on " + BuildConfig.BUILD_PLATFORM; setWindowTitle(winTitle); @@ -119,7 +119,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi // Global shortcuts { - //FIXME: This is kinda weird. and bad. We need some kind of managed shutdown. + // FIXME: This is kinda weird. and bad. We need some kind of managed shutdown. auto q = new QShortcut(QKeySequence::Quit, this); connect(q, SIGNAL(activated()), qApp, SLOT(quit())); } @@ -258,7 +258,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi auto accounts = MMC->accounts(); - QList<CacheDownloadPtr> skin_dls; + QList<CacheDownloadPtr> skin_dls; for (int i = 0; i < accounts->count(); i++) { auto account = accounts->at(i); @@ -269,21 +269,21 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi auto meta = MMC->metacache()->resolveEntry("skins", profile.name + ".png"); auto action = CacheDownload::make( QUrl("http://" + URLConstants::SKINS_BASE + profile.name + ".png"), meta); - skin_dls.append(action); + skin_dls.append(action); meta->stale = true; } } } - if(!skin_dls.isEmpty()) - { - auto job = new NetJob("Startup player skins download"); - connect(job, SIGNAL(succeeded()), SLOT(skinJobFinished())); - connect(job, SIGNAL(failed()), SLOT(skinJobFinished())); - for(auto action: skin_dls) - job->addNetAction(action); - skin_download_job.reset(job); - job->start(); - } + if (!skin_dls.isEmpty()) + { + auto job = new NetJob("Startup player skins download"); + connect(job, SIGNAL(succeeded()), SLOT(skinJobFinished())); + connect(job, SIGNAL(failed()), SLOT(skinJobFinished())); + for (auto action : skin_dls) + job->addNetAction(action); + skin_download_job.reset(job); + job->start(); + } // run the things that load and download other things... FIXME: this is NOT the place // FIXME: invisible actions in the background = NOPE. @@ -334,11 +334,10 @@ MainWindow::~MainWindow() void MainWindow::skinJobFinished() { - activeAccountChanged(); - skin_download_job.reset(); + activeAccountChanged(); + skin_download_job.reset(); } - void MainWindow::showInstanceContextMenu(const QPoint &pos) { QList<QAction *> actions; @@ -360,9 +359,10 @@ void MainWindow::showInstanceContextMenu(const QPoint &pos) QAction *actionCopyInstance = new QAction(tr("Copy instance"), this); actionCopyInstance->setToolTip(ui->actionCopyInstance->toolTip()); - - connect(actionRename, SIGNAL(triggered(bool)), SLOT(on_actionRenameInstance_triggered())); - connect(actionCopyInstance, SIGNAL(triggered(bool)), SLOT(on_actionCopyInstance_triggered())); + connect(actionRename, SIGNAL(triggered(bool)), + SLOT(on_actionRenameInstance_triggered())); + connect(actionCopyInstance, SIGNAL(triggered(bool)), + SLOT(on_actionCopyInstance_triggered())); actions.replace(1, actionRename); actions.prepend(actionSep); @@ -377,7 +377,8 @@ void MainWindow::showInstanceContextMenu(const QPoint &pos) QAction *actionCreateInstance = new QAction(tr("Create instance"), this); actionCreateInstance->setToolTip(ui->actionAddInstance->toolTip()); - connect(actionCreateInstance, SIGNAL(triggered(bool)), SLOT(on_actionAddInstance_triggered())); + connect(actionCreateInstance, SIGNAL(triggered(bool)), + SLOT(on_actionAddInstance_triggered())); actions.prepend(actionSep); actions.prepend(actionVoid); @@ -385,7 +386,7 @@ void MainWindow::showInstanceContextMenu(const QPoint &pos) } QMenu myMenu; myMenu.addActions(actions); - if(onInstance) + if (onInstance) myMenu.setEnabled(m_selectedInstance->canLaunch()); myMenu.exec(view->mapToGlobal(pos)); } @@ -398,7 +399,8 @@ void MainWindow::updateToolsMenu() } QMenu *launchMenu = new QMenu(this); QAction *normalLaunch = launchMenu->addAction(tr("Launch")); - connect(normalLaunch, &QAction::triggered, [this](){doLaunch();}); + connect(normalLaunch, &QAction::triggered, [this]() + { doLaunch(); }); launchMenu->addSeparator()->setText(tr("Profilers")); for (auto profiler : MMC->profilers().values()) { @@ -407,11 +409,13 @@ void MainWindow::updateToolsMenu() if (!profiler->check(&error)) { profilerAction->setDisabled(true); - profilerAction->setToolTip(tr("Profiler not setup correctly. Go into settings, \"External Tools\".")); + profilerAction->setToolTip( + tr("Profiler not setup correctly. Go into settings, \"External Tools\".")); } else { - connect(profilerAction, &QAction::triggered, [this, profiler](){doLaunch(true, profiler.get());}); + connect(profilerAction, &QAction::triggered, [this, profiler]() + { doLaunch(true, profiler.get()); }); } } launchMenu->addSeparator()->setText(tr("Tools")); @@ -422,14 +426,13 @@ void MainWindow::updateToolsMenu() if (!tool->check(&error)) { toolAction->setDisabled(true); - toolAction->setToolTip(tr("Tool not setup correctly. Go into settings, \"External Tools\".")); + toolAction->setToolTip( + tr("Tool not setup correctly. Go into settings, \"External Tools\".")); } else { connect(toolAction, &QAction::triggered, [this, tool]() - { - tool->createDetachedTool(m_selectedInstance, this)->run(); - }); + { tool->createDetachedTool(m_selectedInstance, this)->run(); }); } } ui->actionLaunchInstance->setMenu(launchMenu); @@ -671,7 +674,7 @@ void MainWindow::downloadUpdates(QString repo, int versionId, bool installOnExit if (updateDlg.exec(&updateTask)) { UpdateFlags baseFlags = None; - if(BuildConfig.UPDATER_DRY_RUN) + if (BuildConfig.UPDATER_DRY_RUN) baseFlags |= DryRun; if (installOnExit) MMC->installUpdates(updateTask.updateFilesDir(), baseFlags | OnExit); @@ -708,6 +711,11 @@ void MainWindow::setCatBackground(bool enabled) void MainWindow::on_actionAddInstance_triggered() { +#ifdef TEST_SEGV + // For further testing stuff. + int v = *((int *)-1); +#endif + if (!MMC->minecraftlist()->isLoaded() && m_versionLoadTask && m_versionLoadTask->isRunning()) { @@ -864,17 +872,14 @@ void MainWindow::updateInstanceToolIcon(QString new_icon) void MainWindow::setSelectedInstanceById(const QString &id) { - QModelIndex selectionIndex = proxymodel->index(0, 0); - if (!id.isNull()) + if (id.isNull()) + return; + const QModelIndex index = MMC->instances()->getInstanceIndexById(id); + if (index.isValid()) { - const QModelIndex index = MMC->instances()->getInstanceIndexById(id); - if (index.isValid()) - { - selectionIndex = proxymodel->mapFromSource(index); - } + QModelIndex selectionIndex = proxymodel->mapFromSource(index); + view->selectionModel()->setCurrentIndex(selectionIndex, QItemSelectionModel::ClearAndSelect); } - view->selectionModel()->setCurrentIndex(selectionIndex, - QItemSelectionModel::ClearAndSelect); } void MainWindow::on_actionChangeInstGroup_triggered() @@ -938,6 +943,37 @@ void MainWindow::on_actionSettings_triggered() updateToolsMenu(); } +template <typename T> +void ShowPageDialog(T raw_provider, QWidget * parent, QString open_page = QString()) +{ + auto provider = std::dynamic_pointer_cast<BasePageProvider>(raw_provider); + if(!provider) + return; + PageDialog dlg(provider, open_page, parent); + dlg.exec(); +} + +void MainWindow::on_actionInstanceSettings_triggered() +{ + ShowPageDialog(m_selectedInstance, this, "settings"); +} + +void MainWindow::on_actionEditInstNotes_triggered() +{ + ShowPageDialog(m_selectedInstance, this, "notes"); +} + +void MainWindow::on_actionEditInstance_triggered() +{ + ShowPageDialog(m_selectedInstance, this); +} + +void MainWindow::on_actionScreenshots_triggered() +{ + ShowPageDialog(m_selectedInstance, this, "screenshots"); +} + + void MainWindow::on_actionManageAccounts_triggered() { AccountListDialog dialog(this); @@ -1026,17 +1062,6 @@ void MainWindow::on_actionViewSelectedInstFolder_triggered() } } -void MainWindow::on_actionEditInstMods_triggered() -{ - if (m_selectedInstance) - { - auto dialog = m_selectedInstance->createModEditDialog(this); - if (dialog) - dialog->exec(); - dialog->deleteLater(); - } -} - void MainWindow::closeEvent(QCloseEvent *event) { // Save the window state and geometry. @@ -1062,10 +1087,10 @@ void MainWindow::instanceActivated(QModelIndex index) { if (!index.isValid()) return; - QString id = index.data(InstanceList::InstanceIDRole).toString(); + QString id = index.data(InstanceList::InstanceIDRole).toString(); InstancePtr inst = MMC->instances()->getInstanceById(id); - if(!inst) - return; + if (!inst) + return; NagUtils::checkJVMArgs(inst->settings().get("JvmArgs").toString(), this); @@ -1218,7 +1243,8 @@ void MainWindow::doLaunch(bool online, BaseProfilerFactory *profiler) } } -void MainWindow::updateInstance(InstancePtr instance, AuthSessionPtr session, BaseProfilerFactory *profiler) +void MainWindow::updateInstance(InstancePtr instance, AuthSessionPtr session, + BaseProfilerFactory *profiler) { auto updateTask = instance->doUpdate(); if (!updateTask) @@ -1233,14 +1259,15 @@ void MainWindow::updateInstance(InstancePtr instance, AuthSessionPtr session, Ba tDialog.exec(updateTask.get()); } -void MainWindow::launchInstance(InstancePtr instance, AuthSessionPtr session, BaseProfilerFactory *profiler) +void MainWindow::launchInstance(InstancePtr instance, AuthSessionPtr session, + BaseProfilerFactory *profiler) { Q_ASSERT_X(instance != NULL, "launchInstance", "instance is NULL"); Q_ASSERT_X(session.get() != nullptr, "launchInstance", "session is NULL"); QString launchScript; - if(!instance->prepareForLaunch(session, launchScript)) + if (!instance->prepareForLaunch(session, launchScript)) return; MinecraftProcess *proc = new MinecraftProcess(instance); @@ -1260,7 +1287,8 @@ void MainWindow::launchInstance(InstancePtr instance, AuthSessionPtr session, Ba QString error; if (!profiler->check(&error)) { - QMessageBox::critical(this, tr("Error"), tr("Couldn't start profiler: %1").arg(error)); + QMessageBox::critical(this, tr("Error"), + tr("Couldn't start profiler: %1").arg(error)); proc->abort(); return; } @@ -1270,9 +1298,11 @@ void MainWindow::launchInstance(InstancePtr instance, AuthSessionPtr session, Ba dialog.setMaximum(0); dialog.setValue(0); dialog.setLabelText(tr("Waiting for profiler...")); - connect(&dialog, &QProgressDialog::canceled, profilerInstance, &BaseProfiler::abortProfiling); + connect(&dialog, &QProgressDialog::canceled, profilerInstance, + &BaseProfiler::abortProfiling); dialog.show(); - connect(profilerInstance, &BaseProfiler::readyToLaunch, [&dialog, this, proc](const QString &message) + connect(profilerInstance, &BaseProfiler::readyToLaunch, + [&dialog, this, proc](const QString & message) { dialog.accept(); QMessageBox msg; @@ -1285,7 +1315,8 @@ void MainWindow::launchInstance(InstancePtr instance, AuthSessionPtr session, Ba msg.exec(); proc->launch(); }); - connect(profilerInstance, &BaseProfiler::abortLaunch, [&dialog, this, proc](const QString &message) + connect(profilerInstance, &BaseProfiler::abortLaunch, + [&dialog, this, proc](const QString & message) { dialog.accept(); QMessageBox msg; @@ -1333,119 +1364,26 @@ void MainWindow::startTask(Task *task) 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); - - Util::createShortCut(Util::getDesktopDir(), QApplication::instance()->applicationFilePath(), - QStringList() << "-dl" << QDir::currentPath() << "test", name, - "application-x-octet-stream"); - - CustomMessageBox::selectable( - this, tr("Not useful"), - tr("A Dummy Shortcut was created. it will not do anything productive"), - QMessageBox::Warning)->show(); -} - // BrowserDialog void MainWindow::openWebPage(QUrl url) { QDesktopServices::openUrl(url); } -void MainWindow::on_actionChangeInstMCVersion_triggered() +void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex &previous) { - if (view->selectionModel()->selectedIndexes().count() < 1) - return; - - VersionSelectDialog vselect(m_selectedInstance->versionList().get(), - tr("Change Minecraft version"), this); - vselect.setFuzzyFilter(1, "*OneSix*"); - if (!vselect.exec() || !vselect.selectedVersion()) - return; - - if (!MMC->accounts()->anyAccountIsValid()) - { - CustomMessageBox::selectable( - this, tr("Error"), - tr("MultiMC cannot download Minecraft or update instances unless you have at least " - "one account added.\nPlease add your Mojang or Minecraft account."), - QMessageBox::Warning)->show(); - return; - } - - if (m_selectedInstance->versionIsCustom()) - { - auto result = CustomMessageBox::selectable( - 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::Warning, QMessageBox::Ok | QMessageBox::Abort, - QMessageBox::Abort)->exec(); - - if (result != QMessageBox::Ok) - return; - } - m_selectedInstance->setIntendedVersionId(vselect.selectedVersion()->descriptor()); - - auto updateTask = m_selectedInstance->doUpdate(); - if (!updateTask) + if(!current.isValid()) { + MMC->settings()->set("SelectedInstance", QString()); + selectionBad(); return; } - ProgressDialog tDialog(this); - connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString))); - tDialog.exec(updateTask.get()); -} - -void MainWindow::on_actionChangeInstLWJGLVersion_triggered() -{ - if (!m_selectedInstance) - return; - - LWJGLSelectDialog lselect(this); - lselect.exec(); - if (lselect.result() == QDialog::Accepted) - { - auto ptr = std::dynamic_pointer_cast<LegacyInstance>(m_selectedInstance); - if(ptr) - ptr->setLWJGLVersion(lselect.selectedVersion()); - } -} - -void MainWindow::on_actionInstanceSettings_triggered() -{ - if (view->selectionModel()->selectedIndexes().count() < 1) - return; - - InstanceSettings settings(&m_selectedInstance->settings(), this); - settings.setWindowTitle(tr("Instance settings")); - settings.exec(); -} - -void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex &previous) -{ - if(!current.isValid()) - { - selectionBad(); - MMC->settings()->set("SelectedInstance", QString()); - return; - } - QString id = current.data(InstanceList::InstanceIDRole).toString(); - m_selectedInstance = MMC->instances()->getInstanceById(id); + QString id = current.data(InstanceList::InstanceIDRole).toString(); + m_selectedInstance = MMC->instances()->getInstanceById(id); if ( m_selectedInstance ) { ui->instanceToolBar->setEnabled(m_selectedInstance->canLaunch()); renameButton->setText(m_selectedInstance->name()); - ui->actionChangeInstLWJGLVersion->setEnabled( - m_selectedInstance->menuActionEnabled("actionChangeInstLWJGLVersion")); - ui->actionEditInstMods->setEnabled( - m_selectedInstance->menuActionEnabled("actionEditInstMods")); - ui->actionChangeInstMCVersion->setEnabled( - m_selectedInstance->menuActionEnabled("actionChangeInstMCVersion")); m_statusLeft->setText(m_selectedInstance->getStatusbarDescription()); updateInstanceToolIcon(m_selectedInstance->iconKey()); @@ -1455,9 +1393,9 @@ void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex & } else { - selectionBad(); - MMC->settings()->set("SelectedInstance", QString()); - return; + MMC->settings()->set("SelectedInstance", QString()); + selectionBad(); + return; } } @@ -1475,20 +1413,6 @@ void MainWindow::selectionBad() setSelectedInstanceById(MMC->settings()->get("SelectedInstance").toString()); } -void MainWindow::on_actionEditInstNotes_triggered() -{ - if (!m_selectedInstance) - return; - - EditNotesDialog noteedit(m_selectedInstance->notes(), m_selectedInstance->name(), this); - noteedit.exec(); - if (noteedit.result() == QDialog::Accepted) - { - - m_selectedInstance->setNotes(noteedit.getText()); - } -} - void MainWindow::instanceEnded() { this->show(); @@ -1522,7 +1446,9 @@ void MainWindow::checkMigrateLegacyAssets() void MainWindow::checkSetDefaultJava() { + const QString javaHack = "IntelHack"; bool askForJava = false; + do { QString currentHostName = QHostInfo::localHostName(); QString oldHostName = MMC->settings()->get("LastHostname").toString(); @@ -1530,16 +1456,30 @@ void MainWindow::checkSetDefaultJava() { MMC->settings()->set("LastHostname", currentHostName); askForJava = true; + break; } - } - - { QString currentJavaPath = MMC->settings()->get("JavaPath").toString(); if (currentJavaPath.isEmpty()) { askForJava = true; + break; } - } + #if defined Q_OS_WIN32 + QString currentHack = MMC->settings()->get("JavaDetectionHack").toString(); + if (currentHack != javaHack) + { + CustomMessageBox::selectable( + this, tr("Java detection forced"), + tr("Because of graphics performance issues caused by Intel drivers on Windows, " + "MultiMC java detection was forced. Please select a Java " + "version.<br/><br/>If you have custom java versions set for your instances, " + "make sure you use the 'javaw.exe' executable."), + QMessageBox::Warning)->exec(); + askForJava = true; + break; + } + #endif + } while (0); if (askForJava) { @@ -1567,7 +1507,10 @@ void MainWindow::checkSetDefaultJava() java = ju.GetDefaultJava(); } if (java) + { MMC->settings()->set("JavaPath", java->path); + MMC->settings()->set("JavaDetectionHack", javaHack); + } else MMC->settings()->set("JavaPath", QString("java")); } diff --git a/gui/MainWindow.h b/gui/MainWindow.h index 45ca520c..182e9c0c 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -19,11 +19,10 @@ #include <QProcess> #include <QTimer> -#include "logic/lists/InstanceList.h" +#include "logic/InstanceList.h" #include "logic/BaseInstance.h" - #include "logic/auth/MojangAccount.h" -#include <logic/net/NetJob.h> +#include "logic/net/NetJob.h" class QToolButton; class LabeledToolButton; @@ -81,6 +80,8 @@ slots: void on_actionSettings_triggered(); + void on_actionInstanceSettings_triggered(); + void on_actionManageAccounts_triggered(); void on_actionReportBug_triggered(); @@ -103,14 +104,12 @@ slots: void on_actionRenameInstance_triggered(); - void on_actionMakeDesktopShortcut_triggered(); - - void on_actionChangeInstMCVersion_triggered(); - - void on_actionEditInstMods_triggered(); + void on_actionEditInstance_triggered(); void on_actionEditInstNotes_triggered(); + void on_actionScreenshots_triggered(); + /*! * Launches the currently selected instance with the default account. * If no default account is selected, prompts the user to pick an account. @@ -133,12 +132,8 @@ slots: void taskStart(); void taskEnd(); - void on_actionChangeInstLWJGLVersion_triggered(); - void instanceEnded(); - void on_actionInstanceSettings_triggered(); - // called when an icon is changed in the icon model. void iconUpdated(QString); diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui index 47789449..7adc5d37 100644 --- a/gui/MainWindow.ui +++ b/gui/MainWindow.ui @@ -115,10 +115,8 @@ <addaction name="separator"/> <addaction name="actionScreenshots"/> <addaction name="separator"/> + <addaction name="actionEditInstance"/> <addaction name="actionInstanceSettings"/> - <addaction name="actionChangeInstMCVersion"/> - <addaction name="actionChangeInstLWJGLVersion"/> - <addaction name="actionEditInstMods"/> <addaction name="actionViewSelectedInstFolder"/> <addaction name="actionConfig_Folder"/> <addaction name="separator"/> @@ -388,82 +386,18 @@ <string>Edit the notes for the selected instance.</string> </property> </action> - <action name="actionInstanceSettings"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>Settings</string> - </property> - <property name="toolTip"> - <string>Change settings for the selected instance.</string> - </property> - <property name="statusTip"> - <string>Change settings for the selected instance.</string> - </property> - </action> - <action name="actionMakeDesktopShortcut"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Make Shortcut</string> - </property> - <property name="toolTip"> - <string>Make a shortcut on the desktop for the selected instance.</string> - </property> - <property name="statusTip"> - <string>Make a shortcut on the desktop for the selected instance.</string> - </property> - </action> - <action name="actionManageInstSaves"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Manage Saves</string> - </property> - <property name="toolTip"> - <string>Manage saves for the selected instance.</string> - </property> - <property name="statusTip"> - <string>Manage saves for the selected instance.</string> - </property> - </action> - <action name="actionEditInstMods"> + <action name="actionEditInstance"> <property name="text"> <string>Edit Mods</string> </property> - <property name="toolTip"> - <string>Edit the mods for the selected instance.</string> - </property> - <property name="statusTip"> - <string>Edit the mods for the selected instance.</string> - </property> - </action> - <action name="actionChangeInstMCVersion"> - <property name="text"> - <string>Change Version</string> - </property> - <property name="toolTip"> - <string>Change the selected instance's Minecraft version.</string> - </property> - <property name="statusTip"> - <string>Change the selected instance's Minecraft version.</string> - </property> - </action> - <action name="actionChangeInstLWJGLVersion"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Change LWJGL</string> + <property name="iconText"> + <string>Edit Instance</string> </property> <property name="toolTip"> - <string>Change the version of LWJGL for the selected instance to use.</string> + <string>Change the instance settings, mods and versions.</string> </property> <property name="statusTip"> - <string>Change the version of LWJGL for the selected instance to use.</string> + <string>Change the instance settings, mods and versions.</string> </property> </action> <action name="actionViewSelectedInstFolder"> @@ -555,6 +489,14 @@ <string><html><head/><body><p>View and upload screenshots for this instance</p></body></html></string> </property> </action> + <action name="actionInstanceSettings"> + <property name="text"> + <string>Instance Settings</string> + </property> + <property name="toolTip"> + <string>Change the settings specific to the instance</string> + </property> + </action> </widget> <layoutdefault spacing="6" margin="11"/> <resources> diff --git a/gui/dialogs/CopyInstanceDialog.cpp b/gui/dialogs/CopyInstanceDialog.cpp index 71429367..188cf274 100644 --- a/gui/dialogs/CopyInstanceDialog.cpp +++ b/gui/dialogs/CopyInstanceDialog.cpp @@ -28,7 +28,6 @@ #include "logic/InstanceFactory.h" #include "logic/BaseVersion.h" #include "logic/icons/IconList.h" -#include "logic/lists/MinecraftVersionList.h" #include "logic/tasks/Task.h" #include "logic/BaseInstance.h" diff --git a/gui/dialogs/EditNotesDialog.cpp b/gui/dialogs/EditNotesDialog.cpp deleted file mode 100644 index f2aa029f..00000000 --- a/gui/dialogs/EditNotesDialog.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* 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 "EditNotesDialog.h" -#include "ui_EditNotesDialog.h" -#include "gui/Platform.h" - -#include <QIcon> -#include <QApplication> - -EditNotesDialog::EditNotesDialog(QString notes, QString name, QWidget *parent) - : QDialog(parent), ui(new Ui::EditNotesDialog), m_instance_name(name), - m_instance_notes(notes) -{ - MultiMCPlatform::fixWM_CLASS(this); - ui->setupUi(this); - ui->noteEditor->setText(notes); - setWindowTitle(tr("Edit notes of %1").arg(m_instance_name)); - // connect(ui->closeButton, SIGNAL(clicked()), SLOT(close())); -} - -EditNotesDialog::~EditNotesDialog() -{ - delete ui; -} - -QString EditNotesDialog::getText() -{ - QString test = ui->noteEditor->toPlainText(); - return test; -} diff --git a/gui/dialogs/EditNotesDialog.ui b/gui/dialogs/EditNotesDialog.ui deleted file mode 100644 index 487dfb84..00000000 --- a/gui/dialogs/EditNotesDialog.ui +++ /dev/null @@ -1,77 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>EditNotesDialog</class> - <widget class="QDialog" name="EditNotesDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>459</width> - <height>399</height> - </rect> - </property> - <property name="windowTitle"> - <string>Edit Notes</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QTextEdit" name="noteEditor"> - <property name="verticalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOn</enum> - </property> - <property name="acceptRichText"> - <bool>false</bool> - </property> - <property name="textInteractionFlags"> - <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextEditable|Qt::TextEditorInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> - </property> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>EditNotesDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>EditNotesDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/gui/dialogs/InstanceSettings.cpp b/gui/dialogs/InstanceSettings.cpp deleted file mode 100644 index edb4a921..00000000 --- a/gui/dialogs/InstanceSettings.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* Copyright 2013 MultiMC Contributors - * - * Authors: Andrew Okin - * Peterix - * 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 "MultiMC.h" -#include "InstanceSettings.h" -#include "ui_InstanceSettings.h" -#include "gui/Platform.h" -#include "gui/dialogs/VersionSelectDialog.h" - -#include "logic/JavaUtils.h" -#include "logic/NagUtils.h" -#include "logic/lists/JavaVersionList.h" -#include "logic/JavaChecker.h" - -#include <QFileDialog> -#include <QMessageBox> - -InstanceSettings::InstanceSettings(SettingsObject *obj, QWidget *parent) - : QDialog(parent), ui(new Ui::InstanceSettings), m_obj(obj) -{ - MultiMCPlatform::fixWM_CLASS(this); - ui->setupUi(this); - - restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("SettingsGeometry").toByteArray())); - - loadSettings(); -} - -InstanceSettings::~InstanceSettings() -{ - delete ui; -} - -void InstanceSettings::showEvent(QShowEvent *ev) -{ - QDialog::showEvent(ev); -} - -void InstanceSettings::closeEvent(QCloseEvent *ev) -{ - MMC->settings()->set("SettingsGeometry", saveGeometry().toBase64()); - - QDialog::closeEvent(ev); -} - -void InstanceSettings::on_customCommandsGroupBox_toggled(bool state) -{ - ui->labelCustomCmdsDescription->setEnabled(state); -} - -void InstanceSettings::on_buttonBox_accepted() -{ - MMC->settings()->set("SettingsGeometry", saveGeometry().toBase64()); - - applySettings(); - accept(); -} - -void InstanceSettings::on_buttonBox_rejected() -{ - MMC->settings()->set("SettingsGeometry", saveGeometry().toBase64()); - - reject(); -} - -void InstanceSettings::applySettings() -{ - // Console - bool console = ui->consoleSettingsBox->isChecked(); - m_obj->set("OverrideConsole", console); - if (console) - { - m_obj->set("ShowConsole", ui->showConsoleCheck->isChecked()); - m_obj->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked()); - } - else - { - m_obj->reset("ShowConsole"); - m_obj->reset("AutoCloseConsole"); - } - - // Window Size - bool window = ui->windowSizeGroupBox->isChecked(); - m_obj->set("OverrideWindow", window); - if (window) - { - m_obj->set("LaunchMaximized", ui->maximizedCheckBox->isChecked()); - m_obj->set("MinecraftWinWidth", ui->windowWidthSpinBox->value()); - m_obj->set("MinecraftWinHeight", ui->windowHeightSpinBox->value()); - } - else - { - m_obj->reset("LaunchMaximized"); - m_obj->reset("MinecraftWinWidth"); - m_obj->reset("MinecraftWinHeight"); - } - - // Memory - bool memory = ui->memoryGroupBox->isChecked(); - m_obj->set("OverrideMemory", memory); - if (memory) - { - m_obj->set("MinMemAlloc", ui->minMemSpinBox->value()); - m_obj->set("MaxMemAlloc", ui->maxMemSpinBox->value()); - m_obj->set("PermGen", ui->permGenSpinBox->value()); - } - else - { - m_obj->reset("MinMemAlloc"); - m_obj->reset("MaxMemAlloc"); - m_obj->reset("PermGen"); - } - - // Java Settings - bool java = ui->javaSettingsGroupBox->isChecked(); - m_obj->set("OverrideJava", java); - if (java) - { - m_obj->set("JavaPath", ui->javaPathTextBox->text()); - m_obj->set("JvmArgs", ui->jvmArgsTextBox->text()); - - NagUtils::checkJVMArgs(m_obj->get("JvmArgs").toString(), this->parentWidget()); - } - else - { - m_obj->reset("JavaPath"); - m_obj->reset("JvmArgs"); - } - - // Custom Commands - bool custcmd = ui->customCommandsGroupBox->isChecked(); - m_obj->set("OverrideCommands", custcmd); - if (custcmd) - { - m_obj->set("PreLaunchCommand", ui->preLaunchCmdTextBox->text()); - m_obj->set("PostExitCommand", ui->postExitCmdTextBox->text()); - } - else - { - m_obj->reset("PreLaunchCommand"); - m_obj->reset("PostExitCommand"); - } -} - -void InstanceSettings::loadSettings() -{ - // Console - ui->consoleSettingsBox->setChecked(m_obj->get("OverrideConsole").toBool()); - ui->showConsoleCheck->setChecked(m_obj->get("ShowConsole").toBool()); - ui->autoCloseConsoleCheck->setChecked(m_obj->get("AutoCloseConsole").toBool()); - - // Window Size - ui->windowSizeGroupBox->setChecked(m_obj->get("OverrideWindow").toBool()); - ui->maximizedCheckBox->setChecked(m_obj->get("LaunchMaximized").toBool()); - ui->windowWidthSpinBox->setValue(m_obj->get("MinecraftWinWidth").toInt()); - ui->windowHeightSpinBox->setValue(m_obj->get("MinecraftWinHeight").toInt()); - - // Memory - ui->memoryGroupBox->setChecked(m_obj->get("OverrideMemory").toBool()); - ui->minMemSpinBox->setValue(m_obj->get("MinMemAlloc").toInt()); - ui->maxMemSpinBox->setValue(m_obj->get("MaxMemAlloc").toInt()); - ui->permGenSpinBox->setValue(m_obj->get("PermGen").toInt()); - - // Java Settings - ui->javaSettingsGroupBox->setChecked(m_obj->get("OverrideJava").toBool()); - ui->javaPathTextBox->setText(m_obj->get("JavaPath").toString()); - ui->jvmArgsTextBox->setText(m_obj->get("JvmArgs").toString()); - - // Custom Commands - ui->customCommandsGroupBox->setChecked(m_obj->get("OverrideCommands").toBool()); - ui->preLaunchCmdTextBox->setText(m_obj->get("PreLaunchCommand").toString()); - ui->postExitCmdTextBox->setText(m_obj->get("PostExitCommand").toString()); -} - -void InstanceSettings::on_javaDetectBtn_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 InstanceSettings::on_javaBrowseBtn_clicked() -{ - QString dir = QFileDialog::getOpenFileName(this, tr("Find Java executable")); - if (!dir.isNull()) - { - ui->javaPathTextBox->setText(dir); - } -} - -void InstanceSettings::on_javaTestBtn_clicked() -{ - checker.reset(new JavaChecker()); - connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this, - SLOT(checkFinished(JavaCheckResult))); - checker->path = ui->javaPathTextBox->text(); - checker->performCheck(); -} - -void InstanceSettings::checkFinished(JavaCheckResult result) -{ - if (result.valid) - { - QString text; - text += "Java test succeeded!\n"; - if (result.is_64bit) - text += "Using 64bit java.\n"; - text += "\n"; - text += "Platform reported: " + result.realPlatform; - QMessageBox::information(this, tr("Java test success"), text); - } - else - { - QMessageBox::warning( - this, tr("Java test failure"), - tr("The specified java binary didn't work. You should use the auto-detect feature, " - "or set the path to the java executable.")); - } -} diff --git a/gui/dialogs/LegacyModEditDialog.cpp b/gui/dialogs/LegacyModEditDialog.cpp deleted file mode 100644 index e5039c02..00000000 --- a/gui/dialogs/LegacyModEditDialog.cpp +++ /dev/null @@ -1,393 +0,0 @@ -/* 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 "MultiMC.h" -#include "LegacyModEditDialog.h" -#include "ModEditDialogCommon.h" -#include "VersionSelectDialog.h" -#include "ProgressDialog.h" -#include "ui_LegacyModEditDialog.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) - : QDialog(parent), ui(new Ui::LegacyModEditDialog), m_inst(inst) -{ - MultiMCPlatform::fixWM_CLASS(this); - ui->setupUi(this); - - // Jar mods - { - ensureFolderPathExists(m_inst->jarModsDir()); - m_jarmods = m_inst->jarModList(); - 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); - 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.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.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.get()); - ui->texPackTreeView->installEventFilter(this); - m_texturepacks->startWatching(); - } -} - -LegacyModEditDialog::~LegacyModEditDialog() -{ - m_mods->stopWatching(); - m_coremods->stopWatching(); - m_jarmods->stopWatching(); - m_texturepacks->stopWatching(); - delete ui; -} - -bool LegacyModEditDialog::coreListFilter(QKeyEvent *keyEvent) -{ - switch (keyEvent->key()) - { - 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); -} - -bool LegacyModEditDialog::jarListFilter(QKeyEvent *keyEvent) -{ - switch (keyEvent->key()) - { - case Qt::Key_Up: - { - if (keyEvent->modifiers() & Qt::ControlModifier) - { - on_moveJarUpBtn_clicked(); - return true; - } - break; - } - case Qt::Key_Down: - { - 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(); - return true; - default: - break; - } - return QDialog::eventFilter(ui->jarModsTreeView, keyEvent); -} - -bool LegacyModEditDialog::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 LegacyModEditDialog::texturePackListFilter(QKeyEvent *keyEvent) -{ - switch (keyEvent->key()) - { - 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); -} - -bool LegacyModEditDialog::eventFilter(QObject *obj, QEvent *ev) -{ - if (ev->type() != QEvent::KeyPress) - { - return QDialog::eventFilter(obj, ev); - } - QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev); - if (obj == ui->jarModsTreeView) - return jarListFilter(keyEvent); - if (obj == ui->coreModsTreeView) - return coreListFilter(keyEvent); - if (obj == ui->loaderModTreeView) - return loaderListFilter(keyEvent); - if (obj == ui->texPackTreeView) - return texturePackListFilter(keyEvent); - return QDialog::eventFilter(obj, ev); -} - -void LegacyModEditDialog::on_addCoreBtn_clicked() -{ - //: 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)); - m_coremods->startWatching(); - } -} -void LegacyModEditDialog::on_addForgeBtn_clicked() -{ - VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this); - vselect.setExactFilter(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) - { - NetJob *fjob = new NetJob("Forge download"); - fjob->addNetAction(CacheDownload::make(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() -{ - //: 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)); - m_jarmods->startWatching(); - } -} -void LegacyModEditDialog::on_addModBtn_clicked() -{ - //: 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)); - m_mods->startWatching(); - } -} -void LegacyModEditDialog::on_addTexPackBtn_clicked() -{ - //: 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)); - m_texturepacks->startWatching(); - } -} - -void LegacyModEditDialog::on_moveJarDownBtn_clicked() -{ - int first, last; - auto list = ui->jarModsTreeView->selectionModel()->selectedRows(); - - if (!lastfirst(list, first, last)) - return; - - m_jarmods->moveModsDown(first, last); -} -void LegacyModEditDialog::on_moveJarUpBtn_clicked() -{ - int first, last; - auto list = ui->jarModsTreeView->selectionModel()->selectedRows(); - - if (!lastfirst(list, first, last)) - return; - m_jarmods->moveModsUp(first, last); -} -void LegacyModEditDialog::on_rmCoreBtn_clicked() -{ - int first, last; - auto list = ui->coreModsTreeView->selectionModel()->selectedRows(); - - if (!lastfirst(list, first, last)) - return; - m_coremods->stopWatching(); - m_coremods->deleteMods(first, last); - m_coremods->startWatching(); -} -void LegacyModEditDialog::on_rmJarBtn_clicked() -{ - int first, last; - auto list = ui->jarModsTreeView->selectionModel()->selectedRows(); - - if (!lastfirst(list, first, last)) - return; - m_jarmods->stopWatching(); - m_jarmods->deleteMods(first, last); - m_jarmods->startWatching(); -} -void LegacyModEditDialog::on_rmModBtn_clicked() -{ - int first, last; - auto list = ui->loaderModTreeView->selectionModel()->selectedRows(); - - if (!lastfirst(list, first, last)) - return; - m_mods->stopWatching(); - m_mods->deleteMods(first, last); - m_mods->startWatching(); -} -void LegacyModEditDialog::on_rmTexPackBtn_clicked() -{ - int first, last; - auto list = ui->texPackTreeView->selectionModel()->selectedRows(); - - if (!lastfirst(list, first, last)) - return; - m_texturepacks->stopWatching(); - m_texturepacks->deleteMods(first, last); - m_texturepacks->startWatching(); -} -void LegacyModEditDialog::on_viewCoreBtn_clicked() -{ - openDirInDefaultProgram(m_inst->coreModsDir(), true); -} -void LegacyModEditDialog::on_viewModBtn_clicked() -{ - openDirInDefaultProgram(m_inst->loaderModsDir(), true); -} -void LegacyModEditDialog::on_viewTexPackBtn_clicked() -{ - openDirInDefaultProgram(m_inst->texturePacksDir(), true); -} - -void LegacyModEditDialog::on_buttonBox_rejected() -{ - close(); -} - -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/dialogs/LegacyModEditDialog.h b/gui/dialogs/LegacyModEditDialog.h deleted file mode 100644 index d5582aef..00000000 --- a/gui/dialogs/LegacyModEditDialog.h +++ /dev/null @@ -1,78 +0,0 @@ -/* 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 <QDialog> -#include "logic/LegacyInstance.h" -#include <logic/net/NetJob.h> - -namespace Ui -{ -class LegacyModEditDialog; -} - -class LegacyModEditDialog : public QDialog -{ - Q_OBJECT - -public: - explicit LegacyModEditDialog(LegacyInstance *inst, QWidget *parent = 0); - ~LegacyModEditDialog(); - -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); - -private: - Ui::LegacyModEditDialog *ui; - 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; - NetJobPtr forgeJob; -}; diff --git a/gui/dialogs/LegacyModEditDialog.ui b/gui/dialogs/LegacyModEditDialog.ui deleted file mode 100644 index 0662c712..00000000 --- a/gui/dialogs/LegacyModEditDialog.ui +++ /dev/null @@ -1,321 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>LegacyModEditDialog</class> - <widget class="QDialog" name="LegacyModEditDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>540</width> - <height>420</height> - </rect> - </property> - <property name="windowTitle"> - <string>Edit Mods</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QTabWidget" name="tabWidget"> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="jarTab"> - <attribute name="title"> - <string>Jar Mods</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <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> - <item> - <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="QVBoxLayout" name="verticalLayout_3"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_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> - <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="QVBoxLayout" name="verticalLayout_4"> - <item> - <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> - <item> - <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"> - <property name="acceptDrops"> - <bool>false</bool> - </property> - <attribute name="title"> - <string>Texture Packs</string> - </attribute> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <widget class="ModListView" name="texPackTreeView"> - <property name="acceptDrops"> - <bool>true</bool> - </property> - <property name="dragDropMode"> - <enum>QAbstractItemView::DropOnly</enum> - </property> - </widget> - </item> - <item> - <layout class="QVBoxLayout" name="texturePacksButtonBox"> - <item> - <widget class="QPushButton" name="addTexPackBtn"> - <property name="text"> - <string>&Add</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="rmTexPackBtn"> - <property name="text"> - <string>&Remove</string> - </property> - </widget> - </item> - <item> - <spacer name="texturePacksButtonSpacer"> - <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="viewTexPackBtn"> - <property name="text"> - <string>&View Folder</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="standardButtons"> - <set>QDialogButtonBox::Close</set> - </property> - </widget> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>ModListView</class> - <extends>QTreeView</extends> - <header>gui/widgets/ModListView.h</header> - </customwidget> - <customwidget> - <class>MCModInfoFrame</class> - <extends>QFrame</extends> - <header>gui/widgets/MCModInfoFrame.h</header> - <container>1</container> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui> diff --git a/gui/dialogs/LwjglSelectDialog.cpp b/gui/dialogs/LwjglSelectDialog.cpp index 046a4e2e..e64228b2 100644 --- a/gui/dialogs/LwjglSelectDialog.cpp +++ b/gui/dialogs/LwjglSelectDialog.cpp @@ -18,7 +18,7 @@ #include "ui_LwjglSelectDialog.h" #include "gui/Platform.h" -#include "logic/lists/LwjglVersionList.h" +#include "logic/LwjglVersionList.h" LWJGLSelectDialog::LWJGLSelectDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LWJGLSelectDialog) diff --git a/gui/dialogs/ModEditDialogCommon.cpp b/gui/dialogs/ModEditDialogCommon.cpp index eee42e5e..35942374 100644 --- a/gui/dialogs/ModEditDialogCommon.cpp +++ b/gui/dialogs/ModEditDialogCommon.cpp @@ -1,24 +1,7 @@ -/* 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 "ModEditDialogCommon.h" #include "CustomMessageBox.h" -#include <QDesktopServices> -#include <QMessageBox> -#include <QString> #include <QUrl> + bool lastfirst(QModelIndexList &list, int &first, int &last) { if (!list.size()) @@ -54,4 +37,4 @@ void showWebsiteForMod(QWidget *parentDlg, Mod &m) QObject::tr("The mod author didn't provide a website link for this mod."), QMessageBox::Warning); } -} +}
\ No newline at end of file diff --git a/gui/dialogs/ModEditDialogCommon.h b/gui/dialogs/ModEditDialogCommon.h index a226d5a9..3ccfbf6b 100644 --- a/gui/dialogs/ModEditDialogCommon.h +++ b/gui/dialogs/ModEditDialogCommon.h @@ -1,22 +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 - * 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 <QAbstractItemModel> +#include <QModelIndex> +#include <QDesktopServices> +#include <QWidget> #include <logic/Mod.h> bool lastfirst(QModelIndexList &list, int &first, int &last); -void showWebsiteForMod(QWidget *parentDlg, Mod &m);
\ No newline at end of file +void showWebsiteForMod(QWidget *parentDlg, Mod &m); diff --git a/gui/dialogs/NewInstanceDialog.cpp b/gui/dialogs/NewInstanceDialog.cpp index c7b273af..41ae329c 100644 --- a/gui/dialogs/NewInstanceDialog.cpp +++ b/gui/dialogs/NewInstanceDialog.cpp @@ -20,7 +20,7 @@ #include "logic/InstanceFactory.h" #include "logic/BaseVersion.h" #include "logic/icons/IconList.h" -#include "logic/lists/MinecraftVersionList.h" +#include "logic/minecraft/MinecraftVersionList.h" #include "logic/tasks/Task.h" #include "gui/Platform.h" @@ -47,7 +47,7 @@ NewInstanceDialog::NewInstanceDialog(QWidget *parent) taskDlg->exec(loadTask); } */ - setSelectedVersion(MMC->minecraftlist()->getLatestStable()); + setSelectedVersion(MMC->minecraftlist()->getLatestStable(), true); InstIconKey = "infinity"; ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey)); } @@ -63,13 +63,17 @@ void NewInstanceDialog::updateDialogState() ->setEnabled(!instName().isEmpty() && m_selectedVersion); } -void NewInstanceDialog::setSelectedVersion(BaseVersionPtr version) +void NewInstanceDialog::setSelectedVersion(BaseVersionPtr version, bool initial) { m_selectedVersion = version; if (m_selectedVersion) { ui->versionTextBox->setText(version->name()); + if(ui->instNameTextBox->text().isEmpty() && !initial) + { + ui->instNameTextBox->setText(version->name()); + } } else { diff --git a/gui/dialogs/NewInstanceDialog.h b/gui/dialogs/NewInstanceDialog.h index 4357c28d..17045ec0 100644 --- a/gui/dialogs/NewInstanceDialog.h +++ b/gui/dialogs/NewInstanceDialog.h @@ -33,7 +33,7 @@ public: void updateDialogState(); - void setSelectedVersion(BaseVersionPtr version); + void setSelectedVersion(BaseVersionPtr version, bool initial = false); void loadVersionList(); diff --git a/gui/dialogs/OneSixModEditDialog.cpp b/gui/dialogs/OneSixModEditDialog.cpp deleted file mode 100644 index a3598eb9..00000000 --- a/gui/dialogs/OneSixModEditDialog.cpp +++ /dev/null @@ -1,399 +0,0 @@ -/* 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 "MultiMC.h" - -#include <pathutils.h> -#include <QFileDialog> -#include <QMessageBox> -#include <QDebug> -#include <QEvent> -#include <QKeyEvent> -#include <QDesktopServices> - -#include "OneSixModEditDialog.h" -#include "ModEditDialogCommon.h" -#include "ui_OneSixModEditDialog.h" - -#include "gui/Platform.h" -#include "gui/dialogs/CustomMessageBox.h" -#include "gui/dialogs/VersionSelectDialog.h" - -#include "gui/dialogs/ProgressDialog.h" - -#include "logic/ModList.h" -#include "logic/VersionFinal.h" -#include "logic/EnabledItemFilter.h" -#include "logic/lists/ForgeVersionList.h" -#include "logic/lists/LiteLoaderVersionList.h" -#include "logic/ForgeInstaller.h" -#include "logic/LiteLoaderInstaller.h" -#include "logic/OneSixVersionBuilder.h" - -OneSixModEditDialog::OneSixModEditDialog(OneSixInstance *inst, QWidget *parent) - : QDialog(parent), ui(new Ui::OneSixModEditDialog), m_inst(inst) -{ - MultiMCPlatform::fixWM_CLASS(this); - ui->setupUi(this); - // libraries! - - m_version = m_inst->getFullVersion(); - if (m_version) - { - main_model = new EnabledItemFilter(this); - main_model->setActive(true); - main_model->setSourceModel(m_version.get()); - ui->libraryTreeView->setModel(main_model); - ui->libraryTreeView->installEventFilter(this); - connect(ui->libraryTreeView->selectionModel(), &QItemSelectionModel::currentChanged, - this, &OneSixModEditDialog::versionCurrent); - updateVersionControls(); - } - else - { - disableVersionControls(); - } - // Loader mods - { - ensureFolderPathExists(m_inst->loaderModsDir()); - m_mods = m_inst->loaderModList(); - 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.get()); - ui->resPackTreeView->installEventFilter(this); - m_resourcepacks->startWatching(); - } - - connect(m_inst, &OneSixInstance::versionReloaded, this, - &OneSixModEditDialog::updateVersionControls); -} - -OneSixModEditDialog::~OneSixModEditDialog() -{ - m_mods->stopWatching(); - m_resourcepacks->stopWatching(); - delete ui; -} - -void OneSixModEditDialog::updateVersionControls() -{ - ui->forgeBtn->setEnabled(true); - ui->liteloaderBtn->setEnabled(true); -} - -void OneSixModEditDialog::disableVersionControls() -{ - ui->forgeBtn->setEnabled(false); - ui->liteloaderBtn->setEnabled(false); - ui->reloadLibrariesBtn->setEnabled(false); - ui->removeLibraryBtn->setEnabled(false); -} - -bool OneSixModEditDialog::reloadInstanceVersion() -{ - try - { - m_inst->reloadVersion(); - return true; - } - catch (MMCError &e) - { - QMessageBox::critical(this, tr("Error"), e.cause()); - return false; - } - catch (...) - { - QMessageBox::critical( - this, tr("Error"), - tr("Failed to load the version description file for reasons unknown.")); - return false; - } -} - -void OneSixModEditDialog::on_reloadLibrariesBtn_clicked() -{ - reloadInstanceVersion(); -} - -void OneSixModEditDialog::on_removeLibraryBtn_clicked() -{ - if (ui->libraryTreeView->currentIndex().isValid()) - { - // FIXME: use actual model, not reloading. - if (!m_version->remove(ui->libraryTreeView->currentIndex().row())) - { - QMessageBox::critical(this, tr("Error"), tr("Couldn't remove file")); - } - } -} - -void OneSixModEditDialog::on_resetLibraryOrderBtn_clicked() -{ - try - { - m_version->resetOrder(); - } - catch (MMCError &e) - { - QMessageBox::critical(this, tr("Error"), e.cause()); - } -} - -void OneSixModEditDialog::on_moveLibraryUpBtn_clicked() -{ - if (ui->libraryTreeView->selectionModel()->selectedRows().isEmpty()) - { - return; - } - try - { - const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row(); - const int newRow = 0;m_version->move(row, VersionFinal::MoveUp); - //ui->libraryTreeView->selectionModel()->setCurrentIndex(m_version->index(newRow), QItemSelectionModel::ClearAndSelect); - } - catch (MMCError &e) - { - QMessageBox::critical(this, tr("Error"), e.cause()); - } -} - -void OneSixModEditDialog::on_moveLibraryDownBtn_clicked() -{ - if (ui->libraryTreeView->selectionModel()->selectedRows().isEmpty()) - { - return; - } - try - { - const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row(); - const int newRow = 0;m_version->move(row, VersionFinal::MoveDown); - //ui->libraryTreeView->selectionModel()->setCurrentIndex(m_version->index(newRow), QItemSelectionModel::ClearAndSelect); - } - catch (MMCError &e) - { - QMessageBox::critical(this, tr("Error"), e.cause()); - } -} - -void OneSixModEditDialog::on_forgeBtn_clicked() -{ - // FIXME: use actual model, not reloading. Move logic to model. - if (m_version->hasFtbPack()) - { - if (QMessageBox::question(this, tr("Revert?"), - tr("This action will remove the FTB pack version patch. Continue?")) != - QMessageBox::Yes) - { - return; - } - m_version->removeFtbPack(); - reloadInstanceVersion(); - } - if (m_version->isCustom()) - { - if (QMessageBox::question(this, tr("Revert?"), - tr("This action will remove your custom.json. Continue?")) != - QMessageBox::Yes) - { - return; - } - m_version->revertToBase(); - reloadInstanceVersion(); - } - VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this); - vselect.setExactFilter(1, m_inst->currentVersionId()); - vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") + - m_inst->currentVersionId()); - if (vselect.exec() && vselect.selectedVersion()) - { - ProgressDialog dialog(this); - dialog.exec(ForgeInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this)); - } -} - -void OneSixModEditDialog::on_liteloaderBtn_clicked() -{ - if (m_version->hasFtbPack()) - { - if (QMessageBox::question(this, tr("Revert?"), - tr("This action will remove the FTB pack version patch. Continue?")) != - QMessageBox::Yes) - { - return; - } - m_version->removeFtbPack(); - reloadInstanceVersion(); - } - if (m_version->isCustom()) - { - if (QMessageBox::question(this, tr("Revert?"), - tr("This action will remove your custom.json. Continue?")) != - QMessageBox::Yes) - { - return; - } - m_version->revertToBase(); - reloadInstanceVersion(); - } - VersionSelectDialog vselect(MMC->liteloaderlist().get(), tr("Select LiteLoader version"), - this); - vselect.setExactFilter(1, m_inst->currentVersionId()); - vselect.setEmptyString(tr("No LiteLoader versions are currently available for Minecraft ") + - m_inst->currentVersionId()); - if (vselect.exec() && vselect.selectedVersion()) - { - ProgressDialog dialog(this); - dialog.exec(LiteLoaderInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this)); - } -} - -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); - } - QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev); - if (obj == ui->loaderModTreeView) - return loaderListFilter(keyEvent); - if (obj == ui->resPackTreeView) - return resourcePackListFilter(keyEvent); - return QDialog::eventFilter(obj, ev); -} - -void OneSixModEditDialog::on_buttonBox_rejected() -{ - close(); -} - -void OneSixModEditDialog::on_addModBtn_clicked() -{ - QStringList fileNames = QFileDialog::getOpenFileNames( - this, QApplication::translate("LegacyModEditDialog", "Select Loader Mods")); - for (auto filename : fileNames) - { - m_mods->stopWatching(); - m_mods->installMod(QFileInfo(filename)); - m_mods->startWatching(); - } -} -void OneSixModEditDialog::on_rmModBtn_clicked() -{ - int first, last; - auto list = ui->loaderModTreeView->selectionModel()->selectedRows(); - - if (!lastfirst(list, first, last)) - return; - m_mods->stopWatching(); - m_mods->deleteMods(first, last); - m_mods->startWatching(); -} -void OneSixModEditDialog::on_viewModBtn_clicked() -{ - openDirInDefaultProgram(m_inst->loaderModsDir(), true); -} - -void OneSixModEditDialog::on_addResPackBtn_clicked() -{ - QStringList fileNames = QFileDialog::getOpenFileNames( - this, QApplication::translate("LegacyModEditDialog", "Select Resource Packs")); - for (auto filename : fileNames) - { - m_resourcepacks->stopWatching(); - m_resourcepacks->installMod(QFileInfo(filename)); - m_resourcepacks->startWatching(); - } -} -void OneSixModEditDialog::on_rmResPackBtn_clicked() -{ - int first, last; - auto list = ui->resPackTreeView->selectionModel()->selectedRows(); - - if (!lastfirst(list, first, last)) - return; - m_resourcepacks->stopWatching(); - m_resourcepacks->deleteMods(first, last); - m_resourcepacks->startWatching(); -} -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); -} - -void OneSixModEditDialog::versionCurrent(const QModelIndex ¤t, - const QModelIndex &previous) -{ - if (!current.isValid()) - { - ui->removeLibraryBtn->setDisabled(true); - } - else - { - ui->removeLibraryBtn->setEnabled(m_version->canRemove(current.row())); - } -} diff --git a/gui/dialogs/OneSixModEditDialog.ui b/gui/dialogs/OneSixModEditDialog.ui deleted file mode 100644 index 2c9f70bb..00000000 --- a/gui/dialogs/OneSixModEditDialog.ui +++ /dev/null @@ -1,310 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>OneSixModEditDialog</class> - <widget class="QDialog" name="OneSixModEditDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>555</width> - <height>463</height> - </rect> - </property> - <property name="windowTitle"> - <string>Manage Mods</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QTabWidget" name="tabWidget"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="libTab"> - <attribute name="title"> - <string>Version</string> - </attribute> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <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> - <attribute name="headerVisible"> - <bool>false</bool> - </attribute> - </widget> - </item> - </layout> - </item> - <item> - <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="liteloaderBtn"> - <property name="text"> - <string>Install LiteLoader</string> - </property> - </widget> - </item> - <item> - <widget class="Line" name="line"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="reloadLibrariesBtn"> - <property name="text"> - <string>Reload</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="removeLibraryBtn"> - <property name="text"> - <string>Remove</string> - </property> - </widget> - </item> - <item> - <widget class="Line" name="line_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="moveLibraryUpBtn"> - <property name="toolTip"> - <string>This isn't implemented yet.</string> - </property> - <property name="text"> - <string>Move up</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="moveLibraryDownBtn"> - <property name="toolTip"> - <string>This isn't implemented yet.</string> - </property> - <property name="text"> - <string>Move down</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="resetLibraryOrderBtn"> - <property name="toolTip"> - <string>This isn't implemented yet.</string> - </property> - <property name="text"> - <string>Reset order</string> - </property> - </widget> - </item> - <item> - <spacer name="verticalSpacer_7"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </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> - <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"> - <attribute name="title"> - <string>Resource Packs</string> - </attribute> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="ModListView" name="resPackTreeView"> - <property name="acceptDrops"> - <bool>true</bool> - </property> - <property name="dragDropMode"> - <enum>QAbstractItemView::DropOnly</enum> - </property> - </widget> - </item> - <item> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <widget class="QPushButton" name="addResPackBtn"> - <property name="text"> - <string>&Add</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="rmResPackBtn"> - <property name="text"> - <string>&Remove</string> - </property> - </widget> - </item> - <item> - <spacer name="verticalSpacer_2"> - <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="viewResPackBtn"> - <property name="text"> - <string>&View Folder</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </widget> - </item> - <item row="1" column="0"> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="autoFillBackground"> - <bool>false</bool> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Close</set> - </property> - </widget> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>ModListView</class> - <extends>QTreeView</extends> - <header>gui/widgets/ModListView.h</header> - </customwidget> - <customwidget> - <class>MCModInfoFrame</class> - <extends>QFrame</extends> - <header>gui/widgets/MCModInfoFrame.h</header> - <container>1</container> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui> diff --git a/gui/dialogs/ScreenshotDialog.cpp b/gui/dialogs/ScreenshotDialog.cpp deleted file mode 100644 index a88c8dfd..00000000 --- a/gui/dialogs/ScreenshotDialog.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "ScreenshotDialog.h" -#include "ui_ScreenshotDialog.h" - -#include <QModelIndex> -#include <QMutableListIterator> - -#include "ProgressDialog.h" -#include "CustomMessageBox.h" -#include "logic/net/NetJob.h" -#include "logic/screenshots/ImgurUpload.h" -#include "logic/screenshots/ImgurAlbumCreation.h" -#include "logic/tasks/SequentialTask.h" - -ScreenshotDialog::ScreenshotDialog(ScreenshotList *list, QWidget *parent) - : QDialog(parent), ui(new Ui::ScreenshotDialog), m_list(list) -{ - ui->setupUi(this); - ui->listView->setModel(m_list); -} - -ScreenshotDialog::~ScreenshotDialog() -{ - delete ui; -} - -QString ScreenshotDialog::message() const -{ - return tr("<a href=\"https://imgur.com/a/%1\">Visit album</a><br/>Delete hash: %2 (save " - "this if you want to be able to edit/delete the album)") - .arg(m_imgurAlbum->id(), m_imgurAlbum->deleteHash()); -} - -QList<ScreenshotPtr> ScreenshotDialog::selected() const -{ - QList<ScreenshotPtr> list; - QList<ScreenshotPtr> first = m_list->screenshots(); - for (QModelIndex index : ui->listView->selectionModel()->selectedRows()) - { - list.append(first.at(index.row())); - } - return list; -} - -void ScreenshotDialog::on_uploadBtn_clicked() -{ - m_uploaded = selected(); - if (m_uploaded.isEmpty()) - { - done(NothingDone); - return; - } - SequentialTask *task = new SequentialTask(this); - NetJob *job = new NetJob("Screenshot Upload"); - for (auto shot : m_uploaded) - { - job->addNetAction(ImgurUpload::make(shot)); - } - NetJob *albumTask = new NetJob("Imgur Album Creation"); - albumTask->addNetAction(m_imgurAlbum = ImgurAlbumCreation::make(m_uploaded)); - task->addTask(NetJobPtr(job)); - task->addTask(NetJobPtr(albumTask)); - ProgressDialog prog(this); - if (prog.exec(task) == QDialog::Accepted) - { - accept(); - } - else - { - CustomMessageBox::selectable(this, tr("Failed to upload screenshots!"), - tr("Unknown error"), QMessageBox::Warning)->exec(); - reject(); - } -} - -void ScreenshotDialog::on_deleteBtn_clicked() -{ - m_list->deleteSelected(this); -} diff --git a/gui/dialogs/ScreenshotDialog.h b/gui/dialogs/ScreenshotDialog.h deleted file mode 100644 index 29dd6765..00000000 --- a/gui/dialogs/ScreenshotDialog.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include <QDialog> -#include "logic/screenshots/ScreenshotList.h" - -class ImgurAlbumCreation; - -namespace Ui -{ -class ScreenshotDialog; -} - -class ScreenshotDialog : public QDialog -{ - Q_OBJECT - -public: - explicit ScreenshotDialog(ScreenshotList *list, QWidget *parent = 0); - ~ScreenshotDialog(); - - enum - { - NothingDone = 0x42 - }; - - QString message() const; - QList<ScreenshotPtr> selected() const; - -private -slots: - void on_uploadBtn_clicked(); - - void on_deleteBtn_clicked(); - -private: - Ui::ScreenshotDialog *ui; - ScreenshotList *m_list; - QList<ScreenshotPtr> m_uploaded; - std::shared_ptr<ImgurAlbumCreation> m_imgurAlbum; -}; diff --git a/gui/dialogs/ScreenshotDialog.ui b/gui/dialogs/ScreenshotDialog.ui deleted file mode 100644 index eb3dafba..00000000 --- a/gui/dialogs/ScreenshotDialog.ui +++ /dev/null @@ -1,110 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>ScreenshotDialog</class> - <widget class="QDialog" name="ScreenshotDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>470</width> - <height>300</height> - </rect> - </property> - <property name="windowTitle"> - <string>Screenshot Manager</string> - </property> - <property name="windowIcon"> - <iconset resource="../../resources/multimc/multimc.qrc"> - <normaloff>:/icons/multimc/scalable/apps/multimc.svg</normaloff>:/icons/multimc/scalable/apps/multimc.svg</iconset> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QListView" name="listView"> - <property name="selectionMode"> - <enum>QAbstractItemView::ExtendedSelection</enum> - </property> - <property name="selectionBehavior"> - <enum>QAbstractItemView::SelectItems</enum> - </property> - <property name="iconSize"> - <size> - <width>120</width> - <height>90</height> - </size> - </property> - <property name="flow"> - <enum>QListView::LeftToRight</enum> - </property> - <property name="isWrapping" stdset="0"> - <bool>true</bool> - </property> - <property name="resizeMode"> - <enum>QListView::Adjust</enum> - </property> - <property name="viewMode"> - <enum>QListView::IconMode</enum> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QPushButton" name="uploadBtn"> - <property name="text"> - <string>Upload</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="deleteBtn"> - <property name="text"> - <string>Delete</string> - </property> - </widget> - </item> - <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="QPushButton" name="closeBtn"> - <property name="text"> - <string>Close</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <resources> - <include location="../../resources/multimc/multimc.qrc"/> - </resources> - <connections> - <connection> - <sender>closeBtn</sender> - <signal>clicked()</signal> - <receiver>ScreenshotDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>315</x> - <y>272</y> - </hint> - <hint type="destinationlabel"> - <x>271</x> - <y>258</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/gui/dialogs/SettingsDialog.cpp b/gui/dialogs/SettingsDialog.cpp index 4229ea91..87da0c68 100644 --- a/gui/dialogs/SettingsDialog.cpp +++ b/gui/dialogs/SettingsDialog.cpp @@ -22,10 +22,11 @@ #include "gui/dialogs/VersionSelectDialog.h" #include "gui/dialogs/CustomMessageBox.h" -#include "logic/JavaUtils.h" #include "logic/NagUtils.h" -#include "logic/lists/JavaVersionList.h" -#include <logic/JavaChecker.h> + +#include "logic/java/JavaUtils.h" +#include "logic/java/JavaVersionList.h" +#include "logic/java/JavaChecker.h" #include "logic/updater/UpdateChecker.h" @@ -37,6 +38,15 @@ #include <QMessageBox> #include <QDir> +// FIXME: possibly move elsewhere +enum InstSortMode +{ + // Sort alphabetically by name. + Sort_Name, + // Sort by which instance was launched most recently. + Sort_LastLaunch +}; + SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::SettingsDialog) { MultiMCPlatform::fixWM_CLASS(this); @@ -423,7 +433,7 @@ void SettingsDialog::loadSettings(SettingsObject *s) foreach(const QString & lang, QDir(MMC->staticData() + "/translations") .entryList(QStringList() << "*.qm", QDir::Files)) { - QLocale locale(lang.section(QRegExp("[_\.]"), 1)); + QLocale locale(lang.section(QRegExp("[_\\.]"), 1)); ui->languageBox->addItem(QLocale::languageToString(locale.language()), locale); } ui->languageBox->setCurrentIndex( diff --git a/gui/dialogs/SettingsDialog.h b/gui/dialogs/SettingsDialog.h index d8495fdd..c65e9fb5 100644 --- a/gui/dialogs/SettingsDialog.h +++ b/gui/dialogs/SettingsDialog.h @@ -18,7 +18,7 @@ #include <memory> #include <QDialog> -#include "logic/JavaChecker.h" +#include "logic/java/JavaChecker.h" class SettingsObject; diff --git a/gui/dialogs/VersionSelectDialog.cpp b/gui/dialogs/VersionSelectDialog.cpp index cae5a732..fd8b569d 100644 --- a/gui/dialogs/VersionSelectDialog.cpp +++ b/gui/dialogs/VersionSelectDialog.cpp @@ -24,7 +24,7 @@ #include "gui/Platform.h" #include <logic/BaseVersion.h> -#include <logic/lists/BaseVersionList.h> +#include <logic/BaseVersionList.h> #include <logic/tasks/Task.h> VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent, diff --git a/gui/groupview/InstanceDelegate.cpp b/gui/groupview/InstanceDelegate.cpp index cd26ddaa..64dc31d2 100644 --- a/gui/groupview/InstanceDelegate.cpp +++ b/gui/groupview/InstanceDelegate.cpp @@ -22,7 +22,7 @@ #include "GroupView.h" #include "logic/BaseInstance.h" -#include "logic/lists/InstanceList.h" +#include "logic/InstanceList.h" QCache<QString, QPixmap> ListViewDelegate::m_pixmapCache; diff --git a/gui/pagedialog/PageDialog.cpp b/gui/pagedialog/PageDialog.cpp new file mode 100644 index 00000000..07027a84 --- /dev/null +++ b/gui/pagedialog/PageDialog.cpp @@ -0,0 +1,58 @@ +/* Copyright 2014 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 "PageDialog.h" +#include "gui/Platform.h" +#include "MultiMC.h" +#include <settingsobject.h> + +#include <gui/widgets/IconLabel.h> +#include <gui/widgets/PageContainer.h> +#include <QDialogButtonBox> +#include <QPushButton> +#include <QVBoxLayout> +#include <QtGui/QKeyEvent> + +PageDialog::PageDialog(BasePageProviderPtr pageProvider, QString defaultId, QWidget *parent) : QDialog(parent) +{ + MultiMCPlatform::fixWM_CLASS(this); + setWindowTitle(pageProvider->dialogTitle()); + m_container = new PageContainer(pageProvider, defaultId, this); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(m_container); + mainLayout->setSpacing(0); + mainLayout->setContentsMargins(0,0,0,0); + setLayout(mainLayout); + + QDialogButtonBox *buttons = + new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Close); + buttons->button(QDialogButtonBox::Close)->setDefault(true); + m_container->addButtons(buttons); + + connect(buttons->button(QDialogButtonBox::Close), SIGNAL(clicked()), this, SLOT(close())); + connect(buttons->button(QDialogButtonBox::Help), SIGNAL(clicked()), m_container, SLOT(help())); + + restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("PagedGeometry").toByteArray())); +} + +void PageDialog::closeEvent(QCloseEvent * event) +{ + if(m_container->requestClose(event)) + { + MMC->settings()->set("PagedGeometry", saveGeometry().toBase64()); + QDialog::closeEvent(event); + } +} diff --git a/gui/dialogs/EditNotesDialog.h b/gui/pagedialog/PageDialog.h index b74558c4..097eac64 100644 --- a/gui/dialogs/EditNotesDialog.h +++ b/gui/pagedialog/PageDialog.h @@ -1,4 +1,4 @@ -/* Copyright 2013 MultiMC Contributors +/* Copyright 2014 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,25 +14,22 @@ */ #pragma once - #include <QDialog> +#include <gui/pages/BasePageProvider.h> -namespace Ui -{ -class EditNotesDialog; -} - -class EditNotesDialog : public QDialog +class PageContainer; +class PageDialog : public QDialog { Q_OBJECT - public: - explicit EditNotesDialog(QString notes, QString name, QWidget *parent = 0); - ~EditNotesDialog(); - QString getText(); + explicit PageDialog(BasePageProviderPtr pageProvider, QString defaultId = QString(), + QWidget *parent = 0); + virtual ~PageDialog() {}; + +private +slots: + virtual void closeEvent(QCloseEvent *event); private: - Ui::EditNotesDialog *ui; - QString m_instance_name; - QString m_instance_notes; + PageContainer * m_container; }; diff --git a/gui/pages/BasePage.h b/gui/pages/BasePage.h new file mode 100644 index 00000000..09af3a59 --- /dev/null +++ b/gui/pages/BasePage.h @@ -0,0 +1,48 @@ +/* Copyright 2014 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 <QString> +#include <QIcon> +#include <memory> + +class BasePage +{ +public: + virtual ~BasePage(){}; + virtual QString id() = 0; + virtual QString displayName() = 0; + virtual QIcon icon() = 0; + virtual bool apply() + { + return true; + } + virtual bool shouldDisplay() + { + return true; + } + virtual QString helpPage() + { + return QString(); + } + virtual void opened() + { + + } + int stackIndex = -1; + int listIndex = -1; +}; + +typedef std::shared_ptr<BasePage> BasePagePtr; diff --git a/gui/pages/BasePageProvider.h b/gui/pages/BasePageProvider.h new file mode 100644 index 00000000..cff9c8e7 --- /dev/null +++ b/gui/pages/BasePageProvider.h @@ -0,0 +1,28 @@ +/* Copyright 2014 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 "BasePage.h" +#include <memory> + +class BasePageProvider +{ +public: + virtual QList<BasePage *> getPages() = 0; + virtual QString dialogTitle() = 0; +}; + +typedef std::shared_ptr<BasePageProvider> BasePageProviderPtr; diff --git a/gui/pages/InstanceSettingsPage.cpp b/gui/pages/InstanceSettingsPage.cpp new file mode 100644 index 00000000..6e2ce238 --- /dev/null +++ b/gui/pages/InstanceSettingsPage.cpp @@ -0,0 +1,229 @@ +#include "InstanceSettingsPage.h" +#include <gui/dialogs/VersionSelectDialog.h> +#include "logic/NagUtils.h" +#include <logic/java/JavaVersionList.h> +#include "MultiMC.h" +#include <QDialog> +#include <QFileDialog> +#include <QMessageBox> +#include "ui_InstanceSettingsPage.h" + +QString InstanceSettingsPage::displayName() +{ + return tr("Settings"); +} + +QIcon InstanceSettingsPage::icon() +{ + return QIcon::fromTheme("settings"); +} + +QString InstanceSettingsPage::id() +{ + return "settings"; +} + +InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent) + : QWidget(parent), ui(new Ui::InstanceSettingsPage), m_instance(inst) +{ + m_settings = &(inst->settings()); + ui->setupUi(this); + loadSettings(); +} + +bool InstanceSettingsPage::shouldDisplay() +{ + return !m_instance->isRunning(); +} + +InstanceSettingsPage::~InstanceSettingsPage() +{ + delete ui; +} + +bool InstanceSettingsPage::apply() +{ + applySettings(); + return true; +} + +void InstanceSettingsPage::applySettings() +{ + // Console + bool console = ui->consoleSettingsBox->isChecked(); + m_settings->set("OverrideConsole", console); + if (console) + { + m_settings->set("ShowConsole", ui->showConsoleCheck->isChecked()); + m_settings->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked()); + } + else + { + m_settings->reset("ShowConsole"); + m_settings->reset("AutoCloseConsole"); + } + + // Window Size + bool window = ui->windowSizeGroupBox->isChecked(); + m_settings->set("OverrideWindow", window); + if (window) + { + m_settings->set("LaunchMaximized", ui->maximizedCheckBox->isChecked()); + m_settings->set("MinecraftWinWidth", ui->windowWidthSpinBox->value()); + m_settings->set("MinecraftWinHeight", ui->windowHeightSpinBox->value()); + } + else + { + m_settings->reset("LaunchMaximized"); + m_settings->reset("MinecraftWinWidth"); + m_settings->reset("MinecraftWinHeight"); + } + + // Memory + bool memory = ui->memoryGroupBox->isChecked(); + m_settings->set("OverrideMemory", memory); + if (memory) + { + m_settings->set("MinMemAlloc", ui->minMemSpinBox->value()); + m_settings->set("MaxMemAlloc", ui->maxMemSpinBox->value()); + m_settings->set("PermGen", ui->permGenSpinBox->value()); + } + else + { + m_settings->reset("MinMemAlloc"); + m_settings->reset("MaxMemAlloc"); + m_settings->reset("PermGen"); + } + + // Java Install Settings + bool javaInstall = ui->javaSettingsGroupBox->isChecked(); + m_settings->set("OverrideJavaLocation", javaInstall); + if (javaInstall) + { + m_settings->set("JavaPath", ui->javaPathTextBox->text()); + } + else + { + m_settings->reset("JavaPath"); + } + + // Java arguments + bool javaArgs = ui->javaArgumentsGroupBox->isChecked(); + m_settings->set("OverrideJavaArgs", javaArgs); + if(javaArgs) + { + m_settings->set("JvmArgs", ui->jvmArgsTextBox->toPlainText().replace("\n", " ")); + NagUtils::checkJVMArgs(m_settings->get("JvmArgs").toString(), this->parentWidget()); + } + else + { + m_settings->reset("JvmArgs"); + } + + // old generic 'override both' is removed. + m_settings->reset("OverrideJava"); + + // Custom Commands + bool custcmd = ui->customCommandsGroupBox->isChecked(); + m_settings->set("OverrideCommands", custcmd); + if (custcmd) + { + m_settings->set("PreLaunchCommand", ui->preLaunchCmdTextBox->text()); + m_settings->set("PostExitCommand", ui->postExitCmdTextBox->text()); + } + else + { + m_settings->reset("PreLaunchCommand"); + m_settings->reset("PostExitCommand"); + } +} + +void InstanceSettingsPage::loadSettings() +{ + // Console + ui->consoleSettingsBox->setChecked(m_settings->get("OverrideConsole").toBool()); + ui->showConsoleCheck->setChecked(m_settings->get("ShowConsole").toBool()); + ui->autoCloseConsoleCheck->setChecked(m_settings->get("AutoCloseConsole").toBool()); + + // Window Size + ui->windowSizeGroupBox->setChecked(m_settings->get("OverrideWindow").toBool()); + ui->maximizedCheckBox->setChecked(m_settings->get("LaunchMaximized").toBool()); + ui->windowWidthSpinBox->setValue(m_settings->get("MinecraftWinWidth").toInt()); + ui->windowHeightSpinBox->setValue(m_settings->get("MinecraftWinHeight").toInt()); + + // Memory + ui->memoryGroupBox->setChecked(m_settings->get("OverrideMemory").toBool()); + ui->minMemSpinBox->setValue(m_settings->get("MinMemAlloc").toInt()); + ui->maxMemSpinBox->setValue(m_settings->get("MaxMemAlloc").toInt()); + ui->permGenSpinBox->setValue(m_settings->get("PermGen").toInt()); + + // Java Settings + bool overrideJava = m_settings->get("OverrideJava").toBool(); + bool overrideLocation = m_settings->get("OverrideJavaLocation").toBool() || overrideJava; + bool overrideArgs = m_settings->get("OverrideJavaArgs").toBool() || overrideJava; + + ui->javaSettingsGroupBox->setChecked(overrideLocation); + ui->javaPathTextBox->setText(m_settings->get("JavaPath").toString()); + + ui->javaArgumentsGroupBox->setChecked(overrideArgs); + ui->jvmArgsTextBox->setPlainText(m_settings->get("JvmArgs").toString()); + + // Custom Commands + ui->customCommandsGroupBox->setChecked(m_settings->get("OverrideCommands").toBool()); + ui->preLaunchCmdTextBox->setText(m_settings->get("PreLaunchCommand").toString()); + ui->postExitCmdTextBox->setText(m_settings->get("PostExitCommand").toString()); +} + +void InstanceSettingsPage::on_javaDetectBtn_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 InstanceSettingsPage::on_javaBrowseBtn_clicked() +{ + QString dir = QFileDialog::getOpenFileName(this, tr("Find Java executable")); + if (!dir.isNull()) + { + ui->javaPathTextBox->setText(dir); + } +} + +void InstanceSettingsPage::on_javaTestBtn_clicked() +{ + checker.reset(new JavaChecker()); + connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this, + SLOT(checkFinished(JavaCheckResult))); + checker->path = ui->javaPathTextBox->text(); + checker->performCheck(); +} + +void InstanceSettingsPage::checkFinished(JavaCheckResult result) +{ + if (result.valid) + { + QString text; + text += "Java test succeeded!\n"; + if (result.is_64bit) + text += "Using 64bit java.\n"; + text += "\n"; + text += "Platform reported: " + result.realPlatform; + QMessageBox::information(this, tr("Java test success"), text); + } + else + { + QMessageBox::warning( + this, tr("Java test failure"), + tr("The specified java binary didn't work. You should use the auto-detect feature, " + "or set the path to the java executable.")); + } +} diff --git a/gui/dialogs/InstanceSettings.h b/gui/pages/InstanceSettingsPage.h index e296db4c..2447168f 100644 --- a/gui/dialogs/InstanceSettings.h +++ b/gui/pages/InstanceSettingsPage.h @@ -1,4 +1,4 @@ -/* Copyright 2013 MultiMC Contributors +/* Copyright 2014 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,38 +14,33 @@ */ #pragma once +#include <QWidget> -#include <QDialog> -#include "settingsobject.h" -#include "logic/JavaChecker.h" +#include <logic/OneSixInstance.h> +#include <logic/net/NetJob.h> +#include <logic/java/JavaChecker.h> +#include "BasePage.h" +class JavaChecker; namespace Ui { -class InstanceSettings; +class InstanceSettingsPage; } -class InstanceSettings : public QDialog +class InstanceSettingsPage : public QWidget, public BasePage { Q_OBJECT public: - explicit InstanceSettings(SettingsObject *s, QWidget *parent = 0); - ~InstanceSettings(); - - void updateCheckboxStuff(); - - void applySettings(); - void loadSettings(); - -protected: - virtual void showEvent(QShowEvent *); - virtual void closeEvent(QCloseEvent *); -private -slots: - void on_customCommandsGroupBox_toggled(bool arg1); - void on_buttonBox_accepted(); - void on_buttonBox_rejected(); - + explicit InstanceSettingsPage(BaseInstance *inst, QWidget *parent = 0); + virtual ~InstanceSettingsPage(); + virtual QString displayName() override; + virtual QIcon icon() override; + virtual QString id() override; + virtual bool apply(); + virtual QString helpPage() override { return "Instance-settings"; } + virtual bool shouldDisplay(); +private slots: void on_javaDetectBtn_clicked(); void on_javaTestBtn_clicked(); @@ -53,8 +48,12 @@ slots: void on_javaBrowseBtn_clicked(); void checkFinished(JavaCheckResult result); + + void applySettings(); + void loadSettings(); private: - Ui::InstanceSettings *ui; - SettingsObject *m_obj; + Ui::InstanceSettingsPage *ui; + BaseInstance *m_instance; + SettingsObject *m_settings; std::shared_ptr<JavaChecker> checker; }; diff --git a/gui/dialogs/InstanceSettings.ui b/gui/pages/InstanceSettingsPage.ui index 9c7e1757..b8af6c60 100644 --- a/gui/dialogs/InstanceSettings.ui +++ b/gui/pages/InstanceSettingsPage.ui @@ -1,19 +1,31 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>InstanceSettings</class> - <widget class="QDialog" name="InstanceSettings"> + <class>InstanceSettingsPage</class> + <widget class="QWidget" name="InstanceSettingsPage"> <property name="geometry"> <rect> <x>0</x> <y>0</y> - <width>526</width> - <height>637</height> + <width>458</width> + <height>426</height> </rect> </property> <property name="windowTitle"> - <string>Instance Settings</string> + <string>Form</string> </property> <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> <item> <widget class="QTabWidget" name="settingsTabs"> <property name="tabShape"> @@ -24,16 +36,16 @@ </property> <widget class="QWidget" name="minecraftTab"> <attribute name="title"> - <string>Minecraft</string> + <string>Java</string> </attribute> - <layout class="QVBoxLayout" name="verticalLayout_3"> + <layout class="QVBoxLayout" name="verticalLayout_5"> <item> - <widget class="QGroupBox" name="windowSizeGroupBox"> + <widget class="QGroupBox" name="javaSettingsGroupBox"> <property name="enabled"> <bool>true</bool> </property> <property name="title"> - <string>Window Size</string> + <string>Java installation</string> </property> <property name="checkable"> <bool>true</bool> @@ -41,90 +53,28 @@ <property name="checked"> <bool>false</bool> </property> - <layout class="QVBoxLayout" name="verticalLayout_4"> - <item> - <widget class="QCheckBox" name="maximizedCheckBox"> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" colspan="3"> + <widget class="QLineEdit" name="javaPathTextBox"/> + </item> + <item row="1" column="0"> + <widget class="QPushButton" name="javaDetectBtn"> <property name="text"> - <string>Start Minecraft maximized?</string> + <string>Auto-detect...</string> </property> </widget> </item> - <item> - <layout class="QGridLayout" name="gridLayoutWindowSize"> - <item row="1" column="0"> - <widget class="QLabel" name="labelWindowHeight"> - <property name="text"> - <string>Window height:</string> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="labelWindowWidth"> - <property name="text"> - <string>Window width:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QSpinBox" name="windowWidthSpinBox"> - <property name="minimum"> - <number>854</number> - </property> - <property name="maximum"> - <number>65536</number> - </property> - <property name="singleStep"> - <number>1</number> - </property> - <property name="value"> - <number>854</number> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QSpinBox" name="windowHeightSpinBox"> - <property name="minimum"> - <number>480</number> - </property> - <property name="maximum"> - <number>65536</number> - </property> - <property name="value"> - <number>480</number> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="consoleSettingsBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="title"> - <string>Console Settings</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QCheckBox" name="showConsoleCheck"> + <item row="1" column="1"> + <widget class="QPushButton" name="javaBrowseBtn"> <property name="text"> - <string>Show console while the game is running?</string> + <string>Browse...</string> </property> </widget> </item> - <item> - <widget class="QCheckBox" name="autoCloseConsoleCheck"> + <item row="1" column="2"> + <widget class="QPushButton" name="javaTestBtn"> <property name="text"> - <string>Automatically close console when the game quits?</string> + <string>Test</string> </property> </widget> </item> @@ -132,26 +82,6 @@ </widget> </item> <item> - <spacer name="verticalSpacerMinecraft"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - <widget class="QWidget" name="javaTab"> - <attribute name="title"> - <string>Java</string> - </attribute> - <layout class="QVBoxLayout" name="verticalLayout_5"> - <item> <widget class="QGroupBox" name="memoryGroupBox"> <property name="enabled"> <bool>true</bool> @@ -257,12 +187,12 @@ </widget> </item> <item> - <widget class="QGroupBox" name="javaSettingsGroupBox"> + <widget class="QGroupBox" name="javaArgumentsGroupBox"> <property name="enabled"> <bool>true</bool> </property> <property name="title"> - <string>Java Settings</string> + <string>Java arguments</string> </property> <property name="checkable"> <bool>true</bool> @@ -270,45 +200,131 @@ <property name="checked"> <bool>false</bool> </property> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="2" column="4"> - <widget class="QPushButton" name="javaTestBtn"> - <property name="text"> - <string>Test</string> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="labelJavaPath"> - <property name="text"> - <string>Java path:</string> - </property> - </widget> + <layout class="QGridLayout" name="gridLayout_5"> + <item row="1" column="1"> + <widget class="QPlainTextEdit" name="jvmArgsTextBox"/> </item> - <item row="3" column="0"> - <widget class="QLabel" name="labelJVMArgs"> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacerMinecraft"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <widget class="QWidget" name="javaTab"> + <attribute name="title"> + <string>Game windows</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QGroupBox" name="windowSizeGroupBox"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="title"> + <string>Game Window</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QCheckBox" name="maximizedCheckBox"> <property name="text"> - <string>JVM arguments:</string> + <string>Start Minecraft maximized?</string> </property> </widget> </item> - <item row="3" column="2" colspan="3"> - <widget class="QLineEdit" name="jvmArgsTextBox"/> - </item> - <item row="0" column="2" colspan="3"> - <widget class="QLineEdit" name="javaPathTextBox"/> + <item> + <layout class="QGridLayout" name="gridLayoutWindowSize"> + <item row="1" column="0"> + <widget class="QLabel" name="labelWindowHeight"> + <property name="text"> + <string>Window height:</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="labelWindowWidth"> + <property name="text"> + <string>Window width:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QSpinBox" name="windowWidthSpinBox"> + <property name="minimum"> + <number>854</number> + </property> + <property name="maximum"> + <number>65536</number> + </property> + <property name="singleStep"> + <number>1</number> + </property> + <property name="value"> + <number>854</number> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="windowHeightSpinBox"> + <property name="minimum"> + <number>480</number> + </property> + <property name="maximum"> + <number>65536</number> + </property> + <property name="value"> + <number>480</number> + </property> + </widget> + </item> + </layout> </item> - <item row="2" column="3"> - <widget class="QPushButton" name="javaBrowseBtn"> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="consoleSettingsBox"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="title"> + <string>Console Settings</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QCheckBox" name="showConsoleCheck"> <property name="text"> - <string>Browse...</string> + <string>Show console while the game is running?</string> </property> </widget> </item> - <item row="2" column="2"> - <widget class="QPushButton" name="javaDetectBtn"> + <item> + <widget class="QCheckBox" name="autoCloseConsoleCheck"> <property name="text"> - <string>Auto-detect...</string> + <string>Automatically close console when the game quits?</string> </property> </widget> </item> @@ -316,6 +332,26 @@ </widget> </item> <item> + <spacer name="verticalSpacerMinecraft_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>88</width> + <height>125</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab"> + <attribute name="title"> + <string>Custom commands</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_6"> + <item> <widget class="QGroupBox" name="customCommandsGroupBox"> <property name="enabled"> <bool>true</bool> @@ -358,12 +394,6 @@ <property name="enabled"> <bool>false</bool> </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> <property name="text"> <string>Pre-launch command runs before the instance launches and post-exit command runs after it exits. Both will be run in MultiMC's working directory with INST_ID, INST_DIR, and INST_NAME as environment variables.</string> </property> @@ -378,42 +408,25 @@ </property> </widget> </item> + <item> + <spacer name="verticalSpacerMinecraft_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>88</width> + <height>186</height> + </size> + </property> + </spacer> + </item> </layout> </widget> </widget> </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> </layout> </widget> - <tabstops> - <tabstop>settingsTabs</tabstop> - <tabstop>buttonBox</tabstop> - <tabstop>windowSizeGroupBox</tabstop> - <tabstop>maximizedCheckBox</tabstop> - <tabstop>windowWidthSpinBox</tabstop> - <tabstop>windowHeightSpinBox</tabstop> - <tabstop>consoleSettingsBox</tabstop> - <tabstop>showConsoleCheck</tabstop> - <tabstop>autoCloseConsoleCheck</tabstop> - <tabstop>memoryGroupBox</tabstop> - <tabstop>minMemSpinBox</tabstop> - <tabstop>maxMemSpinBox</tabstop> - <tabstop>permGenSpinBox</tabstop> - <tabstop>javaSettingsGroupBox</tabstop> - <tabstop>jvmArgsTextBox</tabstop> - <tabstop>customCommandsGroupBox</tabstop> - <tabstop>preLaunchCmdTextBox</tabstop> - <tabstop>postExitCmdTextBox</tabstop> - </tabstops> <resources/> <connections/> </ui> diff --git a/gui/pages/LegacyJarModPage.cpp b/gui/pages/LegacyJarModPage.cpp new file mode 100644 index 00000000..b1c0d49a --- /dev/null +++ b/gui/pages/LegacyJarModPage.cpp @@ -0,0 +1,208 @@ +/* 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 "LegacyJarModPage.h" +#include "ui_LegacyJarModPage.h" +#include "gui/dialogs/VersionSelectDialog.h" +#include "gui/dialogs/ProgressDialog.h" +#include "gui/dialogs/ModEditDialogCommon.h" +#include "logic/ModList.h" +#include "logic/LegacyInstance.h" +#include "logic/forge/ForgeVersion.h" +#include "logic/forge/ForgeVersionList.h" +#include "MultiMC.h" +#include <pathutils.h> +#include <QtGui/QKeyEvent> +#include <QFileDialog> +#include <QKeyEvent> + +LegacyJarModPage::LegacyJarModPage(LegacyInstance *inst, QWidget *parent) + : QWidget(parent), ui(new Ui::LegacyJarModPage), m_inst(inst) +{ + ui->setupUi(this); + m_jarmods = m_inst->jarModList(); + ui->jarModsTreeView->setModel(m_jarmods.get()); + ui->jarModsTreeView->setDragDropMode(QAbstractItemView::DragDrop); + ui->jarModsTreeView->setSelectionMode(QAbstractItemView::SingleSelection); + ui->jarModsTreeView->installEventFilter(this); + m_jarmods->startWatching(); + auto smodel = ui->jarModsTreeView->selectionModel(); + connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), + SLOT(jarCurrent(QModelIndex, QModelIndex))); +} + +LegacyJarModPage::~LegacyJarModPage() +{ + m_jarmods->stopWatching(); + delete ui; +} + +QString LegacyJarModPage::displayName() +{ + return tr("Jar Mods"); +} + +bool LegacyJarModPage::shouldDisplay() +{ + return !m_inst->isRunning(); +} + +QIcon LegacyJarModPage::icon() +{ + return QIcon::fromTheme("plugin-red"); +} + +QString LegacyJarModPage::id() +{ + return "jarmods"; +} + +bool LegacyJarModPage::eventFilter(QObject *obj, QEvent *ev) +{ + if (ev->type() != QEvent::KeyPress || obj != ui->jarModsTreeView) + { + return QWidget::eventFilter(obj, ev); + } + + QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev); + switch (keyEvent->key()) + { + case Qt::Key_Up: + { + if (keyEvent->modifiers() & Qt::ControlModifier) + { + on_moveJarUpBtn_clicked(); + return true; + } + break; + } + case Qt::Key_Down: + { + 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(); + return true; + default: + break; + } + return QWidget::eventFilter(obj, ev); +} + +void LegacyJarModPage::on_addForgeBtn_clicked() +{ + VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this); + vselect.setExactFilter(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) + { + NetJob *fjob = new NetJob("Forge download"); + fjob->addNetAction(CacheDownload::make(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 LegacyJarModPage::on_addJarBtn_clicked() +{ + //: 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)); + m_jarmods->startWatching(); + } +} + +void LegacyJarModPage::on_moveJarDownBtn_clicked() +{ + int first, last; + auto list = ui->jarModsTreeView->selectionModel()->selectedRows(); + + if (!lastfirst(list, first, last)) + return; + + m_jarmods->moveModsDown(first, last); +} + +void LegacyJarModPage::on_moveJarUpBtn_clicked() +{ + int first, last; + auto list = ui->jarModsTreeView->selectionModel()->selectedRows(); + + if (!lastfirst(list, first, last)) + return; + m_jarmods->moveModsUp(first, last); +} + +void LegacyJarModPage::on_rmJarBtn_clicked() +{ + int first, last; + auto list = ui->jarModsTreeView->selectionModel()->selectedRows(); + + if (!lastfirst(list, first, last)) + return; + m_jarmods->stopWatching(); + m_jarmods->deleteMods(first, last); + m_jarmods->startWatching(); +} + +void LegacyJarModPage::on_viewJarBtn_clicked() +{ + openDirInDefaultProgram(m_inst->jarModsDir(), true); +} + +void LegacyJarModPage::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); +} diff --git a/gui/pages/LegacyJarModPage.h b/gui/pages/LegacyJarModPage.h new file mode 100644 index 00000000..016f4a8f --- /dev/null +++ b/gui/pages/LegacyJarModPage.h @@ -0,0 +1,63 @@ +/* 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 <QDialog> +#include <logic/net/NetJob.h> +#include "BasePage.h" + +class ModList; +class LegacyInstance; +namespace Ui +{ +class LegacyJarModPage; +} + +class LegacyJarModPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit LegacyJarModPage(LegacyInstance *inst, QWidget *parent = 0); + virtual ~LegacyJarModPage(); + + virtual QString displayName(); + virtual QIcon icon(); + virtual QString id(); + virtual QString helpPage() override { return "Legacy-jar-mods"; }; + virtual bool shouldDisplay(); + +private +slots: + + void on_addJarBtn_clicked(); + void on_rmJarBtn_clicked(); + void on_addForgeBtn_clicked(); + void on_moveJarUpBtn_clicked(); + void on_moveJarDownBtn_clicked(); + void on_viewJarBtn_clicked(); + + void jarCurrent(QModelIndex current, QModelIndex previous); + +protected: + virtual bool eventFilter(QObject *obj, QEvent *ev) override; + +private: + Ui::LegacyJarModPage *ui; + std::shared_ptr<ModList> m_jarmods; + LegacyInstance *m_inst; + NetJobPtr forgeJob; +}; diff --git a/gui/pages/LegacyJarModPage.ui b/gui/pages/LegacyJarModPage.ui new file mode 100644 index 00000000..a1da2b20 --- /dev/null +++ b/gui/pages/LegacyJarModPage.ui @@ -0,0 +1,158 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>LegacyJarModPage</class> + <widget class="QWidget" name="LegacyJarModPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>378</width> + <height>324</height> + </rect> + </property> + <property name="windowTitle"> + <string>LegacyJarModPage</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <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> + <item> + <layout class="QVBoxLayout" name="jarModsButtonBox"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Selection</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="rmJarBtn"> + <property name="text"> + <string>&Remove</string> + </property> + </widget> + </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> + <item> + <widget class="LineSeparator" name="separator" native="true"/> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Install</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="addJarBtn"> + <property name="text"> + <string>&Add jar mod</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="addForgeBtn"> + <property name="text"> + <string>Install Forge</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="viewJarBtn"> + <property name="text"> + <string>&View Folder</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <widget class="MCModInfoFrame" name="jarMIFrame"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>ModListView</class> + <extends>QTreeView</extends> + <header>gui/widgets/ModListView.h</header> + </customwidget> + <customwidget> + <class>MCModInfoFrame</class> + <extends>QFrame</extends> + <header>gui/widgets/MCModInfoFrame.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>LineSeparator</class> + <extends>QWidget</extends> + <header>gui/widgets/LineSeparator.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/gui/pages/LegacyUpgradePage.cpp b/gui/pages/LegacyUpgradePage.cpp new file mode 100644 index 00000000..bb54210c --- /dev/null +++ b/gui/pages/LegacyUpgradePage.cpp @@ -0,0 +1,39 @@ +#include "LegacyUpgradePage.h" +#include <logic/LegacyInstance.h> +#include "ui_LegacyUpgradePage.h" + +QString LegacyUpgradePage::displayName() +{ + return tr("Upgrade"); +} + +QIcon LegacyUpgradePage::icon() +{ + return QIcon::fromTheme("checkupdate"); +} + +QString LegacyUpgradePage::id() +{ + return "upgrade"; +} + +LegacyUpgradePage::LegacyUpgradePage(LegacyInstance *inst, QWidget *parent) + : QWidget(parent), ui(new Ui::LegacyUpgradePage), m_inst(inst) +{ + ui->setupUi(this); +} + +LegacyUpgradePage::~LegacyUpgradePage() +{ + delete ui; +} + +void LegacyUpgradePage::on_upgradeButton_clicked() +{ + // now what? +} + +bool LegacyUpgradePage::shouldDisplay() +{ + return !m_inst->isRunning(); +}
\ No newline at end of file diff --git a/gui/pages/LegacyUpgradePage.h b/gui/pages/LegacyUpgradePage.h new file mode 100644 index 00000000..eb816a7a --- /dev/null +++ b/gui/pages/LegacyUpgradePage.h @@ -0,0 +1,48 @@ +/* Copyright 2014 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include <QWidget> + +#include <logic/OneSixInstance.h> +#include <logic/net/NetJob.h> +#include "BasePage.h" + +class EnabledItemFilter; +namespace Ui +{ +class LegacyUpgradePage; +} + +class LegacyUpgradePage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit LegacyUpgradePage(LegacyInstance *inst, QWidget *parent = 0); + virtual ~LegacyUpgradePage(); + virtual QString displayName() override; + virtual QIcon icon() override; + virtual QString id() override; + virtual QString helpPage() override { return "Legacy-upgrade"; }; + virtual bool shouldDisplay(); +private +slots: + void on_upgradeButton_clicked(); + +private: + Ui::LegacyUpgradePage *ui; + LegacyInstance *m_inst; +}; diff --git a/gui/pages/LegacyUpgradePage.ui b/gui/pages/LegacyUpgradePage.ui new file mode 100644 index 00000000..8d676eae --- /dev/null +++ b/gui/pages/LegacyUpgradePage.ui @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>LegacyUpgradePage</class> + <widget class="QWidget" name="LegacyUpgradePage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>546</width> + <height>405</height> + </rect> + </property> + <property name="windowTitle"> + <string>Upgrade</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QTextBrowser" name="textBrowser"> + <property name="html"> + <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:'Bitstream Vera Sans'; 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;"> </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:18pt; font-weight:600;">New format is available</span> </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">MultiMC now supports old Minecraft versions in the new (OneSix) instance format. The old format won't be getting any new features and only the most critical bugfixes. As a consequence, you should upgrade this instance. </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The upgrade will create a new instance with the same contents as the current one, in the new format. The original instance will remain untouched, in case anything goes wrong in the process. </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Please report any issues on our <a href="https://github.com/MultiMC/MultiMC5/issues"><img src=":/icons/multimc/22x22/bug.png" /></a><a href="https://github.com/MultiMC/MultiMC5/issues"><span style=" text-decoration: underline; color:#68a0df;">github issues page</span></a>.</p></body></html></string> + </property> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCommandLinkButton" name="upgradeButton"> + <property name="text"> + <string>Start the upgrade! (Not Yet Implemented, Coming Soonâ„¢)</string> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/gui/pages/LogPage.cpp b/gui/pages/LogPage.cpp new file mode 100644 index 00000000..dd088862 --- /dev/null +++ b/gui/pages/LogPage.cpp @@ -0,0 +1,137 @@ +#include "LogPage.h" +#include <gui/dialogs/CustomMessageBox.h> +#include <gui/dialogs/ProgressDialog.h> +#include <logic/MinecraftProcess.h> +#include <QtGui/QIcon> +#include "ui_LogPage.h" +#include "logic/net/PasteUpload.h" +#include <QScrollBar> + +QString LogPage::displayName() +{ + return tr("Minecraft Log"); +} + +QIcon LogPage::icon() +{ + return QIcon::fromTheme("refresh"); +} + +QString LogPage::id() +{ + return "console"; +} + +LogPage::LogPage(MinecraftProcess *proc, QWidget *parent) + : QWidget(parent), ui(new Ui::LogPage), m_process(proc) +{ + ui->setupUi(this); + connect(m_process, SIGNAL(log(QString, MessageLevel::Enum)), this, + SLOT(write(QString, MessageLevel::Enum))); +} + +LogPage::~LogPage() +{ + delete ui; +} + +bool LogPage::apply() +{ + return true; +} + +bool LogPage::shouldDisplay() +{ + return m_process->instance()->isRunning(); +} + +void LogPage::on_btnPaste_clicked() +{ + auto text = ui->text->toPlainText(); + ProgressDialog dialog(this); + PasteUpload *paste = new PasteUpload(this, text); + dialog.exec(paste); + if (!paste->successful()) + { + CustomMessageBox::selectable(this, "Upload failed", paste->failReason(), + QMessageBox::Critical)->exec(); + } +} + +void LogPage::writeColor(QString text, const char *color, const char * background) +{ + // append a paragraph + QString newtext; + newtext += "<span style=\""; + { + if (color) + newtext += QString("color:") + color + ";"; + if (background) + newtext += QString("background-color:") + background + ";"; + newtext += "font-family: monospace;"; + } + newtext += "\">"; + newtext += text.toHtmlEscaped(); + newtext += "</span>"; + ui->text->appendHtml(newtext); +} + +void LogPage::write(QString data, MessageLevel::Enum mode) +{ + QScrollBar *bar = ui->text->verticalScrollBar(); + int max_bar = bar->maximum(); + int val_bar = bar->value(); + if(isVisible()) + { + if (m_scroll_active) + { + m_scroll_active = (max_bar - val_bar) <= 1; + } + else + { + m_scroll_active = val_bar == max_bar; + } + } + if (data.endsWith('\n')) + data = data.left(data.length() - 1); + QStringList paragraphs = data.split('\n'); + QStringList filtered; + for (QString ¶graph : paragraphs) + { + // Quick hack for + if(paragraph.contains("Detected an attempt by a mod null to perform game activity during mod construction")) + continue; + filtered.append(paragraph.trimmed()); + } + QListIterator<QString> iter(filtered); + if (mode == MessageLevel::MultiMC) + while (iter.hasNext()) + writeColor(iter.next(), "blue", 0); + else if (mode == MessageLevel::Error) + while (iter.hasNext()) + writeColor(iter.next(), "red", 0); + else if (mode == MessageLevel::Warning) + while (iter.hasNext()) + writeColor(iter.next(), "orange", 0); + else if (mode == MessageLevel::Fatal) + while (iter.hasNext()) + writeColor(iter.next(), "red", "black"); + else if (mode == MessageLevel::Debug) + while (iter.hasNext()) + writeColor(iter.next(), "green", 0); + else if (mode == MessageLevel::PrePost) + while (iter.hasNext()) + writeColor(iter.next(), "grey", 0); + // TODO: implement other MessageLevels + else + while (iter.hasNext()) + writeColor(iter.next(), 0, 0); + if(isVisible()) + { + if (m_scroll_active) + { + bar->setValue(bar->maximum()); + } + m_last_scroll_value = bar->value(); + } +} diff --git a/gui/pages/LogPage.h b/gui/pages/LogPage.h new file mode 100644 index 00000000..7cdea2c1 --- /dev/null +++ b/gui/pages/LogPage.h @@ -0,0 +1,72 @@ +/* Copyright 2014 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#pragma once +#include <QWidget> + +#include <logic/BaseInstance.h> +#include <logic/net/NetJob.h> +#include <logic/MinecraftProcess.h> +#include "BasePage.h" + +class EnabledItemFilter; +class MinecraftProcess; +namespace Ui +{ +class LogPage; +} + +class LogPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit LogPage(MinecraftProcess *proc, QWidget *parent = 0); + virtual ~LogPage(); + virtual QString displayName() override; + virtual QIcon icon() override; + virtual QString id() override; + virtual bool apply(); + virtual QString helpPage() override { return "Minecraft-Log"; }; + virtual bool shouldDisplay(); + +private: + /** + * @brief write a colored paragraph + * @param data the string + * @param color the css color name + * this will only insert a single paragraph. + * \n are ignored. a real \n is always appended. + */ + void writeColor(QString text, const char *color, const char *background); + +private slots: + /** + * @brief write a string + * @param data the string + * @param mode the WriteMode + * lines have to be put through this as a whole! + */ + void write(QString data, MessageLevel::Enum level = MessageLevel::MultiMC); + void on_btnPaste_clicked(); + +private: + Ui::LogPage *ui; + MinecraftProcess *m_process; + int m_last_scroll_value = 0; + bool m_scroll_active = true; + int m_saved_offset = 0; +}; diff --git a/gui/pages/LogPage.ui b/gui/pages/LogPage.ui new file mode 100644 index 00000000..00b611b5 --- /dev/null +++ b/gui/pages/LogPage.ui @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>LogPage</class> + <widget class="QWidget" name="LogPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>831</width> + <height>596</height> + </rect> + </property> + <property name="windowTitle"> + <string>Log</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QPlainTextEdit" name="text"> + <property name="undoRedoEnabled"> + <bool>false</bool> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="plainText"> + <string notr="true"/> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + <property name="centerOnScroll"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QPushButton" name="btnPaste"> + <property name="text"> + <string>Upload Log</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> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/gui/pages/ModFolderPage.cpp b/gui/pages/ModFolderPage.cpp new file mode 100644 index 00000000..2035e57a --- /dev/null +++ b/gui/pages/ModFolderPage.cpp @@ -0,0 +1,149 @@ +/* Copyright 2014 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 "MultiMC.h" + +#include <pathutils.h> +#include <QFileDialog> +#include <QMessageBox> +#include <QDebug> +#include <QEvent> +#include <QKeyEvent> +#include <QDesktopServices> +#include <QAbstractItemModel> + +#include "ModFolderPage.h" +#include "ui_ModFolderPage.h" + +#include "gui/dialogs/CustomMessageBox.h" +#include "gui/dialogs/ModEditDialogCommon.h" + +#include "logic/ModList.h" +#include "logic/Mod.h" + +QString ModFolderPage::displayName() +{ + return m_displayName; +} + +QIcon ModFolderPage::icon() +{ + return QIcon::fromTheme(m_iconName); +} + +QString ModFolderPage::id() +{ + return m_id; +} + +ModFolderPage::ModFolderPage(BaseInstance * inst, std::shared_ptr<ModList> mods, QString id, QString iconName, + QString displayName, QString helpPage, QWidget *parent) + : QWidget(parent), ui(new Ui::ModFolderPage) +{ + ui->setupUi(this); + m_inst = inst; + m_mods = mods; + m_id = id; + m_displayName = displayName; + m_iconName = iconName; + m_helpName = helpPage; + ui->modTreeView->setModel(m_mods.get()); + ui->modTreeView->installEventFilter(this); + m_mods->startWatching(); + auto smodel = ui->modTreeView->selectionModel(); + connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), + SLOT(modCurrent(QModelIndex, QModelIndex))); +} + +ModFolderPage::~ModFolderPage() +{ + m_mods->stopWatching(); + delete ui; +} + +bool ModFolderPage::shouldDisplay() +{ + if(m_inst) + return !m_inst->isRunning(); + return true; +} + +bool ModFolderPage::modListFilter(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 QWidget::eventFilter(ui->modTreeView, keyEvent); +} + +bool ModFolderPage::eventFilter(QObject *obj, QEvent *ev) +{ + if (ev->type() != QEvent::KeyPress) + { + return QWidget::eventFilter(obj, ev); + } + QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev); + if (obj == ui->modTreeView) + return modListFilter(keyEvent); + return QWidget::eventFilter(obj, ev); +} + +void ModFolderPage::on_addModBtn_clicked() +{ + QStringList fileNames = QFileDialog::getOpenFileNames( + this, QApplication::translate("ModFolderPage", "Select Loader Mods")); + for (auto filename : fileNames) + { + m_mods->stopWatching(); + m_mods->installMod(QFileInfo(filename)); + m_mods->startWatching(); + } +} +void ModFolderPage::on_rmModBtn_clicked() +{ + int first, last; + auto list = ui->modTreeView->selectionModel()->selectedRows(); + + if (!lastfirst(list, first, last)) + return; + m_mods->stopWatching(); + m_mods->deleteMods(first, last); + m_mods->startWatching(); +} + +void ModFolderPage::on_viewModBtn_clicked() +{ + openDirInDefaultProgram(m_mods->dir().absolutePath(), true); +} + +void ModFolderPage::modCurrent(const QModelIndex ¤t, const 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/pages/ModFolderPage.h b/gui/pages/ModFolderPage.h new file mode 100644 index 00000000..c193f4c1 --- /dev/null +++ b/gui/pages/ModFolderPage.h @@ -0,0 +1,63 @@ +/* Copyright 2014 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include <QWidget> + +#include <logic/OneSixInstance.h> +#include <logic/net/NetJob.h> +#include "BasePage.h" + +class EnabledItemFilter; +class ModList; +namespace Ui +{ +class ModFolderPage; +} + +class ModFolderPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit ModFolderPage(BaseInstance * inst, std::shared_ptr<ModList> mods, QString id, QString iconName, + QString displayName, QString helpPage = "" , QWidget *parent = 0); + virtual ~ModFolderPage(); + virtual QString displayName() override; + virtual QIcon icon() override; + virtual QString id() override; + virtual QString helpPage() override { return m_helpName; }; + virtual bool shouldDisplay(); +protected: + bool eventFilter(QObject *obj, QEvent *ev); + bool modListFilter(QKeyEvent *ev); +protected: + BaseInstance * m_inst; +private: + Ui::ModFolderPage *ui; + std::shared_ptr<ModList> m_mods; + QString m_iconName; + QString m_id; + QString m_displayName; + QString m_helpName; + +public slots: + void modCurrent(const QModelIndex ¤t, const QModelIndex &previous); + +private slots: + void on_addModBtn_clicked(); + void on_rmModBtn_clicked(); + void on_viewModBtn_clicked(); +}; diff --git a/gui/pages/ModFolderPage.ui b/gui/pages/ModFolderPage.ui new file mode 100644 index 00000000..eb29a2c0 --- /dev/null +++ b/gui/pages/ModFolderPage.ui @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ModFolderPage</class> + <widget class="QWidget" name="ModFolderPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>723</width> + <height>532</height> + </rect> + </property> + <property name="windowTitle"> + <string>Mods</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="ModListView" name="modTreeView"> + <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> + <customwidgets> + <customwidget> + <class>ModListView</class> + <extends>QTreeView</extends> + <header>gui/widgets/ModListView.h</header> + </customwidget> + <customwidget> + <class>MCModInfoFrame</class> + <extends>QFrame</extends> + <header>gui/widgets/MCModInfoFrame.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/gui/pages/NotesPage.cpp b/gui/pages/NotesPage.cpp new file mode 100644 index 00000000..b4746a77 --- /dev/null +++ b/gui/pages/NotesPage.cpp @@ -0,0 +1,35 @@ +#include "NotesPage.h" +#include "ui_NotesPage.h" + +QString NotesPage::displayName() +{ + return tr("Notes"); +} + +QIcon NotesPage::icon() +{ + return QIcon::fromTheme("news"); +} + +QString NotesPage::id() +{ + return "notes"; +} + +NotesPage::NotesPage(BaseInstance *inst, QWidget *parent) + : QWidget(parent), ui(new Ui::NotesPage), m_inst(inst) +{ + ui->setupUi(this); + ui->noteEditor->setText(m_inst->notes()); +} + +NotesPage::~NotesPage() +{ + delete ui; +} + +bool NotesPage::apply() +{ + m_inst->setNotes(ui->noteEditor->toPlainText()); + return true; +} diff --git a/gui/pages/NotesPage.h b/gui/pages/NotesPage.h new file mode 100644 index 00000000..fe916f21 --- /dev/null +++ b/gui/pages/NotesPage.h @@ -0,0 +1,45 @@ +/* Copyright 2014 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include <QWidget> + +#include <logic/BaseInstance.h> +#include <logic/net/NetJob.h> +#include "BasePage.h" + +class EnabledItemFilter; +namespace Ui +{ +class NotesPage; +} + +class NotesPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit NotesPage(BaseInstance *inst, QWidget *parent = 0); + virtual ~NotesPage(); + virtual QString displayName() override; + virtual QIcon icon() override; + virtual QString id() override; + virtual bool apply(); + virtual QString helpPage() override { return "Notes"; }; + +private: + Ui::NotesPage *ui; + BaseInstance *m_inst; +}; diff --git a/gui/pages/NotesPage.ui b/gui/pages/NotesPage.ui new file mode 100644 index 00000000..ab33ffd3 --- /dev/null +++ b/gui/pages/NotesPage.ui @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>NotesPage</class> + <widget class="QWidget" name="NotesPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QTextEdit" name="noteEditor"> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOn</enum> + </property> + <property name="acceptRichText"> + <bool>false</bool> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextEditable|Qt::TextEditorInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/gui/pages/ResourcePackPage.h b/gui/pages/ResourcePackPage.h new file mode 100644 index 00000000..06367905 --- /dev/null +++ b/gui/pages/ResourcePackPage.h @@ -0,0 +1,19 @@ +#pragma once +#include "ModFolderPage.h" + +class ResourcePackPage : public ModFolderPage +{ +public: + explicit ResourcePackPage(BaseInstance *instance, QWidget *parent = 0) + : ModFolderPage(instance, instance->resourcePackList(), "resourcepacks", "resourcepacks", + tr("Resource packs"), "Resource-packs", parent) + { + } + + virtual ~ResourcePackPage() {}; + virtual bool shouldDisplay() override + { + return !m_inst->traits().contains("no-texturepacks") && + !m_inst->traits().contains("texturepacks"); + } +}; diff --git a/gui/pages/ScreenshotsPage.cpp b/gui/pages/ScreenshotsPage.cpp new file mode 100644 index 00000000..051bc12d --- /dev/null +++ b/gui/pages/ScreenshotsPage.cpp @@ -0,0 +1,270 @@ +#include "ScreenshotsPage.h" +#include "ui_ScreenshotsPage.h" + +#include <QModelIndex> +#include <QMutableListIterator> +#include <QFileIconProvider> +#include <QFileSystemModel> +#include <QStyledItemDelegate> +#include <QLineEdit> +#include <QtGui/qevent.h> + +#include <pathutils.h> + +#include "gui/dialogs/ProgressDialog.h" +#include "gui/dialogs/CustomMessageBox.h" +#include "logic/net/NetJob.h" +#include "logic/screenshots/ImgurUpload.h" +#include "logic/screenshots/ImgurAlbumCreation.h" +#include "logic/tasks/SequentialTask.h" + +class FilterModel : public QIdentityProxyModel +{ +public: + virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const + { + auto model = sourceModel(); + if (!model) + return QVariant(); + if (role == Qt::DisplayRole || role == Qt::EditRole) + { + QVariant result = sourceModel()->data(mapToSource(proxyIndex), role); + return result.toString().remove(QRegExp("\\.png$")); + } + if (role == Qt::DecorationRole) + { + QVariant result = sourceModel()->data(mapToSource(proxyIndex), QFileSystemModel::FilePathRole); + QString filePath = result.toString(); + if(thumbnailCache.contains(filePath)) + { + return thumbnailCache[filePath]; + } + bool failed = false; + QFileInfo info(filePath); + failed |= info.isDir(); + failed |= (info.suffix().compare("png", Qt::CaseInsensitive) != 0); + // WARNING: really an IF! this is purely for using break instead of goto... + while(!failed) + { + QImage image(info.absoluteFilePath()); + if (image.isNull()) + { + // TODO: schedule a retry. + failed = true; + break; + } + QImage thumbnail = image.scaledToWidth(512).scaledToWidth(256, Qt::SmoothTransformation); + QIcon icon(QPixmap::fromImage(thumbnail)); + // the casts are a hack for the stupid method being const. + ((QMap<QString, QIcon> &)thumbnailCache).insert(filePath, icon); + return icon; + } + // we failed anyway... + return sourceModel()->data(mapToSource(proxyIndex), QFileSystemModel::FileIconRole); + } + else + { + QVariant result = sourceModel()->data(mapToSource(proxyIndex), role); + return result; + } + } + virtual bool setData(const QModelIndex &index, const QVariant &value, + int role = Qt::EditRole) + { + auto model = sourceModel(); + if (!model) + return false; + if (role != Qt::EditRole) + return false; + // FIXME: this is a workaround for a bug in QFileSystemModel, where it doesn't + // sort after renames + { + ((QFileSystemModel *)model)->setNameFilterDisables(true); + ((QFileSystemModel *)model)->setNameFilterDisables(false); + } + return model->setData(mapToSource(index), value.toString() + ".png", role); + } +private: + QMap<QString, QIcon> thumbnailCache; +}; + +class CenteredEditingDelegate : public QStyledItemDelegate +{ +public: + explicit CenteredEditingDelegate(QObject *parent = 0) : QStyledItemDelegate(parent) + { + } + virtual ~CenteredEditingDelegate() + { + } + virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const + { + auto widget = QStyledItemDelegate::createEditor(parent, option, index); + auto foo = dynamic_cast<QLineEdit *>(widget); + if (foo) + { + foo->setAlignment(Qt::AlignHCenter); + foo->setFrame(true); + foo->setMaximumWidth(192); + } + return widget; + } +}; + +QString ScreenshotsPage::displayName() +{ + return tr("Screenshots"); +} + +QIcon ScreenshotsPage::icon() +{ + return QIcon::fromTheme("screenshots"); +} + +QString ScreenshotsPage::id() +{ + return "screenshots"; +} + +ScreenshotsPage::ScreenshotsPage(BaseInstance *instance, QWidget *parent) + : QWidget(parent), ui(new Ui::ScreenshotsPage) +{ + m_model.reset(new QFileSystemModel()); + m_filterModel.reset(new FilterModel()); + m_filterModel->setSourceModel(m_model.get()); + m_model->setFilter(QDir::Files | QDir::Writable | QDir::Readable); + m_model->setReadOnly(false); + m_folder = PathCombine(instance->minecraftRoot(), "screenshots"); + m_valid = ensureFolderPathExists(m_folder); + + ui->setupUi(this); + ui->listView->setModel(m_filterModel.get()); + ui->listView->setIconSize(QSize(128, 128)); + ui->listView->setGridSize(QSize(192, 128)); + ui->listView->setSpacing(9); + // ui->listView->setUniformItemSizes(true); + ui->listView->setLayoutMode(QListView::Batched); + ui->listView->setViewMode(QListView::IconMode); + ui->listView->setResizeMode(QListView::Adjust); + ui->listView->installEventFilter(this); + ui->listView->setEditTriggers(0); + ui->listView->setItemDelegate(new CenteredEditingDelegate(this)); + connect(ui->listView, SIGNAL(activated(QModelIndex)), SLOT(onItemActivated(QModelIndex))); +} + +bool ScreenshotsPage::eventFilter(QObject *obj, QEvent *evt) +{ + if (obj != ui->listView) + return QWidget::eventFilter(obj, evt); + if (evt->type() != QEvent::KeyPress) + { + return QWidget::eventFilter(obj, evt); + } + QKeyEvent *keyEvent = static_cast<QKeyEvent *>(evt); + switch (keyEvent->key()) + { + case Qt::Key_Delete: + on_deleteBtn_clicked(); + return true; + case Qt::Key_F2: + on_renameBtn_clicked(); + return true; + default: + break; + } + return QWidget::eventFilter(obj, evt); +} + +ScreenshotsPage::~ScreenshotsPage() +{ + delete ui; +} + +void ScreenshotsPage::onItemActivated(QModelIndex index) +{ + if (!index.isValid()) + return; + auto info = m_model->fileInfo(index); + QString fileName = info.absoluteFilePath(); + openFileInDefaultProgram(info.absoluteFilePath()); +} + +void ScreenshotsPage::on_viewFolderBtn_clicked() +{ + openDirInDefaultProgram(m_folder, true); +} + +void ScreenshotsPage::on_uploadBtn_clicked() +{ + auto selection = ui->listView->selectionModel()->selectedIndexes(); + if (selection.isEmpty()) + return; + + QList<ScreenshotPtr> uploaded; + auto job = std::make_shared<NetJob>("Screenshot Upload"); + for (auto item : selection) + { + auto info = m_model->fileInfo(item); + auto screenshot = std::make_shared<ScreenShot>(info); + uploaded.push_back(screenshot); + job->addNetAction(ImgurUpload::make(screenshot)); + } + SequentialTask task; + auto albumTask = std::make_shared<NetJob>("Imgur Album Creation"); + auto imgurAlbum = ImgurAlbumCreation::make(uploaded); + albumTask->addNetAction(imgurAlbum); + task.addTask(job); + task.addTask(albumTask); + ProgressDialog prog(this); + if (prog.exec(&task) != QDialog::Accepted) + { + CustomMessageBox::selectable(this, tr("Failed to upload screenshots!"), + tr("Unknown error"), QMessageBox::Warning)->exec(); + } + else + { + CustomMessageBox::selectable( + this, tr("Upload finished"), + tr("<a href=\"https://imgur.com/a/%1\">Visit album</a><br/>Delete hash: %2 (save " + "this if you want to be able to edit/delete the album)") + .arg(imgurAlbum->id(), imgurAlbum->deleteHash()), + QMessageBox::Information)->exec(); + } +} + +void ScreenshotsPage::on_deleteBtn_clicked() +{ + auto mbox = CustomMessageBox::selectable( + this, tr("Are you sure?"), tr("This will delete all selected screenshots."), + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No); + std::unique_ptr<QMessageBox> box(mbox); + + if (box->exec() != QMessageBox::Yes) + return; + + auto selected = ui->listView->selectionModel()->selectedIndexes(); + for (auto item : selected) + { + m_model->remove(item); + } +} + +void ScreenshotsPage::on_renameBtn_clicked() +{ + auto selection = ui->listView->selectionModel()->selectedIndexes(); + if (selection.isEmpty()) + return; + ui->listView->edit(selection[0]); + // TODO: mass renaming +} + +void ScreenshotsPage::opened() +{ + if (m_valid) + { + QString path = QDir(m_folder).absolutePath(); + m_model->setRootPath(path); + ui->listView->setRootIndex(m_filterModel->mapFromSource(m_model->index(path))); + } +} diff --git a/gui/pages/ScreenshotsPage.h b/gui/pages/ScreenshotsPage.h new file mode 100644 index 00000000..4098e5e4 --- /dev/null +++ b/gui/pages/ScreenshotsPage.h @@ -0,0 +1,68 @@ +/* Copyright 2014 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include <QWidget> +#include <logic/OneSixInstance.h> +#include "BasePage.h" +#include <QIcon> +#include <QEvent> + +class QFileSystemModel; +class QIdentityProxyModel; +namespace Ui +{ +class ScreenshotsPage; +} + +class ScreenShot; +class ScreenshotList; +class ImgurAlbumCreation; + +class ScreenshotsPage : public QWidget, public BasePage +{ + Q_OBJECT + +public: + explicit ScreenshotsPage(BaseInstance *instance, QWidget *parent = 0); + virtual ~ScreenshotsPage(); + + virtual void opened() override; + + enum + { + NothingDone = 0x42 + }; + + virtual bool eventFilter(QObject *, QEvent *); + virtual QString displayName() override; + virtual QIcon icon() override; + virtual QString id() override; + virtual QString helpPage() override { return "Screenshots-management"; }; +private +slots: + void on_uploadBtn_clicked(); + void on_deleteBtn_clicked(); + void on_renameBtn_clicked(); + void on_viewFolderBtn_clicked(); + void onItemActivated(QModelIndex); + +private: + Ui::ScreenshotsPage *ui; + std::shared_ptr<QFileSystemModel> m_model; + std::shared_ptr<QIdentityProxyModel> m_filterModel; + QString m_folder; + bool m_valid = false; +}; diff --git a/gui/pages/ScreenshotsPage.ui b/gui/pages/ScreenshotsPage.ui new file mode 100644 index 00000000..5951ab02 --- /dev/null +++ b/gui/pages/ScreenshotsPage.ui @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ScreenshotsPage</class> + <widget class="QWidget" name="ScreenshotsPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>723</width> + <height>532</height> + </rect> + </property> + <property name="windowTitle"> + <string>Mods</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QListView" name="listView"> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectItems</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QPushButton" name="uploadBtn"> + <property name="text"> + <string>&Upload</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="deleteBtn"> + <property name="text"> + <string>&Delete</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="renameBtn"> + <property name="text"> + <string>&Rename</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="viewFolderBtn"> + <property name="text"> + <string>&View Folder</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + <tabstops> + <tabstop>listView</tabstop> + <tabstop>uploadBtn</tabstop> + <tabstop>deleteBtn</tabstop> + <tabstop>renameBtn</tabstop> + <tabstop>viewFolderBtn</tabstop> + </tabstops> + <resources/> + <connections/> +</ui> diff --git a/gui/pages/TexturePackPage.h b/gui/pages/TexturePackPage.h new file mode 100644 index 00000000..69a47204 --- /dev/null +++ b/gui/pages/TexturePackPage.h @@ -0,0 +1,17 @@ +#pragma once +#include "ModFolderPage.h" + +class TexturePackPage : public ModFolderPage +{ +public: + explicit TexturePackPage(BaseInstance *instance, QWidget *parent = 0) + : ModFolderPage(instance, instance->texturePackList(), "texturepacks", "resourcepacks", + tr("Texture packs"), "Texture-packs", parent) + { + } + virtual ~TexturePackPage() {}; + virtual bool shouldDisplay() override + { + return m_inst->traits().contains("texturepacks"); + } +}; diff --git a/gui/pages/VersionPage.cpp b/gui/pages/VersionPage.cpp new file mode 100644 index 00000000..34599111 --- /dev/null +++ b/gui/pages/VersionPage.cpp @@ -0,0 +1,394 @@ +/* Copyright 2014 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 "MultiMC.h" + +#include <pathutils.h> +#include <QFileDialog> +#include <QMessageBox> +#include <QDebug> +#include <QEvent> +#include <QKeyEvent> + +#include "VersionPage.h" +#include "ui_VersionPage.h" + +#include "gui/Platform.h" +#include "gui/dialogs/CustomMessageBox.h" +#include "gui/dialogs/VersionSelectDialog.h" +#include "gui/dialogs/ModEditDialogCommon.h" + +#include "gui/dialogs/ProgressDialog.h" + +#include "logic/ModList.h" +#include "logic/minecraft/InstanceVersion.h" +#include "logic/EnabledItemFilter.h" +#include "logic/forge/ForgeVersionList.h" +#include "logic/forge/ForgeInstaller.h" +#include "logic/liteloader/LiteLoaderVersionList.h" +#include "logic/liteloader/LiteLoaderInstaller.h" +#include "logic/minecraft/VersionBuilder.h" +#include "logic/auth/MojangAccountList.h" + +#include <QAbstractItemModel> +#include <logic/Mod.h> +#include <logic/icons/IconList.h> + +#include <QMessageBox> +#include <QListView> +#include <QString> +#include <QUrl> + +QString VersionPage::displayName() +{ + return tr("Version"); +} + +QIcon VersionPage::icon() +{ + return MMC->icons()->getIcon(m_inst->iconKey()); +} + +QString VersionPage::id() +{ + return "version"; +} + +bool VersionPage::shouldDisplay() +{ + return !m_inst->isRunning(); +} + +VersionPage::VersionPage(OneSixInstance *inst, QWidget *parent) + : QWidget(parent), ui(new Ui::VersionPage), m_inst(inst) +{ + ui->setupUi(this); + // libraries! + + m_version = m_inst->getFullVersion(); + if (m_version) + { + 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->libraryTreeView->setSelectionMode(QAbstractItemView::SingleSelection); + connect(ui->libraryTreeView->selectionModel(), &QItemSelectionModel::currentChanged, + this, &VersionPage::versionCurrent); + updateVersionControls(); + // select first item. + auto index = main_model->index(0,0); + if(index.isValid()) + ui->libraryTreeView->setCurrentIndex(index); + } + else + { + disableVersionControls(); + } + connect(m_inst, &OneSixInstance::versionReloaded, this, + &VersionPage::updateVersionControls); +} + +VersionPage::~VersionPage() +{ + delete ui; +} + +void VersionPage::updateVersionControls() +{ + ui->forgeBtn->setEnabled(true); + ui->liteloaderBtn->setEnabled(true); +} + +void VersionPage::disableVersionControls() +{ + ui->forgeBtn->setEnabled(false); + ui->liteloaderBtn->setEnabled(false); + ui->reloadLibrariesBtn->setEnabled(false); + ui->removeLibraryBtn->setEnabled(false); +} + +bool VersionPage::reloadInstanceVersion() +{ + try + { + m_inst->reloadVersion(); + return true; + } + catch (MMCError &e) + { + QMessageBox::critical(this, tr("Error"), e.cause()); + return false; + } + catch (...) + { + QMessageBox::critical( + this, tr("Error"), + tr("Failed to load the version description file for reasons unknown.")); + return false; + } +} + +void VersionPage::on_reloadLibrariesBtn_clicked() +{ + reloadInstanceVersion(); +} + +void VersionPage::on_removeLibraryBtn_clicked() +{ + if (ui->libraryTreeView->currentIndex().isValid()) + { + // FIXME: use actual model, not reloading. + if (!m_version->remove(ui->libraryTreeView->currentIndex().row())) + { + QMessageBox::critical(this, tr("Error"), tr("Couldn't remove file")); + } + } +} + +void VersionPage::on_jarmodBtn_clicked() +{ + QFileDialog w; + QSet<QString> locations; + QString modsFolder = MMC->settings()->get("CentralModsDir").toString(); + auto f = [&](QStandardPaths::StandardLocation l) + { + QString location = QStandardPaths::writableLocation(l); + QFileInfo finfo(location); + if (!finfo.exists()) + return; + locations.insert(location); + }; + f(QStandardPaths::DesktopLocation); + f(QStandardPaths::DocumentsLocation); + f(QStandardPaths::DownloadLocation); + f(QStandardPaths::HomeLocation); + QList<QUrl> urls; + for (auto location : locations) + { + urls.append(QUrl::fromLocalFile(location)); + } + urls.append(QUrl::fromLocalFile(modsFolder)); + + w.setFileMode(QFileDialog::ExistingFiles); + w.setAcceptMode(QFileDialog::AcceptOpen); + w.setNameFilter(tr("Minecraft jar mods (*.zip *.jar)")); + w.setDirectory(modsFolder); + w.setSidebarUrls(urls); + + if (w.exec()) + m_version->installJarMods(w.selectedFiles()); +} + +void VersionPage::on_resetLibraryOrderBtn_clicked() +{ + try + { + m_version->resetOrder(); + } + catch (MMCError &e) + { + QMessageBox::critical(this, tr("Error"), e.cause()); + } +} + +void VersionPage::on_moveLibraryUpBtn_clicked() +{ + if (ui->libraryTreeView->selectionModel()->selectedRows().isEmpty()) + { + return; + } + try + { + const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row(); + const int newRow = 0; + m_version->move(row, InstanceVersion::MoveUp); + // ui->libraryTreeView->selectionModel()->setCurrentIndex(m_version->index(newRow), + // QItemSelectionModel::ClearAndSelect); + } + catch (MMCError &e) + { + QMessageBox::critical(this, tr("Error"), e.cause()); + } +} + +void VersionPage::on_moveLibraryDownBtn_clicked() +{ + if (ui->libraryTreeView->selectionModel()->selectedRows().isEmpty()) + { + return; + } + try + { + const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row(); + const int newRow = 0; + m_version->move(row, InstanceVersion::MoveDown); + // ui->libraryTreeView->selectionModel()->setCurrentIndex(m_version->index(newRow), + // QItemSelectionModel::ClearAndSelect); + } + catch (MMCError &e) + { + QMessageBox::critical(this, tr("Error"), e.cause()); + } +} + +void VersionPage::on_changeMCVersionBtn_clicked() +{ + VersionSelectDialog vselect(m_inst->versionList().get(), tr("Change Minecraft version"), + this); + if (!vselect.exec() || !vselect.selectedVersion()) + return; + + if (!MMC->accounts()->anyAccountIsValid()) + { + CustomMessageBox::selectable( + this, tr("Error"), + tr("MultiMC cannot download Minecraft or update instances unless you have at least " + "one account added.\nPlease add your Mojang or Minecraft account."), + QMessageBox::Warning)->show(); + return; + } + + if (m_inst->versionIsCustom()) + { + auto result = CustomMessageBox::selectable( + 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::Warning, QMessageBox::Ok | QMessageBox::Abort, + QMessageBox::Abort)->exec(); + + if (result != QMessageBox::Ok) + return; + m_version->revertToVanilla(); + reloadInstanceVersion(); + } + m_inst->setIntendedVersionId(vselect.selectedVersion()->descriptor()); + + auto updateTask = m_inst->doUpdate(); + if (!updateTask) + { + return; + } + ProgressDialog tDialog(this); + connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString))); + tDialog.exec(updateTask.get()); +} + +void VersionPage::on_forgeBtn_clicked() +{ + // FIXME: use actual model, not reloading. Move logic to model. + if (m_version->hasFtbPack()) + { + if (QMessageBox::question( + this, tr("Revert?"), + tr("This action will remove the FTB pack version patch. Continue?")) != + QMessageBox::Yes) + { + return; + } + m_version->removeFtbPack(); + reloadInstanceVersion(); + } + if (m_version->hasDeprecatedVersionFiles()) + { + if (QMessageBox::question(this, tr("Revert?"), + tr("This action will remove deprecated version files " + "(custom.json and version.json). Continue?")) != + QMessageBox::Yes) + { + return; + } + m_version->removeDeprecatedVersionFiles(); + reloadInstanceVersion(); + } + VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this); + vselect.setExactFilter(1, m_inst->currentVersionId()); + vselect.setEmptyString(tr("No Forge versions are currently available for Minecraft ") + + m_inst->currentVersionId()); + if (vselect.exec() && vselect.selectedVersion()) + { + ProgressDialog dialog(this); + dialog.exec( + ForgeInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this)); + } +} + +void VersionPage::on_liteloaderBtn_clicked() +{ + if (m_version->hasFtbPack()) + { + if (QMessageBox::question( + this, tr("Revert?"), + tr("This action will remove the FTB pack version patch. Continue?")) != + QMessageBox::Yes) + { + return; + } + m_version->removeFtbPack(); + reloadInstanceVersion(); + } + if (m_version->hasDeprecatedVersionFiles()) + { + if (QMessageBox::question(this, tr("Revert?"), + tr("This action will remove deprecated version files " + "(custom.json and version.json). Continue?")) != + QMessageBox::Yes) + { + return; + } + m_version->removeDeprecatedVersionFiles(); + reloadInstanceVersion(); + } + VersionSelectDialog vselect(MMC->liteloaderlist().get(), tr("Select LiteLoader version"), + this); + vselect.setExactFilter(1, m_inst->currentVersionId()); + vselect.setEmptyString(tr("No LiteLoader versions are currently available for Minecraft ") + + m_inst->currentVersionId()); + if (vselect.exec() && vselect.selectedVersion()) + { + ProgressDialog dialog(this); + dialog.exec( + LiteLoaderInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this)); + } +} + +void VersionPage::versionCurrent(const QModelIndex ¤t, const QModelIndex &previous) +{ + if (!current.isValid()) + { + ui->removeLibraryBtn->setDisabled(true); + ui->moveLibraryDownBtn->setDisabled(true); + ui->moveLibraryUpBtn->setDisabled(true); + } + else + { + bool enabled = m_version->canRemove(current.row()); + ui->removeLibraryBtn->setEnabled(enabled); + ui->moveLibraryDownBtn->setEnabled(enabled); + ui->moveLibraryUpBtn->setEnabled(enabled); + } + QString selectedId = m_version->versionFileId(current.row()); + if (selectedId == "net.minecraft" || selectedId == "org.multimc.custom.json" || + selectedId == "org.multimc.version.json") + { + ui->changeMCVersionBtn->setEnabled(true); + } + else + { + ui->changeMCVersionBtn->setEnabled(false); + } +} diff --git a/gui/dialogs/OneSixModEditDialog.h b/gui/pages/VersionPage.h index e106c6fe..dfbb6741 100644 --- a/gui/dialogs/OneSixModEditDialog.h +++ b/gui/pages/VersionPage.h @@ -1,4 +1,4 @@ -/* Copyright 2013 MultiMC Contributors +/* Copyright 2014 MultiMC Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,35 +14,34 @@ */ #pragma once -#include <QDialog> +#include <QWidget> #include <logic/OneSixInstance.h> +#include <logic/net/NetJob.h> +#include "BasePage.h" class EnabledItemFilter; namespace Ui { -class OneSixModEditDialog; +class VersionPage; } -class OneSixModEditDialog : public QDialog +class VersionPage : public QWidget, public BasePage { Q_OBJECT public: - explicit OneSixModEditDialog(OneSixInstance *inst, QWidget *parent = 0); - virtual ~OneSixModEditDialog(); - + explicit VersionPage(OneSixInstance *inst, QWidget *parent = 0); + virtual ~VersionPage(); + virtual QString displayName() override; + virtual QIcon icon() override; + virtual QString id() override; + virtual QString helpPage() override { return "Instance-version"; }; + virtual bool shouldDisplay(); 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(); + // version tab void on_forgeBtn_clicked(); void on_liteloaderBtn_clicked(); void on_reloadLibrariesBtn_clicked(); @@ -50,26 +49,24 @@ slots: void on_resetLibraryOrderBtn_clicked(); void on_moveLibraryUpBtn_clicked(); void on_moveLibraryDownBtn_clicked(); + void on_jarmodBtn_clicked(); + void updateVersionControls(); void disableVersionControls(); + void on_changeMCVersionBtn_clicked(); protected: - bool eventFilter(QObject *obj, QEvent *ev); - bool loaderListFilter(QKeyEvent *ev); - bool resourcePackListFilter(QKeyEvent *ev); /// FIXME: this shouldn't be necessary! bool reloadInstanceVersion(); private: - Ui::OneSixModEditDialog *ui; - std::shared_ptr<VersionFinal> m_version; - std::shared_ptr<ModList> m_mods; - std::shared_ptr<ModList> m_resourcepacks; + Ui::VersionPage *ui; + std::shared_ptr<InstanceVersion> m_version; EnabledItemFilter *main_model; OneSixInstance *m_inst; + NetJobPtr forgeJob; public slots: - void loaderCurrent(QModelIndex current, QModelIndex previous); void versionCurrent(const QModelIndex ¤t, const QModelIndex &previous); }; diff --git a/gui/pages/VersionPage.ui b/gui/pages/VersionPage.ui new file mode 100644 index 00000000..f770df55 --- /dev/null +++ b/gui/pages/VersionPage.ui @@ -0,0 +1,197 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>VersionPage</class> + <widget class="QWidget" name="VersionPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>475</height> + </rect> + </property> + <property name="windowTitle"> + <string>Version</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <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> + <property name="headerHidden"> + <bool>false</bool> + </property> + <attribute name="headerVisible"> + <bool>true</bool> + </attribute> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Selection</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="changeMCVersionBtn"> + <property name="text"> + <string>Change version</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="moveLibraryUpBtn"> + <property name="toolTip"> + <string>This isn't implemented yet.</string> + </property> + <property name="text"> + <string>Move up</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="moveLibraryDownBtn"> + <property name="toolTip"> + <string>This isn't implemented yet.</string> + </property> + <property name="text"> + <string>Move down</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="removeLibraryBtn"> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + <item> + <widget class="LineSeparator" name="separator" native="true"/> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Install</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <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="liteloaderBtn"> + <property name="text"> + <string>Install LiteLoader</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="jarmodBtn"> + <property name="text"> + <string>Add jar mod</string> + </property> + </widget> + </item> + <item> + <widget class="LineSeparator" name="widget" native="true"/> + </item> + <item> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>List</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="resetLibraryOrderBtn"> + <property name="toolTip"> + <string>This isn't implemented yet.</string> + </property> + <property name="text"> + <string>Reset order</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="reloadLibrariesBtn"> + <property name="text"> + <string>Reload</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_7"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>ModListView</class> + <extends>QTreeView</extends> + <header>gui/widgets/ModListView.h</header> + </customwidget> + <customwidget> + <class>LineSeparator</class> + <extends>QWidget</extends> + <header>gui/widgets/LineSeparator.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/gui/widgets/IconLabel.cpp b/gui/widgets/IconLabel.cpp index 1bfe8dc9..773f0b99 100644 --- a/gui/widgets/IconLabel.cpp +++ b/gui/widgets/IconLabel.cpp @@ -7,7 +7,7 @@ #include <QRect> IconLabel::IconLabel(QWidget *parent, QIcon icon, QSize size) - : QWidget(parent), m_icon(icon), m_size(size) + : QWidget(parent), m_size(size), m_icon(icon) { setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); } diff --git a/gui/widgets/LineSeparator.h b/gui/widgets/LineSeparator.h index 376f2056..9546e747 100644 --- a/gui/widgets/LineSeparator.h +++ b/gui/widgets/LineSeparator.h @@ -9,10 +9,10 @@ class LineSeparator : public QWidget public: /// Create a line separator. orientation is the orientation of the line. - explicit LineSeparator(QWidget *parent, Qt::Orientation orientation = Qt::Vertical); + explicit LineSeparator(QWidget *parent, Qt::Orientation orientation = Qt::Horizontal); QSize sizeHint() const; void paintEvent(QPaintEvent *); void initStyleOption(QStyleOption *option) const; private: - Qt::Orientation m_orientation = Qt::Vertical; + Qt::Orientation m_orientation = Qt::Horizontal; }; diff --git a/gui/widgets/PageContainer.cpp b/gui/widgets/PageContainer.cpp new file mode 100644 index 00000000..237e7224 --- /dev/null +++ b/gui/widgets/PageContainer.cpp @@ -0,0 +1,196 @@ +/* Copyright 2014 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 "PageContainer.h" +#include "gui/Platform.h" +#include <QStackedLayout> +#include <QPushButton> +#include <QSortFilterProxyModel> +#include <QUrl> +#include "MultiMC.h" +#include <QStyledItemDelegate> +#include <QListView> +#include <QLineEdit> +#include <QLabel> +#include <QDialogButtonBox> +#include <QGridLayout> +#include <QDesktopServices> +#include <settingsobject.h> + +#include "PageContainer_p.h" +#include <gui/widgets/IconLabel.h> + +class PageEntryFilterModel : public QSortFilterProxyModel +{ +public: + explicit PageEntryFilterModel(QObject *parent = 0) : QSortFilterProxyModel(parent) + { + } + +protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const + { + const QString pattern = filterRegExp().pattern(); + const auto model = static_cast<PageModel *>(sourceModel()); + const auto page = model->pages().at(sourceRow); + if(!page->shouldDisplay()) + return false; + // Regular contents check, then check page-filter. + return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); + } +}; + +PageContainer::PageContainer(BasePageProviderPtr pageProvider, QString defaultId, QWidget *parent) : QWidget(parent) +{ + createUI(); + m_model = new PageModel(this); + m_proxyModel = new PageEntryFilterModel(this); + int firstIndex = -1; + int counter = 0; + auto pages = pageProvider->getPages(); + for(auto page: pages) + { + page->stackIndex = m_pageStack->addWidget(dynamic_cast<QWidget *>(page)); + page->listIndex = counter; + counter++; + if(firstIndex == -1) + { + firstIndex = page->stackIndex; + } + } + m_model->setPages(pages); + + m_proxyModel->setSourceModel(m_model); + m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + + m_pageList->setIconSize(QSize(pageIconSize, pageIconSize)); + m_pageList->setSelectionMode(QAbstractItemView::SingleSelection); + m_pageList->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + m_pageList->setModel(m_proxyModel); + connect(m_pageList->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), + this, SLOT(currentChanged(QModelIndex))); + m_pageStack->setStackingMode(QStackedLayout::StackOne); + m_pageList->setFocus(); + // now find what we want to have selected... + auto page = m_model->findPageEntryById(defaultId); + QModelIndex index; + if(page) + { + index = m_proxyModel->mapFromSource(m_model->index(page->listIndex)); + } + else + { + index = m_proxyModel->index(0,0); + } + if(index.isValid()) + m_pageList->setCurrentIndex(index); +} + +void PageContainer::createUI() +{ + m_pageStack = new QStackedLayout; + m_filter = new QLineEdit; + m_pageList = new PageView; + m_header = new QLabel(); + m_iconHeader = new IconLabel(this, QIcon(), QSize(24,24)); + + QFont headerLabelFont = m_header->font(); + headerLabelFont.setBold(true); + const int pointSize = headerLabelFont.pointSize(); + if (pointSize > 0) + headerLabelFont.setPointSize(pointSize + 2); + m_header->setFont(headerLabelFont); + + QHBoxLayout *headerHLayout = new QHBoxLayout; + const int leftMargin = MMC->style()->pixelMetric(QStyle::PM_LayoutLeftMargin); + headerHLayout->addSpacerItem( + new QSpacerItem(leftMargin, 0, QSizePolicy::Fixed, QSizePolicy::Ignored)); + headerHLayout->addWidget(m_header); + headerHLayout->addSpacerItem( + new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); + headerHLayout->addWidget(m_iconHeader); + + m_pageStack->setMargin(0); + m_pageStack->addWidget(new QWidget(this)); + + m_layout = new QGridLayout; + m_layout->addLayout(headerHLayout, 0, 1, 1, 1); + m_layout->addWidget(m_pageList, 0, 0, 2, 1); + m_layout->addLayout(m_pageStack, 1, 1, 1, 1); + m_layout->setColumnStretch(1, 4); + setLayout(m_layout); +} + +void PageContainer::addButtons(QWidget *buttons) +{ + m_layout->addWidget(buttons, 2, 0, 1, 2); +} + +void PageContainer::addButtons(QLayout *buttons) +{ + m_layout->addLayout(buttons, 2, 0, 1, 2); +} + + +void PageContainer::showPage(int row) +{ + if(row != -1) + { + m_currentPage = m_model->pages().at(row); + } + else + { + m_currentPage = nullptr; + } + if(m_currentPage) + { + m_pageStack->setCurrentIndex(m_currentPage->stackIndex); + m_header->setText(m_currentPage->displayName()); + m_iconHeader->setIcon(m_currentPage->icon()); + m_currentPage->opened(); + } + else + { + m_pageStack->setCurrentIndex(0); + m_header->setText(QString()); + m_iconHeader->setIcon(QIcon::fromTheme("bug")); + } +} + +void PageContainer::help() +{ + if(m_currentPage) + { + QString pageId = m_currentPage->helpPage(); + if(pageId.isEmpty()) + return; + QDesktopServices::openUrl(QUrl("https://github.com/MultiMC/MultiMC5/wiki/" + pageId)); + } +} + +void PageContainer::currentChanged(const QModelIndex ¤t) +{ + showPage(current.isValid() ? m_proxyModel->mapToSource(current).row() : -1); +} + +bool PageContainer::requestClose(QCloseEvent * event) +{ + for(auto page: m_model->pages()) + { + if(!page->apply()) + return false; + } + return true; +} diff --git a/gui/widgets/PageContainer.h b/gui/widgets/PageContainer.h new file mode 100644 index 00000000..c0f17e90 --- /dev/null +++ b/gui/widgets/PageContainer.h @@ -0,0 +1,61 @@ +/* Copyright 2014 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include <QWidget> +#include <QModelIndex> +#include <gui/pages/BasePageProvider.h> + +class QLayout; +class IconLabel; +class QSortFilterProxyModel; +class PageModel; +class QLabel; +class QListView; +class QLineEdit; +class QStackedLayout; +class QGridLayout; + +class PageContainer : public QWidget +{ + Q_OBJECT +public: + explicit PageContainer(BasePageProviderPtr pageProvider, QString defaultId = QString(), + QWidget *parent = 0); + virtual ~PageContainer() {}; + + void addButtons(QWidget * buttons); + void addButtons(QLayout * buttons); + bool requestClose(QCloseEvent *event); + +private: + void createUI(); +private +slots: + void currentChanged(const QModelIndex ¤t); + void showPage(int row); + void help(); + +private: + BasePage * m_currentPage; + QSortFilterProxyModel *m_proxyModel; + PageModel *m_model; + QStackedLayout *m_pageStack; + QLineEdit *m_filter; + QListView *m_pageList; + QLabel *m_header; + IconLabel *m_iconHeader; + QGridLayout *m_layout; +}; diff --git a/gui/widgets/PageContainer_p.h b/gui/widgets/PageContainer_p.h new file mode 100644 index 00000000..f10e8f2c --- /dev/null +++ b/gui/widgets/PageContainer_p.h @@ -0,0 +1,106 @@ +#pragma once +#include <QListView> +#include <QStyledItemDelegate> +#include <QEvent> +#include <QScrollBar> + +class BasePage; +const int pageIconSize = 24; + +class PageViewDelegate : public QStyledItemDelegate +{ +public: + PageViewDelegate(QObject *parent) : QStyledItemDelegate(parent) + { + } + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const + { + QSize size = QStyledItemDelegate::sizeHint(option, index); + size.setHeight(qMax(size.height(), 32)); + return size; + } +}; + +class PageModel : public QAbstractListModel +{ +public: + PageModel(QObject *parent = 0) : QAbstractListModel(parent) + { + QPixmap empty(pageIconSize, pageIconSize); + empty.fill(Qt::transparent); + m_emptyIcon = QIcon(empty); + } + virtual ~PageModel() {}; + + int rowCount(const QModelIndex &parent = QModelIndex()) const + { + return parent.isValid() ? 0 : m_pages.size(); + } + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const + { + switch (role) + { + case Qt::DisplayRole: + return m_pages.at(index.row())->displayName(); + case Qt::DecorationRole: + { + QIcon icon = m_pages.at(index.row())->icon(); + if (icon.isNull()) + icon = m_emptyIcon; + return icon; + } + } + return QVariant(); + } + + void setPages(const QList<BasePage *> &pages) + { + beginResetModel(); + m_pages = pages; + endResetModel(); + } + const QList<BasePage *> &pages() const + { + return m_pages; + } + + BasePage * findPageEntryById(QString id) + { + for(auto page: m_pages) + { + if (page->id() == id) + return page; + } + return nullptr; + } + + QList<BasePage *> m_pages; + QIcon m_emptyIcon; +}; + +class PageView : public QListView +{ +public: + PageView(QWidget *parent = 0) : QListView(parent) + { + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); + setItemDelegate(new PageViewDelegate(this)); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + } + + virtual QSize sizeHint() const + { + int width = sizeHintForColumn(0) + frameWidth() * 2 + 5; + if (verticalScrollBar()->isVisible()) + width += verticalScrollBar()->width(); + return QSize(width, 100); + } + + virtual bool eventFilter(QObject *obj, QEvent *event) + { + if (obj == verticalScrollBar() && + (event->type() == QEvent::Show || event->type() == QEvent::Hide)) + updateGeometry(); + return QListView::eventFilter(obj, event); + } +}; diff --git a/gui/widgets/ServerStatus.cpp b/gui/widgets/ServerStatus.cpp index e540a301..10ed79fb 100644 --- a/gui/widgets/ServerStatus.cpp +++ b/gui/widgets/ServerStatus.cpp @@ -59,7 +59,7 @@ void ServerStatus::reloadStatus() void ServerStatus::addLine() { - layout->addWidget(new LineSeparator(this)); + layout->addWidget(new LineSeparator(this, Qt::Vertical)); } void ServerStatus::addStatus(QString key, QString name) |