diff --git a/Plugins/org.blueberry.ui.qt/resources/darkstyle.qss b/Plugins/org.blueberry.ui.qt/resources/darkstyle.qss index f2b1f818d3..c064d49846 100644 --- a/Plugins/org.blueberry.ui.qt/resources/darkstyle.qss +++ b/Plugins/org.blueberry.ui.qt/resources/darkstyle.qss @@ -1,614 +1,622 @@ /*============================================================================ 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. ============================================================================*/ /* iconColor = #c7c7c7 <- This line is parsed by MITK iconAccentColor = #d4821e <- This line is parsed by MITK */ font.warning { color: #ff5c33; font-weight: bold; } font.normal { color: #f1f1f1; } font.highlight { color: #d4821e; } font.disabled { color: #656565; } QWidget { background-color: #2d2d30; border: none; color: #f1f1f1; } QWidget:disabled { background-color: #2d2d30; border-color: #434346; color: #656565; } QStackedWidget { background-color: transparent; } QAbstractButton:hover, QComboBox:hover, QLineEdit:hover, QAbstractSpinBox:hover { background-color: #3f3f46; } QAbstractButton:pressed, QAbstractButton:checked { background-color: #434346; } QPushButton { border: 1px solid #3f3f46; padding: 4px 8px; } QPushButton:pressed { border: 1px solid #434346; } QPushButton:checked, QToolButton:checked { border: 1px solid #007acc; } QToolButton { padding: 2px; } QToolBar QToolButton { padding: 4px; } QToolButton#qt_toolbar_ext_button { background-color: transparent; border: none; min-width: 12px; max-width: 12px; padding: 0; qproperty-icon: url(:/org.blueberry.ui.qt/dark/tight-right-arrow-textcolor.svg); } QToolBox::tab { border: 1px solid #3f3f46; } QToolBox::tab:hover { background-color: #434346; } QToolBox::tab:selected { background-color: #1c97ea; border: 1px solid #1c97ea; } QAbstractItemView { alternate-background-color: #1b1b1c; background-color: #252526; } +QAbstractItemView:disabled { + background-color: #1b1b1c; +} + QAbstractItemView::item { color: #f1f1f1; } QAbstractItemView::item:selected { background-color: #1c97ea; } +QAbstractItemView::item:disabled { + color: #656565; +} + QHeaderView::section { background-color: #2d2d30; border: 1px solid transparent; } QHeaderView::section:horizontal { border-right: 1px solid #3f3f46; } QHeaderView::section:vertical { border-bottom: 1px solid #3f3f46; } QHeaderView::section:vertical:checked { background-color: #1c97ea; } QHeaderView::section:vertical:pressed { background-color: #1c97ea; font-weight: bold; } QHeaderView::down-arrow { image: url(:/org.blueberry.ui.qt/dark/down-arrow.svg); height: 16px; width: 16px; } QHeaderView::down-arrow:hover { image: url(:/org.blueberry.ui.qt/dark/down-arrow-hover.svg); } QHeaderView::down-arrow:pressed { image: url(:/org.blueberry.ui.qt/dark/down-arrow-pressed.svg); } QHeaderView::up-arrow { image: url(:/org.blueberry.ui.qt/dark/up-arrow.svg); height: 16px; width: 16px; } QHeaderView::up-arrow:hover { image: url(:/org.blueberry.ui.qt/dark/up-arrow-hover.svg); } QHeaderView::up-arrow:pressed { image: url(:/org.blueberry.ui.qt/dark/up-arrow-pressed.svg); } QGroupBox { border: 1px solid #434346; margin-top: 8px; padding-top: 8px; } QGroupBox, QGroupBox:disabled { background-color: #252526; } QGroupBox::title { padding: 0 4px; subcontrol-origin: margin; subcontrol-position: top center; } QComboBox, QLineEdit, QAbstractSpinBox { background-color: #333337; border: 1px solid #434346; } QComboBox QAbstractItemView { border: 1px solid #333337; selection-background-color: #3f3f46; } QComboBox::drop-down { image: url(:/org.blueberry.ui.qt/dark/down-arrow.svg); subcontrol-origin: margin; subcontrol-position: right; width: 12px; } QComboBox::drop-down:hover { background-color: #1f1f20; border-left: 1px solid #007acc; image: url(:/org.blueberry.ui.qt/dark/down-arrow-pressed.svg); } QAbstractSpinBox::up-button, QAbstractSpinBox::down-button { background-color: transparent; border: none; height: 9px; } QAbstractSpinBox::up-button:hover, QAbstractSpinBox::down-button:hover { background-color: #1f1f20; } QAbstractSpinBox::up-arrow { image: url(:/org.blueberry.ui.qt/dark/tight-up-arrow.svg); } QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off { image: url(:/org.blueberry.ui.qt/dark/tight-up-arrow-disabled.svg); } QAbstractSpinBox::up-arrow:hover { image: url(:/org.blueberry.ui.qt/dark/tight-up-arrow-hover.svg); } QAbstractSpinBox::up-arrow:pressed { image: url(:/org.blueberry.ui.qt/dark/tight-up-arrow-pressed.svg); } QAbstractSpinBox::down-arrow { image: url(:/org.blueberry.ui.qt/dark/tight-down-arrow.svg); } QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off { image: url(:/org.blueberry.ui.qt/dark/tight-down-arrow-disabled.svg); } QAbstractSpinBox::down-arrow:hover { image: url(:/org.blueberry.ui.qt/dark/tight-down-arrow-hover.svg); } QAbstractSpinBox::down-arrow:pressed { image: url(:/org.blueberry.ui.qt/dark/tight-down-arrow-pressed.svg); } QCheckBox, QCheckBox:hover, QCheckBox:disabled, QCheckBox:checked, QRadioButton, QRadioButton:hover, QRadioButton:disabled, QRadioButton:checked { background-color: none; } QCheckBox::indicator, QRadioButton::indicator { height: 13px; width: 13px; } QCheckBox::indicator:unchecked { image: url(:/org.blueberry.ui.qt/dark/checkbox-unchecked.svg); } QCheckBox::indicator:unchecked:hover { image: url(:/org.blueberry.ui.qt/dark/checkbox-unchecked-hover.svg); } QCheckBox::indicator:unchecked:disabled { image: url(:/org.blueberry.ui.qt/dark/checkbox-unchecked-disabled.svg); } QCheckBox::indicator:checked { image: url(:/org.blueberry.ui.qt/dark/checkbox-checked.svg); } QCheckBox::indicator:checked:hover { image: url(:/org.blueberry.ui.qt/dark/checkbox-checked-hover.svg); } QCheckBox::indicator:checked:disabled { image: url(:/org.blueberry.ui.qt/dark/checkbox-checked-disabled.svg); } QRadioButton::indicator:unchecked { image: url(:/org.blueberry.ui.qt/dark/radiobutton-unchecked.svg); } QRadioButton::indicator:unchecked:hover { image: url(:/org.blueberry.ui.qt/dark/radiobutton-unchecked-hover.svg); } QRadioButton::indicator:unchecked:disabled { image: url(:/org.blueberry.ui.qt/dark/radiobutton-unchecked-disabled.svg); } QRadioButton::indicator:checked { image: url(:/org.blueberry.ui.qt/dark/radiobutton-checked.svg); } QRadioButton::indicator:checked:hover { image: url(:/org.blueberry.ui.qt/dark/radiobutton-checked-hover.svg); } QRadioButton::indicator:checked:disabled { image: url(:/org.blueberry.ui.qt/dark/radiobutton-checked-disabled.svg); } QSlider::groove { background-color: #686868; } QSlider::groove:hover { background-color: #9e9e9e; } QSlider::groove:horizontal { height: 3px; } QSlider::groove:vertical { width: 3px; } QSlider::handle { background-color: #686868; } QSlider::handle:hover { background-color: #1c97ea; } QSlider::handle:pressed { background-color: #007acc; } QSlider::handle:horizontal { margin: -8px 0; width: 8px; } QSlider::handle::vertical { margin: 0 -8px; height: 8px; } QLineEdit:hover { border: 1px solid #2b7de1; } QLabel, QLabel:disabled { background-color: none; } QMenu { border: 1px solid #3e3e40; } QMenu QWidget { background-color: #1b1b1c; } QMenu::item { background-color: #1b1b1c; } QMenu::item:selected { background-color: #333334; } QMenu::separator { height: 1px; background-color: #3e3e40; } QMenuBar::item:selected { background-color: #3e3e40; } QScrollBar { background-color: #3e3e42; } QScrollBar:horizontal { height: 18px; margin: 0 18px 0 18px; } QScrollBar:vertical { width: 18px; margin: 18px 0 18px 0; } QScrollBar::handle { background-color: #686868; } QScrollBar::handle:hover { background-color: #9e9e9e; } QScrollBar::handle:pressed { background-color: #efebef; } QScrollBar::handle:horizontal { min-width: 18px; margin: 4px 0 5px 0; } QScrollBar::handle:vertical { min-height: 18px; margin: 0 5px 0 4px; } QScrollBar::add-page, QScrollBar::sub-page { background-color: none; } QScrollBar::add-line, QScrollBar::sub-line { background-color: #3e3e42; subcontrol-origin: margin; } QScrollBar::add-line:horizontal { subcontrol-position: right; width: 18px; } QScrollBar::sub-line:horizontal { subcontrol-position: left; width: 18px; } QScrollBar::add-line:vertical { subcontrol-position: bottom; height: 18px; } QScrollBar::sub-line:vertical { subcontrol-position: top; height: 18px; } QScrollBar::up-arrow, QScrollBar::right-arrow, QScrollBar:down-arrow, QScrollBar:left-arrow { width: 18px; height: 18px; } QScrollBar::down-arrow { image: url(:/org.blueberry.ui.qt/dark/down-arrow.svg); } QScrollBar::down-arrow:disabled { image: url(:/org.blueberry.ui.qt/dark/down-arrow-disabled.svg); } QScrollBar::down-arrow:hover { image: url(:/org.blueberry.ui.qt/dark/down-arrow-hover.svg); } QScrollBar::down-arrow:pressed { image: url(:/org.blueberry.ui.qt/dark/down-arrow-pressed.svg); } QScrollBar::left-arrow { image: url(:/org.blueberry.ui.qt/dark/left-arrow.svg); } QScrollBar::left-arrow:disabled { image: url(:/org.blueberry.ui.qt/dark/left-arrow-disabled.svg); } QScrollBar::left-arrow:hover { image: url(:/org.blueberry.ui.qt/dark/left-arrow-hover.svg); } QScrollBar::left-arrow:pressed { image: url(:/org.blueberry.ui.qt/dark/left-arrow-pressed.svg); } QScrollBar::right-arrow { image: url(:/org.blueberry.ui.qt/dark/right-arrow.svg); } QScrollBar::right-arrow:disabled { image: url(:/org.blueberry.ui.qt/dark/right-arrow-disabled.svg); } QScrollBar::right-arrow:hover { image: url(:/org.blueberry.ui.qt/dark/right-arrow-hover.svg); } QScrollBar::right-arrow:pressed { image: url(:/org.blueberry.ui.qt/dark/right-arrow-pressed.svg); } QScrollBar::up-arrow { image: url(:/org.blueberry.ui.qt/dark/up-arrow.svg); } QScrollBar::up-arrow:disabled { image: url(:/org.blueberry.ui.qt/dark/up-arrow-disabled.svg); } QScrollBar::up-arrow:hover { image: url(:/org.blueberry.ui.qt/dark/up-arrow-hover.svg); } QScrollBar::up-arrow:pressed { image: url(:/org.blueberry.ui.qt/dark/up-arrow-pressed.svg); } QTabWidget::pane { border: 1px solid #434346; } QTabBar::tab { background-color: #434346; border: 1px solid #434346; border-bottom: none; padding: 4px; } QTabBar::tab:middle { border-left: none; } QTabBar::tab:last { border-left: none; } QTabBar::tab:next-selected { border-right: none; } QTabBar::tab:selected { border: 1px solid #434346; border-bottom: none; } QTabBar::tab:!selected { background-color: #2d2d30; } QTabBar::tab:!selected:hover { background-color: #434346; } #TabCloseButton { background-color: none; } QTabBar QToolButton::left-arrow { image: url(:/org.blueberry.ui.qt/dark/tight-left-arrow.svg); } QTabBar QToolButton::left-arrow:hover { image: url(:/org.blueberry.ui.qt/dark/tight-left-arrow-hover.svg); } QTabBar QToolButton::left-arrow:pressed { image: url(:/org.blueberry.ui.qt/dark/tight-left-arrow-pressed.svg); } QTabBar QToolButton::left-arrow:disabled { image: url(:/org.blueberry.ui.qt/dark/tight-left-arrow-disabled.svg); } QTabBar QToolButton::right-arrow { image: url(:/org.blueberry.ui.qt/dark/tight-right-arrow.svg); } QTabBar QToolButton::right-arrow:hover { image: url(:/org.blueberry.ui.qt/dark/tight-right-arrow-hover.svg); } QTabBar QToolButton::right-arrow:pressed { image: url(:/org.blueberry.ui.qt/dark/tight-right-arrow-pressed.svg); } QTabBar QToolButton::right-arrow:disabled { image: url(:/org.blueberry.ui.qt/dark/tight-right-arrow-disabled.svg); } QTreeView::branch:closed:has-children:has-siblings, QTreeView::branch:closed:has-children:!has-siblings { image: url(:/org.blueberry.ui.qt/dark/right-arrow.svg); } QTreeView::branch:closed:has-children:has-siblings:hover, QTreeView::branch:closed:has-children:!has-siblings:hover { image: url(:/org.blueberry.ui.qt/dark/right-arrow-hover.svg); } QTreeView::branch:open:has-children:has-siblings, QTreeView::branch:open:has-children:!has-siblings { image: url(:/org.blueberry.ui.qt/dark/down-arrow.svg); } QTreeView::branch:open:has-children:has-siblings:hover, QTreeView::branch:open:has-children:!has-siblings:hover { image: url(:/org.blueberry.ui.qt/dark/down-arrow-hover.svg); } QTreeView::indicator:unchecked { image: url(:/org.blueberry.ui.qt/dark/checkbox-unchecked.svg); } QTreeView::indicator:unchecked:selected { image: url(:/org.blueberry.ui.qt/dark/checkbox-unchecked-selected.svg); } QTreeView::indicator:checked, QTreeView::indicator:indeterminate { image: url(:/org.blueberry.ui.qt/dark/checkbox-checked.svg); } QTreeView::indicator:checked:selected, QTreeView::indicator:indeterminate:selected { image: url(:/org.blueberry.ui.qt/dark/checkbox-checked-selected.svg); } diff --git a/Plugins/org.blueberry.ui.qt/src/berryIViewRegistry.h b/Plugins/org.blueberry.ui.qt/src/berryIViewRegistry.h index 0ee69890b1..7880a457ff 100644 --- a/Plugins/org.blueberry.ui.qt/src/berryIViewRegistry.h +++ b/Plugins/org.blueberry.ui.qt/src/berryIViewRegistry.h @@ -1,79 +1,90 @@ /*============================================================================ 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 BERRYIVIEWREGISTRY_H_ #define BERRYIVIEWREGISTRY_H_ #include #include "berryIViewDescriptor.h" #include "berryIViewCategory.h" #include "berryIStickyViewDescriptor.h" namespace berry { /** * \ingroup org_blueberry_ui_qt * * The view registry maintains a list of views explicitly registered * against the view extension point. *

* The description of a given view is kept in a IViewDescriptor. *

*

* This interface is not intended to be implemented by clients. *

* * @see IViewDescriptor * @see IStickyViewDescriptor */ struct BERRY_UI_QT IViewRegistry { /** * Return a view descriptor with the given extension id. If no view exists * with the id return null. * Will also return null if the view descriptor exists, but * is filtered by an expression-based activity. * * @param id the id to search for * @return the descriptor or null */ virtual IViewDescriptor::Pointer Find(const QString& id) const = 0; /** * Returns an array of view categories. * * @return the categories. */ virtual QList GetCategories() = 0; /** * Return a list of views defined in the registry. * * @return the views. */ virtual QList GetViews() const = 0; + /** + * @brief Get views as multi map with categories as keys. + * + * Exclude views without category and categories that contain a literal '.', e.g. + * "org.blueberry.ui" or "org.mitk.views.general", as they typically do not have + * a corresponding tool bar. + * + * @return the views by category as described above. + */ + virtual QMultiMap GetViewsByCategory() const = 0; + /** * Return a list of sticky views defined in the registry. * * @return the sticky views. Never null. */ virtual QList GetStickyViews() const = 0; virtual ~IViewRegistry(); }; } #endif /*BERRYIVIEWREGISTRY_H_*/ diff --git a/Plugins/org.blueberry.ui.qt/src/berryIWorkbenchWindow.h b/Plugins/org.blueberry.ui.qt/src/berryIWorkbenchWindow.h index 1a475db25a..33cb3c6ca9 100644 --- a/Plugins/org.blueberry.ui.qt/src/berryIWorkbenchWindow.h +++ b/Plugins/org.blueberry.ui.qt/src/berryIWorkbenchWindow.h @@ -1,196 +1,203 @@ /*============================================================================ 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 BERRYIWORKBENCHWINDOW_H_ #define BERRYIWORKBENCHWINDOW_H_ #include #include #include #include "berryIPageService.h" #include "berryShell.h" #include "services/berryIServiceLocator.h" +#include + namespace berry { struct IPartService; struct ISelectionService; struct IWorkbenchPage; struct IWorkbench; /** * \ingroup org_blueberry_ui_qt * * A workbench window is a top level window in a workbench. Visually, a * workbench window has a menubar, a toolbar, a status bar, and a main area for * displaying a single page consisting of a collection of views and editors. *

* Each workbench window has a collection of 0 or more pages; the active page is * the one that is being presented to the end user; at most one page is active * in a window at a time. *

*

* The workbench window supports a few services by default. * If these services are used to allocate resources, it is important to * remember to clean up those resources after you are done with them. Otherwise, * the resources will exist until the workbench window is closed. The supported * services are: *

*
    *
  • {@link ICommandService}
  • *
  • {@link IContextService}
  • *
*

* This interface is not intended to be implemented by clients. *

