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
38namespace
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
81void
83{
85
86 if (not m_imrecman_name.empty())
87 {
88 usingProxy(m_imrecman_name);
89 }
90}
91
92void
94{
96
97 getProxy(m_imrecman, m_imrecman_name);
98
100}
101
102void
109
110void
117
118void
120{
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
131void
133{
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
141QPointer<QDialog>
143{
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
155void
157{
159
160 if (m_config_dialog)
161 {
162 m_imrecman_name = m_config_dialog->getProxyName(::config_key_imrecman);
163 }
164}
165
166void
168 const std::map<std::string, imrec::Config>& configs)
169{
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
193void
195 const std::map<std::string, visionx::imrec::Status>& statuses)
196{
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
220void
222 const std::string& image_provider_name,
223 const imrec::Config& config)
224{
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
248std::map<std::string, visionx::imrec::Config>
250{
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
275void
276visionx::ImageRecorderWidgetController::init_gui()
277{
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
288void
289visionx::ImageRecorderWidgetController::uninit_gui()
290{
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
301void
302visionx::ImageRecorderWidgetController::poll_statuses()
303{
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
319void
320visionx::ImageRecorderWidgetController::get_config_from_imrecman()
321{
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
337void
338visionx::ImageRecorderWidgetController::set_config_at_imrecman()
339{
341
342 try
343 {
344 m_imrecman->configureRecordings(to_config_map());
345 }
346 catch (...)
347 {
348 // pass
349 }
350}
351
352void
353visionx::ImageRecorderWidgetController::add_image_provider()
354{
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
362void
363visionx::ImageRecorderWidgetController::copy_config_json_to_clipboard()
364{
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
373void
374visionx::ImageRecorderWidgetController::update_start_rec_label()
375{
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
384void
385visionx::ImageRecorderWidgetController::start_recordings()
386{
388
389 try
390 {
391 m_imrecman->configureRecordings(to_config_map());
392 m_imrecman->startRecordings();
393 }
394 catch (...)
395 {
396 // pass
397 }
398}
399
400void
401visionx::ImageRecorderWidgetController::stop_recordings()
402{
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
417void
418visionx::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
442void
443visionx::ImageRecorderWidgetController::rename_image_provider(const std::string& old_name,
444 const std::string& new_name)
445{
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
466void
467visionx::ImageRecorderWidgetController::remove_image_provider(const std::string& name)
468{
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}
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
IceManagerPtr getIceManager() const
Returns the IceManager.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
A config-dialog containing one (or multiple) proxy finders.
void addProxyFinder(const std::vector< EntryData > &entryData)
void imageProviderRemoved(const std::string &name)
void imageProviderRenamed(const std::string &old_name, const std::string &new_name)
void onInitComponent() override
Pure virtual hook for the subclass.
void onDisconnectComponent() override
Hook for subclass.
void loadSettings(QSettings *settings) override
Implement to load the settings that are part of the GUI configuration.
void saveSettings(QSettings *settings) override
Implement to save the settings as part of the GUI configuration.
void add_image_provider_conf_widget(const std::string &image_provider_name, const imrec::Config &config)
std::map< std::string, imrec::Config > to_config_map()
void build_ui_from_config(const std::map< std::string, imrec::Config > &configs)
void onConnectComponent() override
Pure virtual hook for the subclass.
void configured() override
This function must be implemented by the user, if he supplies a config dialog.
QPointer< QDialog > getConfigDialog(QWidget *parent) override
getConfigDialog returns a pointer to the a configuration widget of this controller.
void update_statuses(const std::map< std::string, visionx::imrec::Status > &statuses)
#define ARMARX_TRACE
Definition trace.h:77