Medical Imaging Interaction Toolkit  2018.4.99-31d1c60d
Medical Imaging Interaction Toolkit
Customizing the Main Window using Qt-Stylesheets

In a final step, we want to further customize the appearance of our mainWindow to give it an distinct non-native look and feel. We want to achieve this by pursuing the following aims:

  • Change the background and widget colors
  • Change the tab-widget and ToolButton style, also with respect to mouse-over-button (hovering) effects
  • Completing the non-native tab-widget like impression of the perspectives by gluing tab-bar and perspective's PageComposite together
  • DICOM Import functionality

For GUI customization, we will modify the Qt-Stylesheets files already used by blueberry applications. Within the Qt-Stylesheet-Files, all widgets can globally and locally be adressed inside the main window for style changes. We have to adress the berry::IQtStyleManager to tell the BlueBerry workbench to use a specific Qt-Stylesheet. This is done inside the WorkbenchAdvisor in the CustomViewerWorkbenchAdvisor::Initialize() method:

void CustomViewerWorkbenchAdvisor::Initialize(berry::IWorkbenchConfigurer::Pointer configurer)
{
ctkPluginContext *pluginContext = org_mitk_example_gui_customviewer_Activator::GetPluginContext();
ctkServiceReference serviceReference = pluginContext->getServiceReference<berry::IQtStyleManager>();
// always granted by org.blueberry.ui.qt
Q_ASSERT(serviceReference);
berry::IQtStyleManager *styleManager = pluginContext->getService<berry::IQtStyleManager>(serviceReference);
Q_ASSERT(styleManager);
QString styleName = "CustomStyle";
styleManager->AddStyle(":/customstyle.qss", styleName);
styleManager->SetStyle(":/customstyle.qss");
// styleManager->AddStyle("/home/me/customstyle.qss", styleName);
// styleManager->SetStyle("/home/me/customstyle.qss");
}

The style manager is taken from the application's plugin context via service reference. Invoking the berry::IQtStyleManager::AddStyle() and berry::IQtStyleManager::SetStyle() methods, the workbench will now use the announced qss-File to style our Workbench Window. In a production system, the stylesheets are usually compiled into the plug-in or application using the Qt resource system. However, during developement of the stylesheets it is often more convenient to reference them using a hard-coded path to the local file system (see live update functionality below).

Before we start customization we will first provide some customization convenience. We add an UpdateStyle()-slot to our CustomViewerWorkbenchWindowAdvisor where we explicitly reset the css-File to the style manager:

void CustomViewerWorkbenchWindowAdvisor::UpdateStyle()
{
ctkPluginContext *pluginContext = org_mitk_example_gui_customviewer_Activator::GetPluginContext();
ctkServiceReference serviceReference = pluginContext->getServiceReference<berry::IQtStyleManager>();
// granted by org.blueberry.ui.qt
Q_ASSERT(serviceReference);
berry::IQtStyleManager *styleManager = pluginContext->getService<berry::IQtStyleManager>(serviceReference);
Q_ASSERT(styleManager);
styleManager->SetStyle("/home/me/customstyle.qss");
}

By integrating an update style button to the Application's main window and connecting this button with the previously defined slot, we can now button-push-update the style on runtime. This will of course only work for stylesheets which are referenced from the local file system.

StyledMainWindow0.png
The unstyled Main Window

First we might want to change the background color style by setting the background color of the QWidget::CentralWidget to a linear gradient from light to dark blue:

QWidget#CentralWidget
{
background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(43, 75, 116), stop:1 rgb(197, 245, 254));
}

Then, we give the page composite control widget a slight grey border (except for the upper border where no border should be visible) and the same background color as the activated tab widget:

QWidget#PageCompositeControlWidget
{
border-left: 1px solid #a0a0a0;
border-bottom: 1px solid #a0a0a0;
border-right: 1px solid #a0a0a0;
margin: 0px;
padding: 10px;
background: rgb(210, 221, 239);
}

The image below depicts the style changes.

StyledMainWindow2.png
Background-color changed Central and Composite Control Widgets

Concerning the tab-widget style, four states have to be customized: QtPerspectiveSwitcherTabBar::tab (the tab in general), QtPerspectiveSwitcherTabBar::tab:selected (when tab is selected), QtPerspectiveSwitcherTabBar::tab:selected:hover (when tab is selected and the mouse is hovering above), QtPerspectiveSwitcherTabBar::tab:!selected:hover (respectively).

All tabs are given round corners using border-top-left- and border-top-right-radius definitions. Additionally, all tabs is provided a gap to its neighbor defining a positive margin right. Selected tabs appear bigger by defining a negative upper margin, and they have no lower frame in the unselected state so a tab-widget appearance is provided. Finally, they have a brighter background color also used by the QWidget::ClientComposite. Hovering tabs are colored yellow and have a visible lower border:

QtPerspectiveSwitcherTabBar::tab
{
min-height: 24px;
border-top: 1px solid palette(mid);
border-left: 1px solid palette(mid);
border-bottom: 0px;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
margin-top: -1px;
margin-right: 4px;
padding-left: 5px;
background: rgb(210, 221, 239);
}
QtPerspectiveSwitcherTabBar::tab:selected:hover {
border-bottom: 1px solid palette(mid);
background: yellow;
}
QtPerspectiveSwitcherTabBar::tab:!selected {
margin-top: 5px;
background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(156, 181, 220), stop:1 rgb(130, 160, 210));
}
QtPerspectiveSwitcherTabBar::tab:!selected:hover {
background: yellow;
}

Finally, we customize the Push- and Tool-Buttons in a similar way:

QToolButton#FileOpenButton
{
min-height: 20px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border: 1px solid gray;
padding-left: 5px;
background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(156, 181, 220), stop:1 rgb(130, 160, 210));
}
QToolButton#FileOpenButton:hover
{
background: yellow;
}
QPushButton#StyleUpdateButton
{
min-height: 25px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(210, 221, 239), stop:1 rgb(197, 245, 254));
}

The resulting style-customized main window is shown below (the style update button removed).

StyledMainWindow_final1.png
The final version of our Custom Viewer (viewer perspective).
StyledMainWindow_final2.png
The final version of our Custom Viewer (DICOM perspective).

Proceed to the previous page Adding functionality: Data Manager, Render Window, File Opening and DICOM Import.