* * @see IWorkbenchPage * */ struct BERRY_UI_QT IWorkbenchWindow : public IPageService, public IServiceLocator /** \cond */, public virtual Object /** \endcond */ { berryObjectMacro(berry::IWorkbenchWindow, IPageService, IServiceLocator, Object); /** * Closes this workbench window. *

* If the window has an open editor with unsaved content, the user will be * given the opportunity to save it. *

* * @return true if the window was successfully closed, and * false if it is still open */ virtual bool Close() = 0; /** * Returns a list of the pages in this workbench window. *

* Note that each window has its own pages; pages are never shared between * different windows. *

* * @return a list of pages */ virtual QList > GetPages() const = 0; /** * Returns the currently active page for this workbench window. * * @return the active page, or null if none */ SmartPointer GetActivePage() const override = 0; /** * Sets or clears the currently active page for this workbench window. * * @param page * the new active page */ virtual void SetActivePage(SmartPointer page) = 0; /** * Returns the part service which tracks part activation within this * workbench window. * * @return the part service */ virtual IPartService* GetPartService() = 0; /** * Returns the selection service which tracks selection within this * workbench window. * * @return the selection service */ virtual ISelectionService* GetSelectionService() const = 0; /** * Returns this workbench window's shell. * * @return the shell containing this window's controls or null * if the shell has not been created yet or if the window has been closed */ virtual Shell::Pointer GetShell() const = 0; /** * Returns the workbench for this window. * * @return the workbench */ virtual IWorkbench* GetWorkbench() const = 0; + /** + * Returns all tool bars for this window. + */ + virtual QList GetToolBars() const = 0; + /** * Creates and opens a new workbench page. The perspective of the new page * is defined by the specified perspective ID. The new page become active. *

* Note: Since release 2.0, a window is limited to contain at most * one page. If a page exist in the window when this method is used, then * another window is created for the new page. Callers are strongly * recommended to use the IWorkbench.showPerspective APIs to * programmatically show a perspective. *

* * @param perspectiveId * the perspective id for the window's initial page * @param input * the page input, or null if there is no current * input. This is used to seed the input for the new page's * views. * @return the new workbench page * @exception WorkbenchException * if a page could not be opened * * @see IWorkbench#showPerspective(String, IWorkbenchWindow, IAdaptable) */ virtual SmartPointer OpenPage(const QString& perspectiveId, IAdaptable* input) = 0; /** * Creates and opens a new workbench page. The default perspective is used * as a template for creating the page. The page becomes active. *

* Note: Since release 2.0, a window is limited to contain at most * one page. If a page exist in the window when this method is used, then * another window is created for the new page. Callers are strongly * recommended to use the IWorkbench.showPerspective APIs to * programmatically show a perspective. *

* * @param input * the page input, or null if there is no current * input. This is used to seed the input for the new page's * views. * @return the new workbench window * @exception WorkbenchException * if a page could not be opened * * @see IWorkbench#showPerspective(String, IWorkbenchWindow, IAdaptable) */ virtual SmartPointer OpenPage(IAdaptable* input) = 0; //virtual void SetPerspectiveExcludeList(const QStringList& v) = 0; //virtual QStringList GetPerspectiveExcludeList() const = 0; //virtual void SetViewExcludeList(const QStringList& v) = 0; //virtual QStringList GetViewExcludeList() const = 0; ~IWorkbenchWindow() override; }; } #endif /*BERRYIWORKBENCHWINDOW_H_*/ diff --git a/Plugins/org.blueberry.ui.qt/src/internal/berryViewRegistry.cpp b/Plugins/org.blueberry.ui.qt/src/internal/berryViewRegistry.cpp index 309967e985..f2c7fa7e78 100644 --- a/Plugins/org.blueberry.ui.qt/src/internal/berryViewRegistry.cpp +++ b/Plugins/org.blueberry.ui.qt/src/internal/berryViewRegistry.cpp @@ -1,281 +1,301 @@ /*============================================================================ 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 "berryViewRegistry.h" #include "berryPlatformUI.h" #include "berryWorkbenchPlugin.h" #include "berryWorkbenchRegistryConstants.h" #include "berryPlatform.h" namespace berry { ViewRegistry::ViewCategoryProxy::ViewCategoryProxy( IViewDescriptorCategoryPtr rawCategory) : rawCategory(rawCategory) { } QList ViewRegistry::ViewCategoryProxy::GetViews() const { return rawCategory->GetElements(); } QString ViewRegistry::ViewCategoryProxy::GetId() const { return rawCategory->GetId(); } QStringList ViewRegistry::ViewCategoryProxy::GetPath() const { QList path; QString rawParentPath = rawCategory->GetRawParentPath(); // nested categories are not supported yet // assume an empty raw parent path path.push_back(rawParentPath); return path; } QString ViewRegistry::ViewCategoryProxy::GetLabel() const { return rawCategory->GetLabel(); } QString ViewRegistry::ViewCategoryProxy::GetLocalId() const { return GetId(); } QString ViewRegistry::ViewCategoryProxy::GetPluginId() const { return rawCategory->GetPluginId(); } bool ViewRegistry::ViewCategoryProxy::operator==(const Object* o) const { if (const IViewCategory* other = dynamic_cast(o)) return this->GetId() == other->GetId(); return false; } uint ViewRegistry::ViewCategoryProxy::HashCode() const { return qHash(GetId()); } QString ViewRegistry::EXTENSIONPOINT_UNIQUE_ID = "org.blueberry.ui.views"; // PlatformUI::PLUGIN_ID + "." + WorkbenchRegistryConstants::PL_VIEWS; Category::Pointer ViewRegistry::InternalFindCategory(const QString& id) { for (QList::iterator itr = categories.begin(); itr != categories.end(); ++itr) { if (id == (*itr)->GetRootPath()) { return *itr; } } return IViewDescriptorCategoryPtr(nullptr); } IExtensionPoint::Pointer ViewRegistry::GetExtensionPointFilter() { return Platform::GetExtensionRegistry()->GetExtensionPoint(EXTENSIONPOINT_UNIQUE_ID); } const QString ViewRegistry::TAG_DESCRIPTION = "description"; ViewRegistry::ViewRegistry() : dirtyViewCategoryMappings(true) { miscCategory = new IViewDescriptorCategory(); this->Add(miscCategory); //PlatformUI.getWorkbench().getExtensionTracker().registerHandler(this, // ExtensionTracker.createExtensionPointFilter(getExtensionPointFilter())); reader.ReadViews(Platform::GetExtensionRegistry(), this); } void ViewRegistry::Add(IViewDescriptorCategoryPtr desc) { /* fix for 1877 */ if (this->InternalFindCategory(desc->GetId()).IsNull()) { dirtyViewCategoryMappings = true; // Mark categories list as dirty categories.push_back(desc); // IConfigurationElement::Pointer element( // dynamic_cast( // desc->GetAdapter(typeid(IConfigurationElement)) // )); // if (element.IsNull()) // { // return; // } // PlatformUI::GetWorkbench()->GetExtensionTracker() // .registerObject(element->GetDeclaringExtension(), desc, // IExtensionTracker::REF_WEAK); } } void ViewRegistry::Add(ViewDescriptor::Pointer desc) { for (QList::const_iterator itr = views.begin(); itr != views.end(); ++itr) { if (desc.GetPointer() == itr->GetPointer()) return; } views.push_back(desc); dirtyViewCategoryMappings = true; //desc.activateHandler(); } void ViewRegistry::Add(StickyViewDescriptor::Pointer desc) { if (std::find(sticky.begin(), sticky.end(), desc) == sticky.end()) { sticky.push_back(desc); // PlatformUI::GetWorkbench()->GetExtensionTracker() // .registerObject(desc.getConfigurationElement().getDeclaringExtension(), // desc, IExtensionTracker.REF_WEAK); } } IViewDescriptor::Pointer ViewRegistry::Find(const QString& id) const { for (QList::const_iterator itr = views.begin(); itr != views.end(); ++itr) { if (id == (*itr)->GetId()) { return *itr; } } return IViewDescriptor::Pointer(nullptr); } IViewCategory::Pointer ViewRegistry::FindCategory(const QString& id) { this->MapViewsToCategories(); IViewDescriptorCategoryPtr category(this->InternalFindCategory(id)); if (category.IsNull()) { return IViewCategory::Pointer(nullptr); } IViewCategory::Pointer cat(new ViewCategoryProxy(category)); return cat; } QList ViewRegistry::GetCategories() { this->MapViewsToCategories(); QList retArray; for (QList::iterator itr = categories.begin(); itr != categories.end(); ++itr) { retArray.push_back(IViewCategory::Pointer(new ViewCategoryProxy(*itr))); } return retArray; } QList ViewRegistry::GetStickyViews() const { return sticky; } Category::Pointer ViewRegistry::GetMiscCategory() const { return miscCategory; } QList ViewRegistry::GetViews() const { return views; } +QMultiMap ViewRegistry::GetViewsByCategory() const +{ + QMultiMap result; + + const auto views = this->GetViews(); + + for (auto view : views) + { + QString category; + + if (auto categoryPath = view->GetCategoryPath(); !categoryPath.isEmpty()) + category = categoryPath.back(); + + if (!category.isEmpty() && !category.contains('.') && !view->IsInternal()) + result.insert(category, view); + } + + return result; +} + void ViewRegistry::MapViewsToCategories() { if (dirtyViewCategoryMappings) { dirtyViewCategoryMappings = false; // clear all category mappings for (QList::iterator i = categories.begin(); i != categories.end(); ++i) { (*i)->Clear(); // this is bad } miscCategory->Clear(); for (QList::iterator i = views.begin(); i != views.end(); ++i) { IViewDescriptor::Pointer desc(*i); IViewDescriptorCategoryPtr cat(nullptr); const QList& catPath = desc->GetCategoryPath(); if (catPath.size() > 0) { cat = this->InternalFindCategory(catPath[0]); } if (cat.IsNotNull()) { if (!cat->HasElement(desc)) { cat->AddElement(desc); } } else { if (catPath.size() > 0) { // If we get here, this view specified a category which // does not exist. Add this view to the 'Other' category // but give out a message (to the log only) indicating // this has been done. QString fmt("Category %1 not found for view %2. This view added to ''%3'' category."); WorkbenchPlugin::Log(fmt.arg(catPath[0]).arg(desc->GetId()).arg(miscCategory->GetLabel())); } miscCategory->AddElement(desc); } } } } //void ViewRegistry::AddExtension(IExtensionTracker tracker, // IExtension addedExtension) //{ // IConfigurationElement[] addedElements = addedExtension.getConfigurationElements(); // for (int i = 0; i < addedElements.length; i++) // { // IConfigurationElement element = addedElements[i]; // if (element.getName().equals(IWorkbenchRegistryConstants.TAG_VIEW)) // { // reader.readView(element); // } // else if (element.getName().equals(IWorkbenchRegistryConstants.TAG_CATEGORY)) // { // reader.readCategory(element); // } // else if (element.getName().equals(IWorkbenchRegistryConstants.TAG_STICKYVIEW)) // { // reader.readSticky(element); // } // } //} } // namespace berry diff --git a/Plugins/org.blueberry.ui.qt/src/internal/berryViewRegistry.h b/Plugins/org.blueberry.ui.qt/src/internal/berryViewRegistry.h index 91e010688b..161df4674b 100644 --- a/Plugins/org.blueberry.ui.qt/src/internal/berryViewRegistry.h +++ b/Plugins/org.blueberry.ui.qt/src/internal/berryViewRegistry.h @@ -1,227 +1,229 @@ /*============================================================================ 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 BERRYVIEWREGISTRY_H_ #define BERRYVIEWREGISTRY_H_ #include "berryIViewRegistry.h" #include "berryIViewCategory.h" #include "berryIViewDescriptor.h" #include "berryCategory.h" #include "berryViewDescriptor.h" #include "berryViewRegistryReader.h" #include "berryStickyViewDescriptor.h" #include "berryIExtensionPoint.h" namespace berry { /** * \ingroup org_blueberry_ui_internal * * The central manager for view descriptors. */ class ViewRegistry : public IViewRegistry { public: typedef Category IViewDescriptorCategory; typedef IViewDescriptorCategory::Pointer IViewDescriptorCategoryPtr; private: /** * Proxies a Category implementation. * */ class ViewCategoryProxy : public IViewCategory, public IPluginContribution { private: typedef Category IViewDescriptorCategory; IViewDescriptorCategoryPtr rawCategory; /** * Create a new instance of this class * * @param rawCategory the category */ public: ViewCategoryProxy(IViewDescriptorCategoryPtr rawCategory); /* * @see IViewCategory#GetViews() */ QList GetViews() const override; /* * @see IViewCategory#GetId() */ QString GetId() const override; /* * @see IViewCategory#GetPath() */ QStringList GetPath() const override; /* * @see IViewCategory#GetLabel() */ QString GetLabel() const override; /* * @see IPluginContribution#GetLocalId() */ QString GetLocalId() const override; /* * @see IPluginContribution#GetPluginId() */ QString GetPluginId() const override; /* * @see Object#operator==(Object*) */ bool operator==(const Object* o) const override; /* * @see Object#HashCode() */ uint HashCode() const override; }; private: static QString EXTENSIONPOINT_UNIQUE_ID; /** * A set that will only ever contain ViewDescriptors. */ QList views; // = new TreeSet(new Comparator() { // public int compare(Object o1, Object o2) { // String id1 = ((ViewDescriptor) o1).getId(); // String id2 = ((ViewDescriptor) o2).getId(); // // return id1.compareTo(id2); // }}); QList sticky; QList categories; IViewDescriptorCategoryPtr miscCategory; ViewRegistryReader reader; bool dirtyViewCategoryMappings; /** * Returns the category with no updating of the view/category mappings. * * @param id the category id * @return the Category * @since 3.1 */ IViewDescriptorCategoryPtr InternalFindCategory(const QString& id); SmartPointer GetExtensionPointFilter(); protected: static const QString TAG_DESCRIPTION; // = "description"; public: ViewRegistry(); /** * Add a category to the registry. * * @param desc the descriptor to add */ void Add(IViewDescriptorCategoryPtr desc); /** * Add a descriptor to the registry. * * @param desc the descriptor to add */ void Add(ViewDescriptor::Pointer desc); /** * Add a sticky descriptor to the registry. * * @param desc the descriptor to add */ void Add(StickyViewDescriptor::Pointer desc); /** * Find a descriptor in the registry. */ IViewDescriptor::Pointer Find(const QString& id) const override; /** * Find a category with a given name. * * @param id the id to search for * @return the category or null */ IViewCategory::Pointer FindCategory(const QString& id); /** * Get the list of view categories. */ QList GetCategories() override; /** * Get the list of sticky views minus the sticky views which failed the * Expressions check. */ QList GetStickyViews() const override; /** * Returns the Misc category. This may be null if there are * no miscellaneous views. * * @return the misc category or null */ IViewDescriptorCategoryPtr GetMiscCategory() const; /** * Get an enumeration of view descriptors. */ QList GetViews() const override; + QMultiMap GetViewsByCategory() const override; + /** * Adds each view in the registry to a particular category. * The view category may be defined in xml. If not, the view is * added to the "misc" category. */ void MapViewsToCategories(); /* (non-Javadoc) * @see org.blueberry.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.blueberry.core.runtime.dynamicHelpers.IExtensionTracker, org.blueberry.core.runtime.IExtension) */ //void AddExtension(IExtensionTracker tracker, IExtension addedExtension); }; } // namespace berry #endif /*BERRYVIEWREGISTRY_H_*/ diff --git a/Plugins/org.blueberry.ui.qt/src/internal/berryWorkbenchWindow.cpp b/Plugins/org.blueberry.ui.qt/src/internal/berryWorkbenchWindow.cpp index 5ed0e2a5e6..33c0584845 100644 --- a/Plugins/org.blueberry.ui.qt/src/internal/berryWorkbenchWindow.cpp +++ b/Plugins/org.blueberry.ui.qt/src/internal/berryWorkbenchWindow.cpp @@ -1,1936 +1,1955 @@ /*============================================================================ 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 "tweaklets/berryGuiWidgetsTweaklet.h" #include "tweaklets/berryWorkbenchTweaklet.h" #include "berryWorkbenchWindow.h" #include "berryIWorkbenchPage.h" #include "berryIPerspectiveDescriptor.h" #include "berryIContextService.h" #include "berryUIException.h" #include "berryConstants.h" #include "berryIMenuService.h" #include "berryMenuUtil.h" #include "intro/berryIntroConstants.h" #include "berryWorkbenchPlugin.h" #include "berryWorkbenchPage.h" #include "berryWorkbench.h" #include "berryWorkbenchConstants.h" #include "berryPartSite.h" #include "berryIServiceLocatorCreator.h" #include "berryMenuManager.h" #include "berryQActionProperties.h" #include "berryQtControlWidget.h" #include "berryQtPerspectiveSwitcher.h" #include "berryWWinActionBars.h" #include "berryWorkbenchLocationService.h" #include "berryIServiceFactory.h" #include "berryIServiceScopes.h" #include "berryIEvaluationReference.h" #include "berryPlatformUI.h" #include "berryDebugUtil.h" #include #include #include #include #include namespace berry { const QString WorkbenchWindow::PROP_TOOLBAR_VISIBLE = "toolbarVisible"; const QString WorkbenchWindow::PROP_PERSPECTIVEBAR_VISIBLE = "perspectiveBarVisible"; const QString WorkbenchWindow::PROP_STATUS_LINE_VISIBLE = "statusLineVisible"; const ActionBarAdvisor::FillFlags WorkbenchWindow::FILL_ALL_ACTION_BARS = ActionBarAdvisor::FILL_MENU_BAR | ActionBarAdvisor::FILL_TOOL_BAR | ActionBarAdvisor::FILL_STATUS_LINE; WorkbenchWindow::WorkbenchWindow(int number) : Window(Shell::Pointer(nullptr)) , pageComposite(nullptr) , windowAdvisor(nullptr) , actionBarAdvisor(nullptr) , number(number) , largeUpdates(0) , closing(false) , shellActivated(false) , updateDisabled(true) , toolBarVisible(true) , perspectiveBarVisible(true) , statusLineVisible(true) , emptyWindowContentsCreated(false) , emptyWindowContents(nullptr) , asMaximizedState(false) , partService(this) , serviceLocatorOwner(new ServiceLocatorOwner(this)) , resizeEventFilter(this) { this->Register(); // increase the reference count to avoid deleting // this object when temporary smart pointers // go out of scope // Make sure there is a workbench. This call will throw // an exception if workbench not created yet. IWorkbench* workbench = PlatformUI::GetWorkbench(); IServiceLocatorCreator* slc = workbench->GetService(); this->serviceLocator = slc->CreateServiceLocator( workbench, nullptr, IDisposable::WeakPtr(serviceLocatorOwner)).Cast(); InitializeDefaultServices(); // Add contribution managers that are exposed to other plugins. this->AddMenuBar(); //addCoolBar(SWT.NONE); // style is unused //addStatusLine(); this->FireWindowOpening(); // Fill the action bars this->FillActionBars(FILL_ALL_ACTION_BARS); this->UnRegister(false); // decrease reference count and avoid deleting // the window } WorkbenchWindow::~WorkbenchWindow() { // BERRY_INFO << "WorkbenchWindow::~WorkbenchWindow()"; } Object* WorkbenchWindow::GetService(const QString& key) { return serviceLocator->GetService(key); } bool WorkbenchWindow::HasService(const QString& key) const { return serviceLocator->HasService(key); } Shell::Pointer WorkbenchWindow::GetShell() const { return Window::GetShell(); } bool WorkbenchWindow::ClosePage(IWorkbenchPage::Pointer in, bool save) { // Validate the input. if (!pageList.Contains(in)) { return false; } WorkbenchPage::Pointer oldPage = in.Cast (); // Save old perspective. if (save && oldPage->IsSaveNeeded()) { if (!oldPage->SaveAllEditors(true)) { return false; } } // If old page is activate deactivate. bool oldIsActive = (oldPage == this->GetActivePage()); if (oldIsActive) { this->SetActivePage(IWorkbenchPage::Pointer(nullptr)); } // Close old page. pageList.Remove(oldPage); partService.PageClosed(oldPage); //this->FirePageClosed(oldPage); //oldPage->Dispose(); // Activate new page. if (oldIsActive) { IWorkbenchPage::Pointer newPage = pageList.GetNextActive(); if (newPage != 0) { this->SetActivePage(newPage); } } if (!closing && pageList.IsEmpty()) { this->ShowEmptyWindowContents(); } return true; } void WorkbenchWindow::AddPerspectiveListener(IPerspectiveListener* l) { perspectiveEvents.AddListener(l); } void WorkbenchWindow::RemovePerspectiveListener(IPerspectiveListener* l) { perspectiveEvents.RemoveListener(l); } IPerspectiveListener::Events& WorkbenchWindow::GetPerspectiveEvents() { return perspectiveEvents; } void WorkbenchWindow::FireWindowOpening() { // let the application do further configuration this->GetWindowAdvisor()->PreWindowOpen(); } void WorkbenchWindow::FireWindowRestored() { //StartupThreading.runWithWorkbenchExceptions(new StartupRunnable() { // public void runWithException() throws Throwable { this->GetWindowAdvisor()->PostWindowRestore(); // } //}); } void WorkbenchWindow::FireWindowCreated() { this->GetWindowAdvisor()->PostWindowCreate(); } void WorkbenchWindow::FireWindowOpened() { this->GetWorkbenchImpl()->FireWindowOpened(IWorkbenchWindow::Pointer(this)); this->GetWindowAdvisor()->PostWindowOpen(); } bool WorkbenchWindow::FireWindowShellClosing() { return this->GetWindowAdvisor()->PreWindowShellClose(); } void WorkbenchWindow::FireWindowClosed() { // let the application do further deconfiguration this->GetWindowAdvisor()->PostWindowClose(); this->GetWorkbenchImpl()->FireWindowClosed(IWorkbenchWindow::Pointer(this)); } ///** // * Fires page activated // */ //void WorkbenchWindow::FirePageActivated(IWorkbenchPage::Pointer page) { //// String label = null; // debugging only //// if (UIStats.isDebugging(UIStats.NOTIFY_PAGE_LISTENERS)) { //// label = "activated " + page.getLabel(); //$NON-NLS-1$ //// } //// try { //// UIStats.start(UIStats.NOTIFY_PAGE_LISTENERS, label); //// UIListenerLogging.logPageEvent(this, page, //// UIListenerLogging.WPE_PAGE_ACTIVATED); // pageEvents.FirePageActivated(page); // partService.pageActivated(page); //// } finally { //// UIStats.end(UIStats.NOTIFY_PAGE_LISTENERS, page.getLabel(), label); //// } //} // ///** // * Fires page closed // */ //void WorkbenchWindow::FirePageClosed(IWorkbenchPage::Pointer page) { // String label = null; // debugging only // if (UIStats.isDebugging(UIStats.NOTIFY_PAGE_LISTENERS)) { // label = "closed " + page.getLabel(); //$NON-NLS-1$ // } // try { // UIStats.start(UIStats.NOTIFY_PAGE_LISTENERS, label); // UIListenerLogging.logPageEvent(this, page, // UIListenerLogging.WPE_PAGE_CLOSED); // pageListeners.firePageClosed(page); // partService.pageClosed(page); // } finally { // UIStats.end(UIStats.NOTIFY_PAGE_LISTENERS, page.getLabel(), label); // } // //} // ///** // * Fires page opened // */ //void WorkbenchWindow::FirePageOpened(IWorkbenchPage::Pointer page) { // String label = null; // debugging only // if (UIStats.isDebugging(UIStats.NOTIFY_PAGE_LISTENERS)) { // label = "opened " + page.getLabel(); //$NON-NLS-1$ // } // try { // UIStats.start(UIStats.NOTIFY_PAGE_LISTENERS, label); // UIListenerLogging.logPageEvent(this, page, // UIListenerLogging.WPE_PAGE_OPENED); // pageListeners.firePageOpened(page); // partService.pageOpened(page); // } finally { // UIStats.end(UIStats.NOTIFY_PAGE_LISTENERS, page.getLabel(), label); // } //} void WorkbenchWindow::FirePerspectiveActivated(IWorkbenchPage::Pointer page, IPerspectiveDescriptor::Pointer perspective) { // UIListenerLogging.logPerspectiveEvent(this, page, perspective, // UIListenerLogging.PLE_PERSP_ACTIVATED); perspectiveEvents.perspectiveActivated(page, perspective); } void WorkbenchWindow::FirePerspectivePreDeactivate( IWorkbenchPage::Pointer page, IPerspectiveDescriptor::Pointer perspective) { // UIListenerLogging.logPerspectiveEvent(this, page, perspective, // UIListenerLogging.PLE_PERSP_PRE_DEACTIVATE); perspectiveEvents.perspectivePreDeactivate(page, perspective); } void WorkbenchWindow::FirePerspectiveDeactivated(IWorkbenchPage::Pointer page, IPerspectiveDescriptor::Pointer perspective) { // UIListenerLogging.logPerspectiveEvent(this, page, perspective, // UIListenerLogging.PLE_PERSP_DEACTIVATED); perspectiveEvents.perspectiveDeactivated(page, perspective); } void WorkbenchWindow::FirePerspectiveChanged(IWorkbenchPage::Pointer page, IPerspectiveDescriptor::Pointer perspective, const QString& changeId) { // Some callers call this even when there is no active perspective. // Just ignore this case. if (perspective != 0) { // UIListenerLogging.logPerspectiveChangedEvent(this, page, // perspective, null, changeId); perspectiveEvents.perspectiveChanged(page, perspective, changeId); } } void WorkbenchWindow::FirePerspectiveChanged(IWorkbenchPage::Pointer page, IPerspectiveDescriptor::Pointer perspective, IWorkbenchPartReference::Pointer partRef, const QString& changeId) { // Some callers call this even when there is no active perspective. // Just ignore this case. if (perspective != 0) { // UIListenerLogging.logPerspectiveChangedEvent(this, page, // perspective, partRef, changeId); perspectiveEvents.perspectivePartChanged(page, perspective, partRef, changeId); } } void WorkbenchWindow::FirePerspectiveClosed(IWorkbenchPage::Pointer page, IPerspectiveDescriptor::Pointer perspective) { // UIListenerLogging.logPerspectiveEvent(this, page, perspective, // UIListenerLogging.PLE_PERSP_CLOSED); perspectiveEvents.perspectiveClosed(page, perspective); } void WorkbenchWindow::FirePerspectiveOpened(IWorkbenchPage::Pointer page, IPerspectiveDescriptor::Pointer perspective) { // UIListenerLogging.logPerspectiveEvent(this, page, perspective, // UIListenerLogging.PLE_PERSP_OPENED); perspectiveEvents.perspectiveOpened(page, perspective); } void WorkbenchWindow::FirePerspectiveSavedAs(IWorkbenchPage::Pointer page, IPerspectiveDescriptor::Pointer oldPerspective, IPerspectiveDescriptor::Pointer newPerspective) { // UIListenerLogging.logPerspectiveSavedAs(this, page, oldPerspective, // newPerspective); perspectiveEvents.perspectiveSavedAs(page, oldPerspective, newPerspective); } void WorkbenchWindow::FillActionBars(ActionBarAdvisor::FillFlags flags) { // Workbench workbench = getWorkbenchImpl(); // workbench.largeUpdateStart(); //try { this->GetActionBarAdvisor()->FillActionBars(flags); IMenuService* menuService = serviceLocator->GetService(); menuService->PopulateContributionManager(dynamic_cast(GetActionBars()->GetMenuManager()), MenuUtil::MAIN_MENU); // ICoolBarManager coolbar = getActionBars().getCoolBarManager(); // if (coolbar != null) // { // menuService.populateContributionManager( // (ContributionManager) coolbar, // MenuUtil.MAIN_TOOLBAR); // } // } finally { // workbench.largeUpdateEnd(); // } } QPoint WorkbenchWindow::GetInitialSize() { return this->GetWindowConfigurer()->GetInitialSize(); } bool WorkbenchWindow::Close() { //BERRY_INFO << "WorkbenchWindow::Close()"; bool ret = false; //BusyIndicator.showWhile(null, new Runnable() { // public void run() { ret = this->BusyClose(); // } // }); return ret; } bool WorkbenchWindow::BusyClose() { // Whether the window was actually closed or not bool windowClosed = false; // Setup internal flags to indicate window is in // progress of closing and no update should be done. closing = true; updateDisabled = true; try { // Only do the check if it is OK to close if we are not closing // via the workbench as the workbench will check this itself. Workbench* workbench = this->GetWorkbenchImpl(); std::size_t count = workbench->GetWorkbenchWindowCount(); // also check for starting - if the first window dies on startup // then we'll need to open a default window. if (!workbench->IsStarting() && !workbench->IsClosing() && count <= 1 && workbench->GetWorkbenchConfigurer()->GetExitOnLastWindowClose()) { windowClosed = workbench->Close(); } else { if (this->OkToClose()) { windowClosed = this->HardClose(); } } } catch (std::exception& exc) { if (!windowClosed) { // Reset the internal flags if window was not closed. closing = false; updateDisabled = false; } throw exc; } // if (windowClosed && tracker != null) { // tracker.close(); // } return windowClosed; } void WorkbenchWindow::MakeVisible() { Shell::Pointer shell = GetShell(); if (shell) { // see bug 96700 and bug 4414 for a discussion on the use of open() // here shell->Open(); } } bool WorkbenchWindow::OkToClose() { // Save all of the editors. if (!this->GetWorkbenchImpl()->IsClosing()) { if (!this->SaveAllPages(true)) { return false; } } return true; } bool WorkbenchWindow::SaveAllPages(bool bConfirm) { bool bRet = true; PageList::iterator itr = pageList.Begin(); while (bRet && itr != pageList.End()) { bRet = (*itr)->SaveAllEditors(bConfirm); ++itr; } return bRet; } bool WorkbenchWindow::HardClose() { std::exception exc; bool exceptionOccured = false; try { // Clear the action sets, fix for bug 27416. //getActionPresentation().clearActionSets(); // Remove the handler submissions. Bug 64024. /* final IWorkbench workbench = getWorkbench(); final IHandlerService handlerService = (IHandlerService) workbench.getService(IHandlerService.class); handlerService.deactivateHandlers(handlerActivations); final Iterator activationItr = handlerActivations.iterator(); while (activationItr.hasNext()) { final IHandlerActivation activation = (IHandlerActivation) activationItr .next(); activation.getHandler().dispose(); } handlerActivations.clear(); globalActionHandlersByCommandId.clear(); */ // Remove the enabled submissions. Bug 64024. //IContextService* contextService = this->GetWorkbench()->GetService(); //contextService->UnregisterShell(this->GetShell()); this->CloseAllPages(); this->FireWindowClosed(); // time to wipe out our populate /* IMenuService menuService = (IMenuService) workbench .getService(IMenuService.class); menuService .releaseContributions(((ContributionManager) getActionBars() .getMenuManager())); ICoolBarManager coolbar = getActionBars().getCoolBarManager(); if (coolbar != null) { menuService .releaseContributions(((ContributionManager) coolbar)); } */ //getActionBarAdvisor().dispose(); //getWindowAdvisor().dispose(); //detachedWindowShells.dispose(); delete windowAdvisor; windowAdvisor = nullptr; // Null out the progress region. Bug 64024. //progressRegion = null; // Remove drop targets /* DragUtil.removeDragTarget(null, trimDropTarget); DragUtil.removeDragTarget(getShell(), trimDropTarget); trimDropTarget = null; if (trimMgr2 != null) { trimMgr2.dispose(); trimMgr2 = null; } if (trimContributionMgr != null) { trimContributionMgr.dispose(); trimContributionMgr = null; } */ } catch (std::exception& e) { exc = e; exceptionOccured = true; } bool result = Window::Close(); // Bring down all of the services ... after the window goes away serviceLocator->Dispose(); //menuRestrictions.clear(); if (exceptionOccured) throw exc; return result; } void WorkbenchWindow::CloseAllPages() { // Deactivate active page. this->SetActivePage(IWorkbenchPage::Pointer(nullptr)); // Clone and deref all so that calls to getPages() returns // empty list (if called by pageClosed event handlers) PageList oldList = pageList; pageList.Clear(); // Close all. for (PageList::iterator itr = oldList.Begin(); itr != oldList.End(); ++itr) { partService.PageClosed(*itr); //(*itr)->FirePageClosed(page); //page.dispose(); } if (!closing) { this->ShowEmptyWindowContents(); } } WWinActionBars* WorkbenchWindow::GetActionBars() { if (actionBars.IsNull()) { actionBars = new WWinActionBars(this); } return actionBars.GetPointer(); } void WorkbenchWindow::SetPerspectiveExcludeList(const QStringList& v) { perspectiveExcludeList = v; } QStringList WorkbenchWindow::GetPerspectiveExcludeList() const { return perspectiveExcludeList; } void WorkbenchWindow::SetViewExcludeList(const QStringList& v) { viewExcludeList = v; } QStringList WorkbenchWindow::GetViewExcludeList() const { return viewExcludeList; } QList WorkbenchWindow::GetPages() const { return pageList.GetPages(); } IWorkbenchPage::Pointer WorkbenchWindow::GetActivePage() const { return pageList.GetActive(); } IWorkbench* WorkbenchWindow::GetWorkbench() const { return PlatformUI::GetWorkbench(); } +QList WorkbenchWindow::GetToolBars() const +{ + QList result; + + if (auto shell = this->GetShell(); shell.IsNotNull()) + { + if (const auto* mainWindow = qobject_cast(shell->GetControl()); mainWindow != nullptr) + { + for (auto child : mainWindow->children()) + { + if (auto toolBar = qobject_cast(child); toolBar != nullptr) + result.append(toolBar); + } + } + } + + return result; +} + IPartService* WorkbenchWindow::GetPartService() { return &partService; } ISelectionService* WorkbenchWindow::GetSelectionService() const { return partService.GetSelectionService(); } bool WorkbenchWindow::GetToolBarVisible() const { return GetWindowConfigurer()->GetShowToolBar() && toolBarVisible; } bool WorkbenchWindow::GetPerspectiveBarVisible() const { return GetWindowConfigurer()->GetShowPerspectiveBar() && perspectiveBarVisible; } bool WorkbenchWindow::GetStatusLineVisible() const { return GetWindowConfigurer()->GetShowStatusLine() && statusLineVisible; } void WorkbenchWindow::AddPropertyChangeListener(IPropertyChangeListener *listener) { genericPropertyListeners.AddListener(listener); } void WorkbenchWindow::RemovePropertyChangeListener(IPropertyChangeListener *listener) { genericPropertyListeners.RemoveListener(listener); } bool WorkbenchWindow::IsClosing() { return closing || this->GetWorkbenchImpl()->IsClosing(); } int WorkbenchWindow::Open() { if (pageList.IsEmpty()) { this->ShowEmptyWindowContents(); } this->FireWindowCreated(); this->GetWindowAdvisor()->OpenIntro(); int result = Window::Open(); // It's time for a layout ... to insure that if TrimLayout // is in play, it updates all of the trim it's responsible // for. We have to do this before updating in order to get // the PerspectiveBar management correct...see defect 137334 //getShell().layout(); this->FireWindowOpened(); // if (perspectiveSwitcher != null) { // perspectiveSwitcher.updatePerspectiveBar(); // perspectiveSwitcher.updateBarParent(); // } return result; } QWidget* WorkbenchWindow::GetPageComposite() { return pageComposite; } QWidget *WorkbenchWindow::CreatePageComposite(QWidget *parent) { auto pageArea = new QtControlWidget(parent, nullptr); pageArea->setObjectName("Page Composite"); new QHBoxLayout(pageArea); if (qobject_cast (parent) != nullptr) qobject_cast (parent)->setCentralWidget(pageArea); else parent->layout()->addWidget(pageArea); // we have to enable visibility to get a proper layout (see bug #1654) pageArea->setVisible(true); parent->setVisible(true); pageComposite = pageArea; return pageArea; } QWidget* WorkbenchWindow::CreateContents(Shell::Pointer parent) { // we know from Window.create that the parent is a Shell. this->GetWindowAdvisor()->CreateWindowContents(parent); // the page composite must be set by createWindowContents poco_assert(pageComposite != nullptr) ; // "createWindowContents must call configurer.createPageComposite"); //$NON-NLS-1$ return pageComposite; } void WorkbenchWindow::CreateDefaultContents(Shell::Pointer shell) { QMainWindow* mainWindow = qobject_cast(shell->GetControl()); if (GetWindowConfigurer()->GetShowMenuBar() && mainWindow) { QMenuBar* menuBar = GetMenuBarManager()->CreateMenuBar(mainWindow); mainWindow->setMenuBar(menuBar); } if (GetWindowConfigurer()->GetShowPerspectiveBar() && mainWindow) { mainWindow->addToolBar(new QtPerspectiveSwitcher(IWorkbenchWindow::Pointer(this))); } // Create the client composite area (where page content goes). CreatePageComposite(shell->GetControl()); } void WorkbenchWindow::CreateTrimWidgets(SmartPointer /*shell*/) { // do nothing -- trim widgets are created in CreateDefaultContents } bool WorkbenchWindow::UnableToRestorePage(IMemento::Pointer pageMem) { QString pageName; pageMem->GetString(WorkbenchConstants::TAG_LABEL, pageName); // return new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, NLS.bind( // WorkbenchMessages.WorkbenchWindow_unableToRestorePerspective, // pageName), null); WorkbenchPlugin::Log("Unable to restore perspective: " + pageName); return false; } bool WorkbenchWindow::RestoreState(IMemento::Pointer memento, IPerspectiveDescriptor::Pointer activeDescriptor) { //TODO WorkbenchWindow restore state poco_assert(GetShell()); // final MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID, IStatus.OK, // WorkbenchMessages.WorkbenchWindow_problemsRestoringWindow, null); bool result = true; // Restore the window advisor state. IMemento::Pointer windowAdvisorState = memento ->GetChild(WorkbenchConstants::TAG_WORKBENCH_WINDOW_ADVISOR); if (windowAdvisorState) { //result.add(getWindowAdvisor().restoreState(windowAdvisorState)); result &= GetWindowAdvisor()->RestoreState(windowAdvisorState); } // Restore actionbar advisor state. IMemento::Pointer actionBarAdvisorState = memento ->GetChild(WorkbenchConstants::TAG_ACTION_BAR_ADVISOR); if (actionBarAdvisorState) { // result.add(getActionBarAdvisor() // .restoreState(actionBarAdvisorState)); result &= GetActionBarAdvisor() ->RestoreState(actionBarAdvisorState); } // Read window's bounds and state. QRect displayBounds; // StartupThreading.runWithoutExceptions(new StartupRunnable() { // // public void runWithException() { displayBounds = Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetScreenSize(); //displayBounds = GetShell()->GetDisplay()->GetBounds(); // }}); // final IMemento fastViewMem = memento // .getChild(IWorkbenchConstants.TAG_FAST_VIEW_DATA); // if (fastViewMem != null) { // if (fastViewBar != null) { // StartupThreading.runWithoutExceptions(new StartupRunnable() { // // public void runWithException() { // fastViewBar.restoreState(fastViewMem); // }}); // // } // } int x, y, w, h; memento->GetInteger(WorkbenchConstants::TAG_X, x); memento->GetInteger(WorkbenchConstants::TAG_Y, y); memento->GetInteger(WorkbenchConstants::TAG_WIDTH, w); memento->GetInteger(WorkbenchConstants::TAG_HEIGHT, h); QRect shellBounds(x, y, w, h); if (!shellBounds.isEmpty()) { // StartupThreading.runWithoutExceptions(new StartupRunnable() { // // public void runWithException() { if (!shellBounds.intersects(displayBounds)) { // Center on default screen QRect clientArea(Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetAvailableScreenSize()); shellBounds.setX(clientArea.width() * 0.05); shellBounds.setY(clientArea.height() * 0.05); shellBounds.setWidth(clientArea.width() * 0.9); shellBounds.setHeight(clientArea.height() * 0.9); } GetShell()->SetBounds(shellBounds); // }}); } QString maximized; memento->GetString(WorkbenchConstants::TAG_MAXIMIZED, maximized); if (maximized == "true") { // StartupThreading.runWithoutExceptions(new StartupRunnable() { // // public void runWithException() { GetShell()->SetMaximized(true); // }}); } QString minimized; memento->GetString(WorkbenchConstants::TAG_MINIMIZED, minimized); if (minimized == "true") { // getShell().setMinimized(true); } // // restore the width of the perspective bar // if (perspectiveSwitcher != null) { // perspectiveSwitcher.restoreState(memento); // } // // Restore the cool bar order by creating all the tool bar contribution // // items // // This needs to be done before pages are created to ensure proper // // canonical creation // // of cool items // final ICoolBarManager2 coolBarMgr = (ICoolBarManager2) getCoolBarManager2(); // if (coolBarMgr != null) { // IMemento coolBarMem = memento // .getChild(IWorkbenchConstants.TAG_COOLBAR_LAYOUT); // if (coolBarMem != null) { // // Check if the layout is locked // final Integer lockedInt = coolBarMem // .getInteger(IWorkbenchConstants.TAG_LOCKED); // StartupThreading.runWithoutExceptions(new StartupRunnable(){ // // public void runWithException() { // if ((lockedInt != null) && (lockedInt.intValue() == 1)) { // coolBarMgr.setLockLayout(true); // } else { // coolBarMgr.setLockLayout(false); // } // }}); // // // The new layout of the cool bar manager // ArrayList coolBarLayout = new ArrayList(); // // Traverse through all the cool item in the memento // IMemento contributionMems[] = coolBarMem // .getChildren(IWorkbenchConstants.TAG_COOLITEM); // for (int i = 0; i < contributionMems.length; i++) { // IMemento contributionMem = contributionMems[i]; // String type = contributionMem // .getString(IWorkbenchConstants.TAG_ITEM_TYPE); // if (type == null) { // // Do not recognize that type // continue; // } // String id = contributionMem // .getString(IWorkbenchConstants.TAG_ID); // // // Prevent duplicate items from being read back in. // IContributionItem existingItem = coolBarMgr.find(id); // if ((id != null) && (existingItem != null)) { // if (Policy.DEBUG_TOOLBAR_DISPOSAL) { // System.out // .println("Not loading duplicate cool bar item: " + id); //$NON-NLS-1$ // } // coolBarLayout.add(existingItem); // continue; // } // IContributionItem newItem = null; // if (type.equals(IWorkbenchConstants.TAG_TYPE_SEPARATOR)) { // if (id != null) { // newItem = new Separator(id); // } else { // newItem = new Separator(); // } // } else if (id != null) { // if (type // .equals(IWorkbenchConstants.TAG_TYPE_GROUPMARKER)) { // newItem = new GroupMarker(id); // // } else if (type // .equals(IWorkbenchConstants.TAG_TYPE_TOOLBARCONTRIBUTION) // || type // .equals(IWorkbenchConstants.TAG_TYPE_PLACEHOLDER)) { // // // Get Width and height // Integer width = contributionMem // .getInteger(IWorkbenchConstants.TAG_ITEM_X); // Integer height = contributionMem // .getInteger(IWorkbenchConstants.TAG_ITEM_Y); // // Look for the object in the current cool bar // // manager // IContributionItem oldItem = coolBarMgr.find(id); // // If a tool bar contribution item already exists // // for this id then use the old object // if (oldItem != null) { // newItem = oldItem; // } else { // IActionBarPresentationFactory actionBarPresentation = getActionBarPresentationFactory(); // newItem = actionBarPresentation.createToolBarContributionItem( // actionBarPresentation.createToolBarManager(), id); // if (type // .equals(IWorkbenchConstants.TAG_TYPE_PLACEHOLDER)) { // IToolBarContributionItem newToolBarItem = (IToolBarContributionItem) newItem; // if (height != null) { // newToolBarItem.setCurrentHeight(height // .intValue()); // } // if (width != null) { // newToolBarItem.setCurrentWidth(width // .intValue()); // } // newItem = new PlaceholderContributionItem( // newToolBarItem); // } // // make it invisible by default // newItem.setVisible(false); // // Need to add the item to the cool bar manager // // so that its canonical order can be preserved // IContributionItem refItem = findAlphabeticalOrder( // IWorkbenchActionConstants.MB_ADDITIONS, // id, coolBarMgr); // if (refItem != null) { // coolBarMgr.insertAfter(refItem.getId(), // newItem); // } else { // coolBarMgr.add(newItem); // } // } // // Set the current height and width // if ((width != null) // && (newItem instanceof IToolBarContributionItem)) { // ((IToolBarContributionItem) newItem) // .setCurrentWidth(width.intValue()); // } // if ((height != null) // && (newItem instanceof IToolBarContributionItem)) { // ((IToolBarContributionItem) newItem) // .setCurrentHeight(height.intValue()); // } // } // } // // Add new item into cool bar manager // if (newItem != null) { // coolBarLayout.add(newItem); // newItem.setParent(coolBarMgr); // coolBarMgr.markDirty(); // } // } // // // We need to check if we have everything we need in the layout. // boolean newlyAddedItems = false; // IContributionItem[] existingItems = coolBarMgr.getItems(); // for (int i = 0; i < existingItems.length && !newlyAddedItems; i++) { // IContributionItem existingItem = existingItems[i]; // // /* // * This line shouldn't be necessary, but is here for // * robustness. // */ // if (existingItem == null) { // continue; // } // // boolean found = false; // Iterator layoutItemItr = coolBarLayout.iterator(); // while (layoutItemItr.hasNext()) { // IContributionItem layoutItem = (IContributionItem) layoutItemItr // .next(); // if ((layoutItem != null) // && (layoutItem.equals(existingItem))) { // found = true; // break; // } // } // // if (!found) { // if (existingItem != null) { // newlyAddedItems = true; // } // } // } // // // Set the cool bar layout to the given layout. // if (!newlyAddedItems) { // final IContributionItem[] itemsToSet = new IContributionItem[coolBarLayout // .size()]; // coolBarLayout.toArray(itemsToSet); // StartupThreading // .runWithoutExceptions(new StartupRunnable() { // // public void runWithException() { // coolBarMgr.setItems(itemsToSet); // } // }); // } // // } else { // // For older workbenches // coolBarMem = memento // .getChild(IWorkbenchConstants.TAG_TOOLBAR_LAYOUT); // if (coolBarMem != null) { // // Restore an older layout // restoreOldCoolBar(coolBarMem); // } // } // } // Recreate each page in the window. IWorkbenchPage::Pointer newActivePage; QList pageArray = memento ->GetChildren(WorkbenchConstants::TAG_PAGE); for (int i = 0; i < pageArray.size(); i++) { IMemento::Pointer pageMem = pageArray[i]; QString strFocus; pageMem->GetString(WorkbenchConstants::TAG_FOCUS, strFocus); if (strFocus.isEmpty()) { continue; } // Get the input factory. IAdaptable* input = nullptr; IMemento::Pointer inputMem = pageMem->GetChild(WorkbenchConstants::TAG_INPUT); if (inputMem) { QString factoryID; inputMem->GetString(WorkbenchConstants::TAG_FACTORY_ID, factoryID); if (factoryID.isEmpty()) { WorkbenchPlugin ::Log("Unable to restore page - no input factory ID."); //result.add(unableToRestorePage(pageMem)); result &= UnableToRestorePage(pageMem); continue; } // try { // UIStats.start(UIStats.RESTORE_WORKBENCH, // "WorkbenchPageFactory"); //$NON-NLS-1$ // StartupThreading // .runWithoutExceptions(new StartupRunnable() { // // public void runWithException() throws Throwable { // IElementFactory factory = PlatformUI // .getWorkbench().getElementFactory( // factoryID); // if (factory == null) { // WorkbenchPlugin // .log("Unable to restore page - cannot instantiate input factory: " + factoryID); //$NON-NLS-1$ // result // .add(unableToRestorePage(pageMem)); // return; // } // // // Get the input element. // input[0] = factory.createElement(inputMem); // } // }); // // if (input[0] == null) { // WorkbenchPlugin // .log("Unable to restore page - cannot instantiate input element: " + factoryID); //$NON-NLS-1$ // result.add(unableToRestorePage(pageMem)); // continue; // } // } finally { // UIStats.end(UIStats.RESTORE_WORKBENCH, factoryID, // "WorkbenchPageFactory"); //$NON-NLS-1$ // } } // Open the perspective. IAdaptable* finalInput = input; WorkbenchPage::Pointer newPage; try { // StartupThreading.runWithWorkbenchExceptions(new StartupRunnable(){ // // public void runWithException() throws WorkbenchException { newPage = new WorkbenchPage(this, finalInput); // }}); //result.add(newPage[0].restoreState(pageMem, activeDescriptor)); result &= newPage->RestoreState(pageMem, activeDescriptor); pageList.Add(newPage); // StartupThreading.runWithoutExceptions(new StartupRunnable() { // // public void runWithException() throws Throwable { partService.PageOpened(newPage); // firePageOpened(newPage[0]); // }}); } catch (const WorkbenchException& e) { WorkbenchPlugin::Log( "Unable to restore perspective - constructor failed.", e); //$NON-NLS-1$ //result.add(e.getStatus()); continue; } if (!strFocus.isEmpty()) { newActivePage = newPage; } } // If there are no pages create a default. if (pageList.IsEmpty()) { try { const QString defPerspID = this->GetWorkbenchImpl()->GetPerspectiveRegistry() ->GetDefaultPerspective(); if (!defPerspID.isEmpty()) { WorkbenchPage::Pointer newPage; //StartupThreading.runWithWorkbenchExceptions(new StartupRunnable() { // public void runWithException() throws Throwable { newPage = new WorkbenchPage(this, defPerspID, this->GetDefaultPageInput()); // }}); pageList.Add(newPage); //StartupThreading.runWithoutExceptions(new StartupRunnable() { // public void runWithException() throws Throwable { // firePageOpened(newPage[0]); partService.PageOpened(newPage); // }}); } } catch (WorkbenchException& e) { WorkbenchPlugin ::Log( "Unable to create default perspective - constructor failed.", e); result = false; //TODO set product name // String productName = WorkbenchPlugin.getDefault() // .getProductName(); // if (productName == null) { // productName = ""; //$NON-NLS-1$ // } // getShell().setText(productName); } } // Set active page. if (newActivePage.IsNull()) { newActivePage = pageList.GetNextActive().Cast(); } //StartupThreading.runWithoutExceptions(new StartupRunnable() { // public void runWithException() throws Throwable { this->SetActivePage(newActivePage); // }}); IMemento::Pointer introMem = memento->GetChild(WorkbenchConstants::TAG_INTRO); if (introMem) { // StartupThreading.runWithoutExceptions(new StartupRunnable() { // // public void runWithException() throws Throwable { bool isStandby = false; introMem->GetBoolean(WorkbenchConstants::TAG_STANDBY, isStandby); GetWorkbench()->GetIntroManager()->ShowIntro( IWorkbenchWindow::Pointer(this), isStandby); // } // }); } // // // Only restore the trim state if we're using the default layout // if (defaultLayout != null) { // // Restore the trim state. We pass in the 'root' // // memento since we have to check for pre-3.2 // // state. // result.add(restoreTrimState(memento)); // } return result; } IAdaptable* WorkbenchWindow::GetDefaultPageInput() { return this->GetWorkbenchImpl()->GetDefaultPageInput(); } IWorkbenchPage::Pointer WorkbenchWindow::OpenPage( const QString& perspId, IAdaptable* input) { // Run op in busy cursor. IWorkbenchPage::Pointer result; //BusyIndicator.showWhile(null, new Runnable() { // public void run() { result = this->BusyOpenPage(perspId, input); // } return result; } SmartPointer WorkbenchWindow::OpenPage(IAdaptable* input) { QString perspId = this->GetWorkbenchImpl()->GetDefaultPerspectiveId(); return this->OpenPage(perspId, input); } IWorkbenchPage::Pointer WorkbenchWindow::BusyOpenPage( const QString& perspID, IAdaptable* input) { IWorkbenchPage::Pointer newPage; if (pageList.IsEmpty()) { newPage = new WorkbenchPage(this, perspID, input); pageList.Add(newPage); //this->FirePageOpened(newPage); partService.PageOpened(newPage); this->SetActivePage(newPage); } else { IWorkbenchWindow::Pointer window = this->GetWorkbench()->OpenWorkbenchWindow(perspID, input); newPage = window->GetActivePage(); } return newPage; } int WorkbenchWindow::GetNumber() { return number; } void WorkbenchWindow::UpdateActionBars() { if (updateDisabled || UpdatesDeferred()) { return; } // updateAll required in order to enable accelerators on pull-down menus GetMenuBarManager()->Update(false); //GetToolBarManager()->Update(false); //GetStatusLineManager()->Update(false); } void WorkbenchWindow::LargeUpdateStart() { largeUpdates++; } void WorkbenchWindow::LargeUpdateEnd() { if (--largeUpdates == 0) { this->UpdateActionBars(); } } void WorkbenchWindow::SetActivePage(IWorkbenchPage::Pointer in) { if (this->GetActivePage() == in) { return; } // 1FVGTNR: ITPUI:WINNT - busy cursor for switching perspectives //BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() { // public void run() { // Deactivate old persp. WorkbenchPage::Pointer currentPage = pageList.GetActive(); if (currentPage.IsNotNull()) { currentPage->OnDeactivate(); } // Activate new persp. if (in.IsNull() || pageList.Contains(in)) { pageList.SetActive(in); } WorkbenchPage::Pointer newPage = pageList.GetActive(); //Composite parent = getPageComposite(); //StackLayout layout = (StackLayout) parent.getLayout(); if (newPage.IsNotNull()) { //layout.topControl = newPage.getClientComposite(); //parent.layout(); this->HideEmptyWindowContents(); newPage->OnActivate(); //this->FirePageActivated(newPage); partService.PageActivated(newPage); //TODO perspective if (newPage->GetPerspective() != 0) { this->FirePerspectiveActivated(newPage, newPage->GetPerspective()); } } else { //layout.topControl = null; //parent.layout(); } //updateFastViewBar(); if (this->IsClosing()) { return; } updateDisabled = false; // Update action bars ( implicitly calls updateActionBars() ) //updateActionSets(); //submitGlobalActions(); //if (perspectiveSwitcher != null) { // perspectiveSwitcher.update(false); //} GetMenuManager()->Update(QActionProperties::TEXT); // } //}); } MenuManager *WorkbenchWindow::GetMenuManager() const { return this->GetMenuBarManager(); } bool WorkbenchWindow::SaveState(IMemento::Pointer memento) { // MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID, IStatus.OK, // WorkbenchMessages.WorkbenchWindow_problemsSavingWindow, null); bool result = true; // Save the window's state and bounds. if (GetShell()->GetMaximized() || asMaximizedState) { memento->PutString(WorkbenchConstants::TAG_MAXIMIZED, "true"); } if (GetShell()->GetMinimized()) { memento->PutString(WorkbenchConstants::TAG_MINIMIZED, "true"); } if (normalBounds.isEmpty()) { normalBounds = GetShell()->GetBounds(); } // IMemento fastViewBarMem = memento // .createChild(IWorkbenchConstants.TAG_FAST_VIEW_DATA); // if (fastViewBar != null) { // fastViewBar.saveState(fastViewBarMem); // } memento->PutInteger(WorkbenchConstants::TAG_X, normalBounds.x()); memento->PutInteger(WorkbenchConstants::TAG_Y, normalBounds.y()); memento->PutInteger(WorkbenchConstants::TAG_WIDTH, normalBounds.width()); memento->PutInteger(WorkbenchConstants::TAG_HEIGHT, normalBounds.height()); IWorkbenchPage::Pointer activePage = GetActivePage(); if (activePage && activePage->FindView(IntroConstants::INTRO_VIEW_ID)) { IMemento::Pointer introMem = memento ->CreateChild(WorkbenchConstants::TAG_INTRO); bool isStandby = GetWorkbench()->GetIntroManager() ->IsIntroStandby(GetWorkbench()->GetIntroManager()->GetIntro()); introMem->PutBoolean(WorkbenchConstants::TAG_STANDBY, isStandby); } // // save the width of the perspective bar // IMemento persBarMem = memento // .createChild(IWorkbenchConstants.TAG_PERSPECTIVE_BAR); // if (perspectiveSwitcher != null) { // perspectiveSwitcher.saveState(persBarMem); // } // // / Save the order of the cool bar contribution items // ICoolBarManager2 coolBarMgr = (ICoolBarManager2) getCoolBarManager2(); // if (coolBarMgr != null) { // coolBarMgr.refresh(); // IMemento coolBarMem = memento // .createChild(IWorkbenchConstants.TAG_COOLBAR_LAYOUT); // if (coolBarMgr.getLockLayout() == true) { // coolBarMem.putInteger(IWorkbenchConstants.TAG_LOCKED, 1); // } else { // coolBarMem.putInteger(IWorkbenchConstants.TAG_LOCKED, 0); // } // IContributionItem[] items = coolBarMgr.getItems(); // for (int i = 0; i < items.length; i++) { // IMemento coolItemMem = coolBarMem // .createChild(IWorkbenchConstants.TAG_COOLITEM); // IContributionItem item = items[i]; // // The id of the contribution item // if (item.getId() != null) { // coolItemMem.putString(IWorkbenchConstants.TAG_ID, item // .getId()); // } // // Write out type and size if applicable // if (item.isSeparator()) { // coolItemMem.putString(IWorkbenchConstants.TAG_ITEM_TYPE, // IWorkbenchConstants.TAG_TYPE_SEPARATOR); // } else if (item.isGroupMarker() && !item.isSeparator()) { // coolItemMem.putString(IWorkbenchConstants.TAG_ITEM_TYPE, // IWorkbenchConstants.TAG_TYPE_GROUPMARKER); // } else { // if (item instanceof PlaceholderContributionItem) { // coolItemMem.putString( // IWorkbenchConstants.TAG_ITEM_TYPE, // IWorkbenchConstants.TAG_TYPE_PLACEHOLDER); // } else { // // Store the identifier. // coolItemMem // .putString( // IWorkbenchConstants.TAG_ITEM_TYPE, // IWorkbenchConstants.TAG_TYPE_TOOLBARCONTRIBUTION); // } // // /* // * Retrieve a reasonable approximation of the height and // * width, if possible. // */ // final int height; // final int width; // if (item instanceof IToolBarContributionItem) { // IToolBarContributionItem toolBarItem = (IToolBarContributionItem) item; // toolBarItem.saveWidgetState(); // height = toolBarItem.getCurrentHeight(); // width = toolBarItem.getCurrentWidth(); // } else if (item instanceof PlaceholderContributionItem) { // PlaceholderContributionItem placeholder = (PlaceholderContributionItem) item; // height = placeholder.getHeight(); // width = placeholder.getWidth(); // } else { // height = -1; // width = -1; // } // // // Store the height and width. // coolItemMem.putInteger(IWorkbenchConstants.TAG_ITEM_X, // width); // coolItemMem.putInteger(IWorkbenchConstants.TAG_ITEM_Y, // height); // } // } // } // Save each page. for (PageList::iterator itr = pageList.Begin(); itr != pageList.End(); ++itr) { WorkbenchPage::Pointer page = itr->Cast(); // Save perspective. IMemento::Pointer pageMem = memento ->CreateChild(WorkbenchConstants::TAG_PAGE); pageMem->PutString(WorkbenchConstants::TAG_LABEL, page->GetLabel()); //result.add(page.saveState(pageMem)); result &= page->SaveState(pageMem); if (page == GetActivePage().Cast()) { pageMem->PutString(WorkbenchConstants::TAG_FOCUS, "true"); } // // Get the input. // IAdaptable* input = page->GetInput(); // if (input != 0) { // IPersistableElement persistable = (IPersistableElement) Util.getAdapter(input, // IPersistableElement.class); // if (persistable == null) { // WorkbenchPlugin // .log("Unable to save page input: " //$NON-NLS-1$ // + input // + ", because it does not adapt to IPersistableElement"); //$NON-NLS-1$ // } else { // // Save input. // IMemento inputMem = pageMem // .createChild(IWorkbenchConstants.TAG_INPUT); // inputMem.putString(IWorkbenchConstants.TAG_FACTORY_ID, // persistable.getFactoryId()); // persistable.saveState(inputMem); // } // } } // Save window advisor state. IMemento::Pointer windowAdvisorState = memento ->CreateChild(WorkbenchConstants::TAG_WORKBENCH_WINDOW_ADVISOR); //result.add(getWindowAdvisor().saveState(windowAdvisorState)); result &= GetWindowAdvisor()->SaveState(windowAdvisorState); // Save actionbar advisor state. IMemento::Pointer actionBarAdvisorState = memento ->CreateChild(WorkbenchConstants::TAG_ACTION_BAR_ADVISOR); //result.add(getActionBarAdvisor().saveState(actionBarAdvisorState)); result &= GetActionBarAdvisor()->SaveState(actionBarAdvisorState); // // Only save the trim state if we're using the default layout // if (defaultLayout != null) { // IMemento trimState = memento.createChild(IWorkbenchConstants.TAG_TRIM); // result.add(saveTrimState(trimState)); // } return result; } WorkbenchWindowConfigurer::Pointer WorkbenchWindow::GetWindowConfigurer() const { if (windowConfigurer.IsNull()) { // lazy initialize windowConfigurer = new WorkbenchWindowConfigurer(WorkbenchWindow::Pointer(const_cast(this))); } return windowConfigurer; } bool WorkbenchWindow::CanHandleShellCloseEvent() { if (!Window::CanHandleShellCloseEvent()) { return false; } // let the advisor or other interested parties // veto the user's explicit request to close the window return FireWindowShellClosing(); } void WorkbenchWindow::ConfigureShell(Shell::Pointer shell) { Window::ConfigureShell(shell); detachedWindowShells = new ShellPool(shell, Constants::TITLE | Constants::MAX | Constants::CLOSE | Constants::RESIZE | Constants::BORDER ); QString title = this->GetWindowConfigurer()->BasicGetTitle(); if (!title.isEmpty()) { shell->SetText(title); } //IWorkbench* workbench = this->GetWorkbench(); // workbench.getHelpSystem().setHelp(shell, // IWorkbenchHelpContextIds.WORKBENCH_WINDOW); //IContextService* contextService = workbench->GetService(); //contextService->RegisterShell(shell, IContextService::TYPE_WINDOW); shell->GetControl()->installEventFilter(&resizeEventFilter); } ShellPool::Pointer WorkbenchWindow::GetDetachedWindowPool() { return detachedWindowShells; } WorkbenchAdvisor* WorkbenchWindow::GetAdvisor() { return this->GetWorkbenchImpl()->GetAdvisor(); } WorkbenchWindowAdvisor* WorkbenchWindow::GetWindowAdvisor() { if (windowAdvisor == nullptr) { windowAdvisor = this->GetAdvisor()->CreateWorkbenchWindowAdvisor(this->GetWindowConfigurer()); poco_check_ptr(windowAdvisor); } return windowAdvisor; } ActionBarAdvisor::Pointer WorkbenchWindow::GetActionBarAdvisor() { if (actionBarAdvisor.IsNull()) { actionBarAdvisor = this->GetWindowAdvisor()->CreateActionBarAdvisor(this->GetWindowConfigurer()->GetActionBarConfigurer()); poco_assert(actionBarAdvisor.IsNotNull()); } return actionBarAdvisor; } Workbench* WorkbenchWindow::GetWorkbenchImpl() { return dynamic_cast(this->GetWorkbench()); } void WorkbenchWindow::ShowEmptyWindowContents() { if (!emptyWindowContentsCreated) { QWidget* parent = this->GetPageComposite(); emptyWindowContents = this->GetWindowAdvisor()->CreateEmptyWindowContents( parent); emptyWindowContentsCreated = true; // // force the empty window composite to be layed out // ((StackLayout) parent.getLayout()).topControl = emptyWindowContents; // parent.layout(); } } void WorkbenchWindow::HideEmptyWindowContents() { if (emptyWindowContentsCreated) { if (emptyWindowContents != nullptr) { Tweaklets::Get(GuiWidgetsTweaklet::KEY)->Dispose(emptyWindowContents); emptyWindowContents = nullptr; //this->GetPageComposite().layout(); } emptyWindowContentsCreated = false; } } WorkbenchWindow::ServiceLocatorOwner::ServiceLocatorOwner(WorkbenchWindow* wnd) : window(wnd) { } void WorkbenchWindow::ServiceLocatorOwner::Dispose() { Shell::Pointer shell = window->GetShell(); if (shell != 0) { window->Close(); } } bool WorkbenchWindow::PageList::Add(IWorkbenchPage::Pointer object) { pagesInCreationOrder.push_back(object); pagesInActivationOrder.push_front(object); // It will be moved to top only when activated. return true; } WorkbenchWindow::PageList::iterator WorkbenchWindow::PageList::Begin() { return pagesInCreationOrder.begin(); } WorkbenchWindow::PageList::iterator WorkbenchWindow::PageList::End() { return pagesInCreationOrder.end(); } bool WorkbenchWindow::PageList::Contains(IWorkbenchPage::Pointer object) { return std::find(pagesInCreationOrder.begin(), pagesInCreationOrder.end(), object) != pagesInCreationOrder.end(); } bool WorkbenchWindow::PageList::Remove(IWorkbenchPage::Pointer object) { if (active == object) { active = nullptr; } pagesInActivationOrder.removeAll(object); const int origSize = pagesInCreationOrder.size(); pagesInCreationOrder.removeAll(object); return origSize != pagesInCreationOrder.size(); } void WorkbenchWindow::PageList::Clear() { pagesInCreationOrder.clear(); pagesInActivationOrder.clear(); active = nullptr; } bool WorkbenchWindow::PageList::IsEmpty() { return pagesInCreationOrder.empty(); } QList WorkbenchWindow::PageList::GetPages() const { return pagesInCreationOrder; } void WorkbenchWindow::PageList::SetActive(IWorkbenchPage::Pointer page) { if (active == page) { return; } active = page; if (page.IsNotNull()) { pagesInActivationOrder.removeAll(page); pagesInActivationOrder.push_back(page); } } WorkbenchPage::Pointer WorkbenchWindow::PageList::GetActive() const { return active.Cast(); } WorkbenchPage::Pointer WorkbenchWindow::PageList::GetNextActive() { if (active.IsNull()) { if (pagesInActivationOrder.empty()) { return WorkbenchPage::Pointer(nullptr); } return pagesInActivationOrder.back().Cast(); } if (pagesInActivationOrder.size() < 2) { return WorkbenchPage::Pointer(nullptr); } return pagesInActivationOrder.at(pagesInActivationOrder.size()-2).Cast(); } bool WorkbenchWindow::UpdatesDeferred() const { return largeUpdates > 0; } void WorkbenchWindow::InitializeDefaultServices() { workbenchLocationService.reset( new WorkbenchLocationService(IServiceScopes::WINDOW_SCOPE, GetWorkbench(), this, nullptr, 1)); workbenchLocationService->Register(); serviceLocator->RegisterService(workbenchLocationService.data()); //ActionCommandMappingService* mappingService = new ActionCommandMappingService(); //serviceLocator->RegisterService(IActionCommandMappingService, mappingService); } QSet > WorkbenchWindow::GetMenuRestrictions() const { return QSet >(); } void WorkbenchWindow::FirePropertyChanged(const QString& property, const Object::Pointer& oldValue, const Object::Pointer& newValue) { PropertyChangeEvent::Pointer event(new PropertyChangeEvent(Object::Pointer(this), property, oldValue, newValue)); genericPropertyListeners.propertyChange(event); } WorkbenchWindow::ShellEventFilter::ShellEventFilter(WorkbenchWindow* window) : window(window) { } bool WorkbenchWindow::ShellEventFilter::eventFilter(QObject* watched, QEvent* event) { QEvent::Type eventType = event->type(); if (eventType == QEvent::Move || eventType == QEvent::Resize) { QWidget* widget = static_cast(watched); QRect newBounds = widget->geometry(); if (eventType == QEvent::Move) { newBounds.setTopLeft(static_cast(event)->pos()); } else if(eventType == QEvent::Resize) { newBounds.setSize(static_cast(event)->size()); } this->SaveBounds(newBounds); } else if (eventType == QEvent::WindowActivate) { this->ShellActivated(); } else if (eventType == QEvent::WindowDeactivate) { this->ShellDeactivated(); } return false; } void WorkbenchWindow::ShellEventFilter::SaveBounds(const QRect& newBounds) { Shell::Pointer shell = window->GetShell(); if (shell == 0) { return; } // if (shell->IsDisposed()) // { // return; // } if (shell->GetMinimized()) { return; } if (shell->GetMaximized()) { window->asMaximizedState = true; return; } window->asMaximizedState = false; window->normalBounds = newBounds; } void WorkbenchWindow::ShellEventFilter::ShellActivated() { WorkbenchWindow::Pointer wnd(window); wnd->shellActivated = true; wnd->serviceLocator->Activate(); wnd->GetWorkbenchImpl()->SetActivatedWindow(wnd); WorkbenchPage::Pointer currentPage = wnd->GetActivePage().Cast(); if (currentPage != 0) { IWorkbenchPart::Pointer part = currentPage->GetActivePart(); if (part != 0) { PartSite::Pointer site = part->GetSite().Cast(); site->GetPane()->ShellActivated(); } IEditorPart::Pointer editor = currentPage->GetActiveEditor(); if (editor != 0) { PartSite::Pointer site = editor->GetSite().Cast(); site->GetPane()->ShellActivated(); } wnd->GetWorkbenchImpl()->FireWindowActivated(wnd); } //liftRestrictions(); } void WorkbenchWindow::ShellEventFilter::ShellDeactivated() { WorkbenchWindow::Pointer wnd(window); wnd->shellActivated = false; //imposeRestrictions(); wnd->serviceLocator->Deactivate(); WorkbenchPage::Pointer currentPage = wnd->GetActivePage().Cast(); if (currentPage != 0) { IWorkbenchPart::Pointer part = currentPage->GetActivePart(); if (part != 0) { PartSite::Pointer site = part->GetSite().Cast(); site->GetPane()->ShellDeactivated(); } IEditorPart::Pointer editor = currentPage->GetActiveEditor(); if (editor != 0) { PartSite::Pointer site = editor->GetSite().Cast(); site->GetPane()->ShellDeactivated(); } wnd->GetWorkbenchImpl()->FireWindowDeactivated(wnd); } } } diff --git a/Plugins/org.blueberry.ui.qt/src/internal/berryWorkbenchWindow.h b/Plugins/org.blueberry.ui.qt/src/internal/berryWorkbenchWindow.h index 4891d63dc2..d9f26c5d13 100644 --- a/Plugins/org.blueberry.ui.qt/src/internal/berryWorkbenchWindow.h +++ b/Plugins/org.blueberry.ui.qt/src/internal/berryWorkbenchWindow.h @@ -1,705 +1,707 @@ /*============================================================================ 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 BERRYWORKBENCHWINDOW_H_ #define BERRYWORKBENCHWINDOW_H_ #include "berryIWorkbenchWindow.h" #include "berryIPerspectiveListener.h" #include "berryWindow.h" #include "berryWorkbenchWindowConfigurer.h" #include "berryShellPool.h" #include "berryServiceLocator.h" #include "berryWWinPartService.h" #include "application/berryWorkbenchAdvisor.h" #include "application/berryWorkbenchWindowAdvisor.h" #include "application/berryActionBarAdvisor.h" #include #include namespace berry { struct IEvaluationReference; struct IWorkbench; struct IWorkbenchPage; struct IPartService; struct ISelectionService; struct IPerspectiveDescriptor; struct IWorkbenchLocationService; class Workbench; class WorkbenchPage; class WWinActionBars; /** * \ingroup org_blueberry_ui_qt * */ class BERRY_UI_QT WorkbenchWindow: public Window, public IWorkbenchWindow { public: /** * Toolbar visibility change property. */ static const QString PROP_TOOLBAR_VISIBLE; // = "toolbarVisible"; /** * Perspective bar visibility change property. */ static const QString PROP_PERSPECTIVEBAR_VISIBLE; // = "perspectiveBarVisible"; /** * The status line visibility change property. for internal use only. */ static const QString PROP_STATUS_LINE_VISIBLE; // = "statusLineVisible"; public: berryObjectMacro(WorkbenchWindow, Window, IWorkbenchWindow); WorkbenchWindow(int number); ~WorkbenchWindow() override; Object* GetService(const QString& key) override; bool HasService(const QString& key) const override; int Open(); bool Close() override; Shell::Pointer GetShell() const override; /** * @see org.blueberry.ui.IPageService */ void AddPerspectiveListener(IPerspectiveListener* l) override; /** * @see org.blueberry.ui.IPageService */ void RemovePerspectiveListener(IPerspectiveListener* l) override; /** * @see org.blueberry.ui.IPageService */ IPerspectiveListener::Events& GetPerspectiveEvents() override; /** * Returns the action bars for this window. */ WWinActionBars* GetActionBars(); SmartPointer GetActivePage() const override; QList > GetPages() const override; void SetPerspectiveExcludeList(const QStringList& v); QStringList GetPerspectiveExcludeList() const; void SetViewExcludeList(const QStringList& v); QStringList GetViewExcludeList() const; /** * Sets the active page within the window. * * @param in * identifies the new active page, or null for no * active page */ void SetActivePage(SmartPointer in) override; /** * Answer the menu manager for this window. */ MenuManager* GetMenuManager() const; IWorkbench* GetWorkbench() const override; + QList GetToolBars() const override; + IPartService* GetPartService() override; ISelectionService* GetSelectionService() const override; /** * @return whether the tool bar should be shown. This is only applicable if * the window configurer also wishes the cool bar to be visible. */ bool GetToolBarVisible() const; /** * @return whether the perspective bar should be shown. This is only * applicable if the window configurer also wishes the perspective * bar to be visible. */ bool GetPerspectiveBarVisible() const; /** * @return whether the status line should be shown. This is only applicable if * the window configurer also wishes status line to be visible. */ bool GetStatusLineVisible() const; /** * Add a generic property listener. * * @param listener the listener to add */ void AddPropertyChangeListener(IPropertyChangeListener* listener); /** * Removes a generic property listener. * * @param listener the listener to remove */ void RemovePropertyChangeListener(IPropertyChangeListener* listener); SmartPointer OpenPage(const QString& perspectiveId, IAdaptable* input) override; SmartPointer OpenPage(IAdaptable* input) override; //TODO menu manager //virtual QWidget* GetMenuManager() = 0; virtual bool SaveState(IMemento::Pointer memento); /** * Called when this window is about to be closed. * * Subclasses may override to add code that returns false to * prevent closing under certain conditions. */ virtual bool OkToClose(); bool RestoreState(IMemento::Pointer memento, SmartPointer< IPerspectiveDescriptor> activeDescriptor); /** * Returns the number. This corresponds to a page number in a window or a * window number in the workbench. */ int GetNumber(); /** * update the action bars. */ void UpdateActionBars(); /** *

* Indicates the start of a large update within this window. This is used to * disable CPU-intensive, change-sensitive services that were temporarily * disabled in the midst of large changes. This method should always be * called in tandem with largeUpdateEnd, and the event loop * should not be allowed to spin before that method is called. *

*

* Important: always use with largeUpdateEnd! *

* * @since 3.1 */ void LargeUpdateStart(); /** *

* Indicates the end of a large update within this window. This is used to * re-enable services that were temporarily disabled in the midst of large * changes. This method should always be called in tandem with * largeUpdateStart, and the event loop should not be * allowed to spin before this method is called. *

*

* Important: always protect this call by using finally! *

* * @since 3.1 */ void LargeUpdateEnd(); QSet > GetMenuRestrictions() const; protected: friend class WorkbenchConfigurer; friend class WorkbenchWindowConfigurer; friend class WorkbenchWindowConfigurer::WindowActionBarConfigurer; friend class Workbench; friend class LayoutPartSash; friend class EditorSashContainer; friend class WorkbenchPage; friend class DetachedWindow; /** * Returns the GUI dependent page composite, under which the window's * pages create their controls. */ QWidget* GetPageComposite(); /** * Creates and remembers the client composite, under which workbench pages * create their controls. */ QWidget* CreatePageComposite(QWidget* parent); /** * Creates the contents of the workbench window, including trim controls and * the client composite. This MUST create the client composite via a call to * createClientComposite. * * @since 3.0 */ QWidget* CreateContents(Shell::Pointer parent) override; /** * Creates the default contents and layout of the shell. * * @param shell * the shell */ virtual void CreateDefaultContents(Shell::Pointer shell); void CreateTrimWidgets(SmartPointer shell) override; /** * Returns the unique object that applications use to configure this window. *

* IMPORTANT This method is declared package-private to prevent regular * plug-ins from downcasting IWorkbenchWindow to WorkbenchWindow and getting * hold of the workbench window configurer that would allow them to tamper * with the workbench window. The workbench window configurer is available * only to the application. *

*/ WorkbenchWindowConfigurer::Pointer GetWindowConfigurer() const; bool CanHandleShellCloseEvent() override; /* * @see berry::Window#configureShell(Shell::Pointer) */ void ConfigureShell(Shell::Pointer shell) override; ShellPool::Pointer GetDetachedWindowPool(); /** * Fills the window's real action bars. * * @param flags * indicate which bars to fill */ void FillActionBars(ActionBarAdvisor::FillFlags flags); /** * The WorkbenchWindow implementation of this method * delegates to the window configurer. * * @since 3.0 */ QPoint GetInitialSize() override; /** * Returns the default page input for workbench pages opened in this window. * * @return the default page input or null if none * @since 3.1 */ IAdaptable* GetDefaultPageInput(); bool IsClosing(); /** * Opens a new page. Assumes that busy cursor is active. *

* Note: Since release 2.0, a window is limited to contain at most * one page. If a page exist in the window when this method is used, then * another window is created for the new page. Callers are strongly * recommended to use the IWorkbench.openPerspective APIs to * programmatically show a perspective. *

*/ SmartPointer BusyOpenPage(const QString& perspID, IAdaptable* input); bool ClosePage(SmartPointer in, bool save); /** * Makes the window visible and frontmost. */ void MakeVisible(); /** * The composite under which workbench pages create their controls. */ QWidget* pageComposite; private: /** * Constant indicating that all the actions bars should be filled. */ static const ActionBarAdvisor::FillFlags FILL_ALL_ACTION_BARS; ShellPool::Pointer detachedWindowShells; /** * Object for configuring this workbench window. Lazily initialized to an * instance unique to this window. */ mutable WorkbenchWindowConfigurer::Pointer windowConfigurer; WorkbenchWindowAdvisor* windowAdvisor; ActionBarAdvisor::Pointer actionBarAdvisor; SmartPointer actionBars; IPropertyChangeListener::Events genericPropertyListeners; int number; /** * The number of large updates that are currently going on. If this is * number is greater than zero, then UI updateActionBars is a no-op. */ int largeUpdates; bool closing; bool shellActivated; bool updateDisabled; bool toolBarVisible; bool perspectiveBarVisible; bool statusLineVisible; /** * The map of services maintained by the workbench window. These services * are initialized during workbench window during the * {@link #configureShell(Shell)}. */ ServiceLocator::Pointer serviceLocator; QScopedPointer workbenchLocationService; bool emptyWindowContentsCreated; QWidget* emptyWindowContents; QRect normalBounds; bool asMaximizedState; IPerspectiveListener::Events perspectiveEvents; WWinPartService partService; QStringList perspectiveExcludeList; QStringList viewExcludeList; struct ServiceLocatorOwner: public IDisposable { ServiceLocatorOwner(WorkbenchWindow* wnd); WorkbenchWindow* window; void Dispose() override; }; IDisposable::Pointer serviceLocatorOwner; class PageList { private: // List of pages in the order they were created; QList > pagesInCreationOrder; // List of pages where the top is the last activated. QList > pagesInActivationOrder; // The page explicitly activated SmartPointer active; public: typedef QList >::iterator iterator; bool Add(SmartPointer object); iterator Begin(); iterator End(); void Clear(); bool Contains(SmartPointer object); bool Remove(SmartPointer object); bool IsEmpty(); QList > GetPages() const; void SetActive(SmartPointer page); SmartPointer GetActive() const; SmartPointer GetNextActive(); }; PageList pageList; /** * Notifies interested parties (namely the advisor) that the window is about * to be opened. * * @since 3.1 */ void FireWindowOpening(); /** * Notifies interested parties (namely the advisor) that the window has been * restored from a previously saved state. * * @throws WorkbenchException * passed through from the advisor * @since 3.1 */ void FireWindowRestored(); /** * Notifies interested parties (namely the advisor) that the window has been * created. * * @since 3.1 */ void FireWindowCreated(); /** * Notifies interested parties (namely the advisor and the window listeners) * that the window has been opened. * * @since 3.1 */ void FireWindowOpened(); /** * Notifies interested parties (namely the advisor) that the window's shell * is closing. Allows the close to be vetoed. * * @return true if the close should proceed, * false if it should be canceled * @since 3.1 */ bool FireWindowShellClosing(); /** * Notifies interested parties (namely the advisor and the window listeners) * that the window has been closed. * * @since 3.1 */ void FireWindowClosed(); // /** // * Fires page activated // */ // void FirePageActivated(IWorkbenchPage::Pointer page); // // /** // * Fires page closed // */ // void FirePageClosed(IWorkbenchPage::Pointer page); // // /** // * Fires page opened // */ // void FirePageOpened(IWorkbenchPage::Pointer page); /** * Fires perspective activated */ void FirePerspectiveActivated(SmartPointer page, IPerspectiveDescriptor::Pointer perspective); /** * Fires perspective deactivated. * * @since 3.2 */ void FirePerspectivePreDeactivate(SmartPointer page, IPerspectiveDescriptor::Pointer perspective); /** * Fires perspective deactivated. * * @since 3.1 */ void FirePerspectiveDeactivated(SmartPointer page, IPerspectiveDescriptor::Pointer perspective); /** * Fires perspective changed */ void FirePerspectiveChanged(SmartPointer , IPerspectiveDescriptor::Pointer perspective, const QString& changeId); /** * Fires perspective changed for an affected part */ void FirePerspectiveChanged(SmartPointer , IPerspectiveDescriptor::Pointer perspective, IWorkbenchPartReference::Pointer partRef, const QString& changeId); /** * Fires perspective closed */ void FirePerspectiveClosed(SmartPointer , IPerspectiveDescriptor::Pointer perspective); /** * Fires perspective opened */ void FirePerspectiveOpened(SmartPointer , IPerspectiveDescriptor::Pointer perspective); /** * Fires perspective saved as. * * @since 3.1 */ void FirePerspectiveSavedAs(SmartPointer , IPerspectiveDescriptor::Pointer oldPerspective, IPerspectiveDescriptor::Pointer newPerspective); /** * Returns the workbench advisor. Assumes the workbench has been created * already. *

* IMPORTANT This method is declared private to prevent regular plug-ins * from downcasting IWorkbenchWindow to WorkbenchWindow and getting hold of * the workbench advisor that would allow them to tamper with the workbench. * The workbench advisor is internal to the application. *

*/ /* private - DO NOT CHANGE */ WorkbenchAdvisor* GetAdvisor(); /** * Returns the window advisor, creating a new one for this window if needed. *

* IMPORTANT This method is declared private to prevent regular plug-ins * from downcasting IWorkbenchWindow to WorkbenchWindow and getting hold of * the window advisor that would allow them to tamper with the window. The * window advisor is internal to the application. *

*/ /* private - DO NOT CHANGE */ WorkbenchWindowAdvisor* GetWindowAdvisor(); /** * Returns the action bar advisor, creating a new one for this window if * needed. *

* IMPORTANT This method is declared private to prevent regular plug-ins * from downcasting IWorkbenchWindow to WorkbenchWindow and getting hold of * the action bar advisor that would allow them to tamper with the window's * action bars. The action bar advisor is internal to the application. *

*/ /* private - DO NOT CHANGE */ ActionBarAdvisor::Pointer GetActionBarAdvisor(); /* * Returns the IWorkbench implementation. */ Workbench* GetWorkbenchImpl(); bool UnableToRestorePage(IMemento::Pointer pageMem); /** * Close the window. * * Assumes that busy cursor is active. */ bool BusyClose(); /** * Unconditionally close this window. Assumes the proper flags have been set * correctly (e.i. closing and updateDisabled) */ bool HardClose(); /** * Close all of the pages. */ void CloseAllPages(); /** * Save all of the pages. Returns true if the operation succeeded. */ bool SaveAllPages(bool bConfirm); void ShowEmptyWindowContents(); void HideEmptyWindowContents(); struct ShellEventFilter : public QObject { ShellEventFilter(WorkbenchWindow* window); bool eventFilter(QObject* watched, QEvent* event) override; private: void SaveBounds(const QRect& newBounds); void ShellActivated(); void ShellDeactivated(); WorkbenchWindow* window; }; ShellEventFilter resizeEventFilter; /** * Hooks a listener to track the resize of the window's shell. Stores the * new bounds if in normal state - that is, not in minimized or maximized * state) */ void TrackShellResize(Shell::Pointer newShell); /** * Returns true iff we are currently deferring UI processing due to a large * update * * @return true iff we are deferring UI updates. */ bool UpdatesDeferred() const; /** * Initializes all of the default command-based services for the workbench * window. */ void InitializeDefaultServices(); void FirePropertyChanged(const QString& property, const Object::Pointer& oldValue, const Object::Pointer& newValue); }; } #endif /*BERRYWORKBENCHWINDOW_H_*/ diff --git a/Plugins/org.mitk.gui.qt.application/plugin.xml b/Plugins/org.mitk.gui.qt.application/plugin.xml index 13a35d3932..e96ccfb5d2 100644 --- a/Plugins/org.mitk.gui.qt.application/plugin.xml +++ b/Plugins/org.mitk.gui.qt.application/plugin.xml @@ -1,23 +1,23 @@ - + - + diff --git a/Plugins/org.mitk.gui.qt.application/src/internal/QmitkToolBarsPreferencePage.cpp b/Plugins/org.mitk.gui.qt.application/src/internal/QmitkToolBarsPreferencePage.cpp index 4d69aee495..69d1f6d073 100644 --- a/Plugins/org.mitk.gui.qt.application/src/internal/QmitkToolBarsPreferencePage.cpp +++ b/Plugins/org.mitk.gui.qt.application/src/internal/QmitkToolBarsPreferencePage.cpp @@ -1,208 +1,153 @@ /*============================================================================ 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 "QmitkToolBarsPreferencePage.h" #include #include #include #include #include #include -#include -#include - namespace { mitk::IPreferences* GetPreferences() { auto prefService = mitk::CoreServices::GetPreferencesService(); return prefService->GetSystemPreferences()->Node(QmitkApplicationConstants::TOOL_BARS_PREFERENCES); } - // Get views as multimap with categories as keys. - // - // Exclude views without category and categories that contain a literal '.', e.g. - // "org.blueberry.ui" or "org.mitk.views.general", as they typically do not have - // a corresponding tool bar. - std::multimap GetViews() - { - std::multimap result; - - const auto workbench = berry::PlatformUI::GetWorkbench(); - const auto viewRegistry = workbench->GetViewRegistry(); - const auto views = viewRegistry->GetViews(); - - for (auto view : views) - { - QString category; - - if (auto categoryPath = view->GetCategoryPath(); !categoryPath.isEmpty()) - category = categoryPath.back(); - - if (!category.isEmpty() && !category.contains('.') && !view->IsInternal()) - result.emplace(category, view); - } - - return result; - } - - // Get all toolbars of all (typically one) Workbench windows. - std::vector GetToolBars() - { - std::vector result; - - const auto* workbench = berry::PlatformUI::GetWorkbench(); - auto workbenchWindows = workbench->GetWorkbenchWindows(); - - for (auto workbenchWindow : workbenchWindows) - { - if (auto shell = workbenchWindow->GetShell(); shell.IsNotNull()) - { - if (const auto* mainWindow = qobject_cast(shell->GetControl()); mainWindow != nullptr) - { - for (auto child : mainWindow->children()) - { - if (auto toolBar = qobject_cast(child); toolBar != nullptr) - result.push_back(toolBar); - } - } - } - } - - return result; - } - // Find a toolbar by object name and apply preferences. - bool ApplyPreferences(const std::vector& toolBars, const QString& name, bool isVisible, bool showCategory) + bool ApplyPreferences(const QList& toolBars, const QString& name, bool isVisible, bool showCategory) { auto it = std::find_if(toolBars.cbegin(), toolBars.cend(), [&name](const QToolBar* toolBar) { return toolBar->objectName() == name; - }); + }); if (it != toolBars.cend()) { auto toolBar = *it; toolBar->setVisible(isVisible); for (auto action : toolBar->actions()) { if (action->objectName() == "category") { action->setVisible(showCategory); break; } } return true; } return false; } } QmitkToolBarsPreferencePage::QmitkToolBarsPreferencePage() : m_Ui(new Ui::QmitkToolBarsPreferencePage), m_Control(nullptr) { } QmitkToolBarsPreferencePage::~QmitkToolBarsPreferencePage() { } void QmitkToolBarsPreferencePage::Init(berry::IWorkbench::Pointer) { } void QmitkToolBarsPreferencePage::CreateQtControl(QWidget* parent) { m_Control = new QWidget(parent); m_Ui->setupUi(m_Control); - const auto views = GetViews(); + const auto views = berry::PlatformUI::GetWorkbench()->GetViewRegistry()->GetViewsByCategory(); - for (auto category = views.cbegin(), end = views.cend(); category != end; category = views.upper_bound(category->first)) + for(const auto& category : views.uniqueKeys()) { auto categoryItem = new QTreeWidgetItem; - categoryItem->setText(0, category->first); + categoryItem->setText(0, category); categoryItem->setCheckState(0, Qt::Checked); - const auto range = views.equal_range(category->first); + auto [viewIter, end] = views.equal_range(category); - for (auto view = range.first; view != range.second; ++view) + while (viewIter != end) { auto viewItem = new QTreeWidgetItem; - viewItem->setText(0, view->second->GetLabel()); - viewItem->setIcon(0, view->second->GetImageDescriptor()); + viewItem->setText(0, (*viewIter)->GetLabel()); + viewItem->setIcon(0, (*viewIter)->GetImageDescriptor()); categoryItem->addChild(viewItem); + ++viewIter; } m_Ui->treeWidget->addTopLevelItem(categoryItem); } this->Update(); } QWidget* QmitkToolBarsPreferencePage::GetQtControl() const { return m_Control; } bool QmitkToolBarsPreferencePage::PerformOk() { auto prefs = GetPreferences(); bool showCategories = m_Ui->showCategoriesCheckBox->isChecked(); prefs->PutBool(QmitkApplicationConstants::TOOL_BARS_SHOW_CATEGORIES, showCategories); - const auto toolBars = GetToolBars(); + const auto toolBars = berry::PlatformUI::GetWorkbench()->GetWorkbenchWindows().first()->GetToolBars(); for (int i = 0, count = m_Ui->treeWidget->topLevelItemCount(); i < count; ++i) { const auto* item = m_Ui->treeWidget->topLevelItem(i); const auto category = item->text(0); const bool isVisible = item->checkState(0) == Qt::Checked; prefs->PutBool(category.toStdString(), isVisible); if (!ApplyPreferences(toolBars, category, isVisible, showCategories)) MITK_WARN << "Could not find tool bar for category \"" << category << "\" to set its visibility!"; } return true; } void QmitkToolBarsPreferencePage::PerformCancel() { } void QmitkToolBarsPreferencePage::Update() { const auto prefs = GetPreferences(); m_Ui->showCategoriesCheckBox->setChecked(prefs->GetBool(QmitkApplicationConstants::TOOL_BARS_SHOW_CATEGORIES, true)); for (int i = 0, count = m_Ui->treeWidget->topLevelItemCount(); i < count; ++i) { auto item = m_Ui->treeWidget->topLevelItem(i); const auto category = item->text(0).toStdString(); const bool isVisible = prefs->GetBool(category, true); item->setCheckState(0, isVisible ? Qt::Checked : Qt::Unchecked); } } diff --git a/Plugins/org.mitk.gui.qt.ext/files.cmake b/Plugins/org.mitk.gui.qt.ext/files.cmake index b4b7d9d037..26872bf821 100644 --- a/Plugins/org.mitk.gui.qt.ext/files.cmake +++ b/Plugins/org.mitk.gui.qt.ext/files.cmake @@ -1,58 +1,65 @@ set(SRC_CPP_FILES QmitkExtActionBarAdvisor.cpp QmitkExtWorkbenchWindowAdvisor.cpp QmitkExtFileSaveProjectAction.cpp QmitkOpenDicomEditorAction.cpp QmitkOpenMxNMultiWidgetEditorAction.cpp QmitkOpenStdMultiWidgetEditorAction.cpp + QmitkStartupDialog.cpp ) set(INTERNAL_CPP_FILES QmitkAboutHandler.cpp QmitkAppInstancesPreferencePage.cpp + QmitkStartupPreferencePage.cpp QmitkCommonExtPlugin.cpp QmitkModuleView.cpp ) set(UI_FILES src/internal/QmitkAppInstancesPreferencePage.ui + src/internal/QmitkStartupPreferencePage.ui + src/QmitkStartupDialog.ui ) set(MOC_H_FILES src/QmitkExtFileSaveProjectAction.h src/QmitkExtWorkbenchWindowAdvisor.h src/internal/QmitkAboutHandler.h src/internal/QmitkAppInstancesPreferencePage.h + src/internal/QmitkStartupPreferencePage.h src/internal/QmitkCommonExtPlugin.h src/internal/QmitkExtWorkbenchWindowAdvisorHack.h src/internal/QmitkModuleView.h src/QmitkOpenDicomEditorAction.h src/QmitkOpenMxNMultiWidgetEditorAction.h src/QmitkOpenStdMultiWidgetEditorAction.h + src/QmitkStartupDialog.h ) set(CACHED_RESOURCE_FILES # list of resource files which can be used by the plug-in # system without loading the plug-ins shared library, # for example the icon used in the menu and tabs for the # plug-in views in the workbench plugin.xml resources/ModuleView.png ) set(QRC_FILES # uncomment the following line if you want to use Qt resources resources/org_mitk_gui_qt_ext.qrc resources/org_mitk_icons.qrc + resources/org_mitk_presets.qrc ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.ext/plugin.xml b/Plugins/org.mitk.gui.qt.ext/plugin.xml index 293a24f24a..d5ab903f46 100644 --- a/Plugins/org.mitk.gui.qt.ext/plugin.xml +++ b/Plugins/org.mitk.gui.qt.ext/plugin.xml @@ -1,32 +1,36 @@ + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/org_mitk_presets.qrc b/Plugins/org.mitk.gui.qt.ext/resources/org_mitk_presets.qrc new file mode 100644 index 0000000000..afd4787eb2 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/org_mitk_presets.qrc @@ -0,0 +1,8 @@ + + + presets/classic.json + presets/segmentation_only.json + presets/modelfit.json + presets/custom.json + + diff --git a/Plugins/org.mitk.gui.qt.ext/resources/presets/classic.json b/Plugins/org.mitk.gui.qt.ext/resources/presets/classic.json new file mode 100644 index 0000000000..4c107129e4 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/presets/classic.json @@ -0,0 +1,12 @@ +{ + "name": "Classic", + "info": "Display commonly used plugins, filtering out those that are less relevant to the majority of users.", + "categories": [ + "Data", + "General", + "Help", + "Quantification", + "Registration", + "Segmentation" + ] +} diff --git a/Plugins/org.mitk.gui.qt.ext/resources/presets/custom.json b/Plugins/org.mitk.gui.qt.ext/resources/presets/custom.json new file mode 100644 index 0000000000..4d8d3e507d --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/presets/custom.json @@ -0,0 +1,4 @@ +{ + "name": "Custom", + "info": "Create your own preset in the \"Tool Bars\" page of the preferences." +} diff --git a/Plugins/org.mitk.gui.qt.ext/resources/presets/modelfit.json b/Plugins/org.mitk.gui.qt.ext/resources/presets/modelfit.json new file mode 100644 index 0000000000..51f518c38a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/presets/modelfit.json @@ -0,0 +1,9 @@ +{ + "name": "ModelFit", + "info": "Display plugins for model fits and their exploration, including:\n\n
    \n
  • A general purpose fitting tool using frequently used generic models and formula parsing
  • \n
  • Pharmacokinetic analysis for DCE MRI using compartment models
  • \n
  • Semi-quantitative analysis for dynamic images using non-compartmental approaches
  • \n
  • Voxel-wise fit visualization for evaluation of fit quality
  • \n
