Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Configurable TPP Pipeline Widget #210

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)

include_directories(include ${CMAKE_CURRENT_BINARY_DIR})
Expand All @@ -63,6 +65,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 @@ -26,7 +26,7 @@ class TPP;

namespace noether
{
class TPPPipelineWidget;
class ConfigurableTPPPipelineWidget;

/**
* @brief Basic tool path planning widget
Expand All @@ -51,16 +51,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
QVTKWidget* 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
Loading