CustusX  15.8
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"
34 
35 namespace cx
36 {
37 
39  QObject(parent),
40  mServices(services)
41 {
42  this->createActions();
43 }
44 
45 QAction* MainWindowActions::getAction(QString uid)
46 {
47  if (!mActions.count(uid))
48  CX_LOG_ERROR() << QString("Could not find action %1 in MainWindowActions object").arg(uid);
49  return mActions[uid];
50 }
51 
52 void MainWindowActions::createActions()
53 {
54  this->createAction("GotoDocumentation", "Web Documentation",
55  QIcon(":/icons/open_icon_library/applications-internet.png"),
56  QKeySequence(""), "",
57  &MainWindowActions::onGotoDocumentation);
58 
59  this->createAction("StartLogConsole", "Start Log Console",
60  QIcon(),
61  QKeySequence("Ctrl+D"), "Open Log Console as external application",
62  &MainWindowActions::onStartLogConsole);
63 
64  this->createAction("ShootScreen", "Shoot Screen",
65  QIcon(":/icons/screenshot-screen.png"),
66  QKeySequence("Ctrl+f"), "Save a screenshot to the patient folder.",
67  &MainWindowActions::shootScreen);
68 
69  this->createAction("ShootWindow", "Shoot Window",
70  QIcon(":/icons/screenshot-window.png"),
71  QKeySequence("Ctrl+Shift+f"), "Save an image of the application to the patient folder.",
72  &MainWindowActions::shootWindow);
73 
74  mRecordFullscreenStreamingAction = this->createAction("RecordFullscreen", "Record Fullscreen",
75  QIcon(),
76  QKeySequence("F8"), "Record a video of the full screen.",
77  &MainWindowActions::recordFullscreen);
78  connect(vlc(), &VLCRecorder::stateChanged, this, &MainWindowActions::updateRecordFullscreenActionSlot);
79  this->updateRecordFullscreenActionSlot();
80 
81  mShowPointPickerAction = this->createAction("ShowPointPicker", "Point Picker",
82  QIcon(":/icons/point_picker.png"),
83  QKeySequence(""), "Activate the 3D Point Picker Probe",
84  &MainWindowActions::togglePointPickerActionSlot);
85  mShowPointPickerAction->setCheckable(true);
86 
87  if (viewService()->getGroup(0))
88  connect(viewService()->getGroup(0).get(), &ViewGroupData::optionsChanged, this, &MainWindowActions::updatePointPickerActionSlot);
89  this->updatePointPickerActionSlot();
90 
91  mStartStreamingAction = this->createAction("StartStreaming", "Start Streaming",
92  QIcon(":/icons/open_icon_library/.png"),
93  QKeySequence("Ctrl+V"), "",
94  &MainWindowActions::toggleStreamingSlot);
95  connect(videoService().get(), &VideoService::connected, this, &MainWindowActions::updateStreamingActionSlot);
96  this->updateStreamingActionSlot();
97 
98  this->createAction("CenterToImageCenter", "Center Image",
99  QIcon(":/icons/center_image.png"),
100  QKeySequence(), "",
101  &MainWindowActions::centerToImageCenterSlot);
102 
103  this->createAction("CenterToTooltip", "Center Tool",
104  QIcon(":/icons/center_tool.png"),
105  QKeySequence(""), "",
106  &MainWindowActions::centerToTooltipSlot);
107 
108  this->createPatientActions();
109  this->createTrackingActions();
110 }
111 
112 void MainWindowActions::createTrackingActions()
113 {
114  this->createAction("ConfigureTools", "Tool configuration",
115  QIcon(), QKeySequence(), "",
116  &MainWindowActions::configureSlot);
117 
118  boost::function<void()> finit = boost::bind(&TrackingService::setState, trackingService(), Tool::tsINITIALIZED);
119  this->createAction("InitializeTools", "Initialize",
120  QIcon(), QKeySequence(), "",
121  finit);
122 
123  mTrackingToolsAction = this->createAction("TrackingTools", "Start tracking",
124  QIcon(), QKeySequence("Ctrl+T"), "",
125  &MainWindowActions::toggleTrackingSlot);
126 
127  connect(trackingService().get(), &TrackingService::stateChanged, this, &MainWindowActions::updateTrackingActionSlot);
128  this->updateTrackingActionSlot();
129 }
130 
131 void MainWindowActions::createPatientActions()
132 {
133  this->createAction("NewPatient", "New Patient",
134  QIcon(":/icons/open_icon_library/document-new-8.png"),
135  QKeySequence("Ctrl+N"),
136  "Create a new patient file",
137  &MainWindowActions::newPatientSlot);
138 
139  this->createAction("SaveFile", "Save Patient",
140  QIcon(":/icons/open_icon_library/document-save-5.png"),
141  QKeySequence("Ctrl+S"),
142  "Save patient file",
143  &MainWindowActions::savePatientFileSlot);
144 
145  this->createAction("LoadFile", "Load Patient",
146  QIcon(":/icons/open_icon_library/document-open-7.png"),
147  QKeySequence("Ctrl+L"),
148  "Load patient file",
149  &MainWindowActions::loadPatientFileSlot);
150 
151  this->createAction("ClearPatient", "Clear Patient",
152  QIcon(),
153  QKeySequence(),
154  "Clear the current patient from the application",
155  &MainWindowActions::clearPatientSlot);
156 
157  this->createAction("ExportPatient", "Export Patient",
158  QIcon(),
159  QKeySequence(),
160  "Export patient data to a folder",
161  &MainWindowActions::exportDataSlot);
162 
163  this->createAction("ImportData", "Import data",
164  QIcon(":/icons/open_icon_library/document-import-2.png"),
165  QKeySequence("Ctrl+I"),
166  "Import image data",
167  &MainWindowActions::importDataSlot);
168 
169  this->createAction("DeleteData", "Delete current image",
170  QIcon(),
171  QKeySequence(),
172  "Delete selected volume",
173  &MainWindowActions::deleteDataSlot);
174 }
175 
176 template <class T>
177 QAction* MainWindowActions::createAction(QString uid, QString text, QIcon icon,
178  QKeySequence shortcut, QString help,
179  T triggerSlot)
180 {
181  QAction* retval = new QAction(icon, text, this);
182  retval->setShortcut(shortcut);
183  retval->setStatusTip(help);
184  connect(retval, &QAction::triggered, this, triggerSlot);
185  mActions[uid] = retval;
186  return retval;
187 }
188 
189 namespace
190 {
191 QString timestampFormatFolderFriendly()
192 {
193  return QString("yyyy-MM-dd_hh-mm");
194 }
195 }
196 
197 QWidget* MainWindowActions::parentWidget()
198 {
199  return dynamic_cast<QWidget*>(this->parent());
200 }
201 
202 
203 void MainWindowActions::newPatientSlot()
204 {
205  QString patientDatafolder = this->getExistingSessionFolder();
206 
207  QString timestamp = QDateTime::currentDateTime().toString(timestampFormatFolderFriendly());
208  QString filename = QString("%1_%2_%3.cx3")
209  .arg(timestamp)
210  .arg(profile()->getName())
211  .arg(settings()->value("globalPatientNumber").toString());
212 
213  QString choosenDir = patientDatafolder + "/" + filename;
214 
215  QFileDialog dialog(this->parentWidget(), tr("Select directory to save patient in"), patientDatafolder + "/");
216  dialog.setOption(QFileDialog::DontUseNativeDialog, true);
217  dialog.setOption(QFileDialog::ShowDirsOnly, true);
218  dialog.selectFile(filename);
219  if (!dialog.exec())
220  return;
221  choosenDir = dialog.selectedFiles().front();
222 
223  if (!choosenDir.endsWith(".cx3"))
224  choosenDir += QString(".cx3");
225 
226  // Update global patient number
227  int patientNumber = settings()->value("globalPatientNumber").toInt();
228  settings()->setValue("globalPatientNumber", ++patientNumber);
229 
230  mServices->getSession()->load(choosenDir);
231 }
232 
233 QString MainWindowActions::getExistingSessionFolder()
234 {
235  return profile()->getSessionRootFolder();
236 }
237 
238 void MainWindowActions::clearPatientSlot()
239 {
240  mServices->getSession()->clear();
241 }
242 
243 void MainWindowActions::savePatientFileSlot()
244 {
245  if (patientService()->getActivePatientFolder().isEmpty())
246  {
247  reportWarning("No patient selected, select or create patient before saving!");
248  this->newPatientSlot();
249  return;
250  }
251 
252  mServices->getSession()->save();
253 }
254 
255 void MainWindowActions::loadPatientFileSlot()
256 {
257  QString patientDatafolder = this->getExistingSessionFolder();
258 
259  // Open file dialog
260  QString folder = QFileDialog::getExistingDirectory(this->parentWidget(), "Select patient", patientDatafolder, QFileDialog::ShowDirsOnly);
261  if (folder.isEmpty())
262  return;
263 
264  mServices->getSession()->load(folder);
265 }
266 
267 void MainWindowActions::exportDataSlot()
268 {
269  this->savePatientFileSlot();
270 
271  ExportDataDialog* wizard = new ExportDataDialog(mServices->patientModelService, this->parentWidget());
272  wizard->exec(); //calling exec() makes the wizard dialog modal which prevents other user interaction with the system
273 }
274 
275 void MainWindowActions::importDataSlot()
276 {
277  this->savePatientFileSlot();
278 
279  QString folder = mLastImportDataFolder;
280  if (folder.isEmpty())
281  folder = profile()->getSessionRootFolder();
282 
283  QStringList fileName = QFileDialog::getOpenFileNames(this->parentWidget(), QString(tr("Select data file(s) for import")),
284  folder, tr("Image/Mesh (*.mhd *.mha *.stl *.vtk *.mnc *.png)"));
285  if (fileName.empty())
286  {
287  report("Import canceled");
288  return;
289  }
290 
291  mLastImportDataFolder = QFileInfo(fileName[0]).absolutePath();
292 
293  for (int i=0; i<fileName.size(); ++i)
294  {
295  ImportDataDialog* wizard = new ImportDataDialog(mServices->patientModelService, fileName[i], this->parentWidget());
296  wizard->exec(); //calling exec() makes the wizard dialog modal which prevents other user interaction with the system
297  }
298 }
299 
300 void MainWindowActions::deleteDataSlot()
301 {
302  if (!patientService()->getActiveImage())
303  return;
304  QString text = QString("Do you really want to delete data %1?").arg(patientService()->getActiveImage()->getName());
305  if (QMessageBox::question(this->parentWidget(), "Data delete", text, QMessageBox::StandardButtons(QMessageBox::Ok | QMessageBox::Cancel))!=QMessageBox::Ok)
306  return;
307  mServices->patientModelService->removeData(patientService()->getActiveImageUid());
308 }
309 
310 void MainWindowActions::shootScreen()
311 {
312  QDesktopWidget* desktop = qApp->desktop();
313  QList<QScreen*> screens = qApp->screens();
314 
315  for (int i=0; i<desktop->screenCount(); ++i)
316  {
317  QWidget* screenWidget = desktop->screen(i);
318  WId screenWinId = screenWidget->winId();
319  QRect geo = desktop->screenGeometry(i);
320  QString name = "";
321  if (desktop->screenCount()>1)
322  name = screens[i]->name().split(" ").join("");
323  this->saveScreenShot(screens[i]->grabWindow(screenWinId, geo.left(), geo.top(), geo.width(), geo.height()), name);
324  }
325 }
326 
327 void MainWindowActions::shootWindow()
328 {
329  QScreen* screen = qApp->primaryScreen();
330  this->saveScreenShot(screen->grabWindow(this->parentWidget()->winId()));
331 }
332 
333 void MainWindowActions::recordFullscreen()
334 {
335  QString path = patientService()->generateFilePath("Screenshots", "mp4");
336 
337  if(vlc()->isRecording())
338  vlc()->stopRecording();
339  else
340  vlc()->startRecording(path);
341 }
342 
343 void MainWindowActions::updateRecordFullscreenActionSlot()
344 {
345  mRecordFullscreenStreamingAction->setCheckable(true);
346  mRecordFullscreenStreamingAction->blockSignals(true);
347  mRecordFullscreenStreamingAction->setChecked(vlc()->isRecording());
348  mRecordFullscreenStreamingAction->blockSignals(false);
349 
350  if(vlc()->isRecording())
351  {
352  mRecordFullscreenStreamingAction->setIcon(QIcon(":/icons/Video-icon_green.png"));
353  }
354  else
355  {
356  mRecordFullscreenStreamingAction->setIcon(QIcon(":/icons/Video-icon_gray.png"));
357  }
358 
359 }
360 
361 void MainWindowActions::onStartLogConsole()
362 {
363  QString fullname = DataLocations::findExecutableInStandardLocations("LogConsole");
364 // std::cout << "MainWindowActions::onStartLogConsole() " << fullname << std::endl;
365  mLocalVideoServerProcess.reset(new ProcessWrapper(QString("LogConsole")));
366  mLocalVideoServerProcess->launchWithRelativePath(fullname, QStringList());
367 }
368 
369 void MainWindowActions::saveScreenShot(QPixmap pixmap, QString id)
370 {
371  QString ending = "png";
372  if (!id.isEmpty())
373  ending = id + "." + ending;
374  QString path = patientService()->generateFilePath("Screenshots", ending);
375  QtConcurrent::run(boost::bind(&MainWindowActions::saveScreenShotThreaded, this, pixmap.toImage(), path));
376 }
377 
381 void MainWindowActions::saveScreenShotThreaded(QImage pixmap, QString filename)
382 {
383  pixmap.save(filename, "png");
384  report("Saved screenshot to " + filename);
385  reporter()->playScreenShotSound();
386 }
387 
388 void MainWindowActions::toggleStreamingSlot()
389 {
390  if (videoService()->isConnected())
391  videoService()->closeConnection();
392  else
393  videoService()->openConnection();
394 }
395 
396 void MainWindowActions::updateStreamingActionSlot()
397 {
398  if (videoService()->isConnected())
399  {
400  mStartStreamingAction->setIcon(QIcon(":/icons/streaming_green.png"));
401  mStartStreamingAction->setText("Stop Streaming");
402  }
403  else
404  {
405  mStartStreamingAction->setIcon(QIcon(":/icons/streaming_red.png"));
406  mStartStreamingAction->setText("Start Streaming");
407  }
408 }
409 
410 void MainWindowActions::centerToImageCenterSlot()
411 {
412  viewService()->getNavigation()->centerToDataInActiveViewGroup();
413 }
414 
415 void MainWindowActions::centerToTooltipSlot()
416 {
417  NavigationPtr nav = viewService()->getNavigation();
418  nav->centerToTooltip();
419 }
420 
421 void MainWindowActions::togglePointPickerActionSlot()
422 {
423  ViewGroupDataPtr data = viewService()->getGroup(0);
424  ViewGroupData::Options options = data->getOptions();
425  options.mShowPointPickerProbe = !options.mShowPointPickerProbe;
426  data->setOptions(options);
427 }
428 void MainWindowActions::updatePointPickerActionSlot()
429 {
430  if (!viewService()->getGroup(0))
431  return;
432  bool show = viewService()->getGroup(0)->getOptions().mShowPointPickerProbe;
433  mShowPointPickerAction->setChecked(show);
434 }
435 
436 void MainWindowActions::updateTrackingActionSlot()
437 {
438  if (trackingService()->getState() >= Tool::tsTRACKING)
439  {
440  mTrackingToolsAction->setIcon(QIcon(":/icons/polaris-green.png"));
441  mTrackingToolsAction->setText("Stop Tracking");
442  }
443  else
444  {
445  mTrackingToolsAction->setIcon(QIcon(":/icons/polaris-red.png"));
446  mTrackingToolsAction->setText("Start Tracking");
447  }
448 }
449 
450 void MainWindowActions::configureSlot()
451 {
452  trackingService()->setState(Tool::tsCONFIGURED);
453 }
454 
455 void MainWindowActions::toggleTrackingSlot()
456 {
457  if (trackingService()->getState() >= Tool::tsTRACKING)
459  else
460  trackingService()->setState(Tool::tsTRACKING);
461 }
462 
463 void MainWindowActions::onGotoDocumentation()
464 {
466  QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
467 }
468 
469 
470 
471 } // namespace cx
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:169
boost::shared_ptr< class ViewGroupData > ViewGroupDataPtr
Definition: cxViewGroup.h:50
ReporterPtr reporter()
Definition: cxReporter.cpp:59
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:81
void setValue(const QString &key, const QVariant &value)
Definition: cxSettings.cpp:79
void reportWarning(QString msg)
Definition: cxLogger.cpp:91
#define CX_LOG_ERROR
Definition: cxLogger.h:113
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:82
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:83
cxLogicManager_EXPORT TrackingServicePtr trackingService()
VLCRecorder * vlc()
Shortcut for accessing the vlc recorder.