From 3a173648e789f30b2843241ee38e694d16e10358 Mon Sep 17 00:00:00 2001 From: Orochimarufan Date: Fri, 22 Feb 2013 18:18:23 +0100 Subject: [PATCH] Implement ConsoleWindow --- CMakeLists.txt | 3 ++ data/minecraftprocess.cpp | 38 ++++++++++++++++++-- data/minecraftprocess.h | 6 +++- gui/consolewindow.cpp | 73 +++++++++++++++++++++++++++++++++++++++ gui/consolewindow.h | 69 ++++++++++++++++++++++++++++++++++++ gui/consolewindow.ui | 66 +++++++++++++++++++++++++++++++++++ main.cpp | 13 ++++--- 7 files changed, 257 insertions(+), 11 deletions(-) create mode 100644 gui/consolewindow.cpp create mode 100644 gui/consolewindow.h create mode 100644 gui/consolewindow.ui diff --git a/CMakeLists.txt b/CMakeLists.txt index 03f1f514..070dcc15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -165,6 +165,7 @@ gui/logindialog.h gui/taskdialog.h gui/browserdialog.h gui/aboutdialog.h +gui/consolewindow.h data/version.h data/userinfo.h @@ -208,6 +209,7 @@ gui/logindialog.cpp gui/taskdialog.cpp gui/browserdialog.cpp gui/aboutdialog.cpp +gui/consolewindow.cpp java/javautils.cpp java/annotations.cpp @@ -228,6 +230,7 @@ gui/logindialog.ui gui/taskdialog.ui gui/browserdialog.ui gui/aboutdialog.ui +gui/consolewindow.ui ) diff --git a/data/minecraftprocess.cpp b/data/minecraftprocess.cpp index 4cbe7208..d08b767c 100644 --- a/data/minecraftprocess.cpp +++ b/data/minecraftprocess.cpp @@ -117,9 +117,33 @@ MinecraftProcess::MinecraftProcess(InstancePtr inst, QString user, QString sessi this->setWorkingDirectory(mcDir.absolutePath()); m_prepostlaunchprocess.setWorkingDirectory(mcDir.absolutePath()); - //TODO: do console redirection + // std channels + connect(this, SIGNAL(readyReadStandardError()), SLOT(on_stdErr())); + connect(this, SIGNAL(readyReadStandardOutput()), SLOT(on_stdOut())); } +// console window +void MinecraftProcess::on_stdErr() +{ + if (m_console != nullptr) + m_console->write(readAllStandardError(), ConsoleWindow::ERROR); +} + +void MinecraftProcess::on_stdOut() +{ + if (m_console != nullptr) + m_console->write(readAllStandardOutput(), ConsoleWindow::DEFAULT); +} + +void MinecraftProcess::log(QString text) +{ + if (m_console != nullptr) + m_console->write(text); + else + qDebug(qPrintable(text)); +} + +// exit handler void MinecraftProcess::finish(int code, ExitStatus status) { if (status != NormalExit) @@ -127,6 +151,8 @@ void MinecraftProcess::finish(int code, ExitStatus status) //TODO: error handling } + log("Minecraft exited."); + m_prepostlaunchprocess.processEnvironment().insert("INST_EXITCODE", QString(code)); // run post-exit @@ -140,6 +166,9 @@ void MinecraftProcess::finish(int code, ExitStatus status) } } + if (m_console != nullptr) + m_console->setMayClose(true); + emit ended(); } @@ -162,14 +191,17 @@ void MinecraftProcess::launch() genArgs(); - qDebug("Minecraft folder is: '%s'", qPrintable(workingDirectory())); - qDebug("Instance launched with arguments: '%s'", qPrintable(m_arguments.join("' '"))); + log(QString("Minecraft folder is: '%1'").arg(workingDirectory())); + log(QString("Instance launched with arguments: '%1'").arg(m_arguments.join("' '"))); start(m_instance->getJavaPath(), m_arguments); if (!waitForStarted()) { //TODO: error handling } + + if(m_console != nullptr) + m_console->setMayClose(false); } void MinecraftProcess::genArgs() diff --git a/data/minecraftprocess.h b/data/minecraftprocess.h index 99a3bed6..bede9486 100644 --- a/data/minecraftprocess.h +++ b/data/minecraftprocess.h @@ -19,7 +19,7 @@ #include -class ConsoleWindow; +#include "gui/consolewindow.h" #include "instance.h" @@ -86,9 +86,13 @@ protected: QStringList m_arguments; void genArgs(); + void log(QString text); protected slots: void finish(int, QProcess::ExitStatus status); + void on_stdErr(); + void on_stdOut(); + }; #endif // MINECRAFTPROCESS_H diff --git a/gui/consolewindow.cpp b/gui/consolewindow.cpp new file mode 100644 index 00000000..1d84fe04 --- /dev/null +++ b/gui/consolewindow.cpp @@ -0,0 +1,73 @@ +#include "consolewindow.h" +#include "ui_consolewindow.h" + +#include + +ConsoleWindow::ConsoleWindow(QWidget *parent) : + QDialog(parent), + ui(new Ui::ConsoleWindow), + m_mayclose(true) +{ + ui->setupUi(this); +} + +ConsoleWindow::~ConsoleWindow() +{ + delete ui; +} + +void ConsoleWindow::writeColor(QString text, const char *color) +{ + // append a paragraph + if (color != nullptr) + ui->text->appendHtml(QString("%2").arg(color).arg(text)); + else + ui->text->appendPlainText(text); + // scroll down + QScrollBar *bar = ui->text->verticalScrollBar(); + bar->setValue(bar->maximum()); +} + +void ConsoleWindow::write(QString data, WriteMode mode) +{ + if (data.endsWith('\n')) + data = data.left(data.length()-1); + QStringList paragraphs = data.split('\n'); + QListIterator iter(paragraphs); + if (mode == MULTIMC) + while(iter.hasNext()) + writeColor(iter.next(), "blue"); + else if (mode == ERROR) + while(iter.hasNext()) + writeColor(iter.next(), "red"); + else + while(iter.hasNext()) + writeColor(iter.next()); +} + +void ConsoleWindow::clear() +{ + ui->text->clear(); +} + +void ConsoleWindow::on_closeButton_clicked() +{ + close(); +} + +void ConsoleWindow::setMayClose(bool mayclose) +{ + m_mayclose = mayclose; + if (mayclose) + ui->closeButton->setEnabled(true); + else + ui->closeButton->setEnabled(false); +} + +void ConsoleWindow::closeEvent(QCloseEvent * event) +{ + if(!m_mayclose) + event->ignore(); + else + QDialog::closeEvent(event); +} diff --git a/gui/consolewindow.h b/gui/consolewindow.h new file mode 100644 index 00000000..1d322afb --- /dev/null +++ b/gui/consolewindow.h @@ -0,0 +1,69 @@ +#ifndef CONSOLEWINDOW_H +#define CONSOLEWINDOW_H + +#include + +namespace Ui { +class ConsoleWindow; +} + +class ConsoleWindow : public QDialog +{ + Q_OBJECT + +public: + /** + * @brief The WriteMode enum + * defines how stuff is displayed + */ + enum WriteMode { + DEFAULT, + ERROR, + MULTIMC + }; + + explicit ConsoleWindow(QWidget *parent = 0); + ~ConsoleWindow(); + + /** + * @brief specify if the window is allowed to close + * @param mayclose + * used to keep it alive while MC runs + */ + void setMayClose(bool mayclose); + +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, WriteMode mode=MULTIMC); + + /** + * @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 data, const char *color=nullptr); + + /** + * @brief clear the text widget + */ + void clear(); + +private slots: + void on_closeButton_clicked(); + +protected: + void closeEvent(QCloseEvent *); + +private: + Ui::ConsoleWindow *ui; + bool m_mayclose; +}; + +#endif // CONSOLEWINDOW_H diff --git a/gui/consolewindow.ui b/gui/consolewindow.ui new file mode 100644 index 00000000..f8c87aa0 --- /dev/null +++ b/gui/consolewindow.ui @@ -0,0 +1,66 @@ + + + ConsoleWindow + + + + 0 + 0 + 600 + 400 + + + + MultiMC Console + + + + + + + 10 + + + + false + + + true + + + + + + false + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Close + + + + + + + + + + diff --git a/main.cpp b/main.cpp index 4f072b38..5cac6ab0 100644 --- a/main.cpp +++ b/main.cpp @@ -24,6 +24,7 @@ #include "gui/mainwindow.h" #include "gui/logindialog.h" #include "gui/taskdialog.h" +#include "gui/consolewindow.h" #include "instancelist.h" #include "appsettings.h" @@ -49,6 +50,7 @@ private: QString instId; InstancePtr instance; MinecraftProcess *proc; + ConsoleWindow *console; public: InstanceLauncher(QString instId) : QObject(), instances(settings->getInstanceDir()) { @@ -82,15 +84,12 @@ private slots: void onLoginComplete(LoginResponse response) { // TODO: console - proc = new MinecraftProcess(instance, response.getUsername(), response.getSessionID(), nullptr); + console = new ConsoleWindow(); + proc = new MinecraftProcess(instance, response.getUsername(), response.getSessionID(), console); + //if (instance->getShowConsole()) + console->show(); connect(proc, SIGNAL(ended()), SLOT(onTerminated())); proc->launch(); - /*if (proc->pid() == 0) - { - std::cout << "Could not start instance." << std::endl; - QApplication::instance()->quit(); - return; - }*/ } void doLogin(const QString &errorMsg)