", + "ancestor": "Classic", + "categories": [ + "Fitting", + "Perfusion" + ] +} diff --git a/Plugins/org.mitk.gui.qt.ext/resources/presets/segmentation_only.json b/Plugins/org.mitk.gui.qt.ext/resources/presets/segmentation_only.json new file mode 100644 index 0000000000..398cdd7b8b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/resources/presets/segmentation_only.json @@ -0,0 +1,9 @@ +{ + "name": "Segmentation only", + "info": "Display only essential plugins necessary for segmentation.", + "categories": [ + "Data", + "General", + "Segmentation" + ] +} diff --git a/Plugins/org.mitk.gui.qt.ext/src/QmitkExtWorkbenchWindowAdvisor.cpp b/Plugins/org.mitk.gui.qt.ext/src/QmitkExtWorkbenchWindowAdvisor.cpp index b7d3a96ce9..64bf26566a 100644 --- a/Plugins/org.mitk.gui.qt.ext/src/QmitkExtWorkbenchWindowAdvisor.cpp +++ b/Plugins/org.mitk.gui.qt.ext/src/QmitkExtWorkbenchWindowAdvisor.cpp @@ -1,1433 +1,1504 @@ /*============================================================================ 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 "QmitkExtWorkbenchWindowAdvisor.h" #include "QmitkExtActionBarAdvisor.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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // UGLYYY #include "internal/QmitkExtWorkbenchWindowAdvisorHack.h" #include "internal/QmitkCommonExtPlugin.h" #include "mitkUndoController.h" #include "mitkVerboseLimitedLinearUndo.h" #include #include #include #include #include #include +#include QmitkExtWorkbenchWindowAdvisorHack* QmitkExtWorkbenchWindowAdvisorHack::undohack = new QmitkExtWorkbenchWindowAdvisorHack(); QString QmitkExtWorkbenchWindowAdvisor::QT_SETTINGS_FILENAME = "QtSettings.ini"; static bool USE_EXPERIMENTAL_COMMAND_CONTRIBUTIONS = false; +namespace +{ + void ExecuteStartupDialog() + { + QmitkStartupDialog startupDialog; + + if (startupDialog.SkipDialog()) + return; + + try + { + if (startupDialog.exec() != QDialog::Accepted) + return; + } + catch (const mitk::Exception& e) + { + MITK_ERROR << e.GetDescription(); + return; + } + + // Create two lists: one for all categories and one subset for visible categories. + + QStringList allCategories = berry::PlatformUI::GetWorkbench()->GetViewRegistry()->GetViewsByCategory().uniqueKeys(); + QStringList visibleCategories; + + if (startupDialog.UsePreset()) + { + visibleCategories = startupDialog.GetPresetCategories(); + + if (visibleCategories.isEmpty()) // "Custom" preset + { + // Early-out and show the "Tool Bars" preference page instead. + QmitkExtWorkbenchWindowAdvisorHack::undohack->onEditPreferences("org.mitk.ToolBarsPreferencePage"); + return; + } + } + else + { + visibleCategories = allCategories; + } + + // Now set the visibility preferences for all categories and apply them instantly. + + auto prefsService = mitk::CoreServices::GetPreferencesService(); + auto prefs = prefsService->GetSystemPreferences()->Node(QmitkApplicationConstants::TOOL_BARS_PREFERENCES); + const auto toolBars = berry::PlatformUI::GetWorkbench()->GetWorkbenchWindows().first()->GetToolBars(); + + for (const auto& category : allCategories) + { + bool isVisible = visibleCategories.contains(category); + prefs->PutBool(category.toStdString(), isVisible); + + auto toolBarIter = std::find_if(toolBars.cbegin(), toolBars.cend(), [&category](const QToolBar* toolBar) { + return toolBar->objectName() == category; + }); + + if (toolBarIter != toolBars.cend()) + (*toolBarIter)->setVisible(isVisible); + } + + prefs->Flush(); + } +} + class PartListenerForTitle: public berry::IPartListener { public: PartListenerForTitle(QmitkExtWorkbenchWindowAdvisor* 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: QmitkExtWorkbenchWindowAdvisor* windowAdvisor; }; class PartListenerForViewNavigator: public berry::IPartListener { public: PartListenerForViewNavigator(QAction* act) : viewNavigatorAction(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.viewnavigator") { viewNavigatorAction->setChecked(true); } } void PartClosed(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.viewnavigator") { viewNavigatorAction->setChecked(false); } } void PartVisible(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.viewnavigator") { viewNavigatorAction->setChecked(true); } } void PartHidden(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.viewnavigator") { viewNavigatorAction->setChecked(false); } } private: QAction* viewNavigatorAction; }; 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(QmitkExtWorkbenchWindowAdvisor* wa) : windowAdvisor(wa) , perspectivesClosed(false) { } Events::Types GetPerspectiveEventTypes() const override { if (USE_EXPERIMENTAL_COMMAND_CONTRIBUTIONS) { return Events::ACTIVATED | Events::SAVED_AS | Events::DEACTIVATED; } else { 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); } //GetViewRegistry()->Find("org.mitk.views.imagenavigator"); if(windowAdvisor->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.dicombrowser")) { windowAdvisor->openDicomEditorAction->setEnabled(true); } if (windowAdvisor->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.stdmultiwidget")) { windowAdvisor->openStdMultiWidgetEditorAction->setEnabled(true); } if (windowAdvisor->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.mxnmultiwidget")) { windowAdvisor->openMxNMultiWidgetEditorAction->setEnabled(true); } windowAdvisor->fileSaveProjectAction->setEnabled(true); windowAdvisor->closeProjectAction->setEnabled(true); windowAdvisor->undoAction->setEnabled(true); windowAdvisor->redoAction->setEnabled(true); windowAdvisor->imageNavigatorAction->setEnabled(true); windowAdvisor->viewNavigatorAction->setEnabled(true); windowAdvisor->resetPerspAction->setEnabled(true); if( windowAdvisor->GetShowClosePerspectiveMenuItem() ) { windowAdvisor->closePerspAction->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); } if(windowAdvisor->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.dicombrowser")) { windowAdvisor->openDicomEditorAction->setEnabled(false); } if (windowAdvisor->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.stdmultiwidget")) { windowAdvisor->openStdMultiWidgetEditorAction->setEnabled(false); } if (windowAdvisor->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.mxnmultiwidget")) { windowAdvisor->openMxNMultiWidgetEditorAction->setEnabled(false); } windowAdvisor->fileSaveProjectAction->setEnabled(false); windowAdvisor->closeProjectAction->setEnabled(false); windowAdvisor->undoAction->setEnabled(false); windowAdvisor->redoAction->setEnabled(false); windowAdvisor->imageNavigatorAction->setEnabled(false); windowAdvisor->viewNavigatorAction->setEnabled(false); windowAdvisor->resetPerspAction->setEnabled(false); if( windowAdvisor->GetShowClosePerspectiveMenuItem() ) { windowAdvisor->closePerspAction->setEnabled(false); } } } private: QmitkExtWorkbenchWindowAdvisor* windowAdvisor; bool perspectivesClosed; }; class PerspectiveListenerForMenu: public berry::IPerspectiveListener { public: PerspectiveListenerForMenu(QmitkExtWorkbenchWindowAdvisor* 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: QmitkExtWorkbenchWindowAdvisor* windowAdvisor; }; QmitkExtWorkbenchWindowAdvisor::QmitkExtWorkbenchWindowAdvisor(berry::WorkbenchAdvisor* wbAdvisor, berry::IWorkbenchWindowConfigurer::Pointer configurer) : berry::WorkbenchWindowAdvisor(configurer) , lastInput(nullptr) , wbAdvisor(wbAdvisor) , showViewToolbar(true) , showPerspectiveToolbar(false) , showVersionInfo(true) , showMitkVersionInfo(true) , showViewMenuItem(true) , showNewWindowMenuItem(false) , showClosePerspectiveMenuItem(true) , viewNavigatorFound(false) , showMemoryIndicator(true) , dropTargetListener(new QmitkDefaultDropTargetListener) { productName = QCoreApplication::applicationName(); viewExcludeList.push_back("org.mitk.views.viewnavigator"); } QmitkExtWorkbenchWindowAdvisor::~QmitkExtWorkbenchWindowAdvisor() { } berry::ActionBarAdvisor::Pointer QmitkExtWorkbenchWindowAdvisor::CreateActionBarAdvisor(berry::IActionBarConfigurer::Pointer configurer) { if (USE_EXPERIMENTAL_COMMAND_CONTRIBUTIONS) { berry::ActionBarAdvisor::Pointer actionBarAdvisor(new QmitkExtActionBarAdvisor(configurer)); return actionBarAdvisor; } else { return berry::WorkbenchWindowAdvisor::CreateActionBarAdvisor(configurer); } } QWidget* QmitkExtWorkbenchWindowAdvisor::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 QmitkExtWorkbenchWindowAdvisor::ShowClosePerspectiveMenuItem(bool show) { showClosePerspectiveMenuItem = show; } bool QmitkExtWorkbenchWindowAdvisor::GetShowClosePerspectiveMenuItem() { return showClosePerspectiveMenuItem; } void QmitkExtWorkbenchWindowAdvisor::ShowMemoryIndicator(bool show) { showMemoryIndicator = show; } bool QmitkExtWorkbenchWindowAdvisor::GetShowMemoryIndicator() { return showMemoryIndicator; } void QmitkExtWorkbenchWindowAdvisor::ShowNewWindowMenuItem(bool show) { showNewWindowMenuItem = show; } void QmitkExtWorkbenchWindowAdvisor::ShowViewToolbar(bool show) { showViewToolbar = show; } void QmitkExtWorkbenchWindowAdvisor::ShowViewMenuItem(bool show) { showViewMenuItem = show; } void QmitkExtWorkbenchWindowAdvisor::ShowPerspectiveToolbar(bool show) { showPerspectiveToolbar = show; } void QmitkExtWorkbenchWindowAdvisor::ShowVersionInfo(bool show) { showVersionInfo = show; } void QmitkExtWorkbenchWindowAdvisor::ShowMitkVersionInfo(bool show) { showMitkVersionInfo = show; } void QmitkExtWorkbenchWindowAdvisor::SetProductName(const QString& product) { productName = product; } void QmitkExtWorkbenchWindowAdvisor::SetWindowIcon(const QString& wndIcon) { windowIcon = wndIcon; } void QmitkExtWorkbenchWindowAdvisor::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/"); auto fileOpenAction = new QmitkFileOpenAction(berry::QtStyleManager::ThemeIcon(basePath + "document-open.svg"), window); fileOpenAction->setShortcut(QKeySequence::Open); auto fileSaveAction = new QmitkFileSaveAction(berry::QtStyleManager::ThemeIcon(basePath + "document-save.svg"), window); fileSaveAction->setShortcut(QKeySequence::Save); fileSaveProjectAction = new QmitkExtFileSaveProjectAction(window); fileSaveProjectAction->setIcon(berry::QtStyleManager::ThemeIcon(basePath + "document-save.svg")); closeProjectAction = new QmitkCloseProjectAction(window); closeProjectAction->setIcon(berry::QtStyleManager::ThemeIcon(basePath + "edit-delete.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); } if (!USE_EXPERIMENTAL_COMMAND_CONTRIBUTIONS) { QMenu* fileMenu = menuBar->addMenu("&File"); fileMenu->setObjectName("FileMenu"); fileMenu->addAction(fileOpenAction); fileMenu->addAction(fileSaveAction); fileMenu->addAction(fileSaveProjectAction); fileMenu->addAction(closeProjectAction); 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", QKeySequence("CTRL+Z"), QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onUndo())); undoAction->setToolTip("Undo the last action (not supported by all modules)"); redoAction = editMenu->addAction( berry::QtStyleManager::ThemeIcon(basePath + "edit-redo.svg"), "&Redo", QKeySequence("CTRL+Y"), QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onRedo())); redoAction->setToolTip("execute the last action that was undone again (not supported by all modules)"); // ==== Window Menu ========================== QMenu* windowMenu = menuBar->addMenu("Window"); if (showNewWindowMenuItem) { windowMenu->addAction("&New Window", QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onNewWindow())); windowMenu->addSeparator(); } QMenu* perspMenu = windowMenu->addMenu("&Open Perspective"); QMenu* viewMenu = nullptr; if (showViewMenuItem) { viewMenu = windowMenu->addMenu("Show &View"); viewMenu->setObjectName("Show View"); } windowMenu->addSeparator(); resetPerspAction = windowMenu->addAction("&Reset Perspective", QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onResetPerspective())); if(showClosePerspectiveMenuItem) closePerspAction = windowMenu->addAction("&Close Perspective", QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onClosePerspective())); windowMenu->addSeparator(); windowMenu->addAction("&Preferences...", QKeySequence("CTRL+P"), QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onEditPreferences())); // 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()); if (showViewMenuItem) { for (auto viewAction : std::as_const(viewActions)) { viewMenu->addAction(viewAction); } } // ===== 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", QKeySequence("F1"), this, SLOT(onHelp())); helpMenu->addAction("&About",this, SLOT(onAbout())); // ===================================================== } else { undoAction = new QmitkUndoAction(berry::QtStyleManager::ThemeIcon(basePath + "edit-undo.svg"), nullptr); undoAction->setShortcut(QKeySequence::Undo); redoAction = new QmitkRedoAction(berry::QtStyleManager::ThemeIcon(basePath + "edit-redo.svg"), nullptr); redoAction->setShortcut(QKeySequence::Redo); } // 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 (this->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.dicombrowser")) { openDicomEditorAction = new QmitkOpenDicomEditorAction(berry::QtStyleManager::ThemeIcon(basePath + "dicom.svg"), window); } if (this->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.stdmultiwidget")) { openStdMultiWidgetEditorAction = new QmitkOpenStdMultiWidgetEditorAction(berry::QtStyleManager::ThemeIcon(basePath + "Editor.svg"), window); } if (this->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.mxnmultiwidget")) { openMxNMultiWidgetEditorAction = new QmitkOpenMxNMultiWidgetEditorAction(berry::QtStyleManager::ThemeIcon(basePath + "Editor.svg"), window); } if (imageNavigatorViewFound) { QObject::connect(imageNavigatorAction, SIGNAL(triggered(bool)), QmitkExtWorkbenchWindowAdvisorHack::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"); } viewNavigatorAction = new QAction(berry::QtStyleManager::ThemeIcon(QStringLiteral(":/org.mitk.gui.qt.ext/view-manager.svg")),"&View Navigator", nullptr); viewNavigatorFound = window->GetWorkbench()->GetViewRegistry()->Find("org.mitk.views.viewnavigator"); if (viewNavigatorFound) { QObject::connect(viewNavigatorAction, SIGNAL(triggered(bool)), QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onViewNavigator())); viewNavigatorAction->setCheckable(true); // add part listener for view navigator viewNavigatorPartListener.reset(new PartListenerForViewNavigator(viewNavigatorAction)); window->GetPartService()->AddPartListener(viewNavigatorPartListener.data()); berry::IViewPart::Pointer viewnavigatorview = window->GetActivePage()->FindView("org.mitk.views.viewnavigator"); viewNavigatorAction->setChecked(false); if (viewnavigatorview) { bool isViewNavigatorVisible = window->GetActivePage()->IsPartVisible(viewnavigatorview); if (isViewNavigatorVisible) viewNavigatorAction->setChecked(true); } viewNavigatorAction->setToolTip("Toggle View Navigator"); } mainActionsToolBar->addAction(fileOpenAction); mainActionsToolBar->addAction(fileSaveProjectAction); mainActionsToolBar->addAction(closeProjectAction); mainActionsToolBar->addAction(undoAction); mainActionsToolBar->addAction(redoAction); if(this->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.dicombrowser")) { mainActionsToolBar->addAction(openDicomEditorAction); } if (this->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.stdmultiwidget")) { mainActionsToolBar->addAction(openStdMultiWidgetEditorAction); } if (this->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.mxnmultiwidget")) { mainActionsToolBar->addAction(openMxNMultiWidgetEditorAction); } if (imageNavigatorViewFound) { mainActionsToolBar->addAction(imageNavigatorAction); } if (viewNavigatorFound) { mainActionsToolBar->addAction(viewNavigatorAction); } mainWindow->addToolBar(mainActionsToolBar); // ==== Perspective Toolbar ================================== auto qPerspectiveToolbar = new QToolBar; qPerspectiveToolbar->setObjectName("perspectiveToolBar"); if (showPerspectiveToolbar) { qPerspectiveToolbar->addActions(perspGroup->actions()); mainWindow->addToolBar(qPerspectiveToolbar); } else delete qPerspectiveToolbar; if (showViewToolbar) { auto* prefService = mitk::CoreServices::GetPreferencesService(); auto* toolBarsPrefs = prefService->GetSystemPreferences()->Node(QmitkApplicationConstants::TOOL_BARS_PREFERENCES); bool showCategories = toolBarsPrefs->GetBool(QmitkApplicationConstants::TOOL_BARS_SHOW_CATEGORIES, true); // Order view descriptors by category QMultiMap categoryViewDescriptorMap; for (const 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 (const auto &category : categoryViewDescriptorMap.uniqueKeys()) { auto viewDescriptorsInCurrentCategory = categoryViewDescriptorMap.values(category); if (!viewDescriptorsInCurrentCategory.isEmpty()) { auto toolbar = new QToolBar; toolbar->setObjectName(category); mainWindow->addToolBar(toolbar); toolbar->setVisible(toolBarsPrefs->GetBool(category.toStdString(), true)); if (!category.isEmpty()) { auto categoryButton = new QToolButton; categoryButton->setToolButtonStyle(Qt::ToolButtonTextOnly); categoryButton->setText(category); categoryButton->setStyleSheet("background: transparent; margin: 0; padding: 0;"); auto action = toolbar->addWidget(categoryButton); action->setObjectName("category"); action->setVisible(showCategories); 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), QCursor::pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(0.0f, 0.0f), QCursor::pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); QApplication::sendEvent(widget, &pressEvent); QApplication::sendEvent(widget, &releaseEvent); } } }); } for (const auto &viewDescriptor : std::as_const(viewDescriptorsInCurrentCategory)) { 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(); // progBar->AddStepsToDo(2); // progBar->Progress(1); mainWindow->setStatusBar(qStatusBar); if (showMemoryIndicator) { auto memoryIndicator = new QmitkMemoryUsageIndicatorView(); qStatusBar->addPermanentWidget(memoryIndicator, 0); } } void QmitkExtWorkbenchWindowAdvisor::PreWindowOpen() { berry::IWorkbenchWindowConfigurer::Pointer configurer = GetWindowConfigurer(); // show the shortcut bar and progress indicator, which are hidden by // default //configurer->SetShowPerspectiveBar(true); //configurer->SetShowFastViewBars(true); //configurer->SetShowProgressIndicator(true); // // add the drag and drop support for the editor area // configurer.addEditorAreaTransfer(EditorInputTransfer.getInstance()); // configurer.addEditorAreaTransfer(ResourceTransfer.getInstance()); // configurer.addEditorAreaTransfer(FileTransfer.getInstance()); // configurer.addEditorAreaTransfer(MarkerTransfer.getInstance()); // configurer.configureEditorAreaDropListener(new EditorAreaDropAdapter( // configurer.getWindow())); this->HookTitleUpdateListeners(configurer); menuPerspectiveListener.reset(new PerspectiveListenerForMenu(this)); configurer->GetWindow()->AddPerspectiveListener(menuPerspectiveListener.data()); configurer->AddEditorAreaTransfer(QStringList("text/uri-list")); configurer->ConfigureEditorAreaDropListener(dropTargetListener.data()); } void QmitkExtWorkbenchWindowAdvisor::PostWindowOpen() { berry::WorkbenchWindowAdvisor::PostWindowOpen(); // Force Rendering Window Creation on startup. berry::IWorkbenchWindowConfigurer::Pointer configurer = GetWindowConfigurer(); ctkPluginContext* context = QmitkCommonExtPlugin::getContext(); 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); } } auto introPart = configurer->GetWindow()->GetWorkbench()->GetIntroManager()->GetIntro(); if (introPart.IsNotNull()) { configurer->GetWindow()->GetWorkbench()->GetIntroManager()->ShowIntro(GetWindowConfigurer()->GetWindow(), false); } + + ExecuteStartupDialog(); } void QmitkExtWorkbenchWindowAdvisor::onIntro() { QmitkExtWorkbenchWindowAdvisorHack::undohack->onIntro(); } void QmitkExtWorkbenchWindowAdvisor::onHelp() { QmitkExtWorkbenchWindowAdvisorHack::undohack->onHelp(); } void QmitkExtWorkbenchWindowAdvisor::onHelpOpenHelpPerspective() { QmitkExtWorkbenchWindowAdvisorHack::undohack->onHelpOpenHelpPerspective(); } void QmitkExtWorkbenchWindowAdvisor::onAbout() { QmitkExtWorkbenchWindowAdvisorHack::undohack->onAbout(); } //-------------------------------------------------------------------------------- // Ugly hack from here on. Feel free to delete when command framework // and undo buttons are done. //-------------------------------------------------------------------------------- QmitkExtWorkbenchWindowAdvisorHack::QmitkExtWorkbenchWindowAdvisorHack() : QObject() { } QmitkExtWorkbenchWindowAdvisorHack::~QmitkExtWorkbenchWindowAdvisorHack() { } void QmitkExtWorkbenchWindowAdvisorHack::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 QmitkExtWorkbenchWindowAdvisorHack::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 QmitkExtWorkbenchWindowAdvisorHack::onImageNavigator() { // show/hide ImageNavigatorView SafeHandleNavigatorView("org.mitk.views.imagenavigator"); } void QmitkExtWorkbenchWindowAdvisorHack::onViewNavigator() { // show/hide viewnavigatorView SafeHandleNavigatorView("org.mitk.views.viewnavigator"); } -void QmitkExtWorkbenchWindowAdvisorHack::onEditPreferences() +void QmitkExtWorkbenchWindowAdvisorHack::onEditPreferences(const QString& selectedPage) { QmitkPreferencesDialog _PreferencesDialog(QApplication::activeWindow()); + + if (!selectedPage.isEmpty()) + _PreferencesDialog.SetSelectedPage(selectedPage); + _PreferencesDialog.exec(); } void QmitkExtWorkbenchWindowAdvisorHack::onQuit() { berry::PlatformUI::GetWorkbench()->Close(); } void QmitkExtWorkbenchWindowAdvisorHack::onResetPerspective() { berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage()->ResetPerspective(); } void QmitkExtWorkbenchWindowAdvisorHack::onClosePerspective() { berry::IWorkbenchPage::Pointer page = berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage(); page->ClosePerspective(page->GetPerspective(), true, true); } void QmitkExtWorkbenchWindowAdvisorHack::onNewWindow() { berry::PlatformUI::GetWorkbench()->OpenWorkbenchWindow(nullptr); } void QmitkExtWorkbenchWindowAdvisorHack::onIntro() { if (berry::PlatformUI::GetWorkbench()->GetIntroManager()->HasIntro()) { berry::PlatformUI::GetWorkbench()->GetIntroManager()->ShowIntro( berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow(), false); } } void QmitkExtWorkbenchWindowAdvisorHack::onHelp() { ctkPluginContext* context = QmitkCommonExtPlugin::getContext(); 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 QmitkExtWorkbenchWindowAdvisorHack::onHelpOpenHelpPerspective() { berry::PlatformUI::GetWorkbench()->ShowPerspective("org.blueberry.perspectives.help", berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()); } void QmitkExtWorkbenchWindowAdvisorHack::onAbout() { auto aboutDialog = new QmitkAboutDialog(QApplication::activeWindow(), {}); aboutDialog->open(); } void QmitkExtWorkbenchWindowAdvisor::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< QmitkExtWorkbenchWindowAdvisor>(this, &QmitkExtWorkbenchWindowAdvisor::PropertyChange)); // configurer.getWindow().addPageListener(new IPageListener() { // public void pageActivated(IWorkbenchPage page) { // updateTitle(false); // } // // public void pageClosed(IWorkbenchPage page) { // updateTitle(false); // } // // public void pageOpened(IWorkbenchPage page) { // // do nothing // } // }); configurer->GetWindow()->AddPerspectiveListener(titlePerspectiveListener.data()); configurer->GetWindow()->GetPartService()->AddPartListener(titlePartListener.data()); } QString QmitkExtWorkbenchWindowAdvisor::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 QmitkExtWorkbenchWindowAdvisor::RecomputeTitle() { berry::IWorkbenchWindowConfigurer::Pointer configurer = GetWindowConfigurer(); QString oldTitle = configurer->GetTitle(); QString newTitle = ComputeTitle(); if (newTitle != oldTitle) { configurer->SetTitle(newTitle); } } void QmitkExtWorkbenchWindowAdvisor::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 QmitkExtWorkbenchWindowAdvisor::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 QmitkExtWorkbenchWindowAdvisor::SetPerspectiveExcludeList(const QList& v) { this->perspectiveExcludeList = v; } QList QmitkExtWorkbenchWindowAdvisor::GetPerspectiveExcludeList() { return this->perspectiveExcludeList; } void QmitkExtWorkbenchWindowAdvisor::SetViewExcludeList(const QList& v) { this->viewExcludeList = v; } QList QmitkExtWorkbenchWindowAdvisor::GetViewExcludeList() { return this->viewExcludeList; } void QmitkExtWorkbenchWindowAdvisor::PostWindowClose() { berry::IWorkbenchWindow::Pointer window = this->GetWindowConfigurer()->GetWindow(); QMainWindow* mainWindow = static_cast (window->GetShell()->GetControl()); auto fileName = this->GetQSettingsFile(); if (!fileName.isEmpty()) { QSettings settings(fileName, QSettings::IniFormat); settings.setValue("ToolbarPosition", mainWindow->saveState()); } } QString QmitkExtWorkbenchWindowAdvisor::GetQSettingsFile() const { QFileInfo settingsInfo = QmitkCommonExtPlugin::getContext()->getDataFile(QT_SETTINGS_FILENAME); return settingsInfo.canonicalFilePath(); } diff --git a/Plugins/org.mitk.gui.qt.ext/src/QmitkStartupDialog.cpp b/Plugins/org.mitk.gui.qt.ext/src/QmitkStartupDialog.cpp new file mode 100644 index 0000000000..aada1234db --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/src/QmitkStartupDialog.cpp @@ -0,0 +1,276 @@ +/*============================================================================ + +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 +#include + +#include +#include +#include + +#include + +#include + +namespace +{ + mitk::IPreferences* GetPreferences() + { + auto* preferencesService = mitk::CoreServices::GetPreferencesService(); + return preferencesService->GetSystemPreferences()->Node("org.mitk.startupdialog"); + } +} + +QT_BEGIN_NAMESPACE + + // Make nlohmann_json understand QString for deserialization. + void from_json(const nlohmann::json& j, QString& result) + { + result = QString::fromStdString(j.get()); + } + +QT_END_NAMESPACE + +class Preset : public QListWidgetItem +{ +public: + static constexpr int NameRole = Qt::DisplayRole; + static constexpr int InfoRole = Qt::UserRole + 1; + static constexpr int CategoriesRole = Qt::UserRole + 2; + + // Load preset from file. See remarks on the Inherit() method below. + explicit Preset(const QString& filename) + { + QFile file(filename); + + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + mitkThrow() << "Couldn't open \"" << filename.toStdString() << "\"!"; + + auto fileContents = QTextStream(&file).readAll().toStdString(); + auto j = nlohmann::json::parse(fileContents, nullptr, false, true); + + if (j.is_discarded()) + mitkThrow() << "Couldn't parse \"" << filename.toStdString() << "\"!"; + + this->Deserialize(j); + } + + // When all presets are loaded, their inheritances have to be resolved by + // iterating through them once and calling Inherit() on each preset. + void Inherit(const QList& presets) + { + if (m_Ancestor.isEmpty()) + return; + + auto isAncestor = [this](const Preset* p) { return p->GetName() == m_Ancestor; }; + auto ancestor = std::find_if(presets.begin(), presets.end(), isAncestor); + + if (ancestor == presets.end()) + { + mitkThrow() << "Preset \"" << this->GetName().toStdString() << "\" cannot inherit from \"" + << m_Ancestor.toStdString() << "\" because it couldn't be found."; + } + + (*ancestor)->Inherit(presets); // Recursively resolve inheritance of ancestors + this->MergeCategories(*ancestor); // Inherit by merging categories + + m_Ancestor.clear(); // No need to resolve inheritance again for this preset + } + + QString GetName() const + { + return this->data(NameRole).toString(); + } + + QString GetInfo() const + { + return this->data(InfoRole).toString(); + } + + QStringList GetCategories() const + { + return this->data(CategoriesRole).toStringList(); + } + +private: + /* Disclaimer: + * This is an internal, probably only temporal file format. + * + * Example: + * { + * "name": "Mandatory name that is displayed in UI", + * "info": "Optional info text in Qt's RichText format that is displayed when the preset is selected", + * "ancestor": "Optional name of another preset of which the categories are merged with this preset", + * "categories": [ + * "List of categories (resp. tool bars)", + * "Strictly speaking it is optional but its absence is a special case for the custom preset", + * "Hence, think of it as mandatory", + * "BTW, only use

