diff --git a/Plugins/org.mitk.gui.common/src/mitkWorkbenchUtil.cpp b/Plugins/org.mitk.gui.common/src/mitkWorkbenchUtil.cpp index 3a0fc9455b..7c569071d6 100644 --- a/Plugins/org.mitk.gui.common/src/mitkWorkbenchUtil.cpp +++ b/Plugins/org.mitk.gui.common/src/mitkWorkbenchUtil.cpp @@ -1,376 +1,475 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ - #include "mitkWorkbenchUtil.h" #include #include #include #include #include #include #include "mitkIDataStorageService.h" #include "mitkDataStorageEditorInput.h" #include "mitkRenderingManager.h" -#include "mitkIRenderWindowPart.h" #include "mitkIRenderingManager.h" #include "mitkProperties.h" #include "mitkNodePredicateData.h" #include "mitkNodePredicateNot.h" #include "mitkNodePredicateProperty.h" #include "mitkCoreObjectFactory.h" #include "QmitkIOUtil.h" #include #include #include #include "internal/org_mitk_gui_common_Activator.h" namespace mitk { -struct WorkbenchUtilPrivate { - - /** - * Get the editor descriptor for a given name using the editorDescriptor - * passed in as a default as a starting point. - * - * @param name - * The name of the element to open. - * @param editorReg - * The editor registry to do the lookups from. - * @param defaultDescriptor - * IEditorDescriptor or null - * @return IEditorDescriptor - * @throws PartInitException - * if no valid editor can be found - */ - static berry::IEditorDescriptor::Pointer GetEditorDescriptor(const QString& name, - berry::IEditorRegistry* editorReg, - berry::IEditorDescriptor::Pointer defaultDescriptor) - { - - if (defaultDescriptor.IsNotNull()) + struct WorkbenchUtilPrivate { + + /** + * Get the editor descriptor for a given name using the editorDescriptor + * passed in as a default as a starting point. + * + * @param name + * The name of the element to open. + * @param editorReg + * The editor registry to do the lookups from. + * @param defaultDescriptor + * IEditorDescriptor or null + * @return IEditorDescriptor + * @throws PartInitException + * if no valid editor can be found + */ + static berry::IEditorDescriptor::Pointer GetEditorDescriptor(const QString& name, berry::IEditorRegistry* editorReg, berry::IEditorDescriptor::Pointer defaultDescriptor) { - return defaultDescriptor; - } + if (defaultDescriptor.IsNotNull()) + { + return defaultDescriptor; + } - berry::IEditorDescriptor::Pointer editorDesc = defaultDescriptor; + berry::IEditorDescriptor::Pointer editorDesc = defaultDescriptor; - // next check the OS for in-place editor (OLE on Win32) - if (editorReg->IsSystemInPlaceEditorAvailable(name)) - { - editorDesc = editorReg->FindEditor(berry::IEditorRegistry::SYSTEM_INPLACE_EDITOR_ID); - } + // next check the OS for in-place editor (OLE on Win32) + if (editorReg->IsSystemInPlaceEditorAvailable(name)) + { + editorDesc = editorReg->FindEditor(berry::IEditorRegistry::SYSTEM_INPLACE_EDITOR_ID); + } - // next check with the OS for an external editor - if (editorDesc.IsNull() && editorReg->IsSystemExternalEditorAvailable(name)) - { - editorDesc = editorReg->FindEditor(berry::IEditorRegistry::SYSTEM_EXTERNAL_EDITOR_ID); + // next check with the OS for an external editor + if (editorDesc.IsNull() && editorReg->IsSystemExternalEditorAvailable(name)) + { + editorDesc = editorReg->FindEditor(berry::IEditorRegistry::SYSTEM_EXTERNAL_EDITOR_ID); + } + + // if no valid editor found, bail out + if (editorDesc.IsNull()) + { + throw berry::PartInitException("No editor found"); + } + + return editorDesc; } - // if no valid editor found, bail out - if (editorDesc.IsNull()) + static mitk::IDataStorageReference::Pointer GetDataStorageReference() { - throw berry::PartInitException("No editor found"); - } + ctkPluginContext* context = mitk::PluginActivator::GetContext(); + mitk::IDataStorageService* dss = nullptr; + ctkServiceReference dsRef = context->getServiceReference(); + if (dsRef) + { + dss = context->getService(dsRef); + } - return editorDesc; - } -}; -// //! [UtilLoadFiles] -void WorkbenchUtil::LoadFiles(const QStringList &fileNames, berry::IWorkbenchWindow::Pointer window, bool openEditor) -// //! [UtilLoadFiles] -{ - if (fileNames.empty()) - return; + if (nullptr == dss) + { + QString msg = "IDataStorageService service not available. Unable to open files."; + MITK_WARN << msg.toStdString(); + QMessageBox::warning(QApplication::activeWindow(), "Unable to open files", msg); + return mitk::IDataStorageReference::Pointer(nullptr); + } - mitk::IDataStorageReference::Pointer dataStorageRef; + // Get the active data storage (or the default one, if none is active) + mitk::IDataStorageReference::Pointer dataStorageRef = dss->GetDataStorage(); + context->ungetService(dsRef); + return dataStorageRef; + } + + }; // end struct WorkbenchUtilPrivate + + void WorkbenchUtil::LoadFiles(const QStringList &fileNames, berry::IWorkbenchWindow::Pointer window, bool openEditor) { - ctkPluginContext* context = mitk::PluginActivator::GetContext(); - mitk::IDataStorageService* dss = nullptr; - ctkServiceReference dsRef = context->getServiceReference(); - if (dsRef) + if (fileNames.empty()) { - dss = context->getService(dsRef); + return; } - if (!dss) + mitk::IDataStorageReference::Pointer dataStorageReference = WorkbenchUtilPrivate::GetDataStorageReference(); + if (nullptr == dataStorageReference) { - QString msg = "IDataStorageService service not available. Unable to open files."; - MITK_WARN << msg.toStdString(); - QMessageBox::warning(QApplication::activeWindow(), "Unable to open files", msg); return; } + mitk::DataStorage::Pointer dataStorage = dataStorageReference->GetDataStorage(); - // Get the active data storage (or the default one, if none is active) - dataStorageRef = dss->GetDataStorage(); - context->ungetService(dsRef); - } - - mitk::DataStorage::Pointer dataStorage = dataStorageRef->GetDataStorage(); - - // Do the actual work of loading the data into the data storage - - // Turn off ASSERT - #if defined(_MSC_VER) && !defined(NDEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) - int lastCrtReportType = _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_DEBUG ); - #endif + // Turn off ASSERT +#if defined(_MSC_VER) && !defined(NDEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) + int lastCrtReportType = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); +#endif - DataStorage::SetOfObjects::Pointer data; - try - { - data = QmitkIOUtil::Load(fileNames, *dataStorage); - } - catch (const mitk::Exception& e) - { - MITK_INFO << e; - return; - } - const bool dsmodified = !data->empty(); + // Do the actual work of loading the data into the data storage + DataStorage::SetOfObjects::Pointer data; + try + { + data = QmitkIOUtil::Load(fileNames, *dataStorage); + } + catch (const mitk::Exception& e) + { + MITK_INFO << e; + return; + } + const bool dsmodified = !data->empty(); - // Set ASSERT status back to previous status. - #if defined(_MSC_VER) && !defined(NDEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) + // Set ASSERT status back to previous status. +#if defined(_MSC_VER) && !defined(NDEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) if (lastCrtReportType) - _CrtSetReportMode( _CRT_ASSERT, lastCrtReportType ); - #endif + _CrtSetReportMode(_CRT_ASSERT, lastCrtReportType); +#endif - // Check if there is an open perspective. If not, open the default perspective. - if (window->GetActivePage().IsNull()) - { - QString defaultPerspId = window->GetWorkbench()->GetPerspectiveRegistry()->GetDefaultPerspective(); - window->GetWorkbench()->ShowPerspective(defaultPerspId, window); - } + // Check if there is an open perspective. If not, open the default perspective. + if (window->GetActivePage().IsNull()) + { + QString defaultPerspId = window->GetWorkbench()->GetPerspectiveRegistry()->GetDefaultPerspective(); + window->GetWorkbench()->ShowPerspective(defaultPerspId, window); + } - bool globalReinitOnNodeAdded = true; - berry::IPreferencesService* prefService = berry::Platform::GetPreferencesService(); - if (prefService != nullptr) - { + bool globalReinitOnNodeAdded = true; + berry::IPreferencesService* prefService = berry::Platform::GetPreferencesService(); + if (prefService != nullptr) + { berry::IPreferences::Pointer prefs - = prefService->GetSystemPreferences()->Node("org.mitk.views.datamanager"); - if(prefs.IsNotNull()) + = prefService->GetSystemPreferences()->Node("org.mitk.views.datamanager"); + if (prefs.IsNotNull()) { globalReinitOnNodeAdded = prefs->GetBool("Call global reinit if node is added", true); } - } + } - if (openEditor && globalReinitOnNodeAdded) - { - try + if (openEditor && globalReinitOnNodeAdded) { - // Activate the editor using the same data storage or open the default editor - mitk::DataStorageEditorInput::Pointer input(new mitk::DataStorageEditorInput(dataStorageRef)); - berry::IEditorPart::Pointer editor = mitk::WorkbenchUtil::OpenEditor(window->GetActivePage(), input, true); - mitk::IRenderWindowPart* renderEditor = dynamic_cast(editor.GetPointer()); - mitk::IRenderingManager* renderingManager = renderEditor == nullptr ? nullptr : renderEditor->GetRenderingManager(); - - if(dsmodified && renderingManager) + try { - mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage); + // Activate the editor using the same data storage or open the default editor + mitk::DataStorageEditorInput::Pointer input(new mitk::DataStorageEditorInput(dataStorageReference)); + berry::IEditorPart::Pointer editor = mitk::WorkbenchUtil::OpenEditor(window->GetActivePage(), input, true); + mitk::IRenderWindowPart* renderEditor = dynamic_cast(editor.GetPointer()); + mitk::IRenderingManager* renderingManager = renderEditor == nullptr ? nullptr : renderEditor->GetRenderingManager(); + + if (dsmodified && renderingManager) + { + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage); + } + } + catch (const berry::PartInitException& e) + { + QString msg = "An error occurred when displaying the file(s): %1"; + QMessageBox::warning(QApplication::activeWindow(), "Error displaying file", + msg.arg(e.message())); } - } - catch (const berry::PartInitException& e) - { - QString msg = "An error occurred when displaying the file(s): %1"; - QMessageBox::warning(QApplication::activeWindow(), "Error displaying file", - msg.arg(e.message())); } } -} - -berry::IEditorPart::Pointer WorkbenchUtil::OpenEditor(berry::IWorkbenchPage::Pointer page, - berry::IEditorInput::Pointer input, - const QString &editorId, bool activate) -{ - // sanity checks - if (page.IsNull()) + + berry::IEditorPart::Pointer WorkbenchUtil::OpenEditor(berry::IWorkbenchPage::Pointer page, berry::IEditorInput::Pointer input, const QString &editorId, bool activate) { - throw std::invalid_argument("page argument must not be nullptr"); + // sanity checks + if (page.IsNull()) + { + throw std::invalid_argument("page argument must not be nullptr"); + } + + // open the editor on the input + return page->OpenEditor(input, editorId, activate); } - // open the editor on the input - return page->OpenEditor(input, editorId, activate); -} - -berry::IEditorPart::Pointer WorkbenchUtil::OpenEditor(berry::IWorkbenchPage::Pointer page, - mitk::DataStorageEditorInput::Pointer input, - bool activate, - bool determineContentType) -{ - // sanity checks - if (page.IsNull()) + berry::IEditorPart::Pointer WorkbenchUtil::OpenEditor(berry::IWorkbenchPage::Pointer page, mitk::DataStorageEditorInput::Pointer input, bool activate, bool determineContentType) { - throw std::invalid_argument("page argument must not be nullptr"); + // sanity checks + if (page.IsNull()) + { + throw std::invalid_argument("page argument must not be nullptr"); + } + + // open the editor on the data storage + QString name = input->GetName() + ".mitk"; + berry::IEditorDescriptor::Pointer editorDesc = WorkbenchUtilPrivate::GetEditorDescriptor(name, + berry::PlatformUI::GetWorkbench()->GetEditorRegistry(), + GetDefaultEditor(name, determineContentType)); + + return page->OpenEditor(input, editorDesc->GetId(), activate); } - // open the editor on the data storage - QString name = input->GetName() + ".mitk"; - berry::IEditorDescriptor::Pointer editorDesc = - WorkbenchUtilPrivate::GetEditorDescriptor(name, - berry::PlatformUI::GetWorkbench()->GetEditorRegistry(), - GetDefaultEditor(name, determineContentType)); - return page->OpenEditor(input, editorDesc->GetId(), activate); -} - -berry::IEditorDescriptor::Pointer WorkbenchUtil::GetEditorDescriptor( - const QString& name, bool /*inferContentType*/) -{ - if (name.isEmpty()) + berry::IEditorDescriptor::Pointer WorkbenchUtil::GetEditorDescriptor(const QString& name, bool /*inferContentType*/) { - throw std::invalid_argument("name argument must not be empty"); - } + if (name.isEmpty()) + { + throw std::invalid_argument("name argument must not be empty"); + } - // no used for now - //IContentType contentType = inferContentType ? Platform - // .getContentTypeManager().findContentTypeFor(name) : null; + // no used for now + //IContentType contentType = inferContentType ? Platform + // .getContentTypeManager().findContentTypeFor(name) : null; - berry::IEditorRegistry* editorReg = berry::PlatformUI::GetWorkbench()->GetEditorRegistry(); + berry::IEditorRegistry* editorReg = berry::PlatformUI::GetWorkbench()->GetEditorRegistry(); - return WorkbenchUtilPrivate::GetEditorDescriptor(name, editorReg, - editorReg->GetDefaultEditor(name /*, contentType*/)); -} + return WorkbenchUtilPrivate::GetEditorDescriptor(name, editorReg, editorReg->GetDefaultEditor(name /*, contentType*/)); + } -berry::IEditorDescriptor::Pointer WorkbenchUtil::GetDefaultEditor(const QString& name, - bool /*determineContentType*/) -{ - // Try file specific editor. - berry::IEditorRegistry* editorReg = berry::PlatformUI::GetWorkbench()->GetEditorRegistry(); - try + berry::IEditorDescriptor::Pointer WorkbenchUtil::GetDefaultEditor(const QString& name, bool /*determineContentType*/) { - QString editorID; // = file.getPersistentProperty(EDITOR_KEY); - if (!editorID.isEmpty()) + // Try file specific editor. + berry::IEditorRegistry* editorReg = berry::PlatformUI::GetWorkbench()->GetEditorRegistry(); + try { - berry::IEditorDescriptor::Pointer desc = editorReg->FindEditor(editorID); - if (desc.IsNotNull()) + QString editorID; // = file.getPersistentProperty(EDITOR_KEY); + if (!editorID.isEmpty()) { - return desc; + berry::IEditorDescriptor::Pointer desc = editorReg->FindEditor(editorID); + if (desc.IsNotNull()) + { + return desc; + } } } - } - catch (const berry::CoreException&) - { - // do nothing - } + catch (const berry::CoreException&) + { + // do nothing + } -// IContentType contentType = null; -// if (determineContentType) -// { -// contentType = getContentType(file); -// } + // IContentType contentType = null; + // if (determineContentType) + // { + // contentType = getContentType(file); + // } - // Try lookup with filename - return editorReg->GetDefaultEditor(name); //, contentType); -} + // Try lookup with filename + return editorReg->GetDefaultEditor(name); //, contentType); + } -bool WorkbenchUtil::SetDepartmentLogoPreference(const QString &logoResource, ctkPluginContext *context) -{ - if (context == nullptr) + mitk::IRenderWindowPart* WorkbenchUtil::GetRenderWindowPart(berry::IWorkbenchPage::Pointer page, IRenderWindowPartStrategies strategies) { - BERRY_WARN << "Plugin context invalid, unable to set custom logo."; - return false; - } + // Return the active editor if it implements mitk::IRenderWindowPart + mitk::IRenderWindowPart* renderWindowPart = dynamic_cast(page->GetActiveEditor().GetPointer()); + if (renderWindowPart) + { + return renderWindowPart; + } - // The logo must be available in the local filesystem. We check if we have not already extracted the - // logo from the plug-in or if this plug-ins timestamp is newer then the already extracted logo timestamp. - // If one of the conditions is true, extract it and write it to the plug-in specific storage location. - const QString logoFileName = logoResource.mid(logoResource.lastIndexOf('/')+1); + // No suitable active editor found, check visible editors + QList editors = page->GetEditorReferences(); + for (QList::iterator i = editors.begin(); i != editors.end(); ++i) + { + berry::IWorkbenchPart::Pointer part = (*i)->GetPart(false); + if (page->IsPartVisible(part)) + { + renderWindowPart = dynamic_cast(part.GetPointer()); + if (renderWindowPart) + { + return renderWindowPart; + } + } + } - if (logoFileName.isEmpty()) - { - BERRY_WARN << "Logo file name empty, unable to set custom logo."; - return false; - } + // No suitable visible editor found, check visible views + QList views = page->GetViewReferences(); + for (QList::iterator i = views.begin(); i != views.end(); ++i) + { + berry::IWorkbenchPart::Pointer part = (*i)->GetPart(false); + if (page->IsPartVisible(part)) + { + renderWindowPart = dynamic_cast(part.GetPointer()); + if (renderWindowPart) + { + return renderWindowPart; + } + } + } - const QString logoPath = context->getDataFile("").absoluteFilePath(); + // No strategies given + if (strategies == NONE) + { + return nullptr; + } - bool extractLogo = true; - QFileInfo logoFileInfo(logoPath + "/" + logoFileName); + mitk::IDataStorageReference::Pointer dataStorageReference = WorkbenchUtilPrivate::GetDataStorageReference(); + if (nullptr == dataStorageReference) + { + return nullptr; + } - if (logoFileInfo.exists()) - { - // The logo has been extracted previously. Check if the plugin timestamp is newer, which - // means it might contain an updated logo. - QString pluginLocation = QUrl(context->getPlugin()->getLocation()).toLocalFile(); - if (!pluginLocation.isEmpty()) + mitk::DataStorageEditorInput::Pointer input(new mitk::DataStorageEditorInput(dataStorageReference)); + + bool activate = false; + if (strategies & ACTIVATE) + { + activate = true; + } + + berry::IEditorPart::Pointer editorPart; + if (strategies & OPEN) { - QFileInfo pluginFileInfo(pluginLocation); - if (logoFileInfo.lastModified() > pluginFileInfo.lastModified()) + // This will create a default editor for the given input. If an editor + // with that input is already open, the editor is brought to the front. + try { - extractLogo = false; + editorPart = mitk::WorkbenchUtil::OpenEditor(page, input, activate); + } + catch (const berry::PartInitException&) + { + // There is no editor registered which can handle the given input. + } + } + else if (activate || (strategies & BRING_TO_FRONT)) + { + // check if a suitable editor is already opened + editorPart = page->FindEditor(input); + if (editorPart) + { + if (activate) + { + page->Activate(editorPart); + } + else + { + page->BringToTop(editorPart); + } } } + + return dynamic_cast(editorPart.GetPointer()); } - if (extractLogo) + mitk::IRenderWindowPart* WorkbenchUtil::OpenRenderWindowPart(berry::IWorkbenchPage::Pointer page, bool activatedEditor/* = true*/) { - // Extract the logo from the shared library and write it to disk. - QFile logo(logoResource); + if (activatedEditor) + { + return GetRenderWindowPart(page, ACTIVATE | OPEN); + } + else + { + return GetRenderWindowPart(page, BRING_TO_FRONT | OPEN); + } + } - if (!logo.exists()) + bool WorkbenchUtil::SetDepartmentLogoPreference(const QString &logoResource, ctkPluginContext *context) + { + if (context == nullptr) { - BERRY_WARN << "Custom logo '" << logoResource << "' does not exist."; + BERRY_WARN << "Plugin context invalid, unable to set custom logo."; return false; } - if (logo.open(QIODevice::ReadOnly)) + // The logo must be available in the local filesystem. We check if we have not already extracted the + // logo from the plug-in or if this plug-ins timestamp is newer then the already extracted logo timestamp. + // If one of the conditions is true, extract it and write it to the plug-in specific storage location. + const QString logoFileName = logoResource.mid(logoResource.lastIndexOf('/') + 1); + + if (logoFileName.isEmpty()) { - QFile localLogo(logoPath + "/" + logoFileName); + BERRY_WARN << "Logo file name empty, unable to set custom logo."; + return false; + } - if (localLogo.open(QIODevice::WriteOnly)) + const QString logoPath = context->getDataFile("").absoluteFilePath(); + + bool extractLogo = true; + QFileInfo logoFileInfo(logoPath + "/" + logoFileName); + + if (logoFileInfo.exists()) + { + // The logo has been extracted previously. Check if the plugin timestamp is newer, which + // means it might contain an updated logo. + QString pluginLocation = QUrl(context->getPlugin()->getLocation()).toLocalFile(); + if (!pluginLocation.isEmpty()) { - localLogo.write(logo.readAll()); - localLogo.flush(); + QFileInfo pluginFileInfo(pluginLocation); + if (logoFileInfo.lastModified() > pluginFileInfo.lastModified()) + { + extractLogo = false; + } } } - } - logoFileInfo.refresh(); - - if (logoFileInfo.exists()) - { - // Get the preferences service - ctkServiceReference prefServiceRef = context->getServiceReference(); - berry::IPreferencesService* prefService = nullptr; - if (prefServiceRef) + if (extractLogo) { - prefService = context->getService(prefServiceRef); + // Extract the logo from the shared library and write it to disk. + QFile logo(logoResource); + + if (!logo.exists()) + { + BERRY_WARN << "Custom logo '" << logoResource << "' does not exist."; + return false; + } + + if (logo.open(QIODevice::ReadOnly)) + { + QFile localLogo(logoPath + "/" + logoFileName); + + if (localLogo.open(QIODevice::WriteOnly)) + { + localLogo.write(logo.readAll()); + localLogo.flush(); + } + } } - if (prefService) + logoFileInfo.refresh(); + + if (logoFileInfo.exists()) { - prefService->GetSystemPreferences()->Put("DepartmentLogo", qPrintable(logoFileInfo.absoluteFilePath())); + // Get the preferences service + ctkServiceReference prefServiceRef = context->getServiceReference(); + berry::IPreferencesService* prefService = nullptr; + if (prefServiceRef) + { + prefService = context->getService(prefServiceRef); + } + + if (prefService) + { + prefService->GetSystemPreferences()->Put("DepartmentLogo", qPrintable(logoFileInfo.absoluteFilePath())); + } + else + { + BERRY_WARN << "Preferences service not available, unable to set custom logo."; + return false; + } } else { - BERRY_WARN << "Preferences service not available, unable to set custom logo."; + BERRY_WARN << "Custom logo at '" << logoFileInfo.absoluteFilePath().toStdString() << "' does not exist."; return false; } - } - else - { - BERRY_WARN << "Custom logo at '" << logoFileInfo.absoluteFilePath().toStdString() << "' does not exist."; - return false; - } - return true; -} + return true; + } } // namespace mitk diff --git a/Plugins/org.mitk.gui.common/src/mitkWorkbenchUtil.h b/Plugins/org.mitk.gui.common/src/mitkWorkbenchUtil.h index b3dc8a8e86..238d8fc94d 100644 --- a/Plugins/org.mitk.gui.common/src/mitkWorkbenchUtil.h +++ b/Plugins/org.mitk.gui.common/src/mitkWorkbenchUtil.h @@ -1,189 +1,214 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKWORKBENCHUTIL_H #define MITKWORKBENCHUTIL_H #include #include "mitkDataStorageEditorInput.h" +#include "mitkIRenderWindowPart.h" + #include #include class ctkPluginContext; namespace mitk { - -/** - * @ingroup org_mitk_gui_common - * - * @brief Utility class for loading data, opening editors and other tasks in a MITK Workbench. - * - * @note Infering the content type is not yet supported (ignore the comments about it - * in the method documentation). - */ -struct MITK_GUI_COMMON_PLUGIN WorkbenchUtil -{ - /** - * Loads the set of given files into the active data storage of the given Workbench window. - * - * If the window already has an editor open on the active datastorage then that editor - * is activated; otherwise the default editor for the "mitk" extension is activated. + * @ingroup org_mitk_gui_common * - * @param fileNames - * A list of file names with absolute path. - * @param wnd - * The Workbench window in which the data will be loaded. - * @param openEditor - * Whether an Editor is to be opened on file loading (for cases there is none). + * @brief Utility class for loading data, opening editors and other tasks in a MITK Workbench. * - * @see mitk::IOUtil + * @note Inferring the content type is not yet supported (ignore the comments about it + * in the method documentation). */ - static void LoadFiles(const QStringList& fileNames, berry::IWorkbenchWindow::Pointer wnd, bool openEditor = true); - - /** + struct MITK_GUI_COMMON_PLUGIN WorkbenchUtil + { + /** + * Describes the strategies to be used for getting an mitk::IRenderWindowPart instance. + */ + enum IRenderWindowPartStrategy { + + // Do nothing. + NONE = 0x00000000, + // Bring the most recently activated mitk::IRenderWindowPart instance to the front. + BRING_TO_FRONT = 0x00000001, + // Activate an mitk::IRenderWindowPart part (implies bringing it to the front). + ACTIVATE = 0x00000002, + // Create an mitk::IRenderWindowPart if none is alredy opened. + OPEN = 0x00000004 + }; + + Q_DECLARE_FLAGS(IRenderWindowPartStrategies, IRenderWindowPartStrategy) + + /** + * Loads the set of given files into the active data storage of the given Workbench window. + * + * If the window already has an editor open on the active datastorage then that editor + * is activated; otherwise the default editor for the "mitk" extension is activated. + * + * @param fileNames + * A list of file names with absolute path. + * @param wnd + * The Workbench window in which the data will be loaded. + * @param openEditor + * Whether an Editor is to be opened on file loading (for cases there is none). + * + * @see mitk::IOUtil + */ + static void LoadFiles(const QStringList& fileNames, berry::IWorkbenchWindow::Pointer wnd, bool openEditor = true); + /** * Opens an editor on the given object. *

