Fraxinus  16.5.0-fx-rc7
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxMainWindowActions.cpp
Go to the documentation of this file.
1 #include "cxMainWindowActions.h"
2 
3 #include <QtConcurrent>
4 #include <QWidget>
5 #include <QFileDialog>
6 #include <QAction>
7 #include <QScreen>
8 #include <QDesktopWidget>
9 #include <QMessageBox>
10 #include <QApplication>
11 #include <QDesktopServices>
12 
13 #include "boost/bind.hpp"
14 #include "boost/function.hpp"
15 #include "cxReporter.h"
16 #include "cxLogger.h"
17 #include "cxConfig.h"
18 #include "cxDataLocations.h"
19 #include "cxProfile.h"
20 #include "cxLogicManager.h"
21 #include "cxTrackingService.h"
22 #include "cxSettings.h"
23 #include "cxVideoService.h"
24 #include "cxNavigation.h"
25 #include "cxImage.h"
26 #include "cxPatientModelService.h"
27 #include "cxViewService.h"
28 #include "cxViewGroupData.h"
30 #include "cxVisServices.h"
31 #include "cxVLCRecorder.h"
32 #include "cxImportDataDialog.h"
33 #include "cxExportDataDialog.h"
35 #include "cxViewCollectionWidget.h"
37 
38 namespace cx
39 {
40 
42  QObject(parent),
43  mServices(services),
44  mScreenShotWriter(ScreenShotImageWriter::create(services->patient()))
45 {
46  this->createActions();
47 }
48 
49 QAction* MainWindowActions::getAction(QString uid)
50 {
51  if (!mActions.count(uid))
52  CX_LOG_ERROR() << QString("Could not find action %1 in MainWindowActions object").arg(uid);
53  return mActions[uid];
54 }
55 
56 void MainWindowActions::createActions()
57 {
58  this->createAction("GotoDocumentation", "Web Documentation",
59  QIcon(":/icons/open_icon_library/applications-internet.png"),
60  QKeySequence(""), "",
61  &MainWindowActions::onGotoDocumentation);
62 
63  this->createAction("StartLogConsole", "Start Log Console",
64  QIcon(),
65  QKeySequence("Ctrl+D"), "Open Log Console as external application",
66  &MainWindowActions::onStartLogConsole);
67 
68  this->createAction("ShootScreen", "Shoot Screen",
69  QIcon(":/icons/screenshot-screen.png"),
70  QKeySequence("Ctrl+f"), "Save a screenshot to the patient folder.",
71  &MainWindowActions::shootScreen);
72 
73  this->createAction("ShootWindow", "Shoot Window",
74  QIcon(":/icons/screenshot-window.png"),
75  QKeySequence("Ctrl+Shift+f"), "Save an image of the application to the patient folder.",
76  &MainWindowActions::shootWindow);
77 
78  mRecordFullscreenStreamingAction = this->createAction("RecordFullscreen", "Record Fullscreen",
79  QIcon(),
80  QKeySequence("F8"), "Record a video of the full screen.",
81  &MainWindowActions::recordFullscreen);
82  connect(vlc(), &VLCRecorder::stateChanged, this, &MainWindowActions::updateRecordFullscreenActionSlot);
83  this->updateRecordFullscreenActionSlot();
84 
85  mShowPointPickerAction = this->createAction("ShowPointPicker", "Point Picker",
86  QIcon(":/icons/point_picker.png"),
87  QKeySequence(""), "Activate the 3D Point Picker Probe",
88  &MainWindowActions::togglePointPickerActionSlot);
89  mShowPointPickerAction->setCheckable(true);
90 
91  if (viewService()->getGroup(0))
92  connect(viewService()->getGroup(0).get(), &ViewGroupData::optionsChanged, this, &MainWindowActions::updatePointPickerActionSlot);
93  this->updatePointPickerActionSlot();
94 
95  mStartStreamingAction = this->createAction("StartStreaming", "Start Streaming",
96  QIcon(":/icons/open_icon_library/.png"),
97  QKeySequence("Ctrl+V"), "",
98  &MainWindowActions::toggleStreamingSlot);
99  connect(videoService().get(), &VideoService::connected, this, &MainWindowActions::updateStreamingActionSlot);
100  this->updateStreamingActionSlot();
101 
102  this->createAction("CenterToImageCenter", "Center Image",
103  QIcon(":/icons/center_image.png"),
104  QKeySequence(), "",
105  &MainWindowActions::centerToImageCenterSlot);
106 
107  this->createAction("CenterToTooltip", "Center Tool",
108  QIcon(":/icons/center_tool.png"),
109  QKeySequence(""), "",
110  &MainWindowActions::centerToTooltipSlot);
111 
112  this->createPatientActions();
113  this->createTrackingActions();
114 }
115 
116 void MainWindowActions::createTrackingActions()
117 {
118  this->createAction("ConfigureTools", "Tool configuration",
119  QIcon(), QKeySequence(), "",
120  &MainWindowActions::configureSlot);
121 
122  boost::function<void()> finit = boost::bind(&TrackingService::setState, trackingService(), Tool::tsINITIALIZED);
123  this->createAction("InitializeTools", "Initialize",
124  QIcon(), QKeySequence(), "",
125  finit);
126 
127  mTrackingToolsAction = this->createAction("TrackingTools", "Start tracking",
128  QIcon(), QKeySequence("Ctrl+T"), "",
129  &MainWindowActions::toggleTrackingSlot);
130 
131  connect(trackingService().get(), &TrackingService::stateChanged, this, &MainWindowActions::updateTrackingActionSlot);
132  this->updateTrackingActionSlot();
133 }
134 
135 void MainWindowActions::createPatientActions()
136 {
137  this->createAction("NewPatient", "New Patient",
138  QIcon(":/icons/open_icon_library/document-new-8.png"),
139  QKeySequence("Ctrl+N"),
140  "Create a new patient file",
141  &MainWindowActions::newPatientSlot);
142 
143  this->createAction("SaveFile", "Save Patient",
144  QIcon(":/icons/open_icon_library/document-save-5.png"),
145  QKeySequence("Ctrl+S"),
146  "Save patient file",
147  &MainWindowActions::savePatientFileSlot);
148 
149  this->createAction("LoadFile", "Load Patient",
150  QIcon(":/icons/open_icon_library/document-open-7.png"),
151  QKeySequence("Ctrl+L"),
152  "Load patient file",
153  &MainWindowActions::loadPatientFileSlot);
154 
155  this->createAction("ClearPatient", "Clear Patient",
156  QIcon(),
157  QKeySequence(),
158  "Clear the current patient from the application",
159  &MainWindowActions::clearPatientSlot);
160 
161  this->createAction("ExportPatient", "Export Patient",
162  QIcon(),
163  QKeySequence(),
164  "Export patient data to a folder",
165  &MainWindowActions::exportDataSlot);
166 
167  this->createAction("ImportData", "Import data",
168  QIcon(":/icons/open_icon_library/document-import-2.png"),
169  QKeySequence("Ctrl+I"),
170  "Import image data",
171  &MainWindowActions::importDataSlot);
172 }
173 
174 template <class T>
175 QAction* MainWindowActions::createAction(QString uid, QString text, QIcon icon,
176  QKeySequence shortcut, QString help,
177  T triggerSlot)
178 {
179  QAction* retval = new QAction(icon, text, this);
180  retval->setObjectName(uid);
181  retval->setShortcut(shortcut);
182  retval->setStatusTip(help);
183  connect(retval, &QAction::triggered, this, triggerSlot);
184  mActions[uid] = retval;
185  return retval;
186 }
187 
188 namespace
189 {
190 QString timestampFormatFolderFriendly()
191 {
192  return QString("yyyy-MM-dd_hh-mm");
193 }
194 }
195 
196 QWidget* MainWindowActions::parentWidget()
197 {
198  return dynamic_cast<QWidget*>(this->parent());
199 }
200 
201 
202 void MainWindowActions::newPatientSlot()
203 {
204  QString patientDatafolder = this->getExistingSessionFolder();
205 
206  QString timestamp = QDateTime::currentDateTime().toString(timestampFormatFolderFriendly());
207  QString filename = QString("%1_%2_%3.cx3")
208  .arg(timestamp)
209  .arg(profile()->getName())
210  .arg(settings()->value("globalPatientNumber").toString());
211 
212  QString choosenDir = patientDatafolder + "/" + filename;
213 
214  QFileDialog dialog(this->parentWidget(), tr("Select directory to save patient in"), patientDatafolder + "/");
215  dialog.setOption(QFileDialog::DontUseNativeDialog, true);
216  dialog.setOption(QFileDialog::ShowDirsOnly, true);
217  dialog.selectFile(filename);
218  if (!dialog.exec())
219  return;
220  choosenDir = dialog.selectedFiles().front();
221 
222  if (!choosenDir.endsWith(".cx3"))
223  choosenDir += QString(".cx3");
224 
225  // Update global patient number
226  int patientNumber = settings()->value("globalPatientNumber").toInt();
227  settings()->setValue("globalPatientNumber", ++patientNumber);
228 
229  mServices->session()->load(choosenDir);
230 }
231 
232 QString MainWindowActions::getExistingSessionFolder()
233 {
234  return profile()->getSessionRootFolder();
235 }
236 
237 void MainWindowActions::clearPatientSlot()
238 {
239  mServices->session()->clear();
240 }
241 
242 void MainWindowActions::savePatientFileSlot()
243 {
244  if (patientService()->getActivePatientFolder().isEmpty())
245  {
246  reportWarning("No patient selected, select or create patient before saving!");
247  this->newPatientSlot();
248  return;
249  }
250 
251  mServices->session()->save();
252 }
253 
254 void MainWindowActions::loadPatientFileSlot()
255 {
256  QString patientDatafolder = this->getExistingSessionFolder();
257 
258  // Open file dialog
259  QString folder = QFileDialog::getExistingDirectory(this->parentWidget(), "Select patient", patientDatafolder, QFileDialog::ShowDirsOnly);
260  if (folder.isEmpty())
261  return;
262 
263  mServices->session()->load(folder);
264 }
265 
266 void MainWindowActions::exportDataSlot()
267 {
268  this->savePatientFileSlot();
269 
270  ExportDataDialog* wizard = new ExportDataDialog(mServices->patient(), this->parentWidget());
271  wizard->exec(); //calling exec() makes the wizard dialog modal which prevents other user interaction with the system
272 }
273 
274 void MainWindowActions::importDataSlot()
275 {
276  this->savePatientFileSlot();
277 
278  QString folder = mLastImportDataFolder;
279  if (folder.isEmpty())
280  folder = profile()->getSessionRootFolder();
281 
282  QStringList fileName = QFileDialog::getOpenFileNames(this->parentWidget(), QString(tr("Select data file(s) for import")),
283  folder, tr("Image/Mesh (*.mhd *.mha *.stl *.vtk *.mnc *.png)"));
284  if (fileName.empty())
285  {
286  report("Import canceled");
287  return;
288  }
289 
290  mLastImportDataFolder = QFileInfo(fileName[0]).absolutePath();
291 
292  for (int i=0; i<fileName.size(); ++i)
293  {
294  ImportDataDialog* wizard = new ImportDataDialog(mServices->patient(), fileName[i], this->parentWidget());
295  wizard->exec(); //calling exec() makes the wizard dialog modal which prevents other user interaction with the system
296  }
297 }
298 
299 void MainWindowActions::shootScreen()
300 {
301  mScreenShotWriter->grabAllScreensToFile();
302 }
303 
304 void MainWindowActions::shootWindow()
305 {
306 // this->shootOneLayout(0);
307 
308  int index=0;
309  while (mServices->view()->getLayoutWidget(index))
310  this->shootOneLayout(index++);
311 }
312 
313 void MainWindowActions::shootOneLayout(int index)
314 {
315  QWidget* widget = mServices->view()->getLayoutWidget(index);
316  ViewCollectionWidget* vcWidget = dynamic_cast<ViewCollectionWidget*>(widget);
317 
318  ViewCollectionImageWriter grabber(vcWidget);
319  QImage pm = ViewCollectionImageWriter::vtkImageData2QImage(grabber.grab());
320  mScreenShotWriter->save(pm, QString("_layout%1").arg(index));
321 }
322 
323 void MainWindowActions::recordFullscreen()
324 {
325  QString path = patientService()->generateFilePath("Screenshots", "mp4");
326 
327  if(vlc()->isRecording())
328  vlc()->stopRecording();
329  else
330  vlc()->startRecording(path);
331 }
332 
333 void MainWindowActions::updateRecordFullscreenActionSlot()
334 {
335  mRecordFullscreenStreamingAction->setCheckable(true);
336  mRecordFullscreenStreamingAction->blockSignals(true);
337  mRecordFullscreenStreamingAction->setChecked(vlc()->isRecording());
338  mRecordFullscreenStreamingAction->blockSignals(false);
339 
340  if(vlc()->isRecording())
341  {
342  mRecordFullscreenStreamingAction->setIcon(QIcon(":/icons/Video-icon_green.png"));
343  }
344  else
345  {
346  mRecordFullscreenStreamingAction->setIcon(QIcon(":/icons/Video-icon_gray.png"));
347  }
348 
349 }
350 
351 void MainWindowActions::onStartLogConsole()
352 {
353  QString fullname = DataLocations::findExecutableInStandardLocations("LogConsole");
354 // std::cout << "MainWindowActions::onStartLogConsole() " << fullname << std::endl;
355  mLocalVideoServerProcess.reset(new ProcessWrapper(QString("LogConsole")));
356  mLocalVideoServerProcess->launchWithRelativePath(fullname, QStringList());
357 }
358 
359 void MainWindowActions::toggleStreamingSlot()
360 {
361  if (videoService()->isConnected())
362  videoService()->closeConnection();
363  else
364  videoService()->openConnection();
365 }
366 
367 void MainWindowActions::updateStreamingActionSlot()
368 {
369  if (videoService()->isConnected())
370  {
371  mStartStreamingAction->setIcon(QIcon(":/icons/streaming_green.png"));
372  mStartStreamingAction->setText("Stop Streaming");
373  }
374  else
375  {
376  mStartStreamingAction->setIcon(QIcon(":/icons/streaming_red.png"));
377  mStartStreamingAction->setText("Start Streaming");
378  }
379 }
380 
381 void MainWindowActions::centerToImageCenterSlot()
382 {
383  viewService()->centerToImageCenterInActiveViewGroup();
384 }
385 
386 void MainWindowActions::centerToTooltipSlot()
387 {
388  NavigationPtr nav = viewService()->getNavigation();
389  nav->centerToTooltip();
390 }
391 
392 void MainWindowActions::togglePointPickerActionSlot()
393 {
394  ViewGroupDataPtr data = viewService()->getGroup(0);
395  ViewGroupData::Options options = data->getOptions();
396  options.mShowPointPickerProbe = !options.mShowPointPickerProbe;
397  data->setOptions(options);
398 }
399 void MainWindowActions::updatePointPickerActionSlot()
400 {
401  if (!viewService()->getGroup(0))
402  return;
403  bool show = viewService()->getGroup(0)->getOptions().mShowPointPickerProbe;
404  mShowPointPickerAction->setChecked(show);
405 }
406 
407 void MainWindowActions::updateTrackingActionSlot()
408 {
409  if (trackingService()->getState() >= Tool::tsTRACKING)
410  {
411  mTrackingToolsAction->setIcon(QIcon(":/icons/polaris-green.png"));
412  mTrackingToolsAction->setText("Stop Tracking");
413  }
414  else
415  {
416  mTrackingToolsAction->setIcon(QIcon(":/icons/polaris-red.png"));
417  mTrackingToolsAction->setText("Start Tracking");
418  }
419 }
420 
421 void MainWindowActions::configureSlot()
422 {
423  trackingService()->setState(Tool::tsCONFIGURED);
424 }
425 
426 void MainWindowActions::toggleTrackingSlot()
427 {
428  if (trackingService()->getState() >= Tool::tsTRACKING)
430  else
431  trackingService()->setState(Tool::tsTRACKING);
432 }
433 
434 void MainWindowActions::onGotoDocumentation()
435 {
437  QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
438 }
439 
440 
441 
442 } // namespace cx
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:176
boost::shared_ptr< class ViewGroupData > ViewGroupDataPtr
Definition: cxViewGroup.h:50
void connected(bool on)
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:62
static QString getWebsiteUserDocumentationURL()
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Definition: cxSettings.cpp:87
void startRecording(QString saveFile)
boost::shared_ptr< class Navigation > NavigationPtr
Definition: cxViewGroup.h:54
configured with basic info
Definition: cxTool.h:96
void setValue(const QString &key, const QVariant &value)
Definition: cxSettings.cpp:79
static QImage vtkImageData2QImage(vtkImageDataPtr input)
void reportWarning(QString msg)
Definition: cxLogger.cpp:91
#define CX_LOG_ERROR
Definition: cxLogger.h:114
MainWindowActions(VisServicesPtr services, QWidget *parent)
virtual void setState(const Tool::State val)=0
Settings * settings()
Shortcut for accessing the settings instance.
Definition: cxSettings.cpp:42
connected to hardware, if any, ready to use
Definition: cxTool.h:97
QAction * getAction(QString uid)
cxLogicManager_EXPORT ViewServicePtr viewService()
void report(QString msg)
Definition: cxLogger.cpp:90
cxLogicManager_EXPORT VideoServicePtr videoService()
static QString findExecutableInStandardLocations(QString filename)
look for an exe in the same folder as the executable or bundle.
cxLogicManager_EXPORT PatientModelServicePtr patientService()
emitting tracking data
Definition: cxTool.h:98
cxLogicManager_EXPORT TrackingServicePtr trackingService()
VLCRecorder * vlc()
Shortcut for accessing the vlc recorder.