Skip to content

Commit

Permalink
Added Settings menu to Main Window with Theme options (#2144)
Browse files Browse the repository at this point in the history
  • Loading branch information
samtygier-stfc committed Apr 12, 2024
2 parents 5b827de + 764091e commit ea787c4
Show file tree
Hide file tree
Showing 12 changed files with 467 additions and 4 deletions.
3 changes: 3 additions & 0 deletions conda/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ requirements:
- jenkspy=0.2.0
- pyqt=5.15.*
- pyqtgraph=0.13.3
- qt-material=2.14
- darkdetect=0.8.0
- qt-gtk-platformtheme # [linux]


build:
number: 1
entry_points:
Expand Down
19 changes: 19 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from collections import Counter

import pytest
from PyQt5 import QtCore
from PyQt5.QtGui import QFont

from mantidimaging.core.utility.leak_tracker import leak_tracker

Expand Down Expand Up @@ -63,3 +65,20 @@ def leak_test_stats():

# leak_tracker.clear() # Uncomment to clear after each test
# print(leak_tracker.pretty_print(debug_owners=True)) # uncomment to track leaks


@pytest.fixture(autouse=True)
def setup_QSettings():
settings = QtCore.QSettings('mantidproject', 'Mantid Imaging')
default_font = QFont()
extra_style_default = {

# Density Scale
'density_scale': '-5',

# font
'font_size': str(default_font.pointSize()) + 'px',
}
settings.setValue('extra_style_default', extra_style_default)
if settings.value('extra_style') is None:
settings.setValue('extra_style', extra_style_default)
1 change: 1 addition & 0 deletions docs/release_notes/next/feature-2144-UI-theme-settings
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#2144: MI UI theme can be changed in runtime via a settings menu
9 changes: 8 additions & 1 deletion mantidimaging/gui/mvp_base/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@
import time
from logging import getLogger

from PyQt5 import QtCore
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QMainWindow, QMessageBox, QDialog
from PyQt5.QtWidgets import QMainWindow, QMessageBox, QDialog, QApplication

from mantidimaging.gui.utility import compile_ui

LOG = getLogger(__name__)
perf_logger = getLogger("perf." + __name__)
settings = QtCore.QSettings('mantidproject', 'Mantid Imaging')

if not settings.contains("theme_selection") or settings.value("theme_selection") is None:
settings.setValue('theme_selection', 'Fusion')


class BaseMainWindowView(QMainWindow):
Expand All @@ -25,6 +30,8 @@ def __init__(self, parent, ui_file=None):
if ui_file is not None:
compile_ui(ui_file, self)

QApplication.instance().setStyle(settings.value('theme_selection'))

def closeEvent(self, e):
LOG.debug('UI window closed')
self.cleanup()
Expand Down
9 changes: 8 additions & 1 deletion mantidimaging/gui/ui/main_window.ui
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<x>0</x>
<y>0</y>
<width>1100</width>
<height>25</height>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
Expand All @@ -46,6 +46,8 @@
<addaction name="separator"/>
<addaction name="actionLiveViewer"/>
<addaction name="separator"/>
<addaction name="actionSettings"/>
<addaction name="separator"/>
<addaction name="actionExit"/>
</widget>
<widget class="QMenu" name="menuWorkflow">
Expand Down Expand Up @@ -239,6 +241,11 @@
<string>Open Live Viewer</string>
</property>
</action>
<action name="actionSettings">
<property name="text">
<string>Settings</string>
</property>
</action>
</widget>
<resources/>
<connections/>
Expand Down
157 changes: 157 additions & 0 deletions mantidimaging/gui/ui/settings_window.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SettingsWindow</class>
<widget class="QMainWindow" name="SettingsWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>454</width>
<height>444</height>
</rect>
</property>
<property name="maximumSize">
<size>
<width>456</width>
<height>449</height>
</size>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<widget class="QWidget" name="verticalWidget" native="true">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>1921</width>
<height>951</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTabWidget" name="settingsTabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="appearanceTab">
<attribute name="title">
<string>Appearance</string>
</attribute>
<widget class="QWidget" name="formLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>411</width>
<height>361</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="themeLabel">
<property name="text">
<string>Theme:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="themeName">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="menuFontSizeLabel">
<property name="text">
<string>Menu font size:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="menuFontSizeChoice">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="useOsThemeLabel">
<property name="text">
<string>Dark mode:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="darkModeCheckBox">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Use OS defaults: </string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="osDefaultsCheckBox">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
63 changes: 63 additions & 0 deletions mantidimaging/gui/windows/main/presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
from collections.abc import Iterable

import numpy as np
from PyQt5.QtCore import QSettings, Qt
from PyQt5.QtGui import QFont, QPalette, QColor
from PyQt5.QtWidgets import QTabBar, QApplication, QTreeWidgetItem
from qt_material import apply_stylesheet

from mantidimaging.core.data import ImageStack
from mantidimaging.core.data.dataset import StrictDataset, MixedDataset, _get_stack_data_type
Expand All @@ -29,6 +32,8 @@

RECON_TEXT = "Recon"

settings = QSettings('mantidproject', 'Mantid Imaging')


class StackId(NamedTuple):
id: uuid.UUID
Expand Down Expand Up @@ -828,3 +833,61 @@ def _create_strict_dataset_stack_name(stack_type: str, dataset_name: str) -> str

def is_dataset_strict(self, ds_id: uuid.UUID) -> bool:
return self.model.is_dataset_strict(ds_id)

def do_update_UI(self) -> None:
if settings.value('use_os_defaults', defaultValue='True') == 'True':
extra_style = settings.value('extra_style_default')
theme = 'Fusion'
override_os_theme = 'False'
else:
extra_style = settings.value('extra_style')
use_dark_mode = settings.value('use_dark_mode')
theme = settings.value('theme_selection')
override_os_theme = settings.value('override_os_theme')
os_theme = settings.value('os_theme')
font = QFont(settings.value('default_font_family'), int(extra_style['font_size'].replace('px', '')))
for window in [
self.view, self.view.recon, self.view.live_viewer, self.view.spectrum_viewer, self.view.filters,
self.view.settings_window
]:
if window:
QApplication.instance().setFont(font)
window.setStyleSheet(theme)
if theme == 'Fusion':
if override_os_theme == 'False':
if os_theme == 'Light':
self.use_fusion_light_mode()
elif os_theme == 'Dark':
self.use_fusion_dark_mode()
else:
if use_dark_mode == 'True':
self.use_fusion_dark_mode()
else:
self.use_fusion_light_mode()
QApplication.instance().setFont(font)
window.setStyleSheet(theme)
else:
apply_stylesheet(window, theme=theme, invert_secondary=False, extra=extra_style)

@staticmethod
def use_fusion_dark_mode() -> None:
palette = QPalette()
palette.setColor(QPalette.Window, QColor(53, 53, 53))
palette.setColor(QPalette.WindowText, Qt.white)
palette.setColor(QPalette.Base, QColor(25, 25, 25))
palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
palette.setColor(QPalette.ToolTipBase, Qt.black)
palette.setColor(QPalette.ToolTipText, Qt.white)
palette.setColor(QPalette.Text, Qt.white)
palette.setColor(QPalette.Button, QColor(53, 53, 53))
palette.setColor(QPalette.ButtonText, Qt.white)
palette.setColor(QPalette.BrightText, Qt.red)
palette.setColor(QPalette.Link, QColor(42, 130, 218))
palette.setColor(QPalette.Highlight, QColor(42, 130, 218))
palette.setColor(QPalette.HighlightedText, Qt.black)
QApplication.instance().setPalette(palette)

@staticmethod
def use_fusion_light_mode() -> None:
palette = QPalette()
QApplication.instance().setPalette(palette)
Loading

0 comments on commit ea787c4

Please sign in to comment.