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