diff --git a/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.cpp b/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.cpp index 9e232f1abf..023a2f03c8 100644 --- a/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.cpp +++ b/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.cpp @@ -1,114 +1,144 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "org_mitk_gui_qt_flow_segmentation_Activator.h" #include +#include + //MITK #include #include #include #include #include #include #include // Qmitk #include "QmitkSegmentationFlowControlView.h" #include // Qt #include const std::string QmitkSegmentationFlowControlView::VIEW_ID = "org.mitk.views.flow.control"; QmitkSegmentationFlowControlView::QmitkSegmentationFlowControlView() - : m_Controls(new Ui::SegmentationFlowControlView), - m_Parent(nullptr) + : m_Controls(new Ui::SegmentationFlowControlView) { + berry::PlatformUI::GetWorkbench()->AddWorkbenchListener(this); + auto notHelperObject = mitk::NodePredicateNot::New( mitk::NodePredicateProperty::New("helper object")); m_SegmentationPredicate = mitk::NodePredicateAnd::New( mitk::TNodePredicateDataType::New(), notHelperObject); + + m_SegmentationTaskListPredicate = mitk::NodePredicateAnd::New( + mitk::TNodePredicateDataType::New(), + notHelperObject); } QmitkSegmentationFlowControlView::~QmitkSegmentationFlowControlView() { + berry::PlatformUI::GetWorkbench()->RemoveWorkbenchListener(this); } void QmitkSegmentationFlowControlView::SetFocus() { m_Controls->btnStoreAndAccept->setFocus(); } void QmitkSegmentationFlowControlView::CreateQtPartControl(QWidget* parent) { m_Controls->setupUi(parent); - m_Parent = parent; + + m_Controls->segmentationTaskListWidget->SetDataStorage(this->GetDataStorage()); + m_Controls->segmentationTaskListWidget->setVisible(false); + + m_Controls->labelStored->setVisible(false); using Self = QmitkSegmentationFlowControlView; connect(m_Controls->btnStoreAndAccept, &QPushButton::clicked, this, &Self::OnAcceptButtonClicked); - m_Controls->labelStored->setVisible(false); - this->UpdateControls(); m_OutputDir = QString::fromStdString(mitk::BaseApplication::instance().config().getString("flow.outputdir", itksys::SystemTools::GetCurrentWorkingDirectory())); m_OutputDir = QDir::fromNativeSeparators(m_OutputDir); m_FileExtension = QString::fromStdString(mitk::BaseApplication::instance().config().getString("flow.outputextension", "nrrd")); } void QmitkSegmentationFlowControlView::OnAcceptButtonClicked() { auto nodes = this->GetDataStorage()->GetSubset(m_SegmentationPredicate); for (auto node : *nodes) { QString outputpath = m_OutputDir + "/" + QString::fromStdString(node->GetName()) + "." + m_FileExtension; outputpath = QDir::toNativeSeparators(QDir::cleanPath(outputpath)); mitk::IOUtil::Save(node->GetData(), outputpath.toStdString()); } m_Controls->labelStored->setVisible(true); } void QmitkSegmentationFlowControlView::UpdateControls() { auto dataStorage = this->GetDataStorage(); + auto hasSegmentationTaskList = !dataStorage->GetSubset(m_SegmentationTaskListPredicate)->empty(); + + m_Controls->segmentationTaskListWidget->setVisible(hasSegmentationTaskList); + + if (hasSegmentationTaskList) // Give precedence to segmentation task list + { + m_Controls->btnStoreAndAccept->setVisible(false); + m_Controls->labelStored->setVisible(false); + return; + } + auto hasSegmentation = !dataStorage->GetSubset(m_SegmentationPredicate)->empty(); m_Controls->btnStoreAndAccept->setEnabled(hasSegmentation); + m_Controls->btnStoreAndAccept->setVisible(true); } void QmitkSegmentationFlowControlView::NodeAdded(const mitk::DataNode* node) { if (dynamic_cast(node->GetData()) != nullptr) this->UpdateControls(); } void QmitkSegmentationFlowControlView::NodeChanged(const mitk::DataNode* node) { if (dynamic_cast(node->GetData()) != nullptr) this->UpdateControls(); } void QmitkSegmentationFlowControlView::NodeRemoved(const mitk::DataNode* node) { if (dynamic_cast(node->GetData()) != nullptr) this->UpdateControls(); } + +bool QmitkSegmentationFlowControlView::PreShutdown(berry::IWorkbench*, bool) +{ + if (m_Controls->segmentationTaskListWidget->isVisible()) + return m_Controls->segmentationTaskListWidget->OnPreShutdown(); + + return true; // No veto against shutdown +} diff --git a/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.h b/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.h index 54e8fa2f8e..2ac6e8e0a4 100644 --- a/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.h +++ b/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.h @@ -1,78 +1,81 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef QmitkSegmentationFlowControlView_h #define QmitkSegmentationFlowControlView_h #include +#include #include #include "mitkNodePredicateBase.h" namespace Ui { class SegmentationFlowControlView; } /*! \brief QmitkSegmentationFlowControlView Class that "controls" the segmentation view. It offers the possibility to accept a segmentation. Accepting the segmentation stores the segmentation to the given working directory. The working directory is specified by command line arguments. If no commandline flag is set the current working directory will be used. */ -class QmitkSegmentationFlowControlView : public QmitkAbstractView +class QmitkSegmentationFlowControlView : public QmitkAbstractView, public berry::IWorkbenchListener { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; /** * Creates smartpointer typedefs */ berryObjectMacro(QmitkSegmentationFlowControlView) QmitkSegmentationFlowControlView(); ~QmitkSegmentationFlowControlView() override; void CreateQtPartControl(QWidget *parent) override; protected slots: void OnAcceptButtonClicked(); protected: void SetFocus() override; void NodeAdded(const mitk::DataNode* node) override; void NodeChanged(const mitk::DataNode* node) override; void NodeRemoved(const mitk::DataNode* node) override; + bool PreShutdown(berry::IWorkbench*, bool) override; + void UpdateControls(); Ui::SegmentationFlowControlView* m_Controls; private: - QWidget *m_Parent; mitk::NodePredicateBase::Pointer m_SegmentationPredicate; + mitk::NodePredicateBase::Pointer m_SegmentationTaskListPredicate; QString m_OutputDir; QString m_FileExtension; }; #endif diff --git a/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.ui b/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.ui index 964a36323e..0d9da019c7 100644 --- a/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.ui +++ b/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/QmitkSegmentationFlowControlView.ui @@ -1,97 +1,108 @@ SegmentationFlowControlView 0 0 268 324 Qt::Vertical 20 40 + + + 0 50 Save and accept segmentation Accept segmentation 32 32 <html><head/><body><p><span style=" font-size:12pt;">Segmentation accepted! Flow on...</span></p></body></html> Qt::AlignCenter Qt::Vertical 20 40 + + + QmitkSegmentationTaskListWidget + QWidget +
QmitkSegmentationTaskListWidget.h
+ 1 +
+
5 5 true true true
diff --git a/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/perspectives/QmitkFlowSegmentationPerspective.cpp b/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/perspectives/QmitkFlowSegmentationPerspective.cpp index d5650449a4..b515da99d0 100644 --- a/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/perspectives/QmitkFlowSegmentationPerspective.cpp +++ b/Plugins/org.mitk.gui.qt.flow.segmentation/src/internal/perspectives/QmitkFlowSegmentationPerspective.cpp @@ -1,43 +1,44 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkFlowSegmentationPerspective.h" -#include "berryIViewLayout.h" +#include +#include QmitkFlowSegmentationPerspective::QmitkFlowSegmentationPerspective() { } void QmitkFlowSegmentationPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout) { QString editorArea = layout->GetEditorArea(); layout->AddView("org.mitk.views.segmentation", berry::IPageLayout::LEFT, 0.24f, editorArea); berry::IViewLayout::Pointer lo = layout->GetViewLayout("org.mitk.views.segmentation"); lo->SetCloseable(false); layout->AddStandaloneView("org.mitk.views.flow.control",false, berry::IPageLayout::RIGHT, 0.72f, editorArea); lo = layout->GetViewLayout("org.mitk.views.flow.control"); lo->SetCloseable(false); layout->AddView("org.mitk.views.imagenavigator", berry::IPageLayout::TOP, 0.1f, "org.mitk.views.flow.control"); berry::IPlaceholderFolderLayout::Pointer bottomFolder = layout->CreatePlaceholderFolder("bottom", berry::IPageLayout::BOTTOM, 0.7f, editorArea); bottomFolder->AddPlaceholder("org.blueberry.views.logview"); berry::IPlaceholderFolderLayout::Pointer rightFolder = layout->CreatePlaceholderFolder("right", berry::IPageLayout::RIGHT, 0.3f, editorArea); rightFolder->AddPlaceholder("org.mitk.views.datamanager"); layout->AddPerspectiveShortcut("org.mitk.qt.flowapplication.defaultperspective"); } diff --git a/Plugins/org.mitk.gui.qt.flowapplication/src/internal/QmitkFlowApplicationWorkbenchWindowAdvisor.cpp b/Plugins/org.mitk.gui.qt.flowapplication/src/internal/QmitkFlowApplicationWorkbenchWindowAdvisor.cpp index 3ecc52eac8..fb76fb6949 100644 --- a/Plugins/org.mitk.gui.qt.flowapplication/src/internal/QmitkFlowApplicationWorkbenchWindowAdvisor.cpp +++ b/Plugins/org.mitk.gui.qt.flowapplication/src/internal/QmitkFlowApplicationWorkbenchWindowAdvisor.cpp @@ -1,1152 +1,1153 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkFlowApplicationWorkbenchWindowAdvisor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "QmitkExtFileSaveProjectAction.h" #include #include #include #include #include #include #include #include #include #include // UGLYYY #include "QmitkFlowApplicationWorkbenchWindowAdvisorHack.h" #include "QmitkFlowApplicationPlugin.h" #include "mitkUndoController.h" #include "mitkVerboseLimitedLinearUndo.h" #include #include #include #include #include #include QmitkFlowApplicationWorkbenchWindowAdvisorHack* QmitkFlowApplicationWorkbenchWindowAdvisorHack::undohack = new QmitkFlowApplicationWorkbenchWindowAdvisorHack(); QString QmitkFlowApplicationWorkbenchWindowAdvisor::QT_SETTINGS_FILENAME = "QtSettings.ini"; class PartListenerForTitle: public berry::IPartListener { public: PartListenerForTitle(QmitkFlowApplicationWorkbenchWindowAdvisor* wa) : windowAdvisor(wa) { } Events::Types GetPartEventTypes() const override { return Events::ACTIVATED | Events::BROUGHT_TO_TOP | Events::CLOSED | Events::HIDDEN | Events::VISIBLE; } void PartActivated(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref.Cast ()) { windowAdvisor->UpdateTitle(false); } } void PartBroughtToTop(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref.Cast ()) { windowAdvisor->UpdateTitle(false); } } void PartClosed(const berry::IWorkbenchPartReference::Pointer& /*ref*/) override { windowAdvisor->UpdateTitle(false); } void PartHidden(const berry::IWorkbenchPartReference::Pointer& ref) override { auto lockedLastActiveEditor = windowAdvisor->lastActiveEditor.Lock(); if (lockedLastActiveEditor.IsNotNull() && ref->GetPart(false) == lockedLastActiveEditor) { windowAdvisor->UpdateTitle(true); } } void PartVisible(const berry::IWorkbenchPartReference::Pointer& ref) override { auto lockedLastActiveEditor = windowAdvisor->lastActiveEditor.Lock(); if (lockedLastActiveEditor.IsNotNull() && ref->GetPart(false) == lockedLastActiveEditor) { windowAdvisor->UpdateTitle(false); } } private: QmitkFlowApplicationWorkbenchWindowAdvisor* windowAdvisor; }; class PartListenerForImageNavigator: public berry::IPartListener { public: PartListenerForImageNavigator(QAction* act) : imageNavigatorAction(act) { } Events::Types GetPartEventTypes() const override { return Events::OPENED | Events::CLOSED | Events::HIDDEN | Events::VISIBLE; } void PartOpened(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.imagenavigator") { imageNavigatorAction->setChecked(true); } } void PartClosed(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.imagenavigator") { imageNavigatorAction->setChecked(false); } } void PartVisible(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.imagenavigator") { imageNavigatorAction->setChecked(true); } } void PartHidden(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.imagenavigator") { imageNavigatorAction->setChecked(false); } } private: QAction* imageNavigatorAction; }; class PerspectiveListenerForTitle: public berry::IPerspectiveListener { public: PerspectiveListenerForTitle(QmitkFlowApplicationWorkbenchWindowAdvisor* wa) : windowAdvisor(wa) , perspectivesClosed(false) { } Events::Types GetPerspectiveEventTypes() const override { return Events::ACTIVATED | Events::SAVED_AS | Events::DEACTIVATED | Events::CLOSED | Events::OPENED; } void PerspectiveActivated(const berry::IWorkbenchPage::Pointer& /*page*/, const berry::IPerspectiveDescriptor::Pointer& /*perspective*/) override { windowAdvisor->UpdateTitle(false); } void PerspectiveSavedAs(const berry::IWorkbenchPage::Pointer& /*page*/, const berry::IPerspectiveDescriptor::Pointer& /*oldPerspective*/, const berry::IPerspectiveDescriptor::Pointer& /*newPerspective*/) override { windowAdvisor->UpdateTitle(false); } void PerspectiveDeactivated(const berry::IWorkbenchPage::Pointer& /*page*/, const berry::IPerspectiveDescriptor::Pointer& /*perspective*/) override { windowAdvisor->UpdateTitle(false); } void PerspectiveOpened(const berry::IWorkbenchPage::Pointer& /*page*/, const berry::IPerspectiveDescriptor::Pointer& /*perspective*/) override { if (perspectivesClosed) { QListIterator i(windowAdvisor->viewActions); while (i.hasNext()) { i.next()->setEnabled(true); } windowAdvisor->fileSaveProjectAction->setEnabled(true); windowAdvisor->undoAction->setEnabled(true); windowAdvisor->redoAction->setEnabled(true); windowAdvisor->imageNavigatorAction->setEnabled(true); windowAdvisor->resetPerspAction->setEnabled(true); } perspectivesClosed = false; } void PerspectiveClosed(const berry::IWorkbenchPage::Pointer& /*page*/, const berry::IPerspectiveDescriptor::Pointer& /*perspective*/) override { berry::IWorkbenchWindow::Pointer wnd = windowAdvisor->GetWindowConfigurer()->GetWindow(); bool allClosed = true; if (wnd->GetActivePage()) { QList perspectives(wnd->GetActivePage()->GetOpenPerspectives()); allClosed = perspectives.empty(); } if (allClosed) { perspectivesClosed = true; QListIterator i(windowAdvisor->viewActions); while (i.hasNext()) { i.next()->setEnabled(false); } windowAdvisor->fileSaveProjectAction->setEnabled(false); windowAdvisor->undoAction->setEnabled(false); windowAdvisor->redoAction->setEnabled(false); windowAdvisor->imageNavigatorAction->setEnabled(false); windowAdvisor->resetPerspAction->setEnabled(false); } } private: QmitkFlowApplicationWorkbenchWindowAdvisor* windowAdvisor; bool perspectivesClosed; }; class PerspectiveListenerForMenu: public berry::IPerspectiveListener { public: PerspectiveListenerForMenu(QmitkFlowApplicationWorkbenchWindowAdvisor* wa) : windowAdvisor(wa) { } Events::Types GetPerspectiveEventTypes() const override { return Events::ACTIVATED | Events::DEACTIVATED; } void PerspectiveActivated(const berry::IWorkbenchPage::Pointer& /*page*/, const berry::IPerspectiveDescriptor::Pointer& perspective) override { QAction* action = windowAdvisor->mapPerspIdToAction[perspective->GetId()]; if (action) { action->setChecked(true); } } void PerspectiveDeactivated(const berry::IWorkbenchPage::Pointer& /*page*/, const berry::IPerspectiveDescriptor::Pointer& perspective) override { QAction* action = windowAdvisor->mapPerspIdToAction[perspective->GetId()]; if (action) { action->setChecked(false); } } private: QmitkFlowApplicationWorkbenchWindowAdvisor* windowAdvisor; }; QmitkFlowApplicationWorkbenchWindowAdvisor::QmitkFlowApplicationWorkbenchWindowAdvisor(berry::WorkbenchAdvisor* wbAdvisor, berry::IWorkbenchWindowConfigurer::Pointer configurer) : berry::WorkbenchWindowAdvisor(configurer) , lastInput(nullptr) , wbAdvisor(wbAdvisor) , showViewToolbar(true) , showVersionInfo(true) , showMitkVersionInfo(true) , showMemoryIndicator(true) , dropTargetListener(new QmitkDefaultDropTargetListener) { productName = QCoreApplication::applicationName(); viewExcludeList.push_back("org.mitk.views.viewnavigator"); } QmitkFlowApplicationWorkbenchWindowAdvisor::~QmitkFlowApplicationWorkbenchWindowAdvisor() { } QWidget* QmitkFlowApplicationWorkbenchWindowAdvisor::CreateEmptyWindowContents(QWidget* parent) { QWidget* parentWidget = static_cast(parent); auto label = new QLabel(parentWidget); label->setText("No perspectives are open. Open a perspective in the Window->Open Perspective menu."); label->setContentsMargins(10,10,10,10); label->setAlignment(Qt::AlignTop); label->setEnabled(false); parentWidget->layout()->addWidget(label); return label; } void QmitkFlowApplicationWorkbenchWindowAdvisor::ShowMemoryIndicator(bool show) { showMemoryIndicator = show; } bool QmitkFlowApplicationWorkbenchWindowAdvisor::GetShowMemoryIndicator() { return showMemoryIndicator; } void QmitkFlowApplicationWorkbenchWindowAdvisor::ShowViewToolbar(bool show) { showViewToolbar = show; } void QmitkFlowApplicationWorkbenchWindowAdvisor::ShowVersionInfo(bool show) { showVersionInfo = show; } void QmitkFlowApplicationWorkbenchWindowAdvisor::ShowMitkVersionInfo(bool show) { showMitkVersionInfo = show; } void QmitkFlowApplicationWorkbenchWindowAdvisor::SetProductName(const QString& product) { productName = product; } void QmitkFlowApplicationWorkbenchWindowAdvisor::SetWindowIcon(const QString& wndIcon) { windowIcon = wndIcon; } void QmitkFlowApplicationWorkbenchWindowAdvisor::PostWindowCreate() { // very bad hack... berry::IWorkbenchWindow::Pointer window = this->GetWindowConfigurer()->GetWindow(); QMainWindow* mainWindow = qobject_cast (window->GetShell()->GetControl()); if (!windowIcon.isEmpty()) { mainWindow->setWindowIcon(QIcon(windowIcon)); } mainWindow->setContextMenuPolicy(Qt::PreventContextMenu); // Load icon theme QIcon::setThemeSearchPaths(QStringList() << QStringLiteral(":/org_mitk_icons/icons/")); QIcon::setThemeName(QStringLiteral("awesome")); // ==== Application menu ============================ QMenuBar* menuBar = mainWindow->menuBar(); menuBar->setContextMenuPolicy(Qt::PreventContextMenu); #ifdef __APPLE__ menuBar->setNativeMenuBar(true); #else menuBar->setNativeMenuBar(false); #endif auto basePath = QStringLiteral(":/org_mitk_icons/icons/awesome/scalable/actions/"); fileSaveProjectAction = new QmitkExtFileSaveProjectAction(window); fileSaveProjectAction->setIcon(berry::QtStyleManager::ThemeIcon(basePath + "document-save.svg")); auto perspGroup = new QActionGroup(menuBar); std::map VDMap; // sort elements (converting vector to map...) QList::const_iterator iter; berry::IViewRegistry* viewRegistry = berry::PlatformUI::GetWorkbench()->GetViewRegistry(); const QList viewDescriptors = viewRegistry->GetViews(); bool skip = false; for (iter = viewDescriptors.begin(); iter != viewDescriptors.end(); ++iter) { // if viewExcludeList is set, it contains the id-strings of view, which // should not appear as an menu-entry in the menu if (viewExcludeList.size() > 0) { for (int i=0; iGetId()) { skip = true; break; } } if (skip) { skip = false; continue; } } if ((*iter)->GetId() == "org.blueberry.ui.internal.introview") continue; if ((*iter)->GetId() == "org.mitk.views.imagenavigator") continue; if ((*iter)->GetId() == "org.mitk.views.viewnavigator") continue; std::pair p((*iter)->GetLabel(), (*iter)); VDMap.insert(p); } std::map::const_iterator MapIter; for (MapIter = VDMap.begin(); MapIter != VDMap.end(); ++MapIter) { berry::QtShowViewAction* viewAction = new berry::QtShowViewAction(window, (*MapIter).second); viewActions.push_back(viewAction); } QMenu* fileMenu = menuBar->addMenu("&File"); fileMenu->setObjectName("FileMenu"); fileMenu->addAction(fileSaveProjectAction); fileMenu->addSeparator(); QAction* fileExitAction = new QmitkFileExitAction(window); fileExitAction->setIcon(berry::QtStyleManager::ThemeIcon(basePath + "system-log-out.svg")); fileExitAction->setShortcut(QKeySequence::Quit); fileExitAction->setObjectName("QmitkFileExitAction"); fileMenu->addAction(fileExitAction); // another bad hack to get an edit/undo menu... QMenu* editMenu = menuBar->addMenu("&Edit"); undoAction = editMenu->addAction(berry::QtStyleManager::ThemeIcon(basePath + "edit-undo.svg"), "&Undo", QmitkFlowApplicationWorkbenchWindowAdvisorHack::undohack, SLOT(onUndo()), QKeySequence("CTRL+Z")); undoAction->setToolTip("Undo the last action (not supported by all modules)"); redoAction = editMenu->addAction(berry::QtStyleManager::ThemeIcon(basePath + "edit-redo.svg"), "&Redo", QmitkFlowApplicationWorkbenchWindowAdvisorHack::undohack, SLOT(onRedo()), QKeySequence("CTRL+Y")); redoAction->setToolTip("execute the last action that was undone again (not supported by all modules)"); // ==== Window Menu ========================== QMenu* windowMenu = menuBar->addMenu("Window"); QMenu* perspMenu = windowMenu->addMenu("&Open Perspective"); windowMenu->addSeparator(); resetPerspAction = windowMenu->addAction("&Reset Perspective", QmitkFlowApplicationWorkbenchWindowAdvisorHack::undohack, SLOT(onResetPerspective())); windowMenu->addSeparator(); windowMenu->addAction("&Preferences...", QmitkFlowApplicationWorkbenchWindowAdvisorHack::undohack, SLOT(onEditPreferences()), QKeySequence("CTRL+P")); // fill perspective menu berry::IPerspectiveRegistry* perspRegistry = window->GetWorkbench()->GetPerspectiveRegistry(); QList perspectives( perspRegistry->GetPerspectives()); skip = false; for (QList::iterator perspIt = perspectives.begin(); perspIt != perspectives.end(); ++perspIt) { // if perspectiveExcludeList is set, it contains the id-strings of perspectives, which // should not appear as an menu-entry in the perspective menu if (perspectiveExcludeList.size() > 0) { for (int i=0; iGetId()) { skip = true; break; } } if (skip) { skip = false; continue; } } QAction* perspAction = new berry::QtOpenPerspectiveAction(window, *perspIt, perspGroup); mapPerspIdToAction.insert((*perspIt)->GetId(), perspAction); } perspMenu->addActions(perspGroup->actions()); // ===== Help menu ==================================== QMenu* helpMenu = menuBar->addMenu("&Help"); helpMenu->addAction("&Welcome",this, SLOT(onIntro())); helpMenu->addAction("&Open Help Perspective", this, SLOT(onHelpOpenHelpPerspective())); helpMenu->addAction("&Context Help",this, SLOT(onHelp()), QKeySequence("F1")); helpMenu->addAction("&About",this, SLOT(onAbout())); // ===================================================== // toolbar for showing file open, undo, redo and other main actions auto mainActionsToolBar = new QToolBar; mainActionsToolBar->setObjectName("mainActionsToolBar"); mainActionsToolBar->setContextMenuPolicy(Qt::PreventContextMenu); #ifdef __APPLE__ mainActionsToolBar->setToolButtonStyle ( Qt::ToolButtonTextUnderIcon ); #else mainActionsToolBar->setToolButtonStyle ( Qt::ToolButtonTextBesideIcon ); #endif basePath = QStringLiteral(":/org.mitk.gui.qt.ext/"); imageNavigatorAction = new QAction(berry::QtStyleManager::ThemeIcon(basePath + "image_navigator.svg"), "&Image Navigator", nullptr); bool imageNavigatorViewFound = window->GetWorkbench()->GetViewRegistry()->Find("org.mitk.views.imagenavigator"); if (imageNavigatorViewFound) { QObject::connect(imageNavigatorAction, SIGNAL(triggered(bool)), QmitkFlowApplicationWorkbenchWindowAdvisorHack::undohack, SLOT(onImageNavigator())); imageNavigatorAction->setCheckable(true); // add part listener for image navigator imageNavigatorPartListener.reset(new PartListenerForImageNavigator(imageNavigatorAction)); window->GetPartService()->AddPartListener(imageNavigatorPartListener.data()); berry::IViewPart::Pointer imageNavigatorView = window->GetActivePage()->FindView("org.mitk.views.imagenavigator"); imageNavigatorAction->setChecked(false); if (imageNavigatorView) { bool isImageNavigatorVisible = window->GetActivePage()->IsPartVisible(imageNavigatorView); if (isImageNavigatorVisible) imageNavigatorAction->setChecked(true); } imageNavigatorAction->setToolTip("Toggle image navigator for navigating through image"); } mainActionsToolBar->addAction(undoAction); mainActionsToolBar->addAction(redoAction); if (imageNavigatorViewFound) { mainActionsToolBar->addAction(imageNavigatorAction); } mainWindow->addToolBar(mainActionsToolBar); // ==== View Toolbar ================================== if (showViewToolbar) { auto* prefService = mitk::CoreServices::GetPreferencesService(); auto* stylePrefs = prefService->GetSystemPreferences()->Node(berry::QtPreferences::QT_STYLES_NODE); bool showCategoryNames = stylePrefs->GetBool(berry::QtPreferences::QT_SHOW_TOOLBAR_CATEGORY_NAMES, true); // Order view descriptors by category QMultiMap categoryViewDescriptorMap; for (auto labelViewDescriptorPair : VDMap) { auto viewDescriptor = labelViewDescriptorPair.second; auto category = !viewDescriptor->GetCategoryPath().isEmpty() ? viewDescriptor->GetCategoryPath().back() : QString(); categoryViewDescriptorMap.insert(category, viewDescriptor); } // Create a separate toolbar for each category for (auto category : categoryViewDescriptorMap.uniqueKeys()) { auto viewDescriptorsInCurrentCategory = categoryViewDescriptorMap.values(category); QList > relevantViewDescriptors; for (auto viewDescriptor : viewDescriptorsInCurrentCategory) { - if (viewDescriptor->GetId() != "org.mitk.views.flow.control") + if (viewDescriptor->GetId() != "org.mitk.views.flow.control" && + viewDescriptor->GetId() != "org.mitk.views.segmentationtasklist") { relevantViewDescriptors.push_back(viewDescriptor); } } if (!relevantViewDescriptors.isEmpty()) { auto toolbar = new QToolBar; toolbar->setObjectName(category + " View Toolbar"); mainWindow->addToolBar(toolbar); if (showCategoryNames && !category.isEmpty()) { auto categoryButton = new QToolButton; categoryButton->setToolButtonStyle(Qt::ToolButtonTextOnly); categoryButton->setText(category); categoryButton->setStyleSheet("background: transparent; margin: 0; padding: 0;"); toolbar->addWidget(categoryButton); connect(categoryButton, &QToolButton::clicked, [toolbar]() { for (QWidget* widget : toolbar->findChildren()) { if (QStringLiteral("qt_toolbar_ext_button") == widget->objectName() && widget->isVisible()) { QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(0.0f, 0.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(0.0f, 0.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); QApplication::sendEvent(widget, &pressEvent); QApplication::sendEvent(widget, &releaseEvent); } } }); } for (auto viewDescriptor : relevantViewDescriptors) { auto viewAction = new berry::QtShowViewAction(window, viewDescriptor); toolbar->addAction(viewAction); } } } } QSettings settings(GetQSettingsFile(), QSettings::IniFormat); mainWindow->restoreState(settings.value("ToolbarPosition").toByteArray()); auto qStatusBar = new QStatusBar(); //creating a QmitkStatusBar for Output on the QStatusBar and connecting it with the MainStatusBar auto statusBar = new QmitkStatusBar(qStatusBar); //disabling the SizeGrip in the lower right corner statusBar->SetSizeGripEnabled(false); auto progBar = new QmitkProgressBar(); qStatusBar->addPermanentWidget(progBar, 0); progBar->hide(); mainWindow->setStatusBar(qStatusBar); if (showMemoryIndicator) { auto memoryIndicator = new QmitkMemoryUsageIndicatorView(); qStatusBar->addPermanentWidget(memoryIndicator, 0); } } void QmitkFlowApplicationWorkbenchWindowAdvisor::PreWindowOpen() { berry::IWorkbenchWindowConfigurer::Pointer configurer = GetWindowConfigurer(); this->HookTitleUpdateListeners(configurer); menuPerspectiveListener.reset(new PerspectiveListenerForMenu(this)); configurer->GetWindow()->AddPerspectiveListener(menuPerspectiveListener.data()); configurer->AddEditorAreaTransfer(QStringList("text/uri-list")); configurer->ConfigureEditorAreaDropListener(dropTargetListener.data()); } void QmitkFlowApplicationWorkbenchWindowAdvisor::PostWindowOpen() { berry::WorkbenchWindowAdvisor::PostWindowOpen(); // Force Rendering Window Creation on startup. berry::IWorkbenchWindowConfigurer::Pointer configurer = GetWindowConfigurer(); ctkPluginContext* context = QmitkFlowApplicationPlugin::GetDefault()->GetPluginContext(); ctkServiceReference serviceRef = context->getServiceReference(); if (serviceRef) { mitk::IDataStorageService *dsService = context->getService(serviceRef); if (dsService) { mitk::IDataStorageReference::Pointer dsRef = dsService->GetDataStorage(); mitk::DataStorageEditorInput::Pointer dsInput(new mitk::DataStorageEditorInput(dsRef)); mitk::WorkbenchUtil::OpenEditor(configurer->GetWindow()->GetActivePage(),dsInput); } } } void QmitkFlowApplicationWorkbenchWindowAdvisor::onIntro() { QmitkFlowApplicationWorkbenchWindowAdvisorHack::undohack->onIntro(); } void QmitkFlowApplicationWorkbenchWindowAdvisor::onHelp() { QmitkFlowApplicationWorkbenchWindowAdvisorHack::undohack->onHelp(); } void QmitkFlowApplicationWorkbenchWindowAdvisor::onHelpOpenHelpPerspective() { QmitkFlowApplicationWorkbenchWindowAdvisorHack::undohack->onHelpOpenHelpPerspective(); } void QmitkFlowApplicationWorkbenchWindowAdvisor::onAbout() { QmitkFlowApplicationWorkbenchWindowAdvisorHack::undohack->onAbout(); } void QmitkFlowApplicationWorkbenchWindowAdvisor::HookTitleUpdateListeners(berry::IWorkbenchWindowConfigurer::Pointer configurer) { // hook up the listeners to update the window title titlePartListener.reset(new PartListenerForTitle(this)); titlePerspectiveListener.reset(new PerspectiveListenerForTitle(this)); editorPropertyListener.reset(new berry::PropertyChangeIntAdapter< QmitkFlowApplicationWorkbenchWindowAdvisor>(this, &QmitkFlowApplicationWorkbenchWindowAdvisor::PropertyChange)); configurer->GetWindow()->AddPerspectiveListener(titlePerspectiveListener.data()); configurer->GetWindow()->GetPartService()->AddPartListener(titlePartListener.data()); } QString QmitkFlowApplicationWorkbenchWindowAdvisor::ComputeTitle() { berry::IWorkbenchWindowConfigurer::Pointer configurer = GetWindowConfigurer(); berry::IWorkbenchPage::Pointer currentPage = configurer->GetWindow()->GetActivePage(); berry::IEditorPart::Pointer activeEditor; if (currentPage) { activeEditor = lastActiveEditor.Lock(); } QString title; berry::IProduct::Pointer product = berry::Platform::GetProduct(); if (product.IsNotNull()) { title = product->GetName(); } if (title.isEmpty()) { // instead of the product name, we use a custom variable for now title = productName; } if(showMitkVersionInfo) { QString mitkVersionInfo = MITK_REVISION_DESC; if(mitkVersionInfo.isEmpty()) mitkVersionInfo = MITK_VERSION_STRING; title += " " + mitkVersionInfo; } if (showVersionInfo) { // add version informatioin QString versions = QString(" (ITK %1.%2.%3 | VTK %4.%5.%6 | Qt %7)") .arg(ITK_VERSION_MAJOR).arg(ITK_VERSION_MINOR).arg(ITK_VERSION_PATCH) .arg(VTK_MAJOR_VERSION).arg(VTK_MINOR_VERSION).arg(VTK_BUILD_VERSION) .arg(QT_VERSION_STR); title += versions; } if (currentPage) { if (activeEditor) { lastEditorTitle = activeEditor->GetTitleToolTip(); if (!lastEditorTitle.isEmpty()) title = lastEditorTitle + " - " + title; } berry::IPerspectiveDescriptor::Pointer persp = currentPage->GetPerspective(); QString label = ""; if (persp) { label = persp->GetLabel(); } berry::IAdaptable* input = currentPage->GetInput(); if (input && input != wbAdvisor->GetDefaultPageInput()) { label = currentPage->GetLabel(); } if (!label.isEmpty()) { title = label + " - " + title; } } title += " (Not for use in diagnosis or treatment of patients)"; return title; } void QmitkFlowApplicationWorkbenchWindowAdvisor::RecomputeTitle() { berry::IWorkbenchWindowConfigurer::Pointer configurer = GetWindowConfigurer(); QString oldTitle = configurer->GetTitle(); QString newTitle = ComputeTitle(); if (newTitle != oldTitle) { configurer->SetTitle(newTitle); } } void QmitkFlowApplicationWorkbenchWindowAdvisor::UpdateTitle(bool editorHidden) { berry::IWorkbenchWindowConfigurer::Pointer configurer = GetWindowConfigurer(); berry::IWorkbenchWindow::Pointer window = configurer->GetWindow(); berry::IEditorPart::Pointer activeEditor; berry::IWorkbenchPage::Pointer currentPage = window->GetActivePage(); berry::IPerspectiveDescriptor::Pointer persp; berry::IAdaptable* input = nullptr; if (currentPage) { activeEditor = currentPage->GetActiveEditor(); persp = currentPage->GetPerspective(); input = currentPage->GetInput(); } if (editorHidden) { activeEditor = nullptr; } // Nothing to do if the editor hasn't changed if (activeEditor == lastActiveEditor.Lock() && currentPage == lastActivePage.Lock() && persp == lastPerspective.Lock() && input == lastInput) { return; } auto lockedLastActiveEditor = lastActiveEditor.Lock(); if (lockedLastActiveEditor.IsNotNull()) { lockedLastActiveEditor->RemovePropertyListener(editorPropertyListener.data()); } lastActiveEditor = activeEditor; lastActivePage = currentPage; lastPerspective = persp; lastInput = input; if (activeEditor) { activeEditor->AddPropertyListener(editorPropertyListener.data()); } RecomputeTitle(); } void QmitkFlowApplicationWorkbenchWindowAdvisor::PropertyChange(const berry::Object::Pointer& /*source*/, int propId) { if (propId == berry::IWorkbenchPartConstants::PROP_TITLE) { auto lockedLastActiveEditor = lastActiveEditor.Lock(); if (lockedLastActiveEditor.IsNotNull()) { QString newTitle = lockedLastActiveEditor->GetPartName(); if (lastEditorTitle != newTitle) { RecomputeTitle(); } } } } void QmitkFlowApplicationWorkbenchWindowAdvisor::SetPerspectiveExcludeList(const QList& v) { this->perspectiveExcludeList = v; } QList QmitkFlowApplicationWorkbenchWindowAdvisor::GetPerspectiveExcludeList() { return this->perspectiveExcludeList; } void QmitkFlowApplicationWorkbenchWindowAdvisor::SetViewExcludeList(const QList& v) { this->viewExcludeList = v; } QList QmitkFlowApplicationWorkbenchWindowAdvisor::GetViewExcludeList() { return this->viewExcludeList; } void QmitkFlowApplicationWorkbenchWindowAdvisor::PostWindowClose() { berry::IWorkbenchWindow::Pointer window = this->GetWindowConfigurer()->GetWindow(); QMainWindow* mainWindow = static_cast (window->GetShell()->GetControl()); QSettings settings(GetQSettingsFile(), QSettings::IniFormat); settings.setValue("ToolbarPosition", mainWindow->saveState()); } QString QmitkFlowApplicationWorkbenchWindowAdvisor::GetQSettingsFile() const { QFileInfo settingsInfo = QmitkFlowApplicationPlugin::GetDefault()->GetPluginContext()->getDataFile(QT_SETTINGS_FILENAME); return settingsInfo.canonicalFilePath(); } //-------------------------------------------------------------------------------- // Ugly hack from here on. Feel free to delete when command framework // and undo buttons are done. //-------------------------------------------------------------------------------- QmitkFlowApplicationWorkbenchWindowAdvisorHack::QmitkFlowApplicationWorkbenchWindowAdvisorHack() : QObject() { } QmitkFlowApplicationWorkbenchWindowAdvisorHack::~QmitkFlowApplicationWorkbenchWindowAdvisorHack() { } void QmitkFlowApplicationWorkbenchWindowAdvisorHack::onUndo() { mitk::UndoModel* model = mitk::UndoController::GetCurrentUndoModel(); if (model) { if (mitk::VerboseLimitedLinearUndo* verboseundo = dynamic_cast(model)) { mitk::VerboseLimitedLinearUndo::StackDescription descriptions = verboseundo->GetUndoDescriptions(); if (descriptions.size() >= 1) { MITK_INFO << "Undo " << descriptions.front().second; } } model->Undo(); } else { MITK_ERROR << "No undo model instantiated"; } } void QmitkFlowApplicationWorkbenchWindowAdvisorHack::onRedo() { mitk::UndoModel* model = mitk::UndoController::GetCurrentUndoModel(); if (model) { if (mitk::VerboseLimitedLinearUndo* verboseundo = dynamic_cast(model)) { mitk::VerboseLimitedLinearUndo::StackDescription descriptions = verboseundo->GetRedoDescriptions(); if (descriptions.size() >= 1) { MITK_INFO << "Redo " << descriptions.front().second; } } model->Redo(); } else { MITK_ERROR << "No undo model instantiated"; } } // safe calls to the complete chain // berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage()->FindView("org.mitk.views.imagenavigator"); // to cover for all possible cases of closed pages etc. static void SafeHandleNavigatorView(QString view_query_name) { berry::IWorkbench* wbench = berry::PlatformUI::GetWorkbench(); if (wbench == nullptr) return; berry::IWorkbenchWindow::Pointer wbench_window = wbench->GetActiveWorkbenchWindow(); if (wbench_window.IsNull()) return; berry::IWorkbenchPage::Pointer wbench_page = wbench_window->GetActivePage(); if (wbench_page.IsNull()) return; auto wbench_view = wbench_page->FindView(view_query_name); if (wbench_view.IsNotNull()) { bool isViewVisible = wbench_page->IsPartVisible(wbench_view); if (isViewVisible) { wbench_page->HideView(wbench_view); return; } } wbench_page->ShowView(view_query_name); } void QmitkFlowApplicationWorkbenchWindowAdvisorHack::onImageNavigator() { // show/hide ImageNavigatorView SafeHandleNavigatorView("org.mitk.views.imagenavigator"); } void QmitkFlowApplicationWorkbenchWindowAdvisorHack::onEditPreferences() { QmitkPreferencesDialog _PreferencesDialog(QApplication::activeWindow()); _PreferencesDialog.exec(); } void QmitkFlowApplicationWorkbenchWindowAdvisorHack::onQuit() { berry::PlatformUI::GetWorkbench()->Close(); } void QmitkFlowApplicationWorkbenchWindowAdvisorHack::onResetPerspective() { berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage()->ResetPerspective(); } void QmitkFlowApplicationWorkbenchWindowAdvisorHack::onClosePerspective() { berry::IWorkbenchPage::Pointer page = berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage(); page->ClosePerspective(page->GetPerspective(), true, true); } void QmitkFlowApplicationWorkbenchWindowAdvisorHack::onIntro() { bool hasIntro = berry::PlatformUI::GetWorkbench()->GetIntroManager()->HasIntro(); if (!hasIntro) { QRegExp reg("(.*)(\\n)*"); QRegExp reg2("(\\n)*(.*)"); QFile file(":/org.mitk.gui.qt.ext/index.html"); file.open(QIODevice::ReadOnly | QIODevice::Text); //text file only for reading QString text = QString(file.readAll()); file.close(); QString title = text; title.replace(reg, ""); title.replace(reg2, ""); std::cout << title.toStdString() << std::endl; QMessageBox::information(nullptr, title, text, "Close"); } else { berry::PlatformUI::GetWorkbench()->GetIntroManager()->ShowIntro( berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow(), false); } } void QmitkFlowApplicationWorkbenchWindowAdvisorHack::onHelp() { ctkPluginContext* context = QmitkFlowApplicationPlugin::GetDefault()->GetPluginContext(); if (context == nullptr) { MITK_WARN << "Plugin context not set, unable to open context help"; return; } // Check if the org.blueberry.ui.qt.help plug-in is installed and started QList > plugins = context->getPlugins(); foreach(QSharedPointer p, plugins) { if (p->getSymbolicName() == "org.blueberry.ui.qt.help") { if (p->getState() != ctkPlugin::ACTIVE) { // try to activate the plug-in explicitly try { p->start(ctkPlugin::START_TRANSIENT); } catch (const ctkPluginException& pe) { MITK_ERROR << "Activating org.blueberry.ui.qt.help failed: " << pe.what(); return; } } } } ctkServiceReference eventAdminRef = context->getServiceReference(); ctkEventAdmin* eventAdmin = nullptr; if (eventAdminRef) { eventAdmin = context->getService(eventAdminRef); } if (eventAdmin == nullptr) { MITK_WARN << "ctkEventAdmin service not found. Unable to open context help"; } else { ctkEvent ev("org/blueberry/ui/help/CONTEXTHELP_REQUESTED"); eventAdmin->postEvent(ev); } } void QmitkFlowApplicationWorkbenchWindowAdvisorHack::onHelpOpenHelpPerspective() { berry::PlatformUI::GetWorkbench()->ShowPerspective("org.blueberry.perspectives.help", berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()); } void QmitkFlowApplicationWorkbenchWindowAdvisorHack::onAbout() { auto aboutDialog = new QmitkAboutDialog(QApplication::activeWindow(), nullptr); aboutDialog->open(); }