Redo the console window. Log is now a page. Console window has relevant pages.

Dirty fix for screenshot thumbnail generation. Needs more QTimer.
This commit is contained in:
Petr Mrázek 2014-06-30 02:02:57 +02:00
parent 5179aed3a0
commit 421a46e3d3
30 changed files with 547 additions and 329 deletions

View File

@ -304,6 +304,8 @@ SET(MULTIMC_SOURCES
gui/pages/LegacyUpgradePage.h gui/pages/LegacyUpgradePage.h
gui/pages/LegacyJarModPage.cpp gui/pages/LegacyJarModPage.cpp
gui/pages/LegacyJarModPage.h gui/pages/LegacyJarModPage.h
gui/pages/LogPage.cpp
gui/pages/LogPage.h
gui/pages/InstanceSettingsPage.cpp gui/pages/InstanceSettingsPage.cpp
gui/pages/InstanceSettingsPage.h gui/pages/InstanceSettingsPage.h
gui/pages/ScreenshotsPage.cpp gui/pages/ScreenshotsPage.cpp
@ -606,13 +608,13 @@ SET(MULTIMC_SOURCES
SET(MULTIMC_UIS SET(MULTIMC_UIS
# Windows # Windows
gui/MainWindow.ui gui/MainWindow.ui
gui/ConsoleWindow.ui
# Option pages # Option pages
gui/pages/VersionPage.ui gui/pages/VersionPage.ui
gui/pages/ModFolderPage.ui gui/pages/ModFolderPage.ui
gui/pages/LegacyUpgradePage.ui gui/pages/LegacyUpgradePage.ui
gui/pages/LegacyJarModPage.ui gui/pages/LegacyJarModPage.ui
gui/pages/LogPage.ui
gui/pages/InstanceSettingsPage.ui gui/pages/InstanceSettingsPage.ui
gui/pages/NotesPage.ui gui/pages/NotesPage.ui
gui/pages/ScreenshotsPage.ui gui/pages/ScreenshotsPage.ui

View File

@ -14,27 +14,117 @@
*/ */
#include "ConsoleWindow.h" #include "ConsoleWindow.h"
#include "ui_ConsoleWindow.h"
#include "MultiMC.h" #include "MultiMC.h"
#include <QScrollBar> #include <QScrollBar>
#include <QMessageBox> #include <QMessageBox>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include <QHBoxLayout>
#include <QPushButton>
#include <qlayoutitem.h>
#include <gui/Platform.h> #include <gui/Platform.h>
#include <gui/dialogs/CustomMessageBox.h> #include <gui/dialogs/CustomMessageBox.h>
#include <gui/dialogs/ProgressDialog.h> #include <gui/dialogs/ProgressDialog.h>
#include "widgets/PageContainer.h"
#include "pages/LogPage.h"
#include "logic/net/PasteUpload.h"
#include "logic/icons/IconList.h" #include "logic/icons/IconList.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) ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent)
: QMainWindow(parent), ui(new Ui::ConsoleWindow), proc(mcproc) : QMainWindow(parent), m_proc(mcproc)
{ {
MultiMCPlatform::fixWM_CLASS(this); MultiMCPlatform::fixWM_CLASS(this);
ui->setupUi(this);
connect(mcproc, SIGNAL(log(QString, MessageLevel::Enum)), this, auto instance = m_proc->instance();
SLOT(write(QString, MessageLevel::Enum))); 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, connect(mcproc, SIGNAL(ended(InstancePtr, int, QProcess::ExitStatus)), this,
SLOT(onEnded(InstancePtr, int, QProcess::ExitStatus))); SLOT(onEnded(InstancePtr, int, QProcess::ExitStatus)));
connect(mcproc, SIGNAL(prelaunch_failed(InstancePtr, int, QProcess::ExitStatus)), this, connect(mcproc, SIGNAL(prelaunch_failed(InstancePtr, int, QProcess::ExitStatus)), this,
@ -42,34 +132,12 @@ ConsoleWindow::ConsoleWindow(MinecraftProcess *mcproc, QWidget *parent)
connect(mcproc, SIGNAL(launch_failed(InstancePtr)), this, connect(mcproc, SIGNAL(launch_failed(InstancePtr)), this,
SLOT(onLaunchFailed(InstancePtr))); SLOT(onLaunchFailed(InstancePtr)));
restoreState( setMayClose(false);
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);
connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
m_trayIcon->show();
if (mcproc->instance()->settings().get("ShowConsole").toBool()) if (mcproc->instance()->settings().get("ShowConsole").toBool())
{ {
show(); show();
} }
setMayClose(false);
}
ConsoleWindow::~ConsoleWindow()
{
delete ui;
} }
void ConsoleWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) void ConsoleWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
@ -85,110 +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');
QStringList filtered;
for (QString &paragraph : 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();
}
}
void ConsoleWindow::clear()
{
ui->text->clear();
}
void ConsoleWindow::on_closeButton_clicked() void ConsoleWindow::on_closeButton_clicked()
{ {
close(); close();
} }
void ConsoleWindow::on_btnScreenshots_clicked()
{
}
void ConsoleWindow::setMayClose(bool mayclose) void ConsoleWindow::setMayClose(bool mayclose)
{ {
if(mayclose) if(mayclose)
ui->closeButton->setText(tr("Close")); m_closeButton->setText(tr("Close"));
else else
ui->closeButton->setText(tr("Hide")); m_closeButton->setText(tr("Hide"));
m_mayclose = mayclose; m_mayclose = mayclose;
} }
void ConsoleWindow::toggleConsole() void ConsoleWindow::toggleConsole()
{ {
QScrollBar *bar = ui->text->verticalScrollBar(); //QScrollBar *bar = ui->text->verticalScrollBar();
if (isVisible()) if (isVisible())
{ {
if(!isActiveWindow()) if(!isActiveWindow())
@ -196,15 +177,17 @@ void ConsoleWindow::toggleConsole()
activateWindow(); activateWindow();
return; return;
} }
/*
int max_bar = bar->maximum(); int max_bar = bar->maximum();
int val_bar = m_last_scroll_value = bar->value(); int val_bar = m_last_scroll_value = bar->value();
m_scroll_active = (max_bar - val_bar) <= 1; m_scroll_active = (max_bar - val_bar) <= 1;
*/
hide(); hide();
} }
else else
{ {
show(); show();
isTopLevel(); /*
if (m_scroll_active) if (m_scroll_active)
{ {
bar->setValue(bar->maximum()); bar->setValue(bar->maximum());
@ -213,6 +196,7 @@ void ConsoleWindow::toggleConsole()
{ {
bar->setValue(m_last_scroll_value); bar->setValue(m_last_scroll_value);
} }
*/
} }
} }
@ -235,25 +219,23 @@ void ConsoleWindow::closeEvent(QCloseEvent *event)
void ConsoleWindow::on_btnKillMinecraft_clicked() void ConsoleWindow::on_btnKillMinecraft_clicked()
{ {
ui->btnKillMinecraft->setEnabled(false); m_killButton->setEnabled(false);
auto response = CustomMessageBox::selectable( auto response = CustomMessageBox::selectable(
this, tr("Kill Minecraft?"), this, tr("Kill Minecraft?"),
tr("This can cause the instance to get corrupted and should only be used if Minecraft " tr("This can cause the instance to get corrupted and should only be used if Minecraft "
"is frozen for some reason"), "is frozen for some reason"),
QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec(); QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec();
if (response == QMessageBox::Yes) if (response == QMessageBox::Yes)
proc->killMinecraft(); m_proc->killMinecraft();
else else
ui->btnKillMinecraft->setEnabled(true); m_killButton->setEnabled(true);
} }
void ConsoleWindow::onEnded(InstancePtr instance, int code, QProcess::ExitStatus status) void ConsoleWindow::onEnded(InstancePtr instance, int code, QProcess::ExitStatus status)
{ {
bool peacefulExit = code == 0 && status != QProcess::CrashExit; bool peacefulExit = code == 0 && status != QProcess::CrashExit;
ui->btnKillMinecraft->setEnabled(false); m_killButton->setEnabled(false);
setMayClose(true); setMayClose(true);
if (instance->settings().get("AutoCloseConsole").toBool()) if (instance->settings().get("AutoCloseConsole").toBool())
{ {
if (peacefulExit) if (peacefulExit)
@ -262,15 +244,8 @@ void ConsoleWindow::onEnded(InstancePtr instance, int code, QProcess::ExitStatus
return; return;
} }
} }
/*
if(!peacefulExit)
{
m_trayIcon->showMessage(tr("Oh no!"), tr("Minecraft crashed!"), QSystemTrayIcon::Critical);
}
*/
if (!isVisible()) if (!isVisible())
show(); show();
// Raise Window // Raise Window
if (MMC->settings()->get("RaiseConsole").toBool()) if (MMC->settings()->get("RaiseConsole").toBool())
{ {
@ -281,23 +256,10 @@ void ConsoleWindow::onEnded(InstancePtr instance, int code, QProcess::ExitStatus
void ConsoleWindow::onLaunchFailed(InstancePtr instance) void ConsoleWindow::onLaunchFailed(InstancePtr instance)
{ {
ui->btnKillMinecraft->setEnabled(false); m_killButton->setEnabled(false);
setMayClose(true); setMayClose(true);
if (!isVisible()) if (!isVisible())
show(); 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();
}
}

View File

@ -19,18 +19,15 @@
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include "logic/MinecraftProcess.h" #include "logic/MinecraftProcess.h"
namespace Ui class QPushButton;
{ class PageContainer;
class ConsoleWindow;
}
class ConsoleWindow : public QMainWindow class ConsoleWindow : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ConsoleWindow(MinecraftProcess *proc, QWidget *parent = 0); explicit ConsoleWindow(MinecraftProcess *proc, QWidget *parent = 0);
~ConsoleWindow(); virtual ~ConsoleWindow() {};
/** /**
* @brief specify if the window is allowed to close * @brief specify if the window is allowed to close
@ -39,38 +36,12 @@ public:
*/ */
void setMayClose(bool mayclose); 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: signals:
void isClosing(); 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 private
slots: slots:
void on_closeButton_clicked(); void on_closeButton_clicked();
void on_btnScreenshots_clicked();
void on_btnKillMinecraft_clicked(); void on_btnKillMinecraft_clicked();
void onEnded(InstancePtr instance, int code, QProcess::ExitStatus status); 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 // FIXME: add handlers for the other MinecraftProcess signals (pre/post launch command
// failures) // failures)
void on_btnPaste_clicked();
void iconActivated(QSystemTrayIcon::ActivationReason); void iconActivated(QSystemTrayIcon::ActivationReason);
void toggleConsole(); void toggleConsole();
protected: protected:
void closeEvent(QCloseEvent *); void closeEvent(QCloseEvent *);
private: private:
Ui::ConsoleWindow *ui = nullptr; MinecraftProcess *m_proc = nullptr;
MinecraftProcess *proc = nullptr;
bool m_mayclose = true; bool m_mayclose = true;
int m_last_scroll_value = 0;
bool m_scroll_active = true;
QSystemTrayIcon *m_trayIcon = nullptr; QSystemTrayIcon *m_trayIcon = nullptr;
int m_saved_offset = 0; PageContainer *m_container = nullptr;
QPushButton *m_closeButton = nullptr;
QPushButton *m_killButton = nullptr;
}; };

View File

@ -1,86 +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>
<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>&amp;Kill Minecraft</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeButton">
<property name="text">
<string>&amp;Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -420,7 +420,7 @@ void SettingsDialog::loadSettings(SettingsObject *s)
foreach(const QString & lang, QDir(MMC->staticData() + "/translations") foreach(const QString & lang, QDir(MMC->staticData() + "/translations")
.entryList(QStringList() << "*.qm", QDir::Files)) .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->addItem(QLocale::languageToString(locale.language()), locale);
} }
ui->languageBox->setCurrentIndex( ui->languageBox->setCurrentIndex(

View File

@ -23,13 +23,19 @@ QString InstanceSettingsPage::id()
return "settings"; return "settings";
} }
InstanceSettingsPage::InstanceSettingsPage(SettingsObject *s, QWidget *parent) InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent)
: QWidget(parent), ui(new Ui::InstanceSettingsPage), m_settings(s) : QWidget(parent), ui(new Ui::InstanceSettingsPage), m_instance(inst)
{ {
m_settings = &(inst->settings());
ui->setupUi(this); ui->setupUi(this);
loadSettings(); loadSettings();
} }
bool InstanceSettingsPage::shouldDisplay()
{
return !m_instance->isRunning();
}
InstanceSettingsPage::~InstanceSettingsPage() InstanceSettingsPage::~InstanceSettingsPage()
{ {
delete ui; delete ui;

View File

@ -32,15 +32,14 @@ class InstanceSettingsPage : public QWidget, public BasePage
Q_OBJECT Q_OBJECT
public: public:
explicit InstanceSettingsPage(SettingsObject *s, QWidget *parent = 0); explicit InstanceSettingsPage(BaseInstance *inst, QWidget *parent = 0);
virtual ~InstanceSettingsPage(); virtual ~InstanceSettingsPage();
virtual QString displayName() override; virtual QString displayName() override;
virtual QIcon icon() override; virtual QIcon icon() override;
virtual QString id() override; virtual QString id() override;
virtual bool apply(); virtual bool apply();
virtual QString helpPage() override { return "Instance-settings"; }; virtual QString helpPage() override { return "Instance-settings"; }
private: virtual bool shouldDisplay();
void updateCheckboxStuff();
private slots: private slots:
void on_javaDetectBtn_clicked(); void on_javaDetectBtn_clicked();
@ -54,6 +53,7 @@ private slots:
void loadSettings(); void loadSettings();
private: private:
Ui::InstanceSettingsPage *ui; Ui::InstanceSettingsPage *ui;
BaseInstance *m_instance;
SettingsObject *m_settings; SettingsObject *m_settings;
std::shared_ptr<JavaChecker> checker; std::shared_ptr<JavaChecker> checker;
}; };

View File

@ -54,6 +54,11 @@ QString LegacyJarModPage::displayName()
return tr("Jar Mods"); return tr("Jar Mods");
} }
bool LegacyJarModPage::shouldDisplay()
{
return !m_inst->isRunning();
}
QIcon LegacyJarModPage::icon() QIcon LegacyJarModPage::icon()
{ {
return QIcon::fromTheme("plugin-red"); return QIcon::fromTheme("plugin-red");

View File

@ -38,6 +38,7 @@ public:
virtual QIcon icon(); virtual QIcon icon();
virtual QString id(); virtual QString id();
virtual QString helpPage() override { return "Legacy-jar-mods"; }; virtual QString helpPage() override { return "Legacy-jar-mods"; };
virtual bool shouldDisplay();
private private
slots: slots:

View File

@ -1,4 +1,5 @@
#include "LegacyUpgradePage.h" #include "LegacyUpgradePage.h"
#include <logic/LegacyInstance.h>
#include "ui_LegacyUpgradePage.h" #include "ui_LegacyUpgradePage.h"
QString LegacyUpgradePage::displayName() QString LegacyUpgradePage::displayName()
@ -31,3 +32,8 @@ void LegacyUpgradePage::on_upgradeButton_clicked()
{ {
// now what? // now what?
} }
bool LegacyUpgradePage::shouldDisplay()
{
return !m_inst->isRunning();
}

View File

@ -37,6 +37,7 @@ public:
virtual QIcon icon() override; virtual QIcon icon() override;
virtual QString id() override; virtual QString id() override;
virtual QString helpPage() override { return "Legacy-upgrade"; }; virtual QString helpPage() override { return "Legacy-upgrade"; };
virtual bool shouldDisplay();
private private
slots: slots:
void on_upgradeButton_clicked(); void on_upgradeButton_clicked();

137
gui/pages/LogPage.cpp Normal file
View File

@ -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 &paragraph : 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();
}
}

72
gui/pages/LogPage.h Normal file
View File

@ -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;
};

