CustusX  16.5
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->setShortcut(shortcut);
181  retval->setStatusTip(help);
182  connect(retval, &QAction::triggered, this, triggerSlot);
183  mActions[uid] = retval;
184  return retval;
185 }
186 
187 namespace
188 {
189 QString timestampFormatFolderFriendly()
190 {
191  return QString("yyyy-MM-dd_hh-mm");
192 }
193 }
194 
195 QWidget* MainWindowActions::parentWidget()
196 {
197  return dynamic_cast<QWidget*>(this->parent());
198 }
199 
200 
201 void MainWindowActions::newPatientSlot()
202 {
203  QString patientDatafolder = this->getExistingSessionFolder();
204 
205  QString timestamp = QDateTime::currentDateTime().toString(timestampFormatFolderFriendly());
206  QString filename = QString("%1_%2_%3.cx3")
207  .arg(timestamp)
208  .arg(profile()->getName())
209  .arg(settings()->value("globalPatientNumber").toString());
210 
211  QString choosenDir = patientDatafolder + "/" + filename;
212 
213  QFileDialog dialog(this->parentWidget(), tr("Select directory to save patient in"), patientDatafolder + "/");
214  dialog.setOption(QFileDialog::DontUseNativeDialog, true);
215  dialog.setOption(QFileDialog::ShowDirsOnly, true);
216  dialog.selectFile(filename);
217  if (!dialog.exec())
218  return;
219  choosenDir = dialog.selectedFiles().front();
220 
221  if (!choosenDir.endsWith(".cx3"))
222  choosenDir += QString(".cx3");
223 
224  // Update global patient number
225  int patientNumber = settings()->value("globalPatientNumber").toInt();
226  settings()->setValue("globalPatientNumber", ++patientNumber);
227 
228  mServices->session()->load(choosenDir);
229 }
230 
231 QString MainWindowActions::getExistingSessionFolder()
232 {
233  return profile()->getSessionRootFolder();
234 }
235 
236 void MainWindowActions::clearPatientSlot()
237 {
238  mServices->session()->clear();
239 }
240 
241 void MainWindowActions::savePatientFileSlot()
242 {
243  if (patientService()->getActivePatientFolder().isEmpty())
244  {
245  reportWarning("No patient selected, select or create patient before saving!");
246  this->newPatientSlot();
247  return;
248  }
249 
250  mServices->session()->save();
251 }
252 
253 void MainWindowActions::loadPatientFileSlot()
254 {
255  QString patientDatafolder = this->getExistingSessionFolder();
256 
257  // Open file dialog
258  QString folder = QFileDialog::getExistingDirectory(this->parentWidget(), "Select patient", patientDatafolder, QFileDialog::ShowDirsOnly);
259  if (folder.isEmpty())
260  return;
261 
262  mServices->session()->load(folder);
263 }
264 
265 void MainWindowActions::exportDataSlot()
266 {
267  this->savePatientFileSlot();
268 
269  ExportDataDialog* wizard = new ExportDataDialog(mServices->patient(), this->parentWidget());
270  wizard->exec(); //calling exec() makes the wizard dialog modal which prevents other user interaction with the system
271 }
272 
273 void MainWindowActions::importDataSlot()
274 {
275  this->savePatientFileSlot();
276 
277  QString folder = mLastImportDataFolder;
278  if (folder.isEmpty())
279  folder = profile()->getSessionRootFolder();
280 
281  QStringList fileName = QFileDialog::getOpenFileNames(this->parentWidget(), QString(tr("Select data file(s) for import")),
282  folder, tr("Image/Mesh (*.mhd *.mha *.stl *.vtk *.mnc *.png)"));
283  if (fileName.empty())
284  {
285  report("Import canceled");
286  return;
287  }
288 
289  mLastImportDataFolder = QFileInfo(fileName[0]).absolutePath();
290 
291  for (int i=0; i<fileName.size(); ++i)
292  {
293  ImportDataDialog* wizard = new ImportDataDialog(mServices->patient(), fileName[i], this->parentWidget());
294  wizard->exec(); //calling exec() makes the wizard dialog modal which prevents other user interaction with the system
295  }
296 }
297 
298 void MainWindowActions::shootScreen()
299 {
300  mScreenShotWriter->grabAllScreensToFile();
301 }
302 
303 void MainWindowActions::shootWindow()
304 {
305 // this->shootOneLayout(0);
306 
307  int index=0;
308  while (mServices->view()->getLayoutWidget(index))
309  this->shootOneLayout(index++);
310 }
311 
312 void MainWindowActions::shootOneLayout(int index)
313 {
314  QWidget* widget = mServices->view()->getLayoutWidget(index);
315  ViewCollectionWidget* vcWidget = dynamic_cast<ViewCollectionWidget*>(widget);
316 
317  ViewCollectionImageWriter grabber(vcWidget);
318  QImage pm = ViewCollectionImageWriter::vtkImageData2QImage(grabber.grab());
319  mScreenShotWriter->save(pm, QString("_layout%1").arg(index));
320 }
321 
322 void MainWindowActions::recordFullscreen()
323 {
324  QString path = patientService()->generateFilePath("Screenshots", "mp4");
325 
326  if(vlc()->isRecording())
327  vlc()->stopRecording();
328  else
329  vlc()->startRecording(path);
330 }
331 
332 void MainWindowActions::updateRecordFullscreenActionSlot()
333 {
334  mRecordFullscreenStreamingAction->setCheckable(true);
335  mRecordFullscreenStreamingAction->blockSignals(true);
336  mRecordFullscreenStreamingAction->setChecked(vlc()->isRecording());
337  mRecordFullscreenStreamingAction->blockSignals(false);
338 
339  if(vlc()->isRecording())
340  {
341  mRecordFullscreenStreamingAction->setIcon(QIcon(":/icons/Video-icon_green.png"));
342  }
343  else
344  {
345  mRecordFullscreenStreamingAction->setIcon(QIcon(":/icons/Video-icon_gray.png"));
346  }
347 
348 }
349 
350 void MainWindowActions::onStartLogConsole()
351 {
352  QString fullname = DataLocations::findExecutableInStandardLocations("LogConsole");
353 // std::cout << "MainWindowActions::onStartLogConsole() " << fullname << std::endl;
354  mLocalVideoServerProcess.reset(new ProcessWrapper(QString("LogConsole")));
355  mLocalVideoServerProcess->launchWithRelativePath(fullname, QStringList());
356 }
357 
358 void MainWindowActions::toggleStreamingSlot()
359 {
360  if (videoService()->isConnected())
361  videoService()->closeConnection();
362  else
363  videoService()->openConnection();
364 }
365 
366 void MainWindowActions::updateStreamingActionSlot()
367 {
368  if (videoService()->isConnected())
369  {
370  mStartStreamingAction->setIcon(QIcon(":/icons/streaming_green.png"));
371  mStartStreamingAction->setText("Stop Streaming");
372  }
373  else
374  {
375  mStartStreamingAction->setIcon(QIcon(":/icons/streaming_red.png"));
376  mStartStreamingAction->setText("Start Streaming");
377  }
378 }
379 
380 void MainWindowActions::centerToImageCenterSlot()
381 {
382  viewService()->centerToImageCenterInActiveViewGroup();
383 }
384 
385 void MainWindowActions::centerToTooltipSlot()
386 {
387  NavigationPtr nav = viewService()->getNavigation();
388  nav->centerToTooltip();
389 }
390 
391 void MainWindowActions::togglePointPickerActionSlot()
392 {
393  ViewGroupDataPtr data = viewService()->getGroup(0);
394  ViewGroupData::Options options = data->getOptions();
395  options.mShowPointPickerProbe = !options.mShowPointPickerProbe;
396  data->setOptions(options);
397 }
398 void MainWindowActions::updatePointPickerActionSlot()
399 {
400  if (!viewService()->getGroup(0))
401  return;
402  bool show = viewService()->getGroup(0)->getOptions().mShowPointPickerProbe;
403  mShowPointPickerAction->setChecked(show);
404 }
405 
406 void MainWindowActions::updateTrackingActionSlot()
407 {
408  if (trackingService()->getState() >= Tool::tsTRACKING)
409  {
410  mTrackingToolsAction->setIcon(QIcon(":/icons/polaris-green.png"));
411  mTrackingToolsAction->setText("Stop Tracking");
412  }
413  else
414  {
415  mTrackingToolsAction->setIcon(QIcon(":/icons/polaris-red.png"));
416  mTrackingToolsAction->setText("Start Tracking");
417  }
418 }
419 
420 void MainWindowActions::configureSlot()
421 {
422  trackingService()->setState(Tool::tsCONFIGURED);
423 }
424 
425 void MainWindowActions::toggleTrackingSlot()
426 {
427  if (trackingService()->getState() >= Tool::tsTRACKING)
429  else
430  trackingService()->setState(Tool::tsTRACKING);
431 }
432 
433 void MainWindowActions::onGotoDocumentation()
434 {
436  QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
437 }
438 
439 
440 
441 } // 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.