CustusX  15.4.0-beta
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  this->createAction("RecordFullscreen", "Record Fullscreen",
75  QIcon(),
76  QKeySequence("F8"), "Record a video of the full screen.",
77  &MainWindowActions::recordFullscreen);
78 
79  mShowPointPickerAction = this->createAction("ShowPointPicker", "Point Picker",
80  QIcon(":/icons/point_picker.png"),
81  QKeySequence(""), "Activate the 3D Point Picker Probe",
82  &MainWindowActions::togglePointPickerActionSlot);
83  mShowPointPickerAction->setCheckable(true);
84 
85  if (viewService()->getGroup(0))
86  connect(viewService()->getGroup(0).get(), &ViewGroupData::optionsChanged, this, &MainWindowActions::updatePointPickerActionSlot);
87  this->updatePointPickerActionSlot();
88 
89  mStartStreamingAction = this->createAction("StartStreaming", "Start Streaming",
90  QIcon(":/icons/open_icon_library/.png"),
91  QKeySequence("Ctrl+V"), "",
92  &MainWindowActions::toggleStreamingSlot);
93  connect(videoService().get(), &VideoService::connected, this, &MainWindowActions::updateStreamingActionSlot);
94  this->updateStreamingActionSlot();
95 
96  this->createAction("CenterToImageCenter", "Center Image",
97  QIcon(":/icons/center_image.png"),
98  QKeySequence(), "",
99  &MainWindowActions::centerToImageCenterSlot);
100 
101  this->createAction("CenterToTooltip", "Center Tool",
102  QIcon(":/icons/center_tool.png"),
103  QKeySequence(""), "",
104  &MainWindowActions::centerToTooltipSlot);
105 
106  this->createPatientActions();
107  this->createTrackingActions();
108 }
109 
110 void MainWindowActions::createTrackingActions()
111 {
112  this->createAction("ConfigureTools", "Tool configuration",
113  QIcon(), QKeySequence(), "",
114  &MainWindowActions::configureSlot);
115 
116  boost::function<void()> finit = boost::bind(&TrackingService::setState, trackingService(), Tool::tsINITIALIZED);
117  this->createAction("InitializeTools", "Initialize",
118  QIcon(), QKeySequence(), "",
119  finit);
120 
121  mTrackingToolsAction = this->createAction("TrackingTools", "Start tracking",
122  QIcon(), QKeySequence("Ctrl+T"), "",
123  &MainWindowActions::toggleTrackingSlot);
124 
125  connect(trackingService().get(), &TrackingService::stateChanged, this, &MainWindowActions::updateTrackingActionSlot);
126  connect(trackingService().get(), &TrackingService::stateChanged, this, &MainWindowActions::updateTrackingActionSlot);
127  this->updateTrackingActionSlot();
128 }
129 
130 void MainWindowActions::createPatientActions()
131 {
132  this->createAction("NewPatient", "New Patient",
133  QIcon(":/icons/open_icon_library/document-new-8.png"),
134  QKeySequence("Ctrl+N"),
135  "Create a new patient file",
136  &MainWindowActions::newPatientSlot);
137 
138  this->createAction("SaveFile", "Save Patient",
139  QIcon(":/icons/open_icon_library/document-save-5.png"),
140  QKeySequence("Ctrl+S"),
141  "Save patient file",
142  &MainWindowActions::savePatientFileSlot);
143 
144  this->createAction("LoadFile", "Load Patient",
145  QIcon(":/icons/open_icon_library/document-open-7.png"),
146  QKeySequence("Ctrl+L"),
147  "Load patient file",
148  &MainWindowActions::loadPatientFileSlot);
149 
150  this->createAction("ClearPatient", "Clear Patient",
151  QIcon(),
152  QKeySequence(),
153  "Clear the current patient from the application",
154  &MainWindowActions::clearPatientSlot);
155 
156  this->createAction("ExportPatient", "Export Patient",
157  QIcon(),
158  QKeySequence(),
159  "Export patient data to a folder",
160  &MainWindowActions::exportDataSlot);
161 
162  this->createAction("ImportData", "Import data",
163  QIcon(":/icons/open_icon_library/document-import-2.png"),
164  QKeySequence("Ctrl+I"),
165  "Import image data",
166  &MainWindowActions::importDataSlot);
167 
168  this->createAction("DeleteData", "Delete current image",
169  QIcon(),
170  QKeySequence(),
171  "Delete selected volume",
172  &MainWindowActions::deleteDataSlot);
173 }
174 
175 template <class T>
176 QAction* MainWindowActions::createAction(QString uid, QString text, QIcon icon,
177  QKeySequence shortcut, QString help,
178  T triggerSlot)
179 {
180  QAction* retval = new QAction(icon, text, this);
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->getSession()->load(choosenDir);
230 }
231 
232 QString MainWindowActions::getExistingSessionFolder()
233 {
234  QString folder = settings()->value("globalPatientDataFolder").toString();
235 
236  // Create folders
237  if (!QDir().exists(folder))
238  {
239  QDir().mkdir(folder);
240  report("Made a new patient folder: " + folder);
241  }
242 
243  return folder;
244 }
245 
246 void MainWindowActions::clearPatientSlot()
247 {
248  mServices->getSession()->clear();
249 }
250 
251 void MainWindowActions::savePatientFileSlot()
252 {
253  if (patientService()->getActivePatientFolder().isEmpty())
254  {
255  reportWarning("No patient selected, select or create patient before saving!");
256  this->newPatientSlot();
257  return;
258  }
259 
260  mServices->getSession()->save();
261 }
262 
263 void MainWindowActions::loadPatientFileSlot()
264 {
265  QString patientDatafolder = this->getExistingSessionFolder();
266 
267  // Open file dialog
268  QString folder = QFileDialog::getExistingDirectory(this->parentWidget(), "Select patient", patientDatafolder, QFileDialog::ShowDirsOnly);
269  if (folder.isEmpty())
270  return;
271 
272  mServices->getSession()->load(folder);
273 }
274 
275 void MainWindowActions::exportDataSlot()
276 {
277  this->savePatientFileSlot();
278 
279  ExportDataDialog* wizard = new ExportDataDialog(mServices->patientModelService, this->parentWidget());
280  wizard->exec(); //calling exec() makes the wizard dialog modal which prevents other user interaction with the system
281 }
282 
283 void MainWindowActions::importDataSlot()
284 {
285  this->savePatientFileSlot();
286 
287  QString folder = mLastImportDataFolder;
288  if (folder.isEmpty())
289  folder = settings()->value("globalPatientDataFolder").toString();
290 
291  QStringList fileName = QFileDialog::getOpenFileNames(this->parentWidget(), QString(tr("Select data file(s) for import")),
292  folder, tr("Image/Mesh (*.mhd *.mha *.stl *.vtk *.mnc *.png)"));
293  if (fileName.empty())
294  {
295  report("Import canceled");
296  return;
297  }
298 
299  mLastImportDataFolder = QFileInfo(fileName[0]).absolutePath();
300 
301  for (int i=0; i<fileName.size(); ++i)
302  {
303  ImportDataDialog* wizard = new ImportDataDialog(mServices->patientModelService, fileName[i], this->parentWidget());
304  wizard->exec(); //calling exec() makes the wizard dialog modal which prevents other user interaction with the system
305  }
306 }
307 
308 void MainWindowActions::deleteDataSlot()
309 {
310  if (!patientService()->getActiveImage())
311  return;
312  QString text = QString("Do you really want to delete data %1?").arg(patientService()->getActiveImage()->getName());
313  if (QMessageBox::question(this->parentWidget(), "Data delete", text, QMessageBox::StandardButtons(QMessageBox::Ok | QMessageBox::Cancel))!=QMessageBox::Ok)
314  return;
315  mServices->patientModelService->removeData(patientService()->getActiveImageUid());
316 }
317 
318 void MainWindowActions::shootScreen()
319 {
320  QDesktopWidget* desktop = qApp->desktop();
321  QList<QScreen*> screens = qApp->screens();
322 
323  for (int i=0; i<desktop->screenCount(); ++i)
324  {
325  QWidget* screenWidget = desktop->screen(i);
326  WId screenWinId = screenWidget->winId();
327  QRect geo = desktop->screenGeometry(i);
328  QString name = "";
329  if (desktop->screenCount()>1)
330  name = screens[i]->name().split(" ").join("");
331  this->saveScreenShot(screens[i]->grabWindow(screenWinId, geo.left(), geo.top(), geo.width(), geo.height()), name);
332  }
333 }
334 
335 void MainWindowActions::shootWindow()
336 {
337  QScreen* screen = qApp->primaryScreen();
338  this->saveScreenShot(screen->grabWindow(this->parentWidget()->winId()));
339 }
340 
341 void MainWindowActions::recordFullscreen()
342 {
343  QString path = patientService()->generateFilePath("Screenshots", "mp4");
344 
345  if(vlc()->isRecording())
346  vlc()->stopRecording();
347  else
348  vlc()->startRecording(path);
349 
350 }
351 
352 void MainWindowActions::onStartLogConsole()
353 {
354  QString fullname = DataLocations::findExecutableInStandardLocations("LogConsole");
355 // std::cout << "MainWindowActions::onStartLogConsole() " << fullname << std::endl;
356  mLocalVideoServerProcess.reset(new ProcessWrapper(QString("LogConsole")));
357  mLocalVideoServerProcess->launchWithRelativePath(fullname, QStringList());
358 }
359 
360 void MainWindowActions::saveScreenShot(QPixmap pixmap, QString id)
361 {
362  QString ending = "png";
363  if (!id.isEmpty())
364  ending = id + "." + ending;
365  QString path = patientService()->generateFilePath("Screenshots", ending);
366  QtConcurrent::run(boost::bind(&MainWindowActions::saveScreenShotThreaded, this, pixmap.toImage(), path));
367 }
368 
372 void MainWindowActions::saveScreenShotThreaded(QImage pixmap, QString filename)
373 {
374  pixmap.save(filename, "png");
375  report("Saved screenshot to " + filename);
376  reporter()->playScreenShotSound();
377 }
378 
379 void MainWindowActions::toggleStreamingSlot()
380 {
381  if (videoService()->isConnected())
382  videoService()->closeConnection();
383  else
384  videoService()->openConnection();
385 }
386 
387 void MainWindowActions::updateStreamingActionSlot()
388 {
389  if (videoService()->isConnected())
390  {
391  mStartStreamingAction->setIcon(QIcon(":/icons/streaming_green.png"));
392  mStartStreamingAction->setText("Stop Streaming");
393  }
394  else
395  {
396  mStartStreamingAction->setIcon(QIcon(":/icons/streaming_red.png"));
397  mStartStreamingAction->setText("Start Streaming");
398  }
399 }
400 
401 void MainWindowActions::centerToImageCenterSlot()
402 {
403  NavigationPtr nav = viewService()->getNavigation();
404 
405  if (patientService()->getActiveImage())
406  nav->centerToData(patientService()->getActiveImage());
407  else if (!viewService()->groupCount())
408  nav->centerToView(viewService()->getGroup(0)->getData());
409  else
410  nav->centerToGlobalDataCenter();
411 }
412 
413 void MainWindowActions::centerToTooltipSlot()
414 {
415  NavigationPtr nav = viewService()->getNavigation();
416  nav->centerToTooltip();
417 }
418 
419 void MainWindowActions::togglePointPickerActionSlot()
420 {
421  ViewGroupDataPtr data = viewService()->getGroup(0);
422  ViewGroupData::Options options = data->getOptions();
423  options.mShowPointPickerProbe = !options.mShowPointPickerProbe;
424  data->setOptions(options);
425 }
426 void MainWindowActions::updatePointPickerActionSlot()
427 {
428  if (!viewService()->getGroup(0))
429  return;
430  bool show = viewService()->getGroup(0)->getOptions().mShowPointPickerProbe;
431  mShowPointPickerAction->setChecked(show);
432 }
433 
434 void MainWindowActions::updateTrackingActionSlot()
435 {
436  if (trackingService()->getState() >= Tool::tsTRACKING)
437  {
438  mTrackingToolsAction->setIcon(QIcon(":/icons/polaris-green.png"));
439  mTrackingToolsAction->setText("Stop Tracking");
440  }
441  else
442  {
443  mTrackingToolsAction->setIcon(QIcon(":/icons/polaris-red.png"));
444  mTrackingToolsAction->setText("Start Tracking");
445  }
446 }
447 
448 void MainWindowActions::configureSlot()
449 {
450  trackingService()->setState(Tool::tsCONFIGURED);
451 }
452 
453 void MainWindowActions::toggleTrackingSlot()
454 {
455  if (trackingService()->getState() >= Tool::tsTRACKING)
457  else
458  trackingService()->setState(Tool::tsTRACKING);
459 }
460 
461 void MainWindowActions::onGotoDocumentation()
462 {
464  QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
465 }
466 
467 
468 
469 } // namespace cx
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:142
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:99
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:91
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.