76
gui/pages/LogPage.ui Normal file
View File

@ -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>

View File

@ -48,11 +48,12 @@ QString ModFolderPage::id()
return m_id; return m_id;
} }
ModFolderPage::ModFolderPage(std::shared_ptr<ModList> mods, QString id, QString iconName, ModFolderPage::ModFolderPage(BaseInstance * inst, std::shared_ptr<ModList> mods, QString id, QString iconName,
QString displayName, QString helpPage, QWidget *parent) QString displayName, QString helpPage, QWidget *parent)
: QWidget(parent), ui(new Ui::ModFolderPage) : QWidget(parent), ui(new Ui::ModFolderPage)
{ {
ui->setupUi(this); ui->setupUi(this);
m_inst = inst;
m_mods = mods; m_mods = mods;
m_id = id; m_id = id;
m_displayName = displayName; m_displayName = displayName;
@ -72,6 +73,13 @@ ModFolderPage::~ModFolderPage()
delete ui; delete ui;
} }
bool ModFolderPage::shouldDisplay()
{
if(m_inst)
return !m_inst->isRunning();
return true;
}
bool ModFolderPage::modListFilter(QKeyEvent *keyEvent) bool ModFolderPage::modListFilter(QKeyEvent *keyEvent)
{ {
switch (keyEvent->key()) switch (keyEvent->key())

View File

@ -32,17 +32,19 @@ class ModFolderPage : public QWidget, public BasePage
Q_OBJECT Q_OBJECT
public: public:
explicit ModFolderPage(std::shared_ptr<ModList> mods, QString id, QString iconName, explicit ModFolderPage(BaseInstance * inst, std::shared_ptr<ModList> mods, QString id, QString iconName,
QString displayName, QString helpPage = "" , QWidget *parent = 0); QString displayName, QString helpPage = "" , QWidget *parent = 0);
virtual ~ModFolderPage(); virtual ~ModFolderPage();
virtual QString displayName() override; virtual QString displayName() override;
virtual QIcon icon() override; virtual QIcon icon() override;
virtual QString id() override; virtual QString id() override;
virtual QString helpPage() override { return m_helpName; }; virtual QString helpPage() override { return m_helpName; };
virtual bool shouldDisplay();
protected: protected:
bool eventFilter(QObject *obj, QEvent *ev); bool eventFilter(QObject *obj, QEvent *ev);
bool modListFilter(QKeyEvent *ev); bool modListFilter(QKeyEvent *ev);
protected:
BaseInstance * m_inst;
private: private:
Ui::ModFolderPage *ui; Ui::ModFolderPage *ui;
std::shared_ptr<ModList> m_mods; std::shared_ptr<ModList> m_mods;

View File

@ -5,10 +5,9 @@ class ResourcePackPage : public ModFolderPage
{ {
public: public:
explicit ResourcePackPage(BaseInstance *instance, QWidget *parent = 0) explicit ResourcePackPage(BaseInstance *instance, QWidget *parent = 0)
: ModFolderPage(instance->resourcePackList(), "resourcepacks", "resourcepacks", : ModFolderPage(instance, instance->resourcePackList(), "resourcepacks", "resourcepacks",
tr("Resource packs"), "Resource-packs", parent) tr("Resource packs"), "Resource-packs", parent)
{ {
m_inst = instance;
} }
virtual ~ResourcePackPage() {}; virtual ~ResourcePackPage() {};
@ -17,6 +16,4 @@ public:
return !m_inst->traits().contains("no-texturepacks") && return !m_inst->traits().contains("no-texturepacks") &&
!m_inst->traits().contains("texturepacks"); !m_inst->traits().contains("texturepacks");
} }
private:
BaseInstance *m_inst;
}; };