and smaller for headers, if any, in the info text above" + * ] + * } + */ + void Deserialize(const nlohmann::json& j) + { + this->setData(Preset::NameRole, j["name"].get()); + + // Prepend name as header to info text + this->setData(Preset::InfoRole, QString("

%1 preset

\n\n%2").arg(this->GetName()).arg(j.value("info", QString()))); + + this->m_Ancestor = j.value("ancestor", QString()); + + if (j.contains("categories")) + this->setData(Preset::CategoriesRole, j["categories"].get()); + } + + void MergeCategories(const Preset* other) + { + auto categories = this->GetCategories(); + categories.append(other->GetCategories()); + categories.removeDuplicates(); + this->setData(CategoriesRole, categories); + } + + QString m_Ancestor; +}; + +QmitkStartupDialog::QmitkStartupDialog(QWidget* parent) + : QDialog(parent), + m_Ui(new Ui::QmitkStartupDialog) +{ + m_Ui->setupUi(this); + + connect(m_Ui->presetRadioButton, &QAbstractButton::toggled, this, &QmitkStartupDialog::OnPresetRadioButtonToggled); + connect(m_Ui->presetListWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QmitkStartupDialog::OnSelectedPresetChanged); + connect(this, &QDialog::finished, this, &QmitkStartupDialog::OnFinished); +} + +QmitkStartupDialog::~QmitkStartupDialog() +{ + delete m_Ui; +} + +bool QmitkStartupDialog::UsePreset() const +{ + return m_Ui->presetRadioButton->isChecked() && m_Ui->presetListWidget->currentItem() != nullptr; +} + +QString QmitkStartupDialog::GetPresetName() const +{ + return m_Ui->presetListWidget->currentItem()->data(Preset::NameRole).toString(); +} + +QStringList QmitkStartupDialog::GetPresetCategories() const +{ + return m_Ui->presetListWidget->currentItem()->data(Preset::CategoriesRole).toStringList(); +} + +// Check if "Do not show this dialog again" is ticked off. +bool QmitkStartupDialog::SkipDialog() const +{ + auto prefs = GetPreferences(); + return prefs->GetBool("skip", false); +} + +// Load preset resources. +// See "resources/org_mitk_presets.qrc". +void QmitkStartupDialog::LoadPresets() +{ + QList presets; + QDirIterator it(":/org_mitk_presets"); + + while (it.hasNext()) + presets.append(new Preset(it.next())); + + // Only after all presets are loaded their inheritances can be resolved + // and the presets finally added to the list widget. + for (auto preset : presets) + { + preset->Inherit(presets); + m_Ui->presetListWidget->addItem(preset); + } +} + +// Load presets and restore previous settings. +void QmitkStartupDialog::showEvent(QShowEvent*) +{ + this->LoadPresets(); + + auto prefs = GetPreferences(); + bool usePreset = prefs->GetBool("use preset", false); + + if (usePreset) + { + m_Ui->presetRadioButton->setChecked(true); + + QString preset = QString::fromStdString(prefs->Get("preset", "")); + + if (preset.isEmpty()) + return; + + auto items = m_Ui->presetListWidget->findItems(preset, Qt::MatchExactly); + + if (!items.isEmpty()) + m_Ui->presetListWidget->setCurrentItem(items.first()); + } +} + +void QmitkStartupDialog::OnPresetRadioButtonToggled(bool checked) +{ + m_Ui->presetListWidget->setEnabled(checked); + + if (!checked) + { + m_Ui->presetListWidget->clearSelection(); + } + else if (m_Ui->presetListWidget->count() > 0) + { + m_Ui->presetListWidget->setCurrentRow(0); + } +} + +void QmitkStartupDialog::OnSelectedPresetChanged(const QItemSelection& selected, const QItemSelection&) +{ + if (selected.empty()) + { + m_Ui->presetLabel->clear(); + return; + } + + m_Ui->presetLabel->setText(m_Ui->presetListWidget->selectedItems().front()->data(Preset::InfoRole).toString()); +} + +// Save settings to restore them next time. +void QmitkStartupDialog::OnFinished(int result) +{ + auto prefs = GetPreferences(); + + bool skipDialog = m_Ui->skipDialogCheckBox->isChecked(); + prefs->PutBool("skip", skipDialog); + + if (result == QDialog::Accepted) + { + bool usePreset = m_Ui->presetRadioButton->isChecked(); + prefs->PutBool("use preset", usePreset); + + if (usePreset) + { + auto preset = m_Ui->presetListWidget->currentItem()->text().toStdString(); + prefs->Put("preset", preset); + } + else + { + prefs->Remove("preset"); + } + } + + prefs->Flush(); +} diff --git a/Plugins/org.mitk.gui.qt.ext/src/QmitkStartupDialog.h b/Plugins/org.mitk.gui.qt.ext/src/QmitkStartupDialog.h new file mode 100644 index 0000000000..ac78f25336 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/src/QmitkStartupDialog.h @@ -0,0 +1,46 @@ +/*============================================================================ + +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 + +class QItemSelection; + +namespace Ui +{ + class QmitkStartupDialog; +} + +class QmitkStartupDialog : public QDialog +{ + Q_OBJECT + +public: + explicit QmitkStartupDialog(QWidget* parent = nullptr); + ~QmitkStartupDialog() override; + + bool SkipDialog() const; + + bool UsePreset() const; + QString GetPresetName() const; + QStringList GetPresetCategories() const; + +private: + void LoadPresets(); + + void showEvent(QShowEvent* event) override; + + void OnPresetRadioButtonToggled(bool checked); + void OnSelectedPresetChanged(const QItemSelection& selected, const QItemSelection& deselected); + void OnFinished(int result); + + Ui::QmitkStartupDialog* m_Ui; +}; diff --git a/Plugins/org.mitk.gui.qt.ext/src/QmitkStartupDialog.ui b/Plugins/org.mitk.gui.qt.ext/src/QmitkStartupDialog.ui new file mode 100644 index 0000000000..5c66f1087a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/src/QmitkStartupDialog.ui @@ -0,0 +1,228 @@ + + + QmitkStartupDialog + + + Qt::ApplicationModal + + + + 0 + 0 + 480 + 480 + + + + MITK Workbench + + + true + + + true + + + + + + <h2>Welcome to the MITK Workbench</h2> + + + Qt::RichText + + + 4 + + + + + + + + + Show all plugins + + + true + + + + + + + Use a plugin preset: + + + + + + + + + + + false + + + + 0 + 50 + + + + + 16777215 + 120 + + + + QAbstractItemView::NoEditTriggers + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Maximum + + + + 16 + 20 + + + + + + + + QFrame::NoFrame + + + true + + + + + 0 + 0 + 438 + 210 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + + + Qt::RichText + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + + + + + + + + + Can be changed in Preferences (Ctrl+P) again + + + Do not show this dialog again + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + defaultRadioButton + presetRadioButton + presetListWidget + skipDialogCheckBox + + + + + buttonBox + accepted() + QmitkStartupDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + QmitkStartupDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkCommonExtPlugin.cpp b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkCommonExtPlugin.cpp index 390dfdf75f..32159fa505 100644 --- a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkCommonExtPlugin.cpp +++ b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkCommonExtPlugin.cpp @@ -1,236 +1,238 @@ /*============================================================================ 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 "QmitkCommonExtPlugin.h" #include #include "QmitkAboutHandler.h" #include "QmitkAppInstancesPreferencePage.h" +#include "QmitkStartupPreferencePage.h" #include "QmitkModuleView.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include US_INITIALIZE_MODULE ctkPluginContext* QmitkCommonExtPlugin::_context = nullptr; void QmitkCommonExtPlugin::start(ctkPluginContext* context) { this->_context = context; QtWidgetsExtRegisterClasses(); BERRY_REGISTER_EXTENSION_CLASS(QmitkAboutHandler, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkAppInstancesPreferencePage, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkStartupPreferencePage, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkModuleView, context) if (qApp->metaObject()->indexOfSignal("messageReceived(QByteArray)") > -1) { connect(qApp, SIGNAL(messageReceived(QByteArray)), this, SLOT(handleIPCMessage(QByteArray))); } // This is a potentially long running operation. loadDataFromDisk(berry::Platform::GetApplicationArgs(), true); } void QmitkCommonExtPlugin::stop(ctkPluginContext* context) { Q_UNUSED(context) this->_context = nullptr; } ctkPluginContext* QmitkCommonExtPlugin::getContext() { return _context; } void QmitkCommonExtPlugin::loadDataFromDisk(const QStringList &arguments, bool globalReinit) { if (!arguments.empty()) { ctkServiceReference serviceRef = _context->getServiceReference(); if (serviceRef) { mitk::IDataStorageService* dataStorageService = _context->getService(serviceRef); mitk::DataStorage::Pointer dataStorage = dataStorageService->GetDefaultDataStorage()->GetDataStorage(); int argumentsAdded = 0; for (int i = 0; i < arguments.size(); ++i) { if (arguments[i].right(5) == ".mitk") { mitk::SceneIO::Pointer sceneIO = mitk::SceneIO::New(); bool clearDataStorageFirst(false); mitk::ProgressBar::GetInstance()->AddStepsToDo(2); dataStorage = sceneIO->LoadScene( arguments[i].toLocal8Bit().constData(), dataStorage, clearDataStorageFirst ); mitk::ProgressBar::GetInstance()->Progress(2); argumentsAdded++; } else if (arguments[i].right(15) == ".mitksceneindex") { mitk::SceneIO::Pointer sceneIO = mitk::SceneIO::New(); bool clearDataStorageFirst(false); mitk::ProgressBar::GetInstance()->AddStepsToDo(2); dataStorage = sceneIO->LoadSceneUnzipped(arguments[i].toLocal8Bit().constData(), dataStorage, clearDataStorageFirst); mitk::ProgressBar::GetInstance()->Progress(2); argumentsAdded++; } else { try { const std::string path(arguments[i].toStdString()); auto addedNodes = mitk::IOUtil::Load(path, *dataStorage); for (const auto& node : *addedNodes ) { node->SetIntProperty("layer", argumentsAdded); } argumentsAdded++; } catch(...) { MITK_WARN << "Failed to load command line argument: " << arguments[i].toStdString(); } } } // end for each command line argument if (argumentsAdded > 0 && globalReinit) { // calculate bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(dataStorage->ComputeBoundingGeometry3D()); } } else { MITK_ERROR << "A service reference for mitk::IDataStorageService does not exist"; } } } void QmitkCommonExtPlugin::startNewInstance(const QStringList &args, const QStringList& files) { QStringList newArgs(args); #ifdef Q_OS_UNIX newArgs << QString("--") + mitk::BaseApplication::ARG_NEWINSTANCE; #else newArgs << QString("/") + mitk::BaseApplication::ARG_NEWINSTANCE; #endif newArgs << files; QProcess::startDetached(qApp->applicationFilePath(), newArgs); } void QmitkCommonExtPlugin::handleIPCMessage(const QByteArray& msg) { QDataStream ds(msg); QString msgType; ds >> msgType; // we only handle messages containing command line arguments if (msgType != "$cmdLineArgs") return; // activate the current workbench window berry::IWorkbenchWindow::Pointer window = berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow(); QMainWindow* mainWindow = static_cast (window->GetShell()->GetControl()); mainWindow->setWindowState(mainWindow->windowState() & ~Qt::WindowMinimized); mainWindow->raise(); mainWindow->activateWindow(); // Get the preferences for the instantiation behavior auto* prefService = mitk::CoreServices::GetPreferencesService(); auto* prefs = prefService->GetSystemPreferences()->Node("/General"); bool newInstanceAlways = prefs->GetBool("newInstance.always", false); bool newInstanceScene = prefs->GetBool("newInstance.scene", true); QStringList args; ds >> args; QStringList fileArgs; QStringList sceneArgs; foreach (QString arg, args) { if (arg.endsWith(".mitk")) { sceneArgs << arg; } else { fileArgs << arg; } } if (newInstanceAlways) { if (newInstanceScene) { startNewInstance(args, fileArgs); foreach(QString sceneFile, sceneArgs) { startNewInstance(args, QStringList(sceneFile)); } } else { fileArgs.append(sceneArgs); startNewInstance(args, fileArgs); } } else { loadDataFromDisk(fileArgs, false); if (newInstanceScene) { foreach(QString sceneFile, sceneArgs) { startNewInstance(args, QStringList(sceneFile)); } } else { loadDataFromDisk(sceneArgs, false); } } } diff --git a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExtWorkbenchWindowAdvisorHack.h b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExtWorkbenchWindowAdvisorHack.h index c5c190b5fa..6b9d740c7c 100644 --- a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExtWorkbenchWindowAdvisorHack.h +++ b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkExtWorkbenchWindowAdvisorHack.h @@ -1,60 +1,60 @@ /*============================================================================ 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 QmitkExtWorkbenchWindowAdvisorHack_h #define QmitkExtWorkbenchWindowAdvisorHack_h #include class ctkPluginContext; class QmitkPreferencesDialog; class QmitkExtWorkbenchWindowAdvisorHack : public QObject { Q_OBJECT public slots: void onUndo(); void onRedo(); void onImageNavigator(); void onViewNavigator(); - void onEditPreferences(); + void onEditPreferences(const QString& selectedPage = ""); void onQuit(); void onResetPerspective(); void onClosePerspective(); void onNewWindow(); void onIntro(); /** * @brief This slot is called if the user clicks the menu item "help->context help" or presses F1. * The help page is shown in a workbench editor. */ void onHelp(); void onHelpOpenHelpPerspective(); /** * @brief This slot is called if the user clicks in help menu the about button */ void onAbout(); public: QmitkExtWorkbenchWindowAdvisorHack(); ~QmitkExtWorkbenchWindowAdvisorHack() override; static QmitkExtWorkbenchWindowAdvisorHack* undohack; }; #endif diff --git a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkStartupPreferencePage.cpp b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkStartupPreferencePage.cpp new file mode 100644 index 0000000000..145d0e5496 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkStartupPreferencePage.cpp @@ -0,0 +1,73 @@ +/*============================================================================ + +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 "QmitkStartupPreferencePage.h" +#include + +#include +#include +#include + +namespace +{ + mitk::IPreferences* GetPreferences() + { + auto* preferencesService = mitk::CoreServices::GetPreferencesService(); + return preferencesService->GetSystemPreferences()->Node("org.mitk.startupdialog"); + } +} + +QmitkStartupPreferencePage::QmitkStartupPreferencePage() + : m_Ui(new Ui::QmitkStartupPreferencePage), + m_Control(nullptr) +{ +} + +QmitkStartupPreferencePage::~QmitkStartupPreferencePage() +{ + delete m_Ui; +} + +void QmitkStartupPreferencePage::CreateQtControl(QWidget* parent) +{ + m_Control = new QWidget(parent); + m_Ui->setupUi(m_Control); + + this->Update(); +} + +QWidget* QmitkStartupPreferencePage::GetQtControl() const +{ + return m_Control; +} + +void QmitkStartupPreferencePage::Init(berry::IWorkbench::Pointer) +{ +} + +void QmitkStartupPreferencePage::PerformCancel() +{ +} + +bool QmitkStartupPreferencePage::PerformOk() +{ + auto* prefs = GetPreferences(); + prefs->PutBool("skip", !m_Ui->showDialogCheckBox->isChecked()); + + return true; +} + +void QmitkStartupPreferencePage::Update() +{ + auto* prefs = GetPreferences(); + m_Ui->showDialogCheckBox->setChecked(!prefs->GetBool("skip", false)); +} diff --git a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkStartupPreferencePage.h b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkStartupPreferencePage.h new file mode 100644 index 0000000000..c736bc75f6 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkStartupPreferencePage.h @@ -0,0 +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. + +============================================================================*/ + +#ifndef QmitkStartupPreferencePage_h +#define QmitkStartupPreferencePage_h + +#include + +namespace Ui +{ + class QmitkStartupPreferencePage; +} + +class QmitkStartupPreferencePage : public QObject, public berry::IQtPreferencePage +{ + Q_OBJECT + Q_INTERFACES(berry::IPreferencePage) + +public: + QmitkStartupPreferencePage(); + ~QmitkStartupPreferencePage() override; + + void CreateQtControl(QWidget* parent) override; + QWidget* GetQtControl() const override; + void Init(berry::IWorkbench::Pointer) override; + void PerformCancel() override; + bool PerformOk() override; + void Update() override; + +private: + Ui::QmitkStartupPreferencePage* m_Ui; + QWidget* m_Control; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkStartupPreferencePage.ui b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkStartupPreferencePage.ui new file mode 100644 index 0000000000..08ea4a940a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.ext/src/internal/QmitkStartupPreferencePage.ui @@ -0,0 +1,44 @@ + + + QmitkStartupPreferencePage + + + + 0 + 0 + 563 + 288 + + + + Application Startup + + + + + + Show preset dialog at application startup + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + +