TopicReplayerWidgetController.cpp
Go to the documentation of this file.
1/*
2
3 * This file is part of ArmarX.
4 *
5 * ArmarX is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * ArmarX is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * \package ArmarXGui::gui-plugins::TopicReplayerWidgetController
18 * \author Stefan Reither ( stef dot reither at web dot de )
19 * \date 2016
20 * \copyright http://www.gnu.org/licenses/gpl-2.0.txt
21 * GNU General Public License
22 */
23
25
26#include <string>
27
28#include <QDateTime>
29#include <QFileDialog>
30#include <QMessageBox>
31#include <QProgressDialog>
32#include <qnamespace.h>
33
34#include <IceUtil/UUID.h>
35
39
40#define REQUEST_TIMEKEEPER_TIME_FREQUENCY 30
41
42namespace armarx
43{
48
52
53 void
55 {
56 }
57
58 void
60 {
61 }
62
63 void
65 {
66 this->setPausedGuiMode();
67 widget.pushButton_play->setEnabled(false);
68 widget.pushButton_load->setFocus();
69 }
70
71 void
73 {
74 connect(widget.pushButton_load, SIGNAL(clicked()), this, SLOT(loadFile()));
75 connect(widget.pushButton_play, SIGNAL(clicked()), this, SLOT(resumeReplay()));
76 connect(widget.pushButton_pause, SIGNAL(clicked()), this, SLOT(pauseReplay()));
77 connect(widget.checkBox_loop, SIGNAL(toggled()), this, SLOT(loopReplay()));
78 connect(widget.horizontalSlider_replaySpeed,
79 SIGNAL(valueChanged(int)),
80 this,
81 SLOT(replaySpeedSliderChanged()));
82 connect(widget.doubleSpinBox_replaySpeed,
83 SIGNAL(editingFinished()),
84 this,
85 SLOT(replaySpeedSpinBoxChanged()));
86
87 connect(widget.horizontalSlider_replayPosition,
88 SIGNAL(valueChanged(int)),
89 this,
90 SLOT(replayPositionSliderChanged()));
91
92 connect(widget.horizontalSlider_replayPosition,
93 SIGNAL(sliderPressed()),
94 this,
95 SLOT(stopSliderUpdater()));
96 connect(widget.horizontalSlider_replayPosition,
97 SIGNAL(sliderReleased()),
98 this,
99 SLOT(startSliderUpdater()));
100
101 connect(widget.horizontalSlider_replayPosition,
102 SIGNAL(sliderReleased()),
103 this,
104 SLOT(jumpToPosition()));
105 }
106
107 void
108 TopicReplayerWidgetController::onDisconnectComponent()
109 {
110 this->killTimer(replayPositionSliderUpdaterTimer);
111 if (topicReplayer)
112 {
113 getArmarXManager()->removeObjectNonBlocking(topicReplayer->getName());
114 }
115 }
116
117 void
118 armarx::TopicReplayerWidgetController::loadFile()
119 {
120 widget.pushButton_load->setEnabled(false);
121
122 QFileDialog fileDialog(getWidget(), "Open Topic Recording File");
123 fileDialog.setFileMode(QFileDialog::ExistingFile);
124 QStringList filters;
125 filters << tr("TopicRecorder files (*.bag)");
126 filters << tr("All files (*.*)");
127 fileDialog.setNameFilters(filters);
128
129
130 fileDialog.setViewMode(QFileDialog::Detail);
131 fileDialog.setVisible(true);
132
133 QString fileName;
134 if (fileDialog.exec() == QDialog::Accepted)
135 {
136 fileName = fileDialog.selectedFiles().first();
137 if (topicReplayer)
138 {
139 getArmarXManager()->removeObjectBlocking(topicReplayer->getName());
140 }
141
142 if (!fileName.isEmpty())
143 {
145 properties->setProperty("ArmarX.TopicReplayer.RecordFile", fileName.toStdString());
146 topicReplayer = armarx::Component::create<TopicReplayer>(properties);
147 topicReplayer->setAutoplay(false);
148 widget.doubleSpinBox_replaySpeed->setValue(1.0);
149 QProgressDialog dProgress;
150 dProgress.setMaximum(0);
151 dProgress.setMinimum(0);
152 getArmarXManager()->addObject(topicReplayer,
153 false,
154 topicReplayer->getDefaultName() +
155 IceUtil::generateUUID());
156 dProgress.show();
157 // waiting for TopicReplayer to set up
158 while (topicReplayer->getObjectScheduler()->getObject()->getState() <
159 eManagedIceObjectStarted)
160 {
161 usleep(100000);
162 }
163
164 // Checks whether opened file has database-format, if not, abort
165 if (topicReplayer->getReplayLength().toMilliSeconds() == 0)
166 {
167 this->setPausedGuiMode();
168 widget.pushButton_play->setEnabled(false);
169 widget.lineEdit_fileName->setText("");
170 widget.horizontalSlider_replayPosition->setValue(0);
171 widget.horizontalSlider_replayPosition->setEnabled(false);
172 widget.horizontalSlider_replaySpeed->setEnabled(false);
173 widget.listWidget_topics->clear();
174
175 QMessageBox msg;
176 msg.setWindowTitle("TopicReplayerGui");
177 msg.setText("The format of the selected file is not supported.");
178 msg.setIcon(QMessageBox::Warning);
179 msg.exec();
180 }
181 else
182 {
183 widget.lineEdit_fileName->setText(fileName);
184 this->fillListOfRecordedTopics();
185 this->setUpReplayPositionSlider();
186 widget.pushButton_play->setEnabled(true);
187 widget.horizontalSlider_replayPosition->setEnabled(true);
188 widget.horizontalSlider_replaySpeed->setEnabled(true);
189
190 replayPositionSliderUpdaterTimer =
191 this->startTimer(REQUEST_TIMEKEEPER_TIME_FREQUENCY);
192 }
193 }
194 }
195
196 widget.pushButton_load->setEnabled(true);
197 }
198
199 void
200 armarx::TopicReplayerWidgetController::pauseReplay()
201 {
202 this->setPausedGuiMode();
203
204 if (topicReplayer)
205 {
206 topicReplayer->pauseReplay();
207 }
208 }
209
210 void
211 armarx::TopicReplayerWidgetController::loopReplay()
212 {
213 // if (topicReplayer)
214 // {
215 // topicReplayer->setLoop(widget.checkBox_loop->isChecked());
216 // }
217 }
218
219 void
220 armarx::TopicReplayerWidgetController::resumeReplay()
221 {
222 if (topicReplayer && !(this->replayLength.toMilliSeconds() ==
223 widget.horizontalSlider_replayPosition->value()))
224 {
225 std::vector<std::string> replayingTopics;
226 for (int i = 0; i < widget.listWidget_topics->count(); i++)
227 {
228 auto item = widget.listWidget_topics->item(i);
229 if (item->checkState() == Qt::Checked)
230 {
231 replayingTopics.push_back(item->text().toStdString());
232 }
233 }
234 topicReplayer->setReplayingTopics(replayingTopics);
235
236 setReplaySpeed();
237 topicReplayer->resumeReplay();
238
239 this->setPlayingGuiMode();
240 }
241 }
242
243 void
244 armarx::TopicReplayerWidgetController::setReplaySpeed()
245 {
246 if (topicReplayer)
247 {
248 topicReplayer->setReplaySpeed(widget.doubleSpinBox_replaySpeed->value());
249 }
250 }
251
252 void
253 armarx::TopicReplayerWidgetController::replaySpeedSliderChanged()
254 {
255 updateReplayPositionSlider();
256
257 double spinBoxValue = 0.0;
258 int sliderValue = widget.horizontalSlider_replaySpeed->value();
259 int m = widget.horizontalSlider_replaySpeed->maximum() / 2;
260
261 if (sliderValue < m)
262 {
263 spinBoxValue = (double)sliderValue / (double)m;
264 }
265 else
266 {
267 spinBoxValue = 1 + 9.0 * ((double)sliderValue / (double)m - 1);
268 }
269
270 widget.doubleSpinBox_replaySpeed->setValue(spinBoxValue);
271 setReplaySpeed();
272 }
273
274 void
275 TopicReplayerWidgetController::replaySpeedSpinBoxChanged()
276 {
277 double spinBoxValue = widget.doubleSpinBox_replaySpeed->value();
278 int sliderValue = 0;
279 int m = widget.horizontalSlider_replaySpeed->maximum() / 2;
280
281 if (spinBoxValue <= 1.0)
282 {
283 sliderValue = (int)(spinBoxValue * m);
284 }
285 else
286 {
287 sliderValue = (int)(m * (1 + (spinBoxValue - 1) / 9));
288 }
289
290 widget.horizontalSlider_replaySpeed->setValue(sliderValue);
291 setReplaySpeed();
292 }
293
294 void
295 TopicReplayerWidgetController::fillListOfRecordedTopics()
296 {
297 QListWidget* topicsListWidget = widget.listWidget_topics;
298 topicsListWidget->clear();
299
300 const Qt::CheckState checkState = widget.checkBoxLoadTopicsEnabled->checkState();
301
302 if (this->topicReplayer)
303 {
304 std::vector<std::string> recordedTopics = topicReplayer->getRecordedTopics();
305 std::sort(recordedTopics.begin(), recordedTopics.end());
306
307 for (std::string topic : recordedTopics)
308 {
309 QListWidgetItem* item = new QListWidgetItem;
310 item->setData(Qt::DisplayRole, QString::fromStdString(topic));
311 item->setData(Qt::CheckStateRole, checkState);
312 topicsListWidget->addItem(item);
313 }
314 }
315 }
316
317 void
318 TopicReplayerWidgetController::setPausedGuiMode()
319 {
320 widget.pushButton_pause->setEnabled(false);
321
322 widget.pushButton_load->setEnabled(true);
323 widget.pushButton_play->setEnabled(true);
324 widget.pushButton_play->setFocus();
325 widget.listWidget_topics->setEnabled(true);
326
327 this->stopSliderUpdater();
328 }
329
330 void
331 TopicReplayerWidgetController::setPlayingGuiMode()
332 {
333 widget.pushButton_load->setEnabled(false);
334 widget.listWidget_topics->setEnabled(false);
335 widget.pushButton_play->setEnabled(false);
336
337 widget.pushButton_pause->setEnabled(true);
338 widget.pushButton_pause->setFocus();
339
340 widget.horizontalSlider_replayPosition->setEnabled(true);
341 widget.horizontalSlider_replaySpeed->setEnabled(true);
342
343 this->startSliderUpdater();
344 }
345
346 void
347 TopicReplayerWidgetController::setUpReplayPositionSlider()
348 {
349 if (topicReplayer)
350 {
351 replayLength = topicReplayer->getReplayLength();
352 QTime t(0, 0, 0, 0);
353 t = t.addMSecs((int)replayLength.toMilliSeconds());
354 widget.label_replayLength->setText(t.toString("h:mm:ss.zzz"));
355 widget.horizontalSlider_replayPosition->setMaximum((int)replayLength.toMilliSeconds());
356 widget.horizontalSlider_replayPosition->setTickInterval(
357 (int)replayLength.toMilliSeconds() / 100);
358 widget.horizontalSlider_replayPosition->setSingleStep(
359 (int)replayLength.toMilliSeconds() / 100);
360 widget.horizontalSlider_replayPosition->setValue(0);
361 }
362 }
363
364 void
365 TopicReplayerWidgetController::updateReplayPositionSlider()
366 {
367 if (topicReplayer)
368 {
369 int currentTime = (int)topicReplayer->getCurrentTimePosition().toMilliSeconds();
370 widget.horizontalSlider_replayPosition->setValue(currentTime);
371 if (currentTime >= replayLength.toMilliSeconds())
372 {
373 this->pauseReplay();
374
375 if (widget.checkBox_loop->isChecked())
376 {
377 widget.horizontalSlider_replayPosition->setSliderPosition(0);
378 jumpToPosition();
379 resumeReplay();
380 }
381 }
382 }
383 }
384
385 void
386 TopicReplayerWidgetController::replayPositionSliderChanged()
387 {
388 QTime t(0, 0, 0, 0);
389 t = t.addMSecs(widget.horizontalSlider_replayPosition->value());
390 widget.label_replayPosition->setText(t.toString("h:mm:ss.zzz"));
391 }
392
393 void
394 TopicReplayerWidgetController::timerEvent(QTimerEvent* event)
395 {
396 if (event->timerId() == this->replayPositionSliderUpdaterTimer)
397 {
398 this->updateReplayPositionSlider();
399 }
400 }
401
402 void
403 TopicReplayerWidgetController::stopSliderUpdater()
404 {
405 this->killTimer(replayPositionSliderUpdaterTimer);
406 }
407
408 void
409 TopicReplayerWidgetController::startSliderUpdater()
410 {
411 replayPositionSliderUpdaterTimer = this->startTimer(REQUEST_TIMEKEEPER_TIME_FREQUENCY);
412 }
413
414 void
415 TopicReplayerWidgetController::jumpToPosition()
416 {
417 if (topicReplayer)
418 {
419 topicReplayer->jumpToPosition(
420 IceUtil::Time().milliSeconds(widget.horizontalSlider_replayPosition->value()));
421 }
422 }
423} // namespace armarx
#define REQUEST_TIMEKEEPER_TIME_FREQUENCY
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
static TPtr create(Ice::PropertiesPtr properties=Ice::createProperties(), const std::string &configName="", const std::string &configDomain="ArmarX")
Factory method for a component.
Definition Component.h:116
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
void loadSettings(QSettings *settings) override
void saveSettings(QSettings *settings) override
~TopicReplayerWidgetController() override
Controller destructor.
Ice::PropertiesPtr createProperties()
::IceInternal::Handle<::Ice::Properties > PropertiesPtr
This file offers overloads of toIce() and fromIce() functions for STL container types.