From f29e44209eda00d6e8d31c58e3427d4ea4e7ecd5 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Wed, 3 Jan 2018 13:53:01 -1000 Subject: [PATCH] Fixes with in-app console --- hecl-gui/Common.cpp | 6 + hecl-gui/EscapeSequenceParser.cpp | 29 +-- hecl-gui/MainWindow.cpp | 186 ++++++++++----- hecl-gui/MainWindow.hpp | 3 +- hecl-gui/MainWindow.ui | 360 ++++++++++++++---------------- 5 files changed, 322 insertions(+), 262 deletions(-) diff --git a/hecl-gui/Common.cpp b/hecl-gui/Common.cpp index e25b0b897..c6ba5c709 100644 --- a/hecl-gui/Common.cpp +++ b/hecl-gui/Common.cpp @@ -1,5 +1,6 @@ #include "Common.hpp" #include +#include #ifndef _WIN32 #include @@ -134,8 +135,13 @@ QString URDEVersion::fileString(bool withExtension) const VectorISAToString(m_vectorISA)); } +static void HUPHandler(int) {} + void InitializePlatform() { + /* This can happen when terminating hecl - do nothing */ + signal(SIGHUP, HUPHandler); + #if ZEUS_ARCH_X86_64 const_cast(CurArchitecture) = Architecture::X86_64; #elif ZEUS_ARCH_X86 diff --git a/hecl-gui/EscapeSequenceParser.cpp b/hecl-gui/EscapeSequenceParser.cpp index b16667517..0d80a2739 100644 --- a/hecl-gui/EscapeSequenceParser.cpp +++ b/hecl-gui/EscapeSequenceParser.cpp @@ -167,37 +167,38 @@ void ParseEscapeSequence(int attribute, QListIterator& i, QTextCharForm } } } else { + /* Normally dark colors, but forced to light colors for visibility */ switch (colorIndex) { case 0 : { - color = Qt::black; + color = Qt::darkGray; break; } case 1 : { - color = Qt::darkRed; + color = Qt::red; break; } case 2 : { - color = Qt::darkGreen; + color = Qt::green; break; } case 3 : { - color = Qt::darkYellow; + color = Qt::yellow; break; } case 4 : { - color = Qt::darkBlue; + color = Qt::blue; break; } case 5 : { - color = Qt::darkMagenta; + color = Qt::magenta; break; } case 6 : { - color = Qt::darkCyan; + color = Qt::cyan; break; } case 7 : { - color = Qt::lightGray; + color = Qt::white; break; } default : { @@ -448,9 +449,9 @@ void ParseEscapeSequence(int attribute, QListIterator& i, QTextCharForm Q_ASSERT(false); } } - color.setRedF(color.redF() * 0.8); - color.setGreenF(color.greenF() * 0.8); - color.setBlueF(color.blueF() * 0.8); + //color.setRedF(color.redF() * 0.8); + //color.setGreenF(color.greenF() * 0.8); + //color.setBlueF(color.blueF() * 0.8); textCharFormat.setForeground(color); break; } @@ -502,9 +503,9 @@ void ParseEscapeSequence(int attribute, QListIterator& i, QTextCharForm Q_ASSERT(false); } } - color.setRedF(color.redF() * 0.8); - color.setGreenF(color.greenF() * 0.8); - color.setBlueF(color.blueF() * 0.8); + //color.setRedF(color.redF() * 0.8); + //color.setGreenF(color.greenF() * 0.8); + //color.setBlueF(color.blueF() * 0.8); textCharFormat.setBackground(color); break; } diff --git a/hecl-gui/MainWindow.cpp b/hecl-gui/MainWindow.cpp index 605e5a985..6830e5ed0 100644 --- a/hecl-gui/MainWindow.cpp +++ b/hecl-gui/MainWindow.cpp @@ -1,6 +1,7 @@ #include "MainWindow.hpp" #include "ui_MainWindow.h" #include +#include #include "EscapeSequenceParser.hpp" #include "FileDirDialog.hpp" @@ -18,7 +19,6 @@ MainWindow::MainWindow(QWidget *parent) : { m_ui->setupUi(this); m_ui->heclTabs->setCurrentIndex(0); - m_ui->splitter->setSizes({0,100}); m_ui->aboutIcon->setPixmap(QApplication::windowIcon().pixmap(256, 256)); @@ -28,6 +28,7 @@ MainWindow::MainWindow(QWidget *parent) : m_ui->recommendedBinaryLabel->setFont(mFont); mFont.setPointSize(10); m_ui->processOutput->setFont(mFont); + m_cursor = QTextCursor(m_ui->processOutput->document()); m_updateURDEButton = new QPushButton(QStringLiteral("Update URDE"), m_ui->centralwidget); m_ui->gridLayout->addWidget(m_updateURDEButton, 2, 3, 1, 1); @@ -60,15 +61,20 @@ void MainWindow::onExtract() { if (m_path.isEmpty()) return; - QString imgPath = QFileDialog::getOpenFileName(this, QStringLiteral("Extract Image"), {}, + QString imgPath = QFileDialog::getOpenFileName(this, QStringLiteral("Extract Image"), m_path, QStringLiteral("Images (*.iso *.wbfs *.gcm)")); - m_ansiString.clear(); + if (imgPath.isEmpty()) + return; + m_ui->processOutput->clear(); m_heclProc.close(); m_heclProc.terminate(); m_heclProc.setProcessChannelMode(QProcess::ProcessChannelMode::MergedChannels); m_heclProc.setWorkingDirectory(m_path); - m_heclProc.start(m_heclPath, {"extract", "-y", imgPath, m_path}); + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + env.insert("TERM", "xterm-color"); + m_heclProc.setProcessEnvironment(env); + m_heclProc.start(m_heclPath, {"extract", "-y", "-o", m_path, imgPath}); m_ui->heclTabs->setCurrentIndex(0); @@ -93,12 +99,14 @@ void MainWindow::onPackage() { if (m_path.isEmpty()) return; - m_ansiString.clear(); m_ui->processOutput->clear(); m_heclProc.close(); m_heclProc.terminate(); m_heclProc.setProcessChannelMode(QProcess::ProcessChannelMode::MergedChannels); m_heclProc.setWorkingDirectory(m_path); + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + env.insert("TERM", "xterm-color"); + m_heclProc.setProcessEnvironment(env); m_heclProc.start(m_heclPath, {"package", "-y"}); m_ui->heclTabs->setCurrentIndex(0); @@ -124,12 +132,14 @@ void MainWindow::onLaunch() { if (m_path.isEmpty()) return; - m_ansiString.clear(); m_ui->processOutput->clear(); m_heclProc.close(); m_heclProc.terminate(); m_heclProc.setProcessChannelMode(QProcess::ProcessChannelMode::MergedChannels); m_heclProc.setWorkingDirectory(m_path); + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + env.insert("TERM", "xterm-color"); + m_heclProc.setProcessEnvironment(env); m_heclProc.start(m_urdePath, {"--no-shader-warmup", m_path + "/out"}); m_ui->heclTabs->setCurrentIndex(0); @@ -148,6 +158,8 @@ void MainWindow::onLaunchFinished(int returnCode) void MainWindow::doHECLTerminate() { m_heclProc.terminate(); + m_cursor.movePosition(QTextCursor::End); + m_cursor.insertText("\n"); } void MainWindow::onReturnPressed() @@ -235,14 +247,22 @@ void MainWindow::disableOperations() m_ui->extractBtn->setEnabled(false); m_ui->packageBtn->setEnabled(false); m_ui->launchBtn->setEnabled(false); + m_ui->pathEdit->setEnabled(false); + m_ui->browseBtn->setEnabled(false); + m_ui->downloadButton->setEnabled(false); } void MainWindow::enableOperations() { disableOperations(); + m_ui->pathEdit->setEnabled(true); + m_ui->browseBtn->setEnabled(true); + if (m_path.isEmpty()) return; + m_ui->downloadButton->setEnabled(true); + m_ui->extractBtn->setText(QStringLiteral("Extract")); m_ui->packageBtn->setText(QStringLiteral("Package")); m_ui->launchBtn->setText(QStringLiteral("Launch")); @@ -348,10 +368,29 @@ bool MainWindow::checkDownloadedBinary() void MainWindow::setPath(const QString& path) { - m_path = path; + QFileInfo finfo(path); + QString usePath = finfo.absoluteFilePath(); + if (!finfo.exists()) + { + if (QMessageBox::question(this, QStringLiteral("Make Directory"), + QStringLiteral("%1 does not exist. Create it now?").arg(usePath)) == QMessageBox::Yes) + QDir().mkpath(usePath); + else + usePath = QString(); + } + + if (!usePath.isEmpty() && !finfo.isDir()) + { + QMessageBox::warning(this, QStringLiteral("Directory Error"), + QStringLiteral("%1 is not a directory").arg(usePath), + QMessageBox::Ok, QMessageBox::NoButton); + usePath = QString(); + } + + m_path = usePath; m_settings.setValue(QStringLiteral("working_dir"), m_path); - if (!path.isEmpty()) + if (!m_path.isEmpty()) { m_ui->pathEdit->setText(m_path); m_ui->downloadButton->setToolTip(QString()); @@ -373,8 +412,7 @@ void MainWindow::initSlots() m_heclProc.setEnvironment(QProcessEnvironment::systemEnvironment().toStringList() + QStringList("ConEmuANSI=ON")); #endif connect(&m_heclProc, &QProcess::readyRead, [=](){ - m_ansiString = m_heclProc.readAll(); - setTextTermFormatting(m_ansiString); + setTextTermFormatting(m_heclProc.readAll()); m_ui->processOutput->ensureCursorVisible(); }); @@ -384,15 +422,15 @@ void MainWindow::initSlots() connect(m_ui->browseBtn, &QPushButton::clicked, [=]() { FileDirDialog dialog(this); + dialog.setDirectory(m_path); dialog.setWindowTitle("Select Working Directory"); - int res = dialog.exec();//QFileDialog::getOpenFileName(this, "Select ISO or Directory"); + int res = dialog.exec(); if (res == QFileDialog::Rejected) return; if (dialog.selectedFiles().size() <= 0) return; - /* TODO: Add beacon detection */ setPath(dialog.selectedFiles().at(0)); }); @@ -401,32 +439,74 @@ void MainWindow::initSlots() static void ReturnInsert(QTextCursor& cur, const QString& text) { - QStringList list = text.split('\r'); - if (!list.front().isEmpty()) - cur.insertText(list.front()); - if (list.size() > 1) + auto DoLine = [&](const QString& line) { - for (auto it = list.begin() + 1; it != list.end(); ++it) + auto DoReturn = [&](const QString& ret) { - cur.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); - if (!it->isEmpty()) - cur.insertText(*it); + if (!ret.isEmpty()) + { + cur.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, ret.size()); + cur.insertText(ret); + } + }; + QStringList list = line.split('\r'); + DoReturn(list.front()); + if (list.size() > 1) + { + for (auto it = list.begin() + 1; it != list.end(); ++it) + { + cur.movePosition(QTextCursor::StartOfLine); + DoReturn(*it); + } + } + }; + + QStringList lineSplit = text.split('\n'); + DoLine(lineSplit.front()); + if (lineSplit.size() > 1) + { + for (auto it = lineSplit.begin() + 1; it != lineSplit.end(); ++it) + { + cur.movePosition(QTextCursor::EndOfLine); + cur.insertText("\n"); + DoLine(*it); } } } static void ReturnInsert(QTextCursor& cur, const QString& text, const QTextCharFormat& format) { - QStringList list = text.split('\r'); - if (!list.front().isEmpty()) - cur.insertText(list.front(), format); - if (list.size() > 1) + auto DoLine = [&](const QString& line) { - for (auto it = list.begin() + 1; it != list.end(); ++it) + auto DoReturn = [&](const QString& ret) { - cur.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); - if (!it->isEmpty()) - cur.insertText(*it, format); + if (!ret.isEmpty()) + { + cur.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, ret.size()); + cur.insertText(ret, format); + } + }; + QStringList list = line.split('\r'); + DoReturn(list.front()); + if (list.size() > 1) + { + for (auto it = list.begin() + 1; it != list.end(); ++it) + { + cur.movePosition(QTextCursor::StartOfLine); + DoReturn(*it); + } + } + }; + + QStringList lineSplit = text.split('\n'); + DoLine(lineSplit.front()); + if (lineSplit.size() > 1) + { + for (auto it = lineSplit.begin() + 1; it != lineSplit.end(); ++it) + { + cur.movePosition(QTextCursor::EndOfLine); + cur.insertText("\n", format); + DoLine(*it); } } } @@ -435,36 +515,32 @@ void MainWindow::setTextTermFormatting(const QString& text) { m_inContinueNote = false; - QTextDocument* document = m_ui->processOutput->document(); - QRegExp const escapeSequenceExpression(R"(\x1B\[([\d;]+)m)"); - QTextCursor cursor(document); - cursor.movePosition(QTextCursor::End); - QTextCharFormat defaultTextCharFormat = cursor.charFormat(); - cursor.beginEditBlock(); + QRegExp const escapeSequenceExpression(R"(\x1B\[([\d;\?]+)([mlh]))"); + QTextCharFormat defaultTextCharFormat = m_cursor.charFormat(); int offset = escapeSequenceExpression.indexIn(text); - ReturnInsert(cursor, text.mid(0, offset)); + ReturnInsert(m_cursor, text.mid(0, offset)); QTextCharFormat textCharFormat = defaultTextCharFormat; - while (!(offset < 0)) { + while (offset >= 0) { int previousOffset = offset + escapeSequenceExpression.matchedLength(); - QStringList capturedTexts = escapeSequenceExpression.capturedTexts().back().split(';'); - QListIterator< QString > i(capturedTexts); - while (i.hasNext()) { - bool ok = false; - int attribute = i.next().toInt(&ok); - Q_ASSERT(ok); - ParseEscapeSequence(attribute, i, textCharFormat, defaultTextCharFormat); + if (escapeSequenceExpression.capturedTexts()[2] == "m") + { + QStringList capturedTexts = escapeSequenceExpression.capturedTexts()[1].split(';'); + QListIterator i(capturedTexts); + while (i.hasNext()) { + bool ok = false; + int attribute = i.next().toInt(&ok); + Q_ASSERT(ok); + ParseEscapeSequence(attribute, i, textCharFormat, defaultTextCharFormat); + } } offset = escapeSequenceExpression.indexIn(text, previousOffset); if (offset < 0) { - ReturnInsert(cursor, text.mid(previousOffset), textCharFormat); + ReturnInsert(m_cursor, text.mid(previousOffset), textCharFormat); } else { - ReturnInsert(cursor, text.mid(previousOffset, offset - previousOffset), textCharFormat); + ReturnInsert(m_cursor, text.mid(previousOffset, offset - previousOffset), textCharFormat); } } - cursor.setCharFormat(defaultTextCharFormat); - cursor.endEditBlock(); - cursor.movePosition(QTextCursor::End); - m_ui->processOutput->setTextCursor(cursor); + m_cursor.setCharFormat(defaultTextCharFormat); } void MainWindow::insertContinueNote(const QString& text) @@ -473,14 +549,8 @@ void MainWindow::insertContinueNote(const QString& text) return; m_inContinueNote = true; - QTextDocument* document = m_ui->processOutput->document(); - QTextCursor cursor(document); - cursor.movePosition(QTextCursor::End); - QTextCharFormat textCharFormat = cursor.charFormat(); + m_cursor.movePosition(QTextCursor::End); + QTextCharFormat textCharFormat = m_cursor.charFormat(); textCharFormat.setForeground(QColor(0,255,0)); - cursor.beginEditBlock(); - cursor.insertText(text + '\n', textCharFormat); - cursor.endEditBlock(); - cursor.movePosition(QTextCursor::End); - m_ui->processOutput->setTextCursor(cursor); + m_cursor.insertText(text + '\n', textCharFormat); } diff --git a/hecl-gui/MainWindow.hpp b/hecl-gui/MainWindow.hpp index 4e2d7fffa..90b8e3d7a 100644 --- a/hecl-gui/MainWindow.hpp +++ b/hecl-gui/MainWindow.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include "DownloadManager.hpp" #include "Common.hpp" @@ -18,7 +19,7 @@ class MainWindow : public QMainWindow { Q_OBJECT Ui::MainWindow* m_ui; - QString m_ansiString; + QTextCursor m_cursor; QString m_path; QString m_urdePath; QString m_heclPath; diff --git a/hecl-gui/MainWindow.ui b/hecl-gui/MainWindow.ui index 519cbfa5e..4dbba39fb 100644 --- a/hecl-gui/MainWindow.ui +++ b/hecl-gui/MainWindow.ui @@ -34,204 +34,88 @@ - - - - false - - - &Extract - - - - - - - false - - - &Package - - - - - - - false - - - &Launch - - - - - - - Qt::Horizontal - - - - 167 - 20 - - - - - - - - - - - 0 - 0 - - - - Wor&king Directory: - - - pathEdit - - - - - - - - 0 - 0 - - - - - 1 - 0 - - - - - - - - - 0 - 0 - - - - - 32 - 16777215 - - - - ... - - - - - - 2 + 0 Data - - - 2 - - - 2 - - - 2 - - - 2 - - - - - Qt::Vertical + + + + + + + + + + 255 + 255 + 255 + + + + + + + 29 + 29 + 29 + + + + + + + + + 255 + 255 + 255 + + + + + + + 29 + 29 + 29 + + + + + + + + + 120 + 120 + 120 + + + + + + + 240 + 240 + 240 + + + + + + + + true + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - - - 120 - 120 - 120 - - - - - - - 240 - 240 - 240 - - - - - - - - true - - - Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - @@ -776,6 +660,104 @@ p, li { white-space: pre-wrap; } + + + + false + + + &Extract + + + + + + + false + + + &Package + + + + + + + false + + + &Launch + + + + + + + Qt::Horizontal + + + + 167 + 20 + + + + + + + + + + + 0 + 0 + + + + Wor&king Directory: + + + pathEdit + + + + + + + + 0 + 0 + + + + + 1 + 0 + + + + + + + + + 0 + 0 + + + + + 32 + 16777215 + + + + ... + + + + +