Medical Imaging Interaction Toolkit  2018.4.99-08619e4f
Medical Imaging Interaction Toolkit
mitkWorkbenchUtil.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkWorkbenchUtil.h"
14 
15 #include <berryPlatform.h>
16 #include <berryPlatformUI.h>
17 #include <berryIEditorRegistry.h>
18 #include <berryCoreException.h>
20 #include <berryIPreferences.h>
21 
24 #include "mitkRenderingManager.h"
25 #include "mitkIRenderingManager.h"
26 
27 #include "mitkProperties.h"
28 #include "mitkNodePredicateData.h"
29 #include "mitkNodePredicateNot.h"
31 #include "mitkCoreObjectFactory.h"
32 
33 #include "QmitkIOUtil.h"
34 
35 #include <QMessageBox>
36 #include <QApplication>
37 #include <QDateTime>
38 
39 #include "internal/org_mitk_gui_common_Activator.h"
40 
41 namespace mitk {
42 
43  struct WorkbenchUtilPrivate {
44 
59  static berry::IEditorDescriptor::Pointer GetEditorDescriptor(const QString& name, berry::IEditorRegistry* editorReg, berry::IEditorDescriptor::Pointer defaultDescriptor)
60  {
61  if (defaultDescriptor.IsNotNull())
62  {
63  return defaultDescriptor;
64  }
65 
66  berry::IEditorDescriptor::Pointer editorDesc = defaultDescriptor;
67 
68  // next check the OS for in-place editor (OLE on Win32)
69  if (editorReg->IsSystemInPlaceEditorAvailable(name))
70  {
72  }
73 
74  // next check with the OS for an external editor
75  if (editorDesc.IsNull() && editorReg->IsSystemExternalEditorAvailable(name))
76  {
78  }
79 
80  // if no valid editor found, bail out
81  if (editorDesc.IsNull())
82  {
83  throw berry::PartInitException("No editor found");
84  }
85 
86  return editorDesc;
87  }
88 
89  static mitk::IDataStorageReference::Pointer GetDataStorageReference()
90  {
91  ctkPluginContext* context = mitk::PluginActivator::GetContext();
92  mitk::IDataStorageService* dss = nullptr;
93  ctkServiceReference dsRef = context->getServiceReference<mitk::IDataStorageService>();
94  if (dsRef)
95  {
96  dss = context->getService<mitk::IDataStorageService>(dsRef);
97  }
98 
99  if (nullptr == dss)
100  {
101  QString msg = "IDataStorageService service not available. Unable to open files.";
102  MITK_WARN << msg.toStdString();
103  QMessageBox::warning(QApplication::activeWindow(), "Unable to open files", msg);
104  return mitk::IDataStorageReference::Pointer(nullptr);
105  }
106 
107  // Get the active data storage (or the default one, if none is active)
109  context->ungetService(dsRef);
110 
111  return dataStorageRef;
112  }
113 
114  }; // end struct WorkbenchUtilPrivate
115 
116  void WorkbenchUtil::LoadFiles(const QStringList &fileNames, berry::IWorkbenchWindow::Pointer window, bool openEditor)
117  {
118  if (fileNames.empty())
119  {
120  return;
121  }
122 
123  mitk::IDataStorageReference::Pointer dataStorageReference = WorkbenchUtilPrivate::GetDataStorageReference();
124  if (nullptr == dataStorageReference)
125  {
126  return;
127  }
128  mitk::DataStorage::Pointer dataStorage = dataStorageReference->GetDataStorage();
129 
130  // Turn off ASSERT
131 #if defined(_MSC_VER) && !defined(NDEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
132  int lastCrtReportType = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
133 #endif
134 
135  // Do the actual work of loading the data into the data storage
136  DataStorage::SetOfObjects::Pointer data;
137  try
138  {
139  data = QmitkIOUtil::Load(fileNames, *dataStorage);
140  }
141  catch (const mitk::Exception& e)
142  {
143  MITK_INFO << e;
144  return;
145  }
146  const bool dsmodified = !data->empty();
147 
148  // Set ASSERT status back to previous status.
149 #if defined(_MSC_VER) && !defined(NDEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
150  if (lastCrtReportType)
151  _CrtSetReportMode(_CRT_ASSERT, lastCrtReportType);
152 #endif
153 
154  // Check if there is an open perspective. If not, open the default perspective.
155  if (window->GetActivePage().IsNull())
156  {
157  QString defaultPerspId = window->GetWorkbench()->GetPerspectiveRegistry()->GetDefaultPerspective();
158  window->GetWorkbench()->ShowPerspective(defaultPerspId, window);
159  }
160 
161  bool globalReinitOnNodeAdded = true;
163  if (prefService != nullptr)
164  {
166  = prefService->GetSystemPreferences()->Node("org.mitk.views.datamanager");
167  if (prefs.IsNotNull())
168  {
169  globalReinitOnNodeAdded = prefs->GetBool("Call global reinit if node is added", true);
170  }
171  }
172 
173  if (openEditor && globalReinitOnNodeAdded)
174  {
175  try
176  {
177  // Activate the editor using the same data storage or open the default editor
179  berry::IEditorPart::Pointer editor = mitk::WorkbenchUtil::OpenEditor(window->GetActivePage(), input, true);
180  mitk::IRenderWindowPart* renderEditor = dynamic_cast<mitk::IRenderWindowPart*>(editor.GetPointer());
181  mitk::IRenderingManager* renderingManager = renderEditor == nullptr ? nullptr : renderEditor->GetRenderingManager();
182 
183  if (dsmodified && renderingManager)
184  {
186  }
187  }
188  catch (const berry::PartInitException& e)
189  {
190  QString msg = "An error occurred when displaying the file(s): %1";
191  QMessageBox::warning(QApplication::activeWindow(), "Error displaying file",
192  msg.arg(e.message()));
193  }
194  }
195  }
196 
198  {
199  // sanity checks
200  if (page.IsNull())
201  {
202  throw std::invalid_argument("page argument must not be nullptr");
203  }
204 
205  // open the editor on the input
206  return page->OpenEditor(input, editorId, activate);
207  }
208 
210  {
211  // sanity checks
212  if (page.IsNull())
213  {
214  throw std::invalid_argument("page argument must not be nullptr");
215  }
216 
217  // open the editor on the data storage
218  QString name = input->GetName() + ".mitk";
219  berry::IEditorDescriptor::Pointer editorDesc = WorkbenchUtilPrivate::GetEditorDescriptor(name,
220  berry::PlatformUI::GetWorkbench()->GetEditorRegistry(),
221  GetDefaultEditor(name, determineContentType));
222 
223  return page->OpenEditor(input, editorDesc->GetId(), activate);
224  }
225 
226  berry::IEditorDescriptor::Pointer WorkbenchUtil::GetEditorDescriptor(const QString& name, bool /*inferContentType*/)
227  {
228  if (name.isEmpty())
229  {
230  throw std::invalid_argument("name argument must not be empty");
231  }
232 
233  // no used for now
234  //IContentType contentType = inferContentType ? Platform
235  // .getContentTypeManager().findContentTypeFor(name) : null;
236 
238 
239  return WorkbenchUtilPrivate::GetEditorDescriptor(name, editorReg, editorReg->GetDefaultEditor(name /*, contentType*/));
240  }
241 
242  berry::IEditorDescriptor::Pointer WorkbenchUtil::GetDefaultEditor(const QString& name, bool /*determineContentType*/)
243  {
244  // Try file specific editor.
246  try
247  {
248  QString editorID; // = file.getPersistentProperty(EDITOR_KEY);
249  if (!editorID.isEmpty())
250  {
251  berry::IEditorDescriptor::Pointer desc = editorReg->FindEditor(editorID);
252  if (desc.IsNotNull())
253  {
254  return desc;
255  }
256  }
257  }
258  catch (const berry::CoreException&)
259  {
260  // do nothing
261  }
262 
263  // IContentType contentType = null;
264  // if (determineContentType)
265  // {
266  // contentType = getContentType(file);
267  // }
268 
269  // Try lookup with filename
270  return editorReg->GetDefaultEditor(name); //, contentType);
271  }
272 
274  {
275  // Return the active editor if it implements mitk::IRenderWindowPart
276  mitk::IRenderWindowPart* renderWindowPart = dynamic_cast<mitk::IRenderWindowPart*>(page->GetActiveEditor().GetPointer());
277  if (renderWindowPart)
278  {
279  return renderWindowPart;
280  }
281 
282  // No suitable active editor found, check visible editors
283  QList<berry::IEditorReference::Pointer> editors = page->GetEditorReferences();
284  for (QList<berry::IEditorReference::Pointer>::iterator i = editors.begin(); i != editors.end(); ++i)
285  {
286  berry::IWorkbenchPart::Pointer part = (*i)->GetPart(false);
287  if (page->IsPartVisible(part))
288  {
289  renderWindowPart = dynamic_cast<mitk::IRenderWindowPart*>(part.GetPointer());
290  if (renderWindowPart)
291  {
292  return renderWindowPart;
293  }
294  }
295  }
296 
297  // No suitable visible editor found, check visible views
298  QList<berry::IViewReference::Pointer> views = page->GetViewReferences();
299  for (QList<berry::IViewReference::Pointer>::iterator i = views.begin(); i != views.end(); ++i)
300  {
301  berry::IWorkbenchPart::Pointer part = (*i)->GetPart(false);
302  if (page->IsPartVisible(part))
303  {
304  renderWindowPart = dynamic_cast<mitk::IRenderWindowPart*>(part.GetPointer());
305  if (renderWindowPart)
306  {
307  return renderWindowPart;
308  }
309  }
310  }
311 
312  // No strategies given
313  if (strategies == NONE)
314  {
315  return nullptr;
316  }
317 
318  mitk::IDataStorageReference::Pointer dataStorageReference = WorkbenchUtilPrivate::GetDataStorageReference();
319  if (nullptr == dataStorageReference)
320  {
321  return nullptr;
322  }
323 
325 
326  bool activate = false;
327  if (strategies & ACTIVATE)
328  {
329  activate = true;
330  }
331 
332  berry::IEditorPart::Pointer editorPart;
333  if (strategies & OPEN)
334  {
335  // This will create a default editor for the given input. If an editor
336  // with that input is already open, the editor is brought to the front.
337  try
338  {
339  editorPart = mitk::WorkbenchUtil::OpenEditor(page, input, activate);
340  }
341  catch (const berry::PartInitException&)
342  {
343  // There is no editor registered which can handle the given input.
344  }
345  }
346  else if (activate || (strategies & BRING_TO_FRONT))
347  {
348  // check if a suitable editor is already opened
349  editorPart = page->FindEditor(input);
350  if (editorPart)
351  {
352  if (activate)
353  {
354  page->Activate(editorPart);
355  }
356  else
357  {
358  page->BringToTop(editorPart);
359  }
360  }
361  }
362 
363  return dynamic_cast<mitk::IRenderWindowPart*>(editorPart.GetPointer());
364  }
365 
367  {
368  if (activatedEditor)
369  {
370  return GetRenderWindowPart(page, ACTIVATE | OPEN);
371  }
372  else
373  {
374  return GetRenderWindowPart(page, BRING_TO_FRONT | OPEN);
375  }
376  }
377 
378  bool WorkbenchUtil::SetDepartmentLogoPreference(const QString &logoResource, ctkPluginContext *context)
379  {
380  if (context == nullptr)
381  {
382  BERRY_WARN << "Plugin context invalid, unable to set custom logo.";
383  return false;
384  }
385 
386  // The logo must be available in the local filesystem. We check if we have not already extracted the
387  // logo from the plug-in or if this plug-ins timestamp is newer then the already extracted logo timestamp.
388  // If one of the conditions is true, extract it and write it to the plug-in specific storage location.
389  const QString logoFileName = logoResource.mid(logoResource.lastIndexOf('/') + 1);
390 
391  if (logoFileName.isEmpty())
392  {
393  BERRY_WARN << "Logo file name empty, unable to set custom logo.";
394  return false;
395  }
396 
397  const QString logoPath = context->getDataFile("").absoluteFilePath();
398 
399  bool extractLogo = true;
400  QFileInfo logoFileInfo(logoPath + "/" + logoFileName);
401 
402  if (logoFileInfo.exists())
403  {
404  // The logo has been extracted previously. Check if the plugin timestamp is newer, which
405  // means it might contain an updated logo.
406  QString pluginLocation = QUrl(context->getPlugin()->getLocation()).toLocalFile();
407  if (!pluginLocation.isEmpty())
408  {
409  QFileInfo pluginFileInfo(pluginLocation);
410  if (logoFileInfo.lastModified() > pluginFileInfo.lastModified())
411  {
412  extractLogo = false;
413  }
414  }
415  }
416 
417  if (extractLogo)
418  {
419  // Extract the logo from the shared library and write it to disk.
420  QFile logo(logoResource);
421 
422  if (!logo.exists())
423  {
424  BERRY_WARN << "Custom logo '" << logoResource << "' does not exist.";
425  return false;
426  }
427 
428  if (logo.open(QIODevice::ReadOnly))
429  {
430  QFile localLogo(logoPath + "/" + logoFileName);
431 
432  if (localLogo.open(QIODevice::WriteOnly))
433  {
434  localLogo.write(logo.readAll());
435  localLogo.flush();
436  }
437  }
438  }
439 
440  logoFileInfo.refresh();
441 
442  if (logoFileInfo.exists())
443  {
444  // Get the preferences service
445  ctkServiceReference prefServiceRef = context->getServiceReference<berry::IPreferencesService>();
446  berry::IPreferencesService* prefService = nullptr;
447  if (prefServiceRef)
448  {
449  prefService = context->getService<berry::IPreferencesService>(prefServiceRef);
450  }
451 
452  if (prefService)
453  {
454  prefService->GetSystemPreferences()->Put("DepartmentLogo", qPrintable(logoFileInfo.absoluteFilePath()));
455  }
456  else
457  {
458  BERRY_WARN << "Preferences service not available, unable to set custom logo.";
459  return false;
460  }
461  }
462  else
463  {
464  BERRY_WARN << "Custom logo at '" << logoFileInfo.absoluteFilePath().toStdString() << "' does not exist.";
465  return false;
466  }
467 
468  return true;
469  }
470 
471 } // namespace mitk
static const QString SYSTEM_INPLACE_EDITOR_ID
static berry::IEditorDescriptor::Pointer GetDefaultEditor(const QString &file, bool determineContentType)
virtual IEditorDescriptor::Pointer FindEditor(const QString &editorId)=0
#define MITK_INFO
Definition: mitkLogMacros.h:18
static berry::IEditorDescriptor::Pointer GetEditorDescriptor(const QString &name, bool inferContentType=true)
virtual IDataStorageReference::Pointer GetDataStorage() const =0
Interface for a MITK Workbench Part providing a render window.
static IRenderWindowPart * GetRenderWindowPart(berry::IWorkbenchPage::Pointer page, IRenderWindowPartStrategies strategies)
Returns the currently active mitk::IRenderWindowPart.
DataCollection - Class to facilitate loading/accessing structured data.
virtual SmartPointer< IPreferences > GetSystemPreferences()=0
static IRenderWindowPart * OpenRenderWindowPart(berry::IWorkbenchPage::Pointer page, bool activatedEditor=true)
Uses &#39;GetRenderWindowPart&#39; to open the a render window part with a certain strategy: Calls &#39;GetRender...
An editor input based on a mitk::DataStorage.
static bool SetDepartmentLogoPreference(const QString &logoResource, ctkPluginContext *context)
static void LoadFiles(const QStringList &fileNames, berry::IWorkbenchWindow::Pointer wnd, bool openEditor=true)
berry::SmartPointer< Self > Pointer
Definition: berryObject.h:82
#define MITK_WARN
Definition: mitkLogMacros.h:19
An object of this class represents an exception of MITK. Please don&#39;t instantiate exceptions manually...
Definition: mitkException.h:45
static RenderingManager * GetInstance()
static IWorkbench * GetWorkbench()
virtual IEditorDescriptor::Pointer GetDefaultEditor()=0
#define BERRY_WARN
Definition: berryLog.h:21
virtual bool IsSystemInPlaceEditorAvailable(const QString &filename)=0
virtual bool IsSystemExternalEditorAvailable(const QString &filename)=0
static berry::IEditorPart::Pointer OpenEditor(berry::IWorkbenchPage::Pointer page, berry::IEditorInput::Pointer input, const QString &editorId, bool activate=false)
static QList< mitk::BaseData::Pointer > Load(const QStringList &paths, QWidget *parent=nullptr)
Loads the specified files.
static const QString SYSTEM_EXTERNAL_EDITOR_ID
virtual void InitializeViewsByBoundingObjects(const DataStorage *)
Initializes the renderwindows by the aggregated geometry of all objects that are held in the data sto...
An interface for accessing a mitk::RenderingManager instance.
virtual IEditorRegistry * GetEditorRegistry() const =0
static IPreferencesService * GetPreferencesService()
ObjectType * GetPointer() const