Skip to content

Commit

Permalink
Implement OneOf in Form
Browse files Browse the repository at this point in the history
  • Loading branch information
gergondet committed Jul 31, 2023
1 parent dc3fc04 commit 65f0980
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 1 deletion.
127 changes: 127 additions & 0 deletions mc_rtc_rviz_panel/src/FormElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1070,6 +1070,133 @@ void GenericArray::update()
values_->update();
}

OneOf::OneOf(QWidget * parent,
const std::string & name,
bool required,
const std::optional<std::pair<size_t, mc_rtc::Configuration>> & data,
FormElementContainer * parentForm)
: FormElement(parent, name, required)
{
container_ = new FormElementContainer(this, parentForm);
container_->hide();
auto layout = new QVBoxLayout(this);
selector_ = new QComboBox(this);
using sig_t = void (QComboBox::*)(int);
connect(selector_, static_cast<sig_t>(&QComboBox::currentIndexChanged), this,
[this](int index)
{
locked_ = true;
updateValue(index, {});
});
layout->addWidget(selector_);
activeLayout_ = new QVBoxLayout();
layout->addLayout(activeLayout_);
}

void OneOf::changed(bool required,
const std::optional<std::pair<size_t, mc_rtc::Configuration>> & data,
FormElementContainer *)
{
changed_(required);
if(!data)
{
if(active_) { updateValue(-1, {}); }
}
else { updateValue(data->first, data->second); }
}

mc_rtc::Configuration OneOf::serialize() const
{
auto out = mc_rtc::Configuration::rootArray();
out.push(selector_->currentIndex());
out.push(active_->serialize());
return out;
}

void OneOf::reset()
{
locked_ = false;
updateValue(-1, {});
}

bool OneOf::ready() const
{
return active_ && active_->ready();
}

bool OneOf::locked() const
{
return locked_ || (active_ && active_->locked());
}

void OneOf::unlock()
{
reset();
}

FormElement * OneOf::clone(QWidget * parent, const std::string & name) const
{
auto out = new OneOf(parent, name, required_, std::nullopt, nullptr);
out->container_->copy(*container_);
out->updateValue(data_.first, data_.second);
return out;
}

void OneOf::fill(const mc_rtc::Configuration & value)
{
if(value.isArray())
{
if(value.size() != 2) { mc_rtc::log::error_and_throw("Wrong data to fill OneOf: {}", value.dump(true, true)); }
updateValue(value[0], value[1]);
}
}

void OneOf::updateValue(int idx, mc_rtc::Configuration data)
{
if(container_->elements().size() == 0) { return; }
selector_->blockSignals(true);
if(idx < 0)
{
selector_->setCurrentIndex(-1);
if(active_)
{
active_->deleteLater();
active_ = nullptr;
}
data_.first = std::numeric_limits<size_t>::max();
}
else if(data_.first != idx)
{
data_.first = idx;
if(data_.first >= container_->elements().size())
{
mc_rtc::log::error_and_throw("Data out of range for OneOf::updateValue");
}
if(active_) { active_->deleteLater(); }
auto template_ = container_->elements()[data_.first];
active_ = template_->clone(this, template_->name());
activeLayout_->addWidget(active_);
}
selector_->setCurrentIndex(idx);
if(active_)
{
data_.second = data;
if(!data_.second.empty()) { active_->fill(data_.second); }
}
selector_->blockSignals(false);
}

void OneOf::update()
{
const auto & templates = container_->elements();
if(templates.size() == 0 || templates.size() == selector_->count()) { return; }
selector_->blockSignals(true);
while(selector_->count()) { selector_->removeItem(0); }
for(const auto & t : templates) { selector_->addItem(t->name().c_str()); }
selector_->setCurrentIndex(-1);
selector_->blockSignals(false);
}

} // namespace form

} // namespace mc_rtc_rviz
41 changes: 41 additions & 0 deletions mc_rtc_rviz_panel/src/FormElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,47 @@ struct GenericArray : public FormElement
void addValue(const std::string & name);
};

