From 9899099775162fdcfa97d91989fcd6412af3ceff Mon Sep 17 00:00:00 2001 From: Andy Zelenak Date: Mon, 11 Apr 2016 17:11:48 -0600 Subject: [PATCH 1/5] Squashed commit of the following: commit f7d6a773954ddde51dbba812bbbe98c91559f83b Author: Andy Zelenak Date: Mon Apr 11 17:07:36 2016 -0600 Add dialog box when exiting with unsaved changes. Issue #50 commit 37b7d9c32b3091dd833f15d47070585bd3dc16c6 Author: Andy Zelenak Date: Mon Apr 11 16:03:14 2016 -0600 Detecting all new joints/links, all deletes, and all changes. Reordering may not be detected. --- urdf_editor/include/urdf_editor/urdf_editor.h | 2 ++ urdf_editor/include/urdf_editor/urdf_property.h | 2 ++ urdf_editor/src/urdf_editor.cpp | 11 +++++++++++ urdf_editor/src/urdf_property.cpp | 8 +++++++- 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/urdf_editor/include/urdf_editor/urdf_editor.h b/urdf_editor/include/urdf_editor/urdf_editor.h index fcae80f..de4f433 100644 --- a/urdf_editor/include/urdf_editor/urdf_editor.h +++ b/urdf_editor/include/urdf_editor/urdf_editor.h @@ -24,6 +24,8 @@ private slots: void on_action_Save_triggered(); + void unsaved_changes(); + void on_actionSave_As_triggered(); void on_action_New_triggered(); diff --git a/urdf_editor/include/urdf_editor/urdf_property.h b/urdf_editor/include/urdf_editor/urdf_property.h index 2170ff3..0830941 100644 --- a/urdf_editor/include/urdf_editor/urdf_property.h +++ b/urdf_editor/include/urdf_editor/urdf_property.h @@ -28,6 +28,8 @@ namespace urdf_editor bool clear(); + bool unsavedChanges; + private slots: void on_treeWidget_customContextMenuRequested(const QPoint &pos); diff --git a/urdf_editor/src/urdf_editor.cpp b/urdf_editor/src/urdf_editor.cpp index 555d536..787fac5 100644 --- a/urdf_editor/src/urdf_editor.cpp +++ b/urdf_editor/src/urdf_editor.cpp @@ -28,6 +28,8 @@ URDFEditor::URDFEditor(QWidget *parent) : URDFEditor::~URDFEditor() { + if ( urdf_tree_->unsavedChanges == true ) // If there were unsaved changes + unsaved_changes(); delete ui; } @@ -43,6 +45,15 @@ void URDFEditor::on_action_Open_triggered() } } +void URDFEditor::unsaved_changes() +{ + QMessageBox::StandardButton reply; + reply = QMessageBox::question(this,"Save changes?","Save your changes before exiting?", QMessageBox::Yes|QMessageBox::No); + + if (reply == QMessageBox::Yes) + on_actionSave_As_triggered(); +} + void URDFEditor::on_action_Save_triggered() { urdf_tree_->saveURDF(file_path_); diff --git a/urdf_editor/src/urdf_property.cpp b/urdf_editor/src/urdf_property.cpp index 2c9e2e0..e50fdca 100644 --- a/urdf_editor/src/urdf_property.cpp +++ b/urdf_editor/src/urdf_property.cpp @@ -71,6 +71,8 @@ namespace urdf_editor connect(property_editor_.get(), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(on_propertyWidget_customContextMenuRequested(QPoint))); + unsavedChanges=false; // No changes to be saved, yet + } URDFProperty::~URDFProperty() @@ -211,6 +213,7 @@ namespace urdf_editor QTreeWidgetItem* item = addLinkTreeItem(parent, new_link); // now add the property addLinkProperty(item, new_link); + unsavedChanges = true; } QTreeWidgetItem* URDFProperty::addLinkTreeItem(QTreeWidgetItem* parent, urdf::LinkSharedPtr link) @@ -251,6 +254,7 @@ namespace urdf_editor QTreeWidgetItem* item = addJointTreeItem(parent, new_joint); // now add the property addJointProperty(item, new_joint); + unsavedChanges = true; } QTreeWidgetItem* URDFProperty::addJointTreeItem(QTreeWidgetItem* parent, urdf::JointSharedPtr joint) @@ -327,7 +331,7 @@ namespace urdf_editor addModelJoint(sel); } } - else + else // Remove { if (isLink(sel)) { @@ -715,6 +719,8 @@ namespace urdf_editor void URDFProperty::on_propertyWidget_valueChanged() { rviz_widget_->loadRobot(model_); + + unsavedChanges = true; } } From 8ba43a51a3e45231c990fb22c5c7c655e5ea5f79 Mon Sep 17 00:00:00 2001 From: Andy Zelenak Date: Tue, 19 Apr 2016 11:43:00 -0600 Subject: [PATCH 2/5] Detecting tree changes with slots & signals --- .../include/urdf_editor/urdf_property.h | 15 +++++++++- urdf_editor/src/urdf_editor.cpp | 4 +-- urdf_editor/src/urdf_property.cpp | 29 +++++++++++++++++-- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/urdf_editor/include/urdf_editor/urdf_property.h b/urdf_editor/include/urdf_editor/urdf_property.h index 0830941..5bf6077 100644 --- a/urdf_editor/include/urdf_editor/urdf_property.h +++ b/urdf_editor/include/urdf_editor/urdf_property.h @@ -24,7 +24,9 @@ namespace urdf_editor bool loadURDF(QString file_path); - bool saveURDF(QString file_path); + bool saveURDF_withConfirm(QString file_path); + + bool saveURDF_noConfirm(QString file_path); bool clear(); @@ -43,6 +45,17 @@ namespace urdf_editor void on_propertyWidget_valueChanged(); + void on_unsavedChanges(); + + signals: + void jointAddition(); + + void jointDeletion(); + + void linkAddition(); + + void linkDeletion(); + private: bool populateTreeWidget(); diff --git a/urdf_editor/src/urdf_editor.cpp b/urdf_editor/src/urdf_editor.cpp index 787fac5..1596bf2 100644 --- a/urdf_editor/src/urdf_editor.cpp +++ b/urdf_editor/src/urdf_editor.cpp @@ -56,7 +56,7 @@ void URDFEditor::unsaved_changes() void URDFEditor::on_action_Save_triggered() { - urdf_tree_->saveURDF(file_path_); + urdf_tree_->saveURDF_withConfirm(file_path_); } void URDFEditor::on_actionSave_As_triggered() @@ -65,7 +65,7 @@ void URDFEditor::on_actionSave_As_triggered() if (!file_path.isEmpty()) { file_path_ = file_path; - urdf_tree_->saveURDF(file_path); + urdf_tree_->saveURDF_noConfirm(file_path); ui->action_Save->setDisabled(false); } } diff --git a/urdf_editor/src/urdf_property.cpp b/urdf_editor/src/urdf_property.cpp index e50fdca..b1517de 100644 --- a/urdf_editor/src/urdf_property.cpp +++ b/urdf_editor/src/urdf_property.cpp @@ -71,6 +71,14 @@ namespace urdf_editor connect(property_editor_.get(), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(on_propertyWidget_customContextMenuRequested(QPoint))); + connect(this, SIGNAL(jointAddition()), SLOT(on_unsavedChanges())); + + connect(this, SIGNAL(jointDeletion()), SLOT(on_unsavedChanges())); + + connect(this, SIGNAL(linkAddition()), SLOT(on_unsavedChanges())); + + connect(this, SIGNAL(linkDeletion()), SLOT(on_unsavedChanges())); + unsavedChanges=false; // No changes to be saved, yet } @@ -118,7 +126,7 @@ namespace urdf_editor return rviz_widget_->loadRobot(model_); } - bool URDFProperty::saveURDF(QString file_path) + bool URDFProperty::saveURDF_withConfirm(QString file_path) { TiXmlDocument* doc = urdf::exportURDF(model_); TiXmlDeclaration decl("1.0", "", ""); @@ -142,6 +150,16 @@ namespace urdf_editor return true; } + bool URDFProperty::saveURDF_noConfirm(QString file_path) + { + TiXmlDocument* doc = urdf::exportURDF(model_); + TiXmlDeclaration decl("1.0", "", ""); + doc->InsertBeforeChild(doc->RootElement(), decl); + doc->SaveFile(file_path.toStdString()); + + return true; + } + bool URDFProperty::populateTreeWidget() { // add all links to the tree, starting with the root @@ -213,6 +231,7 @@ namespace urdf_editor QTreeWidgetItem* item = addLinkTreeItem(parent, new_link); // now add the property addLinkProperty(item, new_link); + emit linkAddition(); unsavedChanges = true; } @@ -255,6 +274,7 @@ namespace urdf_editor // now add the property addJointProperty(item, new_joint); unsavedChanges = true; + emit jointAddition(); } QTreeWidgetItem* URDFProperty::addJointTreeItem(QTreeWidgetItem* parent, urdf::JointSharedPtr joint) @@ -331,17 +351,19 @@ namespace urdf_editor addModelJoint(sel); } } - else // Remove + else { if (isLink(sel)) { link_names_.removeOne(sel->text(0)); link_root_->removeChild(sel); + emit linkDeletion(); } else if (isJoint(sel)) { joint_names_.removeOne(sel->text(0)); sel->parent()->removeChild(sel); + emit jointDeletion(); } } } @@ -719,7 +741,10 @@ namespace urdf_editor void URDFProperty::on_propertyWidget_valueChanged() { rviz_widget_->loadRobot(model_); + } + void URDFProperty::on_unsavedChanges() + { unsavedChanges = true; } From bf26bde1aacfbea1aa80f93accee9e7e22adc072 Mon Sep 17 00:00:00 2001 From: Andy Zelenak Date: Wed, 20 Apr 2016 14:18:28 -0600 Subject: [PATCH 3/5] The logic behind saving is good, now I need to reformat saveURDF functions. --- urdf_editor/include/urdf_editor/urdf_editor.h | 4 ++- urdf_editor/src/urdf_editor.cpp | 30 +++++++++++++++---- urdf_editor/src/urdf_property.cpp | 20 +++++++++++-- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/urdf_editor/include/urdf_editor/urdf_editor.h b/urdf_editor/include/urdf_editor/urdf_editor.h index de4f433..7caad6f 100644 --- a/urdf_editor/include/urdf_editor/urdf_editor.h +++ b/urdf_editor/include/urdf_editor/urdf_editor.h @@ -24,7 +24,7 @@ private slots: void on_action_Save_triggered(); - void unsaved_changes(); + bool unsaved_changes(); void on_actionSave_As_triggered(); @@ -39,6 +39,8 @@ private slots: urdf_editor::URDFPropertySharedPtr urdf_tree_; QString file_path_; + + virtual void closeEvent(QCloseEvent *event); }; #endif // __URDF_EDITOR_H__ diff --git a/urdf_editor/src/urdf_editor.cpp b/urdf_editor/src/urdf_editor.cpp index 1596bf2..996b96b 100644 --- a/urdf_editor/src/urdf_editor.cpp +++ b/urdf_editor/src/urdf_editor.cpp @@ -28,8 +28,6 @@ URDFEditor::URDFEditor(QWidget *parent) : URDFEditor::~URDFEditor() { - if ( urdf_tree_->unsavedChanges == true ) // If there were unsaved changes - unsaved_changes(); delete ui; } @@ -45,13 +43,17 @@ void URDFEditor::on_action_Open_triggered() } } -void URDFEditor::unsaved_changes() +bool URDFEditor::unsaved_changes() { QMessageBox::StandardButton reply; - reply = QMessageBox::question(this,"Save changes?","Save your changes before exiting?", QMessageBox::Yes|QMessageBox::No); + reply = QMessageBox::question(this,"Save changes?","Save your changes before exiting?", QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel); if (reply == QMessageBox::Yes) on_actionSave_As_triggered(); + if (reply == QMessageBox::Cancel) + return false; + if (reply == QMessageBox::No) + return true; } void URDFEditor::on_action_Save_triggered() @@ -79,5 +81,23 @@ void URDFEditor::on_action_New_triggered() void URDFEditor::on_actionE_xit_triggered() { - QApplication::quit(); + QCloseEvent closing; + closeEvent(&closing); +} + +void URDFEditor::closeEvent(QCloseEvent *event) +{ + if ( urdf_tree_->unsavedChanges == true ) // If there were unsaved changes + { + bool exit = unsaved_changes(); + if (!exit) + event->ignore(); + else + { + event->accept(); + QMainWindow::closeEvent(event); + } + } + else + QMainWindow::closeEvent(event); } diff --git a/urdf_editor/src/urdf_property.cpp b/urdf_editor/src/urdf_property.cpp index b1517de..37d4042 100644 --- a/urdf_editor/src/urdf_property.cpp +++ b/urdf_editor/src/urdf_property.cpp @@ -137,8 +137,10 @@ namespace urdf_editor QMessageBox msgBox; if (savedCorrectly) { - msgBox.setWindowTitle("Success"); - msgBox.setText("The file was saved."); + unsavedChanges = false; + msgBox.setWindowTitle("Success"); + msgBox.setText("The file was saved."); + msgBox.exec(); } else { @@ -155,7 +157,18 @@ namespace urdf_editor TiXmlDocument* doc = urdf::exportURDF(model_); TiXmlDeclaration decl("1.0", "", ""); doc->InsertBeforeChild(doc->RootElement(), decl); - doc->SaveFile(file_path.toStdString()); + bool savedCorrectly = false; + savedCorrectly = doc->SaveFile(file_path.toStdString()); + + QMessageBox msgBox; + if (!savedCorrectly) + { + msgBox.setWindowTitle("FAILURE"); + msgBox.setText("An error occurred during saving."); + msgBox.exec(); + } + else + unsavedChanges = false; return true; } @@ -741,6 +754,7 @@ namespace urdf_editor void URDFProperty::on_propertyWidget_valueChanged() { rviz_widget_->loadRobot(model_); + unsavedChanges = true; } void URDFProperty::on_unsavedChanges() From 50389825705b1b3975c1fb607902b3d0923fd8e5 Mon Sep 17 00:00:00 2001 From: Andy Zelenak Date: Wed, 20 Apr 2016 14:49:37 -0600 Subject: [PATCH 4/5] Reformatted saveURDF() to minimize duplicate code. --- .../include/urdf_editor/urdf_property.h | 4 +- urdf_editor/src/urdf_editor.cpp | 35 ++++++++++++++-- urdf_editor/src/urdf_property.cpp | 41 +------------------ 3 files changed, 34 insertions(+), 46 deletions(-) diff --git a/urdf_editor/include/urdf_editor/urdf_property.h b/urdf_editor/include/urdf_editor/urdf_property.h index 5bf6077..f143bb6 100644 --- a/urdf_editor/include/urdf_editor/urdf_property.h +++ b/urdf_editor/include/urdf_editor/urdf_property.h @@ -24,9 +24,7 @@ namespace urdf_editor bool loadURDF(QString file_path); - bool saveURDF_withConfirm(QString file_path); - - bool saveURDF_noConfirm(QString file_path); + bool saveURDF(QString file_path); bool clear(); diff --git a/urdf_editor/src/urdf_editor.cpp b/urdf_editor/src/urdf_editor.cpp index 996b96b..9a1aabf 100644 --- a/urdf_editor/src/urdf_editor.cpp +++ b/urdf_editor/src/urdf_editor.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -58,7 +59,20 @@ bool URDFEditor::unsaved_changes() void URDFEditor::on_action_Save_triggered() { - urdf_tree_->saveURDF_withConfirm(file_path_); + QMessageBox msgBox; + if (urdf_tree_->saveURDF(file_path_)) + { + urdf_tree_->unsavedChanges = false; + msgBox.setWindowTitle("Success"); + msgBox.setText("The file was saved."); + msgBox.exec(); + } + else + { + msgBox.setWindowTitle("FAILURE"); + msgBox.setText("An error occurred during saving."); + msgBox.exec(); + } } void URDFEditor::on_actionSave_As_triggered() @@ -67,7 +81,17 @@ void URDFEditor::on_actionSave_As_triggered() if (!file_path.isEmpty()) { file_path_ = file_path; - urdf_tree_->saveURDF_noConfirm(file_path); + + QMessageBox msgBox; + if (!urdf_tree_->saveURDF(file_path)) + { + msgBox.setWindowTitle("FAILURE"); + msgBox.setText("An error occurred during saving."); + msgBox.exec(); + } + else + urdf_tree_->unsavedChanges = false; + ui->action_Save->setDisabled(false); } } @@ -89,15 +113,18 @@ void URDFEditor::closeEvent(QCloseEvent *event) { if ( urdf_tree_->unsavedChanges == true ) // If there were unsaved changes { - bool exit = unsaved_changes(); - if (!exit) + if ( !unsaved_changes() ) event->ignore(); else { event->accept(); QMainWindow::closeEvent(event); + QApplication::quit(); } } else + { QMainWindow::closeEvent(event); + QApplication::quit(); + } } diff --git a/urdf_editor/src/urdf_property.cpp b/urdf_editor/src/urdf_property.cpp index 37d4042..3488d75 100644 --- a/urdf_editor/src/urdf_property.cpp +++ b/urdf_editor/src/urdf_property.cpp @@ -1,6 +1,5 @@ #include -#include #include @@ -126,7 +125,7 @@ namespace urdf_editor return rviz_widget_->loadRobot(model_); } - bool URDFProperty::saveURDF_withConfirm(QString file_path) + bool URDFProperty::saveURDF(QString file_path) { TiXmlDocument* doc = urdf::exportURDF(model_); TiXmlDeclaration decl("1.0", "", ""); @@ -134,43 +133,7 @@ namespace urdf_editor bool savedCorrectly = false; savedCorrectly = doc->SaveFile(file_path.toStdString()); - QMessageBox msgBox; - if (savedCorrectly) - { - unsavedChanges = false; - msgBox.setWindowTitle("Success"); - msgBox.setText("The file was saved."); - msgBox.exec(); - } - else - { - msgBox.setWindowTitle("FAILURE"); - msgBox.setText("An error occurred during saving."); - } - msgBox.exec(); - - return true; - } - - bool URDFProperty::saveURDF_noConfirm(QString file_path) - { - TiXmlDocument* doc = urdf::exportURDF(model_); - TiXmlDeclaration decl("1.0", "", ""); - doc->InsertBeforeChild(doc->RootElement(), decl); - bool savedCorrectly = false; - savedCorrectly = doc->SaveFile(file_path.toStdString()); - - QMessageBox msgBox; - if (!savedCorrectly) - { - msgBox.setWindowTitle("FAILURE"); - msgBox.setText("An error occurred during saving."); - msgBox.exec(); - } - else - unsavedChanges = false; - - return true; + return savedCorrectly; } bool URDFProperty::populateTreeWidget() From b06bf68a8854aff6564b2a5a6e217a58b765512e Mon Sep 17 00:00:00 2001 From: Andy Zelenak Date: Fri, 22 Apr 2016 14:38:23 -0600 Subject: [PATCH 5/5] Tweaking closeEvent() and quit() for best performance. --- .../urdf_editor/industrial_robot_builder.ui | 6 +- urdf_editor/include/urdf_editor/urdf_editor.h | 4 +- urdf_editor/src/urdf_editor.cpp | 76 ++++++++++--------- 3 files changed, 45 insertions(+), 41 deletions(-) diff --git a/urdf_editor/include/urdf_editor/industrial_robot_builder.ui b/urdf_editor/include/urdf_editor/industrial_robot_builder.ui index 7a7d0d8..6c3f12e 100644 --- a/urdf_editor/include/urdf_editor/industrial_robot_builder.ui +++ b/urdf_editor/include/urdf_editor/industrial_robot_builder.ui @@ -118,7 +118,7 @@ - + @@ -184,12 +184,12 @@ Ctrl+N - + - E&xit + &Exit Ctrl+Q diff --git a/urdf_editor/include/urdf_editor/urdf_editor.h b/urdf_editor/include/urdf_editor/urdf_editor.h index 7caad6f..910996a 100644 --- a/urdf_editor/include/urdf_editor/urdf_editor.h +++ b/urdf_editor/include/urdf_editor/urdf_editor.h @@ -30,7 +30,7 @@ private slots: void on_action_New_triggered(); - void on_actionE_xit_triggered(); + void on_action_Exit_triggered(); private: Ui::URDFEditor *ui; @@ -40,7 +40,7 @@ private slots: urdf_editor::URDFPropertySharedPtr urdf_tree_; QString file_path_; - virtual void closeEvent(QCloseEvent *event); + void closeEvent(QCloseEvent *event); }; #endif // __URDF_EDITOR_H__ diff --git a/urdf_editor/src/urdf_editor.cpp b/urdf_editor/src/urdf_editor.cpp index 9a1aabf..e1927d5 100644 --- a/urdf_editor/src/urdf_editor.cpp +++ b/urdf_editor/src/urdf_editor.cpp @@ -47,14 +47,17 @@ void URDFEditor::on_action_Open_triggered() bool URDFEditor::unsaved_changes() { QMessageBox::StandardButton reply; - reply = QMessageBox::question(this,"Save changes?","Save your changes before exiting?", QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel); + reply = QMessageBox::question(this, "Save changes?", "Save your changes before exiting?", QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); if (reply == QMessageBox::Yes) + { on_actionSave_As_triggered(); + return true; + } if (reply == QMessageBox::Cancel) - return false; + return false; if (reply == QMessageBox::No) - return true; + return true; } void URDFEditor::on_action_Save_triggered() @@ -62,16 +65,16 @@ void URDFEditor::on_action_Save_triggered() QMessageBox msgBox; if (urdf_tree_->saveURDF(file_path_)) { - urdf_tree_->unsavedChanges = false; - msgBox.setWindowTitle("Success"); - msgBox.setText("The file was saved."); - msgBox.exec(); + urdf_tree_->unsavedChanges = false; + msgBox.setWindowTitle("Success"); + msgBox.setText("The file was saved."); + msgBox.exec(); } else { - msgBox.setWindowTitle("FAILURE"); - msgBox.setText("An error occurred during saving."); - msgBox.exec(); + msgBox.setWindowTitle("FAILURE"); + msgBox.setText("An error occurred during saving."); + msgBox.exec(); } } @@ -85,46 +88,47 @@ void URDFEditor::on_actionSave_As_triggered() QMessageBox msgBox; if (!urdf_tree_->saveURDF(file_path)) { - msgBox.setWindowTitle("FAILURE"); - msgBox.setText("An error occurred during saving."); - msgBox.exec(); + msgBox.setWindowTitle("FAILURE"); + msgBox.setText("An error occurred during saving."); + msgBox.exec(); } else - urdf_tree_->unsavedChanges = false; - - ui->action_Save->setDisabled(false); + { + urdf_tree_->unsavedChanges = false; + ui->action_Save->setDisabled(false); + } } } void URDFEditor::on_action_New_triggered() { - file_path_.clear(); - urdf_tree_->clear(); - ui->action_Save->setDisabled(true); + file_path_.clear(); + urdf_tree_->clear(); + ui->action_Save->setDisabled(true); } -void URDFEditor::on_actionE_xit_triggered() +void URDFEditor::on_action_Exit_triggered() { - QCloseEvent closing; - closeEvent(&closing); + QCloseEvent closing; + closeEvent( &closing ); } -void URDFEditor::closeEvent(QCloseEvent *event) +void URDFEditor::closeEvent( QCloseEvent *event ) { - if ( urdf_tree_->unsavedChanges == true ) // If there were unsaved changes - { - if ( !unsaved_changes() ) - event->ignore(); - else - { - event->accept(); - QMainWindow::closeEvent(event); - QApplication::quit(); - } - } + if ( urdf_tree_->unsavedChanges == true ) // If there were unsaved changes + { + if ( !unsaved_changes() ) // User canceled the quit + event->ignore(); else { - QMainWindow::closeEvent(event); - QApplication::quit(); + event->accept(); + QMainWindow::closeEvent(event); + QApplication::quit(); } + } + else + { + event->accept(); + QApplication::quit(); + } }