* If the page already has an editor open on the target object then that * editor is brought to front; otherwise, a new editor is opened. If * activate == true the editor will be activated. *

* * @param page * the page in which the editor will be opened * @param input * the editor input * @param editorId * the id of the editor extension to use * @param activate * if true the editor will be activated * @return an open editor or null if an external editor was * opened * @exception PartInitException * if the editor could not be initialized * @see IWorkbenchPage#OpenEditor(IEditorInput::Pointer, std::string, bool) */ - static berry::IEditorPart::Pointer OpenEditor(berry::IWorkbenchPage::Pointer page, - berry::IEditorInput::Pointer input, - const QString& editorId, bool activate = false); - - /** + static berry::IEditorPart::Pointer OpenEditor(berry::IWorkbenchPage::Pointer page, berry::IEditorInput::Pointer input, const QString& editorId, bool activate = false); + /** * Opens an editor on the given file resource. This method will attempt to * resolve the editor based on content-type bindings as well as traditional * name/extension bindings if determineContentType is * true. *

* If the page already has an editor open on the target object then that * editor is brought to front; otherwise, a new editor is opened. If * activate == true the editor will be activated. *

* * @param page * the page in which the editor will be opened * @param input * the editor input * @param activate * if true the editor will be activated * @param determineContentType * attempt to resolve the content type for this file * @return an open editor or null if an external editor was * opened * @exception PartInitException * if the editor could not be initialized * @see IWorkbenchPage#OpenEditor(IEditorInput::Pointer,std::string,bool) */ - static berry::IEditorPart::Pointer OpenEditor(berry::IWorkbenchPage::Pointer page, - mitk::DataStorageEditorInput::Pointer input, - bool activate = false, - bool determineContentType = false); - - /** + static berry::IEditorPart::Pointer OpenEditor(berry::IWorkbenchPage::Pointer page, DataStorageEditorInput::Pointer input, bool activate = false, bool determineContentType = false); + /** * Returns an editor descriptor appropriate for opening a file resource with * the given name. *

