diff options
-rw-r--r-- | qtmips_gui/MainWindow.ui | 20 | ||||
-rw-r--r-- | qtmips_gui/extprocess.cpp | 116 | ||||
-rw-r--r-- | qtmips_gui/extprocess.h | 63 | ||||
-rw-r--r-- | qtmips_gui/icons.qrc | 1 | ||||
-rw-r--r-- | qtmips_gui/icons/build-256.png | bin | 0 -> 19203 bytes | |||
-rw-r--r-- | qtmips_gui/mainwindow.cpp | 106 | ||||
-rw-r--r-- | qtmips_gui/mainwindow.h | 13 | ||||
-rw-r--r-- | qtmips_gui/qtmips_gui.pro | 8 | ||||
-rw-r--r-- | qtmips_gui/savechangeddialog.cpp | 117 | ||||
-rw-r--r-- | qtmips_gui/savechangeddialog.h | 61 | ||||
-rw-r--r-- | qtmips_gui/srceditor.cpp | 6 | ||||
-rw-r--r-- | qtmips_gui/srceditor.h | 1 |
12 files changed, 503 insertions, 9 deletions
diff --git a/qtmips_gui/MainWindow.ui b/qtmips_gui/MainWindow.ui index aa01737..0e51abc 100644 --- a/qtmips_gui/MainWindow.ui +++ b/qtmips_gui/MainWindow.ui @@ -104,6 +104,7 @@ <addaction name="actionMnemonicRegisters"/> <addaction name="actionShow_Symbol"/> <addaction name="actionCompileSource"/> + <addaction name="actionBuildExe"/> </widget> <widget class="QMenu" name="menuHelp"> <property name="title"> @@ -150,6 +151,7 @@ <addaction name="actionOpen"/> <addaction name="actionSave"/> <addaction name="actionCompileSource"/> + <addaction name="actionBuildExe"/> </widget> <action name="actionNewMachine"> <property name="icon"> @@ -263,6 +265,24 @@ <string>Ctrl+C</string> </property> </action> + <action name="actionBuildExe"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset resource="icons.qrc"> + <normaloff>:/icons/build-256.png</normaloff>:/icons/build-256.png</iconset> + </property> + <property name="text"> + <string>Build Executable</string> + </property> + <property name="toolTip"> + <string>Build executable by external make</string> + </property> + <property name="shortcut"> + <string>Ctrl+B</string> + </property> + </action> <action name="actionExit"> <property name="icon"> <iconset resource="icons.qrc"> diff --git a/qtmips_gui/extprocess.cpp b/qtmips_gui/extprocess.cpp new file mode 100644 index 0000000..18cc3c3 --- /dev/null +++ b/qtmips_gui/extprocess.cpp @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0+ +/******************************************************************************* + * QtMips - MIPS 32-bit Architecture Subset Simulator + * + * Implemented to support following courses: + * + * B35APO - Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b35apo + * + * B4M35PAP - Advanced Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b4m35pap/start + * + * Copyright (c) 2017-2019 Karel Koci<cynerd@email.cz> + * Copyright (c) 2019 Pavel Pisa <pisa@cmp.felk.cvut.cz> + * + * Faculty of Electrical Engineering (http://www.fel.cvut.cz) + * Czech Technical University (http://www.cvut.cz/) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ******************************************************************************/ + +#include <QFileInfo> +#include <QDir> +#include "extprocess.h" +#include <iostream> +#include <fstream> +#include <iomanip> +#include <typeinfo> + +using namespace std; + +ExtProcess::ExtProcess(QObject *parent) : Super(parent) { + setProcessChannelMode(QProcess::MergedChannels); + connect(this, SIGNAL(readyReadStandardOutput()), this, SLOT(process_output())); + connect(this, SIGNAL(finished(int,QProcess::ExitStatus)), + this, SLOT(report_finished(int,QProcess::ExitStatus))); + connect(this, SIGNAL(started()), this, SLOT(report_started())); +} + +void ExtProcess::report_finished(int exitCode, QProcess::ExitStatus exitStatus) { + if ((exitStatus != QProcess::NormalExit) || (exitCode != 0)) + report_message(messagetype::MSG_FINISH, "", 0, 0, program() + + ": failed - exit code " + QString::number(exitCode), ""); + else + report_message(messagetype::MSG_FINISH, "", 0, 0, program() + + ": finished", ""); + deleteLater(); +} + +void ExtProcess::report_started() { + report_message(messagetype::MSG_START, "", 0, 0, program() + ": started", ""); +} + +void ExtProcess::process_output() +{ + QString file = ""; + int ln = 0; + int col = 0; + messagetype::Type type = messagetype::MSG_INFO; + if (!canReadLine()) + return; + QString line = QString::fromLocal8Bit(readLine()); + while (line.count() > 0) { + if (line.at(line.count() - 1) != '\n' && + line.at(line.count() - 1) != '\r') + break; + line.truncate(line.count() - 1); + } + + int pos = line.indexOf(':'); + if (pos >= 0) { + QFileInfo fi(QDir(workingDirectory()), line.mid(0, pos)); + line = line.mid(pos + 1); + file = fi.absoluteFilePath(); + } + + for(pos = 0; line.count() > pos && line.at(pos).isDigit(); pos++); + if ((pos < line.count()) && (line.at(pos) == ':')) { + ln = line.mid(0, pos).toInt(); + line = line.mid(pos + 1); + } + + for(pos = 0; line.count() > pos && line.at(pos).isDigit(); pos++); + if ((pos < line.count()) && (line.at(pos) == ':')) { + col = line.mid(0, pos).toInt(); + line = line.mid(pos + 1); + } + + if (line.startsWith(' ')) { + line = line.mid(1); + } + if (line.startsWith('\t')) { + line = line.mid(1); + } + if (line.startsWith("error:", Qt::CaseInsensitive)) { + type = messagetype::MSG_ERROR; + } else if (line.startsWith("warning:", Qt::CaseInsensitive)) { + type = messagetype::MSG_WARNING; + } + + report_message(type, file, ln, col, line, ""); +} diff --git a/qtmips_gui/extprocess.h b/qtmips_gui/extprocess.h new file mode 100644 index 0000000..24cc5da --- /dev/null +++ b/qtmips_gui/extprocess.h @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0+ +/******************************************************************************* + * QtMips - MIPS 32-bit Architecture Subset Simulator + * + * Implemented to support following courses: + * + * B35APO - Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b35apo + * + * B4M35PAP - Advanced Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b4m35pap/start + * + * Copyright (c) 2017-2019 Karel Koci<cynerd@email.cz> + * Copyright (c) 2019 Pavel Pisa <pisa@cmp.felk.cvut.cz> + * + * Faculty of Electrical Engineering (http://www.fel.cvut.cz) + * Czech Technical University (http://www.cvut.cz/) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ******************************************************************************/ + +#ifndef MSGREPORT_H +#define MSGREPORT_H + +#include <QProcess> +#include <QString> +#include "messagetype.h" + +class ExtProcess : public QProcess { + Q_OBJECT + + using Super = QProcess; + +public: + ExtProcess(QObject *parent = nullptr); + +signals: + void report_message(messagetype::Type type, QString file, int line, int column, QString text, QString hint); + +protected slots: + void process_output(); + void report_started(); + void report_finished(int exitCode, QProcess::ExitStatus exitStatus); + +protected: + QByteArray m_buffer; +}; + +#endif // MSGREPORT_H diff --git a/qtmips_gui/icons.qrc b/qtmips_gui/icons.qrc index b43e84f..91ccd98 100644 --- a/qtmips_gui/icons.qrc +++ b/qtmips_gui/icons.qrc @@ -16,5 +16,6 @@ <file>icons/save.png</file> <file>icons/closetab.png</file> <file>icons/compfile-256.png</file> + <file>icons/build-256.png</file> </qresource> </RCC> diff --git a/qtmips_gui/icons/build-256.png b/qtmips_gui/icons/build-256.png Binary files differnew file mode 100644 index 0000000..b21fd38 --- /dev/null +++ b/qtmips_gui/icons/build-256.png diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp index 3af5e47..db9acce 100644 --- a/qtmips_gui/mainwindow.cpp +++ b/qtmips_gui/mainwindow.cpp @@ -51,6 +51,8 @@ #include "gotosymboldialog.h" #include "fixmatheval.h" #include "simpleasm.h" +#include "extprocess.h" +#include "savechangeddialog.h" #ifdef __EMSCRIPTEN__ #include <QFileInfo> @@ -120,6 +122,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { connect(ui->actionClose, SIGNAL(triggered(bool)), this, SLOT(close_source())); connect(ui->actionMnemonicRegisters, SIGNAL(triggered(bool)), this, SLOT(view_mnemonics_registers(bool))); connect(ui->actionCompileSource, SIGNAL(triggered(bool)), this, SLOT(compile_source())); + connect(ui->actionBuildExe, SIGNAL(triggered(bool)), this, SLOT(build_execute())); connect(ui->actionShow_Symbol, SIGNAL(triggered(bool)), this, SLOT(show_symbol_dialog())); connect(ui->actionRegisters, SIGNAL(triggered(bool)), this, SLOT(show_registers())); connect(ui->actionProgram_memory, SIGNAL(triggered(bool)), this, SLOT(show_program())); @@ -164,6 +167,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { delete(editor); } } + +#ifdef __EMSCRIPTEN__ + ui->actionBuildExe->setEnabled(false); +#endif } MainWindow::~MainWindow() { @@ -310,10 +317,10 @@ void MainWindow::new_machine() { ndialog->show(); } -void MainWindow::machine_reload(bool force_memory_reset) { +void MainWindow::machine_reload(bool force_memory_reset, bool force_elf_load) { if (machine == nullptr) return new_machine(); - bool load_executable = machine->executable_loaded(); + bool load_executable = force_elf_load || machine->executable_loaded(); machine::MachineConfig cnf(&machine->config()); // We have to make local copy as create_core will delete current machine try { create_core(cnf, load_executable, !load_executable && !force_memory_reset); @@ -334,7 +341,7 @@ void MainWindow::print_action() { QPrintDialog print_dialog(&printer, this); if (print_dialog.exec() == QDialog::Accepted) { QRectF scene_rect = corescene->sceneRect(); - if (printer.outputFormat() == QPrinter::PdfFormat && scene_rect.height()) { + if (printer.outputFormat() == QPrinter::PdfFormat && (scene_rect.height() != 0)) { QPageLayout layout = printer.pageLayout(); layout.setOrientation(QPageLayout::Portrait); QPageSize pagesize = layout.pageSize(); @@ -541,6 +548,27 @@ void MainWindow::update_open_file_list() { settings->setValue("openSrcFiles", open_src_files); } +bool MainWindow::modified_file_list(QStringList &list) { + bool ret = false; + list.clear(); + QStringList open_src_files; + if (central_window == nullptr) + return false; + for (int i = 0; i < central_window->count(); i++) { + QWidget *w = central_window->widget(i); + SrcEditor *editor = dynamic_cast<SrcEditor *>(w); + if (editor == nullptr) + continue; + if (editor->filename() == "") + continue; + if (!editor->isModified()) + continue; + ret = true; + list.append(editor->filename()); + } + return ret; +} + static int compare_filenames(const QString &filename1, const QString &filename2) { QFileInfo fi1(filename1); QFileInfo fi2(filename2); @@ -557,7 +585,7 @@ SrcEditor *MainWindow::source_editor_for_file(QString filename, bool open) { if (central_window == nullptr) return nullptr; int found_match = 0; - SrcEditor *found_editor; + SrcEditor *found_editor = nullptr; for (int i = 0; i < central_window->count(); i++) { QWidget *w = central_window->widget(i); SrcEditor *editor = dynamic_cast<SrcEditor *>(w); @@ -596,7 +624,7 @@ void MainWindow::open_source() { #ifndef __EMSCRIPTEN__ QString file_name = ""; - file_name = QFileDialog::getOpenFileName(this, tr("Open File"), "", "Source Files (*.asm *.S *.s)"); + file_name = QFileDialog::getOpenFileName(this, tr("Open File"), "", "Source Files (*.asm *.S *.s *.c Makefile)"); if (!file_name.isEmpty()) { SrcEditor *editor = source_editor_for_file(file_name, false); @@ -705,6 +733,8 @@ void MainWindow::message_selected(messagetype::Type type, QString file, int line (void)text; (void)hint; + if (file.isEmpty()) + return; SrcEditor *editor = source_editor_for_file(file, true); if (editor == nullptr) return; @@ -758,3 +788,69 @@ void MainWindow::compile_source() { if (error_occured) show_messages(); } + +void MainWindow::build_execute() { + QStringList list; + if (modified_file_list(list)) { + SaveChnagedDialog *dialog = new SaveChnagedDialog(list, this); + connect(dialog, SIGNAL(user_decision(bool,QStringList&)), + this, SLOT(build_execute_with_save(bool,QStringList&))); + dialog->open(); + } else { + build_execute_no_check(); + } +} + +void MainWindow::build_execute_with_save(bool cancel, QStringList &tosavelist) { + if (cancel) + return; + for (const auto &fname : tosavelist) { + SrcEditor *editor = source_editor_for_file(fname, false); + editor->saveFile(); + } + build_execute_no_check(); +} + +void MainWindow::build_execute_no_check() { + QString work_dir = ""; + ExtProcess *proc; + ExtProcess *procptr = build_process; + if (procptr != nullptr) { + procptr->close(); + procptr->deleteLater(); + } + + emit clear_messages(); + show_messages(); + proc = new ExtProcess(this); + build_process = procptr; + connect(proc, SIGNAL(report_message(messagetype::Type,QString,int,int,QString,QString)), + this, SIGNAL(report_message(messagetype::Type,QString,int,int,QString,QString))); + connect(proc, SIGNAL(finished(int,QProcess::ExitStatus)), + this, SLOT(build_execute_finished(int,QProcess::ExitStatus))); + if (current_srceditor != nullptr) { + if (!current_srceditor->filename().isEmpty()) { + QFileInfo fi(current_srceditor->filename()); + work_dir = fi.dir().path(); + } + } + if (work_dir.isEmpty() && (machine != nullptr)) { + if (!machine->config().elf().isEmpty()) { + QFileInfo fi(machine->config().elf()); + work_dir = fi.dir().path(); + } + } + if (!work_dir.isEmpty()) + proc->setWorkingDirectory(work_dir); + proc->start("make", QProcess::Unbuffered | QProcess::ReadOnly); +} + +void MainWindow::build_execute_finished(int exitCode, QProcess::ExitStatus exitStatus) { + if ((exitStatus != QProcess::NormalExit) || (exitCode != 0)) + return; + + if (machine != nullptr) { + if (machine->config().reset_at_compile()) + machine_reload(true, true); + } +} diff --git a/qtmips_gui/mainwindow.h b/qtmips_gui/mainwindow.h index d48ccda..09c82fd 100644 --- a/qtmips_gui/mainwindow.h +++ b/qtmips_gui/mainwindow.h @@ -39,6 +39,8 @@ #include <QMainWindow> #include <QSettings> #include <QTabWidget> +#include <QPointer> + #include "ui_MainWindow.h" #include "newdialog.h" #include "coreview.h" @@ -51,6 +53,7 @@ #include "lcddisplaydock.h" #include "cop0dock.h" #include "messagesdock.h" +#include "extprocess.h" #include "qtmipsmachine.h" #include "machineconfig.h" @@ -60,7 +63,7 @@ class MainWindow : public QMainWindow { Q_OBJECT public: - explicit MainWindow(QWidget *parent = 0); + explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); void start(); @@ -77,7 +80,7 @@ signals: public slots: // Actions signals void new_machine(); - void machine_reload(bool force_memory_reset = false); + void machine_reload(bool force_memory_reset = false, bool force_elf_load = false); void print_action(); void new_source(); void open_source(); @@ -85,6 +88,9 @@ public slots: void save_source_as(); void close_source(); void compile_source(); + void build_execute(); + void build_execute_no_check(); + void build_execute_with_save(bool cancel, QStringList &tosavelist); void show_registers(); void show_program(); void show_memory(); @@ -117,6 +123,7 @@ protected: protected slots: void src_editor_save_to(QString filename); + void build_execute_finished(int exitCode, QProcess::ExitStatus exitStatus); private: Ui::MainWindow *ui; @@ -148,7 +155,9 @@ private: void show_dockwidget(QDockWidget *w, Qt::DockWidgetArea area = Qt::RightDockWidgetArea); void add_src_editor_to_tabs(SrcEditor *editor); void update_open_file_list(); + bool modified_file_list(QStringList &list); SrcEditor *source_editor_for_file(QString filename, bool open); + QPointer<ExtProcess> build_process; }; #endif // MAINWINDOW_H diff --git a/qtmips_gui/qtmips_gui.pro b/qtmips_gui/qtmips_gui.pro index 6cf1c06..16cd5cf 100644 --- a/qtmips_gui/qtmips_gui.pro +++ b/qtmips_gui/qtmips_gui.pro @@ -80,7 +80,9 @@ SOURCES += \ highlighterc.cpp \ messagesdock.cpp \ messagesmodel.cpp \ - messagesview.cpp + messagesview.cpp \ + extprocess.cpp \ + savechangeddialog.cpp HEADERS += \ mainwindow.h \ @@ -129,7 +131,9 @@ HEADERS += \ highlighterc.h \ messagesdock.h \ messagesmodel.h \ - messagesview.h + messagesview.h \ + extprocess.h \ + savechangeddialog.h wasm: SOURCES += \ qhtml5file_html5.cpp diff --git a/qtmips_gui/savechangeddialog.cpp b/qtmips_gui/savechangeddialog.cpp new file mode 100644 index 0000000..dda1949 --- /dev/null +++ b/qtmips_gui/savechangeddialog.cpp @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0+ +/******************************************************************************* + * QtMips - MIPS 32-bit Architecture Subset Simulator + * + * Implemented to support following courses: + * + * B35APO - Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b35apo + * + * B4M35PAP - Advanced Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b4m35pap/start + * + * Copyright (c) 2017-2019 Karel Koci<cynerd@email.cz> + * Copyright (c) 2019 Pavel Pisa <pisa@cmp.felk.cvut.cz> + * + * Faculty of Electrical Engineering (http://www.fel.cvut.cz) + * Czech Technical University (http://www.cvut.cz/) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ******************************************************************************/ + +#include "savechangeddialog.h" +#include <QTabWidget> +#include <QVBoxLayout> +#include <QPlainTextEdit> +#include <QLabel> +#include <QPushButton> +#include <QStandardItem> +#include <QListView> + +SaveChnagedDialog::SaveChnagedDialog(QStringList &changedlist, QWidget *parent) : + QDialog(parent) +{ + setAttribute(Qt::WA_DeleteOnClose); + setAttribute(Qt::WA_ShowModal); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + setWindowTitle(tr("Save next modified files?")); + + model = new QStandardItemModel(this); + + for ( const auto& fname : changedlist) { + int row = model->rowCount(); + QStandardItem* item = new QStandardItem(); + item->setText(fname); + item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + item->setCheckState(Qt::Checked); + model->setItem(row, 0, item); + } + + QVBoxLayout *all = new QVBoxLayout(this); + + QListView *listview = new QListView(this); + listview->setModel(model); + listview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + all->addWidget(listview); + + QWidget *hbBtn = new QWidget(); + QHBoxLayout *hlBtn = new QHBoxLayout(hbBtn); + + QPushButton *cancelButton = new QPushButton(tr("&Cancel"), parent); + QPushButton *ignoreButton = new QPushButton(tr("&Ignore"), parent); + QPushButton *saveButton = new QPushButton(tr("&Save"), parent); + saveButton->setFocus(); + connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancel_clicked())); + connect(ignoreButton, SIGNAL(clicked()), this, SLOT(ignore_clicked())); + connect(saveButton, SIGNAL(clicked()), this, SLOT(save_clicked())); + hlBtn->addWidget(cancelButton); + hlBtn->addStretch(); + hlBtn->addWidget(ignoreButton); + hlBtn->addStretch(); + hlBtn->addWidget(saveButton); + + all->addWidget(hbBtn); + + setMinimumSize(400, 300); +} + +SaveChnagedDialog::~SaveChnagedDialog() +{ +} + +void SaveChnagedDialog::cancel_clicked() { + QStringList list; + emit user_decision(true, list); + close(); +} + +void SaveChnagedDialog::ignore_clicked() { + QStringList list; + emit user_decision(false, list); + close(); +} + +void SaveChnagedDialog::save_clicked() { + QStringList list; + for(int r = 0; r < model->rowCount(); ++r) { + if (model->item(r)->checkState() == Qt::Checked) + list.append(model->item(r)->text()); + } + emit user_decision(false, list); + close(); +} + diff --git a/qtmips_gui/savechangeddialog.h b/qtmips_gui/savechangeddialog.h new file mode 100644 index 0000000..34eb5cd --- /dev/null +++ b/qtmips_gui/savechangeddialog.h @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0+ +/******************************************************************************* + * QtMips - MIPS 32-bit Architecture Subset Simulator + * + * Implemented to support following courses: + * + * B35APO - Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b35apo + * + * B4M35PAP - Advanced Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b4m35pap/start + * + * Copyright (c) 2017-2019 Karel Koci<cynerd@email.cz> + * Copyright (c) 2019 Pavel Pisa <pisa@cmp.felk.cvut.cz> + * + * Faculty of Electrical Engineering (http://www.fel.cvut.cz) + * Czech Technical University (http://www.cvut.cz/) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ******************************************************************************/ + +#ifndef SAVECHANGED_H +#define SAVECHANGED_H + +#include <QDialog> +#include <QList> +#include <QStringList> +#include <QStandardItemModel> + +class SaveChnagedDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SaveChnagedDialog(QStringList &changedlist, QWidget *parent= nullptr); + ~SaveChnagedDialog(); +signals: + void user_decision(bool cancel, QStringList &tosavelist); +private slots: + void cancel_clicked(); + void ignore_clicked(); + void save_clicked(); +private: + QStandardItemModel *model; +}; + +#endif // SAVECHANGED_H diff --git a/qtmips_gui/srceditor.cpp b/qtmips_gui/srceditor.cpp index 8b0000d..18da3b5 100644 --- a/qtmips_gui/srceditor.cpp +++ b/qtmips_gui/srceditor.cpp @@ -116,6 +116,8 @@ bool SrcEditor::saveFile(QString filename) { writer.setFormat("plaintext"); bool success = writer.write(document()); setFileName(filename); + if (success) + document()->setModified(false); return success; } @@ -123,3 +125,7 @@ void SrcEditor::setCursorToLine(int ln) { QTextCursor cursor(document()->findBlockByLineNumber(ln-1)); setTextCursor(cursor); } + +bool SrcEditor::isModified() const { + return document()->isModified(); +} diff --git a/qtmips_gui/srceditor.h b/qtmips_gui/srceditor.h index 02650e5..880520e 100644 --- a/qtmips_gui/srceditor.h +++ b/qtmips_gui/srceditor.h @@ -55,6 +55,7 @@ public: bool loadByteArray(const QByteArray &content, QString filename = ""); void setCursorToLine(int ln); void setFileName(QString filename); + bool isModified() const; private: QSyntaxHighlighter *highlighter; void setup_common(); |