From ff53cd5e3920c2b5eb1cd9cf2d43c7b219a64b08 Mon Sep 17 00:00:00 2001 From: Robert Brothers Date: Sat, 5 Jun 2021 18:10:19 -0500 Subject: [PATCH 1/5] Added duplicate option to plugin right-click and ctrl+d hotkey for duplicating selected plugins --- mapviz/include/mapviz/config_item.h | 4 ++ mapviz/include/mapviz/mapviz.h | 3 + mapviz/src/config_item.cpp | 9 +++ mapviz/src/mapviz.cpp | 85 +++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+) diff --git a/mapviz/include/mapviz/config_item.h b/mapviz/include/mapviz/config_item.h index e40aedb8..ee712068 100644 --- a/mapviz/include/mapviz/config_item.h +++ b/mapviz/include/mapviz/config_item.h @@ -33,6 +33,7 @@ // C++ standard libraries #include #include +#include // QT libraries #include @@ -66,11 +67,13 @@ namespace mapviz Q_SIGNALS: void UpdateSizeHint(); void ToggledDraw(QListWidgetItem* plugin, bool visible); + void DuplicateRequest(QListWidgetItem* plugin); void RemoveRequest(QListWidgetItem* plugin); public Q_SLOTS: void Hide(); void EditName(); + void Duplicate(); void Remove(); void ToggleDraw(bool toggled); @@ -82,6 +85,7 @@ namespace mapviz QString name_; QString type_; QAction* edit_name_action_; + QAction* duplicate_item_action_; QAction* remove_item_action_; bool visible_; }; diff --git a/mapviz/include/mapviz/mapviz.h b/mapviz/include/mapviz/mapviz.h index d2e68072..072b432a 100644 --- a/mapviz/include/mapviz/mapviz.h +++ b/mapviz/include/mapviz/mapviz.h @@ -51,6 +51,7 @@ #include #include #include +#include // ROS libraries #include @@ -92,6 +93,8 @@ namespace mapviz void SelectNewDisplay(); void RemoveDisplay(); void RemoveDisplay(QListWidgetItem* item); + void DuplicateDisplay(); + void DuplicateDisplay(QListWidgetItem *item); void ReorderDisplays(); void FixedFrameSelected(const QString& text); void TargetFrameSelected(const QString& text); diff --git a/mapviz/src/config_item.cpp b/mapviz/src/config_item.cpp index 416af311..0beee149 100644 --- a/mapviz/src/config_item.cpp +++ b/mapviz/src/config_item.cpp @@ -42,10 +42,13 @@ namespace mapviz ui_.setupUi(this); edit_name_action_ = new QAction("Edit Name", this); + duplicate_item_action_ = new QAction("Duplicate", this); + duplicate_item_action_->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_D)); remove_item_action_ = new QAction("Remove", this); remove_item_action_->setIcon(QIcon(":/images/remove-icon-th.png")); connect(edit_name_action_, SIGNAL(triggered()), this, SLOT(EditName())); + connect(duplicate_item_action_, SIGNAL(triggered()), this, SLOT(Duplicate())); connect(remove_item_action_, SIGNAL(triggered()), this, SLOT(Remove())); } @@ -71,6 +74,7 @@ namespace mapviz { QMenu menu(this); menu.addAction(edit_name_action_); + menu.addAction(duplicate_item_action_); menu.addAction(remove_item_action_); menu.exec(event->globalPos()); } @@ -109,6 +113,11 @@ namespace mapviz } } + void ConfigItem::Duplicate() + { + Q_EMIT DuplicateRequest(item_); + } + void ConfigItem::Remove() { Q_EMIT RemoveRequest(item_); diff --git a/mapviz/src/mapviz.cpp b/mapviz/src/mapviz.cpp index 6adf8094..bf80a191 100644 --- a/mapviz/src/mapviz.cpp +++ b/mapviz/src/mapviz.cpp @@ -201,6 +201,10 @@ Mapviz::Mapviz(bool is_standalone, int argc, char** argv, QWidget *parent, Qt::W ui_.bg_color->setColor(background_); canvas_->SetBackground(background_); + + // Keyboard shortcuts for the main window + QShortcut *duplicate_display_shortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_D), this); + connect(duplicate_display_shortcut, SIGNAL(activated()), this, SLOT(DuplicateDisplay())); } Mapviz::~Mapviz() @@ -1188,6 +1192,7 @@ MapvizPluginPtr Mapviz::CreateNewDisplay( item->setSizeHint(config_item->sizeHint()); connect(config_item, SIGNAL(UpdateSizeHint()), this, SLOT(UpdateSizeHints())); connect(config_item, SIGNAL(ToggledDraw(QListWidgetItem*, bool)), this, SLOT(ToggleShowPlugin(QListWidgetItem*, bool))); + connect(config_item, SIGNAL(DuplicateRequest(QListWidgetItem*)), this, SLOT(DuplicateDisplay(QListWidgetItem*))); connect(config_item, SIGNAL(RemoveRequest(QListWidgetItem*)), this, SLOT(RemoveDisplay(QListWidgetItem*))); connect(plugin.get(), SIGNAL(VisibleChanged(bool)), config_item, SLOT(ToggleDraw(bool))); connect(plugin.get(), SIGNAL(SizeChanged()), this, SLOT(UpdateSizeHints())); @@ -1499,6 +1504,86 @@ void Mapviz::RemoveDisplay(QListWidgetItem* item) } } +void Mapviz::DuplicateDisplay() +{ + QListWidgetItem* item = ui_.configs->item(ui_.configs->currentRow()); + if (item != nullptr) + { + DuplicateDisplay(item); + } +} + +void Mapviz::DuplicateDisplay(QListWidgetItem* item) +{ + ROS_INFO("Duplicating active display... "); + // - Get plugin associated with QListWidgetItem + if (plugins_.count(item) != 1) + { + ROS_ERROR("Item attempted to duplicate is not a plugin."); + return; + } + MapvizPluginPtr target_plugin = plugins_[item]; + ConfigItem* target_config_item = static_cast(ui_.configs->itemWidget(item)); + + // - Save plugin config to a temporary file location to reload it via the class + // loader as a completely new object + QString temp_config_path = QDir::tempPath() + "/mapviz_duplicate_config"; + QTemporaryFile temp_config_file(temp_config_path); + if (!temp_config_file.open()) + { + ROS_ERROR_STREAM("Cannot duplicate plugin of type: " + << target_plugin->Type() << "\nCould not open file: " + << temp_config_file.fileName().toStdString()); + return; + } + + YAML::Emitter out; + out << YAML::BeginMap; + out << YAML::Key << "type" << YAML::Value << target_plugin->Type(); + out << YAML::Key << "name" << YAML::Value << target_config_item->Name().toStdString(); + out << YAML::Key << "config" << YAML::Value; + out << YAML::BeginMap; + out << YAML::Key << "visible" << YAML::Value << target_plugin->Visible(); + out << YAML::Key << "collapsed" << YAML::Value << target_config_item->Collapsed(); + target_plugin->SaveConfig(out, temp_config_path.toStdString()); + out << YAML::EndMap; + out << YAML::EndMap; + QTextStream temp_file_writer(&temp_config_file); + temp_file_writer << out.c_str(); + temp_config_file.close(); + + // - Create the new display via existing methods + // I Don't think I actually need to create a temporary file. the file + // path does not seem to be used in either the LoadConfig or SaveConfig + // methods, but I'll keep the temp file creation for now because it simplifies + // going from YAML::Emitter to YAML::Node. Maybe MapvizPlugin::SaveConfig + // could be updated to use YAML::Node and conver to emitter internally? + YAML::Node temp_node; + swri_yaml_util::LoadFile(temp_config_file.fileName().toStdString(), temp_node); + YAML::Node temp_config_node = temp_node["config"]; + if (!temp_config_node) + { + ROS_ERROR("Cannot duplicate plugin of type %s. Invalid config.", + target_plugin->Type().c_str()); + return; + } + try + { + MapvizPluginPtr duplicate_plugin = CreateNewDisplay( + target_config_item->Name().toStdString(), + target_plugin->Type(), + target_plugin->Visible(), + target_config_item->Collapsed()); + duplicate_plugin->LoadConfig(temp_config_node, + temp_config_file.fileName().toStdString()); + duplicate_plugin->DrawIcon(); + } + catch (const pluginlib::LibraryLoadException& e) + { + ROS_ERROR("%s", e.what()); + } +} + void Mapviz::ClearDisplays() { while (ui_.configs->count() > 0) From 107ea9e1d31b11ee516cfb34467b9be7eb22c058 Mon Sep 17 00:00:00 2001 From: Robert Brothers Date: Sat, 5 Jun 2021 21:23:32 -0500 Subject: [PATCH 2/5] Removed unnecessary header from config_item.h --- mapviz/include/mapviz/config_item.h | 1 - 1 file changed, 1 deletion(-) diff --git a/mapviz/include/mapviz/config_item.h b/mapviz/include/mapviz/config_item.h index ee712068..880beff4 100644 --- a/mapviz/include/mapviz/config_item.h +++ b/mapviz/include/mapviz/config_item.h @@ -33,7 +33,6 @@ // C++ standard libraries #include #include -#include // QT libraries #include From ad340777d6bd1e3097ae4015acad62f3c68b0016 Mon Sep 17 00:00:00 2001 From: Robert Brothers Date: Sat, 12 Jun 2021 10:05:18 -0500 Subject: [PATCH 3/5] Removed use of temp file for duplicate feature. Used emitter -> string -> node conversion instead. --- mapviz/src/mapviz.cpp | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/mapviz/src/mapviz.cpp b/mapviz/src/mapviz.cpp index bf80a191..c9e4f8ed 100644 --- a/mapviz/src/mapviz.cpp +++ b/mapviz/src/mapviz.cpp @@ -1525,18 +1525,7 @@ void Mapviz::DuplicateDisplay(QListWidgetItem* item) MapvizPluginPtr target_plugin = plugins_[item]; ConfigItem* target_config_item = static_cast(ui_.configs->itemWidget(item)); - // - Save plugin config to a temporary file location to reload it via the class - // loader as a completely new object - QString temp_config_path = QDir::tempPath() + "/mapviz_duplicate_config"; - QTemporaryFile temp_config_file(temp_config_path); - if (!temp_config_file.open()) - { - ROS_ERROR_STREAM("Cannot duplicate plugin of type: " - << target_plugin->Type() << "\nCould not open file: " - << temp_config_file.fileName().toStdString()); - return; - } - + // - Save plugin config to a temporary string via an emitter YAML::Emitter out; out << YAML::BeginMap; out << YAML::Key << "type" << YAML::Value << target_plugin->Type(); @@ -1545,21 +1534,13 @@ void Mapviz::DuplicateDisplay(QListWidgetItem* item) out << YAML::BeginMap; out << YAML::Key << "visible" << YAML::Value << target_plugin->Visible(); out << YAML::Key << "collapsed" << YAML::Value << target_config_item->Collapsed(); - target_plugin->SaveConfig(out, temp_config_path.toStdString()); + target_plugin->SaveConfig(out, ""); out << YAML::EndMap; out << YAML::EndMap; - QTextStream temp_file_writer(&temp_config_file); - temp_file_writer << out.c_str(); - temp_config_file.close(); - - // - Create the new display via existing methods - // I Don't think I actually need to create a temporary file. the file - // path does not seem to be used in either the LoadConfig or SaveConfig - // methods, but I'll keep the temp file creation for now because it simplifies - // going from YAML::Emitter to YAML::Node. Maybe MapvizPlugin::SaveConfig - // could be updated to use YAML::Node and conver to emitter internally? + + // - Create the new display via existing MapvizPlugin::LoadConfig interface YAML::Node temp_node; - swri_yaml_util::LoadFile(temp_config_file.fileName().toStdString(), temp_node); + swri_yaml_util::LoadString(out.c_str(), temp_node); YAML::Node temp_config_node = temp_node["config"]; if (!temp_config_node) { @@ -1574,8 +1555,7 @@ void Mapviz::DuplicateDisplay(QListWidgetItem* item) target_plugin->Type(), target_plugin->Visible(), target_config_item->Collapsed()); - duplicate_plugin->LoadConfig(temp_config_node, - temp_config_file.fileName().toStdString()); + duplicate_plugin->LoadConfig(temp_config_node, ""); duplicate_plugin->DrawIcon(); } catch (const pluginlib::LibraryLoadException& e) From 4724abc6c8be69a3c39e87b50b25d4d84f4d41b7 Mon Sep 17 00:00:00 2001 From: rjb0026 Date: Sun, 5 Sep 2021 17:15:18 -0500 Subject: [PATCH 4/5] cleanup --- mapviz/src/mapviz.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mapviz/src/mapviz.cpp b/mapviz/src/mapviz.cpp index c9e4f8ed..9efb1124 100644 --- a/mapviz/src/mapviz.cpp +++ b/mapviz/src/mapviz.cpp @@ -1531,9 +1531,9 @@ void Mapviz::DuplicateDisplay(QListWidgetItem* item) out << YAML::Key << "type" << YAML::Value << target_plugin->Type(); out << YAML::Key << "name" << YAML::Value << target_config_item->Name().toStdString(); out << YAML::Key << "config" << YAML::Value; - out << YAML::BeginMap; + out << YAML::BeginMap; out << YAML::Key << "visible" << YAML::Value << target_plugin->Visible(); - out << YAML::Key << "collapsed" << YAML::Value << target_config_item->Collapsed(); + out << YAML::Key << "collapsed" << YAML::Value << target_config_item->Collapsed(); target_plugin->SaveConfig(out, ""); out << YAML::EndMap; out << YAML::EndMap; @@ -1551,9 +1551,9 @@ void Mapviz::DuplicateDisplay(QListWidgetItem* item) try { MapvizPluginPtr duplicate_plugin = CreateNewDisplay( - target_config_item->Name().toStdString(), - target_plugin->Type(), - target_plugin->Visible(), + target_config_item->Name().toStdString(), + target_plugin->Type(), + target_plugin->Visible(), target_config_item->Collapsed()); duplicate_plugin->LoadConfig(temp_config_node, ""); duplicate_plugin->DrawIcon(); From 524f434c91976d4b8e137569b09a71097cdb2738 Mon Sep 17 00:00:00 2001 From: "robert.brothers" Date: Mon, 27 Nov 2023 16:24:17 -0600 Subject: [PATCH 5/5] Removed duplicate keyboard shortcut. --- mapviz/include/mapviz/mapviz.h | 1 - mapviz/src/config_item.cpp | 1 - mapviz/src/mapviz.cpp | 4 ---- 3 files changed, 6 deletions(-) diff --git a/mapviz/include/mapviz/mapviz.h b/mapviz/include/mapviz/mapviz.h index 072b432a..fffa9314 100644 --- a/mapviz/include/mapviz/mapviz.h +++ b/mapviz/include/mapviz/mapviz.h @@ -51,7 +51,6 @@ #include #include #include -#include // ROS libraries #include diff --git a/mapviz/src/config_item.cpp b/mapviz/src/config_item.cpp index 0beee149..41b9925c 100644 --- a/mapviz/src/config_item.cpp +++ b/mapviz/src/config_item.cpp @@ -43,7 +43,6 @@ namespace mapviz edit_name_action_ = new QAction("Edit Name", this); duplicate_item_action_ = new QAction("Duplicate", this); - duplicate_item_action_->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_D)); remove_item_action_ = new QAction("Remove", this); remove_item_action_->setIcon(QIcon(":/images/remove-icon-th.png")); diff --git a/mapviz/src/mapviz.cpp b/mapviz/src/mapviz.cpp index 9efb1124..595fdfca 100644 --- a/mapviz/src/mapviz.cpp +++ b/mapviz/src/mapviz.cpp @@ -201,10 +201,6 @@ Mapviz::Mapviz(bool is_standalone, int argc, char** argv, QWidget *parent, Qt::W ui_.bg_color->setColor(background_); canvas_->SetBackground(background_); - - // Keyboard shortcuts for the main window - QShortcut *duplicate_display_shortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_D), this); - connect(duplicate_display_shortcut, SIGNAL(activated()), this, SLOT(DuplicateDisplay())); } Mapviz::~Mapviz()