* The editor descriptor is determined using a multi-step process. This * method will attempt to infer the content type of the file if * inferContentType is true. *

*
    *
  1. The file is consulted for a persistent property named * IDE.EDITOR_KEY containing the preferred editor id to be * used.
  2. *
  3. The workbench editor registry is consulted to determine if an editor * extension has been registered for the file type. If so, an instance of * the editor extension is opened on the file. See * IEditorRegistry#GetDefaultEditor(std::string).
  4. *
  5. The operating system is consulted to determine if an in-place * component editor is available (e.g. OLE editor on Win32 platforms).
  6. *
  7. The operating system is consulted to determine if an external editor * is available.
  8. *
*

* * @param name * the file name * @param inferContentType * attempt to infer the content type from the file name if this * is true * @return an editor descriptor, appropriate for opening the file * @throws PartInitException * if no editor can be found */ - static berry::IEditorDescriptor::Pointer GetEditorDescriptor( - const QString& name, bool inferContentType = true); - - /** + static berry::IEditorDescriptor::Pointer GetEditorDescriptor(const QString& name, bool inferContentType = true); + /** * Returns the default editor for a given file. This method will attempt to * resolve the editor based on content-type bindings as well as traditional * name/extension bindings if determineContentType is * true. *

* A default editor id may be registered for a specific file using * setDefaultEditor. If the given file has a registered * default editor id the default editor will derived from it. If not, the * default editor is determined by taking the file name for the file and * obtaining the default editor for that name. *

* * @param file * the file * @param determineContentType * determine the content type for the given file * @return the descriptor of the default editor, or null if * not found */ - static berry::IEditorDescriptor::Pointer GetDefaultEditor(const QString& file, - bool determineContentType); - /** - * Set the "DepartmentLogo" preference using a Qt resource path. - * - * This is a convenience method to set the preference for a "deparment" logo which is usually - * shown in render windows in the MITK workbench. - * - * @param logoResource A Qt resource path to the logo, e.g. ":/MyLogo.png". - * @param context The plugin context of the plug-in containing the logo resource. - * @return \c true if the preference was set successfully, \c false otherwise. - */ - static bool SetDepartmentLogoPreference(const QString& logoResource, ctkPluginContext* context); - -}; - + static berry::IEditorDescriptor::Pointer GetDefaultEditor(const QString& file, bool determineContentType); + /** + * @brief Returns the currently active mitk::IRenderWindowPart. + * + * @param page The page in which the editor will be opened. + * @param strategies Strategies for returning a mitk::IRenderWindowPart instance if there + * is currently no active one. + * @return The active mitk::IRenderWindowPart. + */ + static IRenderWindowPart* GetRenderWindowPart(berry::IWorkbenchPage::Pointer page, IRenderWindowPartStrategies strategies); + /** + * @brief Uses 'GetRenderWindowPart' to open the a render window part with a certain strategy: + * Calls 'GetRenderWindowPart' with strategy "ACTIVATE | OPEN" if the bool argument is true. + * Calls 'GetRenderWindowPart' with strategy "BRING_TO_FRONT | OPEN" if the bool argument is false. + * + * @param page The page in which the editor will be opened. + * @param activatedEditor Determine if the render window part should be activated or just brought to front. + * @return The active and opened mitk::IRenderWindowPart. + */ + static IRenderWindowPart* OpenRenderWindowPart(berry::IWorkbenchPage::Pointer page, bool activatedEditor = true); + /** + * Set the "DepartmentLogo" preference using a Qt resource path. + * + * This is a convenience method to set the preference for a "department" logo which is usually + * shown in render windows in the MITK workbench. + * + * @param logoResource A Qt resource path to the logo, e.g. ":/MyLogo.png". + * @param context The plugin context of the plug-in containing the logo resource. + * @return \c true if the preference was set successfully, \c false otherwise. + */ + static bool SetDepartmentLogoPreference(const QString& logoResource, ctkPluginContext* context); + }; } +Q_DECLARE_OPERATORS_FOR_FLAGS(mitk::WorkbenchUtil::IRenderWindowPartStrategies) + #endif // MITKWORKBENCHUTIL_H diff --git a/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.cpp b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.cpp index 33c8bf4dd2..fc92092b26 100644 --- a/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.cpp +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.cpp @@ -1,602 +1,526 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkAbstractView.h" #include "QmitkDataNodeSelectionProvider.h" #include "internal/QmitkCommonActivator.h" #include "internal/QmitkDataNodeItemModel.h" // mitk Includes #include #include #include -#include #include #include // berry Includes #include #include #include #include #include // CTK Includes #include // Qt Includes #include #include #include #include #include class QmitkAbstractViewPrivate { public: QmitkAbstractViewPrivate(QmitkAbstractView* qq) : q(qq) , m_PrefServiceTracker(QmitkCommonActivator::GetContext()) , m_DataStorageServiceTracker(QmitkCommonActivator::GetContext()) , m_Parent(nullptr) , m_DataNodeItemModel(new QmitkDataNodeItemModel) , m_DataNodeSelectionModel(new QItemSelectionModel(m_DataNodeItemModel)) , m_InDataStorageChanged(false) { m_PrefServiceTracker.open(); m_DataStorageServiceTracker.open(); } ~QmitkAbstractViewPrivate() { delete m_DataNodeSelectionModel; delete m_DataNodeItemModel; m_PrefServiceTracker.close(); m_DataStorageServiceTracker.close(); } /** * Called when a DataStorage Add Event was thrown. Sets * m_InDataStorageChanged to true and calls NodeAdded afterwards. * \see m_InDataStorageChanged */ void NodeAddedProxy(const mitk::DataNode* node) { // garantuee no recursions when a new node event is thrown in NodeAdded() if(!m_InDataStorageChanged) { m_InDataStorageChanged = true; q->NodeAdded(node); q->DataStorageModified(); m_InDataStorageChanged = false; } } /** * Called when a DataStorage remove event was thrown. Sets * m_InDataStorageChanged to true and calls NodeRemoved afterwards. * \see m_InDataStorageChanged */ void NodeRemovedProxy(const mitk::DataNode* node) { // garantuee no recursions when a new node event is thrown in NodeAdded() if(!m_InDataStorageChanged) { m_InDataStorageChanged = true; q->NodeRemoved(node); q->DataStorageModified(); m_InDataStorageChanged = false; } } /** * Called when a DataStorage changed event was thrown. Sets * m_InDataStorageChanged to true and calls NodeChanged afterwards. * \see m_InDataStorageChanged */ void NodeChangedProxy(const mitk::DataNode* node) { // garantuee no recursions when a new node event is thrown in NodeAdded() if(!m_InDataStorageChanged) { m_InDataStorageChanged = true; q->NodeChanged(node); q->DataStorageModified(); m_InDataStorageChanged = false; } } /** * reactions to selection events from views */ void BlueBerrySelectionChanged(const berry::IWorkbenchPart::Pointer& sourcepart, const berry::ISelection::ConstPointer& selection) { if(sourcepart.IsNull() || sourcepart.GetPointer() == static_cast(q)) return; if(selection.IsNull()) { q->OnNullSelection(sourcepart); return; } mitk::DataNodeSelection::ConstPointer _DataNodeSelection = selection.Cast(); q->OnSelectionChanged(sourcepart, this->DataNodeSelectionToQList(_DataNodeSelection)); } /** * Converts a mitk::DataNodeSelection to a QList (possibly empty) */ QList DataNodeSelectionToQList(mitk::DataNodeSelection::ConstPointer currentSelection) const; QmitkAbstractView* const q; ctkServiceTracker m_PrefServiceTracker; ctkServiceTracker m_DataStorageServiceTracker; /** * Saves the parent of this view (this is the scrollarea created in CreatePartControl(QWidget*) * \see CreatePartControl(QWidget*) */ QWidget* m_Parent; /** * Holds the current selection (selection made by this View !!!) */ QmitkDataNodeSelectionProvider::Pointer m_SelectionProvider; /** * Holds a helper model for firing selection events. */ QmitkDataNodeItemModel* m_DataNodeItemModel; /** * The selection model for the QmitkDataNodeItemModel; */ QItemSelectionModel* m_DataNodeSelectionModel; /** * object to observe BlueBerry selections */ QScopedPointer m_BlueBerrySelectionListener; /** * Saves if this class is currently working on DataStorage changes. * This is a protector variable to avoid recursive calls on event listener functions. */ bool m_InDataStorageChanged; }; QmitkAbstractView::QmitkAbstractView() : d(new QmitkAbstractViewPrivate(this)) { } void QmitkAbstractView::CreatePartControl(QWidget* parent) { // scrollArea auto scrollArea = new QScrollArea; //QVBoxLayout* scrollAreaLayout = new QVBoxLayout(scrollArea); scrollArea->setFrameShadow(QFrame::Plain); scrollArea->setFrameShape(QFrame::NoFrame); scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); // m_Parent d->m_Parent = new QWidget; //m_Parent->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding)); this->CreateQtPartControl(d->m_Parent); //scrollAreaLayout->addWidget(m_Parent); //scrollArea->setLayout(scrollAreaLayout); // set the widget now scrollArea->setWidgetResizable(true); scrollArea->setWidget(d->m_Parent); // add the scroll area to the real parent (the view tabbar) QWidget* parentQWidget = static_cast(parent); auto parentLayout = new QVBoxLayout(parentQWidget); parentLayout->setMargin(0); parentLayout->setSpacing(0); parentLayout->addWidget(scrollArea); // finally set the layout containing the scroll area to the parent widget (= show it) parentQWidget->setLayout(parentLayout); this->AfterCreateQtPartControl(); } void QmitkAbstractView::AfterCreateQtPartControl() { this->SetSelectionProvider(); // REGISTER DATASTORAGE LISTENER this->GetDataStorage()->AddNodeEvent.AddListener( mitk::MessageDelegate1 ( d.data(), &QmitkAbstractViewPrivate::NodeAddedProxy ) ); this->GetDataStorage()->ChangedNodeEvent.AddListener( mitk::MessageDelegate1 ( d.data(), &QmitkAbstractViewPrivate::NodeChangedProxy ) ); this->GetDataStorage()->RemoveNodeEvent.AddListener( mitk::MessageDelegate1 ( d.data(), &QmitkAbstractViewPrivate::NodeRemovedProxy ) ); // REGISTER PREFERENCES LISTENER berry::IBerryPreferences::Pointer prefs = this->GetPreferences().Cast(); if(prefs.IsNotNull()) prefs->OnChanged.AddListener( berry::MessageDelegate1(this, &QmitkAbstractView::OnPreferencesChanged)); // REGISTER FOR WORKBENCH SELECTION EVENTS d->m_BlueBerrySelectionListener.reset(new berry::NullSelectionChangedAdapter( d.data(), &QmitkAbstractViewPrivate::BlueBerrySelectionChanged)); this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->AddPostSelectionListener(d->m_BlueBerrySelectionListener.data()); // EMULATE INITIAL SELECTION EVENTS // send the current selection berry::IWorkbenchPart::Pointer activePart = this->GetSite()->GetPage()->GetActivePart(); if (activePart.IsNotNull()) { this->OnSelectionChanged(activePart, this->GetCurrentSelection()); } // send preferences changed event this->OnPreferencesChanged(this->GetPreferences().Cast().GetPointer()); } QmitkAbstractView::~QmitkAbstractView() { this->Register(); this->GetDataStorage()->AddNodeEvent.RemoveListener( mitk::MessageDelegate1 ( d.data(), &QmitkAbstractViewPrivate::NodeAddedProxy ) ); this->GetDataStorage()->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1 ( d.data(), &QmitkAbstractViewPrivate::NodeRemovedProxy) ); this->GetDataStorage()->ChangedNodeEvent.RemoveListener( mitk::MessageDelegate1 ( d.data(), &QmitkAbstractViewPrivate::NodeChangedProxy ) ); berry::IBerryPreferences::Pointer prefs = this->GetPreferences().Cast(); if(prefs.IsNotNull()) { prefs->OnChanged.RemoveListener( berry::MessageDelegate1(this, &QmitkAbstractView::OnPreferencesChanged)); // flush the preferences here (disabled, everyone should flush them by themselves at the right moment) // prefs->Flush(); } // REMOVE SELECTION PROVIDER this->GetSite()->SetSelectionProvider(berry::ISelectionProvider::Pointer(nullptr)); berry::ISelectionService* s = GetSite()->GetWorkbenchWindow()->GetSelectionService(); if(s) { s->RemovePostSelectionListener(d->m_BlueBerrySelectionListener.data()); } this->UnRegister(false); } void QmitkAbstractView::SetSelectionProvider() { // REGISTER A SELECTION PROVIDER d->m_SelectionProvider = QmitkDataNodeSelectionProvider::Pointer(new QmitkDataNodeSelectionProvider); d->m_SelectionProvider->SetItemSelectionModel(GetDataNodeSelectionModel()); this->GetSite()->SetSelectionProvider(berry::ISelectionProvider::Pointer(d->m_SelectionProvider)); } QItemSelectionModel *QmitkAbstractView::GetDataNodeSelectionModel() const { return nullptr; } void QmitkAbstractView::OnPreferencesChanged( const berry::IBerryPreferences* ) { } void QmitkAbstractView::DataStorageModified() { } void QmitkAbstractView::DataStorageChanged(mitk::IDataStorageReference::Pointer /*dsRef*/) { } -mitk::IRenderWindowPart* QmitkAbstractView::GetRenderWindowPart( IRenderWindowPartStrategies strategies ) const +mitk::IRenderWindowPart* QmitkAbstractView::GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategies strategies) const { - berry::IWorkbenchPage::Pointer page = this->GetSite()->GetPage(); - - // Return the active editor if it implements mitk::IRenderWindowPart - mitk::IRenderWindowPart* renderPart = - dynamic_cast(page->GetActiveEditor().GetPointer()); - if (renderPart) return renderPart; - - // No suitable active editor found, check visible editors - QList editors = page->GetEditorReferences(); - for (QList::iterator i = editors.begin(); - i != editors.end(); ++i) - { - berry::IWorkbenchPart::Pointer part = (*i)->GetPart(false); - if (page->IsPartVisible(part)) - { - renderPart = dynamic_cast(part.GetPointer()); - if (renderPart) return renderPart; - } - } - - // No suitable visible editor found, check visible views - QList views = page->GetViewReferences(); - for(QList::iterator i = views.begin(); - i != views.end(); ++i) - { - berry::IWorkbenchPart::Pointer part = (*i)->GetPart(false); - if (page->IsPartVisible(part)) - { - renderPart = dynamic_cast(part.GetPointer()); - if (renderPart) return renderPart; - } - } - - // No strategies given - if (strategies == NONE) return nullptr; - - mitk::DataStorageEditorInput::Pointer input(new mitk::DataStorageEditorInput(GetDataStorageReference())); - - bool activate = false; - if(strategies & ACTIVATE) - { - activate = true; - } - - berry::IEditorPart::Pointer editorPart; - - if(strategies & OPEN) - { - // This will create a default editor for the given input. If an editor - // with that input is already open, the editor is brought to the front. - try - { - editorPart = mitk::WorkbenchUtil::OpenEditor(page, input, activate); - } - catch (const berry::PartInitException&) - { - // There is no editor registered which can handle the given input. - } - } - else if (activate || (strategies & BRING_TO_FRONT)) - { - // check if a suitable editor is already opened - editorPart = page->FindEditor(input); - if (editorPart) - { - if (activate) - { - page->Activate(editorPart); - } - else - { - page->BringToTop(editorPart); - } - } - } - - return dynamic_cast(editorPart.GetPointer()); + berry::IWorkbenchPage::Pointer page = GetSite()->GetPage(); + return mitk::WorkbenchUtil::GetRenderWindowPart(page, strategies); } void QmitkAbstractView::RequestRenderWindowUpdate(mitk::RenderingManager::RequestType requestType) { mitk::IRenderWindowPart* renderPart = this->GetRenderWindowPart(); if (renderPart == nullptr) return; if (mitk::IRenderingManager* renderingManager = renderPart->GetRenderingManager()) { renderingManager->RequestUpdateAll(requestType); } else { renderPart->RequestUpdate(requestType); } } void QmitkAbstractView::HandleException( const char* str, QWidget* parent, bool showDialog ) const { //itkGenericOutputMacro( << "Exception caught: " << str ); MITK_ERROR << str; if ( showDialog ) { QMessageBox::critical ( parent, "Exception caught!", str ); } } void QmitkAbstractView::HandleException( std::exception& e, QWidget* parent, bool showDialog ) const { HandleException( e.what(), parent, showDialog ); } void QmitkAbstractView::WaitCursorOn() { QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); } void QmitkAbstractView::BusyCursorOn() { QApplication::setOverrideCursor( QCursor(Qt::BusyCursor) ); } void QmitkAbstractView::WaitCursorOff() { this->RestoreOverrideCursor(); } void QmitkAbstractView::BusyCursorOff() { this->RestoreOverrideCursor(); } void QmitkAbstractView::RestoreOverrideCursor() { QApplication::restoreOverrideCursor(); } berry::IPreferences::Pointer QmitkAbstractView::GetPreferences() const { berry::IPreferencesService* prefService = d->m_PrefServiceTracker.getService(); // const_cast workaround for bad programming: const uncorrectness this->GetViewSite() should be const QString id = "/" + (const_cast(this))->GetViewSite()->GetId(); return prefService ? prefService->GetSystemPreferences()->Node(id): berry::IPreferences::Pointer(nullptr); } mitk::DataStorage::Pointer QmitkAbstractView::GetDataStorage() const { mitk::IDataStorageService* dsService = d->m_DataStorageServiceTracker.getService(); if (dsService != nullptr) { return dsService->GetDataStorage()->GetDataStorage(); } return nullptr; } mitk::IDataStorageReference::Pointer QmitkAbstractView::GetDataStorageReference() const { mitk::IDataStorageService* dsService = d->m_DataStorageServiceTracker.getService(); if (dsService != nullptr) { return dsService->GetDataStorage(); } return mitk::IDataStorageReference::Pointer(nullptr); } QList QmitkAbstractView::GetCurrentSelection() const { berry::ISelection::ConstPointer selection( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection()); mitk::DataNodeSelection::ConstPointer currentSelection = selection.Cast(); return d->DataNodeSelectionToQList(currentSelection); } bool QmitkAbstractView::IsCurrentSelectionValid() const { return this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection(); } QList QmitkAbstractView::GetDataManagerSelection() const { berry::ISelection::ConstPointer selection( this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager")); mitk::DataNodeSelection::ConstPointer currentSelection = selection.Cast(); return d->DataNodeSelectionToQList(currentSelection); } bool QmitkAbstractView::IsDataManagerSelectionValid() const { return this->GetSite()->GetWorkbenchWindow()->GetSelectionService()->GetSelection("org.mitk.views.datamanager"); } void QmitkAbstractView::SetDataManagerSelection(const berry::ISelection::ConstPointer &selection, QItemSelectionModel::SelectionFlags flags) const { berry::IViewPart::Pointer datamanagerView = this->GetSite()->GetWorkbenchWindow()->GetActivePage()->FindView("org.mitk.views.datamanager"); if (datamanagerView.IsNull()) return; datamanagerView->GetSite()->GetSelectionProvider().Cast()->SetSelection(selection, flags); } void QmitkAbstractView::SynchronizeDataManagerSelection() const { berry::ISelection::ConstPointer currentSelection = this->GetSite()->GetSelectionProvider()->GetSelection(); if (currentSelection.IsNull()) return; SetDataManagerSelection(currentSelection); } void QmitkAbstractView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& /*nodes*/) { } void QmitkAbstractView::OnNullSelection(berry::IWorkbenchPart::Pointer /*part*/) { } QList QmitkAbstractViewPrivate::DataNodeSelectionToQList(mitk::DataNodeSelection::ConstPointer currentSelection) const { if (currentSelection.IsNull()) return QList(); return QList::fromStdList(currentSelection->GetSelectedDataNodes()); } void QmitkAbstractView::NodeAdded( const mitk::DataNode* /*node*/ ) { } void QmitkAbstractView::NodeRemoved( const mitk::DataNode* /*node*/ ) { } void QmitkAbstractView::NodeChanged( const mitk::DataNode* /*node*/ ) { } void QmitkAbstractView::FireNodeSelected( mitk::DataNode::Pointer node ) { QList nodes; nodes << node; this->FireNodesSelected(nodes); } void QmitkAbstractView::FireNodesSelected( const QList& nodes ) { // if this is the first call to FireNodesSelected and the selection provider has no QItemSelectiomMode // yet, set our helper model if (d->m_SelectionProvider->GetItemSelectionModel() == nullptr) { d->m_SelectionProvider->SetItemSelectionModel(d->m_DataNodeSelectionModel); } else if (d->m_SelectionProvider->GetItemSelectionModel() != d->m_DataNodeSelectionModel) { MITK_WARN << "A custom data node selection model has been set. Ignoring call to FireNodesSelected()."; return; } if (nodes.empty()) { d->m_DataNodeSelectionModel->clearSelection(); d->m_DataNodeItemModel->clear(); } else { // The helper data node model is just used for sending selection events. // We add the to be selected nodes and set the selection range to everything. d->m_DataNodeItemModel->clear(); foreach(mitk::DataNode::Pointer node, nodes) { d->m_DataNodeItemModel->AddDataNode(node); } d->m_DataNodeSelectionModel->select(QItemSelection(d->m_DataNodeItemModel->index(0,0), d->m_DataNodeItemModel->index(nodes.size()-1, 0)), QItemSelectionModel::ClearAndSelect); } } diff --git a/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.h b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.h index d92f6560ad..75fff11011 100644 --- a/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.h +++ b/Plugins/org.mitk.gui.qt.common/src/QmitkAbstractView.h @@ -1,384 +1,366 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKABSTRACTVIEW_H_ #define QMITKABSTRACTVIEW_H_ //# blueberry stuff #include #include #include #include //# mitk stuff #include #include "mitkDataNodeSelection.h" #include "mitkIRenderWindowPart.h" +#include + #include #include #include #include namespace mitk { class DataNode; } namespace berry { struct IBerryPreferences; } class QmitkAbstractViewPrivate; class QmitkAbstractViewSelectionProvider; /** * \ingroup org_mitk_gui_qt_common * * \brief A convenient base class for MITK related BlueBerry Views. * * QmitkAbstractView provides several convenience methods that ease the introduction of a new view: * *
    *
  1. Access to the DataStorage (~ the shared data repository) *
  2. Access to the active IRenderWindowPart *
  3. Access to and update notification for the view's preferences *
  4. Access to and update notification for the current DataNode selection / to DataNode selection events send through the SelectionService *
  5. Access to and update notification for DataNode events (added/removed/modified) *
  6. Methods to send DataNode selections through the SelectionService *
  7. Some minor important convenience methods (like changing the mouse cursor/exception handling) *