View File

@ -18,43 +18,63 @@
#include "logic/screenshots/ImgurAlbumCreation.h" #include "logic/screenshots/ImgurAlbumCreation.h"
#include "logic/tasks/SequentialTask.h" #include "logic/tasks/SequentialTask.h"
class ThumbnailProvider : public QFileIconProvider
{
public:
virtual ~ThumbnailProvider() {};
virtual QIcon icon(const QFileInfo &info) const
{
QImage image(info.absoluteFilePath());
if (image.isNull())
{
return QFileIconProvider::icon(info);
}
QImage thumbnail = image.scaledToWidth(256, Qt::SmoothTransformation);
return QIcon(QPixmap::fromImage(thumbnail));
}
};
class FilterModel : public QIdentityProxyModel class FilterModel : public QIdentityProxyModel
{ {
public:
virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const
{ {
auto model = sourceModel(); auto model = sourceModel();
if(!model) if (!model)
return QVariant(); return QVariant();
QVariant result = sourceModel()->data(mapToSource(proxyIndex), role); if (role == Qt::DisplayRole || role == Qt::EditRole)
if(role == Qt::DisplayRole || role == Qt::EditRole)
{ {
return result.toString().remove(QRegExp("\.png$")); 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;
} }
return result;
} }
virtual bool setData(const QModelIndex &index, const QVariant &value, virtual bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole) int role = Qt::EditRole)
{ {
auto model = sourceModel(); auto model = sourceModel();
if(!model) if (!model)
return false; return false;
if(role != Qt::EditRole) if (role != Qt::EditRole)
return false; return false;
// FIXME: this is a workaround for a bug in QFileSystemModel, where it doesn't // FIXME: this is a workaround for a bug in QFileSystemModel, where it doesn't
// sort after renames // sort after renames
@ -64,22 +84,25 @@ class FilterModel : public QIdentityProxyModel
} }
return model->setData(mapToSource(index), value.toString() + ".png", role); return model->setData(mapToSource(index), value.toString() + ".png", role);
} }
private:
QMap<QString, QIcon> thumbnailCache;
}; };
class CenteredEditingDelegate : public QStyledItemDelegate class CenteredEditingDelegate : public QStyledItemDelegate
{ {
public: public:
explicit CenteredEditingDelegate(QObject *parent = 0) explicit CenteredEditingDelegate(QObject *parent = 0) : QStyledItemDelegate(parent)
: QStyledItemDelegate(parent) {
}
virtual ~CenteredEditingDelegate()
{ {
} }
virtual ~CenteredEditingDelegate() {}
virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const const QModelIndex &index) const
{ {
auto widget = QStyledItemDelegate::createEditor(parent, option, index); auto widget = QStyledItemDelegate::createEditor(parent, option, index);
auto foo = dynamic_cast<QLineEdit *> (widget); auto foo = dynamic_cast<QLineEdit *>(widget);
if(foo) if (foo)
{ {
foo->setAlignment(Qt::AlignHCenter); foo->setAlignment(Qt::AlignHCenter);
foo->setFrame(true); foo->setFrame(true);
@ -111,7 +134,6 @@ ScreenshotsPage::ScreenshotsPage(BaseInstance *instance, QWidget *parent)
m_filterModel.reset(new FilterModel()); m_filterModel.reset(new FilterModel());
m_filterModel->setSourceModel(m_model.get()); m_filterModel->setSourceModel(m_model.get());
m_model->setFilter(QDir::Files | QDir::Writable | QDir::Readable); m_model->setFilter(QDir::Files | QDir::Writable | QDir::Readable);
m_model->setIconProvider(new ThumbnailProvider);
m_model->setReadOnly(false); m_model->setReadOnly(false);
m_folder = PathCombine(instance->minecraftRoot(), "screenshots"); m_folder = PathCombine(instance->minecraftRoot(), "screenshots");
m_valid = ensureFolderPathExists(m_folder); m_valid = ensureFolderPathExists(m_folder);
@ -218,11 +240,11 @@ void ScreenshotsPage::on_deleteBtn_clicked()
QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No); QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No);
std::unique_ptr<QMessageBox> box(mbox); std::unique_ptr<QMessageBox> box(mbox);
if(box->exec() != QMessageBox::Yes) if (box->exec() != QMessageBox::Yes)
return; return;
auto selected = ui->listView->selectionModel()->selectedIndexes(); auto selected = ui->listView->selectionModel()->selectedIndexes();
for(auto item : selected) for (auto item : selected)
{ {
m_model->remove(item); m_model->remove(item);
} }

View File

@ -5,16 +5,13 @@ class TexturePackPage : public ModFolderPage
{ {
public: public:
explicit TexturePackPage(BaseInstance *instance, QWidget *parent = 0) explicit TexturePackPage(BaseInstance *instance, QWidget *parent = 0)
: ModFolderPage(instance->texturePackList(), "texturepacks", "resourcepacks", : ModFolderPage(instance, instance->texturePackList(), "texturepacks", "resourcepacks",
tr("Texture packs"), "Texture-packs", parent) tr("Texture packs"), "Texture-packs", parent)
{ {
m_inst = instance;
} }
virtual ~TexturePackPage() {}; virtual ~TexturePackPage() {};
virtual bool shouldDisplay() override virtual bool shouldDisplay() override
{ {
return m_inst->traits().contains("texturepacks"); return m_inst->traits().contains("texturepacks");
} }
private:
BaseInstance *m_inst;
}; };

View File

@ -66,6 +66,11 @@ QString VersionPage::id()
return "version"; return "version";
} }
bool VersionPage::shouldDisplay()
{
return !m_inst->isRunning();
}
VersionPage::VersionPage(OneSixInstance *inst, QWidget *parent) VersionPage::VersionPage(OneSixInstance *inst, QWidget *parent)
: QWidget(parent), ui(new Ui::VersionPage), m_inst(inst) : QWidget(parent), ui(new Ui::VersionPage), m_inst(inst)
{ {

View File

@ -37,6 +37,7 @@ public:
virtual QIcon icon() override; virtual QIcon icon() override;
virtual QString id() override; virtual QString id() override;
virtual QString helpPage() override { return "Instance-version"; }; virtual QString helpPage() override { return "Instance-version"; };
virtual bool shouldDisplay();
private private
slots: slots:

View File

@ -7,7 +7,7 @@
#include <QRect> #include <QRect>
IconLabel::IconLabel(QWidget *parent, QIcon icon, QSize size) 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); setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
} }

