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 
27 #include <QProgressDialog>
28 #include <qnamespace.h>
29 #include <string>
30 
34 
35 #include <QFileDialog>
36 #include <QDateTime>
37 #include <QMessageBox>
38 #include <IceUtil/UUID.h>
39 
40 #define REQUEST_TIMEKEEPER_TIME_FREQUENCY 30
41 
42 namespace armarx
43 {
45  {
46  widget.setupUi(getWidget());
47  }
48 
49 
51  {
52  }
53 
54 
56  {
57 
58  }
59 
61  {
62 
63  }
64 
65 
67  {
68  this->setPausedGuiMode();
69  widget.pushButton_play->setEnabled(false);
70  widget.pushButton_load->setFocus();
71  }
72 
73 
75  {
76  connect(widget.pushButton_load, SIGNAL(clicked()), this, SLOT(loadFile()));
77  connect(widget.pushButton_play, SIGNAL(clicked()), this, SLOT(resumeReplay()));
78  connect(widget.pushButton_pause, SIGNAL(clicked()), this, SLOT(pauseReplay()));
79  connect(widget.checkBox_loop, SIGNAL(toggled()), this, SLOT(loopReplay()));
80  connect(widget.horizontalSlider_replaySpeed, SIGNAL(valueChanged(int)), this, SLOT(replaySpeedSliderChanged()));
81  connect(widget.doubleSpinBox_replaySpeed, SIGNAL(editingFinished()), this, SLOT(replaySpeedSpinBoxChanged()));
82 
83  connect(widget.horizontalSlider_replayPosition, SIGNAL(valueChanged(int)), this, SLOT(replayPositionSliderChanged()));
84 
85  connect(widget.horizontalSlider_replayPosition, SIGNAL(sliderPressed()), this, SLOT(stopSliderUpdater()));
86  connect(widget.horizontalSlider_replayPosition, SIGNAL(sliderReleased()), this, SLOT(startSliderUpdater()));
87 
88  connect(widget.horizontalSlider_replayPosition, SIGNAL(sliderReleased()), this, SLOT(jumpToPosition()));
89  }
90 
91  void TopicReplayerWidgetController::onDisconnectComponent()
92  {
93  this->killTimer(replayPositionSliderUpdaterTimer);
94  if (topicReplayer)
95  {
96  getArmarXManager()->removeObjectNonBlocking(topicReplayer->getName());
97  }
98  }
99 
100  void armarx::TopicReplayerWidgetController::loadFile()
101  {
102  widget.pushButton_load->setEnabled(false);
103 
104  QFileDialog fileDialog(getWidget(), "Open Topic Recording File");
105  fileDialog.setFileMode(QFileDialog::ExistingFile);
106  QStringList filters;
107  filters << tr("TopicRecorder files (*.bag)");
108  filters << tr("All files (*.*)");
109  fileDialog.setNameFilters(filters);
110 
111 
112  fileDialog.setViewMode(QFileDialog::Detail);
113  fileDialog.setVisible(true);
114 
115  QString fileName;
116  if (fileDialog.exec() == QDialog::Accepted)
117  {
118  fileName = fileDialog.selectedFiles().first();
119  if (topicReplayer)
120  {
121  getArmarXManager()->removeObjectBlocking(topicReplayer->getName());
122  }
123 
124  if (!fileName.isEmpty())
125  {
127  properties->setProperty("ArmarX.TopicReplayer.RecordFile", fileName.toStdString());
128  topicReplayer = armarx::Component::create<TopicReplayer>(properties);
129  topicReplayer->setAutoplay(false);
130  widget.doubleSpinBox_replaySpeed->setValue(1.0);
131  QProgressDialog dProgress;
132  dProgress.setMaximum(0);
133  dProgress.setMinimum(0);
134  getArmarXManager()->addObject(topicReplayer, false, topicReplayer->getDefaultName() + IceUtil::generateUUID());
135  dProgress.show();
136  // waiting for TopicReplayer to set up
137  while (topicReplayer->getObjectScheduler()->getObject()->getState() < eManagedIceObjectStarted)
138  {
139  usleep(100000);
140  }
141 
142  // Checks whether opened file has database-format, if not, abort
143  if (topicReplayer->getReplayLength().toMilliSeconds() == 0)
144  {
145  this->setPausedGuiMode();
146  widget.pushButton_play->setEnabled(false);
147  widget.lineEdit_fileName->setText("");
148  widget.horizontalSlider_replayPosition->setValue(0);
149  widget.horizontalSlider_replayPosition->setEnabled(false);
150  widget.horizontalSlider_replaySpeed->setEnabled(false);
151  widget.listWidget_topics->clear();
152 
153  QMessageBox msg;
154  msg.setWindowTitle("TopicReplayerGui");
155  msg.setText("The format of the selected file is not supported.");
156  msg.setIcon(QMessageBox::Warning);
157  msg.exec();
158  }
159  else
160  {
161  widget.lineEdit_fileName->setText(fileName);
162  this->fillListOfRecordedTopics();
163  this->setUpReplayPositionSlider();
164  widget.pushButton_play->setEnabled(true);
165  widget.horizontalSlider_replayPosition->setEnabled(true);
166  widget.horizontalSlider_replaySpeed->setEnabled(true);
167 
168  replayPositionSliderUpdaterTimer = this->startTimer(REQUEST_TIMEKEEPER_TIME_FREQUENCY);
169  }
170  }
171  }
172 
173  widget.pushButton_load->setEnabled(true);
174  }
175 
176  void armarx::TopicReplayerWidgetController::pauseReplay()
177  {
178  this->setPausedGuiMode();
179 
180  if (topicReplayer)
181  {
182  topicReplayer->pauseReplay();
183  }
184  }
185 
186  void armarx::TopicReplayerWidgetController::loopReplay()
187  {
188  // if (topicReplayer)
189  // {
190  // topicReplayer->setLoop(widget.checkBox_loop->isChecked());
191  // }
192  }
193 
194  void armarx::TopicReplayerWidgetController::resumeReplay()
195  {
196  if (topicReplayer && !(this->replayLength.toMilliSeconds() == widget.horizontalSlider_replayPosition->value()))
197  {
198  std::vector<std::string> replayingTopics;
199  for (int i = 0; i < widget.listWidget_topics->count(); i++)
200  {
201  auto item = widget.listWidget_topics->item(i);
202  if (item->checkState() == Qt::Checked)
203  {
204  replayingTopics.push_back(item->text().toStdString());
205  }
206  }
207  topicReplayer->setReplayingTopics(replayingTopics);
208 
209  setReplaySpeed();
210  topicReplayer->resumeReplay();
211 
212  this->setPlayingGuiMode();
213  }
214  }
215 
216  void armarx::TopicReplayerWidgetController::setReplaySpeed()
217  {
218  if (topicReplayer)
219  {
220  topicReplayer->setReplaySpeed(widget.doubleSpinBox_replaySpeed->value());
221  }
222  }
223 
224  void armarx::TopicReplayerWidgetController::replaySpeedSliderChanged()
225  {
226  updateReplayPositionSlider();
227 
228  double spinBoxValue = 0.0;
229  int sliderValue = widget.horizontalSlider_replaySpeed->value();
230  int m = widget.horizontalSlider_replaySpeed->maximum() / 2;
231 
232  if (sliderValue < m)
233  {
234  spinBoxValue = (double) sliderValue / (double) m;
235  }
236  else
237  {
238  spinBoxValue = 1 + 9.0 * ((double) sliderValue / (double) m - 1);
239  }
240 
241  widget.doubleSpinBox_replaySpeed->setValue(spinBoxValue);
242  setReplaySpeed();
243  }
244 
245  void TopicReplayerWidgetController::replaySpeedSpinBoxChanged()
246  {
247  double spinBoxValue = widget.doubleSpinBox_replaySpeed->value();
248  int sliderValue = 0;
249  int m = widget.horizontalSlider_replaySpeed->maximum() / 2;
250 
251  if (spinBoxValue <= 1.0)
252  {
253  sliderValue = (int)(spinBoxValue * m);
254  }
255  else
256  {
257  sliderValue = (int)(m * (1 + (spinBoxValue - 1) / 9));
258  }
259 
260  widget.horizontalSlider_replaySpeed->setValue(sliderValue);
261  setReplaySpeed();
262  }
263 
264 
265  void TopicReplayerWidgetController::fillListOfRecordedTopics()
266  {
267  QListWidget* topicsListWidget = widget.listWidget_topics;
268  topicsListWidget->clear();
269 
270  const Qt::CheckState checkState = widget.checkBoxLoadTopicsEnabled->checkState();
271 
272  if (this->topicReplayer)
273  {
274  std::vector<std::string> recordedTopics = topicReplayer->getRecordedTopics();
275  std::sort(recordedTopics.begin(), recordedTopics.end());
276 
277  for (std::string topic : recordedTopics)
278  {
279  QListWidgetItem* item = new QListWidgetItem;
280  item->setData(Qt::DisplayRole, QString::fromStdString(topic));
281  item->setData(Qt::CheckStateRole, checkState);
282  topicsListWidget->addItem(item);
283  }
284  }
285  }
286 
287  void TopicReplayerWidgetController::setPausedGuiMode()
288  {
289  widget.pushButton_pause->setEnabled(false);
290 
291  widget.pushButton_load->setEnabled(true);
292  widget.pushButton_play->setEnabled(true);
293  widget.pushButton_play->setFocus();
294  widget.listWidget_topics->setEnabled(true);
295 
296  this->stopSliderUpdater();
297  }
298 
299  void TopicReplayerWidgetController::setPlayingGuiMode()
300  {
301  widget.pushButton_load->setEnabled(false);
302  widget.listWidget_topics->setEnabled(false);
303  widget.pushButton_play->setEnabled(false);
304 
305  widget.pushButton_pause->setEnabled(true);
306  widget.pushButton_pause->setFocus();
307 
308  widget.horizontalSlider_replayPosition->setEnabled(true);
309  widget.horizontalSlider_replaySpeed->setEnabled(true);
310 
311  this->startSliderUpdater();
312  }
313 
314  void TopicReplayerWidgetController::setUpReplayPositionSlider()
315  {
316  if (topicReplayer)
317  {
318  replayLength = topicReplayer->getReplayLength();
319  QTime t(0, 0, 0, 0);
320  t = t.addMSecs((int)replayLength.toMilliSeconds());
321  widget.label_replayLength->setText(t.toString("h:mm:ss.zzz"));
322  widget.horizontalSlider_replayPosition->setMaximum((int) replayLength.toMilliSeconds());
323  widget.horizontalSlider_replayPosition->setTickInterval((int) replayLength.toMilliSeconds() / 100);
324  widget.horizontalSlider_replayPosition->setSingleStep((int) replayLength.toMilliSeconds() / 100);
325  widget.horizontalSlider_replayPosition->setValue(0);
326  }
327  }
328 
329  void TopicReplayerWidgetController::updateReplayPositionSlider()
330  {
331  if (topicReplayer)
332  {
333  int currentTime = (int) topicReplayer->getCurrentTimePosition().toMilliSeconds();
334  widget.horizontalSlider_replayPosition->setValue(currentTime);
335  if (currentTime >= replayLength.toMilliSeconds())
336  {
337  this->pauseReplay();
338 
339  if (widget.checkBox_loop->isChecked())
340  {
341  widget.horizontalSlider_replayPosition->setSliderPosition(0);
342  jumpToPosition();
343  resumeReplay();
344  }
345  }
346  }
347  }
348 
349  void TopicReplayerWidgetController::replayPositionSliderChanged()
350  {
351  QTime t(0, 0, 0, 0);
352  t = t.addMSecs(widget.horizontalSlider_replayPosition->value());
353  widget.label_replayPosition->setText(t.toString("h:mm:ss.zzz"));
354  }
355 
356 
357  void TopicReplayerWidgetController::timerEvent(QTimerEvent* event)
358  {
359  if (event->timerId() == this->replayPositionSliderUpdaterTimer)
360  {
361  this->updateReplayPositionSlider();
362  }
363  }
364 
365  void TopicReplayerWidgetController::stopSliderUpdater()
366  {
367  this->killTimer(replayPositionSliderUpdaterTimer);
368  }
369 
370  void TopicReplayerWidgetController::startSliderUpdater()
371  {
372  replayPositionSliderUpdaterTimer = this->startTimer(REQUEST_TIMEKEEPER_TIME_FREQUENCY);
373  }
374 
375  void TopicReplayerWidgetController::jumpToPosition()
376  {
377  if (topicReplayer)
378  {
379  topicReplayer->jumpToPosition(IceUtil::Time().milliSeconds(widget.horizontalSlider_replayPosition->value()));
380  }
381  }
382 }
ArmarXManager.h
REQUEST_TIMEKEEPER_TIME_FREQUENCY
#define REQUEST_TIMEKEEPER_TIME_FREQUENCY
Definition: TopicReplayerWidgetController.cpp:40
armarx::ManagedIceObject::getArmarXManager
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
Definition: ManagedIceObject.cpp:348
TopicReplayerWidgetController.h
armarx::TopicReplayerWidgetController::~TopicReplayerWidgetController
~TopicReplayerWidgetController() override
Controller destructor.
Definition: TopicReplayerWidgetController.cpp:50
armarx::TopicReplayerWidgetController::onInitComponent
void onInitComponent() override
Definition: TopicReplayerWidgetController.cpp:66
IceInternal::Handle< ::Ice::Properties >
armarx::TopicReplayerWidgetController::saveSettings
void saveSettings(QSettings *settings) override
Definition: TopicReplayerWidgetController.cpp:60
armarx::TopicReplayerWidgetController::TopicReplayerWidgetController
TopicReplayerWidgetController()
Controller Constructor.
Definition: TopicReplayerWidgetController.cpp:44
Ice::createProperties
Ice::PropertiesPtr createProperties()
armarx::TopicReplayerWidgetController::loadSettings
void loadSettings(QSettings *settings) override
Definition: TopicReplayerWidgetController.cpp:55
ArmarXObjectScheduler.h
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
CMakePackageFinder.h
armarx::TopicReplayerWidgetController::onConnectComponent
void onConnectComponent() override
Definition: TopicReplayerWidgetController.cpp:74
armarx::ArmarXWidgetController::getWidget
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
Definition: ArmarXWidgetController.cpp:54
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28