ImageRecorderWidgetController.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @package VisionX::gui-plugins::ImageRecorder
17  * @author Christian R. G. Dreher <c.dreher@kit.edu>
18  * @date 2020
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 
25 
26 
27 // STD/STL
28 #include <thread>
29 
30 // Qt
31 #include <QApplication>
32 #include <QClipboard>
33 
34 // ArmarX
37 
38 namespace
39 {
40  static const std::string config_key_imrecman = "imrecman_name";
41  static const std::string config_key_start_in = "start_in";
42 } // namespace
43 
45 {
47 
48  using this_class = ImageRecorderWidgetController;
49 
50  m_widget.setupUi(getWidget());
51  m_poll_timer = new QTimer(getWidget());
52  m_poll_timer->setSingleShot(false);
53  m_poll_timer->setInterval(50);
54  uninit_gui();
55 
56  connect(m_poll_timer, &QTimer::timeout, this, &this_class::poll_statuses);
57  connect(
58  m_widget.add_image_provider, &QPushButton::clicked, this, &this_class::add_image_provider);
59  connect(m_widget.copy_config_json,
60  &QPushButton::clicked,
61  this,
62  &this_class::copy_config_json_to_clipboard);
63  connect(
64  m_widget.config_get, &QPushButton::clicked, this, &this_class::get_config_from_imrecman);
65  connect(m_widget.config_set, &QPushButton::clicked, this, &this_class::set_config_at_imrecman);
66  connect(m_widget.start_in,
67  QOverload<double>::of(&QDoubleSpinBox::valueChanged),
68  this,
69  &this_class::update_start_rec_label);
70  connect(m_widget.start_rec, &QPushButton::clicked, this, &this_class::start_recordings);
71  connect(m_widget.stop_rec, &QPushButton::clicked, this, &this_class::stop_recordings);
72  connect(m_widget.edit_mode, &QCheckBox::stateChanged, this, &this_class::edit_mode_changed);
73  connect(this, &this_class::component_connected, this, &this_class::init_gui);
74  connect(this, &this_class::component_connected, this, &this_class::get_config_from_imrecman);
75  connect(this, &this_class::component_connected, this, &this_class::update_start_rec_label);
76  connect(this, &this_class::component_disconnected, this, &this_class::uninit_gui);
77 
78  edit_mode_changed(m_widget.edit_mode->checkState());
79 }
80 
81 void
83 {
85 
86  if (not m_imrecman_name.empty())
87  {
88  usingProxy(m_imrecman_name);
89  }
90 }
91 
92 void
94 {
96 
97  getProxy(m_imrecman, m_imrecman_name);
98 
99  emit component_connected();
100 }
101 
102 void
104 {
105  ARMARX_TRACE;
106 
107  emit component_disconnected();
108 }
109 
110 void
112 {
113  ARMARX_TRACE;
114 
115  // pass
116 }
117 
118 void
120 {
121  ARMARX_TRACE;
122 
123  m_imrecman_name =
124  settings->value(QString::fromStdString(::config_key_imrecman), "ImageRecordingManager")
125  .toString()
126  .toStdString();
127  m_widget.start_in->setValue(
128  settings->value(QString::fromStdString(::config_key_start_in), 1.0).toDouble());
129 }
130 
131 void
133 {
134  ARMARX_TRACE;
135 
136  settings->setValue(QString::fromStdString(::config_key_imrecman),
137  QString::fromStdString(m_imrecman_name));
138  settings->setValue(QString::fromStdString(::config_key_start_in), m_widget.start_in->value());
139 }
140 
141 QPointer<QDialog>
143 {
144  ARMARX_TRACE;
145 
146  if (not m_config_dialog)
147  {
148  m_config_dialog = new armarx::SimpleConfigDialog{parent};
149  m_config_dialog->addProxyFinder<ImageRecordingManagerInterfacePrx>(
150  {::config_key_imrecman, "Image recording manager", "*"});
151  }
152  return qobject_cast<QDialog*>(m_config_dialog);
153 }
154 
155 void
157 {
158  ARMARX_TRACE;
159 
160  if (m_config_dialog)
161  {
162  m_imrecman_name = m_config_dialog->getProxyName(::config_key_imrecman);
163  }
164 }
165 
166 void
168  const std::map<std::string, imrec::Config>& configs)
169 {
170  ARMARX_TRACE;
171 
172  for (const auto& [image_provider_name, config_widget] : m_config_widgets)
173  {
174  m_widget.image_providers->layout()->removeWidget(config_widget);
175  config_widget->deleteLater();
176  }
177  m_config_widgets.clear();
178 
179  if (not configs.empty())
180  {
181  const imrec::Config& ref_config = configs.begin()->second;
182  m_widget.pp_package->setText(QString::fromStdString(ref_config.location.package));
183  m_widget.pp_path->setText(QString::fromStdString(ref_config.location.path));
184  m_widget.recording_name->setText(QString::fromStdString(ref_config.name));
185  }
186 
187  for (const auto& [image_provider_name, config] : configs)
188  {
189  add_image_provider_conf_widget(image_provider_name, config);
190  }
191 }
192 
193 void
195  const std::map<std::string, visionx::imrec::Status>& statuses)
196 {
197  ARMARX_TRACE;
198 
199  // Upate statuses of known image providers.
200  for (const auto& [image_provider_name, status] : statuses)
201  {
202  if (m_config_widgets.find(image_provider_name) != m_config_widgets.end())
203  {
204  m_config_widgets.at(image_provider_name)->setImageProviderStatus(status);
205  }
206  }
207 
208  // Reset statuses of those image providers which are unknown to the recording manager yet
209  // configured in the GUI.
210  std::optional<imrec::Status> empty_status;
211  for (const auto& [image_provider_name, config_widget] : m_config_widgets)
212  {
213  if (statuses.find(image_provider_name) == statuses.end())
214  {
215  m_config_widgets.at(image_provider_name)->setImageProviderStatus(empty_status);
216  }
217  }
218 }
219 
220 void
222  const std::string& image_provider_name,
223  const imrec::Config& config)
224 {
225  ARMARX_TRACE;
226 
228  m_widget.image_providers, getIceManager(), image_provider_name, config.channelConfigs};
229 
230  m_config_widgets[image_provider_name] = cw;
231  m_widget.image_providers->layout()->addWidget(cw);
232 
233  connect(cw,
235  this,
236  &ImageRecorderWidgetController::rename_image_provider);
237  connect(cw,
239  this,
240  &ImageRecorderWidgetController::remove_image_provider);
241 
242  if (m_widget.auto_sync->isChecked())
243  {
244  set_config_at_imrecman();
245  }
246 }
247 
248 std::map<std::string, visionx::imrec::Config>
250 {
251  ARMARX_TRACE;
252 
253  const IceUtil::Time start_in = IceUtil::Time::secondsDouble(m_widget.start_in->value());
254  const IceUtil::Time start_at = IceUtil::Time::now() + start_in;
255 
256  std::map<std::string, visionx::imrec::Config> configs;
257  visionx::imrec::Config config_template;
258  config_template.location.package = m_widget.pp_package->text().toStdString();
259  config_template.location.path = m_widget.pp_path->text().toStdString();
260  config_template.name = m_widget.recording_name->text().toStdString();
261  config_template.startTimestamp = start_at.toMicroSeconds();
262  if (config_template.name.empty())
263  {
264  config_template.name = "rec_%TIMESTAMP%";
265  }
266 
267  for (const auto& [name, config_widget] : m_config_widgets)
268  {
269  config_template.channelConfigs = config_widget->toChannelConfigs();
270  configs[name] = config_template;
271  }
272  return configs;
273 }
274 
275 void
276 visionx::ImageRecorderWidgetController::init_gui()
277 {
278  ARMARX_TRACE;
279 
280  const bool enabled = true;
281  m_widget.start_rec->setEnabled(enabled);
282  m_widget.stop_rec->setEnabled(enabled);
283  m_widget.config_get->setEnabled(enabled);
284  m_widget.config_set->setEnabled(enabled);
285  m_poll_timer->start();
286 }
287 
288 void
289 visionx::ImageRecorderWidgetController::uninit_gui()
290 {
291  ARMARX_TRACE;
292 
293  const bool enabled = false;
294  m_widget.start_rec->setEnabled(enabled);
295  m_widget.stop_rec->setEnabled(enabled);
296  m_widget.config_get->setEnabled(enabled);
297  m_widget.config_set->setEnabled(enabled);
298  m_poll_timer->stop();
299 }
300 
301 void
302 visionx::ImageRecorderWidgetController::poll_statuses()
303 {
304  ARMARX_TRACE;
305 
306  try
307  {
308  if (m_imrecman->isConfigured())
309  {
310  update_statuses(m_imrecman->getRecordingStatuses());
311  }
312  }
313  catch (...)
314  {
315  // pass
316  }
317 }
318 
319 void
320 visionx::ImageRecorderWidgetController::get_config_from_imrecman()
321 {
322  ARMARX_TRACE;
323 
324  try
325  {
326  if (m_imrecman->isConfigured())
327  {
328  build_ui_from_config(m_imrecman->getConfiguration());
329  }
330  }
331  catch (...)
332  {
333  // pass
334  }
335 }
336 
337 void
338 visionx::ImageRecorderWidgetController::set_config_at_imrecman()
339 {
340  ARMARX_TRACE;
341 
342  try
343  {
344  m_imrecman->configureRecordings(to_config_map());
345  }
346  catch (...)
347  {
348  // pass
349  }
350 }
351 
352 void
353 visionx::ImageRecorderWidgetController::add_image_provider()
354 {
355  ARMARX_TRACE;
356 
357  visionx::imrec::Config config;
358  add_image_provider_conf_widget("image_provider_" + std::to_string(++m_image_provider_ctr),
359  config);
360 }
361 
362 void
363 visionx::ImageRecorderWidgetController::copy_config_json_to_clipboard()
364 {
365  ARMARX_TRACE;
366 
367  nlohmann::json j = to_config_map();
368  const std::string config_map_json = j.dump();
369  QClipboard* clipboard = QGuiApplication::clipboard();
370  clipboard->setText(QString::fromStdString(config_map_json));
371 }
372 
373 void
374 visionx::ImageRecorderWidgetController::update_start_rec_label()
375 {
376  ARMARX_TRACE;
377 
378  QString text = "Start recordings in ";
379  text += m_widget.start_in->cleanText();
380  text += " sec";
381  m_widget.start_rec->setText(text);
382 }
383 
384 void
385 visionx::ImageRecorderWidgetController::start_recordings()
386 {
387  ARMARX_TRACE;
388 
389  try
390  {
391  m_imrecman->configureRecordings(to_config_map());
392  m_imrecman->startRecordings();
393  }
394  catch (...)
395  {
396  // pass
397  }
398 }
399 
400 void
401 visionx::ImageRecorderWidgetController::stop_recordings()
402 {
403  ARMARX_TRACE;
404 
405  try
406  {
407  auto fn = [&] { m_imrecman->stopRecordings(); };
408  std::thread t{fn};
409  t.detach();
410  }
411  catch (...)
412  {
413  // pass
414  }
415 }
416 
417 void
418 visionx::ImageRecorderWidgetController::edit_mode_changed(const int state)
419 {
420  const ViewMode viewMode =
421  state == Qt::CheckState::Checked ? ViewMode::Full : ViewMode::StatusOnly;
422  for (const auto& [image_provider_name, config_widget] : m_config_widgets)
423  {
424  config_widget->setViewMode(viewMode);
425  }
426 
427  switch (viewMode)
428  {
429  case ViewMode::Full:
430  m_widget.config_get->setEnabled(true);
431  m_widget.config_set->setEnabled(true);
432  m_widget.add_image_provider->show();
433  break;
435  m_widget.config_get->setEnabled(false);
436  m_widget.config_set->setEnabled(false);
437  m_widget.add_image_provider->hide();
438  break;
439  }
440 }
441 
442 void
443 visionx::ImageRecorderWidgetController::rename_image_provider(const std::string& old_name,
444  const std::string& new_name)
445 {
446  ARMARX_TRACE;
447 
448  if (m_config_widgets.find(new_name) == m_config_widgets.end())
449  {
450  auto node_handler = m_config_widgets.extract(old_name);
451  node_handler.key() = new_name;
452  m_config_widgets.insert(std::move(node_handler));
453  m_config_widgets.at(new_name)->confirmImageProviderName(new_name);
454 
455  if (m_widget.auto_sync->isChecked())
456  {
457  set_config_at_imrecman();
458  }
459  }
460  else
461  {
462  m_config_widgets.at(new_name)->rejectImageProviderName(new_name);
463  }
464 }
465 
466 void
467 visionx::ImageRecorderWidgetController::remove_image_provider(const std::string& name)
468 {
469  ARMARX_TRACE;
470 
471  ImageProviderConfigWidget* config_widget = m_config_widgets.at(name);
472  m_widget.image_providers->layout()->removeWidget(config_widget);
473  config_widget->deleteLater();
474  m_config_widgets.erase(m_config_widgets.find(name));
475 
476  if (m_widget.auto_sync->isChecked())
477  {
478  set_config_at_imrecman();
479  }
480 }
visionx::ImageRecorderWidgetController::add_image_provider_conf_widget
void add_image_provider_conf_widget(const std::string &image_provider_name, const imrec::Config &config)
Definition: ImageRecorderWidgetController.cpp:221
visionx::ImageRecorderWidgetController::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: ImageRecorderWidgetController.cpp:82
visionx::ImageRecorderWidgetController::to_config_map
std::map< std::string, imrec::Config > to_config_map()
Definition: ImageRecorderWidgetController.cpp:249
visionx::ImageRecorderWidgetController::update_statuses
void update_statuses(const std::map< std::string, visionx::imrec::Status > &statuses)
Definition: ImageRecorderWidgetController.cpp:194
visionx::ImageRecorderWidgetController::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: ImageRecorderWidgetController.cpp:93
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:77
armarx::status
status
Definition: FiniteStateMachine.h:244
imrec.h
visionx::ImageRecorderWidgetController::build_ui_from_config
void build_ui_from_config(const std::map< std::string, imrec::Config > &configs)
Definition: ImageRecorderWidgetController.cpp:167
armarx::core::time::DateTime::toMicroSeconds
std::int64_t toMicroSeconds() const
Definition: DateTime.h:101
visionx::ViewMode::StatusOnly
@ StatusOnly
enabled
std::atomic< bool > * enabled
Definition: RemoteGuiWidgetController.cpp:75
visionx::ImageProviderConfigWidget::imageProviderRemoved
void imageProviderRemoved(const std::string &name)
visionx::ImageRecorderWidgetController::getConfigDialog
QPointer< QDialog > getConfigDialog(QWidget *parent) override
getConfigDialog returns a pointer to the a configuration widget of this controller.
Definition: ImageRecorderWidgetController.cpp:142
visionx::ImageRecorderWidgetController::ImageRecorderWidgetController
ImageRecorderWidgetController()
Definition: ImageRecorderWidgetController.cpp:44
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:41
visionx::ViewMode::Full
@ Full
armarx::SimpleConfigDialog::addProxyFinder
void addProxyFinder(const std::vector< EntryData > &entryData)
Definition: SimpleConfigDialog.h:103
visionx::ImageProviderConfigWidget::imageProviderRenamed
void imageProviderRenamed(const std::string &old_name, const std::string &new_name)
visionx::ImageProviderConfigWidget
Definition: ImageProviderConfigWidget.h:59
visionx::ImageRecorderWidgetController::loadSettings
void loadSettings(QSettings *settings) override
Implement to load the settings that are part of the GUI configuration.
Definition: ImageRecorderWidgetController.cpp:119
visionx::ImageRecorderWidgetController::configured
void configured() override
This function must be implemented by the user, if he supplies a config dialog.
Definition: ImageRecorderWidgetController.cpp:156
visionx::ImageRecorderWidgetController::saveSettings
void saveSettings(QSettings *settings) override
Implement to save the settings as part of the GUI configuration.
Definition: ImageRecorderWidgetController.cpp:132
ImageRecorderWidgetController.h
json_conversions.h
armarx::ArmarXWidgetController::getWidget
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
Definition: ArmarXWidgetController.cpp:54
visionx::ImageRecorderWidgetController::onExitComponent
void onExitComponent() override
Hook for subclass.
Definition: ImageRecorderWidgetController.cpp:111
visionx::ViewMode
ViewMode
Definition: ImageProviderConfigWidget.h:53
visionx::ImageRecorderWidgetController::onDisconnectComponent
void onDisconnectComponent() override
Hook for subclass.
Definition: ImageRecorderWidgetController.cpp:103
armarx::SimpleConfigDialog
A config-dialog containing one (or multiple) proxy finders.
Definition: SimpleConfigDialog.h:84