View File

@ -138,6 +138,12 @@ void PageContainer::addButtons(QWidget *buttons)
m_layout->addWidget(buttons, 2, 0, 1, 2); 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) void PageContainer::showPage(int row)
{ {
if(row != -1) if(row != -1)

View File

@ -18,6 +18,7 @@
#include <QModelIndex> #include <QModelIndex>
#include <gui/pages/BasePageProvider.h> #include <gui/pages/BasePageProvider.h>
class QLayout;
class IconLabel; class IconLabel;
class QSortFilterProxyModel; class QSortFilterProxyModel;
class PageModel; class PageModel;
@ -36,6 +37,7 @@ public:
virtual ~PageContainer() {}; virtual ~PageContainer() {};
void addButtons(QWidget * buttons); void addButtons(QWidget * buttons);
void addButtons(QLayout * buttons);
bool requestClose(QCloseEvent *event); bool requestClose(QCloseEvent *event);
private: private:

View File

@ -106,6 +106,18 @@ QString BaseInstance::id() const
return QFileInfo(instanceRoot()).fileName(); return QFileInfo(instanceRoot()).fileName();
} }
bool BaseInstance::isRunning() const
{
I_D(BaseInstance);
return d->m_isRunning;
}
void BaseInstance::setRunning(bool running) const
{
I_D(BaseInstance);
d->m_isRunning = running;
}
QString BaseInstance::instanceType() const QString BaseInstance::instanceType() const
{ {
I_D(BaseInstance); I_D(BaseInstance);

View File

@ -65,6 +65,9 @@ public:
/// be unique. /// be unique.
virtual QString id() const; virtual QString id() const;
virtual void setRunning(bool running) const;
virtual bool isRunning() const;
/// get the type of this instance /// get the type of this instance
QString instanceType() const; QString instanceType() const;

View File

@ -32,4 +32,5 @@ public:
QString m_group; QString m_group;
std::shared_ptr<SettingsObject> m_settings; std::shared_ptr<SettingsObject> m_settings;
QSet<BaseInstance::InstanceFlag> m_flags; QSet<BaseInstance::InstanceFlag> m_flags;
bool m_isRunning = false;
}; };

