Skip to content

Commit

Permalink
Create Configurable TPP Pipeline Widget (#212)
Browse files Browse the repository at this point in the history
* Added configurable TPP pipeline widget

* Included configurable TPP pipeline widget in TPP widget

* Moved scroll widgets into TPP pipeline pages

* Exposed TPP pipeline methods in configurable TPP widget

* Added function to configure from file

* Show app maximized
  • Loading branch information
marip8 authored Jan 4, 2024
1 parent 1fda318 commit f5f1cae
Show file tree
Hide file tree
Showing 14 changed files with 288 additions and 166 deletions.
3 changes: 3 additions & 0 deletions noether_gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ option(NOETHER_ENABLE_TESTING "Enables compilation of unit tests" OFF)
qt5_wrap_cpp(${PROJECT_NAME}_widget_mocs
include/${PROJECT_NAME}/widgets/collapsible_area_widget.h
include/${PROJECT_NAME}/widgets/tpp_pipeline_widget.h
include/${PROJECT_NAME}/widgets/configurable_tpp_pipeline_widget.h
include/${PROJECT_NAME}/widgets/tpp_widget.h
# Tool Path Planners
# Raster
Expand Down Expand Up @@ -52,6 +53,7 @@ qt5_wrap_ui(${PROJECT_NAME}_widget_ui_mocs
ui/linear_approach_modifier_widget.ui
ui/raster_planner_widget.ui
ui/tpp_pipeline_widget.ui
ui/configurable_tpp_pipeline_widget.ui
ui/tpp_widget.ui)

# Core Library
Expand All @@ -61,6 +63,7 @@ add_library(${PROJECT_NAME} SHARED
src/widgets/collapsible_area_widget.cpp
src/widgets/plugin_loader_widget.cpp
src/widgets/tpp_pipeline_widget.cpp
src/widgets/configurable_tpp_pipeline_widget.cpp
src/widgets/tpp_widget.cpp
# Tool Path Planners
# Raster Planner
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include <QWidget>
#include <boost_plugin_loader/plugin_loader.h>
#include <noether_tpp/core/tool_path_planner_pipeline.h>

namespace Ui
{
class ConfigurableTPPPipeline;
}

namespace YAML
{
class Node;
}

namespace noether
{
class TPPPipelineWidget;

class ConfigurableTPPPipelineWidget : public QWidget
{
Q_OBJECT
public:
ConfigurableTPPPipelineWidget(boost_plugin_loader::PluginLoader loader, QWidget* parent = nullptr);

void setConfigurationFile(const QString& file);

ToolPathPlannerPipeline createPipeline() const;
void configure(const YAML::Node& config);
void configure(const QString& file);
void save(YAML::Node& config) const;

private:
void onLoadConfiguration(const bool /*checked*/);
void onSaveConfiguration(const bool /*checked*/);

Ui::ConfigurableTPPPipeline* ui_;
TPPPipelineWidget* pipeline_widget_;
};

} // namespace noether
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ namespace YAML
class Node;
}

class QVBoxLayout;

namespace noether
{
/**
Expand All @@ -35,6 +37,7 @@ class PluginLoaderWidget : public QWidget
void addWidget(const QString& plugin_name, const YAML::Node& config);

Ui::PluginLoader* ui_;
QVBoxLayout* widgets_layout_;
const boost_plugin_loader::PluginLoader loader_;
};

Expand Down
20 changes: 11 additions & 9 deletions noether_gui/include/noether_gui/widgets/plugin_loader_widget.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ template <typename PluginT>
PluginLoaderWidget<PluginT>::PluginLoaderWidget(boost_plugin_loader::PluginLoader loader,
const QString& title,
QWidget* parent)
: QWidget(parent), ui_(new Ui::PluginLoader()), loader_(std::move(loader))
: QWidget(parent), ui_(new Ui::PluginLoader()), widgets_layout_(new QVBoxLayout()), loader_(std::move(loader))
{
ui_->setupUi(this);

ui_->contents->setLayout(widgets_layout_);

ui_->group_box->setTitle(title);
ui_->combo_box->addItems(getAvailablePlugins<PluginT>(loader_));

Expand Down Expand Up @@ -45,7 +47,7 @@ void PluginLoaderWidget<PluginT>::addWidget(const QString& plugin_name, const YA
collapsible_area->setWidget(plugin->create(this, config));
collapsible_area->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);

ui_->vertical_layout_plugins->addWidget(collapsible_area);
widgets_layout_->addWidget(collapsible_area);

// Add a right click menu option for deleting this tool path modifier widget
connect(collapsible_area, &QWidget::customContextMenuRequested, [this, collapsible_area](const QPoint& pos) {
Expand All @@ -54,7 +56,7 @@ void PluginLoaderWidget<PluginT>::addWidget(const QString& plugin_name, const YA
QAction* action = context_menu.exec(collapsible_area->mapToGlobal(pos));
if (action == remove_action)
{
ui_->vertical_layout_plugins->removeWidget(collapsible_area);
widgets_layout_->removeWidget(collapsible_area);
delete collapsible_area;
}
});
Expand All @@ -67,9 +69,9 @@ template <typename PluginT>
QWidgetList PluginLoaderWidget<PluginT>::getWidgets() const
{
QWidgetList widgets;
for (int i = 0; i < ui_->vertical_layout_plugins->count(); ++i)
for (int i = 0; i < widgets_layout_->count(); ++i)
{
QLayoutItem* item = ui_->vertical_layout_plugins->itemAt(i);
QLayoutItem* item = widgets_layout_->itemAt(i);
if (item)
{
auto collapsible_area = dynamic_cast<CollapsibleArea*>(item->widget());
Expand All @@ -96,9 +98,9 @@ void PluginLoaderWidget<PluginT>::configure(const YAML::Node& config)
template <typename PluginT>
void PluginLoaderWidget<PluginT>::save(YAML::Node& config) const
{
for (int i = 0; i < ui_->vertical_layout_plugins->count(); ++i)
for (int i = 0; i < widgets_layout_->count(); ++i)
{
QLayoutItem* item = ui_->vertical_layout_plugins->itemAt(i);
QLayoutItem* item = widgets_layout_->itemAt(i);
if (item)
{
auto collapsible_area = dynamic_cast<const CollapsibleArea*>(item->widget());
Expand All @@ -121,9 +123,9 @@ void PluginLoaderWidget<PluginT>::save(YAML::Node& config) const
template <typename PluginT>
void PluginLoaderWidget<PluginT>::removeWidgets()
{
for (int i = 0; i < ui_->vertical_layout_plugins->count(); ++i)
for (int i = 0; i < widgets_layout_->count(); ++i)
{
ui_->vertical_layout_plugins->itemAt(i)->widget()->deleteLater();
widgets_layout_->itemAt(i)->widget()->deleteLater();
}
}

Expand Down
6 changes: 2 additions & 4 deletions noether_gui/include/noether_gui/widgets/tpp_widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class TPP;

namespace noether
{
class TPPPipelineWidget;
class ConfigurableTPPPipelineWidget;

/**
* @brief Basic tool path planning widget
Expand All @@ -62,16 +62,14 @@ class TPPWidget : public QWidget

private:
void onLoadMesh(const bool /*checked*/);
void onLoadConfiguration(const bool /*checked*/);
void onSaveConfiguration(const bool /*checked*/);
void onPlan(const bool /*checked*/);
void onShowOriginalMesh(const bool);
void onShowModifiedMesh(const bool);
void onShowUnmodifiedToolPath(const bool);
void onShowModifiedToolPath(const bool);

Ui::TPP* ui_;
TPPPipelineWidget* pipeline_widget_;
ConfigurableTPPPipelineWidget* pipeline_widget_;

// Viewer rendering
RenderWidget* render_widget_;
Expand Down
2 changes: 1 addition & 1 deletion noether_gui/src/tpp_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ int main(int argc, char** argv)

// Set the TPP widget as the central widget and show
w.setCentralWidget(widget);
w.show();
w.showMaximized();

return app.exec();
}
2 changes: 2 additions & 0 deletions noether_gui/src/widgets/collapsible_area_widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ CollapsibleArea::CollapsibleArea(const QString& label, QWidget* parent)
content->setStyleSheet("QScrollArea { border: none; }");
content->setMaximumHeight(0);
content->setMinimumHeight(0);
content->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
content->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

animation_->addAnimation(new QPropertyAnimation(this, "minimumHeight"));
animation_->addAnimation(new QPropertyAnimation(this, "maximumHeight"));
Expand Down
123 changes: 123 additions & 0 deletions noether_gui/src/widgets/configurable_tpp_pipeline_widget.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#include <noether_gui/widgets/configurable_tpp_pipeline_widget.h>
#include <noether_gui/widgets/tpp_pipeline_widget.h>
#include <noether_gui/utils.h>
#include "ui_configurable_tpp_pipeline_widget.h"

#include <fstream>
#include <QFileDialog>
#include <QMessageBox>
#include <QTextStream>
#include <QStandardPaths>
#include <yaml-cpp/yaml.h>

namespace noether
{
ConfigurableTPPPipelineWidget::ConfigurableTPPPipelineWidget(boost_plugin_loader::PluginLoader loader, QWidget* parent)
: QWidget(parent)
, ui_(new Ui::ConfigurableTPPPipeline())
, pipeline_widget_(new TPPPipelineWidget(std::move(loader), this))
{
ui_->setupUi(this);
layout()->addWidget(pipeline_widget_);

// Connect
connect(ui_->push_button_load, &QPushButton::clicked, this, &ConfigurableTPPPipelineWidget::onLoadConfiguration);
connect(ui_->push_button_save, &QPushButton::clicked, this, &ConfigurableTPPPipelineWidget::onSaveConfiguration);
}

ToolPathPlannerPipeline ConfigurableTPPPipelineWidget::createPipeline() const
{
return pipeline_widget_->createPipeline();
}

void ConfigurableTPPPipelineWidget::configure(const YAML::Node& config) { return pipeline_widget_->configure(config); }

void ConfigurableTPPPipelineWidget::configure(const QString& file)
{
try
{
configure(YAML::LoadFile(file.toStdString()));
ui_->line_edit->setText(file);
}
catch (const YAML::BadFile&)
{
QString message;
QTextStream ss(&message);
ss << "Failed to open YAML file at '" << file << "'";
QMessageBox::warning(this, "Configuration Error", message);
}
catch (const std::exception& ex)
{
std::stringstream ss;
noether::printException(ex, ss);
QMessageBox::warning(this, "Configuration Error", QString::fromStdString(ss.str()));
}
}

void ConfigurableTPPPipelineWidget::save(YAML::Node& config) const { return pipeline_widget_->save(config); }

void ConfigurableTPPPipelineWidget::setConfigurationFile(const QString& file)
{
ui_->line_edit->setText(file);

try
{
configure(YAML::LoadFile(file.toStdString()));
}
catch (const YAML::BadFile&)
{
QString message;
QTextStream ss;
ss << "Failed to open YAML file at '" << file << "'";
QMessageBox::warning(this, "Configuration Error", message);
}
catch (const std::exception& ex)
{
std::stringstream ss;
printException(ex, ss);
QMessageBox::warning(this, "Configuration Error", QString::fromStdString(ss.str()));
}
}

void ConfigurableTPPPipelineWidget::onLoadConfiguration(const bool /*checked*/)
{
QString file = ui_->line_edit->text();
if (file.isEmpty())
file = QStandardPaths::standardLocations(QStandardPaths::HomeLocation).at(0);

file = QFileDialog::getOpenFileName(this, "Load configuration file", file, "YAML files (*.yaml)");
if (!file.isEmpty())
setConfigurationFile(file);
}

void ConfigurableTPPPipelineWidget::onSaveConfiguration(const bool /*checked*/)
{
try
{
QString file = ui_->line_edit->text();
if (file.isEmpty())
file = QStandardPaths::standardLocations(QStandardPaths::HomeLocation).at(0);

file = QFileDialog::getSaveFileName(this, "Save configuration file", file, "YAML files (*.yaml)");
if (file.isEmpty())
return;

YAML::Node config;
save(config);

std::ofstream ofh(file.toStdString());
if (!ofh)
throw std::runtime_error("Failed to open output file at '" + file.toStdString() + "'");

ofh << config;
QMessageBox::information(this, "Configuration", "Successfully saved tool path planning pipeline configuration");
}
catch (const std::exception& ex)
{
std::stringstream ss;
printException(ex, ss);
QMessageBox::warning(this, "Save Error", QString::fromStdString(ss.str()));
}
}

} // namespace noether
12 changes: 6 additions & 6 deletions noether_gui/src/widgets/tpp_pipeline_widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ TPPPipelineWidget::TPPPipelineWidget(boost_plugin_loader::PluginLoader loader, Q
ui_->group_box_tpp->setTitle(text);
if (text.isEmpty())
{
overwriteWidget(ui_->group_box_tpp->layout(), ui_->widget_tpp, new QWidget(this));
ui_->scroll_area->setWidget(new QWidget(this));
}
else
{
auto plugin = loader_.createInstance<ToolPathPlannerWidgetPlugin>(text.toStdString());
overwriteWidget(ui_->group_box_tpp->layout(), ui_->widget_tpp, plugin->create(this));
ui_->scroll_area->setWidget(plugin->create(this));
}
}
catch (const std::exception& ex)
Expand All @@ -98,7 +98,7 @@ void TPPPipelineWidget::configure(const YAML::Node& config)
auto tpp_config = config[TOOL_PATH_PLANNER_KEY];
auto name = getEntry<std::string>(tpp_config, "name");
auto plugin = loader_.createInstance<ToolPathPlannerWidgetPlugin>(name);
overwriteWidget(ui_->group_box_tpp->layout(), ui_->widget_tpp, plugin->create(this, tpp_config));
ui_->scroll_area->setWidget(plugin->create(this, tpp_config));
ui_->group_box_tpp->setTitle(QString::fromStdString(name));
}
catch (const std::exception&)
Expand All @@ -112,7 +112,7 @@ void TPPPipelineWidget::configure(const YAML::Node& config)
catch (const std::exception&)
{
// Clear the widgets
overwriteWidget(ui_->group_box_tpp->layout(), ui_->widget_tpp, new QWidget(this));
ui_->scroll_area->setWidget(new QWidget(this));
mesh_modifier_loader_widget_->removeWidgets();
tool_path_modifier_loader_widget_->removeWidgets();

Expand All @@ -131,7 +131,7 @@ void TPPPipelineWidget::save(YAML::Node& config) const

// Tool path planner
{
auto tpp_widget = dynamic_cast<const ToolPathPlannerWidget*>(ui_->widget_tpp);
auto tpp_widget = dynamic_cast<const ToolPathPlannerWidget*>(ui_->scroll_area->widget());
if (tpp_widget)
{
YAML::Node tpp_config;
Expand All @@ -151,7 +151,7 @@ void TPPPipelineWidget::save(YAML::Node& config) const

ToolPathPlannerPipeline TPPPipelineWidget::createPipeline() const
{
auto widget_tpp = dynamic_cast<ToolPathPlannerWidget*>(ui_->widget_tpp);
auto widget_tpp = dynamic_cast<ToolPathPlannerWidget*>(ui_->scroll_area->widget());
if (!widget_tpp)
throw std::runtime_error("No tool path planner specified");

Expand Down
Loading

0 comments on commit f5f1cae

Please sign in to comment.