* * Usually all MITK Views inherit from QmitkAbstractView to achieve a consistent Workbench behavior. * * When inheriting from QmitkAbstractView, you must implement the following methods: *
    *
  • void CreateQtPartControl(QWidget* parent) *
  • void SetFocus() *
* * You may reimplement the following private virtual methods to customize your View's behavior: *
    *
  • void SetSelectionProvider() *
  • QItemSelectionModel* GetDataNodeSelectionModel() const *
* * You may reimplement the following private virtual methods to be notified about certain changes: *
    *
  • void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList &nodes) *
  • void OnNullSelection(berry::IWorkbenchPart::Pointer part) *
  • void OnPreferencesChanged(const berry::IBerryPreferences*) *
  • void NodeAdded(const mitk::DataNode* node) *
  • void NodeChanged(const mitk::DataNode* node) *
  • void NodeRemoved(const mitk::DataNode* node) *
  • void DataStorageModified() *
  • void DataStorageChanged(mitk::IDataStorageReference::Pointer dsRef) *
* * \see mitk::ILifecycleAwarePart * \see mitk::IZombieViewPart * \see mitk::IRenderWindowPartListener */ class MITK_QT_COMMON QmitkAbstractView : public berry::QtViewPart { public: - /** - * Describes the strategies to be used for getting a mitk::IRenderWindowPart - * instance. - */ - enum IRenderWindowPartStrategy { - - /** Do nothing. */ - NONE = 0x00000000, - /** Bring the most recently activated mitk::IRenderWindowPart instance to the front. */ - BRING_TO_FRONT = 0x00000001, - /** Activate a mitk::IRenderWindowPart part (implies bringing it to the front). */ - ACTIVATE = 0x00000002, - /** Create a mitk::IRenderWindowPart if none is alredy opened. */ - OPEN = 0x00000004 - }; - - Q_DECLARE_FLAGS(IRenderWindowPartStrategies, IRenderWindowPartStrategy) - /** * Creates smartpointer typedefs */ berryObjectMacro(QmitkAbstractView); /** * Nothing to do in the standard ctor. Initiliaze your GUI in CreateQtPartControl(QWidget*) * \see berry::QtViewPart::CreateQtPartControl(QWidget*) */ QmitkAbstractView(); /** * Disconnects all standard event listeners */ ~QmitkAbstractView() override; protected: /** * Informs other parts of the workbench that node is selected via the blueberry selection service. * * \note This method should not be used if you have set your own selection provider via * SetSelectionProvider() or your own QItemSelectionModel via GetDataNodeSelectionModel(). */ void FireNodeSelected(mitk::DataNode::Pointer node); /** * Informs other parts of the workbench that the nodes are selected via the blueberry selection service. * * \note This method should not be used if you have set your own selection provider via * SetSelectionProvider() or your own QItemSelectionModel via GetDataNodeSelectionModel(). */ virtual void FireNodesSelected(const QList& nodes); /** * \return The selection of the currently active part of the workbench or an empty list * if there is no selection or if it is empty. * * \see IsCurrentSelectionValid */ QList GetCurrentSelection() const; /** * Queries the state of the current selection. * * \return If the current selection is nullptr, this method returns * false and true otherwise. */ bool IsCurrentSelectionValid() const; /** * Returns the current selection made in the datamanager bundle or an empty list * if there is no selection or if it is empty. * * \see IsDataManagerSelectionValid */ QList GetDataManagerSelection() const; /** * Queries the state of the current selection of the data manager view. * * \return If the current data manager selection is nullptr, this method returns * false and true otherwise. */ bool IsDataManagerSelectionValid() const; /** * Sets the selection of the data manager view if available. * * \param selection The new selection for the data manager. * \param flags The Qt selection flags for controlling the way how the selection is updated. */ void SetDataManagerSelection(const berry::ISelection::ConstPointer& selection, QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::ClearAndSelect) const; /** * Takes the current selection and sets it on the data manager. Only matching nodes in the * data manager view will be selected. */ void SynchronizeDataManagerSelection() const; /** * Returns the Preferences object for this View. * Important: When refering to this preferences, e.g. in a PreferencePage: The ID * for this preferences object is "/", e.g. "/org.mitk.views.datamanager" */ berry::IPreferences::Pointer GetPreferences() const; /** * Returns a reference to the currently active DataStorage. */ mitk::IDataStorageReference::Pointer GetDataStorageReference() const; /** * Returns the currently active DataStorage. */ mitk::DataStorage::Pointer GetDataStorage() const; /** * Returns the currently active mitk::IRenderWindowPart. * * \param strategies Strategies for returning a mitk::IRenderWindowPart instance if there * is currently no active one. * \return The active mitk::IRenderWindowPart. */ - mitk::IRenderWindowPart* GetRenderWindowPart(IRenderWindowPartStrategies strategies = NONE) const; + mitk::IRenderWindowPart* GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategies strategies = mitk::WorkbenchUtil::NONE) const; /** * Request an update of all render windows of the currently active IRenderWindowPart. * * \param requestType Specifies the type of render windows for which an update * will be requested. */ void RequestRenderWindowUpdate(mitk::RenderingManager::RequestType requestType = mitk::RenderingManager::REQUEST_UPDATE_ALL); /** * Outputs an error message to the console and displays a message box containing * the exception description. * \param e the exception which should be handled * \param showDialog controls, whether additionally a message box should be * displayed to inform the user that something went wrong */ void HandleException( std::exception& e, QWidget* parent = nullptr, bool showDialog = true ) const; /** * Calls HandleException ( std::exception&, QWidget*, bool ) internally * \see HandleException ( std::exception&, QWidget*, bool ) */ void HandleException( const char* str, QWidget* parent = nullptr, bool showDialog = true ) const; /** * Convenient method to set and reset a wait cursor ("hourglass") */ void WaitCursorOn(); /** * Convenient method to restore the standard cursor */ void WaitCursorOff(); /** * Convenient method to set and reset a busy cursor */ void BusyCursorOn(); /** * Convenient method to restore the standard cursor */ void BusyCursorOff(); /** * Convenient method to restore the standard cursor */ void RestoreOverrideCursor(); private: /** * Reimplement this method to set a custom selection provider. This method is * called once after CreateQtPartControl(). * * The default implementation registers a QmitkDataNodeSelectionProvider with * a QItemSelectionModel returned by GetDataNodeSelectionModel(). */ virtual void SetSelectionProvider(); /** * Reimplement this method to supply a custom Qt selection model. The custom * model will be used with the default selection provider QmitkDataNodeSelectionProvider * to inform the MITK Workbench about selection changes. * * If you reimplement this method, the methods FireNodeSelected() and FireNodesSelected() * will have no effect. Use your custom selection model to notify the MITK Workbench * about selection changes. * * The Qt item model used with the custom selection model must return mitk::DataNode::Pointer * objects for model indexes when the role is QmitkDataNodeRole. */ virtual QItemSelectionModel* GetDataNodeSelectionModel() const; /** * Called when the selection in the workbench changed. * May be reimplemented by deriving classes. * * \param part The source part responsible for the selection change. * \param nodes A list of selected nodes. * * \see OnNullSelection */ virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList &nodes); /** * Called when a nullptr selection occurs. * * \param part The source part responsible for the selection change. */ virtual void OnNullSelection(berry::IWorkbenchPart::Pointer part); /** * Called when the preferences object of this view changed. * May be reimplemented by deriving classes. * * \see GetPreferences() */ virtual void OnPreferencesChanged(const berry::IBerryPreferences*); /** * Called when a DataStorage Add event was thrown. May be reimplemented * by deriving classes. */ virtual void NodeAdded(const mitk::DataNode* node); /** * Called when a DataStorage Changed event was thrown. May be reimplemented * by deriving classes. */ virtual void NodeChanged(const mitk::DataNode* node); /** * Called when a DataStorage Remove event was thrown. May be reimplemented * by deriving classes. */ virtual void NodeRemoved(const mitk::DataNode* node); /** * Called when a DataStorage add *or* remove *or* change event from the currently active * data storage is thrown. * * May be reimplemented by deriving classes. */ virtual void DataStorageModified(); /** * Called when the currently active DataStorage changed. * May be reimplemented by deriving classes. * * \param dsRef A reference to the new active DataStorage. */ virtual void DataStorageChanged(mitk::IDataStorageReference::Pointer dsRef); /** * Creates a scroll area for this view and calls CreateQtPartControl then */ void CreatePartControl(QWidget* parent) override; /** * Called immediately after CreateQtPartControl(). * Here standard event listeners for a QmitkAbstractView are registered */ void AfterCreateQtPartControl(); private: friend class QmitkAbstractViewPrivate; friend class QmitkViewCoordinator; Q_DISABLE_COPY(QmitkAbstractView) const QScopedPointer d; }; -Q_DECLARE_OPERATORS_FOR_FLAGS(QmitkAbstractView::IRenderWindowPartStrategies) - #endif /*QMITKABSTRACTVIEW_H_*/ diff --git a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp index 499f2adfe5..94f448a606 100644 --- a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp +++ b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.cpp @@ -1,308 +1,296 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkDataManagerView.h" // mitk gui qt datamanager #include "src/internal/QmitkNodeTableViewKeyFilter.h" #include "src/internal/QmitkInfoDialog.h" #include "src/internal/QmitkDataManagerItemDelegate.h" // mitk core #include #include #include #include #include #include #include #include #include #include #include #include #include #include // mitk core services plugin #include #include // qt widgets module #include #include #include #include #include // beery plugins #include #include #include #include #include #include #include #include #include // mitk gui qt application plugin #include // qt #include #include #include #include #include #include #include #include #include #include // mitk gui common plugin #include #include #include // mitk gui qt common plugin #include const QString QmitkDataManagerView::VIEW_ID = "org.mitk.views.datamanager"; QmitkDataManagerView::QmitkDataManagerView() : m_GlobalReinitOnNodeDelete(true) , m_GlobalReinitOnNodeVisibilityChanged(false) , m_ItemDelegate(nullptr) { } QmitkDataManagerView::~QmitkDataManagerView() { // nothing here } void QmitkDataManagerView::CreateQtPartControl(QWidget* parent) { m_CurrentRowCount = 0; m_Parent = parent; //# Preferences berry::IPreferencesService* prefService = berry::Platform::GetPreferencesService(); berry::IBerryPreferences::Pointer prefs = (prefService->GetSystemPreferences()->Node(VIEW_ID)).Cast(); assert(prefs); prefs->OnChanged.AddListener(berry::MessageDelegate1(this, &QmitkDataManagerView::OnPreferencesChanged)); //# GUI m_NodeTreeModel = new QmitkDataStorageTreeModel(GetDataStorage(), prefs->GetBool("Place new nodes on top", true)); m_NodeTreeModel->setParent(parent); m_NodeTreeModel->SetAllowHierarchyChange(prefs->GetBool("Allow changing of parent node", false)); m_SurfaceDecimation = prefs->GetBool("Use surface decimation", false); // Prepare filters m_HelperObjectFilterPredicate = mitk::NodePredicateOr::New( mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true)), mitk::NodePredicateProperty::New("hidden object", mitk::BoolProperty::New(true))); m_NodeWithNoDataFilterPredicate = mitk::NodePredicateData::New(nullptr); m_FilterModel = new QmitkDataStorageFilterProxyModel(); m_FilterModel->setSourceModel(m_NodeTreeModel); m_FilterModel->AddFilterPredicate(m_HelperObjectFilterPredicate); m_FilterModel->AddFilterPredicate(m_NodeWithNoDataFilterPredicate); //# Tree View (experimental) m_NodeTreeView = new QTreeView; m_NodeTreeView->setHeaderHidden(true); m_NodeTreeView->setSelectionMode(QAbstractItemView::ExtendedSelection); m_NodeTreeView->setSelectionBehavior(QAbstractItemView::SelectRows); m_NodeTreeView->setAlternatingRowColors(true); m_NodeTreeView->setDragEnabled(true); m_NodeTreeView->setDropIndicatorShown(true); m_NodeTreeView->setAcceptDrops(true); m_NodeTreeView->setContextMenuPolicy(Qt::CustomContextMenu); m_NodeTreeView->setModel(m_FilterModel); m_NodeTreeView->setTextElideMode(Qt::ElideMiddle); m_NodeTreeView->installEventFilter(new QmitkNodeTableViewKeyFilter(this)); m_ItemDelegate = new QmitkDataManagerItemDelegate(m_NodeTreeView); m_NodeTreeView->setItemDelegate(m_ItemDelegate); connect(m_NodeTreeModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(NodeTreeViewRowsInserted(const QModelIndex&, int, int))); connect(m_NodeTreeModel, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), this, SLOT(NodeTreeViewRowsRemoved(const QModelIndex&, int, int))); connect(m_NodeTreeView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(NodeSelectionChanged(const QItemSelection &, const QItemSelection &))); connect(m_NodeTreeModel, &QmitkDataStorageTreeModel::nodeVisibilityChanged, this, &QmitkDataManagerView::OnNodeVisibilityChanged); // data node context menu and menu actions m_DataNodeContextMenu = new QmitkDataNodeContextMenu(GetSite(), m_NodeTreeView); m_DataNodeContextMenu->SetDataStorage(GetDataStorage()); m_DataNodeContextMenu->SetSurfaceDecimation(m_SurfaceDecimation); connect(m_NodeTreeView, SIGNAL(customContextMenuRequested(const QPoint&)), m_DataNodeContextMenu, SLOT(OnContextMenuRequested(const QPoint&))); berry::IEditorRegistry* editorRegistry = berry::PlatformUI::GetWorkbench()->GetEditorRegistry(); QList editors = editorRegistry->GetEditors("*.mitk"); if (editors.size() > 1) { m_ShowInMapper = new QSignalMapper(this); foreach(berry::IEditorDescriptor::Pointer descriptor, editors) { QAction* action = new QAction(descriptor->GetLabel(), this); m_ShowInActions << action; m_ShowInMapper->connect(action, SIGNAL(triggered()), m_ShowInMapper, SLOT(map())); m_ShowInMapper->setMapping(action, descriptor->GetId()); } connect(m_ShowInMapper, SIGNAL(mapped(QString)), this, SLOT(ShowIn(QString))); } QGridLayout* dndFrameWidgetLayout = new QGridLayout; dndFrameWidgetLayout->addWidget(m_NodeTreeView, 0, 0); dndFrameWidgetLayout->setContentsMargins(0, 0, 0, 0); m_DnDFrameWidget = new QmitkDnDFrameWidget(m_Parent); m_DnDFrameWidget->setLayout(dndFrameWidgetLayout); QVBoxLayout* layout = new QVBoxLayout(parent); layout->addWidget(m_DnDFrameWidget); layout->setContentsMargins(0, 0, 0, 0); m_Parent->setLayout(layout); } void QmitkDataManagerView::SetFocus() { } void QmitkDataManagerView::NodeChanged(const mitk::DataNode* /*node*/) { // m_FilterModel->invalidate(); // fix as proposed by R. Khlebnikov in the mitk-users mail from 02.09.2014 QMetaObject::invokeMethod(m_FilterModel, "invalidate", Qt::QueuedConnection); } void QmitkDataManagerView::OnPreferencesChanged(const berry::IBerryPreferences* prefs) { if (m_NodeTreeModel->GetPlaceNewNodesOnTopFlag() != prefs->GetBool("Place new nodes on top", true)) { m_NodeTreeModel->SetPlaceNewNodesOnTop(!m_NodeTreeModel->GetPlaceNewNodesOnTopFlag()); } bool hideHelperObjects = !prefs->GetBool("Show helper objects", false); if (m_FilterModel->HasFilterPredicate(m_HelperObjectFilterPredicate) != hideHelperObjects) { if (hideHelperObjects) { m_FilterModel->AddFilterPredicate(m_HelperObjectFilterPredicate); } else { m_FilterModel->RemoveFilterPredicate(m_HelperObjectFilterPredicate); } } bool hideNodesWithNoData = !prefs->GetBool("Show nodes containing no data", false); if (m_FilterModel->HasFilterPredicate(m_NodeWithNoDataFilterPredicate) != hideNodesWithNoData) { if (hideNodesWithNoData) { m_FilterModel->AddFilterPredicate(m_NodeWithNoDataFilterPredicate); } else { m_FilterModel->RemoveFilterPredicate(m_NodeWithNoDataFilterPredicate); } } m_GlobalReinitOnNodeDelete = prefs->GetBool("Call global reinit if node is deleted", true); m_GlobalReinitOnNodeVisibilityChanged = prefs->GetBool("Call global reinit if node visibility is changed", false); m_NodeTreeView->expandAll(); m_SurfaceDecimation = prefs->GetBool("Use surface decimation", false); m_DataNodeContextMenu->SetSurfaceDecimation(m_SurfaceDecimation); m_NodeTreeModel->SetAllowHierarchyChange(prefs->GetBool("Allow changing of parent node", false)); GlobalReinitAction::Run(GetSite(), GetDataStorage()); } ////////////////////////////////////////////////////////////////////////// // Node tree modification ////////////////////////////////////////////////////////////////////////// void QmitkDataManagerView::NodeTreeViewRowsInserted(const QModelIndex& parent, int /*start*/, int /*end*/) { QModelIndex viewIndex = m_FilterModel->mapFromSource(parent); m_NodeTreeView->setExpanded(viewIndex, true); // a new row was inserted if (m_CurrentRowCount == 0 && m_NodeTreeModel->rowCount() == 1) { - OpenRenderWindowPart(); + mitk::WorkbenchUtil::OpenRenderWindowPart(GetSite()->GetPage()); m_CurrentRowCount = m_NodeTreeModel->rowCount(); } } void QmitkDataManagerView::NodeTreeViewRowsRemoved(const QModelIndex& /*parent*/, int /*start*/, int /*end*/) { m_CurrentRowCount = m_NodeTreeModel->rowCount(); } void QmitkDataManagerView::NodeSelectionChanged(const QItemSelection& /*selected*/, const QItemSelection& /*deselected*/) { auto selectedNodes = GetCurrentSelection(); auto nodeSet = m_NodeTreeModel->GetNodeSet(); for (auto node : nodeSet) { if (node.IsNotNull()) { node->SetSelected(selectedNodes.contains(node)); } } } void QmitkDataManagerView::OnNodeVisibilityChanged() { if (m_GlobalReinitOnNodeVisibilityChanged) { GlobalReinitAction::Run(GetSite(), GetDataStorage()); } else { mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkDataManagerView::ShowIn(const QString& editorId) { berry::IWorkbenchPage::Pointer page = GetSite()->GetPage(); berry::IEditorInput::Pointer input(new mitk::DataStorageEditorInput(GetDataStorageReference())); page->OpenEditor(input, editorId, false, berry::IWorkbenchPage::MATCH_ID); } QItemSelectionModel* QmitkDataManagerView::GetDataNodeSelectionModel() const { return m_NodeTreeView->selectionModel(); } - -mitk::IRenderWindowPart* QmitkDataManagerView::OpenRenderWindowPart(bool activatedEditor/* = true*/) -{ - if (activatedEditor) - { - return GetRenderWindowPart(QmitkAbstractView::ACTIVATE | QmitkAbstractView::OPEN); - } - else - { - return GetRenderWindowPart(QmitkAbstractView::BRING_TO_FRONT | QmitkAbstractView::OPEN); - } -} \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.h b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.h index fc6920db54..a60490e122 100644 --- a/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.h +++ b/Plugins/org.mitk.gui.qt.datamanager/src/QmitkDataManagerView.h @@ -1,149 +1,146 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKDATAMANAGERVIEW_H_ #define QMITKDATAMANAGERVIEW_H_ #include // mitk core #include // berry plugin #include // mitk gui qt common plugin #include // mitk gui qt application #include // qt #include // forward declarations class QAction; class QModelIndex; class QTreeView; class QSignalMapper; class QmitkDnDFrameWidget; class QmitkDataStorageTreeModel; class QmitkDataManagerItemDelegate; class QmitkDataStorageFilterProxyModel; /** * @brief A view that shows all data nodes of the data storage in a qt tree view. * */ class MITK_QT_DATAMANAGER QmitkDataManagerView : public QmitkAbstractView { Q_OBJECT public: static const QString VIEW_ID; // = "org.mitk.views.datamanager" QmitkDataManagerView(); ~QmitkDataManagerView() override; public Q_SLOTS: // invoked when the berry preferences were changed void OnPreferencesChanged(const berry::IBerryPreferences* prefs) override; ////////////////////////////////////////////////////////////////////////// // Slots for Qt node tree signals ////////////////////////////////////////////////////////////////////////// /// When rows are inserted auto expand them void NodeTreeViewRowsInserted(const QModelIndex& parent, int start, int end); /// will setup m_CurrentRowCount void NodeTreeViewRowsRemoved(const QModelIndex& parent, int start, int end); /// Whenever the selection changes set the "selected" property respectively void NodeSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); void OnNodeVisibilityChanged(); /// Opens the editor with the given id using the current data storage void ShowIn(const QString& editorId); protected: void CreateQtPartControl(QWidget* parent) override; void SetFocus() override; /// /// React to node changes. Overridden from QmitkAbstractView. /// void NodeChanged(const mitk::DataNode* node) override; protected: QWidget* m_Parent; QmitkDnDFrameWidget* m_DnDFrameWidget; /// /// \brief A plain widget as the base pane. /// QmitkDataStorageTreeModel* m_NodeTreeModel; QmitkDataStorageFilterProxyModel* m_FilterModel; mitk::NodePredicateBase::Pointer m_HelperObjectFilterPredicate; mitk::NodePredicateBase::Pointer m_NodeWithNoDataFilterPredicate; /// /// Holds the preferences for the data manager. /// berry::IBerryPreferences::Pointer m_DataManagerPreferencesNode; /// /// \brief The Table view to show the selected nodes. /// QTreeView* m_NodeTreeView; /// /// \brief The context menu that shows up when right clicking on a node. /// QmitkDataNodeContextMenu* m_DataNodeContextMenu; /// /// \brief flag indicating whether a surface created from a selected decimation is decimated with vtkQuadricDecimation or not /// bool m_SurfaceDecimation; /// Maps "Show in" actions to editor ids QSignalMapper* m_ShowInMapper; /// A list of "Show in" actions QList m_ShowInActions; /// saves the current amount of rows shown in the data manager size_t m_CurrentRowCount; /// if true, GlobalReinit() is called if a node is deleted bool m_GlobalReinitOnNodeDelete; bool m_GlobalReinitOnNodeVisibilityChanged; QmitkDataManagerItemDelegate* m_ItemDelegate; private: QItemSelectionModel* GetDataNodeSelectionModel() const override; - /// Reopen multi widget editor if it has been closed - mitk::IRenderWindowPart *OpenRenderWindowPart(bool activatedEditor = true); - }; #endif // QMITKDATAMANAGERVIEW_H_ diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp index 38476db4cc..e3a88a5d86 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp @@ -1,1127 +1,1125 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include "mitkProperties.h" #include "mitkSegTool2D.h" #include "mitkStatusBar.h" #include "QmitkNewSegmentationDialog.h" #include #include #include #include "QmitkSegmentationView.h" #include #include "mitkVtkResliceInterpolationProperty.h" #include "mitkApplicationCursor.h" #include "mitkSegmentationObjectFactory.h" #include "mitkPluginActivator.h" #include "mitkCameraController.h" #include "mitkLabelSetImage.h" #include #include "usModuleResource.h" #include "usModuleResourceStream.h" //micro service to get the ToolManager instance #include "mitkToolManagerProvider.h" +#include + const std::string QmitkSegmentationView::VIEW_ID = "org.mitk.views.segmentation"; QmitkSegmentationView::QmitkSegmentationView() : m_Parent(nullptr) , m_Controls(nullptr) , m_RenderWindowPart(nullptr) , m_MouseCursorSet(false) , m_DataSelectionChanged(false) , m_AutoSelectionEnabled(false) { mitk::TNodePredicateDataType::Pointer isImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("DiffusionImage"); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isOdf = mitk::NodePredicateDataType::New("OdfImage"); auto isSegment = mitk::NodePredicateDataType::New("Segment"); mitk::NodePredicateOr::Pointer validImages = mitk::NodePredicateOr::New(); validImages->AddPredicate(mitk::NodePredicateAnd::New(isImage, mitk::NodePredicateNot::New(isSegment))); validImages->AddPredicate(isDwi); validImages->AddPredicate(isDti); validImages->AddPredicate(isOdf); mitk::NodePredicateNot::Pointer isNotAHelperObject = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true))); m_IsOfTypeImagePredicate = mitk::NodePredicateAnd::New(validImages, isNotAHelperObject); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateNot::Pointer isNotBinaryPredicate = mitk::NodePredicateNot::New(isBinaryPredicate); mitk::NodePredicateAnd::Pointer isABinaryImagePredicate = mitk::NodePredicateAnd::New(m_IsOfTypeImagePredicate, isBinaryPredicate); mitk::NodePredicateAnd::Pointer isNotABinaryImagePredicate = mitk::NodePredicateAnd::New(m_IsOfTypeImagePredicate, isNotBinaryPredicate); m_IsASegmentationImagePredicate = mitk::NodePredicateOr::New(isABinaryImagePredicate, mitk::TNodePredicateDataType::New()); m_IsAPatientImagePredicate = mitk::NodePredicateAnd::New(isNotABinaryImagePredicate, mitk::NodePredicateNot::New(mitk::TNodePredicateDataType::New())); } QmitkSegmentationView::~QmitkSegmentationView() { if (m_Controls) { SetToolSelectionBoxesEnabled(false); // deactivate all tools mitk::ToolManagerProvider::GetInstance()->GetToolManager()->ActivateTool(-1); // removing all observers for (NodeTagMapType::iterator dataIter = m_WorkingDataObserverTags.begin(); dataIter != m_WorkingDataObserverTags.end(); ++dataIter) { (*dataIter).first->GetProperty("visible")->RemoveObserver((*dataIter).second); } m_WorkingDataObserverTags.clear(); for (NodeTagMapType::iterator dataIter = m_BinaryPropertyObserverTags.begin(); dataIter != m_BinaryPropertyObserverTags.end(); ++dataIter) { (*dataIter).first->GetProperty("binary")->RemoveObserver((*dataIter).second); } m_BinaryPropertyObserverTags.clear(); mitk::RenderingManager::GetInstance()->RemoveObserver(m_RenderingManagerObserverTag); ctkPluginContext* context = mitk::PluginActivator::getContext(); ctkServiceReference ppmRef = context->getServiceReference(); mitk::PlanePositionManagerService* service = context->getService(ppmRef); service->RemoveAllPlanePositions(); context->ungetService(ppmRef); SetToolManagerSelection(0, 0); } delete m_Controls; } void QmitkSegmentationView::NewNodesGenerated() { MITK_WARN << "Use of deprecated function: NewNodesGenerated!! This function is empty and will be removed in the next time!"; } void QmitkSegmentationView::NewNodeObjectsGenerated(mitk::ToolManager::DataVectorType* nodes) { if (!nodes) return; mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); if (!toolManager) return; for (mitk::ToolManager::DataVectorType::iterator iter = nodes->begin(); iter != nodes->end(); ++iter) { this->FireNodeSelected( *iter ); // only last iteration meaningful, multiple generated objects are not taken into account here } } void QmitkSegmentationView::Visible() { } void QmitkSegmentationView::Hidden() { } void QmitkSegmentationView::Activated() { } void QmitkSegmentationView::Deactivated() { } void QmitkSegmentationView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) { if (m_RenderWindowPart != renderWindowPart) { m_RenderWindowPart = renderWindowPart; } if (m_Parent) { m_Parent->setEnabled(true); } // tell the interpolation about tool manager, data storage and render window part if (m_Controls) { mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); m_Controls->m_SlicesInterpolator->SetDataStorage(this->GetDataStorage()); QList controllers; controllers.push_back(renderWindowPart->GetQmitkRenderWindow("axial")->GetSliceNavigationController()); controllers.push_back(renderWindowPart->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()); controllers.push_back(renderWindowPart->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()); m_Controls->m_SlicesInterpolator->Initialize(toolManager, controllers); } } void QmitkSegmentationView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* /*renderWindowPart*/) { m_RenderWindowPart = nullptr; if (m_Parent) { m_Parent->setEnabled(false); } } void QmitkSegmentationView::OnPreferencesChanged(const berry::IBerryPreferences* prefs) { if (m_Controls != nullptr) { bool slimView = prefs->GetBool("slim view", false); m_Controls->m_ManualToolSelectionBox2D->SetShowNames(!slimView); m_Controls->m_ManualToolSelectionBox3D->SetShowNames(!slimView); m_Controls->btnNewSegmentation->setToolButtonStyle(slimView ? Qt::ToolButtonIconOnly : Qt::ToolButtonTextOnly); } m_AutoSelectionEnabled = prefs->GetBool("auto selection", false); this->ForceDisplayPreferencesUponAllImages(); } void QmitkSegmentationView::CreateNewSegmentation() { mitk::DataNode::Pointer node = mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetReferenceData(0); if (node.IsNotNull()) { mitk::Image::Pointer image = dynamic_cast(node->GetData()); if (image.IsNotNull()) { if (image->GetDimension() > 1) { // ask about the name and organ type of the new segmentation QmitkNewSegmentationDialog* dialog = new QmitkNewSegmentationDialog(m_Parent); // needs a QWidget as parent, "this" is not QWidget QStringList organColors = mitk::OrganNamesHandling::GetDefaultOrganColorString();; dialog->SetSuggestionList(organColors); int dialogReturnValue = dialog->exec(); if (dialogReturnValue == QDialog::Rejected) { // user clicked cancel or pressed Esc or something similar return; } // ask the user about an organ type and name, add this information to the image's (!) propertylist // create a new image of the same dimensions and smallest possible pixel type mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); mitk::Tool* firstTool = toolManager->GetToolById(0); if (firstTool) { try { std::string newNodeName = dialog->GetSegmentationName().toStdString(); if (newNodeName.empty()) { newNodeName = "no_name"; } mitk::DataNode::Pointer emptySegmentation = firstTool->CreateEmptySegmentationNode(image, newNodeName, dialog->GetColor()); // initialize showVolume to false to prevent recalculating the volume while working on the segmentation emptySegmentation->SetProperty("showVolume", mitk::BoolProperty::New(false)); if (!emptySegmentation) { return; // could be aborted by user } mitk::OrganNamesHandling::UpdateOrganList(organColors, dialog->GetSegmentationName(), dialog->GetColor()); // escape ';' here (replace by '\;'), see longer comment above QString stringForStorage = organColors.replaceInStrings(";", "\\;").join(";"); MITK_DEBUG << "Will store: " << stringForStorage; this->GetPreferences()->Put("Organ-Color-List", stringForStorage); this->GetPreferences()->Flush(); if (mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetWorkingData(0)) { mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetWorkingData(0)->SetSelected(false); } emptySegmentation->SetSelected(true); this->GetDataStorage()->Add(emptySegmentation, node); // add as a child, because the segmentation "derives" from the original this->FireNodeSelected(emptySegmentation); this->OnSelectionChanged(emptySegmentation); m_Controls->segImageSelector->SetSelectedNode(emptySegmentation); mitk::RenderingManager::GetInstance()->InitializeViews(emptySegmentation->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); } catch (std::bad_alloc) { QMessageBox::warning(nullptr, tr("Create new segmentation"), tr("Could not allocate memory for new segmentation")); } } } else { QMessageBox::information(nullptr, tr("Segmentation"), tr("Segmentation is currently not supported for 2D images")); } } } else { MITK_ERROR << "'Create new segmentation' button should never be clickable unless a patient image is selected..."; } } void QmitkSegmentationView::OnVisiblePropertyChanged() { mitk::DataNode* selectedNode = m_Controls->segImageSelector->GetSelectedNode(); if ( !selectedNode ) { this->SetToolSelectionBoxesEnabled(false); return; } mitk::IRenderWindowPart* renderWindowPart = this->GetRenderWindowPart(); bool selectedNodeIsVisible = renderWindowPart && selectedNode->IsVisible(renderWindowPart->GetQmitkRenderWindow("axial")->GetRenderer()); if (!selectedNodeIsVisible) { this->SetToolSelectionBoxesEnabled(false); this->UpdateWarningLabel(tr("The selected segmentation is currently not visible!")); } else { this->SetToolSelectionBoxesEnabled(true); this->UpdateWarningLabel(""); } } void QmitkSegmentationView::OnBinaryPropertyChanged() { mitk::DataStorage::SetOfObjects::ConstPointer patImages = m_Controls->patImageSelector->GetNodes(); for (mitk::DataStorage::SetOfObjects::ConstIterator it = patImages->Begin(); it != patImages->End(); ++it) { const mitk::DataNode* node = it->Value(); if(m_IsASegmentationImagePredicate->CheckNode(node)) { m_Controls->patImageSelector->RemoveNode(node); m_Controls->segImageSelector->AddNode(node); this->SetToolManagerSelection(nullptr,nullptr); return; } } mitk::DataStorage::SetOfObjects::ConstPointer segImages = m_Controls->segImageSelector->GetNodes(); for (mitk::DataStorage::SetOfObjects::ConstIterator it = segImages->Begin(); it != segImages->End(); ++it) { const mitk::DataNode* node = it->Value(); if(!m_IsASegmentationImagePredicate->CheckNode(node)) { m_Controls->segImageSelector->RemoveNode(node); m_Controls->patImageSelector->AddNode(node); if (mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetWorkingData(0) == node) { mitk::ToolManagerProvider::GetInstance()->GetToolManager()->SetWorkingData(nullptr); } return; } } } void QmitkSegmentationView::NodeAdded(const mitk::DataNode *node) { if (!m_IsOfTypeImagePredicate->CheckNode(node)) { return; } itk::SimpleMemberCommand::Pointer command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSegmentationView::OnVisiblePropertyChanged); m_WorkingDataObserverTags.insert(std::pair(const_cast(node), node->GetProperty("visible")->AddObserver(itk::ModifiedEvent(), command))); itk::SimpleMemberCommand::Pointer command2 = itk::SimpleMemberCommand::New(); command2->SetCallbackFunction(this, &QmitkSegmentationView::OnBinaryPropertyChanged); m_BinaryPropertyObserverTags.insert(std::pair(const_cast(node), node->GetProperty("binary")->AddObserver(itk::ModifiedEvent(), command2))); ApplyDisplayOptions(const_cast(node)); } void QmitkSegmentationView::NodeRemoved(const mitk::DataNode* node) { if (m_IsASegmentationImagePredicate->CheckNode(node)) { //First of all remove all possible contour markers of the segmentation mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers = this->GetDataStorage()->GetDerivations(node, mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true))); ctkPluginContext* context = mitk::PluginActivator::getContext(); ctkServiceReference ppmRef = context->getServiceReference(); mitk::PlanePositionManagerService* service = context->getService(ppmRef); for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End(); ++it) { std::string nodeName = node->GetName(); unsigned int t = nodeName.find_last_of(" "); unsigned int id = atof(nodeName.substr(t + 1).c_str()) - 1; service->RemovePlanePosition(id); this->GetDataStorage()->Remove(it->Value()); } context->ungetService(ppmRef); service = nullptr; if ((mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetWorkingData(0) == node) && m_Controls->patImageSelector->GetSelectedNode().IsNotNull()) { this->SetToolManagerSelection(mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetReferenceData(0), nullptr); this->UpdateWarningLabel(tr("Select or create a segmentation")); } mitk::Image* image = dynamic_cast(node->GetData()); mitk::SurfaceInterpolationController::GetInstance()->RemoveInterpolationSession(image); } mitk::DataNode* tempNode = const_cast(node); //Since the binary property could be changed during runtime by the user if (m_IsOfTypeImagePredicate->CheckNode(node)) { node->GetProperty("visible")->RemoveObserver(m_WorkingDataObserverTags[tempNode]); m_WorkingDataObserverTags.erase(tempNode); node->GetProperty("binary")->RemoveObserver(m_BinaryPropertyObserverTags[tempNode]); m_BinaryPropertyObserverTags.erase(tempNode); } if (mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetReferenceData(0) == node) { //as we don't know which node was actually removed e.g. our reference node, disable 'New Segmentation' button. //consider the case that there is no more image in the datastorage this->SetToolManagerSelection(nullptr, nullptr); this->SetToolSelectionBoxesEnabled(false); } } void QmitkSegmentationView::OnPatientComboBoxSelectionChanged( const mitk::DataNode* node ) { //mitk::DataNode* selectedNode = const_cast(node); if( node != nullptr ) { this->UpdateWarningLabel(""); mitk::DataNode* segNode = m_Controls->segImageSelector->GetSelectedNode(); if (segNode) { mitk::DataStorage::SetOfObjects::ConstPointer possibleParents = this->GetDataStorage()->GetSources(segNode, m_IsAPatientImagePredicate); bool isSourceNode(false); for (mitk::DataStorage::SetOfObjects::ConstIterator it = possibleParents->Begin(); it != possibleParents->End(); it++) { if (it.Value() == node) isSourceNode = true; } if ( !isSourceNode && (!this->CheckForSameGeometry(segNode, node) || possibleParents->Size() > 0 )) { this->SetToolManagerSelection(node, nullptr); this->SetToolSelectionBoxesEnabled( false ); this->UpdateWarningLabel(tr("The selected patient image does not match with the selected segmentation!")); } else if ((!isSourceNode && this->CheckForSameGeometry(segNode, node)) || isSourceNode ) { this->SetToolManagerSelection(node, segNode); //Doing this we can assure that the segmenation is always visible if the segmentation and the patient image are //loaded separately int layer(10); node->GetIntProperty("layer", layer); layer++; segNode->SetProperty("layer", mitk::IntProperty::New(layer)); //this->UpdateWarningLabel(""); RenderingManagerReinitialized(); } } else { this->SetToolManagerSelection(node, nullptr); this->SetToolSelectionBoxesEnabled( false ); this->UpdateWarningLabel(tr("Select or create a segmentation")); } } else { this->UpdateWarningLabel(tr("Please load an image!")); this->SetToolSelectionBoxesEnabled( false ); } } void QmitkSegmentationView::OnSegmentationComboBoxSelectionChanged(const mitk::DataNode *node) { if (node == nullptr) { this->UpdateWarningLabel(tr("Select or create a segmentation")); this->SetToolSelectionBoxesEnabled( false ); return; } mitk::DataNode* refNode = m_Controls->patImageSelector->GetSelectedNode(); RenderingManagerReinitialized(); if ( m_Controls->lblSegmentationWarnings->isVisible()) // "RenderingManagerReinitialized()" caused a warning. we do not need to go any further return; if (m_AutoSelectionEnabled) { this->OnSelectionChanged(const_cast(node)); } else { mitk::DataStorage::SetOfObjects::ConstPointer possibleParents = this->GetDataStorage()->GetSources(node, m_IsAPatientImagePredicate); if ( possibleParents->Size() == 1 ) { mitk::DataNode* parentNode = possibleParents->ElementAt(0); if (parentNode != refNode) { this->UpdateWarningLabel(tr("The selected segmentation does not match with the selected patient image!")); this->SetToolSelectionBoxesEnabled( false ); this->SetToolManagerSelection(nullptr, node); } else { this->UpdateWarningLabel(""); this->SetToolManagerSelection(refNode, node); } } else if (refNode && this->CheckForSameGeometry(node, refNode)) { this->UpdateWarningLabel(""); this->SetToolManagerSelection(refNode, node); } else if (!refNode || !this->CheckForSameGeometry(node, refNode)) { this->UpdateWarningLabel(tr("Please select or load the according patient image!")); } } mitk::IRenderWindowPart* renderWindowPart = this->GetRenderWindowPart(); if (!renderWindowPart || !node->IsVisible(renderWindowPart->GetQmitkRenderWindow("axial")->GetRenderer())) { this->UpdateWarningLabel(tr("The selected segmentation is currently not visible!")); this->SetToolSelectionBoxesEnabled( false ); } } void QmitkSegmentationView::OnShowMarkerNodes (bool state) { mitk::SegTool2D::Pointer manualSegmentationTool; unsigned int numberOfExistingTools = mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetTools().size(); for(unsigned int i = 0; i < numberOfExistingTools; i++) { manualSegmentationTool = dynamic_cast(mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetToolById(i)); if (manualSegmentationTool) { if(state == true) { manualSegmentationTool->SetShowMarkerNodes( true ); } else { manualSegmentationTool->SetShowMarkerNodes( false ); } } } } void QmitkSegmentationView::OnSelectionChanged(mitk::DataNode* node) { berry::IWorkbenchPart::Pointer nullPart; QList nodes; nodes.push_back(node); this->OnSelectionChanged(nullPart, nodes); } void QmitkSegmentationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& nodes) { if (nodes.size() != 0) { std::string markerName = "Position"; unsigned int numberOfNodes = nodes.size(); std::string nodeName = nodes.at(0)->GetName(); if ((numberOfNodes == 1) && (nodeName.find(markerName) == 0)) { OnContourMarkerSelected(nodes.at(0)); return; } } if (m_AutoSelectionEnabled) { if (nodes.size() == 0 && m_Controls->patImageSelector->GetSelectedNode().IsNull()) { SetToolManagerSelection(nullptr, nullptr); } else if (nodes.size() == 1) { mitk::DataNode::Pointer selectedNode = nodes.at(0); if (selectedNode.IsNull()) { return; } mitk::Image::Pointer selectedImage = dynamic_cast(selectedNode->GetData()); if (selectedImage.IsNull()) { SetToolManagerSelection(nullptr, nullptr); return; } if (m_IsASegmentationImagePredicate->CheckNode(selectedNode)) { // set all nodes to invisible mitk::DataStorage::SetOfObjects::ConstPointer allImages = GetDataStorage()->GetSubset(m_IsOfTypeImagePredicate); for (mitk::DataStorage::SetOfObjects::const_iterator iter = allImages->begin(); iter != allImages->end(); ++iter) { (*iter)->SetVisibility(false); } // if a segmentation is selected find a possible patient image mitk::DataStorage::SetOfObjects::ConstPointer sources = GetDataStorage()->GetSources(selectedNode, m_IsAPatientImagePredicate); mitk::DataNode::Pointer refNode; if (sources->Size() != 0) { // found one or more sources - use the first one refNode = sources->ElementAt(0); refNode->SetVisibility(true); selectedNode->SetVisibility(true); SetToolManagerSelection(refNode, selectedNode); } else { // did not find a source / patient image, check all images and compare geometry mitk::DataStorage::SetOfObjects::ConstPointer possiblePatientImages = GetDataStorage()->GetSubset(m_IsAPatientImagePredicate); for (mitk::DataStorage::SetOfObjects::ConstIterator iter = possiblePatientImages->Begin(); iter != possiblePatientImages->End(); ++iter) { refNode = iter->Value(); if (CheckForSameGeometry(selectedNode, iter->Value())) { refNode->SetVisibility(true); selectedNode->SetVisibility(true); SetToolManagerSelection(refNode, selectedNode); // doing this we can assure that the segmentation is always visible if the segmentation and the patient image are at the // same level in the data manager int layer(10); refNode->GetIntProperty("layer", layer); layer++; selectedNode->SetProperty("layer", mitk::IntProperty::New(layer)); return; } } // did not find a source / patient image with the same geometry SetToolManagerSelection(nullptr, selectedNode); } mitk::RenderingManager::GetInstance()->InitializeViews(selectedNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); } else { if (mitk::ToolManagerProvider::GetInstance()->GetToolManager()->GetReferenceData(0) != selectedNode) { SetToolManagerSelection(selectedNode, nullptr); // may be a bug in the selection services. A node which is deselected will be passed as selected node to the OnSelectionChanged function mitk::IRenderWindowPart* renderWindowPart = GetRenderWindowPart(); if (renderWindowPart && !selectedNode->IsVisible(renderWindowPart->GetQmitkRenderWindow("axial")->GetRenderer())) { selectedNode->SetVisibility(true); } UpdateWarningLabel(tr("The selected patient image does not match with the selected segmentation!")); SetToolSelectionBoxesEnabled(false); } } } if (m_Controls->lblSegmentationWarnings->isVisible()) // "RenderingManagerReinitialized()" caused a warning. we do not need to go any further { return; } RenderingManagerReinitialized(); } } void QmitkSegmentationView::OnContourMarkerSelected(const mitk::DataNode *node) { QmitkRenderWindow* selectedRenderWindow = 0; - QmitkRenderWindow* axialRenderWindow = - this->GetRenderWindowPart(OPEN)->GetQmitkRenderWindow("axial"); - QmitkRenderWindow* sagittalRenderWindow = - this->GetRenderWindowPart(OPEN)->GetQmitkRenderWindow("sagittal"); - QmitkRenderWindow* coronalRenderWindow = - this->GetRenderWindowPart(OPEN)->GetQmitkRenderWindow("coronal"); - QmitkRenderWindow* _3DRenderWindow = - this->GetRenderWindowPart(OPEN)->GetQmitkRenderWindow("3d"); + QmitkRenderWindow* axialRenderWindow = GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetQmitkRenderWindow("axial"); + QmitkRenderWindow* sagittalRenderWindow = GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetQmitkRenderWindow("sagittal"); + QmitkRenderWindow* coronalRenderWindow = GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetQmitkRenderWindow("coronal"); + QmitkRenderWindow* _3DRenderWindow = GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetQmitkRenderWindow("3d"); bool PlanarFigureInitializedWindow = false; // find initialized renderwindow if (node->GetBoolProperty("PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, axialRenderWindow->GetRenderer())) { selectedRenderWindow = axialRenderWindow; } if (!selectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, sagittalRenderWindow->GetRenderer())) { selectedRenderWindow = sagittalRenderWindow; } if (!selectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, coronalRenderWindow->GetRenderer())) { selectedRenderWindow = coronalRenderWindow; } if (!selectedRenderWindow && node->GetBoolProperty( "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, _3DRenderWindow->GetRenderer())) { selectedRenderWindow = _3DRenderWindow; } // make node visible if (selectedRenderWindow) { std::string nodeName = node->GetName(); unsigned int t = nodeName.find_last_of(" "); unsigned int id = atof(nodeName.substr(t+1).c_str())-1; { ctkPluginContext* context = mitk::PluginActivator::getContext(); ctkServiceReference ppmRef = context->getServiceReference(); mitk::PlanePositionManagerService* service = context->getService(ppmRef); selectedRenderWindow->GetSliceNavigationController()->ExecuteOperation(service->GetPlanePosition(id)); context->ungetService(ppmRef); } selectedRenderWindow->GetRenderer()->GetCameraController()->Fit(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSegmentationView::OnTabWidgetChanged(int id) { //always disable tools on tab changed mitk::ToolManagerProvider::GetInstance()->GetToolManager()->ActivateTool(-1); //2D Tab ID = 0 //3D Tab ID = 1 if (id == 0) { //Hide 3D selection box, show 2D selection box m_Controls->m_ManualToolSelectionBox3D->hide(); m_Controls->m_ManualToolSelectionBox2D->show(); //Deactivate possible active tool //TODO Remove possible visible interpolations -> Maybe changes in SlicesInterpolator } else { //Hide 3D selection box, show 2D selection box m_Controls->m_ManualToolSelectionBox2D->hide(); m_Controls->m_ManualToolSelectionBox3D->show(); //Deactivate possible active tool } } void QmitkSegmentationView::InitToolManagerSelection(const mitk::DataNode* referenceData, const mitk::DataNode* workingData) { // initial tool manager selection, called from 'CreateQtPartControl' mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); toolManager->SetReferenceData(const_cast(referenceData)); toolManager->SetWorkingData(const_cast(workingData)); // check original image m_Controls->btnNewSegmentation->setEnabled(referenceData != nullptr); if (referenceData) { UpdateWarningLabel(""); } } void QmitkSegmentationView::SetToolManagerSelection(const mitk::DataNode* referenceData, const mitk::DataNode* workingData) { // called as a result of new BlueBerry selections // tells the ToolManager for manual segmentation about new selections // updates GUI information about what the user should select mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); toolManager->SetReferenceData(const_cast(referenceData)); toolManager->SetWorkingData(const_cast(workingData)); // check original image m_Controls->btnNewSegmentation->setEnabled(referenceData != nullptr); if (referenceData) { UpdateWarningLabel(""); disconnect(m_Controls->patImageSelector, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnPatientComboBoxSelectionChanged(const mitk::DataNode*))); m_Controls->patImageSelector->setCurrentIndex(m_Controls->patImageSelector->Find(referenceData)); connect(m_Controls->patImageSelector, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnPatientComboBoxSelectionChanged(const mitk::DataNode*))); // check segmentation if (workingData) { //FireNodeSelected(const_cast(workingData)); disconnect(m_Controls->segImageSelector, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnSegmentationComboBoxSelectionChanged(const mitk::DataNode*))); m_Controls->segImageSelector->setCurrentIndex(m_Controls->segImageSelector->Find(workingData)); connect(m_Controls->segImageSelector, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnSegmentationComboBoxSelectionChanged(const mitk::DataNode*))); } } } void QmitkSegmentationView::ForceDisplayPreferencesUponAllImages() { if (!m_Parent) { return; } // check all images and segmentations in DataStorage: // (items in brackets are implicitly done by previous steps) // 1. // if a reference image is selected, // show the reference image // and hide all other images (orignal and segmentation), // (and hide all segmentations of the other original images) // and show all the reference's segmentations // if no reference image is selected, do do nothing // // 2. // if a segmentation is selected, // show it // (and hide all all its siblings (childs of the same parent, incl, nullptr parent)) // if no segmentation is selected, do nothing if (!m_Controls) { return; // might happen on initialization (preferences loaded) } mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); mitk::DataNode::Pointer referenceData = toolManager->GetReferenceData(0); mitk::DataNode::Pointer workingData = toolManager->GetWorkingData(0); // 1. if (referenceData.IsNotNull()) { // iterate all images mitk::DataStorage::SetOfObjects::ConstPointer allImages = this->GetDataStorage()->GetSubset(m_IsASegmentationImagePredicate); for ( mitk::DataStorage::SetOfObjects::const_iterator iter = allImages->begin(); iter != allImages->end(); ++iter) { mitk::DataNode* node = *iter; // apply display preferences ApplyDisplayOptions(node); // set visibility node->SetVisibility(node == referenceData); } } // 2. if (workingData.IsNotNull()) workingData->SetVisibility(true); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSegmentationView::ApplyDisplayOptions(mitk::DataNode* node) { if (!node) { return; } mitk::BoolProperty::Pointer drawOutline = mitk::BoolProperty::New(GetPreferences()->GetBool("draw outline", true)); mitk::BoolProperty::Pointer volumeRendering = mitk::BoolProperty::New(GetPreferences()->GetBool("volume rendering", false)); mitk::LabelSetImage* labelSetImage = dynamic_cast(node->GetData()); if (nullptr != labelSetImage) { // node is actually a multi label segmentation, // but its outline property can be set in the 'single label' segmentation preference page as well node->SetProperty("labelset.contour.active", drawOutline); node->SetProperty("opacity", mitk::FloatProperty::New(drawOutline->GetValue() ? 1.0f : 0.3f)); node->SetProperty("volumerendering", volumeRendering); // force render window update to show outline node->GetData()->Modified(); } else { // node is a 'single label' segmentation bool isBinary = false; node->GetBoolProperty("binary", isBinary); if (isBinary) { node->SetProperty("outline binary", drawOutline); node->SetProperty("outline width", mitk::FloatProperty::New(2.0)); node->SetProperty("opacity", mitk::FloatProperty::New(drawOutline->GetValue() ? 1.0f : 0.3f)); node->SetProperty("volumerendering", volumeRendering); // force render window update to show outline node->GetData()->Modified(); } } } void QmitkSegmentationView::RenderingManagerReinitialized() { if (!this->GetRenderWindowPart()) { return; } /* * Here we check whether the geometry of the selected segmentation image if aligned with the worldgeometry * At the moment it is not supported to use a geometry different from the selected image for reslicing. * For further information see Bug 16063 */ mitk::DataNode* workingNode = m_Controls->segImageSelector->GetSelectedNode(); const mitk::BaseGeometry* worldGeo = this->GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetSliceNavigationController()->GetCurrentGeometry3D(); if (workingNode && worldGeo) { const mitk::BaseGeometry* workingNodeGeo = workingNode->GetData()->GetGeometry(); const mitk::BaseGeometry* worldGeo = this->GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetSliceNavigationController()->GetCurrentGeometry3D(); if (mitk::Equal(*workingNodeGeo->GetBoundingBox(), *worldGeo->GetBoundingBox(), mitk::eps, true)) { this->SetToolManagerSelection(m_Controls->patImageSelector->GetSelectedNode(), workingNode); this->SetToolSelectionBoxesEnabled(true); this->UpdateWarningLabel(""); } else { this->SetToolManagerSelection(m_Controls->patImageSelector->GetSelectedNode(), nullptr); this->SetToolSelectionBoxesEnabled(false); this->UpdateWarningLabel(tr("Please perform a reinit on the segmentation image!")); } } } bool QmitkSegmentationView::CheckForSameGeometry(const mitk::DataNode *node1, const mitk::DataNode *node2) const { bool isSameGeometry(true); mitk::Image* image1 = dynamic_cast(node1->GetData()); mitk::Image* image2 = dynamic_cast(node2->GetData()); if (image1 && image2) { mitk::BaseGeometry* geo1 = image1->GetGeometry(); mitk::BaseGeometry* geo2 = image2->GetGeometry(); isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetOrigin(), geo2->GetOrigin()); isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetExtent(0), geo2->GetExtent(0)); isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetExtent(1), geo2->GetExtent(1)); isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetExtent(2), geo2->GetExtent(2)); isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetSpacing(), geo2->GetSpacing()); isSameGeometry = isSameGeometry && mitk::MatrixEqualElementWise(geo1->GetIndexToWorldTransform()->GetMatrix(), geo2->GetIndexToWorldTransform()->GetMatrix()); return isSameGeometry; } else { return false; } } void QmitkSegmentationView::UpdateWarningLabel(QString text) { if (text.size() == 0) m_Controls->lblSegmentationWarnings->hide(); else m_Controls->lblSegmentationWarnings->show(); m_Controls->lblSegmentationWarnings->setText(text); } void QmitkSegmentationView::CreateQtPartControl(QWidget* parent) { // setup the basic GUI of this view m_Parent = parent; m_Controls = new Ui::QmitkSegmentationControls; m_Controls->setupUi(parent); m_Controls->patImageSelector->SetDataStorage(GetDataStorage()); m_Controls->patImageSelector->SetPredicate(m_IsAPatientImagePredicate); UpdateWarningLabel(tr("Please load an image")); if (m_Controls->patImageSelector->GetSelectedNode().IsNotNull()) { UpdateWarningLabel(tr("Select or create a new segmentation")); } m_Controls->segImageSelector->SetDataStorage(GetDataStorage()); m_Controls->segImageSelector->SetPredicate(m_IsASegmentationImagePredicate); if (m_Controls->segImageSelector->GetSelectedNode().IsNotNull()) { UpdateWarningLabel(""); } mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); assert(toolManager); toolManager->SetDataStorage(*(GetDataStorage())); toolManager->InitializeTools(); // all part of open source MITK m_Controls->m_ManualToolSelectionBox2D->setEnabled(true); m_Controls->m_ManualToolSelectionBox2D->SetGenerateAccelerators(true); m_Controls->m_ManualToolSelectionBox2D->SetToolGUIArea( m_Controls->m_ManualToolGUIContainer2D ); m_Controls->m_ManualToolSelectionBox2D->SetDisplayedToolGroups(tr("Add Subtract Correction Paint Wipe 'Region Growing' Fill Erase 'Live Wire' '2D Fast Marching'").toStdString()); m_Controls->m_ManualToolSelectionBox2D->SetLayoutColumns(3); m_Controls->m_ManualToolSelectionBox2D->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible ); connect( m_Controls->m_ManualToolSelectionBox2D, SIGNAL(ToolSelected(int)), this, SLOT(OnManualTool2DSelected(int)) ); //setup 3D Tools m_Controls->m_ManualToolSelectionBox3D->setEnabled(true); m_Controls->m_ManualToolSelectionBox3D->SetGenerateAccelerators(true); m_Controls->m_ManualToolSelectionBox3D->SetToolGUIArea( m_Controls->m_ManualToolGUIContainer3D ); //specify tools to be added to 3D Tool area m_Controls->m_ManualToolSelectionBox3D->SetDisplayedToolGroups(tr("Threshold 'UL Threshold' Otsu 'Fast Marching 3D' 'Region Growing 3D' Watershed Picking").toStdString()); m_Controls->m_ManualToolSelectionBox3D->SetLayoutColumns(3); m_Controls->m_ManualToolSelectionBox3D->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible ); //Hide 3D selection box, show 2D selection box m_Controls->m_ManualToolSelectionBox3D->hide(); m_Controls->m_ManualToolSelectionBox2D->show(); // update the list of segmentations toolManager->NewNodesGenerated += mitk::MessageDelegate(this, &QmitkSegmentationView::NewNodesGenerated); // update the list of segmentations toolManager->NewNodeObjectsGenerated += mitk::MessageDelegate1(this, &QmitkSegmentationView::NewNodeObjectsGenerated); // create signal/slot connections connect(m_Controls->patImageSelector, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnPatientComboBoxSelectionChanged(const mitk::DataNode*))); connect(m_Controls->segImageSelector, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnSegmentationComboBoxSelectionChanged(const mitk::DataNode*))); connect( m_Controls->btnNewSegmentation, SIGNAL(clicked()), this, SLOT(CreateNewSegmentation()) ); // connect( m_Controls->CreateSegmentationFromSurface, SIGNAL(clicked()), this, SLOT(CreateSegmentationFromSurface()) ); // connect( m_Controls->widgetStack, SIGNAL(currentChanged(int)), this, SLOT(ToolboxStackPageChanged(int)) ); connect( m_Controls->tabWidgetSegmentationTools, SIGNAL(currentChanged(int)), this, SLOT(OnTabWidgetChanged(int))); // connect(m_Controls->MaskSurfaces, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), // this, SLOT( OnSurfaceSelectionChanged( ) ) ); connect(m_Controls->m_SlicesInterpolator, SIGNAL(SignalShowMarkerNodes(bool)), this, SLOT(OnShowMarkerNodes(bool))); // m_Controls->MaskSurfaces->SetDataStorage(this->GetDataStorage()); // m_Controls->MaskSurfaces->SetPredicate(mitk::NodePredicateDataType::New("Surface")); mitk::DataStorage::SetOfObjects::ConstPointer patientImages = GetDataStorage()->GetSubset(m_IsAPatientImagePredicate); if (!patientImages->empty()) { OnSelectionChanged(*patientImages->begin()); } // set callback function for already existing nodes (images & segmentations) mitk::DataStorage::SetOfObjects::ConstPointer allImages = GetDataStorage()->GetSubset(m_IsOfTypeImagePredicate); for (mitk::DataStorage::SetOfObjects::const_iterator iter = allImages->begin(); iter != allImages->end(); ++iter) { mitk::DataNode* node = *iter; itk::SimpleMemberCommand::Pointer command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSegmentationView::OnVisiblePropertyChanged); m_WorkingDataObserverTags.insert(std::pair(node, node->GetProperty("visible")->AddObserver(itk::ModifiedEvent(), command))); itk::SimpleMemberCommand::Pointer command2 = itk::SimpleMemberCommand::New(); command2->SetCallbackFunction(this, &QmitkSegmentationView::OnBinaryPropertyChanged); m_BinaryPropertyObserverTags.insert(std::pair(node, node->GetProperty("binary")->AddObserver(itk::ModifiedEvent(), command2))); } itk::SimpleMemberCommand::Pointer command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSegmentationView::RenderingManagerReinitialized); m_RenderingManagerObserverTag = mitk::RenderingManager::GetInstance()->AddObserver(mitk::RenderingManagerViewsInitializedEvent(), command); InitToolManagerSelection(m_Controls->patImageSelector->GetSelectedNode(), m_Controls->segImageSelector->GetSelectedNode()); m_RenderWindowPart = GetRenderWindowPart(); if (m_RenderWindowPart) { RenderWindowPartActivated(m_RenderWindowPart); } } void QmitkSegmentationView::SetFocus() { m_Controls->btnNewSegmentation->setFocus(); } void QmitkSegmentationView::OnManualTool2DSelected(int id) { if (id >= 0) { std::string text = "Active Tool: \""; mitk::ToolManager* toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); text += toolManager->GetToolById(id)->GetName(); text += "\""; mitk::StatusBar::GetInstance()->DisplayText(text.c_str()); us::ModuleResource resource = toolManager->GetToolById(id)->GetCursorIconResource(); this->SetMouseCursor(resource, 0, 0); } else { this->ResetMouseCursor(); mitk::StatusBar::GetInstance()->DisplayText(""); } } void QmitkSegmentationView::ResetMouseCursor() { if ( m_MouseCursorSet ) { mitk::ApplicationCursor::GetInstance()->PopCursor(); m_MouseCursorSet = false; } } void QmitkSegmentationView::SetMouseCursor( const us::ModuleResource& resource, int hotspotX, int hotspotY ) { if (!resource) return; // Remove previously set mouse cursor if ( m_MouseCursorSet ) { mitk::ApplicationCursor::GetInstance()->PopCursor(); } us::ModuleResourceStream cursor(resource, std::ios::binary); mitk::ApplicationCursor::GetInstance()->PushCursor( cursor, hotspotX, hotspotY ); m_MouseCursorSet = true; } void QmitkSegmentationView::SetToolSelectionBoxesEnabled(bool status) { if (status) { m_Controls->m_ManualToolSelectionBox2D->RecreateButtons(); m_Controls->m_ManualToolSelectionBox3D->RecreateButtons(); } m_Controls->m_ManualToolSelectionBox2D->setEnabled(status); m_Controls->m_ManualToolSelectionBox3D->setEnabled(status); m_Controls->m_SlicesInterpolator->setEnabled(status); }