struct OneOf : public FormElement
{
OneOf(QWidget * parent,
const std::string & name,
bool required,
const std::optional<std::pair<size_t, mc_rtc::Configuration>> & data,
FormElementContainer * parentForm);

void changed(bool required,
const std::optional<std::pair<size_t, mc_rtc::Configuration>> & data,
FormElementContainer * parentForm);

mc_rtc::Configuration serialize() const override;

void reset() override;

bool ready() const override;

bool locked() const override;

void unlock() override;

inline FormElementContainer * container() noexcept { return container_; }

FormElement * clone(QWidget * parent, const std::string & name) const override;

void fill(const mc_rtc::Configuration & value) override;

void update();

private:
QComboBox * selector_;
QVBoxLayout * activeLayout_ = nullptr;
FormElement * active_ = nullptr;
FormElementContainer * container_ = nullptr;

void updateValue(int idx, mc_rtc::Configuration data);

std::pair<size_t, mc_rtc::Configuration> data_ = {std::numeric_limits<size_t>::max(), {}};
};

} // namespace form

} // namespace mc_rtc_rviz
32 changes: 32 additions & 0 deletions mc_rtc_rviz_panel/src/Panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ Panel::Panel(QWidget * parent)
qRegisterMetaType<rbd::parsers::Visual>("rbd::parsers::Visual");
qRegisterMetaType<std::optional<std::vector<mc_rtc::Configuration>>>(
"std::optional<std::vector<mc_rtc::Configuration>>");
qRegisterMetaType<std::optional<std::pair<size_t, mc_rtc::Configuration>>>(
"std::optional<std::pair<size_t, mc_rtc::Configuration>>");
tree_.parent = this;
setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(contextMenu(const QPoint &)));
Expand Down Expand Up @@ -238,6 +240,9 @@ Panel::Panel(QWidget * parent)
CONNECT_SIGNAL_SLOT(
start_form_generic_array_input(const std::string &, bool, std::optional<std::vector<mc_rtc::Configuration>>));
CONNECT_SIGNAL_SLOT(end_form_generic_array_input());
CONNECT_SIGNAL_SLOT(start_form_one_of_input(const std::string &, bool,
const std::optional<std::pair<size_t, mc_rtc::Configuration>> &));
CONNECT_SIGNAL_SLOT(end_form_one_of_input());
CONNECT_SIGNAL_SLOT(start_plot(uint64_t, const std::string &));
CONNECT_SIGNAL_SLOT(plot_setup_xaxis(uint64_t, const std::string &, const mc_rtc::gui::plot::Range &));
CONNECT_SIGNAL_SLOT(plot_setup_yaxis_left(uint64_t, const std::string &, const mc_rtc::gui::plot::Range &));
Expand Down Expand Up @@ -593,6 +598,18 @@ void Panel::end_form_generic_array_input()
Q_EMIT signal_end_form_generic_array_input();
}

void Panel::start_form_one_of_input(const std::string & name,
bool required,
const std::optional<std::pair<size_t, mc_rtc::Configuration>> & data)
{
Q_EMIT signal_start_form_one_of_input(name, required, data);
}

void Panel::end_form_one_of_input()
{
Q_EMIT signal_end_form_one_of_input();
}

void Panel::start_plot(uint64_t id, const std::string & title)
{
Q_EMIT signal_start_plot(id, title);
Expand Down Expand Up @@ -1039,6 +1056,21 @@ void Panel::got_end_form_generic_array_input()
activeForm_ = activeForm_->parentForm();
}

void Panel::got_start_form_one_of_input(const std::string & name,
bool required,
const std::optional<std::pair<size_t, mc_rtc::Configuration>> & data)
{
auto oneof = activeForm_->element<form::OneOf>(name, required, data, activeForm_);
oneof->update();
activeForm_ = oneof->container();
}

void Panel::got_end_form_one_of_input()
{
activeForm_->update();
activeForm_ = activeForm_->parentForm();
}

void Panel::got_start_plot(uint64_t id, const std::string & title)
{
got_category({}, "Plots");
Expand Down
6 changes: 5 additions & 1 deletion mc_rtc_rviz_panel/src/Panel.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,13 @@ protected: \
DEFINE_OVERRIDE(start_form_generic_array_input(const std::string & name,
bool required,
std::optional<std::vector<mc_rtc::Configuration>> data))

DEFINE_OVERRIDE(end_form_generic_array_input())

DEFINE_OVERRIDE(start_form_one_of_input(const std::string & name,
bool required,
const std::optional<std::pair<size_t, mc_rtc::Configuration>> & data))
DEFINE_OVERRIDE(end_form_one_of_input())

DEFINE_OVERRIDE(start_plot(uint64_t id, const std::string & title))
DEFINE_OVERRIDE(plot_setup_xaxis(uint64_t id, const std::string & legend, const mc_rtc::gui::plot::Range & range))
DEFINE_OVERRIDE(plot_setup_yaxis_left(uint64_t id,
Expand Down

0 comments on commit 65f0980

Please sign in to comment.