mirror of https://github.com/AxioDL/metaforce.git
Initial implementation
This commit is contained in:
parent
6a6bed1e79
commit
479a44910b
|
@ -0,0 +1,14 @@
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
|
||||||
|
find_package(Qt5Widgets)
|
||||||
|
|
||||||
|
add_executable(hecl-gui
|
||||||
|
MainWindow.ui MainWindow.hpp MainWindow.cpp
|
||||||
|
FileDirDialog.hpp FileDirDialog.cpp
|
||||||
|
main.cpp)
|
||||||
|
|
||||||
|
target_link_libraries(hecl-gui ${Qt5Widgets_LIBRARIES})
|
|
@ -0,0 +1,68 @@
|
||||||
|
#include "FileDirDialog.hpp"
|
||||||
|
#include <QModelIndex>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QTreeView>
|
||||||
|
#include <QListView>
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
FileDirDialog::FileDirDialog(QWidget *parent)
|
||||||
|
: QFileDialog(parent)
|
||||||
|
{
|
||||||
|
m_selectedFiles.clear();
|
||||||
|
|
||||||
|
this->setOption(QFileDialog::DontUseNativeDialog, true);
|
||||||
|
this->setFileMode(QFileDialog::Directory);
|
||||||
|
QList<QPushButton*> btns = this->findChildren<QPushButton*>();
|
||||||
|
for (int i = 0; i < btns.size(); ++i)
|
||||||
|
{
|
||||||
|
QString text = btns[i]->text();
|
||||||
|
if (text.toLower().contains("open") || text.toLower().contains("choose"))
|
||||||
|
{
|
||||||
|
m_btnOpen = btns[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_btnOpen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_btnOpen->installEventFilter(this);
|
||||||
|
m_btnOpen->disconnect(SIGNAL(clicked()));
|
||||||
|
connect(m_btnOpen, SIGNAL(clicked()), this, SLOT(chooseClicked()));
|
||||||
|
|
||||||
|
|
||||||
|
m_listView = findChild<QListView*>("listView");
|
||||||
|
if (m_listView) {
|
||||||
|
m_listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_treeView = findChild<QTreeView*>();
|
||||||
|
if (m_treeView)
|
||||||
|
m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileDirDialog::eventFilter( QObject* watched, QEvent* event )
|
||||||
|
{
|
||||||
|
QPushButton *btn = qobject_cast<QPushButton*>(watched);
|
||||||
|
if (btn && !btn->isEnabled() && event->type()==QEvent::EnabledChange)
|
||||||
|
btn->setEnabled(true);
|
||||||
|
|
||||||
|
return QWidget::eventFilter(watched, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FileDirDialog::chooseClicked()
|
||||||
|
{
|
||||||
|
QModelIndexList indexList = m_listView->selectionModel()->selectedIndexes();
|
||||||
|
foreach (QModelIndex index, indexList)
|
||||||
|
if (index.column( )== 0)
|
||||||
|
m_selectedFiles.append(this->directory().absolutePath() + "/" + index.data().toString());
|
||||||
|
|
||||||
|
QDialog::accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList FileDirDialog::selectedFiles()
|
||||||
|
{
|
||||||
|
return m_selectedFiles;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef FILEDIRDIALOG_HPP
|
||||||
|
#define FILEDIRDIALOG_HPP
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QTreeWidget>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
class QPushButton;
|
||||||
|
class QTreeView;
|
||||||
|
class QListView;
|
||||||
|
|
||||||
|
class FileDirDialog : public QFileDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
QListView* m_listView = nullptr;
|
||||||
|
QTreeView* m_treeView = nullptr;
|
||||||
|
QPushButton* m_btnOpen = nullptr;
|
||||||
|
QStringList m_selectedFiles;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void chooseClicked();
|
||||||
|
public:
|
||||||
|
FileDirDialog(QWidget* parent = nullptr);
|
||||||
|
QStringList selectedFiles();
|
||||||
|
bool eventFilter(QObject* watched, QEvent* event);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FILEDIRDIALOG_HPP
|
|
@ -0,0 +1,640 @@
|
||||||
|
#include "MainWindow.hpp"
|
||||||
|
#include "ui_MainWindow.h"
|
||||||
|
#include <QFontDatabase>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QDebug>
|
||||||
|
#include "FileDirDialog.hpp"
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent) :
|
||||||
|
QMainWindow(parent),
|
||||||
|
m_ui(new Ui::MainWindow)
|
||||||
|
, m_heclProc(this)
|
||||||
|
{
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
m_ui->heclTabs->setCurrentIndex(0);
|
||||||
|
m_ui->splitter->setSizes({0,-1});
|
||||||
|
initSlots();
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow()
|
||||||
|
{
|
||||||
|
m_heclProc.close();
|
||||||
|
m_heclProc.terminate();
|
||||||
|
delete m_ui;
|
||||||
|
}
|
||||||
|
/* TODO: more complete Vt102 emulation */
|
||||||
|
// based on information: http://en.m.wikipedia.org/wiki/ANSI_escape_code http://misc.flogisoft.com/bash/tip_colors_and_formatting http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||||
|
void MainWindow::parseEscapeSequence(int attribute, QListIterator< QString > & i, QTextCharFormat & textCharFormat, QTextCharFormat const & defaultTextCharFormat)
|
||||||
|
{
|
||||||
|
switch (attribute) {
|
||||||
|
case 0 : { // Normal/Default (reset all attributes)
|
||||||
|
textCharFormat = defaultTextCharFormat;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1 : { // Bold/Bright (bold or increased intensity)
|
||||||
|
textCharFormat.setFontWeight(QFont::Bold);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2 : { // Dim/Faint (decreased intensity)
|
||||||
|
textCharFormat.setFontWeight(QFont::Light);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3 : { // Italicized (italic on)
|
||||||
|
textCharFormat.setFontItalic(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4 : { // Underscore (single underlined)
|
||||||
|
textCharFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
|
||||||
|
textCharFormat.setFontUnderline(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5 : { // Blink (slow, appears as Bold)
|
||||||
|
textCharFormat.setFontWeight(QFont::Bold);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 6 : { // Blink (rapid, appears as very Bold)
|
||||||
|
textCharFormat.setFontWeight(QFont::Black);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7 : { // Reverse/Inverse (swap foreground and background)
|
||||||
|
QBrush foregroundBrush = textCharFormat.foreground();
|
||||||
|
textCharFormat.setForeground(textCharFormat.background());
|
||||||
|
textCharFormat.setBackground(foregroundBrush);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8 : { // Concealed/Hidden/Invisible (usefull for passwords)
|
||||||
|
textCharFormat.setForeground(textCharFormat.background());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 9 : { // Crossed-out characters
|
||||||
|
textCharFormat.setFontStrikeOut(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 10 : { // Primary (default) font
|
||||||
|
textCharFormat.setFont(defaultTextCharFormat.font());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 11:
|
||||||
|
case 12:
|
||||||
|
case 13:
|
||||||
|
case 14:
|
||||||
|
case 15:
|
||||||
|
case 16:
|
||||||
|
case 17:
|
||||||
|
case 18:
|
||||||
|
case 19: {
|
||||||
|
QFontDatabase fontDatabase;
|
||||||
|
QString fontFamily = textCharFormat.fontFamily();
|
||||||
|
QStringList fontStyles = fontDatabase.styles(fontFamily);
|
||||||
|
int fontStyleIndex = attribute - 11;
|
||||||
|
if (fontStyleIndex < fontStyles.length()) {
|
||||||
|
textCharFormat.setFont(fontDatabase.font(fontFamily, fontStyles.at(fontStyleIndex), textCharFormat.font().pointSize()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 20 : { // Fraktur (unsupported)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 21 : { // Set Bold off
|
||||||
|
textCharFormat.setFontWeight(QFont::Normal);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 22 : { // Set Dim off
|
||||||
|
textCharFormat.setFontWeight(QFont::Normal);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 23 : { // Unset italic and unset fraktur
|
||||||
|
textCharFormat.setFontItalic(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 24 : { // Unset underlining
|
||||||
|
textCharFormat.setUnderlineStyle(QTextCharFormat::NoUnderline);
|
||||||
|
textCharFormat.setFontUnderline(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 25 : { // Unset Blink/Bold
|
||||||
|
textCharFormat.setFontWeight(QFont::Normal);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 26 : { // Reserved
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 27 : { // Positive (non-inverted)
|
||||||
|
QBrush backgroundBrush = textCharFormat.background();
|
||||||
|
textCharFormat.setBackground(textCharFormat.foreground());
|
||||||
|
textCharFormat.setForeground(backgroundBrush);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 28 : {
|
||||||
|
textCharFormat.setForeground(defaultTextCharFormat.foreground());
|
||||||
|
textCharFormat.setBackground(defaultTextCharFormat.background());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 29 : {
|
||||||
|
textCharFormat.setUnderlineStyle(QTextCharFormat::NoUnderline);
|
||||||
|
textCharFormat.setFontUnderline(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 30:
|
||||||
|
case 31:
|
||||||
|
case 32:
|
||||||
|
case 33:
|
||||||
|
case 34:
|
||||||
|
case 35:
|
||||||
|
case 36:
|
||||||
|
case 37:
|
||||||
|
{
|
||||||
|
int colorIndex = attribute - 30;
|
||||||
|
QColor color;
|
||||||
|
if (QFont::Normal < textCharFormat.fontWeight()) {
|
||||||
|
switch (colorIndex) {
|
||||||
|
case 0 : {
|
||||||
|
color = Qt::darkGray;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1 : {
|
||||||
|
color = Qt::red;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2 : {
|
||||||
|
color = Qt::green;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3 : {
|
||||||
|
color = Qt::yellow;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4 : {
|
||||||
|
color = Qt::blue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5 : {
|
||||||
|
color = Qt::magenta;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 6 : {
|
||||||
|
color = Qt::cyan;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7 : {
|
||||||
|
color = Qt::white;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
Q_ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (colorIndex) {
|
||||||
|
case 0 : {
|
||||||
|
color = Qt::black;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1 : {
|
||||||
|
color = Qt::darkRed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2 : {
|
||||||
|
color = Qt::darkGreen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3 : {
|
||||||
|
color = Qt::darkYellow;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4 : {
|
||||||
|
color = Qt::darkBlue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5 : {
|
||||||
|
color = Qt::darkMagenta;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 6 : {
|
||||||
|
color = Qt::darkCyan;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7 : {
|
||||||
|
color = Qt::lightGray;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
Q_ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
textCharFormat.setForeground(color);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 38 : {
|
||||||
|
if (i.hasNext()) {
|
||||||
|
bool ok = false;
|
||||||
|
int selector = i.next().toInt(&ok);
|
||||||
|
Q_ASSERT(ok);
|
||||||
|
QColor color;
|
||||||
|
switch (selector) {
|
||||||
|
case 2 : {
|
||||||
|
if (!i.hasNext()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int red = i.next().toInt(&ok);
|
||||||
|
Q_ASSERT(ok);
|
||||||
|
if (!i.hasNext()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int green = i.next().toInt(&ok);
|
||||||
|
Q_ASSERT(ok);
|
||||||
|
if (!i.hasNext()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int blue = i.next().toInt(&ok);
|
||||||
|
Q_ASSERT(ok);
|
||||||
|
color.setRgb(red, green, blue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5 :
|
||||||
|
{
|
||||||
|
if (!i.hasNext()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int index = i.next().toInt(&ok);
|
||||||
|
Q_ASSERT(ok);
|
||||||
|
if (index >= 0 && index <= 0x07)
|
||||||
|
{ // 0x00-0x07: standard colors (as in ESC [ 30..37 m)
|
||||||
|
return parseEscapeSequence(index - 0x00 + 30, i, textCharFormat, defaultTextCharFormat);
|
||||||
|
}
|
||||||
|
else if (index >= 0x08 && index <= 0x0F)
|
||||||
|
{ // 0x08-0x0F: high intensity colors (as in ESC [ 90..97 m)
|
||||||
|
return parseEscapeSequence(index - 0x08 + 90, i, textCharFormat, defaultTextCharFormat);
|
||||||
|
}
|
||||||
|
else if (index >= 0x10 && index <= 0xE7)
|
||||||
|
{ // 0x10-0xE7: 6*6*6=216 colors: 16 + 36*r + 6*g + b (0≤r,g,b≤5)
|
||||||
|
index -= 0x10;
|
||||||
|
int red = index % 6;
|
||||||
|
index /= 6;
|
||||||
|
int green = index % 6;
|
||||||
|
index /= 6;
|
||||||
|
int blue = index % 6;
|
||||||
|
index /= 6;
|
||||||
|
Q_ASSERT(index == 0);
|
||||||
|
color.setRgb(red, green, blue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (index >= 0xE8 && index <= 0xFF)
|
||||||
|
{ // 0xE8-0xFF: grayscale from black to white in 24 steps
|
||||||
|
qreal intensity = qreal(index - 0xE8) / (0xFF - 0xE8);
|
||||||
|
color.setRgbF(intensity, intensity, intensity);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
textCharFormat.setForeground(color);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 39 : {
|
||||||
|
textCharFormat.setForeground(defaultTextCharFormat.foreground());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 40:
|
||||||
|
case 41:
|
||||||
|
case 42:
|
||||||
|
case 43:
|
||||||
|
case 44:
|
||||||
|
case 45:
|
||||||
|
case 46:
|
||||||
|
case 47: {
|
||||||
|
int colorIndex = attribute - 40;
|
||||||
|
QColor color;
|
||||||
|
switch (colorIndex) {
|
||||||
|
case 0 : {
|
||||||
|
color = Qt::darkGray;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1 : {
|
||||||
|
color = Qt::red;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2 : {
|
||||||
|
color = Qt::green;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3 : {
|
||||||
|
color = Qt::yellow;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4 : {
|
||||||
|
color = Qt::blue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5 : {
|
||||||
|
color = Qt::magenta;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 6 : {
|
||||||
|
color = Qt::cyan;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7 : {
|
||||||
|
color = Qt::white;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
Q_ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
textCharFormat.setBackground(color);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 48 : {
|
||||||
|
if (i.hasNext()) {
|
||||||
|
bool ok = false;
|
||||||
|
int selector = i.next().toInt(&ok);
|
||||||
|
Q_ASSERT(ok);
|
||||||
|
QColor color;
|
||||||
|
switch (selector) {
|
||||||
|
case 2 : {
|
||||||
|
if (!i.hasNext()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int red = i.next().toInt(&ok);
|
||||||
|
Q_ASSERT(ok);
|
||||||
|
if (!i.hasNext()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int green = i.next().toInt(&ok);
|
||||||
|
Q_ASSERT(ok);
|
||||||
|
if (!i.hasNext()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int blue = i.next().toInt(&ok);
|
||||||
|
Q_ASSERT(ok);
|
||||||
|
color.setRgb(red, green, blue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5 : {
|
||||||
|
if (!i.hasNext()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int index = i.next().toInt(&ok);
|
||||||
|
Q_ASSERT(ok);
|
||||||
|
if (index >= 0x00 && index <= 0x07)
|
||||||
|
{ // 0x00-0x07: standard colors (as in ESC [ 40..47 m)
|
||||||
|
return parseEscapeSequence(index - 0x00 + 40, i, textCharFormat, defaultTextCharFormat);
|
||||||
|
}
|
||||||
|
else if (index >= 0x08 && index <= 0x0F)
|
||||||
|
{ // 0x08-0x0F: high intensity colors (as in ESC [ 100..107 m)
|
||||||
|
return parseEscapeSequence(index - 0x08 + 100, i, textCharFormat, defaultTextCharFormat);
|
||||||
|
}
|
||||||
|
else if (index >= 0x10 && index <= 0xE7)
|
||||||
|
{ // 0x10-0xE7: 6*6*6=216 colors: 16 + 36*r + 6*g + b (0≤r,g,b≤5)
|
||||||
|
index -= 0x10;
|
||||||
|
int red = index % 6;
|
||||||
|
index /= 6;
|
||||||
|
int green = index % 6;
|
||||||
|
index /= 6;
|
||||||
|
int blue = index % 6;
|
||||||
|
index /= 6;
|
||||||
|
Q_ASSERT(index == 0);
|
||||||
|
color.setRgb(red, green, blue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (index >= 0xE8 && index <= 0xFF)
|
||||||
|
{ // 0xE8-0xFF: grayscale from black to white in 24 steps
|
||||||
|
qreal intensity = qreal(index - 0xE8) / (0xFF - 0xE8);
|
||||||
|
color.setRgbF(intensity, intensity, intensity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
textCharFormat.setBackground(color);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 49: {
|
||||||
|
textCharFormat.setBackground(defaultTextCharFormat.background());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 90:
|
||||||
|
case 91:
|
||||||
|
case 92:
|
||||||
|
case 93:
|
||||||
|
case 94:
|
||||||
|
case 95:
|
||||||
|
case 96:
|
||||||
|
case 97: {
|
||||||
|
int colorIndex = attribute - 90;
|
||||||
|
QColor color;
|
||||||
|
switch (colorIndex) {
|
||||||
|
case 0 : {
|
||||||
|
color = Qt::darkGray;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1 : {
|
||||||
|
color = Qt::red;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2 : {
|
||||||
|
color = Qt::green;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3 : {
|
||||||
|
color = Qt::yellow;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4 : {
|
||||||
|
color = Qt::blue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5 : {
|
||||||
|
color = Qt::magenta;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 6 : {
|
||||||
|
color = Qt::cyan;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7 : {
|
||||||
|
color = Qt::white;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
Q_ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
color.setRedF(color.redF() * 0.8);
|
||||||
|
color.setGreenF(color.greenF() * 0.8);
|
||||||
|
color.setBlueF(color.blueF() * 0.8);
|
||||||
|
textCharFormat.setForeground(color);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 100:
|
||||||
|
case 101:
|
||||||
|
case 102:
|
||||||
|
case 103:
|
||||||
|
case 104:
|
||||||
|
case 105:
|
||||||
|
case 106:
|
||||||
|
case 107:
|
||||||
|
{
|
||||||
|
int colorIndex = attribute - 100;
|
||||||
|
QColor color;
|
||||||
|
switch (colorIndex) {
|
||||||
|
case 0 : {
|
||||||
|
color = Qt::darkGray;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1 : {
|
||||||
|
color = Qt::red;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2 : {
|
||||||
|
color = Qt::green;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3 : {
|
||||||
|
color = Qt::yellow;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4 : {
|
||||||
|
color = Qt::blue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5 : {
|
||||||
|
color = Qt::magenta;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 6 : {
|
||||||
|
color = Qt::cyan;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7 : {
|
||||||
|
color = Qt::white;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
Q_ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
color.setRedF(color.redF() * 0.8);
|
||||||
|
color.setGreenF(color.greenF() * 0.8);
|
||||||
|
color.setBlueF(color.blueF() * 0.8);
|
||||||
|
textCharFormat.setBackground(color);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::onExtract()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::onReturnPressed()
|
||||||
|
{
|
||||||
|
if (sender() == m_ui->pathEdit && !m_ui->pathEdit->text().isEmpty())
|
||||||
|
m_path = m_ui->pathEdit->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::initSlots()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
m_heclProc.setEnvironment(QProcessEnvironment::systemEnvironment().toStringList() + QStringList("ConEmuANSI=ON"));
|
||||||
|
#endif
|
||||||
|
connect(&m_heclProc, &QProcess::readyRead, [=](){
|
||||||
|
m_ansiString = m_heclProc.readAll();
|
||||||
|
m_ui->processOutput->clear();
|
||||||
|
setTextTermFormatting(m_ui->processOutput, m_ansiString);
|
||||||
|
m_ui->processOutput->ensureCursorVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_ui->extractBtn, &QPushButton::clicked, [=](){
|
||||||
|
if (m_path.isEmpty())
|
||||||
|
return;
|
||||||
|
QString path = QFileInfo(m_path).absolutePath();
|
||||||
|
m_ansiString.clear();
|
||||||
|
m_heclProc.close();
|
||||||
|
m_heclProc.terminate();
|
||||||
|
m_heclProc.setProcessChannelMode(QProcess::ProcessChannelMode::MergedChannels);
|
||||||
|
m_heclProc.setWorkingDirectory(path);
|
||||||
|
m_heclProc.start("../hecl/driver/hecl.exe", {"extract", m_path, "-y"});
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_ui->browseBtn, &QPushButton::clicked, [=]() {
|
||||||
|
FileDirDialog dialog(this);
|
||||||
|
dialog.setWindowTitle("Select ISO or Directory");
|
||||||
|
int res = dialog.exec();//QFileDialog::getOpenFileName(this, "Select ISO or Directory");
|
||||||
|
if (res == QFileDialog::Rejected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dialog.selectedFiles().size() <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString path = dialog.selectedFiles().at(0);
|
||||||
|
/* TODO: Add beacon detection */
|
||||||
|
if (!path.isEmpty())
|
||||||
|
{
|
||||||
|
m_path = path;
|
||||||
|
m_ui->pathEdit->setText(m_path);
|
||||||
|
m_ui->extractBtn->setEnabled(true);
|
||||||
|
m_ui->packageBtn->setEnabled(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_ui->packageBtn, &QPushButton::clicked, [=](){
|
||||||
|
if (m_path.isEmpty())
|
||||||
|
return;
|
||||||
|
QString projectDir = m_path;
|
||||||
|
if (projectDir.endsWith(".iso", Qt::CaseInsensitive))
|
||||||
|
projectDir.remove(m_path.length() - 4, 4);
|
||||||
|
|
||||||
|
m_ansiString.clear();
|
||||||
|
m_heclProc.close();
|
||||||
|
m_heclProc.terminate();
|
||||||
|
m_heclProc.setWorkingDirectory(projectDir);
|
||||||
|
m_heclProc.setProcessChannelMode(QProcess::ProcessChannelMode::MergedChannels);
|
||||||
|
m_heclProc.start("../hecl/driver/hecl.exe", {"package", "-y"});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::setTextTermFormatting(QTextEdit* textEdit, const QString& text)
|
||||||
|
{
|
||||||
|
QTextDocument * document = textEdit->document();
|
||||||
|
QRegExp const escapeSequenceExpression(R"(\x1B\[([\d;]+)m)");
|
||||||
|
QTextCursor cursor(document);
|
||||||
|
QTextCharFormat defaultTextCharFormat = cursor.charFormat();
|
||||||
|
cursor.beginEditBlock();
|
||||||
|
int offset = escapeSequenceExpression.indexIn(text);
|
||||||
|
cursor.insertText(text.mid(0, offset));
|
||||||
|
QTextCharFormat textCharFormat = defaultTextCharFormat;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
offset = escapeSequenceExpression.indexIn(text, previousOffset);
|
||||||
|
if (offset < 0) {
|
||||||
|
cursor.insertText(text.mid(previousOffset), textCharFormat);
|
||||||
|
} else {
|
||||||
|
cursor.insertText(text.mid(previousOffset, offset - previousOffset), textCharFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursor.setCharFormat(defaultTextCharFormat);
|
||||||
|
cursor.endEditBlock();
|
||||||
|
cursor.movePosition(QTextCursor::End);
|
||||||
|
textEdit->setTextCursor(cursor);
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef MAINWINDOW_HPP
|
||||||
|
#define MAINWINDOW_HPP
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <memory>
|
||||||
|
class QTextEdit;
|
||||||
|
class QTextCharFormat;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class MainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Ui::MainWindow* m_ui;
|
||||||
|
QString m_ansiString;
|
||||||
|
QString m_path;
|
||||||
|
QProcess m_heclProc;
|
||||||
|
public:
|
||||||
|
explicit MainWindow(QWidget *parent = 0);
|
||||||
|
~MainWindow();
|
||||||
|
void setTextTermFormatting(QTextEdit* textEdit, QString const & text);
|
||||||
|
void parseEscapeSequence(int attribute, QListIterator< QString > & i, QTextCharFormat & textCharFormat, QTextCharFormat const & defaultTextCharFormat);
|
||||||
|
private slots:
|
||||||
|
void onExtract();
|
||||||
|
void onReturnPressed();
|
||||||
|
private:
|
||||||
|
void initSlots();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MAINWINDOW_HPP
|
|
@ -21,66 +21,16 @@
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget">
|
<widget class="QWidget" name="centralwidget">
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="2" column="0">
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>166</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QPushButton" name="pushButton_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Extract</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="2">
|
|
||||||
<widget class="QPushButton" name="pushButton_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Package</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="3">
|
|
||||||
<widget class="QPushButton" name="pushButton_2">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>&Launch</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="4">
|
|
||||||
<spacer name="horizontalSpacer_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>167</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0" colspan="5">
|
<item row="1" column="0" colspan="5">
|
||||||
<widget class="QTabWidget" name="heclTabs">
|
<widget class="QTabWidget" name="heclTabs">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>2</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="dataTab">
|
<widget class="QWidget" name="dataTab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Data</string>
|
<string>Data</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -93,13 +43,97 @@
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0">
|
<item>
|
||||||
<widget class="QSplitter" name="splitter">
|
<widget class="QSplitter" name="splitter">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QTextEdit" name="textEdit"/>
|
<widget class="QListView" name="pakList"/>
|
||||||
<widget class="QTextEdit" name="textEdit_2"/>
|
<widget class="QTextEdit" name="processOutput">
|
||||||
|
<property name="palette">
|
||||||
|
<palette>
|
||||||
|
<active>
|
||||||
|
<colorrole role="Text">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>255</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Base">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</active>
|
||||||
|
<inactive>
|
||||||
|
<colorrole role="Text">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>255</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Base">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</inactive>
|
||||||
|
<disabled>
|
||||||
|
<colorrole role="Text">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>120</red>
|
||||||
|
<green>120</green>
|
||||||
|
<blue>120</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Base">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>240</red>
|
||||||
|
<green>240</green>
|
||||||
|
<blue>240</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</disabled>
|
||||||
|
</palette>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Terminal</family>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<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:'Terminal'; font-size:10pt; font-weight:400; font-style:normal;">
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -134,6 +168,62 @@
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>166</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QPushButton" name="extractBtn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Extract</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QPushButton" name="packageBtn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Package</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="3">
|
||||||
|
<widget class="QPushButton" name="launchBtn">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Launch</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="4">
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>167</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
<item row="0" column="0" colspan="5">
|
<item row="0" column="0" colspan="5">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
|
@ -148,12 +238,12 @@
|
||||||
<string>Working Directory:</string>
|
<string>Working Directory:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy">
|
<property name="buddy">
|
||||||
<cstring>lineEdit</cstring>
|
<cstring>pathEdit</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="lineEdit">
|
<widget class="QLineEdit" name="pathEdit">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
|
@ -169,13 +259,19 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="pushButton">
|
<widget class="QPushButton" name="browseBtn">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>...</string>
|
<string>...</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -188,5 +284,25 @@
|
||||||
<widget class="QStatusBar" name="statusbar"/>
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>pathEdit</sender>
|
||||||
|
<signal>returnPressed()</signal>
|
||||||
|
<receiver>MainWindow</receiver>
|
||||||
|
<slot>onReturnPressed()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>331</x>
|
||||||
|
<y>20</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>302</x>
|
||||||
|
<y>305</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
<slots>
|
||||||
|
<slot>onReturnPressed()</slot>
|
||||||
|
</slots>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
Loading…
Reference in New Issue