View File

@ -52,14 +52,14 @@ QList<BasePage *> LegacyInstance::getPages()
QList<BasePage *> values; QList<BasePage *> values;
values.append(new LegacyUpgradePage(this)); values.append(new LegacyUpgradePage(this));
values.append(new LegacyJarModPage(this)); values.append(new LegacyJarModPage(this));
values.append(new ModFolderPage(loaderModList(), "mods", "plugin-blue", tr("Loader mods"), values.append(new ModFolderPage(this, loaderModList(), "mods", "plugin-blue", tr("Loader mods"),
"Loader-mods")); "Loader-mods"));
values.append(new ModFolderPage(coreModList(), "coremods", "plugin-green", tr("Core mods"), values.append(new ModFolderPage(this, coreModList(), "coremods", "plugin-green", tr("Core mods"),
"Core-mods")); "Core-mods"));
values.append(new TexturePackPage(this)); values.append(new TexturePackPage(this));
values.append(new NotesPage(this)); values.append(new NotesPage(this));
values.append(new ScreenshotsPage(this)); values.append(new ScreenshotsPage(this));
values.append(new InstanceSettingsPage(&settings())); values.append(new InstanceSettingsPage(this));
return values; return values;
} }

View File

@ -71,6 +71,9 @@ MinecraftProcess::MinecraftProcess(InstancePtr inst) : m_instance(inst)
connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardOutput, this, connect(&m_prepostlaunchprocess, &QProcess::readyReadStandardOutput, this,
&MinecraftProcess::on_prepost_stdOut); &MinecraftProcess::on_prepost_stdOut);
} }
// a process has been constructed for the instance. It is running from MultiMC POV
m_instance->setRunning(true);
} }
void MinecraftProcess::setWorkdir(QString path) void MinecraftProcess::setWorkdir(QString path)
@ -254,6 +257,8 @@ void MinecraftProcess::finish(int code, ExitStatus status)
// run post-exit // run post-exit
postLaunch(); postLaunch();
m_instance->cleanupAfterRun(); m_instance->cleanupAfterRun();
// no longer running...
m_instance->setRunning(false);
emit ended(m_instance, code, status); emit ended(m_instance, code, status);
} }
@ -304,6 +309,8 @@ bool MinecraftProcess::preLaunch()
m_instance->cleanupAfterRun(); m_instance->cleanupAfterRun();
emit prelaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(), emit prelaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(),
m_prepostlaunchprocess.exitStatus()); m_prepostlaunchprocess.exitStatus());
// not running, failed
m_instance->setRunning(false);
return false; return false;
} }
else else
@ -343,6 +350,8 @@ bool MinecraftProcess::postLaunch()
MessageLevel::Error); MessageLevel::Error);
emit postlaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(), emit postlaunch_failed(m_instance, m_prepostlaunchprocess.exitCode(),
m_prepostlaunchprocess.exitStatus()); m_prepostlaunchprocess.exitStatus());
// not running, failed
m_instance->setRunning(false);
} }
else else
emit log(tr("Post-Launch command ran successfully.\n\n")); emit log(tr("Post-Launch command ran successfully.\n\n"));
@ -460,6 +469,8 @@ void MinecraftProcess::arm()
emit log(tr("Could not launch minecraft!"), MessageLevel::Error); emit log(tr("Could not launch minecraft!"), MessageLevel::Error);
m_instance->cleanupAfterRun(); m_instance->cleanupAfterRun();
emit launch_failed(m_instance); emit launch_failed(m_instance);
// not running, failed
m_instance->setRunning(false);
return; return;
} }
// send the launch script to the launcher part // send the launch script to the launcher part

View File

@ -63,15 +63,15 @@ QList<BasePage *> OneSixInstance::getPages()
{ {
QList<BasePage *> values; QList<BasePage *> values;
values.append(new VersionPage(this)); values.append(new VersionPage(this));
values.append(new ModFolderPage(loaderModList(), "mods", "plugin-blue", tr("Loader mods"), values.append(new ModFolderPage(this, loaderModList(), "mods", "plugin-blue", tr("Loader mods"),
"Loader-mods")); "Loader-mods"));
values.append(new ModFolderPage(coreModList(), "coremods", "plugin-green", tr("Core mods"), values.append(new ModFolderPage(this, coreModList(), "coremods", "plugin-green", tr("Core mods"),
"Core-mods")); "Core-mods"));
values.append(new ResourcePackPage(this)); values.append(new ResourcePackPage(this));
values.append(new TexturePackPage(this)); values.append(new TexturePackPage(this));
values.append(new NotesPage(this)); values.append(new NotesPage(this));
values.append(new ScreenshotsPage(this)); values.append(new ScreenshotsPage(this));
values.append(new InstanceSettingsPage(&settings())); values.append(new InstanceSettingsPage(this));
return values; return values;
} }