diff --git a/src/icons/close.svg b/src/icons/close.svg new file mode 100644 --- /dev/null +++ b/src/icons/close.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/icons/dark_cancel.svg b/src/icons/dark_cancel.svg new file mode 100644 --- /dev/null +++ b/src/icons/dark_cancel.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/icons/dark_save.svg b/src/icons/dark_save.svg new file mode 100644 --- /dev/null +++ b/src/icons/dark_save.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/icons/dark_save_all.svg b/src/icons/dark_save_all.svg new file mode 100644 --- /dev/null +++ b/src/icons/dark_save_all.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/icons/light_cancel.svg b/src/icons/light_cancel.svg new file mode 100644 --- /dev/null +++ b/src/icons/light_cancel.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/icons/light_save.svg b/src/icons/light_save.svg new file mode 100644 --- /dev/null +++ b/src/icons/light_save.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/icons/light_save_all.svg b/src/icons/light_save_all.svg new file mode 100644 --- /dev/null +++ b/src/icons/light_save_all.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/mainwindow.h b/src/mainwindow.h --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -66,6 +66,7 @@ QString m_theme; QTabWidget *m_instances; bool askToClose(); + bool askToSave(const QVector &fileList); void atCoreInstanceNameChange(const QString &name); QString getTheme(); void initWidgets(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -63,6 +63,10 @@ void MainWindow::closeEvent(QCloseEvent *event) { + if (!askToSave(m_gcodeEditor->modifiedFiles())) { + event->ignore(); + } + bool closePrompt = false; for (int i = 0; i < m_instances->count(); i++) { AtCoreInstanceWidget *instance = qobject_cast(m_instances->widget(i)); @@ -147,22 +151,41 @@ }); connect(newInstanceWidget, &AtCoreInstanceWidget::requestFileChooser, this, [newInstanceWidget, this] { + QUrl file; switch (m_openFiles.size()) { case 0: QMessageBox::warning(this, i18n("Error"), i18n("There's no GCode File open. \n Please select a file and try again."), QMessageBox::Ok); break; case 1: - newInstanceWidget->printFile(m_openFiles.at(0)); + file = m_openFiles.at(0); break; default: ChooseFileDialog dialog(this, m_openFiles); if (dialog.exec() == QDialog::Accepted) { - newInstanceWidget->printFile(dialog.choosenFile()); + file = dialog.choosenFile(); } + break; } + if (m_gcodeEditor->modifiedFiles().contains(file)) + { + int result = QMessageBox::question( + this + , i18n("Document Modified") + , i18n("%1 \n Contains Unsaved Changes That will not be in the print.\n Would you like to Save before printing?", file.toLocalFile()) + , QMessageBox::Save + , QMessageBox::Cancel + , QMessageBox::Ignore + ); + if (result == QMessageBox::Cancel) { + return; + } else if (result == QMessageBox::Save) { + m_gcodeEditor->saveFile(file); + } + } + newInstanceWidget->printFile(file); }); connect(newInstanceWidget, &AtCoreInstanceWidget::connectionChanged, this, &MainWindow::atCoreInstanceNameChange); @@ -370,3 +393,83 @@ } m_currEditorView = view; } + +bool MainWindow::askToSave(const QVector &fileList) +{ + + if (fileList.isEmpty()) { + return true; + } + QSize iconSize = QSize(fontMetrics().lineSpacing(), fontMetrics().lineSpacing()); + auto dialog = new QDialog(); + const int padding = 30; + auto listWidget = new QListWidget(); + listWidget->setMinimumWidth(fontMetrics().height() / 2 * padding); + for (const auto &url : fileList) { + listWidget->addItem(url.toLocalFile() + " [*]"); + } + + auto hLayout = new QHBoxLayout(); + auto saveBtn = new QPushButton(QIcon::fromTheme("document-save", QIcon(QStringLiteral(":/%1/save").arg(m_theme))), i18n("Save Selected")); + saveBtn->setIconSize(iconSize); + connect(saveBtn, &QPushButton::clicked, this, [this, &listWidget, &fileList, &dialog] { + if (!m_gcodeEditor->saveFile(fileList.at(listWidget->currentRow()))) + { + QMessageBox::information(this, i18n("Save Failed"), i18n("Failed to save file: %1").arg(fileList.at(listWidget->currentRow()).toLocalFile())); + } else + { + QString txt = listWidget->item(listWidget->currentRow())->text(); + txt.remove(" [*]"); + listWidget->item(listWidget->currentRow())->setText(txt); + for (int i = 0; i < listWidget->count(); i++) { + QString string = listWidget->item(i)->text(); + if (string.endsWith(" [*]")) { + return; + } + } + dialog->accept(); + } + }); + hLayout->addWidget(saveBtn); + + auto saveAllBtn = new QPushButton(QIcon::fromTheme("document-save-all", QIcon(QStringLiteral(":/%1/saveAll").arg(m_theme))), i18n("Save All")); + saveAllBtn->setIconSize(iconSize); + connect(saveAllBtn, &QPushButton::clicked, this, [this, &listWidget, &fileList, &dialog] { + for (int i = 0; i < listWidget->count(); i++) + { + if (!m_gcodeEditor->saveFile(fileList.at(i))) { + QMessageBox::information(this, i18n("Save Failed"), i18n("Failed to save file: %1").arg(fileList.at(i).toLocalFile())); + dialog->reject(); + } else { + QString txt = listWidget->item(listWidget->currentRow())->text(); + txt.remove(" [*]"); + listWidget->item(listWidget->currentRow())->setText(txt); + } + } + dialog->accept(); + }); + hLayout->addWidget(saveAllBtn); + + auto cancelBtn = new QPushButton(QIcon::fromTheme("dialog-cancel", QIcon(QStringLiteral(":/%1/cancel").arg(m_theme))), i18n("Cancel")); + cancelBtn->setIconSize(iconSize); + connect(cancelBtn, &QPushButton::clicked, this, [&dialog] { + dialog->reject(); + }); + hLayout->addWidget(cancelBtn); + + auto ignoreBtn = new QPushButton(QIcon::fromTheme("window-close", QIcon(QStringLiteral(":/icon/close"))), i18n("Ignore")); + ignoreBtn->setIconSize(iconSize); + connect(ignoreBtn, &QPushButton::clicked, this, [&dialog] { + dialog->accept(); + }); + hLayout->addWidget(ignoreBtn); + + auto layout = new QVBoxLayout; + auto label = new QLabel(i18n("Files with Unsaved Changes.")); + layout->addWidget(label); + layout->addWidget(listWidget); + layout->addItem(hLayout); + dialog->setLayout(layout); + + return dialog->exec(); +} diff --git a/src/resources.qrc b/src/resources.qrc --- a/src/resources.qrc +++ b/src/resources.qrc @@ -1,32 +1,39 @@ ../deploy/atelier.png + icons/close.svg icons/application-exit.svg icons/camera-web.svg icons/kwrite.svg icons/logo.svg + icons/light_cancel.svg icons/light_configure.svg icons/light_open.svg icons/light_3d.svg icons/light_add.svg icons/light_home.svg icons/light_connect.svg icons/light_disconnect.svg + icons/light_save.svg + icons/light_save_all.svg icons/light_start.svg icons/light_stop.svg icons/light_pause.svg icons/light_view_refresh.svg + icons/dark_cancel.svg icons/dark_configure.svg icons/dark_open.svg icons/dark_3d.svg icons/dark_add.svg icons/dark_home.svg icons/dark_connect.svg icons/dark_disconnect.svg + icons/dark_save.svg + icons/dark_save_all.svg icons/dark_start.svg icons/dark_stop.svg icons/dark_pause.svg diff --git a/src/widgets/gcodeeditorwidget.h b/src/widgets/gcodeeditorwidget.h --- a/src/widgets/gcodeeditorwidget.h +++ b/src/widgets/gcodeeditorwidget.h @@ -28,10 +28,11 @@ class GCodeEditorWidget : public QWidget { Q_OBJECT - public: explicit GCodeEditorWidget(QWidget *parent = nullptr); void loadFile(const QUrl &file); + QVector modifiedFiles(); + bool saveFile(const QUrl &url); private: QMap urlDoc; diff --git a/src/widgets/gcodeeditorwidget.cpp b/src/widgets/gcodeeditorwidget.cpp --- a/src/widgets/gcodeeditorwidget.cpp +++ b/src/widgets/gcodeeditorwidget.cpp @@ -118,4 +118,25 @@ if (event->mimeData()->hasUrls()) { emit droppedUrls(event->mimeData()->urls()); } + +} + +QVector GCodeEditorWidget::modifiedFiles() +{ + QVector modList; + for (auto const &doc : m_editor->documents()) { + if (doc->isModified()) { + modList.append(doc->url()); + } + } + return modList; +} + +bool GCodeEditorWidget::saveFile(const QUrl &url) +{ + if (!urlDoc.contains(url)) { + return false; + } + KTextEditor::Document *doc = urlDoc[url]; + return doc->save(); }