From 592b5976687873e1e543187f8eab0ca367f48ecc Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 24 Oct 2022 16:56:20 -0400 Subject: [PATCH 01/67] Create a global style sheet attached to MainWindow that is housed in the user directory. --- src/sas/qtgui/MainWindow/MainWindow.py | 4 +- src/sas/system/__init__.py | 2 +- src/sas/system/sasview.css | 6 +++ src/sas/system/style.py | 73 ++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 src/sas/system/sasview.css create mode 100644 src/sas/system/style.py diff --git a/src/sas/qtgui/MainWindow/MainWindow.py b/src/sas/qtgui/MainWindow/MainWindow.py index 875332ea1f..eeef74a76c 100644 --- a/src/sas/qtgui/MainWindow/MainWindow.py +++ b/src/sas/qtgui/MainWindow/MainWindow.py @@ -5,7 +5,7 @@ import sys from sas import config -from sas.system import env, version +from sas.system import env, version, style from PyQt5.QtWidgets import QMainWindow from PyQt5.QtWidgets import QMdiArea @@ -98,7 +98,7 @@ def run_sasview(): splash.show() app.setAttribute(Qt.AA_EnableHighDpiScaling) # Main application style. - #app.setStyle('Fusion') + app.setStyleSheet(style.style_sheet()) # fix for pyinstaller packages app to avoid ReactorAlreadyInstalledError if 'twisted.internet.reactor' in sys.modules: diff --git a/src/sas/system/__init__.py b/src/sas/system/__init__.py index 5b84646217..8bf008909d 100644 --- a/src/sas/system/__init__.py +++ b/src/sas/system/__init__.py @@ -3,4 +3,4 @@ from .env import env from .config.config import config -__all__ = ["web", "legal", "env", "config"] \ No newline at end of file +__all__ = ["web", "legal", "env", "config", "style"] diff --git a/src/sas/system/sasview.css b/src/sas/system/sasview.css new file mode 100644 index 0000000000..67636f614b --- /dev/null +++ b/src/sas/system/sasview.css @@ -0,0 +1,6 @@ +* {font-size: 10pt;} + +QLineEdit {background-color: white; color: black;} +QLineEdit:focus {background-color: #98dbcc; color: #333333} + +.warning {background-color: red;} \ No newline at end of file diff --git a/src/sas/system/style.py b/src/sas/system/style.py new file mode 100644 index 0000000000..59cc11b358 --- /dev/null +++ b/src/sas/system/style.py @@ -0,0 +1,73 @@ +import os +import pkg_resources +import sys + +from sas.system import user + +DEFAULT_STYLE_SHEET_NAME = 'sasview.css' + + +class StyleSheet: + """ + The directory where the per-user style sheet is stored. + + Returns ~/.sasview/sasview.css, creating it if it does not already exist. + """ + def __init__(self): + self.style_sheet = None + self._find_style_sheet() + self.save() + + def style_sheet_filename(self): + """Filename for saving config items""" + user_dir = user.get_user_dir() + self.style_sheet = os.path.join(user_dir, DEFAULT_STYLE_SHEET_NAME) + + def save(self): + self._find_style_sheet() + sheet = self() + self.style_sheet_filename() + with open(self.style_sheet, 'a') as file: + file.write(sheet) + + def _find_style_sheet(self, filename=DEFAULT_STYLE_SHEET_NAME): + ''' + The style sheet is in: + User directory ~/.sasview/ + Debug . + Packaging: sas/sasview/ + Packaging / production does not work well with absolute paths + thus the multiple paths below + ''' + self.style_sheet_filename() + places_to_look_for_conf_file = [ + self.style_sheet, + os.path.join(os.path.abspath(os.path.dirname(__file__)), filename), + filename, + os.path.join("sas", "system", filename), + os.path.join(os.getcwd(), "sas", "system", filename), + os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), filename) #For OSX app + ] + + # To avoid the exception in OSx + # NotImplementedError: resource_filename() only supported for .egg, not .zip + try: + places_to_look_for_conf_file.append( + pkg_resources.resource_filename(__name__, filename)) + except NotImplementedError: + pass + + for filepath in places_to_look_for_conf_file: + if os.path.exists(filepath): + self.style_sheet = filepath + return + print(f"'{filename}' not found.", file=sys.stderr) + self.style_sheet = None + + def __call__(self, *args, **kwargs): + with open(self.style_sheet) as f: + style = f.read() + return style + + +style_sheet = StyleSheet() From 56a129c9462af851949a9c521d8705be7db16aa2 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 12:25:47 -0400 Subject: [PATCH 02/67] Remove inline styles from the about box --- src/sas/qtgui/MainWindow/AboutBox.py | 3 --- src/sas/qtgui/MainWindow/UI/AboutUI.ui | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/sas/qtgui/MainWindow/AboutBox.py b/src/sas/qtgui/MainWindow/AboutBox.py index 582e633c6f..388d677788 100644 --- a/src/sas/qtgui/MainWindow/AboutBox.py +++ b/src/sas/qtgui/MainWindow/AboutBox.py @@ -32,9 +32,6 @@ def addText(self): version = sas.system.version.__version__ self.lblVersion.setText(str(version)) - lbl_font = self.font() - lbl_font.setPointSize(24) - self.lblVersion.setFont(lbl_font) about_text = f""" diff --git a/src/sas/qtgui/MainWindow/UI/AboutUI.ui b/src/sas/qtgui/MainWindow/UI/AboutUI.ui index 584cfabc5b..d56a123431 100755 --- a/src/sas/qtgui/MainWindow/UI/AboutUI.ui +++ b/src/sas/qtgui/MainWindow/UI/AboutUI.ui @@ -27,14 +27,14 @@ - <html><head/><body><p><span style=" font-size:36pt;">SasView</span></p></body></html> + <html><head/><body><h1>SasView<</h1></body></html> - <html><head/><body><p><span style=" font-size:28pt;">TextLabel</span></p></body></html> + <html><head/><body><p class="label">TextLabel</p></body></html> From 592f8c14ad4797744ac02ebea47b5a599304b7a2 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 12:42:51 -0400 Subject: [PATCH 03/67] Remove inline styles from the acknowledgements window --- src/sas/qtgui/MainWindow/UI/AcknowledgementsUI.ui | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/sas/qtgui/MainWindow/UI/AcknowledgementsUI.ui b/src/sas/qtgui/MainWindow/UI/AcknowledgementsUI.ui index f074eea21f..4828a5f4f0 100755 --- a/src/sas/qtgui/MainWindow/UI/AcknowledgementsUI.ui +++ b/src/sas/qtgui/MainWindow/UI/AcknowledgementsUI.ui @@ -62,13 +62,6 @@ 85 - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt;">This work benefited from the use of the SasView application, originally developed under NSF Award DMR-0520547. SasView also contains code developed with funding from the EU Horizon 2020 programme under the SINE2020 project Grant No 654000.</span></p></body></html> - @@ -104,13 +97,6 @@ p, li { white-space: pre-wrap; } 31 - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt;">M. Doucet et al. SasView Version 5.0.3, Zenodo, 10.5281/zenodo.3930098</span></p></body></html> - From be7d3a36f30ae7488587dcab5ff63f8172a921ce Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 12:43:06 -0400 Subject: [PATCH 04/67] Remove inline styles from the data explorer widget --- src/sas/qtgui/MainWindow/UI/DataExplorerUI.ui | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/sas/qtgui/MainWindow/UI/DataExplorerUI.ui b/src/sas/qtgui/MainWindow/UI/DataExplorerUI.ui index 04c47dd53c..f471821b3d 100755 --- a/src/sas/qtgui/MainWindow/UI/DataExplorerUI.ui +++ b/src/sas/qtgui/MainWindow/UI/DataExplorerUI.ui @@ -60,10 +60,7 @@ - <html><head/><body><p><span style=" font-size:8pt;">Load a file with data</span></p></body></html> - - - font: 11pt "MS Shell Dlg 2"; + Load a file with data Load data @@ -198,20 +195,8 @@ 50 - - - MS Shell Dlg 2 - 11 - 50 - false - false - - - <html><head/><body><p><span style=" font-size:8pt;">Send data to perspective</span></p></body></html> - - - font: 11pt "MS Shell Dlg 2"; + Send data to perspective Send data to From 9abf24686b6ee69981117966b354bd6ab93edbd4 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 12:47:58 -0400 Subject: [PATCH 05/67] Remove inline styles from the welcome panel --- src/sas/qtgui/MainWindow/UI/WelcomePanelUI.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sas/qtgui/MainWindow/UI/WelcomePanelUI.ui b/src/sas/qtgui/MainWindow/UI/WelcomePanelUI.ui index 16518c1b1e..e9b9332df0 100755 --- a/src/sas/qtgui/MainWindow/UI/WelcomePanelUI.ui +++ b/src/sas/qtgui/MainWindow/UI/WelcomePanelUI.ui @@ -73,7 +73,7 @@ <html><head/><body><p>Comments? Bugs? Requests?</p> -<p>Send us a ticket at: <a href="mailto:help@sasview.org"><span style=" text-decoration: underline; color:#0000ff;"> help@sasview.org</span></a></p></body></html> +<p>Send us a ticket at: <a href="mailto:help@sasview.org">help@sasview.org</a></p></body></html> true From 876488fcc4af3820e14c19273376b6c1ff3d5701 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 12:50:11 -0400 Subject: [PATCH 06/67] Overwrite style sheet on save instead of appending --- src/sas/system/style.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sas/system/style.py b/src/sas/system/style.py index 59cc11b358..83d0ef3c92 100644 --- a/src/sas/system/style.py +++ b/src/sas/system/style.py @@ -27,7 +27,7 @@ def save(self): self._find_style_sheet() sheet = self() self.style_sheet_filename() - with open(self.style_sheet, 'a') as file: + with open(self.style_sheet, 'w') as file: file.write(sheet) def _find_style_sheet(self, filename=DEFAULT_STYLE_SHEET_NAME): From 7b04a81937939e8a48f2d80dc3054efb2a5eb186 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 12:52:41 -0400 Subject: [PATCH 07/67] Add headers to differentiate different styles --- src/sas/system/sasview.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sas/system/sasview.css b/src/sas/system/sasview.css index 67636f614b..44bfcfa93e 100644 --- a/src/sas/system/sasview.css +++ b/src/sas/system/sasview.css @@ -1,6 +1,12 @@ +/* Global Properties */ * {font-size: 10pt;} +/* HTML Elements */ +h1 {font-size: 240%;} + +/* Qt Elements */ QLineEdit {background-color: white; color: black;} QLineEdit:focus {background-color: #98dbcc; color: #333333} +/* Class-specific Properties */ .warning {background-color: red;} \ No newline at end of file From 05d1aa9a9be1969e549f556eb8973f4b7b302800 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 12:55:28 -0400 Subject: [PATCH 08/67] Replace inline styles in data operations panel with dynamic styles --- .../Calculators/DataOperationUtilityPanel.py | 36 +++++++++---------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/src/sas/qtgui/Calculators/DataOperationUtilityPanel.py b/src/sas/qtgui/Calculators/DataOperationUtilityPanel.py index d7938718a9..adaaf70eaf 100644 --- a/src/sas/qtgui/Calculators/DataOperationUtilityPanel.py +++ b/src/sas/qtgui/Calculators/DataOperationUtilityPanel.py @@ -15,9 +15,6 @@ from .UI.DataOperationUtilityUI import Ui_DataOperationUtility -BG_WHITE = "background-color: rgb(255, 255, 255); color: rgb(0, 0, 0);" -BG_RED = "background-color: rgb(244, 170, 164);" - class DataOperationUtilityPanel(QtWidgets.QDialog, Ui_DataOperationUtility): def __init__(self, parent=None): @@ -271,16 +268,16 @@ def onInputCoefficient(self): if input_to_check is None or input_to_check == '': msg = 'DataOperation: Number requires a float number' logging.warning(msg) - self.txtNumber.setStyleSheet(BG_RED) + self.txtNumber.setProperty('class', 'warning') elif float(self.txtNumber.text()) == 0.: # should be check that 0 is not chosen msg = 'DataOperation: Number requires a non zero number' logging.warning(msg) - self.txtNumber.setStyleSheet(BG_RED) + self.txtNumber.setProperty('class', 'warning') else: - self.txtNumber.setStyleSheet(BG_WHITE) + self.txtNumber.setProperty('class', None) self.data2 = float(self.txtNumber.text()) self.updatePlot(self.graphData2, self.layoutData2, self.data2) @@ -291,13 +288,13 @@ def onCheckChosenData(self): return False else: if self.cbData2.currentText() == 'Number': - self.cbData1.setStyleSheet(BG_WHITE) - self.cbData2.setStyleSheet(BG_WHITE) + self.cbData1.setProperty('class', None) + self.cbData2.setProperty('class', None) return True elif self.data1.__class__.__name__ != self.data2.__class__.__name__: - self.cbData1.setStyleSheet(BG_RED) - self.cbData2.setStyleSheet(BG_RED) + self.cbData1.setProperty('class', 'warning') + self.cbData2.setProperty('class', 'warning') print(self.data1.__class__.__name__ != self.data2.__class__.__name__) logging.error('Cannot compute data of different dimensions') return False @@ -306,8 +303,8 @@ def onCheckChosenData(self): and (len(self.data2.x) != len(self.data1.x) or not all(i == j for i, j in zip(self.data1.x, self.data2.x))): logging.error('Cannot compute 1D data of different lengths') - self.cbData1.setStyleSheet(BG_RED) - self.cbData2.setStyleSheet(BG_RED) + self.cbData1.setProperty('class', 'warning') + self.cbData2.setProperty('class', 'warning') return False elif self.data1.__class__.__name__ == 'Data2D' \ @@ -318,33 +315,32 @@ def onCheckChosenData(self): or not all(i == j for i, j in zip(self.data1.qy_data, self.data2.qy_data)) ): - self.cbData1.setStyleSheet(BG_RED) - self.cbData2.setStyleSheet(BG_RED) + self.cbData1.setProperty('class', 'warning') + self.cbData2.setProperty('class', 'warning') logging.error('Cannot compute 2D data of different lengths') return False else: - self.cbData1.setStyleSheet(BG_WHITE) - self.cbData2.setStyleSheet(BG_WHITE) + self.cbData1.setProperty('class', None) + self.cbData2.setProperty('class', None) return True def onCheckOutputName(self): """ Check that name of output does not already exist """ name_to_check = str(self.txtOutputData.text()) - self.txtOutputData.setStyleSheet(BG_WHITE) if name_to_check is None or name_to_check == '': - self.txtOutputData.setStyleSheet(BG_RED) + self.txtOutputData.setProperty('class', 'warning') logging.warning('No output name') return False elif name_to_check in self.list_data_items: - self.txtOutputData.setStyleSheet(BG_RED) + self.txtOutputData.setProperty('class', 'warning') logging.warning('The Output data name already exists') return False else: - self.txtOutputData.setStyleSheet(BG_WHITE) + self.txtOutputData.setProperty('class', None) return True # ######## From 6cd5cbb1a27c65c1c1da3d86479abdc514baa3fb Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 13:26:00 -0400 Subject: [PATCH 09/67] Move inline styles from generic scattering calculator to the style sheet --- .../Calculators/GenericScatteringCalculator.py | 13 ------------- src/sas/system/sasview.css | 2 +- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/src/sas/qtgui/Calculators/GenericScatteringCalculator.py b/src/sas/qtgui/Calculators/GenericScatteringCalculator.py index 193fc719fb..500575aba0 100644 --- a/src/sas/qtgui/Calculators/GenericScatteringCalculator.py +++ b/src/sas/qtgui/Calculators/GenericScatteringCalculator.py @@ -240,19 +240,6 @@ def __init__(self, parent=None): # TODO the option Ellipsoid has not been implemented self.cbShape.currentIndexChanged.connect(self.selectedshapechange) - # New font to display angstrom symbol - new_font = 'font-family: -apple-system, "Helvetica Neue", "Ubuntu";' - self.lblUnitSolventSLD.setStyleSheet(new_font) - self.lblUnitVolume.setStyleSheet(new_font) - self.lbl5.setStyleSheet(new_font) - self.lblUnitMx.setStyleSheet(new_font) - self.lblUnitMy.setStyleSheet(new_font) - self.lblUnitMz.setStyleSheet(new_font) - self.lblUnitNucl.setStyleSheet(new_font) - self.lblUnitx.setStyleSheet(new_font) - self.lblUnity.setStyleSheet(new_font) - self.lblUnitz.setStyleSheet(new_font) - def setup_display(self): """ This function sets up the GUI display of the different coordinate systems. diff --git a/src/sas/system/sasview.css b/src/sas/system/sasview.css index 44bfcfa93e..61e33f0483 100644 --- a/src/sas/system/sasview.css +++ b/src/sas/system/sasview.css @@ -1,5 +1,5 @@ /* Global Properties */ -* {font-size: 10pt;} +* {font-size: 9pt; font-family: -apple-system, "Helvetica Neue", "Ubuntu";} /* HTML Elements */ h1 {font-size: 240%;} From 9b52fc9bd83d3df118bc4a2070bb6e9a0e627e45 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 13:35:07 -0400 Subject: [PATCH 10/67] Set global font family and style class for special characters --- .../Calculators/GenericScatteringCalculator.py | 12 ++++++++++++ .../Calculators/ResolutionCalculatorPanel.py | 15 +++++++-------- src/sas/system/sasview.css | 5 +++-- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/sas/qtgui/Calculators/GenericScatteringCalculator.py b/src/sas/qtgui/Calculators/GenericScatteringCalculator.py index 500575aba0..8f7960ccc0 100644 --- a/src/sas/qtgui/Calculators/GenericScatteringCalculator.py +++ b/src/sas/qtgui/Calculators/GenericScatteringCalculator.py @@ -240,6 +240,18 @@ def __init__(self, parent=None): # TODO the option Ellipsoid has not been implemented self.cbShape.currentIndexChanged.connect(self.selectedshapechange) + # New font to display angstrom symbol + self.lblUnitSolventSLD.setProperty('class', 'angstrom') + self.lblUnitVolume.setProperty('class', 'angstrom') + self.lbl5.setProperty('class', 'angstrom') + self.lblUnitMx.setProperty('class', 'angstrom') + self.lblUnitMy.setProperty('class', 'angstrom') + self.lblUnitMz.setProperty('class', 'angstrom') + self.lblUnitNucl.setProperty('class', 'angstrom') + self.lblUnitx.setProperty('class', 'angstrom') + self.lblUnity.setProperty('class', 'angstrom') + self.lblUnitz.setProperty('class', 'angstrom') + def setup_display(self): """ This function sets up the GUI display of the different coordinate systems. diff --git a/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py b/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py index 431c960256..ed961209f9 100644 --- a/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py +++ b/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py @@ -46,14 +46,13 @@ def __init__(self, parent=None): self.manager = parent # New font to display angstrom symbol - new_font = 'font-family: -apple-system, "Helvetica Neue", "Ubuntu";' - self.lblUnitWavelength.setStyleSheet(new_font) - self.lblUnitQx.setStyleSheet(new_font) - self.lblUnitQy.setStyleSheet(new_font) - self.lblUnitSigmax.setStyleSheet(new_font) - self.lblUnitSigmay.setStyleSheet(new_font) - self.lblUnitSigmalamd.setStyleSheet(new_font) - self.lblUnit1DSigma.setStyleSheet(new_font) + self.lblUnitWavelength.setProperty('class', 'angstrom') + self.lblUnitQx.setProperty('class', 'angstrom') + self.lblUnitQy.setProperty('class', 'angstrom') + self.lblUnitSigmax.setProperty('class', 'angstrom') + self.lblUnitSigmay.setProperty('class', 'angstrom') + self.lblUnitSigmalamd.setProperty('class', 'angstrom') + self.lblUnit1DSigma.setProperty('class', 'angstrom') # by default Spectrum label and cbCustomSpectrum are not visible self.cbCustomSpectrum.setVisible(False) diff --git a/src/sas/system/sasview.css b/src/sas/system/sasview.css index 61e33f0483..1c0386e4ef 100644 --- a/src/sas/system/sasview.css +++ b/src/sas/system/sasview.css @@ -1,5 +1,5 @@ /* Global Properties */ -* {font-size: 9pt; font-family: -apple-system, "Helvetica Neue", "Ubuntu";} +* {font-size: 9pt; font-family: "Lucinda Grande", "Lucinda Sans Unicode", Helvetica, Arial, Verdana, sans-serif} /* HTML Elements */ h1 {font-size: 240%;} @@ -9,4 +9,5 @@ QLineEdit {background-color: white; color: black;} QLineEdit:focus {background-color: #98dbcc; color: #333333} /* Class-specific Properties */ -.warning {background-color: red;} \ No newline at end of file +.warning {background-color: red;} +.angstrom {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} From d479fa7bc0d6a451d26012f27bc227ea5100d889 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 14:38:15 -0400 Subject: [PATCH 11/67] Create GuiUtils widget property updater and apply urgent property to model addition editor --- src/sas/qtgui/Utilities/AddMultEditor.py | 14 +++++++------- src/sas/qtgui/Utilities/GuiUtils.py | 11 +++++++++++ src/sas/system/sasview.css | 5 ++++- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/sas/qtgui/Utilities/AddMultEditor.py b/src/sas/qtgui/Utilities/AddMultEditor.py index c870083296..c4fe19ec46 100644 --- a/src/sas/qtgui/Utilities/AddMultEditor.py +++ b/src/sas/qtgui/Utilities/AddMultEditor.py @@ -35,10 +35,6 @@ Model = make_model_from_info(model_info) """ -# Color of backgrounds to underline valid or invalid input -BG_WHITE = "background-color: rgb(255, 255, 255);" -BG_RED = "background-color: rgb(244, 170, 164);" - class AddMultEditor(QtWidgets.QDialog, Ui_AddMultEditorUI): """ @@ -87,6 +83,7 @@ def __init__(self, parent=None): rx = QtCore.QRegExp("^[A-Za-z0-9_]*$") txt_validator = QtGui.QRegExpValidator(rx) self.txtName.setValidator(txt_validator) + GuiUtils.updateProperty(self.txtName, 'urgent', 'false') def setupModels(self): """ Add list of models to 'Model1' and 'Model2' comboboxes """ @@ -160,7 +157,7 @@ def onNameCheck(self): # allow overwriting -> only valid name needs to be checked # (done with validator in __init__ above) self.good_name = True - self.txtName.setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(self.txtName, 'urgent', 'false') self.plugin_filename = os.path.join(self.plugin_dir, filename) else: # No overwriting -> check existence of filename @@ -169,7 +166,10 @@ def onNameCheck(self): models_list = [item + '.py' for item in self.list_models] if filename in models_list: self.good_name = False - self.txtName.setStyleSheet(BG_RED) + GuiUtils.updateProperty(self.txtName, 'urgent', 'true') + self.txtName.style().unpolish(self.txtName) + self.txtName.style().polish(self.txtName) + self.txtName.update() msg = "Plugin with specified name already exists.\n" msg += "Please specify different filename or allow file overwrite." logging.warning(msg) @@ -181,7 +181,7 @@ def onNameCheck(self): logging.info("Model function ({}) has been set!\n". format(str(s_title))) self.good_name = True - self.txtName.setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(self.txtName, 'urgent', 'false') self.plugin_filename = os.path.join(self.plugin_dir, filename) # Enable Apply push button only if valid name diff --git a/src/sas/qtgui/Utilities/GuiUtils.py b/src/sas/qtgui/Utilities/GuiUtils.py index ee47683a58..dc551d16c3 100644 --- a/src/sas/qtgui/Utilities/GuiUtils.py +++ b/src/sas/qtgui/Utilities/GuiUtils.py @@ -321,6 +321,17 @@ def updateModelItem(item, update_data, name=""): # Append the new row to the main item item.appendRow(object_item) + +def updateProperty(obj: QtWidgets.QWidget, qt_prop: str, val: str): + """ + Update a Qt property for a given Widget. This requires a series of operations on the widget. + """ + obj.setProperty(qt_prop, val) + obj.style().unpolish(obj) + obj.style().polish(obj) + obj.update() + + def updateModelItemStatus(model_item, filename="", name="", status=2): """ Update status of checkbox related to high- and low-Q extrapolation diff --git a/src/sas/system/sasview.css b/src/sas/system/sasview.css index 1c0386e4ef..4204817c0d 100644 --- a/src/sas/system/sasview.css +++ b/src/sas/system/sasview.css @@ -7,7 +7,10 @@ h1 {font-size: 240%;} /* Qt Elements */ QLineEdit {background-color: white; color: black;} QLineEdit:focus {background-color: #98dbcc; color: #333333} +QLineEdit[urgent=true] {background-color: red;} + +QToolTip {font-size: 80%;} /* Class-specific Properties */ -.warning {background-color: red;} .angstrom {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} +.monospace {font-family: 'monospace, monospace'} \ No newline at end of file From f4f4232d9dd32545a7b6903cd6586bac9c798290 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 14:49:13 -0400 Subject: [PATCH 12/67] Apply GuiUtils property updater to data operations panel --- .../Calculators/DataOperationUtilityPanel.py | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/sas/qtgui/Calculators/DataOperationUtilityPanel.py b/src/sas/qtgui/Calculators/DataOperationUtilityPanel.py index adaaf70eaf..6b9460af2c 100644 --- a/src/sas/qtgui/Calculators/DataOperationUtilityPanel.py +++ b/src/sas/qtgui/Calculators/DataOperationUtilityPanel.py @@ -268,16 +268,16 @@ def onInputCoefficient(self): if input_to_check is None or input_to_check == '': msg = 'DataOperation: Number requires a float number' logging.warning(msg) - self.txtNumber.setProperty('class', 'warning') + GuiUtils.updateProperty(self.txtNumber, 'urgent', 'true') elif float(self.txtNumber.text()) == 0.: # should be check that 0 is not chosen msg = 'DataOperation: Number requires a non zero number' logging.warning(msg) - self.txtNumber.setProperty('class', 'warning') + GuiUtils.updateProperty(self.txtNumber, 'urgent', 'true') else: - self.txtNumber.setProperty('class', None) + GuiUtils.updateProperty(self.txtNumber, 'urgent', 'false') self.data2 = float(self.txtNumber.text()) self.updatePlot(self.graphData2, self.layoutData2, self.data2) @@ -288,13 +288,14 @@ def onCheckChosenData(self): return False else: if self.cbData2.currentText() == 'Number': - self.cbData1.setProperty('class', None) - self.cbData2.setProperty('class', None) + + GuiUtils.updateProperty(self.cbData1, 'urgent', 'false') + GuiUtils.updateProperty(self.cbData2, 'urgent', 'false') return True elif self.data1.__class__.__name__ != self.data2.__class__.__name__: - self.cbData1.setProperty('class', 'warning') - self.cbData2.setProperty('class', 'warning') + GuiUtils.updateProperty(self.cbData1, 'urgent', 'true') + GuiUtils.updateProperty(self.cbData2, 'urgent', 'true') print(self.data1.__class__.__name__ != self.data2.__class__.__name__) logging.error('Cannot compute data of different dimensions') return False @@ -303,8 +304,8 @@ def onCheckChosenData(self): and (len(self.data2.x) != len(self.data1.x) or not all(i == j for i, j in zip(self.data1.x, self.data2.x))): logging.error('Cannot compute 1D data of different lengths') - self.cbData1.setProperty('class', 'warning') - self.cbData2.setProperty('class', 'warning') + GuiUtils.updateProperty(self.cbData1, 'urgent', 'true') + GuiUtils.updateProperty(self.cbData2, 'urgent', 'true') return False elif self.data1.__class__.__name__ == 'Data2D' \ @@ -315,14 +316,14 @@ def onCheckChosenData(self): or not all(i == j for i, j in zip(self.data1.qy_data, self.data2.qy_data)) ): - self.cbData1.setProperty('class', 'warning') - self.cbData2.setProperty('class', 'warning') + GuiUtils.updateProperty(self.cbData1, 'urgent', 'true') + GuiUtils.updateProperty(self.cbData2, 'urgent', 'true') logging.error('Cannot compute 2D data of different lengths') return False else: - self.cbData1.setProperty('class', None) - self.cbData2.setProperty('class', None) + GuiUtils.updateProperty(self.cbData1, 'urgent', 'false') + GuiUtils.updateProperty(self.cbData2, 'urgent', 'false') return True def onCheckOutputName(self): @@ -330,17 +331,17 @@ def onCheckOutputName(self): name_to_check = str(self.txtOutputData.text()) if name_to_check is None or name_to_check == '': - self.txtOutputData.setProperty('class', 'warning') + GuiUtils.updateProperty(self.txtOutputData, 'urgent', 'true') logging.warning('No output name') return False elif name_to_check in self.list_data_items: - self.txtOutputData.setProperty('class', 'warning') + GuiUtils.updateProperty(self.txtOutputData, 'urgent', 'true') logging.warning('The Output data name already exists') return False else: - self.txtOutputData.setProperty('class', None) + GuiUtils.updateProperty(self.txtOutputData, 'urgent', 'false') return True # ######## From 6d2dbad817aaa0cb5fe2bb555bb0034c55a885fc Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 15:01:54 -0400 Subject: [PATCH 13/67] Respond to review concerns --- src/sas/qtgui/MainWindow/MainWindow.py | 2 +- src/sas/system/config/config.py | 2 ++ src/sas/system/style.py | 39 +++++++++++--------------- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/sas/qtgui/MainWindow/MainWindow.py b/src/sas/qtgui/MainWindow/MainWindow.py index eeef74a76c..9e3765df55 100644 --- a/src/sas/qtgui/MainWindow/MainWindow.py +++ b/src/sas/qtgui/MainWindow/MainWindow.py @@ -98,7 +98,7 @@ def run_sasview(): splash.show() app.setAttribute(Qt.AA_EnableHighDpiScaling) # Main application style. - app.setStyleSheet(style.style_sheet()) + app.setStyleSheet(style.style_sheet.read()) # fix for pyinstaller packages app to avoid ReactorAlreadyInstalledError if 'twisted.internet.reactor' in sys.modules: diff --git a/src/sas/system/config/config.py b/src/sas/system/config/config.py index 98cc0ed26f..bb05f43905 100644 --- a/src/sas/system/config/config.py +++ b/src/sas/system/config/config.py @@ -176,6 +176,8 @@ def __init__(self): # Time out for updating sasview self.UPDATE_TIMEOUT = 2 + # Default style sheet name + self.STYLE_SHEET = 'sasview.css' # # Lock the class down, this is necessary both for diff --git a/src/sas/system/style.py b/src/sas/system/style.py index 83d0ef3c92..ddb2fea42a 100644 --- a/src/sas/system/style.py +++ b/src/sas/system/style.py @@ -2,51 +2,46 @@ import pkg_resources import sys -from sas.system import user - -DEFAULT_STYLE_SHEET_NAME = 'sasview.css' +from sas.system import user, config class StyleSheet: """ - The directory where the per-user style sheet is stored. + Class to create and load the per-user style sheet. - Returns ~/.sasview/sasview.css, creating it if it does not already exist. + Stores the file in ~/.sasview/sasview.css, if it does not already exist, otherwise overwrites it """ def __init__(self): self.style_sheet = None - self._find_style_sheet() self.save() - def style_sheet_filename(self): + def _style_sheet_filename(self): """Filename for saving config items""" user_dir = user.get_user_dir() - self.style_sheet = os.path.join(user_dir, DEFAULT_STYLE_SHEET_NAME) + self.style_sheet = os.path.join(user_dir, config.STYLE_SHEET) def save(self): + """ + Save the existing style in the user directory + """ self._find_style_sheet() - sheet = self() - self.style_sheet_filename() + sheet = self.read() + self._style_sheet_filename() with open(self.style_sheet, 'w') as file: file.write(sheet) - def _find_style_sheet(self, filename=DEFAULT_STYLE_SHEET_NAME): - ''' + def _find_style_sheet(self, filename=None): + """ The style sheet is in: User directory ~/.sasview/ Debug . - Packaging: sas/sasview/ - Packaging / production does not work well with absolute paths - thus the multiple paths below - ''' - self.style_sheet_filename() + """ + if filename is None: + filename = config.STYLE_SHEET + self._style_sheet_filename() places_to_look_for_conf_file = [ self.style_sheet, - os.path.join(os.path.abspath(os.path.dirname(__file__)), filename), filename, - os.path.join("sas", "system", filename), - os.path.join(os.getcwd(), "sas", "system", filename), - os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), filename) #For OSX app ] # To avoid the exception in OSx @@ -64,7 +59,7 @@ def _find_style_sheet(self, filename=DEFAULT_STYLE_SHEET_NAME): print(f"'{filename}' not found.", file=sys.stderr) self.style_sheet = None - def __call__(self, *args, **kwargs): + def read(self): with open(self.style_sheet) as f: style = f.read() return style From c7e8435fb391bedfa29914db0ec570c396b20eb3 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 15:11:42 -0400 Subject: [PATCH 14/67] Use guiutils property updater for GSC and resolution calculator --- .../GenericScatteringCalculator.py | 20 +++++++++--------- .../Calculators/ResolutionCalculatorPanel.py | 14 ++++++------- src/sas/system/style.py | 21 ++++++++++++++++++- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/sas/qtgui/Calculators/GenericScatteringCalculator.py b/src/sas/qtgui/Calculators/GenericScatteringCalculator.py index 8f7960ccc0..15f793b259 100644 --- a/src/sas/qtgui/Calculators/GenericScatteringCalculator.py +++ b/src/sas/qtgui/Calculators/GenericScatteringCalculator.py @@ -241,16 +241,16 @@ def __init__(self, parent=None): self.cbShape.currentIndexChanged.connect(self.selectedshapechange) # New font to display angstrom symbol - self.lblUnitSolventSLD.setProperty('class', 'angstrom') - self.lblUnitVolume.setProperty('class', 'angstrom') - self.lbl5.setProperty('class', 'angstrom') - self.lblUnitMx.setProperty('class', 'angstrom') - self.lblUnitMy.setProperty('class', 'angstrom') - self.lblUnitMz.setProperty('class', 'angstrom') - self.lblUnitNucl.setProperty('class', 'angstrom') - self.lblUnitx.setProperty('class', 'angstrom') - self.lblUnity.setProperty('class', 'angstrom') - self.lblUnitz.setProperty('class', 'angstrom') + GuiUtils.updateProperty(self.lblUnitSolventSLD, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblUnitVolume, 'angstrom', 'true') + GuiUtils.updateProperty(self.lbl5, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblUnitMx, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblUnitMy, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblUnitMz, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblUnitNucl, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblUnitx, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblUnity, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblUnitz, 'angstrom', 'true') def setup_display(self): """ diff --git a/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py b/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py index ed961209f9..0e4d45f2f4 100644 --- a/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py +++ b/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py @@ -46,13 +46,13 @@ def __init__(self, parent=None): self.manager = parent # New font to display angstrom symbol - self.lblUnitWavelength.setProperty('class', 'angstrom') - self.lblUnitQx.setProperty('class', 'angstrom') - self.lblUnitQy.setProperty('class', 'angstrom') - self.lblUnitSigmax.setProperty('class', 'angstrom') - self.lblUnitSigmay.setProperty('class', 'angstrom') - self.lblUnitSigmalamd.setProperty('class', 'angstrom') - self.lblUnit1DSigma.setProperty('class', 'angstrom') + GuiUtils.updateProperty(self.lblUnitWavelength, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblUnitQx, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblUnitQy, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblUnitSigmax, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblUnitSigmay, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblUnitSigmalamd, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblUnit1DSigma, 'angstrom', 'true') # by default Spectrum label and cbCustomSpectrum are not visible self.cbCustomSpectrum.setVisible(False) diff --git a/src/sas/system/style.py b/src/sas/system/style.py index ddb2fea42a..32e8c0de1c 100644 --- a/src/sas/system/style.py +++ b/src/sas/system/style.py @@ -41,7 +41,6 @@ def _find_style_sheet(self, filename=None): self._style_sheet_filename() places_to_look_for_conf_file = [ self.style_sheet, - filename, ] # To avoid the exception in OSx @@ -66,3 +65,23 @@ def read(self): style_sheet = StyleSheet() + + +default_sheet = """ +/* Global Properties */ +* {font-size: 9pt; font-family: "Lucinda Grande", "Lucinda Sans Unicode", Helvetica, Arial, Verdana, sans-serif} + +/* HTML Elements */ +h1 {font-size: 240%;} + +/* Qt Elements */ +QLineEdit {background-color: white; color: black;} +QLineEdit:focus {background-color: #98dbcc; color: #333333} +QLineEdit[urgent=true] {background-color: red;} + +QToolTip {font-size: 80%;} + +/* Class-specific Properties */ +.angstrom {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} +.monospace {font-family: 'monospace, monospace'} +""" From 060e6e0cbf8b7d2a1447d649cc2e4c574d5f67e1 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 15:12:40 -0400 Subject: [PATCH 15/67] Commit sasview.css changes for previous commit and roll-back style.py changes --- src/sas/system/sasview.css | 3 ++- src/sas/system/style.py | 22 +--------------------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/src/sas/system/sasview.css b/src/sas/system/sasview.css index 4204817c0d..1d5a023b4d 100644 --- a/src/sas/system/sasview.css +++ b/src/sas/system/sasview.css @@ -9,8 +9,9 @@ QLineEdit {background-color: white; color: black;} QLineEdit:focus {background-color: #98dbcc; color: #333333} QLineEdit[urgent=true] {background-color: red;} +QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} + QToolTip {font-size: 80%;} /* Class-specific Properties */ -.angstrom {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} .monospace {font-family: 'monospace, monospace'} \ No newline at end of file diff --git a/src/sas/system/style.py b/src/sas/system/style.py index 32e8c0de1c..e3cfa5b057 100644 --- a/src/sas/system/style.py +++ b/src/sas/system/style.py @@ -64,24 +64,4 @@ def read(self): return style -style_sheet = StyleSheet() - - -default_sheet = """ -/* Global Properties */ -* {font-size: 9pt; font-family: "Lucinda Grande", "Lucinda Sans Unicode", Helvetica, Arial, Verdana, sans-serif} - -/* HTML Elements */ -h1 {font-size: 240%;} - -/* Qt Elements */ -QLineEdit {background-color: white; color: black;} -QLineEdit:focus {background-color: #98dbcc; color: #333333} -QLineEdit[urgent=true] {background-color: red;} - -QToolTip {font-size: 80%;} - -/* Class-specific Properties */ -.angstrom {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} -.monospace {font-family: 'monospace, monospace'} -""" +style_sheet = StyleSheet() \ No newline at end of file From 00f97d17543242c65c5e4ded2ff862a97d0e48e9 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 15:13:23 -0400 Subject: [PATCH 16/67] Remove unneeded style polish and updates in add multiply editor window --- src/sas/qtgui/Utilities/AddMultEditor.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/sas/qtgui/Utilities/AddMultEditor.py b/src/sas/qtgui/Utilities/AddMultEditor.py index c4fe19ec46..a99900e238 100644 --- a/src/sas/qtgui/Utilities/AddMultEditor.py +++ b/src/sas/qtgui/Utilities/AddMultEditor.py @@ -167,9 +167,6 @@ def onNameCheck(self): if filename in models_list: self.good_name = False GuiUtils.updateProperty(self.txtName, 'urgent', 'true') - self.txtName.style().unpolish(self.txtName) - self.txtName.style().polish(self.txtName) - self.txtName.update() msg = "Plugin with specified name already exists.\n" msg += "Please specify different filename or allow file overwrite." logging.warning(msg) From 55372da21275a5dadf27dc5a9e4d689d758d1c30 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 15:32:18 -0400 Subject: [PATCH 17/67] Add italics option to style sheet and apply to grid panel while generalizing the type hint in gui utils --- src/sas/qtgui/Utilities/GridPanel.py | 4 +--- src/sas/qtgui/Utilities/GuiUtils.py | 2 +- src/sas/system/sasview.css | 3 ++- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/sas/qtgui/Utilities/GridPanel.py b/src/sas/qtgui/Utilities/GridPanel.py index af3efeb606..67a810e9fb 100644 --- a/src/sas/qtgui/Utilities/GridPanel.py +++ b/src/sas/qtgui/Utilities/GridPanel.py @@ -393,9 +393,7 @@ def setupTable(self, widget=None, data=None): for i_row, error in enumerate(error_values): item = QtWidgets.QTableWidgetItem(GuiUtils.formatNumber(error, high=True)) # Fancy, italic font for errors - font = QtGui.QFont() - font.setItalic(True) - item.setFont(font) + GuiUtils.updateProperty(item, 'italic', 'true') widget.setItem(i_row, error_column, item) # resize content diff --git a/src/sas/qtgui/Utilities/GuiUtils.py b/src/sas/qtgui/Utilities/GuiUtils.py index dc551d16c3..2501035be5 100644 --- a/src/sas/qtgui/Utilities/GuiUtils.py +++ b/src/sas/qtgui/Utilities/GuiUtils.py @@ -322,7 +322,7 @@ def updateModelItem(item, update_data, name=""): item.appendRow(object_item) -def updateProperty(obj: QtWidgets.QWidget, qt_prop: str, val: str): +def updateProperty(obj: QtWidgets, qt_prop: str, val: str): """ Update a Qt property for a given Widget. This requires a series of operations on the widget. """ diff --git a/src/sas/system/sasview.css b/src/sas/system/sasview.css index 1d5a023b4d..d011e14513 100644 --- a/src/sas/system/sasview.css +++ b/src/sas/system/sasview.css @@ -1,5 +1,5 @@ /* Global Properties */ -* {font-size: 9pt; font-family: "Lucinda Grande", "Lucinda Sans Unicode", Helvetica, Arial, Verdana, sans-serif} +* {font-size: 9pt; font-family: Helvetica, Arial, Verdana, sans-serif} /* HTML Elements */ h1 {font-size: 240%;} @@ -8,6 +8,7 @@ h1 {font-size: 240%;} QLineEdit {background-color: white; color: black;} QLineEdit:focus {background-color: #98dbcc; color: #333333} QLineEdit[urgent=true] {background-color: red;} +QTableWidgetItem[italic=true] {font-style: italic} QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} From e267beb1d0f6ed93c608dbebbc72a4b32c99aa34 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 25 Oct 2022 15:41:34 -0400 Subject: [PATCH 18/67] Move default styles into python to eliminate file not found errors --- src/sas/system/sasview.css | 18 ------------------ src/sas/system/style.py | 34 +++++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 23 deletions(-) delete mode 100644 src/sas/system/sasview.css diff --git a/src/sas/system/sasview.css b/src/sas/system/sasview.css deleted file mode 100644 index d011e14513..0000000000 --- a/src/sas/system/sasview.css +++ /dev/null @@ -1,18 +0,0 @@ -/* Global Properties */ -* {font-size: 9pt; font-family: Helvetica, Arial, Verdana, sans-serif} - -/* HTML Elements */ -h1 {font-size: 240%;} - -/* Qt Elements */ -QLineEdit {background-color: white; color: black;} -QLineEdit:focus {background-color: #98dbcc; color: #333333} -QLineEdit[urgent=true] {background-color: red;} -QTableWidgetItem[italic=true] {font-style: italic} - -QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} - -QToolTip {font-size: 80%;} - -/* Class-specific Properties */ -.monospace {font-family: 'monospace, monospace'} \ No newline at end of file diff --git a/src/sas/system/style.py b/src/sas/system/style.py index e3cfa5b057..fb38e07428 100644 --- a/src/sas/system/style.py +++ b/src/sas/system/style.py @@ -5,12 +5,34 @@ from sas.system import user, config + class StyleSheet: """ Class to create and load the per-user style sheet. Stores the file in ~/.sasview/sasview.css, if it does not already exist, otherwise overwrites it """ + _default_sheet = """ + /* Global Properties */ + * {font-size: 9pt; font-family: Helvetica, Arial, Verdana, sans-serif} + + /* HTML Elements */ + h1 {font-size: 240%;} + + /* Qt Elements */ + QLineEdit {background-color: white; color: black;} + QLineEdit:focus {background-color: #98dbcc; color: #333333} + QLineEdit[urgent=true] {background-color: red;} + QTableWidgetItem[italic=true] {font-style: italic} + + QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} + + QToolTip {font-size: 80%;} + + /* Class-specific Properties */ + .monospace {font-family: 'monospace, monospace'} + """ + def __init__(self): self.style_sheet = None self.save() @@ -24,7 +46,6 @@ def save(self): """ Save the existing style in the user directory """ - self._find_style_sheet() sheet = self.read() self._style_sheet_filename() with open(self.style_sheet, 'w') as file: @@ -55,13 +76,16 @@ def _find_style_sheet(self, filename=None): if os.path.exists(filepath): self.style_sheet = filepath return - print(f"'{filename}' not found.", file=sys.stderr) self.style_sheet = None def read(self): - with open(self.style_sheet) as f: - style = f.read() + self._find_style_sheet() + if self.style_sheet is not None: + with open(self.style_sheet) as f: + style = f.read() + else: + style = self._default_sheet return style -style_sheet = StyleSheet() \ No newline at end of file +style_sheet = StyleSheet() From 213e4b3b37c3a5be956aeb06cee6326404e48b55 Mon Sep 17 00:00:00 2001 From: krzywon Date: Sat, 16 Sep 2023 16:44:44 +0100 Subject: [PATCH 19/67] Create helper methods and default style sheet in configuration system --- src/sas/system/themes/__init__.py | 48 +++++++++++++++++++++++++++++++ src/sas/system/themes/default.css | 19 ++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/sas/system/themes/__init__.py create mode 100644 src/sas/system/themes/default.css diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py new file mode 100644 index 0000000000..a0660983ea --- /dev/null +++ b/src/sas/system/themes/__init__.py @@ -0,0 +1,48 @@ +"""The base themes shipped with SasView.""" +import os +import logging +from typing import Dict +from pathlib import Path + +from sas.system import user + +logger = logging.getLogger() + + +def load_theme(theme: str = None) -> str: + """Using a theme name, load the associated CSS file. + :param theme: The key value in ALL_THEMES + :return: The loaded CSS + """ + if not theme or theme not in ALL_THEMES: + logger.warning(f"Invalid theme name provided: {theme}") + theme = 'Default' + path = get_user_theme_path(theme) if 'User:' in theme else Path(os.path.join('.', OPTIONS.get(theme))) + with open(path) as fd: + css = fd.read() + return css + + +def get_user_theme_path(theme: str) -> Path: + """Helper method to find the user file in the user directory""" + return Path(os.path.join(user.get_user_dir(), 'themes', theme.replace('User:', ''))) + + +def find_available_themes() -> Dict: + """Find all available themes and return the list of options. + + The default themes should be shipped in the same directory as this file. + User created themes should be kept in ~/.sasview/themes. + """ + themes = OPTIONS.copy() + user_path = os.path.join(user.get_user_dir(), 'themes') + if not os.path.exists(user_path): + os.mkdir(user_path) + for file in os.listdir(user_path): + name = f'User:{file}' + themes[name] = Path(os.path.join(user_path, file)) + return themes + + +OPTIONS = {'Default': Path('default.css')} +ALL_THEMES = find_available_themes() diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css new file mode 100644 index 0000000000..abeef40aa4 --- /dev/null +++ b/src/sas/system/themes/default.css @@ -0,0 +1,19 @@ +/* Global Properties */ +* {font-size: 9pt; font-family: Helvetica, Arial, Verdana, sans-serif} + +/* HTML Elements */ +h1 {font-size: 240%;} + +/* Qt Elements */ +QLineEdit {background-color: white; color: black;} +QLineEdit:focus {background-color: #98dbcc; color: #333333} +QLineEdit[warning=true] {background-color: yellow;} +QLineEdit[urgent=true] {background-color: red;} +QTableWidgetItem[italic=true] {font-style: italic} + +QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} + +QToolTip {font-size: 80%;} + +/* Class-specific Properties */ +.monospace {font-family: 'monospace, monospace'} \ No newline at end of file From 954b05ae6c5124e84c4c521e3c1d541ff57c66b3 Mon Sep 17 00:00:00 2001 From: krzywon Date: Sat, 16 Sep 2023 16:47:32 +0100 Subject: [PATCH 20/67] Rename STYLE_SHEET to THEME and change value --- src/sas/system/config/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sas/system/config/config.py b/src/sas/system/config/config.py index 9d673d13ee..87299afc9f 100644 --- a/src/sas/system/config/config.py +++ b/src/sas/system/config/config.py @@ -209,7 +209,7 @@ def __init__(self): self.FITTING_DEFAULT_OPTIMIZER = 'lm' # Default style sheet name - self.STYLE_SHEET = 'sasview.css' + self.THEME = 'Default' # # Lock the class down, this is necessary both for From 0b212c850812fc1484080f36bc1896d51c397038 Mon Sep 17 00:00:00 2001 From: krzywon Date: Sat, 16 Sep 2023 16:58:42 +0100 Subject: [PATCH 21/67] Remove unneeded value from themes and update style manager to match themes --- src/sas/system/style.py | 91 +++++-------------------------- src/sas/system/themes/__init__.py | 3 +- 2 files changed, 16 insertions(+), 78 deletions(-) diff --git a/src/sas/system/style.py b/src/sas/system/style.py index fb38e07428..3a0eccb065 100644 --- a/src/sas/system/style.py +++ b/src/sas/system/style.py @@ -1,91 +1,30 @@ -import os -import pkg_resources -import sys - -from sas.system import user, config +from typing import List +from sas.system import config +from sas.system.themes import load_theme, find_available_themes class StyleSheet: """ - Class to create and load the per-user style sheet. + Class used to manage all available themes. - Stores the file in ~/.sasview/sasview.css, if it does not already exist, otherwise overwrites it + Built-in themes are available in sas.system.themes. User themes should live in ~/.sasview/themes. """ - _default_sheet = """ - /* Global Properties */ - * {font-size: 9pt; font-family: Helvetica, Arial, Verdana, sans-serif} - - /* HTML Elements */ - h1 {font-size: 240%;} - - /* Qt Elements */ - QLineEdit {background-color: white; color: black;} - QLineEdit:focus {background-color: #98dbcc; color: #333333} - QLineEdit[urgent=true] {background-color: red;} - QTableWidgetItem[italic=true] {font-style: italic} - - QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} - - QToolTip {font-size: 80%;} - - /* Class-specific Properties */ - .monospace {font-family: 'monospace, monospace'} - """ def __init__(self): - self.style_sheet = None - self.save() - - def _style_sheet_filename(self): - """Filename for saving config items""" - user_dir = user.get_user_dir() - self.style_sheet = os.path.join(user_dir, config.STYLE_SHEET) - - def save(self): - """ - Save the existing style in the user directory - """ - sheet = self.read() - self._style_sheet_filename() - with open(self.style_sheet, 'w') as file: - file.write(sheet) - - def _find_style_sheet(self, filename=None): - """ - The style sheet is in: - User directory ~/.sasview/ - Debug . - """ - if filename is None: - filename = config.STYLE_SHEET - self._style_sheet_filename() - places_to_look_for_conf_file = [ - self.style_sheet, - ] + self._available_themes = find_available_themes() + self.theme = config.THEME + self.css = load_theme(self.theme) - # To avoid the exception in OSx - # NotImplementedError: resource_filename() only supported for .egg, not .zip - try: - places_to_look_for_conf_file.append( - pkg_resources.resource_filename(__name__, filename)) - except NotImplementedError: - pass + def update_theme_list(self): + self._available_themes = find_available_themes() - for filepath in places_to_look_for_conf_file: - if os.path.exists(filepath): - self.style_sheet = filepath - return - self.style_sheet = None + def get_theme_names(self) -> List[str]: + return list(self._available_themes.keys()) - def read(self): - self._find_style_sheet() - if self.style_sheet is not None: - with open(self.style_sheet) as f: - style = f.read() - else: - style = self._default_sheet - return style + def change_theme(self, theme: str): + self.theme = theme + self.css = load_theme(self.theme) style_sheet = StyleSheet() diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py index a0660983ea..960f3b20a3 100644 --- a/src/sas/system/themes/__init__.py +++ b/src/sas/system/themes/__init__.py @@ -14,7 +14,7 @@ def load_theme(theme: str = None) -> str: :param theme: The key value in ALL_THEMES :return: The loaded CSS """ - if not theme or theme not in ALL_THEMES: + if not theme or theme not in find_available_themes(): logger.warning(f"Invalid theme name provided: {theme}") theme = 'Default' path = get_user_theme_path(theme) if 'User:' in theme else Path(os.path.join('.', OPTIONS.get(theme))) @@ -45,4 +45,3 @@ def find_available_themes() -> Dict: OPTIONS = {'Default': Path('default.css')} -ALL_THEMES = find_available_themes() From 03cd392ded31112b2929173b6a6f906453097b7e Mon Sep 17 00:00:00 2001 From: krzywon Date: Sat, 16 Sep 2023 17:06:09 +0100 Subject: [PATCH 22/67] Replace theme updator with property --- src/sas/system/style.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/sas/system/style.py b/src/sas/system/style.py index 3a0eccb065..31a3dc1ba5 100644 --- a/src/sas/system/style.py +++ b/src/sas/system/style.py @@ -14,7 +14,17 @@ class StyleSheet: def __init__(self): self._available_themes = find_available_themes() self.theme = config.THEME - self.css = load_theme(self.theme) + self._css = load_theme(self.theme) + + @property + def css(self) -> str: + self._css = load_theme(self.theme) + return self._css + + @css.setter + def css(self, theme: str): + self.theme = theme + self._css = load_theme(theme) def update_theme_list(self): self._available_themes = find_available_themes() @@ -22,9 +32,5 @@ def update_theme_list(self): def get_theme_names(self) -> List[str]: return list(self._available_themes.keys()) - def change_theme(self, theme: str): - self.theme = theme - self.css = load_theme(self.theme) - style_sheet = StyleSheet() From e53bfd51ff3f88b65f26e98cd8be1004c79a5af7 Mon Sep 17 00:00:00 2001 From: krzywon Date: Sat, 16 Sep 2023 17:06:37 +0100 Subject: [PATCH 23/67] Update main window styles --- src/sas/qtgui/MainWindow/MainWindow.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sas/qtgui/MainWindow/MainWindow.py b/src/sas/qtgui/MainWindow/MainWindow.py index fadee90178..5c2342d1b9 100644 --- a/src/sas/qtgui/MainWindow/MainWindow.py +++ b/src/sas/qtgui/MainWindow/MainWindow.py @@ -79,13 +79,12 @@ def run_sasview(): app = QApplication([]) app.setAttribute(Qt.AA_ShareOpenGLContexts) app.setAttribute(Qt.AA_EnableHighDpiScaling) - app.setStyleSheet("* {font-size: 11pt;}") splash = SplashScreen() splash.show() # Main application style. - app.setStyleSheet(style.style_sheet.read()) + app.setStyleSheet(style.css) # fix for pyinstaller packages app to avoid ReactorAlreadyInstalledError if 'twisted.internet.reactor' in sys.modules: From fa014d91a7e81e5eb0f7b2017cba843f49fb906d Mon Sep 17 00:00:00 2001 From: krzywon Date: Sat, 16 Sep 2023 17:21:37 +0100 Subject: [PATCH 24/67] Add theme combobox to display preferences --- .../Preferences/DisplayPreferencesWidget.py | 12 +++++++++--- src/sas/system/__init__.py | 1 + src/sas/system/themes/__init__.py | 2 ++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py b/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py index da535cb4f6..e6bdaed55a 100644 --- a/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py +++ b/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py @@ -1,4 +1,4 @@ -from sas.system import config +from sas.system import config, style from .PreferencesWidget import PreferencesWidget @@ -9,11 +9,16 @@ def __init__(self): self.config_params = ['QT_SCALE_FACTOR', 'QT_AUTO_SCREEN_SCALE_FACTOR', 'DISABLE_RESIDUAL_PLOT', - 'DISABLE_POLYDISPERSITY_PLOT'] + 'DISABLE_POLYDISPERSITY_PLOT', + 'THEME'] self.restart_params = {'QT_SCALE_FACTOR': 'QT Screen Scale Factor', - 'QT_AUTO_SCREEN_SCALE_FACTOR': "Enable Automatic Scaling"} + 'QT_AUTO_SCREEN_SCALE_FACTOR': "Enable Automatic Scaling", + 'THEME': "Display theme"} def _addAllWidgets(self): + self.theme = self.addComboBox(title="Theme", params=style.get_theme_names(), default='Default') + self.theme.currentIndexChanged.connect( + lambda: self._stageChange('THEME', self.theme.currentText())) self.qtScaleFactor = self.addFloatInput( title="QT Screen Scale Factor", default_number=config.QT_SCALE_FACTOR) @@ -42,6 +47,7 @@ def _toggleBlockAllSignaling(self, toggle): self.disablePolydispersityPlot.blockSignals(toggle) def _restoreFromConfig(self): + self.theme.setCurrentText(config.THEME) self.qtScaleFactor.setText(str(config.QT_SCALE_FACTOR)) self.qtScaleFactor.setStyleSheet("background-color: white") self.autoScaling.setChecked(bool(config.QT_AUTO_SCREEN_SCALE_FACTOR)) diff --git a/src/sas/system/__init__.py b/src/sas/system/__init__.py index 2a9126fd61..ef1bfef6ab 100644 --- a/src/sas/system/__init__.py +++ b/src/sas/system/__init__.py @@ -1,5 +1,6 @@ from .web import web from .legal import legal from .config.config import config +from .style import style_sheet as style __all__ = ["web", "legal", "config", "style"] diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py index 960f3b20a3..90ef08a03e 100644 --- a/src/sas/system/themes/__init__.py +++ b/src/sas/system/themes/__init__.py @@ -44,4 +44,6 @@ def find_available_themes() -> Dict: return themes + + OPTIONS = {'Default': Path('default.css')} From 869d9aa2fa32ddca1d5048fec90d4abab71c9dc3 Mon Sep 17 00:00:00 2001 From: krzywon Date: Sat, 16 Sep 2023 17:37:37 +0100 Subject: [PATCH 25/67] Fix pathing issue when loading files --- src/sas/system/themes/__init__.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py index 90ef08a03e..0f405b90b0 100644 --- a/src/sas/system/themes/__init__.py +++ b/src/sas/system/themes/__init__.py @@ -8,6 +8,8 @@ logger = logging.getLogger() +OPTIONS = {'Default': Path(os.path.join(os.path.dirname(__file__), 'default.css'))} + def load_theme(theme: str = None) -> str: """Using a theme name, load the associated CSS file. @@ -17,17 +19,12 @@ def load_theme(theme: str = None) -> str: if not theme or theme not in find_available_themes(): logger.warning(f"Invalid theme name provided: {theme}") theme = 'Default' - path = get_user_theme_path(theme) if 'User:' in theme else Path(os.path.join('.', OPTIONS.get(theme))) - with open(path) as fd: + path = OPTIONS.get(theme) + with open(path.absolute()) as fd: css = fd.read() return css -def get_user_theme_path(theme: str) -> Path: - """Helper method to find the user file in the user directory""" - return Path(os.path.join(user.get_user_dir(), 'themes', theme.replace('User:', ''))) - - def find_available_themes() -> Dict: """Find all available themes and return the list of options. @@ -42,8 +39,3 @@ def find_available_themes() -> Dict: name = f'User:{file}' themes[name] = Path(os.path.join(user_path, file)) return themes - - - - -OPTIONS = {'Default': Path('default.css')} From 558fc0f74562c63e71178157ac47f21f9ea47315 Mon Sep 17 00:00:00 2001 From: krzywon Date: Sat, 16 Sep 2023 17:47:41 +0100 Subject: [PATCH 26/67] Tweak default styles and remove html-specific styles --- src/sas/system/themes/default.css | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index abeef40aa4..0fae673fce 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -1,8 +1,5 @@ /* Global Properties */ -* {font-size: 9pt; font-family: Helvetica, Arial, Verdana, sans-serif} - -/* HTML Elements */ -h1 {font-size: 240%;} +* {font-size: 10pt; font-family: Helvetica, Arial, Verdana, sans-serif} /* Qt Elements */ QLineEdit {background-color: white; color: black;} From 8a242073cf1863280571cabbee5e75af040c3fb4 Mon Sep 17 00:00:00 2001 From: krzywon Date: Sun, 17 Sep 2023 10:33:13 +0100 Subject: [PATCH 27/67] Update generic scattering calculator to to use common styles --- .../GenericScatteringCalculator.py | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/sas/qtgui/Calculators/GenericScatteringCalculator.py b/src/sas/qtgui/Calculators/GenericScatteringCalculator.py index e9bb8fe63c..c9e748ba26 100644 --- a/src/sas/qtgui/Calculators/GenericScatteringCalculator.py +++ b/src/sas/qtgui/Calculators/GenericScatteringCalculator.py @@ -44,11 +44,6 @@ class GenericScatteringCalculator(QtWidgets.QDialog, Ui_GenericScatteringCalcula calculationFinishedSignal = QtCore.Signal() loadingFinishedSignal = QtCore.Signal(list, bool) - # class constants for textbox background colours - TEXTBOX_DEFAULT_STYLESTRING = 'background-color: rgb(255, 255, 255);' - TEXTBOX_WARNING_STYLESTRING = 'background-color: rgb(255, 226, 110);' - TEXTBOX_ERROR_STYLESTRING = 'background-color: rgb(255, 182, 193);' - def __init__(self, parent=None): super(GenericScatteringCalculator, self).__init__() self.setupUi(self) @@ -417,17 +412,17 @@ def gui_text_changed(self, sender): if senderInvalid: self.invalidLineEdits.remove(sender) self.toggle_error_functionality() - sender.setStyleSheet("") # If the LineEdit has been corrected from an invalid value restore functionality elif sender.hasAcceptableInput() and senderInvalid: self.invalidLineEdits.remove(sender) self.toggle_error_functionality() - sender.setStyleSheet(self.TEXTBOX_DEFAULT_STYLESTRING) + GuiUtils.updateProperty(sender, 'warning', 'false') + GuiUtils.updateProperty(sender, 'urgent', 'false') # If the LineEdit has had an invalid value stored then remove functionality elif (not sender.hasAcceptableInput()) and (not senderInvalid): self.invalidLineEdits.append(sender) self.toggle_error_functionality() - sender.setStyleSheet(self.TEXTBOX_ERROR_STYLESTRING) + GuiUtils.updateProperty(sender, 'urgent', 'true') # If the LineEdit is an acceptable value according to the regex apply warnings # This functionality was previously found in check_value() if not(sender in self.invalidLineEdits): @@ -439,9 +434,10 @@ def gui_text_changed(self, sender): max_step = 3*max(xnodes, ynodes, znodes) # limits qmin > maxq / nodes if value < 2 or value > max_step: - self.txtNoQBins.setStyleSheet(self.TEXTBOX_WARNING_STYLESTRING) + GuiUtils.updateProperty(self.txtNoQBins, 'warning', 'true') else: - self.txtNoQBins.setStyleSheet(self.TEXTBOX_DEFAULT_STYLESTRING) + GuiUtils.updateProperty(self.txtNoQBins, 'warning', 'false') + GuiUtils.updateProperty(self.txtNoQBins, 'urgent', 'false') elif sender == self.txtQxMax: xstepsize = float(self.txtXstepsize.text()) ystepsize = float(self.txtYstepsize.text()) @@ -449,9 +445,10 @@ def gui_text_changed(self, sender): value = float(str(self.txtQxMax.text())) max_q = numpy.pi / (max(xstepsize, ystepsize, zstepsize)) if value <= 0 or value > max_q: - self.txtQxMax.setStyleSheet(self.TEXTBOX_WARNING_STYLESTRING) + GuiUtils.updateProperty(self.txtQxMax, 'warning', 'true') else: - self.txtQxMax.setStyleSheet(self.TEXTBOX_DEFAULT_STYLESTRING) + GuiUtils.updateProperty(self.txtQxMax, 'warning', 'false') + GuiUtils.updateProperty(self.txtQxMax, 'urgent', 'false') From 834636800294389ed34c0b32db458cf9cc4be115 Mon Sep 17 00:00:00 2001 From: krzywon Date: Sun, 17 Sep 2023 10:38:43 +0100 Subject: [PATCH 28/67] Update resolution calculator to to use common styles --- .../Calculators/ResolutionCalculatorPanel.py | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py b/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py index 8de1f8be36..d84e25b1af 100644 --- a/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py +++ b/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py @@ -126,23 +126,23 @@ def checkWavelength(self): if TOF, wavelength = min - max else only one number """ text_edit = self.txtWavelength # self.sender() if text_edit.isModified(): - text_edit.setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(text_edit, 'urgent', 'false') input_string = str(text_edit.text()) if self.cbWaveColor.currentText() != 'TOF': input_wavelength = re.match('\d+\.?\d*', input_string) if input_wavelength is None: - text_edit.setStyleSheet(BG_RED) + GuiUtils.updateProperty(text_edit, 'urgent', 'true') self.cmdCompute.setEnabled(False) logging.info('Wavelength has to be a number.') else: - text_edit.setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(text_edit, 'urgent', 'false') self.cmdCompute.setEnabled(True) else: interval_wavelength = re.match('^\d+\.?\d*\s*-\s*\d+\.?\d*$', input_string) if interval_wavelength is None: - text_edit.setStyleSheet(BG_RED) + GuiUtils.updateProperty(text_edit, 'urgent', 'true') self.cmdCompute.setEnabled(False) logging.info("Wavelength's input has to be an interval: " "min - max.") @@ -152,12 +152,12 @@ def checkWavelength(self): re.findall('\d+\.?\d*', interval_wavelength.group()) if float(wavelength_min) >= float(wavelength_max): - text_edit.setStyleSheet(BG_RED) + GuiUtils.updateProperty(text_edit, 'urgent', 'true') self.cmdCompute.setEnabled(False) logging.info("Wavelength: min must be smaller than max.") else: - text_edit.setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(text_edit, 'urgent', 'false') self.cmdCompute.setEnabled(True) def checkWavelengthSpread(self): @@ -166,14 +166,14 @@ def checkWavelengthSpread(self): text_edit = self.sender() if text_edit.isModified(): - text_edit.setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(text_edit, 'urgent', 'false') if self.cbWaveColor.currentText() != 'TOF': pattern = '^\d+\.?\d*(|;\s*\d+)$' input_string = str(text_edit.text()) wavelength_spread_input = re.match(pattern, input_string) if wavelength_spread_input is None: - text_edit.setStyleSheet(BG_RED) + GuiUtils.updateProperty(text_edit, 'urgent', 'true') self.cmdCompute.setEnabled(False) logging.info('Wavelength spread has to be specified: ' 'single value or value; integer number of bins.') @@ -181,7 +181,7 @@ def checkWavelengthSpread(self): else: split_input = wavelength_spread_input.group().split(';') self.num_wave = split_input[1] if len(split_input) > 1 else 10 - text_edit.setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(text_edit, 'urgent', 'false') self.cmdCompute.setEnabled(True) else: pattern = '^\d+\.?\d*\s*-\s*\d+\.?\d*(|;\s*\d+)$' @@ -189,7 +189,7 @@ def checkWavelengthSpread(self): wavelength_spread_input = re.match(pattern, input_string) if wavelength_spread_input is None: - text_edit.setStyleSheet(BG_RED) + GuiUtils.updateProperty(text_edit, 'urgent', 'true') self.cmdCompute.setEnabled(False) logging.info("Wavelength spread has to be specified: " "doublet separated by '-' with optional " @@ -200,7 +200,7 @@ def checkWavelengthSpread(self): split_input = wavelength_spread_input.group().split(';') self.num_wave = split_input[1] if len( split_input) > 1 else 10 - text_edit.setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(text_edit, 'urgent', 'false') self.cmdCompute.setEnabled(True) def checkPixels(self): @@ -208,19 +208,19 @@ def checkPixels(self): text_edit = self.sender() if text_edit.isModified(): - text_edit.setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(text_edit, 'urgent', 'false') pattern = '^\d+\.?\d*,\s*\d+\.?\d*$' input_string = str(text_edit.text()) pixels_input = re.match(pattern, input_string) if pixels_input is None: - text_edit.setStyleSheet(BG_RED) + GuiUtils.updateProperty(text_edit, 'urgent', 'true') self.cmdCompute.setEnabled(False) logging.info('The input for the detector should contain 2 ' 'values separated by a comma.') else: - text_edit.setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(text_edit, 'urgent', 'false') self.cmdCompute.setEnabled(True) def checkQx_y(self): @@ -232,11 +232,11 @@ def checkQx_y(self): input_string = str(text_edit.text()) q_input = re.match(pattern, input_string) if q_input is None: - text_edit.setStyleSheet(BG_RED) + GuiUtils.updateProperty(text_edit, 'urgent', 'true') self.cmdCompute.setEnabled(False) logging.info('Qx and Qy should contain one or more comma-separated numbers.') else: - text_edit.setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(text_edit, 'urgent', 'false') self.cmdCompute.setEnabled(True) qx = str(self.txtQx.text()).split(',') qy = str(self.txtQy.text()).split(',') @@ -250,13 +250,13 @@ def checkQx_y(self): self.txtQy.setText(fill_qy) elif len(qx) != len(qy): - text_edit.setStyleSheet(BG_RED) + GuiUtils.updateProperty(text_edit, 'urgent', 'true') self.cmdCompute.setEnabled(False) logging.info( 'Qx and Qy should have the same number of elements.') else: - text_edit.setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(text_edit, 'urgent', 'false') self.cmdCompute.setEnabled(True) def checkAperture(self): @@ -264,20 +264,20 @@ def checkAperture(self): text_edit = self.sender() if text_edit.isModified(): - text_edit.setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(text_edit, 'urgent', 'false') input_string = str(text_edit.text()) pattern = '^\d+\.?\d*(|,\s*\d+)$' aperture_input = re.match(pattern, input_string) if aperture_input is None: - text_edit.setStyleSheet(BG_RED) + GuiUtils.updateProperty(text_edit, 'urgent', 'true') self.cmdCompute.setEnabled(False) logging.info('A circular aperture is defined by a single ' 'value (diameter). A rectangular aperture is ' 'defined by 2 values separated by a comma.') else: - text_edit.setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(text_edit, 'urgent', 'false') self.cmdCompute.setEnabled(True) # ################################# From 9800ca00135ec414bf2c72295d0442895ae56784 Mon Sep 17 00:00:00 2001 From: krzywon Date: Sun, 17 Sep 2023 10:45:49 +0100 Subject: [PATCH 29/67] Update preferences panel to use style sheets --- .../qtgui/Utilities/Preferences/DisplayPreferencesWidget.py | 4 +++- .../qtgui/Utilities/Preferences/PlottingPreferencesWidget.py | 4 +++- src/sas/qtgui/Utilities/Preferences/PreferencesWidget.py | 5 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py b/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py index e6bdaed55a..6220c9eee9 100644 --- a/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py +++ b/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py @@ -1,5 +1,7 @@ from sas.system import config, style +from sas.qtgui.Utilities import GuiUtils + from .PreferencesWidget import PreferencesWidget @@ -49,7 +51,7 @@ def _toggleBlockAllSignaling(self, toggle): def _restoreFromConfig(self): self.theme.setCurrentText(config.THEME) self.qtScaleFactor.setText(str(config.QT_SCALE_FACTOR)) - self.qtScaleFactor.setStyleSheet("background-color: white") + GuiUtils.updateProperty(self.qtScaleFactor, 'warning', 'false') self.autoScaling.setChecked(bool(config.QT_AUTO_SCREEN_SCALE_FACTOR)) self.disableResidualPlot.setChecked(config.DISABLE_RESIDUAL_PLOT) self.disablePolydispersityPlot.setChecked(config.DISABLE_POLYDISPERSITY_PLOT) diff --git a/src/sas/qtgui/Utilities/Preferences/PlottingPreferencesWidget.py b/src/sas/qtgui/Utilities/Preferences/PlottingPreferencesWidget.py index 2f9f8dea07..13eea0b86a 100644 --- a/src/sas/qtgui/Utilities/Preferences/PlottingPreferencesWidget.py +++ b/src/sas/qtgui/Utilities/Preferences/PlottingPreferencesWidget.py @@ -1,5 +1,7 @@ from sas.system import config +from sas.qtgui.Utilities import GuiUtils + from .PreferencesWidget import PreferencesWidget @@ -36,4 +38,4 @@ def _restoreFromConfig(self): self.legendFullWidth.setChecked(bool(config.FITTING_PLOT_FULL_WIDTH_LEGENDS)) self.legendTruncate.setChecked(bool(config.FITTING_PLOT_LEGEND_TRUNCATE)) self.legendLineLength.setText(str(config.FITTING_PLOT_LEGEND_MAX_LINE_LENGTH)) - self.legendLineLength.setStyleSheet("background-color: white") + GuiUtils.updateProperty(self.legendLineLength, 'warning', 'false') diff --git a/src/sas/qtgui/Utilities/Preferences/PreferencesWidget.py b/src/sas/qtgui/Utilities/Preferences/PreferencesWidget.py index b493f05ff2..95cab3d8cc 100644 --- a/src/sas/qtgui/Utilities/Preferences/PreferencesWidget.py +++ b/src/sas/qtgui/Utilities/Preferences/PreferencesWidget.py @@ -5,6 +5,7 @@ from typing import Optional, List, Union, Dict from sas.system import config +from sas.qtgui.Utilities import GuiUtils ConfigType = Union[str, bool, float, int, List[Union[str, float, int]]] logger = logging.getLogger(__name__) @@ -165,14 +166,14 @@ def _validate_input_and_stage(self, edit: QLineEdit, key: str): :param key: The string representation of the key the QLineEdit value is stored as in the configuration system. :return: None """ - edit.setStyleSheet("background-color: white") + GuiUtils.updateProperty(edit, 'warning', 'false') validator = edit.validator() text = edit.text() (state, val, pos) = validator.validate(text, 0) if validator else (0, 0, 0) if state == QValidator.Acceptable or not validator: self._stageChange(key, text) else: - edit.setStyleSheet("background-color: yellow") + GuiUtils.updateProperty(edit, 'warning', 'true') self._unStageChange(key) self._setInvalid(key) From b8af23c7297f5208b5a97844f5aa5e675fd6bf1b Mon Sep 17 00:00:00 2001 From: krzywon Date: Sun, 17 Sep 2023 11:01:50 +0100 Subject: [PATCH 30/67] Update model editor to use style sheets --- src/sas/qtgui/Utilities/ModelEditor.py | 2 -- src/sas/qtgui/Utilities/TabbedModelEditor.py | 10 +++++----- src/sas/system/themes/default.css | 4 +++- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/sas/qtgui/Utilities/ModelEditor.py b/src/sas/qtgui/Utilities/ModelEditor.py index 9fa8cba822..19224eaae1 100644 --- a/src/sas/qtgui/Utilities/ModelEditor.py +++ b/src/sas/qtgui/Utilities/ModelEditor.py @@ -34,8 +34,6 @@ def setupWidgets(self): from sas.qtgui.Utilities.PythonSyntax import PythonHighlighter self.highlight = PythonHighlighter(self.txtEditor.document(), is_python=self.is_python) - self.txtEditor.setFont(GuiUtils.getMonospaceFont()) - def addSignals(self): """ Respond to signals in the widget diff --git a/src/sas/qtgui/Utilities/TabbedModelEditor.py b/src/sas/qtgui/Utilities/TabbedModelEditor.py index c7d22b461e..a28300597e 100644 --- a/src/sas/qtgui/Utilities/TabbedModelEditor.py +++ b/src/sas/qtgui/Utilities/TabbedModelEditor.py @@ -168,7 +168,7 @@ def loadFile(self, filename): return # In case previous model was incorrect, change the frame colours back - self.editor_widget.txtEditor.setStyleSheet("") + GuiUtils.updateProperty(self.editor_widget.txtEditor, 'warning', 'false') self.editor_widget.txtEditor.setToolTip("") # See if there is filename.c present @@ -219,7 +219,7 @@ def editorModelModified(self): Disable the plugin editor and show that the model is changed. """ self.setTabEdited(True) - self.plugin_widget.txtFunction.setStyleSheet("") + GuiUtils.updateProperty(self.plugin_widget.txtFunction, 'warning', 'false') self.buttonBox.button(QtWidgets.QDialogButtonBox.Apply).setEnabled(True) self.is_modified = True @@ -338,7 +338,7 @@ def checkModel(self, model_str): self.parent.communicate.statusBarUpdateSignal.emit("Model check failed") # Put a thick, red border around the mini-editor - self.tabWidget.currentWidget().txtEditor.setStyleSheet("border: 5px solid red") + GuiUtils.updateProperty(self.tabWidget.currentWidget().txtEditor, 'warning', 'true') # last_lines = traceback.format_exc().split('\n')[-4:] traceback_to_show = '\n'.join(last_lines) self.tabWidget.currentWidget().txtEditor.setToolTip(traceback_to_show) @@ -381,7 +381,7 @@ def isModelCorrect(self, full_path): # Remove the file so it is not being loaded on refresh os.remove(full_path) # Put a thick, red border around the mini-editor - self.plugin_widget.txtFunction.setStyleSheet("border: 5px solid red") + GuiUtils.updateProperty(self.plugin_widget.txtFunction, 'warning', 'true') # Use the last line of the traceback for the tooltip last_lines = traceback.format_exc().split('\n')[-2:] traceback_to_show = '\n'.join(last_lines) @@ -412,7 +412,7 @@ def updateFromEditor(self): return # change the frame colours back - w.txtEditor.setStyleSheet("") + GuiUtils.updateProperty(w.txtEditor, 'warning', 'false') w.txtEditor.setToolTip("") # Save the file self.writeFile(filename, model_str) diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index 0fae673fce..ea48ad40eb 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -13,4 +13,6 @@ QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} QToolTip {font-size: 80%;} /* Class-specific Properties */ -.monospace {font-family: 'monospace, monospace'} \ No newline at end of file +QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow} +QCodeEditor {font-family: 'monospace, monospace'} +QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} \ No newline at end of file From e41b65291d7f29d187fd0f5c0f1608ca1fb0756c Mon Sep 17 00:00:00 2001 From: krzywon Date: Sun, 17 Sep 2023 11:14:51 +0100 Subject: [PATCH 31/67] Update invariant perspective to use style sheets --- .../Invariant/InvariantDetails.py | 30 ++++--------------- .../Invariant/InvariantPerspective.py | 29 +++++++++--------- src/sas/system/themes/default.css | 3 ++ 3 files changed, 23 insertions(+), 39 deletions(-) diff --git a/src/sas/qtgui/Perspectives/Invariant/InvariantDetails.py b/src/sas/qtgui/Perspectives/Invariant/InvariantDetails.py index 167d7c8f1e..7aff01e18d 100755 --- a/src/sas/qtgui/Perspectives/Invariant/InvariantDetails.py +++ b/src/sas/qtgui/Perspectives/Invariant/InvariantDetails.py @@ -7,9 +7,8 @@ from .UI.InvariantDetailsUI import Ui_Dialog from .InvariantUtils import WIDGETS -# ERROR_COLOR = wx.Colour(255, 0, 0, 128) -# EXTRAPOLATION_COLOR = wx.Colour(169, 169, 168, 128) -# INVARIANT_COLOR = wx.Colour(67, 208, 128, 128) +from sas.qtgui.Utilities import GuiUtils + class DetailsDialog(QtWidgets.QDialog, Ui_Dialog): """ @@ -21,24 +20,6 @@ def __init__(self, parent): super(DetailsDialog, self).__init__(parent) self.setupUi(self) - - DEFAULT_STYLE = """ - QProgressBar{ - border: 2px solid grey; - border-radius: 5px; - text-align: center - } - - QProgressBar::chunk { - background-color: #b1daf9; - width: 10px; - margin: 1px; - } - """ - self.progressBarLowQ.setStyleSheet(DEFAULT_STYLE) - self.progressBarData.setStyleSheet(DEFAULT_STYLE) - self.progressBarHighQ.setStyleSheet(DEFAULT_STYLE) - self.progressBarLowQ.setMinimum(0) self.progressBarLowQ.setMaximum(100) @@ -49,10 +30,9 @@ def __init__(self, parent): self.progressBarHighQ.setMaximum(100) # Modify font in order to display Angstrom symbol correctly - new_font = 'font-family: -apple-system, "Helvetica Neue", "Ubuntu";' - self.lblQLowQUnits.setStyleSheet(new_font) - self.lblQDataUnits.setStyleSheet(new_font) - self.lblQHighQUnits.setStyleSheet(new_font) + GuiUtils.updateProperty(self.lblQLowQUnits, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblQDataUnits, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblQHighQUnits, 'angstrom', 'true') self.cmdOK.clicked.connect(self.accept) diff --git a/src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py b/src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py index b1d587c26b..459c9a3dfd 100644 --- a/src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py +++ b/src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py @@ -97,13 +97,12 @@ def __init__(self, parent=None): self._allow_close = False # Modify font in order to display Angstrom symbol correctly - new_font = 'font-family: -apple-system, "Helvetica Neue", "Ubuntu";' - self.lblTotalQUnits.setStyleSheet(new_font) - self.lblSpecificSurfaceUnits.setStyleSheet(new_font) - self.lblInvariantTotalQUnits.setStyleSheet(new_font) - self.lblContrastUnits.setStyleSheet(new_font) - self.lblPorodCstUnits.setStyleSheet(new_font) - self.lblExtrapolQUnits.setStyleSheet(new_font) + GuiUtils.updateProperty(self.lblTotalQUnits, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblSpecificSurfaceUnits, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblInvariantTotalQUnits, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblContrastUnits, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblPorodCstUnits, 'angstrom', 'true') + GuiUtils.updateProperty(self.lblExtrapolQUnits, 'angstrom', 'true') # To remove blue square around line edits self.txtBackgd.setAttribute(QtCore.Qt.WA_MacShowFocusRect, False) @@ -609,15 +608,15 @@ def checkLength(self): try: int_value = int(self.sender().text()) except ValueError: - self.sender().setStyleSheet(BG_RED) + GuiUtils.updateProperty(self.sender(), 'urgent', 'true') return if self._data: if len(self._data.x) < int_value: - self.sender().setStyleSheet(BG_RED) + GuiUtils.updateProperty(self.sender(), 'urgent', 'true') logging.warning('The number of points must be smaller than {}'.format(len(self._data.x))) else: - self.sender().setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(self.sender(), 'urgent', 'false') self.allow_calculation() def modelChanged(self, item): @@ -711,8 +710,10 @@ def checkQRange(self): calculate = ((q_low_min < q_low_max) and (q_high_min < q_high_max) and (q_high_min > q_low_max) and self.txtExtrapolQMax.text() and self.txtExtrapolQMin.text() and self.txtNptsLowQ.text() and self.txtNptsHighQ.text()) - self.txtExtrapolQMin.setStyleSheet(BG_RED if q_low_min >= q_low_max and q_low_max < q_high_min else BG_WHITE) - self.txtExtrapolQMax.setStyleSheet(BG_RED if q_high_min >= q_high_max and q_low_max < q_high_min else BG_WHITE) + GuiUtils.updateProperty(self.txtExtrapolQMin, 'urgent', + 'true'if q_low_min >= q_low_max and q_low_max < q_high_min else 'false') + GuiUtils.updateProperty(self.txtExtrapolQMax, 'urgent', + 'true' if q_high_min >= q_high_max and q_low_max < q_high_min else 'false') if calculate: self.allow_calculation() else: @@ -742,11 +743,11 @@ def updateFromGui(self): self.model.setItem(related_widgets[index_elt], item) try: related_internal_values[index_elt] = float(self.sender().text()) - self.sender().setStyleSheet(BG_WHITE) + GuiUtils.updateProperty(self.sender(), 'urgent', 'false') self.allow_calculation() except ValueError: # empty field, just skip - self.sender().setStyleSheet(BG_RED) + GuiUtils.updateProperty(self.sender(), 'urgent', 'true') self.cmdCalculate.setEnabled(False) def lowGuinierAndPowerToggle(self, toggle): diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index ea48ad40eb..9a764e0d04 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -12,6 +12,9 @@ QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} QToolTip {font-size: 80%;} +QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} +QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} + /* Class-specific Properties */ QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow} QCodeEditor {font-family: 'monospace, monospace'} From 444017eafb43adfd9d9c2f093ecb6aa56789d02b Mon Sep 17 00:00:00 2001 From: krzywon Date: Sun, 17 Sep 2023 11:49:11 +0100 Subject: [PATCH 32/67] Update corfunc perspective to use style sheets --- .../Perspectives/Corfunc/CorfuncPerspective.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sas/qtgui/Perspectives/Corfunc/CorfuncPerspective.py b/src/sas/qtgui/Perspectives/Corfunc/CorfuncPerspective.py index 7f25ca4797..5ffd4b8208 100644 --- a/src/sas/qtgui/Perspectives/Corfunc/CorfuncPerspective.py +++ b/src/sas/qtgui/Perspectives/Corfunc/CorfuncPerspective.py @@ -134,9 +134,9 @@ def set_background_warning(self): show_warning = False if show_warning: - self.txtBackground.setStyleSheet("QLineEdit { background-color: rgb(255,255,0) }") + GuiUtils.updateProperty(self.txtBackground, 'urgent', 'true') else: - self.txtBackground.setStyleSheet("") + GuiUtils.updateProperty(self.txtBackground, 'urgent', 'false') def isSerializable(self): """ @@ -593,10 +593,10 @@ def on_extrapolation_text_changed_3(self, text): def notify_extrapolation_text_box_validity(self, params): """ Set the colour of the text boxes to red if they have bad parameter definitions""" - box_1_style = "" - box_2_style = "" - box_3_style = "" - red = "QLineEdit { background-color: rgb(255,0,0); color: rgb(255,255,255) }" + box_1_style = "false" + box_2_style = "false" + box_3_style = "false" + red = "true" if params.point_1 <= params.data_q_min: box_1_style = red @@ -617,9 +617,9 @@ def notify_extrapolation_text_box_validity(self, params): box_1_style = red box_3_style = red - self.txtLowerQMax.setStyleSheet(box_1_style) - self.txtUpperQMin.setStyleSheet(box_2_style) - self.txtUpperQMax.setStyleSheet(box_3_style) + GuiUtils.updateProperty(self.txtLowerQMax, 'urgent', box_1_style) + GuiUtils.updateProperty(self.txtUpperQMin, 'urgent', box_2_style) + GuiUtils.updateProperty(self.txtUpperQMax, 'urgent', box_3_style) def on_extrapolation_slider_changed(self, state: ExtrapolationParameters): """ Slider state changed""" From 110d6325b6e6b34a20794bc97b75ba6f662d954f Mon Sep 17 00:00:00 2001 From: krzywon Date: Sun, 17 Sep 2023 12:01:57 +0100 Subject: [PATCH 33/67] Update fitting widget to use style sheets --- .../Perspectives/Fitting/FittingWidget.py | 40 +++---------------- src/sas/system/themes/default.css | 13 +++++- 2 files changed, 16 insertions(+), 37 deletions(-) diff --git a/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py b/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py index fc89951667..1a432b772a 100644 --- a/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py +++ b/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py @@ -165,9 +165,8 @@ def __init__(self, parent=None, data=None, tab_id=1): self.data = data # New font to display angstrom symbol - new_font = 'font-family: -apple-system, "Helvetica Neue", "Ubuntu";' - self.label_17.setStyleSheet(new_font) - self.label_19.setStyleSheet(new_font) + GuiUtils.updateProperty(self.label_17, 'angstrom', 'true') + GuiUtils.updateProperty(self.label_19, 'angstrom', 'true') def info(self, type, value, tb): logger.error("".join(traceback.format_exception(type, value, tb))) @@ -404,35 +403,6 @@ def initializeModels(self): self.lstParams.setItemDelegate(ModelViewDelegate(self)) self.lstParams.setAlternatingRowColors(True) - stylesheet = """ - - QTreeView { - paint-alternating-row-colors-for-empty-area:0; - } - - QTreeView::item { - border: 1px; - padding: 2px 1px; - } - - QTreeView::item:hover { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1); - border: 1px solid #bfcde4; - } - - QTreeView::item:selected { - border: 1px solid #567dbc; - } - - QTreeView::item:selected:active{ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc); - } - - QTreeView::item:selected:!active { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf); - } - """ - self.lstParams.setStyleSheet(stylesheet) self.lstParams.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.lstParams.customContextMenuRequested.connect(self.showModelContextMenu) self.lstParams.setAttribute(QtCore.Qt.WA_MacShowFocusRect, False) @@ -3887,7 +3857,7 @@ def enableInteractiveElements(self): Enable the param table(s) """ # Notify the user that fitting is available - self.cmdFit.setStyleSheet('QPushButton {color: black;}') + GuiUtils.updateProperty(self.cmdFit, 'urgent', 'false') self.cmdFit.setText("Fit") self.fit_started = False self.setInteractiveElements(True) @@ -3899,7 +3869,7 @@ def disableInteractiveElements(self): """ # Notify the user that fitting is being run # Allow for stopping the job - self.cmdFit.setStyleSheet('QPushButton {color: red;}') + GuiUtils.updateProperty(self.cmdFit, 'urgent', 'true') self.cmdFit.setText('Stop fit') self.setInteractiveElements(False) @@ -3910,7 +3880,7 @@ def disableInteractiveElementsOnCalculate(self): """ # Notify the user that fitting is being run # Allow for stopping the job - self.cmdFit.setStyleSheet('QPushButton {color: red;}') + GuiUtils.updateProperty(self.cmdFit, 'urgent', 'false') self.cmdFit.setText('Running...') self.setInteractiveElements(False) diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index 9a764e0d04..725a80a5eb 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -10,12 +10,21 @@ QTableWidgetItem[italic=true] {font-style: italic} QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} +QPushButton {color: black;} +QPushButton[urgent=true] {color: red;} + QToolTip {font-size: 80%;} QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} -/* Class-specific Properties */ QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow} QCodeEditor {font-family: 'monospace, monospace'} -QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} \ No newline at end of file +QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} + +QTreeView {paint-alternating-row-colors-for-empty-area:0;} +QTreeView::item {border: 1px; padding: 2px 1px;} +QTreeView::item:hover {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1); border: 1px solid #bfcde4;} +QTreeView::item:selected {border: 1px solid #567dbc;} +QTreeView::item:selected:active{background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);} +QTreeView::item:selected:!active {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);} \ No newline at end of file From 585622d3115e1474ac2134c8633a5792db10011e Mon Sep 17 00:00:00 2001 From: krzywon Date: Sun, 17 Sep 2023 12:16:02 +0100 Subject: [PATCH 34/67] Update remaining fitting pieces to use style sheets --- src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py | 9 ++++----- src/sas/qtgui/Perspectives/Fitting/FittingOptions.py | 4 ++-- src/sas/qtgui/Perspectives/Fitting/MultiConstraint.py | 4 ++-- src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py | 5 ++--- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py b/src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py index 0e8343c25c..474cfee6ae 100644 --- a/src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py +++ b/src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py @@ -309,7 +309,6 @@ def onFit(self): if self.is_running: self.is_running = False #re-enable the Fit button - self.cmdFit.setStyleSheet('QPushButton {color: black;}') self.cmdFit.setText("Fit") # stop the fitpages self.calc_fit.stop() @@ -402,7 +401,7 @@ def onFit(self): self.calc_fit.ready(2.5) # modify the Fit button - self.cmdFit.setStyleSheet('QPushButton {color: red;}') + GuiUtils.updateProperty(self.cmdFit, 'urgent', 'true') self.cmdFit.setText('Stop fit') self.parent.communicate.statusBarUpdateSignal.emit('Fitting started...') self.is_running = True @@ -650,7 +649,7 @@ def fitComplete(self, result): Respond to the successful fit complete signal """ #re-enable the Fit button - self.cmdFit.setStyleSheet('QPushButton {color: black;}') + GuiUtils.updateProperty(self.cmdFit, 'urgent', 'false') self.cmdFit.setText("Fit") self.is_running = False @@ -710,7 +709,7 @@ def batchComplete(self, result): Respond to the successful batch fit complete signal """ #re-enable the Fit button - self.cmdFit.setStyleSheet('QPushButton {color: black;}') + GuiUtils.updateProperty(self.cmdFit, 'urgent', 'false') self.cmdFit.setText("Fit") self.is_running = False @@ -757,7 +756,7 @@ def fitFailed(self, reason): Respond to fitting failure. """ #re-enable the Fit button - self.cmdFit.setStyleSheet('QPushButton {color: black;}') + GuiUtils.updateProperty(self.cmdFit, 'urgent', 'false') self.cmdFit.setText("Fit") self.is_running = False diff --git a/src/sas/qtgui/Perspectives/Fitting/FittingOptions.py b/src/sas/qtgui/Perspectives/Fitting/FittingOptions.py index 4194f1567c..b4aa335291 100644 --- a/src/sas/qtgui/Perspectives/Fitting/FittingOptions.py +++ b/src/sas/qtgui/Perspectives/Fitting/FittingOptions.py @@ -112,8 +112,8 @@ def check_state(self, *args, **kwargs): sender = self.sender() validator = sender.validator() state = validator.validate(sender.text(), 0)[0] - color = '' if state == QtGui.QValidator.Acceptable else '#fff79a' - sender.setStyleSheet('QLineEdit { background-color: %s }' % color) + warning = 'false' if state == QtGui.QValidator.Acceptable else 'true' + GuiUtils.updateProperty(sender, 'warning', warning) def onDefaultAlgorithmChange(self): text = self.cbAlgorithmDefault.currentText() diff --git a/src/sas/qtgui/Perspectives/Fitting/MultiConstraint.py b/src/sas/qtgui/Perspectives/Fitting/MultiConstraint.py index fe0eb54ddd..16dcdb325a 100644 --- a/src/sas/qtgui/Perspectives/Fitting/MultiConstraint.py +++ b/src/sas/qtgui/Perspectives/Fitting/MultiConstraint.py @@ -113,10 +113,10 @@ def validateFormula(self): formula_is_valid = self.validateConstraint(self.txtConstraint.text()) if not formula_is_valid: self.cmdOK.setEnabled(False) - self.txtConstraint.setStyleSheet("QLineEdit {background-color: red;}") + GuiUtils.updateProperty(self.txtConstraint, 'urgent', 'true') else: self.cmdOK.setEnabled(True) - self.txtConstraint.setStyleSheet("QLineEdit {background-color: white;}") + GuiUtils.updateProperty(self.txtConstraint, 'urgent', 'false') def validateConstraint(self, constraint_text): """ diff --git a/src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py b/src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py index 57807235bb..b217580cf7 100644 --- a/src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py +++ b/src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py @@ -97,9 +97,8 @@ def __init__(self, parent=None, logic=None): self.txtNptsFit.setText(str(self.npts_fit)) self.model.blockSignals(False) - new_font = 'font-family: -apple-system, "Helvetica Neue", "Ubuntu";' - self.label_13.setStyleSheet(new_font) - self.label_15.setStyleSheet(new_font) + GuiUtils.updateProperty(self.label_13, 'angstrom', 'true') + GuiUtils.updateProperty(self.label_15, 'angstrom', 'true') def initModel(self): """ From 5cabf679f19c7ff21f597f26661a80465a446bc9 Mon Sep 17 00:00:00 2001 From: krzywon Date: Sun, 17 Sep 2023 13:34:59 +0100 Subject: [PATCH 35/67] Add start of dark theme --- src/sas/system/themes/__init__.py | 5 ++++- src/sas/system/themes/dark.css | 32 +++++++++++++++++++++++++++++++ src/sas/system/themes/default.css | 2 +- 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/sas/system/themes/dark.css diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py index 0f405b90b0..df6fe1fbc6 100644 --- a/src/sas/system/themes/__init__.py +++ b/src/sas/system/themes/__init__.py @@ -8,7 +8,10 @@ logger = logging.getLogger() -OPTIONS = {'Default': Path(os.path.join(os.path.dirname(__file__), 'default.css'))} +OPTIONS = { + 'Default': Path(os.path.join(os.path.dirname(__file__), 'default.css')), + 'Dark': Path(os.path.join(os.path.dirname(__file__), 'dark.css')) +} def load_theme(theme: str = None) -> str: diff --git a/src/sas/system/themes/dark.css b/src/sas/system/themes/dark.css new file mode 100644 index 0000000000..31f9b02781 --- /dev/null +++ b/src/sas/system/themes/dark.css @@ -0,0 +1,32 @@ +/* Global Properties */ +* {font-size: 10pt; font-family: Helvetica, Arial, Verdana, sans-serif; color: grey; background-color: black;} + +/* Qt Elements */ +QLineEdit {background-color: white; color: black;} +QLineEdit:focus {background-color: #98dbcc; color: #333333} +QLineEdit[warning=true] {background-color: yellow;} +QLineEdit[urgent=true] {background-color: red;} +QTableWidgetItem[italic=true] {font-style: italic} + +QLabel {background-color: lightgrey} +QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} + +QPushButtun {background-color: lightgrey} +QPushButton:hover {background-color: darkgrey} +QPushButton[urgent=true] {color: red;} + +QToolTip {font-size: 80%; background-color: lightgrey} + +QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} +QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} + +QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow} +QCodeEditor {font-family: 'monospace, monospace'} +QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} + +QTreeView {paint-alternating-row-colors-for-empty-area:0; background-color: lightgrey} +QTreeView::item {border: 1px; padding: 2px 1px;} +QTreeView::item:hover {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1); border: 1px solid #bfcde4;} +QTreeView::item:selected {border: 1px solid #567dbc;} +QTreeView::item:selected:active{background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);} +QTreeView::item:selected:!active {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);} diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index 725a80a5eb..9ba9ee3355 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -27,4 +27,4 @@ QTreeView::item {border: 1px; padding: 2px 1px;} QTreeView::item:hover {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1); border: 1px solid #bfcde4;} QTreeView::item:selected {border: 1px solid #567dbc;} QTreeView::item:selected:active{background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);} -QTreeView::item:selected:!active {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);} \ No newline at end of file +QTreeView::item:selected:!active {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);} From c8d22b540dc68ca3379b842443c470acaa7f7085 Mon Sep 17 00:00:00 2001 From: krzywon Date: Sun, 17 Sep 2023 14:39:37 +0100 Subject: [PATCH 36/67] Add start of large font theme --- src/sas/system/themes/__init__.py | 3 ++- src/sas/system/themes/largefont.css | 33 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/sas/system/themes/largefont.css diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py index df6fe1fbc6..f9d216d612 100644 --- a/src/sas/system/themes/__init__.py +++ b/src/sas/system/themes/__init__.py @@ -10,7 +10,8 @@ OPTIONS = { 'Default': Path(os.path.join(os.path.dirname(__file__), 'default.css')), - 'Dark': Path(os.path.join(os.path.dirname(__file__), 'dark.css')) + 'Dark': Path(os.path.join(os.path.dirname(__file__), 'dark.css')), + 'Large Font': Path(os.path.join(os.path.dirname(__file__), 'largefont.css')), } diff --git a/src/sas/system/themes/largefont.css b/src/sas/system/themes/largefont.css new file mode 100644 index 0000000000..77c34e2846 --- /dev/null +++ b/src/sas/system/themes/largefont.css @@ -0,0 +1,33 @@ +/* Global Properties */ +* {font-size: 11pt; font-family: Helvetica, Arial, Verdana, sans-serif} + +/* Deviations from default theme */ +QTabBar::tab, QLineEdit, QTableWidgetItem, QLabel, QPushButton, QComboBox {font-size: 12pt;} + +/* Qt Elements */ +QLineEdit {background-color: white; color: black} +QLineEdit:focus {background-color: #98dbcc; color: #333333} +QLineEdit[warning=true] {background-color: yellow;} +QLineEdit[urgent=true] {background-color: red;} +QTableWidgetItem[italic=true] {font-style: italic} + +QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} + +QPushButton {color: black} +QPushButton[urgent=true] {color: red;} + +QToolTip {font-size: 80%;} + +QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} +QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} + +QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow; font-size: 12pt;} +QCodeEditor {font-family: 'monospace, monospace'; font-size: 12pt;} +QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} + +QTreeView {paint-alternating-row-colors-for-empty-area:0;} +QTreeView::item {border: 1px; padding: 2px 1px;} +QTreeView::item:hover {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1); border: 1px solid #bfcde4;} +QTreeView::item:selected {border: 1px solid #567dbc;} +QTreeView::item:selected:active{background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);} +QTreeView::item:selected:!active {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);} From 9bedc88b112a7b93bccc886d39db4fd0951838f4 Mon Sep 17 00:00:00 2001 From: krzywon Date: Sun, 17 Sep 2023 14:39:57 +0100 Subject: [PATCH 37/67] Tweaks to dark font theme --- src/sas/system/themes/dark.css | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sas/system/themes/dark.css b/src/sas/system/themes/dark.css index 31f9b02781..9c888a2690 100644 --- a/src/sas/system/themes/dark.css +++ b/src/sas/system/themes/dark.css @@ -1,5 +1,5 @@ /* Global Properties */ -* {font-size: 10pt; font-family: Helvetica, Arial, Verdana, sans-serif; color: grey; background-color: black;} +* {font-size: 10pt; font-family: Helvetica, Arial, Verdana, sans-serif; color: grey; background-color: black; border-color: lightgrey;} /* Qt Elements */ QLineEdit {background-color: white; color: black;} @@ -8,11 +8,12 @@ QLineEdit[warning=true] {background-color: yellow;} QLineEdit[urgent=true] {background-color: red;} QTableWidgetItem[italic=true] {font-style: italic} -QLabel {background-color: lightgrey} +QTabBar::tab {background-color: black; color: lightgrey;} +QTabBar::tab:hover, QComboBox:hover, QPushButton:hover {background-color: lightgrey} + QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} -QPushButtun {background-color: lightgrey} -QPushButton:hover {background-color: darkgrey} +QPushButton {background-color: lightgrey} QPushButton[urgent=true] {color: red;} QToolTip {font-size: 80%; background-color: lightgrey} From 03f857f507c27eb44eb8f98abc264e91706a12ab Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 18 Sep 2023 11:33:47 +0100 Subject: [PATCH 38/67] Fix issue where config file was secondary to config defaults --- src/sas/qtgui/MainWindow/GuiManager.py | 5 ++++- src/sas/qtgui/MainWindow/MainWindow.py | 4 ---- src/sas/system/style.py | 1 + 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sas/qtgui/MainWindow/GuiManager.py b/src/sas/qtgui/MainWindow/GuiManager.py index 2ebc711792..7eaa52b51b 100644 --- a/src/sas/qtgui/MainWindow/GuiManager.py +++ b/src/sas/qtgui/MainWindow/GuiManager.py @@ -72,7 +72,7 @@ import sas from sas import config -from sas.system import web +from sas.system import web, style logger = logging.getLogger(__name__) @@ -91,6 +91,9 @@ def __init__(self, parent=None): # Decide on a locale QLocale.setDefault(QLocale('en_US')) + # Main application style. + self._parent.setStyleSheet(style.css) + # Redefine exception hook to not explicitly crash the app. sys.excepthook = self.info diff --git a/src/sas/qtgui/MainWindow/MainWindow.py b/src/sas/qtgui/MainWindow/MainWindow.py index 5c2342d1b9..5c5c1d3598 100644 --- a/src/sas/qtgui/MainWindow/MainWindow.py +++ b/src/sas/qtgui/MainWindow/MainWindow.py @@ -2,7 +2,6 @@ import os import sys -from sas.system import style from sas.system.version import __version__ from PySide6.QtWidgets import QMainWindow @@ -83,9 +82,6 @@ def run_sasview(): splash = SplashScreen() splash.show() - # Main application style. - app.setStyleSheet(style.css) - # fix for pyinstaller packages app to avoid ReactorAlreadyInstalledError if 'twisted.internet.reactor' in sys.modules: del sys.modules['twisted.internet.reactor'] diff --git a/src/sas/system/style.py b/src/sas/system/style.py index 31a3dc1ba5..e79c0c21ec 100644 --- a/src/sas/system/style.py +++ b/src/sas/system/style.py @@ -18,6 +18,7 @@ def __init__(self): @property def css(self) -> str: + self.theme = config.THEME self._css = load_theme(self.theme) return self._css From d8701f4dfd3421646c1cc8160f1c649e684989eb Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 18 Sep 2023 12:44:44 +0100 Subject: [PATCH 39/67] Remove reject from fitting options and return instead --- src/sas/qtgui/Perspectives/Fitting/FittingOptions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sas/qtgui/Perspectives/Fitting/FittingOptions.py b/src/sas/qtgui/Perspectives/Fitting/FittingOptions.py index b4aa335291..fe2e593b45 100644 --- a/src/sas/qtgui/Perspectives/Fitting/FittingOptions.py +++ b/src/sas/qtgui/Perspectives/Fitting/FittingOptions.py @@ -210,7 +210,7 @@ def bumpsUpdate(option): self.config.values[self.current_fitter_id][option] = new_value except ValueError: # Don't update bumps if widget has bad data - self.reject + return # Update the BUMPS singleton [bumpsUpdate(o) for o in self.config.values[self.current_fitter_id].keys()] From 10bc32b9e5159841fbf4d9a4cdbae3b8486d5d17 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 18 Sep 2023 12:47:38 +0100 Subject: [PATCH 40/67] Set proper default value for style preference --- src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py b/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py index 6220c9eee9..159129a56c 100644 --- a/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py +++ b/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py @@ -18,7 +18,7 @@ def __init__(self): 'THEME': "Display theme"} def _addAllWidgets(self): - self.theme = self.addComboBox(title="Theme", params=style.get_theme_names(), default='Default') + self.theme = self.addComboBox(title="Theme", params=style.get_theme_names(), default=style.theme) self.theme.currentIndexChanged.connect( lambda: self._stageChange('THEME', self.theme.currentText())) self.qtScaleFactor = self.addFloatInput( From f160d917096931e1b265261611565318150de175 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 18 Sep 2023 12:50:16 +0100 Subject: [PATCH 41/67] Disable alternate themes to be finalized later --- src/sas/system/themes/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py index f9d216d612..ee9d718c43 100644 --- a/src/sas/system/themes/__init__.py +++ b/src/sas/system/themes/__init__.py @@ -10,8 +10,8 @@ OPTIONS = { 'Default': Path(os.path.join(os.path.dirname(__file__), 'default.css')), - 'Dark': Path(os.path.join(os.path.dirname(__file__), 'dark.css')), - 'Large Font': Path(os.path.join(os.path.dirname(__file__), 'largefont.css')), + #'Dark': Path(os.path.join(os.path.dirname(__file__), 'dark.css')), + #'Large Font': Path(os.path.join(os.path.dirname(__file__), 'largefont.css')), } From 3f81896a4181146e7365db0de26e188bc3534c29 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 18 Sep 2023 14:36:41 +0100 Subject: [PATCH 42/67] Include css files in the build spec --- installers/sasview.spec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/installers/sasview.spec b/installers/sasview.spec index fca9705b5f..2ab993a19c 100644 --- a/installers/sasview.spec +++ b/installers/sasview.spec @@ -17,7 +17,8 @@ datas = [ ('../src/sas/qtgui/Perspectives/Fitting/plugin_models', 'plugin_models'), ('../src/sas/system/log.ini', 'sas/system/'), ('../../sasmodels/sasmodels','sasmodels'), - ('../docs/sphinx-docs/build/html','doc') + ('../docs/sphinx-docs/build/html','doc'), + ('../src/sas/system/themes/', 'sas/system/themes/') ] #TODO: Hopefully we can get away from version specific packages datas.append((os.path.join(PYTHON_PACKAGES, 'debugpy'), 'debugpy')) From 1d0e07529f425e2f6a83a720362372a083d6ee58 Mon Sep 17 00:00:00 2001 From: lucas-wilkins Date: Fri, 22 Sep 2023 15:30:14 +0100 Subject: [PATCH 43/67] Dark theme improved a bit --- src/sas/system/themes/__init__.py | 4 ++-- src/sas/system/themes/dark.css | 25 ++++++++++++++++--------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py index ee9d718c43..f9d216d612 100644 --- a/src/sas/system/themes/__init__.py +++ b/src/sas/system/themes/__init__.py @@ -10,8 +10,8 @@ OPTIONS = { 'Default': Path(os.path.join(os.path.dirname(__file__), 'default.css')), - #'Dark': Path(os.path.join(os.path.dirname(__file__), 'dark.css')), - #'Large Font': Path(os.path.join(os.path.dirname(__file__), 'largefont.css')), + 'Dark': Path(os.path.join(os.path.dirname(__file__), 'dark.css')), + 'Large Font': Path(os.path.join(os.path.dirname(__file__), 'largefont.css')), } diff --git a/src/sas/system/themes/dark.css b/src/sas/system/themes/dark.css index 9c888a2690..c3ca5d343b 100644 --- a/src/sas/system/themes/dark.css +++ b/src/sas/system/themes/dark.css @@ -1,20 +1,26 @@ /* Global Properties */ -* {font-size: 10pt; font-family: Helvetica, Arial, Verdana, sans-serif; color: grey; background-color: black; border-color: lightgrey;} +* {font-size: 10pt; font-family: Helvetica, Arial, Verdana, sans-serif; color: whitesmoke; background-color: #333337; border-color: lightgrey;} /* Qt Elements */ QLineEdit {background-color: white; color: black;} -QLineEdit:focus {background-color: #98dbcc; color: #333333} -QLineEdit[warning=true] {background-color: yellow;} -QLineEdit[urgent=true] {background-color: red;} +QLineEdit:focus {background-color: #98dbcc; color: #555555} +QLineEdit[warning=true] {background-color: goldenrod;} +QLineEdit[urgent=true] {background-color: darksalmon;} + +QCheckBox::indicator:checked {background-color: whitesmoke; color: red} +QCheckBox::indicator:unchecked {background-color: blue; color: green} + QTableWidgetItem[italic=true] {font-style: italic} -QTabBar::tab {background-color: black; color: lightgrey;} -QTabBar::tab:hover, QComboBox:hover, QPushButton:hover {background-color: lightgrey} +QTabBar::tab {background-color: #444448; color: lightgrey;} +QTabBar::tab:hover, QComboBox:hover, QPushButton:hover {background-color: #272728} +QTabBar::tab:disabled {color: #272728} QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} -QPushButton {background-color: lightgrey} -QPushButton[urgent=true] {color: red;} +QPushButton {background-color: #333337; border-color: #555555; border-style: dashed; color: whitesmoke} +QPushButton[urgent=true] {color: darksalmon;} + QToolTip {font-size: 80%; background-color: lightgrey} @@ -25,9 +31,10 @@ QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow QCodeEditor {font-family: 'monospace, monospace'} QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} -QTreeView {paint-alternating-row-colors-for-empty-area:0; background-color: lightgrey} +QTreeView {paint-alternating-row-colors-for-empty-area:0; background-color: #333337} QTreeView::item {border: 1px; padding: 2px 1px;} QTreeView::item:hover {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1); border: 1px solid #bfcde4;} QTreeView::item:selected {border: 1px solid #567dbc;} QTreeView::item:selected:active{background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);} QTreeView::item:selected:!active {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);} + From 483057aa173d06142252d85d27e61288ad620cd1 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 10:24:38 -0400 Subject: [PATCH 44/67] Rename default to classic --- src/sas/system/themes/classic.css | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/sas/system/themes/classic.css diff --git a/src/sas/system/themes/classic.css b/src/sas/system/themes/classic.css new file mode 100644 index 0000000000..725a80a5eb --- /dev/null +++ b/src/sas/system/themes/classic.css @@ -0,0 +1,30 @@ +/* Global Properties */ +* {font-size: 10pt; font-family: Helvetica, Arial, Verdana, sans-serif} + +/* Qt Elements */ +QLineEdit {background-color: white; color: black;} +QLineEdit:focus {background-color: #98dbcc; color: #333333} +QLineEdit[warning=true] {background-color: yellow;} +QLineEdit[urgent=true] {background-color: red;} +QTableWidgetItem[italic=true] {font-style: italic} + +QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} + +QPushButton {color: black;} +QPushButton[urgent=true] {color: red;} + +QToolTip {font-size: 80%;} + +QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} +QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} + +QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow} +QCodeEditor {font-family: 'monospace, monospace'} +QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} + +QTreeView {paint-alternating-row-colors-for-empty-area:0;} +QTreeView::item {border: 1px; padding: 2px 1px;} +QTreeView::item:hover {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1); border: 1px solid #bfcde4;} +QTreeView::item:selected {border: 1px solid #567dbc;} +QTreeView::item:selected:active{background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);} +QTreeView::item:selected:!active {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);} \ No newline at end of file From 0649dbe775e372d9acb81e6f7394eda1799a6fa6 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 10:27:14 -0400 Subject: [PATCH 45/67] Include classic theme as an option --- src/sas/system/themes/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py index f9d216d612..532f84125c 100644 --- a/src/sas/system/themes/__init__.py +++ b/src/sas/system/themes/__init__.py @@ -11,6 +11,7 @@ OPTIONS = { 'Default': Path(os.path.join(os.path.dirname(__file__), 'default.css')), 'Dark': Path(os.path.join(os.path.dirname(__file__), 'dark.css')), + 'Classic': Path(os.path.join(os.path.dirname(__file__), 'classic.css')), 'Large Font': Path(os.path.join(os.path.dirname(__file__), 'largefont.css')), } From e0ad23230c15c1beeafd9d6d85d5749d13264009 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 10:27:31 -0400 Subject: [PATCH 46/67] Update default theme to be more modern looking --- src/sas/system/themes/default.css | 421 ++++++++++++++++++++++++++++-- 1 file changed, 404 insertions(+), 17 deletions(-) diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index 9ba9ee3355..c48da71d60 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -1,30 +1,417 @@ /* Global Properties */ * {font-size: 10pt; font-family: Helvetica, Arial, Verdana, sans-serif} -/* Qt Elements */ -QLineEdit {background-color: white; color: black;} -QLineEdit:focus {background-color: #98dbcc; color: #333333} -QLineEdit[warning=true] {background-color: yellow;} -QLineEdit[urgent=true] {background-color: red;} -QTableWidgetItem[italic=true] {font-style: italic} +/* QWidget Properties */ -QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} +QWidget { + background: rgb(248,249,250); + color: rgb(77,81,87); + selection-color: rgb(77,81,87); + selection-background-color: rgba(26,115,232,0.5); +} +QWidget:disabled { + color: rgb(248,51,57); + selection-background-color: rgba(77,81,87,0.25); + selection-color: rgba(77,81,87,0.4); +} +QWidget:focus { + outline: none; +} -QPushButton {color: black;} -QPushButton[urgent=true] {color: red;} +/* QMainWindow Properties */ +QMainWindow::separator { + width: 4px; + height: 4px; + background: rgb(218,220,224); +} +QMainWindow::separator:hover, +QMainWindow::separator:pressed { + background: rgb(26,115,232); +} -QToolTip {font-size: 80%;} +/* QCheckBox and QRadioButton Properties */ +QCheckBox, +QRadioButton { + border-top: 2px solid transparent; + border-bottom: 2px solid transparent; +} +QCheckBox:hover, +QRadioButton:hover { + border-bottom: 2px solid rgb(26,115,232); +} +/* QGroupBox Properties */ +QGroupBox { + font-weight: bold; + margin-top: 8px; + padding: 2px 1px 1px 1px; + border-radius: 4px; + border: 1px solid rgb(218,220,224); +} +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + left: 7px; + margin: 0 2px 0 3px; +} +QGroupBox:flat { + border-color: transparent; +} + +/* QToolTip Properties */ +QToolTip { + font-size: 80%; + background: rgba(248,249,250,0.2); + color: rgb(77,81,87); +} + +/* QMenuBar Properties */ +QMenuBar { + padding: 2px; + border-bottom: 1px solid rgb(218,220,224); + background: rgb(248,249,250); +} +QMenuBar::item { + background: transparent; + padding: 4px; +} +QMenuBar::item:selected { + padding: 4px; + border-radius: 4px; + background: rgba(0,0,0,0.20); +} +QMenuBar::item:pressed { + padding: 4px; + margin-bottom: 0; + padding-bottom: 0; +} + +/* QToolBar */ +QToolBar { + padding: 1px; + font-weight: bold; + spacing: 2px; + margin: 1px; + background: rgb(235,235,235); + /* QToolBar must override `border-style` to set the style. */ + border-style: none; +} +QToolBar::separator { + background: rgb(218,220,224); +} +QToolBar::separator:horizontal { + width: 2px; + margin: 0 6px; +} +QToolBar::separator:vertical { + height: 2px; + margin: 6px 0; +} +QToolBar > QToolButton { + background: transparent; + padding: 3px; + border-radius: 4px; +} +QToolBar > QToolButton:hover, +QToolBar > QToolButton::menu-button:hover { + background: rgba(0,0,0,0.15); +} +QToolBar > QToolButton::menu-button { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +QToolBar > QToolButton:pressed, +QToolBar > QToolButton::menu-button:pressed:enabled, +QToolBar > QToolButton:checked:enabled { + background: rgba(0,0,0,0.24); +} +QToolBar > QWidget { + background: transparent; +} + +/* QmenU Preperties */ +QMenu { + background: rgb1(248,249,250,0.20); + padding: 8px 0; + border-radius: 4px; +} +QMenu::separator { + margin: 4px 0; + height: 1px; + background: rgb(218,220,224); +} +QMenu::item { + padding: 4px 19px; +} +QMenu::item:selected { + background: rgba(0,0,0,0.12); +} +QMenu::icon { + padding-left: 10px; + width: 14px; + height: 14px; +} + +/* QScrollBar */ +QScrollBar { + background: rgba(0,0,0,0.40); + border-radius: 4px; +} +QScrollBar:horizontal { + height: 14px; +} +QScrollBar:vertical { +} +QScrollBar::handle { + background: rgba(0,0,0,0.40); + border-radius: 3px; +} +QScrollBar::handle:hover { + background: rgba(0,0,0,0.50); +} +QScrollBar::handle:pressed { + background: rgba(0,0,0,0.24); +} +QScrollBar::handle:disabled { + background: rgba(0,0,0,0.15); +} +QScrollBar::handle:horizontal { + min-width: 8px; + margin: 4px 14px; +} +QScrollBar::handle:horizontal:hover { + margin: 2px 14px; +} +QScrollBar::handle:vertical { + min-height: 8px; + margin: 14px 4px; +} +QScrollBar::handle:vertical:hover { + margin: 14px 2px; +} +/* +Hide QScrollBar background. +The `sub-page` and `add-page` are not colored by default on most OS, but are colored on Windows. +*/ +QScrollBar::sub-page, +QScrollBar::add-page { + background: transparent; +} +QScrollBar::sub-line, +QScrollBar::add-line { + background: transparent; +} + +QPushButton { + color: rgb(26,115,232); + border: 1px solid rgb(218,220,224); + padding: 4px 8px; + border-radius: 4px; +} +QPushButton:flat, +QPushButton:default { + border: none; + padding: 5px 9px; +} +QPushButton:default { + color: rgb(248,249,250); + background: rgb(26,115,232); +} +QPushButton:hover { + background: rgba(26,115,232,0.3); +} +QPushButton:pressed { + background: rgba(26,115,232,0.3); +} +QPushButton:checked:enabled { + background: rgba(26,115,232,0.3); +} +QPushButton:default:hover { + background: rgba(26,115,232,0.1); +} +QPushButton:default:pressed, +QPushButton:default:checked { + background: rgba(26,115,232,0.3); +} +QPushButton:default:disabled, +QPushButton:default:checked:disabled { + background: rgba(77,81,87,0.25); +} + +/* QDialogButtonBox */ +QDialogButtonBox { + dialogbuttonbox-buttons-have-icons: 0; +} +QDialogButtonBox QPushButton { + min-width: 65px; +} + +/* QComboBox */ +QComboBox { + min-height: 1.5em; + padding: 0 8px 0 4px; + background: rgb(248,249,250); + border: 1px solid rgb(218,220,224); + border-radius: 4px; +} +QComboBox:hover, QComboBox::item:hover, QComboBox:focus, QComboBox:open { + border-color: rgb(26,115,232); +} +QComboBox::drop-down { + margin: 2px 2px 2px -6px; + border-radius: 4px; /* This remove default style. */ +} +QComboBox::drop-down:editable:hover { + background: rgba(0,0,0,0.13); +} +/* Setting background color of selected item when editable is false. */ +QComboBox::item:selected { + border: none; /* This remove the border of indicator. */ + background: rgba(26,115,278,0.35); + border-radius: 4px; +} + +/* QAbstractItemView in QComboBox is NoFrame. Override default settings and show border. */ +QComboBox QListView { + margin: 0; + padding: 4px; + background: rgba(248,249,250,0.25); + border-radius: 4px; +} +QComboBox QListView::item { + border-radius: 4px; +} + +/* QListView QTreeView */ +QListView { + padding: 1px +} +QListView, +QTreeView { + background: rgb(248,249,250); +} +QListView::item:hover, +QTreeView::item:hover, +QTreeView::branch:hover { + background: rgb(218,220,224); +} +QTreeView::branch:open:has-children:!has-siblings, +QTreeView::branch:open:has-children:has-siblings { + border-image: unset; + background: rgba(77,81,87,0.05); +} +QTreeView::branch:open:has-children:!has-siblings:disabled, +QTreeView::branch:open:has-children:has-siblings:disabled { + background: rgba(77,81,87,0.05); +} +QTreeView > QHeaderView { + background: rgb(248,249,250); +} +QTreeView > QHeaderView::section { + background: rgb(218,220,224); +} + +/* +Following arrow settings are for QColumnView. +QColumnView::left-arrow and QColumnView::right-arrow are not working. +*/ +QListView::left-arrow { + margin: -2px; +} +QListView::right-arrow { + margin: -2px; +} + +/* QColumnView */ +QColumnView { + background: rgb(248,249,250); +} +QColumnViewGrip { + margin: -4px; + background: rgb(248,249,250); +} + +/* QTableView */ +QTableView { + gridline-color: rgb(218,220,224); + background: rgba(248,249,250,0.5); +} +QTableView:!active { + background: rgba(0,0,0,0.12); +} +QTableView::item:alternate { + background: rgba(0,0,0,0.12); +} +QTableView::item:selected { + background: rgba(248,249,250,0.5); +} +QTableView QTableCornerButton::section { + margin: 0 1px 1px 0; + background: rgb(218,220,224); + border-top-left-radius: 2px; +} +QTableView QTableCornerButton::section:pressed { + background: rgba(26,115,232,0.35); +} +QTableView > QHeaderView { + background: rgba(248,249,250,0.50); + border-radius: 3px; +} +QTableView > QHeaderView::section { + background: rgb(218,220,224); +} + +/* QLineEdit */ +QLineEdit { + padding: 3px 4px; + /* Adjust the min-height of QLineEdit to the height of the characters. */ + min-height: 1em; + border: 1px solid rgb(218,220,224); + background: rgb(248,249,250); + border-radius: 4px; +} +QLineEdit:focus { + border-color: rgb(26,115,232); +} + +/* QFileDialog */ +QFileDialog QFrame { + border: none; +} + +/* Check */ +QComboBox::indicator, +QMenu::indicator { + width: 18px; + height: 18px; +} +QMenu::indicator { + background: rgba(0,0,0,0.19); + margin-left: 3px; + border-radius: 4px; +} + +/* Check indicator */ +QCheckBox, +QRadioButton { + spacing: 8px; +} +QGroupBox::title, +QAbstractItemView::item { + spacing: 6px; +} +QCheckBox::indicator, +QGroupBox::indicator, +QAbstractItemView::indicator, +QRadioButton::indicator { + height: 18px; + width: 18px; +} + +/* Styles that are not from taken PyQtDarkTheme */ QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow} QCodeEditor {font-family: 'monospace, monospace'} QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} - -QTreeView {paint-alternating-row-colors-for-empty-area:0;} -QTreeView::item {border: 1px; padding: 2px 1px;} -QTreeView::item:hover {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1); border: 1px solid #bfcde4;} -QTreeView::item:selected {border: 1px solid #567dbc;} -QTreeView::item:selected:active{background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);} -QTreeView::item:selected:!active {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);} From 9439855964ba9b1920a49d58c9dac06055467769 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 11:20:17 -0400 Subject: [PATCH 47/67] Add QTabWidget styles in default theme --- src/sas/system/themes/default.css | 82 +++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index c48da71d60..814eade22c 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -322,6 +322,88 @@ QListView::right-arrow { margin: -2px; } +/* QTabWidget QTabBar */ +QTabWidget::pane { + border: 1px solid rgb(218,220,224); + border-radius: 4px; +} +QTabBar { + /* + Not filling background color when drawBase property is true. So need to set drawBase to false. + Default QTabBar is no need following declaration, but QMdiArea is need. + */ + qproperty-drawBase: 0; +} +QTabBar::close-button:hover { + background: rgba(0,0,0,0.20); + border-radius: 4px; +} +QTabBar::tab { + padding: 3px; + border-style: solid; +} +QTabBar::tab:hover, +QTabBar::tab:selected:hover:enabled { + background: rgba(0,0,0,0.15); +} +QTabBar::tab:selected:enabled { + color: rgb(26,115,232); + background: rgba(0,0,0,0.24); +} +QTabBar::tab:selected:disabled, +QTabBar::tab:only-one:selected:enabled { + border-color: rgb(218,220,224); +} +QTabBar::tab:top { + border-bottom-width: 2px; + margin: 3px 6px 0 0; + border-top-left-radius: 2px; + border-top-right-radius: 2px; +} +QTabBar::tab:bottom { + border-top-width: 2px; + margin: 0 6px 3px 0; + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; +} +QTabBar::tab:left { + border-right-width: 2px; + margin: 0 0 6px 3px; + border-top-left-radius: 2px; + border-bottom-left-radius: 2px; +} +QTabBar::tab:right { + border-left-width: 2px; + margin-bottom: 6px; + margin: 0 3px 6px 0; + border-top-right-radius: 2px; + border-bottom-right-radius: 2px; +} +QTabBar::tab:top:first, +QTabBar::tab:top:only-one, +QTabBar::tab:bottom:first, +QTabBar::tab:bottom:only-one { + margin-left: 2px; +} +QTabBar::tab:top:last, +QTabBar::tab:top:only-one, +QTabBar::tab:bottom:last, +QTabBar::tab:bottom:only-one { + margin-right: 2px; +} +QTabBar::tab:left:first, +QTabBar::tab:left:only-one, +QTabBar::tab:right:first, +QTabBar::tab:right:only-one { + margin-top: 2px; +} +QTabBar::tab:left:last, +QTabBar::tab:left:only-one, +QTabBar::tab:right:last, +QTabBar::tab:right:only-one { + margin-bottom: 2px; +} + /* QColumnView */ QColumnView { background: rgb(248,249,250); From 37abdbec1b88d8bda07be132e8b8d08334b6e8e1 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 11:20:42 -0400 Subject: [PATCH 48/67] Tweaks to default theme --- src/sas/system/themes/default.css | 33 ++++--------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index 814eade22c..ddf3b29a4d 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -10,7 +10,7 @@ QWidget { selection-background-color: rgba(26,115,232,0.5); } QWidget:disabled { - color: rgb(248,51,57); + color: rgba(77,81,87,0.4); selection-background-color: rgba(77,81,87,0.25); selection-color: rgba(77,81,87,0.4); } @@ -37,7 +37,7 @@ QRadioButton { } QCheckBox:hover, QRadioButton:hover { - border-bottom: 2px solid rgb(26,115,232); + border-bottom: 2px solid; } /* QGroupBox Properties */ @@ -208,35 +208,10 @@ QPushButton { padding: 4px 8px; border-radius: 4px; } -QPushButton:flat, -QPushButton:default { - border: none; - padding: 5px 9px; -} -QPushButton:default { - color: rgb(248,249,250); - background: rgb(26,115,232); -} -QPushButton:hover { - background: rgba(26,115,232,0.3); -} -QPushButton:pressed { +QPushButton:hover, QPushButton:pressed, QPushButton:checked:enabled { + color: rgb(0,0,0); background: rgba(26,115,232,0.3); } -QPushButton:checked:enabled { - background: rgba(26,115,232,0.3); -} -QPushButton:default:hover { - background: rgba(26,115,232,0.1); -} -QPushButton:default:pressed, -QPushButton:default:checked { - background: rgba(26,115,232,0.3); -} -QPushButton:default:disabled, -QPushButton:default:checked:disabled { - background: rgba(77,81,87,0.25); -} /* QDialogButtonBox */ QDialogButtonBox { From 97ec0771b8481035ec92fa47ffa1b6aecedc9908 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 11:51:48 -0400 Subject: [PATCH 49/67] Tweak menu items in default theme --- src/sas/system/themes/default.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index ddf3b29a4d..8057eb2721 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -129,9 +129,9 @@ QToolBar > QWidget { background: transparent; } -/* QmenU Preperties */ +/* Qmenu Properties */ QMenu { - background: rgb1(248,249,250,0.20); + background: rgba(248,249,250,0.70); padding: 8px 0; border-radius: 4px; } @@ -141,6 +141,7 @@ QMenu::separator { background: rgb(218,220,224); } QMenu::item { + background: transparent; padding: 4px 19px; } QMenu::item:selected { From ceea678bb2349b68a98d57284895a8f5d085a158 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 11:54:17 -0400 Subject: [PATCH 50/67] Replace dark theme using default theme as a basis --- src/sas/system/themes/dark.css | 482 +++++++++++++++++++++++++++++++-- 1 file changed, 458 insertions(+), 24 deletions(-) diff --git a/src/sas/system/themes/dark.css b/src/sas/system/themes/dark.css index c3ca5d343b..8b2d515254 100644 --- a/src/sas/system/themes/dark.css +++ b/src/sas/system/themes/dark.css @@ -1,40 +1,474 @@ /* Global Properties */ -* {font-size: 10pt; font-family: Helvetica, Arial, Verdana, sans-serif; color: whitesmoke; background-color: #333337; border-color: lightgrey;} +* {font-size: 10pt; font-family: Helvetica, Arial, Verdana, sans-serif} -/* Qt Elements */ -QLineEdit {background-color: white; color: black;} -QLineEdit:focus {background-color: #98dbcc; color: #555555} -QLineEdit[warning=true] {background-color: goldenrod;} -QLineEdit[urgent=true] {background-color: darksalmon;} +/* QWidget Properties */ -QCheckBox::indicator:checked {background-color: whitesmoke; color: red} -QCheckBox::indicator:unchecked {background-color: blue; color: green} +QWidget { + background: rgb(63,64,66); + color: rgb(228,231,235); + selection-color: rgb(228,231,235); + selection-background-color: rgba(138,180,247,0.5); +} +QWidget:disabled { + color: rgba(228,231,235,0.4); + selection-background-color: rgba(228,231,235,0.25); + selection-color: rgba(228,231,235,0.4); +} +QWidget:focus { + outline: none; +} -QTableWidgetItem[italic=true] {font-style: italic} +/* QMainWindow Properties */ +QMainWindow::separator { + width: 4px; + height: 4px; + background: rgb(42,43,66); +} +QMainWindow::separator:hover, +QMainWindow::separator:pressed { + background: rgb(138,180,247); +} -QTabBar::tab {background-color: #444448; color: lightgrey;} -QTabBar::tab:hover, QComboBox:hover, QPushButton:hover {background-color: #272728} -QTabBar::tab:disabled {color: #272728} +/* QCheckBox and QRadioButton Properties */ +QCheckBox, +QRadioButton { + border-top: 2px solid transparent; + border-bottom: 2px solid transparent; +} +QCheckBox:hover, +QRadioButton:hover { + border-bottom: 2px solid; +} -QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} +/* QGroupBox Properties */ +QGroupBox { + font-weight: bold; + margin-top: 8px; + padding: 2px 1px 1px 1px; + border-radius: 4px; + border: 1px solid rgb(42,43,66); +} +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + left: 7px; + margin: 0 2px 0 3px; +} +QGroupBox:flat { + border-color: transparent; +} -QPushButton {background-color: #333337; border-color: #555555; border-style: dashed; color: whitesmoke} -QPushButton[urgent=true] {color: darksalmon;} +/* QToolTip Properties */ +QToolTip { + font-size: 80%; + background: rgba(63,64,66,0.2); + color: rgb(228,231,235); +} +/* QMenuBar Properties */ +QMenuBar { + padding: 2px; + border-bottom: 1px solid rgb(42,43,66); + background: rgb(63,64,66); +} +QMenuBar::item { + background: transparent; + padding: 4px; +} +QMenuBar::item:selected { + padding: 4px; + border-radius: 4px; + background: rgba(255,255,255,0.20); +} +QMenuBar::item:pressed { + padding: 4px; + margin-bottom: 0; + padding-bottom: 0; +} -QToolTip {font-size: 80%; background-color: lightgrey} +/* QToolBar */ +QToolBar { + padding: 1px; + font-weight: bold; + spacing: 2px; + margin: 1px; + background: rgb(51,51,51); + /* QToolBar must override `border-style` to set the style. */ + border-style: none; +} +QToolBar::separator { + background: rgb(42,43,66); +} +QToolBar::separator:horizontal { + width: 2px; + margin: 0 6px; +} +QToolBar::separator:vertical { + height: 2px; + margin: 6px 0; +} +QToolBar > QToolButton { + background: transparent; + padding: 3px; + border-radius: 4px; +} +QToolBar > QToolButton:hover, +QToolBar > QToolButton::menu-button:hover { + background: rgba(255,255,255,0.15); +} +QToolBar > QToolButton::menu-button { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +QToolBar > QToolButton:pressed, +QToolBar > QToolButton::menu-button:pressed:enabled, +QToolBar > QToolButton:checked:enabled { + background: rgba(255,255,255,0.24); +} +QToolBar > QWidget { + background: transparent; +} +/* Qmenu Properties */ +QMenu { + background: rgba(63,64,66,0.20); + padding: 8px 0; + border-radius: 4px; +} +QMenu::separator { + margin: 4px 0; + height: 1px; + background: rgb(42,43,66); +} +QMenu::item { + padding: 4px 19px; +} +QMenu::item:selected { + background: rgba(255,255,255,0.12); +} +QMenu::icon { + padding-left: 10px; + width: 14px; + height: 14px; +} + +/* QScrollBar */ +QScrollBar { + background: rgba(255,255,255,0.40); + border-radius: 4px; +} +QScrollBar:horizontal { + height: 14px; +} +QScrollBar:vertical { +} +QScrollBar::handle { + background: rgba(255,255,255,0.40); + border-radius: 3px; +} +QScrollBar::handle:hover { + background: rgba(255,255,255,0.50); +} +QScrollBar::handle:pressed { + background: rgba(255,255,255,0.24); +} +QScrollBar::handle:disabled { + background: rgba(255,255,255,0.15); +} +QScrollBar::handle:horizontal { + min-width: 8px; + margin: 4px 14px; +} +QScrollBar::handle:horizontal:hover { + margin: 2px 14px; +} +QScrollBar::handle:vertical { + min-height: 8px; + margin: 14px 4px; +} +QScrollBar::handle:vertical:hover { + margin: 14px 2px; +} +/* +Hide QScrollBar background. +The `sub-page` and `add-page` are not colored by default on most OS, but are colored on Windows. +*/ +QScrollBar::sub-page, +QScrollBar::add-page { + background: transparent; +} +QScrollBar::sub-line, +QScrollBar::add-line { + background: transparent; +} + +QPushButton { + color: rgb(138,180,247); + border: 1px solid rgb(42,43,66); + padding: 4px 8px; + border-radius: 4px; +} +QPushButton:hover, QPushButton:pressed, QPushButton:checked:enabled { + color: rgb(0,0,0); + background: rgba(138,180,247,0.3); +} + +/* QDialogButtonBox */ +QDialogButtonBox { + dialogbuttonbox-buttons-have-icons: 0; +} +QDialogButtonBox QPushButton { + min-width: 65px; +} + +/* QComboBox */ +QComboBox { + min-height: 1.5em; + padding: 0 8px 0 4px; + background: rgb(63,64,66); + border: 1px solid rgb(42,43,66); + border-radius: 4px; +} +QComboBox:hover, QComboBox::item:hover, QComboBox:focus, QComboBox:open { + border-color: rgb(138,180,247); +} +QComboBox::drop-down { + margin: 2px 2px 2px -6px; + border-radius: 4px; /* This remove default style. */ +} +QComboBox::drop-down:editable:hover { + background: rgba(255,255,255,0.13); +} +/* Setting background color of selected item when editable is false. */ +QComboBox::item:selected { + border: none; /* This remove the border of indicator. */ + background: rgba(26,115,278,0.35); + border-radius: 4px; +} + +/* QAbstractItemView in QComboBox is NoFrame. Override default settings and show border. */ +QComboBox QListView { + margin: 0; + padding: 4px; + background: rgba(63,64,66,0.25); + border-radius: 4px; +} +QComboBox QListView::item { + border-radius: 4px; +} + +/* QListView QTreeView */ +QListView { + padding: 1px +} +QListView, +QTreeView { + background: rgb(63,64,66); +} +QListView::item:hover, +QTreeView::item:hover, +QTreeView::branch:hover { + background: rgb(42,43,66); +} +QTreeView::branch:open:has-children:!has-siblings, +QTreeView::branch:open:has-children:has-siblings { + border-image: unset; + background: rgba(228,231,235,0.05); +} +QTreeView::branch:open:has-children:!has-siblings:disabled, +QTreeView::branch:open:has-children:has-siblings:disabled { + background: rgba(228,231,235,0.05); +} +QTreeView > QHeaderView { + background: rgb(63,64,66); +} +QTreeView > QHeaderView::section { + background: rgb(42,43,66); +} + +/* +Following arrow settings are for QColumnView. +QColumnView::left-arrow and QColumnView::right-arrow are not working. +*/ +QListView::left-arrow { + margin: -2px; +} +QListView::right-arrow { + margin: -2px; +} + +/* QTabWidget QTabBar */ +QTabWidget::pane { + border: 1px solid rgb(42,43,66); + border-radius: 4px; +} +QTabBar { + /* + Not filling background color when drawBase property is true. So need to set drawBase to false. + Default QTabBar is no need following declaration, but QMdiArea is need. + */ + qproperty-drawBase: 0; +} +QTabBar::close-button:hover { + background: rgba(255,255,255,0.20); + border-radius: 4px; +} +QTabBar::tab { + padding: 3px; + border-style: solid; +} +QTabBar::tab:hover, +QTabBar::tab:selected:hover:enabled { + background: rgba(255,255,255,0.15); +} +QTabBar::tab:selected:enabled { + color: rgb(138,180,247); + background: rgba(255,255,255,0.24); +} +QTabBar::tab:selected:disabled, +QTabBar::tab:only-one:selected:enabled { + border-color: rgb(42,43,66); +} +QTabBar::tab:top { + border-bottom-width: 2px; + margin: 3px 6px 0 0; + border-top-left-radius: 2px; + border-top-right-radius: 2px; +} +QTabBar::tab:bottom { + border-top-width: 2px; + margin: 0 6px 3px 0; + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; +} +QTabBar::tab:left { + border-right-width: 2px; + margin: 0 0 6px 3px; + border-top-left-radius: 2px; + border-bottom-left-radius: 2px; +} +QTabBar::tab:right { + border-left-width: 2px; + margin-bottom: 6px; + margin: 0 3px 6px 0; + border-top-right-radius: 2px; + border-bottom-right-radius: 2px; +} +QTabBar::tab:top:first, +QTabBar::tab:top:only-one, +QTabBar::tab:bottom:first, +QTabBar::tab:bottom:only-one { + margin-left: 2px; +} +QTabBar::tab:top:last, +QTabBar::tab:top:only-one, +QTabBar::tab:bottom:last, +QTabBar::tab:bottom:only-one { + margin-right: 2px; +} +QTabBar::tab:left:first, +QTabBar::tab:left:only-one, +QTabBar::tab:right:first, +QTabBar::tab:right:only-one { + margin-top: 2px; +} +QTabBar::tab:left:last, +QTabBar::tab:left:only-one, +QTabBar::tab:right:last, +QTabBar::tab:right:only-one { + margin-bottom: 2px; +} + +/* QColumnView */ +QColumnView { + background: rgb(63,64,66); +} +QColumnViewGrip { + margin: -4px; + background: rgb(63,64,66); +} + +/* QTableView */ +QTableView { + gridline-color: rgb(42,43,66); + background: rgba(63,64,66,0.5); +} +QTableView:!active { + background: rgba(255,255,255,0.12); +} +QTableView::item:alternate { + background: rgba(255,255,255,0.12); +} +QTableView::item:selected { + background: rgba(63,64,66,0.5); +} +QTableView QTableCornerButton::section { + margin: 0 1px 1px 0; + background: rgb(42,43,66); + border-top-left-radius: 2px; +} +QTableView QTableCornerButton::section:pressed { + background: rgba(138,180,247,0.35); +} +QTableView > QHeaderView { + background: rgba(63,64,66,0.50); + border-radius: 3px; +} +QTableView > QHeaderView::section { + background: rgb(42,43,66); +} + +/* QLineEdit */ +QLineEdit { + padding: 3px 4px; + /* Adjust the min-height of QLineEdit to the height of the characters. */ + min-height: 1em; + border: 1px solid rgb(42,43,66); + background: rgb(63,64,66); + border-radius: 4px; +} +QLineEdit:focus { + border-color: rgb(138,180,247); +} + +/* QFileDialog */ +QFileDialog QFrame { + border: none; +} + +/* Check */ +QComboBox::indicator, +QMenu::indicator { + width: 18px; + height: 18px; +} +QMenu::indicator { + background: rgba(255,255,255,0.19); + margin-left: 3px; + border-radius: 4px; +} + +/* Check indicator */ +QCheckBox, +QRadioButton { + spacing: 8px; +} +QGroupBox::title, +QAbstractItemView::item { + spacing: 6px; +} +QCheckBox::indicator, +QGroupBox::indicator, +QAbstractItemView::indicator, +QRadioButton::indicator { + height: 18px; + width: 18px; +} + +/* Styles that are not from taken PyQtDarkTheme */ QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow} QCodeEditor {font-family: 'monospace, monospace'} QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} - -QTreeView {paint-alternating-row-colors-for-empty-area:0; background-color: #333337} -QTreeView::item {border: 1px; padding: 2px 1px;} -QTreeView::item:hover {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1); border: 1px solid #bfcde4;} -QTreeView::item:selected {border: 1px solid #567dbc;} -QTreeView::item:selected:active{background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);} -QTreeView::item:selected:!active {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);} - From 450e37f68b903fcabd90baedefc2285b967f9463 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 11:54:57 -0400 Subject: [PATCH 51/67] Replace large font theme using default theme as a basis --- src/sas/system/themes/largefont.css | 486 ++++++++++++++++++++++++++-- 1 file changed, 464 insertions(+), 22 deletions(-) diff --git a/src/sas/system/themes/largefont.css b/src/sas/system/themes/largefont.css index 77c34e2846..b6f36421ab 100644 --- a/src/sas/system/themes/largefont.css +++ b/src/sas/system/themes/largefont.css @@ -1,33 +1,475 @@ /* Global Properties */ -* {font-size: 11pt; font-family: Helvetica, Arial, Verdana, sans-serif} +* {font-size: 12pt; font-family: Helvetica, Arial, Verdana, sans-serif} -/* Deviations from default theme */ -QTabBar::tab, QLineEdit, QTableWidgetItem, QLabel, QPushButton, QComboBox {font-size: 12pt;} +/* QWidget Properties */ -/* Qt Elements */ -QLineEdit {background-color: white; color: black} -QLineEdit:focus {background-color: #98dbcc; color: #333333} -QLineEdit[warning=true] {background-color: yellow;} -QLineEdit[urgent=true] {background-color: red;} -QTableWidgetItem[italic=true] {font-style: italic} +QWidget { + background: rgb(248,249,250); + color: rgb(77,81,87); + selection-color: rgb(77,81,87); + selection-background-color: rgba(26,115,232,0.5); +} +QWidget:disabled { + color: rgba(77,81,87,0.4); + selection-background-color: rgba(77,81,87,0.25); + selection-color: rgba(77,81,87,0.4); +} +QWidget:focus { + outline: none; +} -QLabel[angstrom=true] {font-family: -apple-system, "Helvetica Neue", "Ubuntu";} +/* QMainWindow Properties */ +QMainWindow::separator { + width: 4px; + height: 4px; + background: rgb(218,220,224); +} +QMainWindow::separator:hover, +QMainWindow::separator:pressed { + background: rgb(26,115,232); +} -QPushButton {color: black} -QPushButton[urgent=true] {color: red;} +/* QCheckBox and QRadioButton Properties */ +QCheckBox, +QRadioButton { + border-top: 2px solid transparent; + border-bottom: 2px solid transparent; +} +QCheckBox:hover, +QRadioButton:hover { + border-bottom: 2px solid; +} -QToolTip {font-size: 80%;} +/* QGroupBox Properties */ +QGroupBox { + font-weight: bold; + margin-top: 8px; + padding: 2px 1px 1px 1px; + border-radius: 4px; + border: 1px solid rgb(218,220,224); +} +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + left: 7px; + margin: 0 2px 0 3px; +} +QGroupBox:flat { + border-color: transparent; +} +/* QToolTip Properties */ +QToolTip { + font-size: 80%; + background: rgba(248,249,250,0.2); + color: rgb(77,81,87); +} + +/* QMenuBar Properties */ +QMenuBar { + padding: 2px; + border-bottom: 1px solid rgb(218,220,224); + background: rgb(248,249,250); +} +QMenuBar::item { + background: transparent; + padding: 4px; +} +QMenuBar::item:selected { + padding: 4px; + border-radius: 4px; + background: rgba(0,0,0,0.20); +} +QMenuBar::item:pressed { + padding: 4px; + margin-bottom: 0; + padding-bottom: 0; +} + +/* QToolBar */ +QToolBar { + padding: 1px; + font-weight: bold; + spacing: 2px; + margin: 1px; + background: rgb(235,235,235); + /* QToolBar must override `border-style` to set the style. */ + border-style: none; +} +QToolBar::separator { + background: rgb(218,220,224); +} +QToolBar::separator:horizontal { + width: 2px; + margin: 0 6px; +} +QToolBar::separator:vertical { + height: 2px; + margin: 6px 0; +} +QToolBar > QToolButton { + background: transparent; + padding: 3px; + border-radius: 4px; +} +QToolBar > QToolButton:hover, +QToolBar > QToolButton::menu-button:hover { + background: rgba(0,0,0,0.15); +} +QToolBar > QToolButton::menu-button { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +QToolBar > QToolButton:pressed, +QToolBar > QToolButton::menu-button:pressed:enabled, +QToolBar > QToolButton:checked:enabled { + background: rgba(0,0,0,0.24); +} +QToolBar > QWidget { + background: transparent; +} + +/* Qmenu Properties */ +QMenu { + background: rgba(248,249,250,0.70); + padding: 8px 0; + border-radius: 4px; +} +QMenu::separator { + margin: 4px 0; + height: 1px; + background: rgb(218,220,224); +} +QMenu::item { + background: transparent; + padding: 4px 19px; +} +QMenu::item:selected { + background: rgba(0,0,0,0.12); +} +QMenu::icon { + padding-left: 10px; + width: 14px; + height: 14px; +} + +/* QScrollBar */ +QScrollBar { + background: rgba(0,0,0,0.40); + border-radius: 4px; +} +QScrollBar:horizontal { + height: 14px; +} +QScrollBar:vertical { +} +QScrollBar::handle { + background: rgba(0,0,0,0.40); + border-radius: 3px; +} +QScrollBar::handle:hover { + background: rgba(0,0,0,0.50); +} +QScrollBar::handle:pressed { + background: rgba(0,0,0,0.24); +} +QScrollBar::handle:disabled { + background: rgba(0,0,0,0.15); +} +QScrollBar::handle:horizontal { + min-width: 8px; + margin: 4px 14px; +} +QScrollBar::handle:horizontal:hover { + margin: 2px 14px; +} +QScrollBar::handle:vertical { + min-height: 8px; + margin: 14px 4px; +} +QScrollBar::handle:vertical:hover { + margin: 14px 2px; +} +/* +Hide QScrollBar background. +The `sub-page` and `add-page` are not colored by default on most OS, but are colored on Windows. +*/ +QScrollBar::sub-page, +QScrollBar::add-page { + background: transparent; +} +QScrollBar::sub-line, +QScrollBar::add-line { + background: transparent; +} + +QPushButton { + color: rgb(26,115,232); + border: 1px solid rgb(218,220,224); + padding: 4px 8px; + border-radius: 4px; +} +QPushButton:hover, QPushButton:pressed, QPushButton:checked:enabled { + color: rgb(0,0,0); + background: rgba(26,115,232,0.3); +} + +/* QDialogButtonBox */ +QDialogButtonBox { + dialogbuttonbox-buttons-have-icons: 0; +} +QDialogButtonBox QPushButton { + min-width: 65px; +} + +/* QComboBox */ +QComboBox { + min-height: 1.5em; + padding: 0 8px 0 4px; + background: rgb(248,249,250); + border: 1px solid rgb(218,220,224); + border-radius: 4px; +} +QComboBox:hover, QComboBox::item:hover, QComboBox:focus, QComboBox:open { + border-color: rgb(26,115,232); +} +QComboBox::drop-down { + margin: 2px 2px 2px -6px; + border-radius: 4px; /* This remove default style. */ +} +QComboBox::drop-down:editable:hover { + background: rgba(0,0,0,0.13); +} +/* Setting background color of selected item when editable is false. */ +QComboBox::item:selected { + border: none; /* This remove the border of indicator. */ + background: rgba(26,115,278,0.35); + border-radius: 4px; +} + +/* QAbstractItemView in QComboBox is NoFrame. Override default settings and show border. */ +QComboBox QListView { + margin: 0; + padding: 4px; + background: rgba(248,249,250,0.25); + border-radius: 4px; +} +QComboBox QListView::item { + border-radius: 4px; +} + +/* QListView QTreeView */ +QListView { + padding: 1px +} +QListView, +QTreeView { + background: rgb(248,249,250); +} +QListView::item:hover, +QTreeView::item:hover, +QTreeView::branch:hover { + background: rgb(218,220,224); +} +QTreeView::branch:open:has-children:!has-siblings, +QTreeView::branch:open:has-children:has-siblings { + border-image: unset; + background: rgba(77,81,87,0.05); +} +QTreeView::branch:open:has-children:!has-siblings:disabled, +QTreeView::branch:open:has-children:has-siblings:disabled { + background: rgba(77,81,87,0.05); +} +QTreeView > QHeaderView { + background: rgb(248,249,250); +} +QTreeView > QHeaderView::section { + background: rgb(218,220,224); +} + +/* +Following arrow settings are for QColumnView. +QColumnView::left-arrow and QColumnView::right-arrow are not working. +*/ +QListView::left-arrow { + margin: -2px; +} +QListView::right-arrow { + margin: -2px; +} + +/* QTabWidget QTabBar */ +QTabWidget::pane { + border: 1px solid rgb(218,220,224); + border-radius: 4px; +} +QTabBar { + /* + Not filling background color when drawBase property is true. So need to set drawBase to false. + Default QTabBar is no need following declaration, but QMdiArea is need. + */ + qproperty-drawBase: 0; +} +QTabBar::close-button:hover { + background: rgba(0,0,0,0.20); + border-radius: 4px; +} +QTabBar::tab { + padding: 3px; + border-style: solid; +} +QTabBar::tab:hover, +QTabBar::tab:selected:hover:enabled { + background: rgba(0,0,0,0.15); +} +QTabBar::tab:selected:enabled { + color: rgb(26,115,232); + background: rgba(0,0,0,0.24); +} +QTabBar::tab:selected:disabled, +QTabBar::tab:only-one:selected:enabled { + border-color: rgb(218,220,224); +} +QTabBar::tab:top { + border-bottom-width: 2px; + margin: 3px 6px 0 0; + border-top-left-radius: 2px; + border-top-right-radius: 2px; +} +QTabBar::tab:bottom { + border-top-width: 2px; + margin: 0 6px 3px 0; + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; +} +QTabBar::tab:left { + border-right-width: 2px; + margin: 0 0 6px 3px; + border-top-left-radius: 2px; + border-bottom-left-radius: 2px; +} +QTabBar::tab:right { + border-left-width: 2px; + margin-bottom: 6px; + margin: 0 3px 6px 0; + border-top-right-radius: 2px; + border-bottom-right-radius: 2px; +} +QTabBar::tab:top:first, +QTabBar::tab:top:only-one, +QTabBar::tab:bottom:first, +QTabBar::tab:bottom:only-one { + margin-left: 2px; +} +QTabBar::tab:top:last, +QTabBar::tab:top:only-one, +QTabBar::tab:bottom:last, +QTabBar::tab:bottom:only-one { + margin-right: 2px; +} +QTabBar::tab:left:first, +QTabBar::tab:left:only-one, +QTabBar::tab:right:first, +QTabBar::tab:right:only-one { + margin-top: 2px; +} +QTabBar::tab:left:last, +QTabBar::tab:left:only-one, +QTabBar::tab:right:last, +QTabBar::tab:right:only-one { + margin-bottom: 2px; +} + +/* QColumnView */ +QColumnView { + background: rgb(248,249,250); +} +QColumnViewGrip { + margin: -4px; + background: rgb(248,249,250); +} + +/* QTableView */ +QTableView { + gridline-color: rgb(218,220,224); + background: rgba(248,249,250,0.5); +} +QTableView:!active { + background: rgba(0,0,0,0.12); +} +QTableView::item:alternate { + background: rgba(0,0,0,0.12); +} +QTableView::item:selected { + background: rgba(248,249,250,0.5); +} +QTableView QTableCornerButton::section { + margin: 0 1px 1px 0; + background: rgb(218,220,224); + border-top-left-radius: 2px; +} +QTableView QTableCornerButton::section:pressed { + background: rgba(26,115,232,0.35); +} +QTableView > QHeaderView { + background: rgba(248,249,250,0.50); + border-radius: 3px; +} +QTableView > QHeaderView::section { + background: rgb(218,220,224); +} + +/* QLineEdit */ +QLineEdit { + padding: 3px 4px; + /* Adjust the min-height of QLineEdit to the height of the characters. */ + min-height: 1em; + border: 1px solid rgb(218,220,224); + background: rgb(248,249,250); + border-radius: 4px; +} +QLineEdit:focus { + border-color: rgb(26,115,232); +} + +/* QFileDialog */ +QFileDialog QFrame { + border: none; +} + +/* Check */ +QComboBox::indicator, +QMenu::indicator { + width: 18px; + height: 18px; +} +QMenu::indicator { + background: rgba(0,0,0,0.19); + margin-left: 3px; + border-radius: 4px; +} + +/* Check indicator */ +QCheckBox, +QRadioButton { + spacing: 8px; +} +QGroupBox::title, +QAbstractItemView::item { + spacing: 6px; +} +QCheckBox::indicator, +QGroupBox::indicator, +QAbstractItemView::indicator, +QRadioButton::indicator { + height: 18px; + width: 18px; +} + +/* Styles that are not from taken PyQtDarkTheme */ QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} -QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow; font-size: 12pt;} -QCodeEditor {font-family: 'monospace, monospace'; font-size: 12pt;} +QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow} +QCodeEditor {font-family: 'monospace, monospace'} QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} - -QTreeView {paint-alternating-row-colors-for-empty-area:0;} -QTreeView::item {border: 1px; padding: 2px 1px;} -QTreeView::item:hover {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1); border: 1px solid #bfcde4;} -QTreeView::item:selected {border: 1px solid #567dbc;} -QTreeView::item:selected:active{background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);} -QTreeView::item:selected:!active {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);} From 85cd6092fe8db39f51aef79730a768406d7ab1be Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 12:00:56 -0400 Subject: [PATCH 52/67] Remove alternating colors from model list view --- src/sas/qtgui/Perspectives/Fitting/FittingWidget.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py b/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py index 1a432b772a..d8a7291ba9 100644 --- a/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py +++ b/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py @@ -402,7 +402,6 @@ def initializeModels(self): # Delegates for custom editing and display self.lstParams.setItemDelegate(ModelViewDelegate(self)) - self.lstParams.setAlternatingRowColors(True) self.lstParams.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.lstParams.customContextMenuRequested.connect(self.showModelContextMenu) self.lstParams.setAttribute(QtCore.Qt.WA_MacShowFocusRect, False) From 2a8fe1886013e8f2a112b81d1bc39ac094860a3d Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 12:18:56 -0400 Subject: [PATCH 53/67] Pass parent to tool panels to ensure theme is applied to them --- src/sas/qtgui/Calculators/DataOperationUtilityPanel.py | 2 +- src/sas/qtgui/Calculators/DensityPanel.py | 2 +- src/sas/qtgui/Calculators/GenericScatteringCalculator.py | 2 +- src/sas/qtgui/Calculators/KiessigPanel.py | 2 +- src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py | 2 +- src/sas/qtgui/Calculators/SldPanel.py | 2 +- src/sas/qtgui/Calculators/SlitSizeCalculator.py | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/sas/qtgui/Calculators/DataOperationUtilityPanel.py b/src/sas/qtgui/Calculators/DataOperationUtilityPanel.py index e7a1670fa7..2105cbbe11 100644 --- a/src/sas/qtgui/Calculators/DataOperationUtilityPanel.py +++ b/src/sas/qtgui/Calculators/DataOperationUtilityPanel.py @@ -18,7 +18,7 @@ class DataOperationUtilityPanel(QtWidgets.QDialog, Ui_DataOperationUtility): def __init__(self, parent=None): - super(DataOperationUtilityPanel, self).__init__() + super(DataOperationUtilityPanel, self).__init__(parent._parent if parent else None) self.setupUi(self) self.manager = parent self.communicator = self.manager.communicator() diff --git a/src/sas/qtgui/Calculators/DensityPanel.py b/src/sas/qtgui/Calculators/DensityPanel.py index d8f642774e..bab7340d40 100644 --- a/src/sas/qtgui/Calculators/DensityPanel.py +++ b/src/sas/qtgui/Calculators/DensityPanel.py @@ -42,7 +42,7 @@ def toMolarMass(formula): class DensityPanel(QtWidgets.QDialog): def __init__(self, parent=None): - super(DensityPanel, self).__init__() + super(DensityPanel, self).__init__(parent._parent if parent else None) self.mode = None self.manager = parent diff --git a/src/sas/qtgui/Calculators/GenericScatteringCalculator.py b/src/sas/qtgui/Calculators/GenericScatteringCalculator.py index c9e748ba26..0bca241101 100644 --- a/src/sas/qtgui/Calculators/GenericScatteringCalculator.py +++ b/src/sas/qtgui/Calculators/GenericScatteringCalculator.py @@ -45,7 +45,7 @@ class GenericScatteringCalculator(QtWidgets.QDialog, Ui_GenericScatteringCalcula loadingFinishedSignal = QtCore.Signal(list, bool) def __init__(self, parent=None): - super(GenericScatteringCalculator, self).__init__() + super(GenericScatteringCalculator, self).__init__(parent._parent if parent else None) self.setupUi(self) # disable the context help icon self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint) diff --git a/src/sas/qtgui/Calculators/KiessigPanel.py b/src/sas/qtgui/Calculators/KiessigPanel.py index 7677234ded..331e8f675a 100644 --- a/src/sas/qtgui/Calculators/KiessigPanel.py +++ b/src/sas/qtgui/Calculators/KiessigPanel.py @@ -12,7 +12,7 @@ class KiessigPanel(QtWidgets.QDialog, Ui_KiessigPanel): def __init__(self, parent=None): - super(KiessigPanel, self).__init__() + super(KiessigPanel, self).__init__(parent._parent if parent else None) self.setupUi(self) # disable the context help icon self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint) diff --git a/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py b/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py index d84e25b1af..a4d768ea6e 100644 --- a/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py +++ b/src/sas/qtgui/Calculators/ResolutionCalculatorPanel.py @@ -38,7 +38,7 @@ class ResolutionCalculatorPanel(QtWidgets.QDialog, Ui_ResolutionCalculatorPanel) compute resolution in 2D """ def __init__(self, parent=None): - super(ResolutionCalculatorPanel, self).__init__() + super(ResolutionCalculatorPanel, self).__init__(parent._parent if parent else None) self.setupUi(self) # disable the context help icon self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint) diff --git a/src/sas/qtgui/Calculators/SldPanel.py b/src/sas/qtgui/Calculators/SldPanel.py index 1b657e4c96..52547100c0 100644 --- a/src/sas/qtgui/Calculators/SldPanel.py +++ b/src/sas/qtgui/Calculators/SldPanel.py @@ -90,7 +90,7 @@ def xraySldAlgorithm(molecular_formula, mass_density, xray_wavelength): class SldPanel(QtWidgets.QDialog): def __init__(self, parent=None): - super(SldPanel, self).__init__() + super(SldPanel, self).__init__(parent._parent if parent else None) self.manager = parent diff --git a/src/sas/qtgui/Calculators/SlitSizeCalculator.py b/src/sas/qtgui/Calculators/SlitSizeCalculator.py index 26783b1daf..1ddfe43b51 100644 --- a/src/sas/qtgui/Calculators/SlitSizeCalculator.py +++ b/src/sas/qtgui/Calculators/SlitSizeCalculator.py @@ -22,7 +22,7 @@ class SlitSizeCalculator(QtWidgets.QDialog, Ui_SlitSizeCalculator): Provides the slit length calculator GUI. """ def __init__(self, parent=None): - super(SlitSizeCalculator, self).__init__() + super(SlitSizeCalculator, self).__init__(parent._parent if parent else None) self.setupUi(self) # disable the context help icon self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint) From f4e9146691efedfa02cfa7314a1dc8f5f4a87fe0 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 12:40:44 -0400 Subject: [PATCH 54/67] Apply style sheet to orientation viewer and what's new box --- src/sas/qtgui/MainWindow/GuiManager.py | 6 +++--- .../qtgui/Utilities/OrientationViewer/OrientationViewer.py | 5 +++-- src/sas/qtgui/Utilities/WhatsNew/WhatsNew.py | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/sas/qtgui/MainWindow/GuiManager.py b/src/sas/qtgui/MainWindow/GuiManager.py index 5fe658a954..ef2cfb5ef2 100644 --- a/src/sas/qtgui/MainWindow/GuiManager.py +++ b/src/sas/qtgui/MainWindow/GuiManager.py @@ -178,8 +178,8 @@ def addWidgets(self): self._workspace.resizeDocks([self.dockedFilesWidget], [305], Qt.Horizontal) # Add other, minor widgets - self.ackWidget = Acknowledgements() - self.aboutWidget = AboutBox() + self.ackWidget = Acknowledgements(self._parent) + self.aboutWidget = AboutBox(self._parent) self.categoryManagerWidget = CategoryManager(self._parent, manager=self) self.grid_window = None @@ -1041,7 +1041,7 @@ def actionOrientation_Viewer(self): """ Make sasmodels orientation & jitter viewer available """ - show_orientation_viewer() + show_orientation_viewer(self._parent) def actionImage_Viewer(self): """ diff --git a/src/sas/qtgui/Utilities/OrientationViewer/OrientationViewer.py b/src/sas/qtgui/Utilities/OrientationViewer/OrientationViewer.py index 54437ca983..750469b8fd 100644 --- a/src/sas/qtgui/Utilities/OrientationViewer/OrientationViewer.py +++ b/src/sas/qtgui/Utilities/OrientationViewer/OrientationViewer.py @@ -63,6 +63,7 @@ def __init__(self, parent=None): super().__init__() self.parent = parent + self.setStyleSheet(self.parent.styleSheet()) self.setWindowTitle("Orientation Viewer") @@ -290,8 +291,8 @@ def closeEvent(self, event): # Code for handling multiple orientation viewers _orientation_viewers = [] -def show_orientation_viewer(): - ov = OrientationViewer() +def show_orientation_viewer(parent=None): + ov = OrientationViewer(parent) ov.show() ov.resize(600, 600) diff --git a/src/sas/qtgui/Utilities/WhatsNew/WhatsNew.py b/src/sas/qtgui/Utilities/WhatsNew/WhatsNew.py index c271e506a6..111e9c627f 100644 --- a/src/sas/qtgui/Utilities/WhatsNew/WhatsNew.py +++ b/src/sas/qtgui/Utilities/WhatsNew/WhatsNew.py @@ -47,7 +47,7 @@ class WhatsNew(QDialog): """ def __init__(self, parent=None): - super().__init__() + super().__init__(parent._parent if parent else None) self.setWindowTitle(f"What's New in SasView {sasview_version}") From 001d2201346f03f6bbfcc5ca23e1d281f9b1a5d1 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 13:43:10 -0400 Subject: [PATCH 55/67] Ensure user themes use the classic theme as a basis. --- src/sas/system/themes/__init__.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py index 532f84125c..0023b43399 100644 --- a/src/sas/system/themes/__init__.py +++ b/src/sas/system/themes/__init__.py @@ -17,16 +17,21 @@ def load_theme(theme: str = None) -> str: - """Using a theme name, load the associated CSS file. - :param theme: The key value in ALL_THEMES - :return: The loaded CSS + """Using a theme name, load the associated CSS file. User themes will be based off the Classic theme. + :param theme: The key value in OPTIONS + :return: The CSS string loaded from file """ + css = "" if not theme or theme not in find_available_themes(): logger.warning(f"Invalid theme name provided: {theme}") theme = 'Default' + # User themes should use the classic theme as a basis and build on it from there + if theme.startswith('User:'): + with open(OPTIONS.get('Classic').absolute()) as fd: + css += fd.read() path = OPTIONS.get(theme) with open(path.absolute()) as fd: - css = fd.read() + css += fd.read() return css From 1f96f972c2edb69e02bace4a1685e26b7e3be7d7 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 14:07:54 -0400 Subject: [PATCH 56/67] Auto apply theme when selected --- .../Preferences/DisplayPreferencesWidget.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py b/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py index eef7b03302..9d41f556e9 100644 --- a/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py +++ b/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py @@ -14,13 +14,11 @@ def __init__(self): 'DISABLE_POLYDISPERSITY_PLOT', 'THEME'] self.restart_params = {'QT_SCALE_FACTOR': 'QT Screen Scale Factor', - 'QT_AUTO_SCREEN_SCALE_FACTOR': "Enable Automatic Scaling", - 'THEME': "Display theme"} + 'QT_AUTO_SCREEN_SCALE_FACTOR': "Enable Automatic Scaling"} def _addAllWidgets(self): self.theme = self.addComboBox(title="Theme", params=style.get_theme_names(), default=style.theme) - self.theme.currentIndexChanged.connect( - lambda: self._stageChange('THEME', self.theme.currentText())) + self.theme.currentIndexChanged.connect(self._previewTheme) self.qtScaleFactor = self.addFloatInput( title="QT Screen Scale Factor", default_number=config.QT_SCALE_FACTOR) @@ -38,6 +36,18 @@ def _toggleBlockAllSignaling(self, toggle): def _restoreFromConfig(self): self.theme.setCurrentText(config.THEME) + self._previewTheme() self.qtScaleFactor.setText(str(config.QT_SCALE_FACTOR)) GuiUtils.updateProperty(self.qtScaleFactor, 'warning', 'false') self.autoScaling.setChecked(bool(config.QT_AUTO_SCREEN_SCALE_FACTOR)) + + def _previewTheme(self): + # Store existing theme + self._stageChange('THEME', self.theme.currentText()) + theme = config.THEME + style.css = self.theme.currentText() + # The CSS getter uses the config theme, not the set theme + config.THEME = self.theme.currentText() + self.parent.parent.setStyleSheet(style.css) + # Set the config theme back for easy reset + config.THEME = theme From 47c62f69143567295534a36fa6e8b84380599ae5 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 14:40:27 -0400 Subject: [PATCH 57/67] Ensure user themes are in dictionary when switching themes --- src/sas/system/themes/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py index 0023b43399..493efc4820 100644 --- a/src/sas/system/themes/__init__.py +++ b/src/sas/system/themes/__init__.py @@ -21,16 +21,16 @@ def load_theme(theme: str = None) -> str: :param theme: The key value in OPTIONS :return: The CSS string loaded from file """ + themes = find_available_themes() css = "" if not theme or theme not in find_available_themes(): logger.warning(f"Invalid theme name provided: {theme}") theme = 'Default' # User themes should use the classic theme as a basis and build on it from there if theme.startswith('User:'): - with open(OPTIONS.get('Classic').absolute()) as fd: + with open(themes.get('Classic').absolute()) as fd: css += fd.read() - path = OPTIONS.get(theme) - with open(path.absolute()) as fd: + with open(themes.get(theme).absolute()) as fd: css += fd.read() return css From 3d8bf0bdc5be52b080a8fe4845d728fa02ad9e86 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 15:00:02 -0400 Subject: [PATCH 58/67] Documentation --- src/sas/qtgui/MainWindow/media/preferences_help.rst | 6 ++++++ src/sas/system/style.py | 6 ++++++ src/sas/system/themes/__init__.py | 1 + 3 files changed, 13 insertions(+) diff --git a/src/sas/qtgui/MainWindow/media/preferences_help.rst b/src/sas/qtgui/MainWindow/media/preferences_help.rst index 587cf293d6..4c9b6f9479 100644 --- a/src/sas/qtgui/MainWindow/media/preferences_help.rst +++ b/src/sas/qtgui/MainWindow/media/preferences_help.rst @@ -39,6 +39,12 @@ Display Preferences The display preferences modify underlying features of our GUI framework, Qt. For more information on each setting, please read more on the `Qt High DPI Settings `_. +**Theme**: A few basic themes are available for SasView. On selection of a new theme, the window will update as a preview. +Users can create their own themes and store them in `/.sasview/themes/` folder of their user directory. User themes will +use the `Classic` theme as a fall back for any styles not defined in the stylesheet. SasView assumes any file in the directory +is a stylesheet. For more information on writing Qt stylesheets, please see the +`Qt style sheet reference `_ *persistent* + **QT Screen Scale Factor**: A percent scaling factor that is applied all element sizes within the GUI. A restart of SasView is required to take effect. *persistent* diff --git a/src/sas/system/style.py b/src/sas/system/style.py index e79c0c21ec..0b1e2d200f 100644 --- a/src/sas/system/style.py +++ b/src/sas/system/style.py @@ -18,19 +18,25 @@ def __init__(self): @property def css(self) -> str: + """A property that exposes the css string to the public.""" self.theme = config.THEME self._css = load_theme(self.theme) return self._css @css.setter def css(self, theme: str): + """A way to set the theme from outside the class. This attempts to load the theme and will throw an + exception for undefined themes.""" self.theme = theme self._css = load_theme(theme) def update_theme_list(self): + """A helper method to find the latest list of themes. + Potential future use includes monitoring user theme changes.""" self._available_themes = find_available_themes() def get_theme_names(self) -> List[str]: + """Return a list of theme names for use by an external system.""" return list(self._available_themes.keys()) diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py index 493efc4820..939833f20d 100644 --- a/src/sas/system/themes/__init__.py +++ b/src/sas/system/themes/__init__.py @@ -8,6 +8,7 @@ logger = logging.getLogger() +# The base dictionary mapping theme names to their location on disk. OPTIONS = { 'Default': Path(os.path.join(os.path.dirname(__file__), 'default.css')), 'Dark': Path(os.path.join(os.path.dirname(__file__), 'dark.css')), From d7a5d394dc0196a5fe5c21517693e51ffb31aabf Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 30 Oct 2023 16:12:47 -0400 Subject: [PATCH 59/67] Update themes for new "Send To" perspective button type --- src/sas/system/themes/dark.css | 5 +++-- src/sas/system/themes/default.css | 5 +++-- src/sas/system/themes/largefont.css | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/sas/system/themes/dark.css b/src/sas/system/themes/dark.css index 8b2d515254..7935f6a19a 100644 --- a/src/sas/system/themes/dark.css +++ b/src/sas/system/themes/dark.css @@ -202,13 +202,14 @@ QScrollBar::add-line { background: transparent; } -QPushButton { +QPushButton, QToolButton { color: rgb(138,180,247); border: 1px solid rgb(42,43,66); padding: 4px 8px; border-radius: 4px; } -QPushButton:hover, QPushButton:pressed, QPushButton:checked:enabled { +QPushButton:hover, QPushButton:pressed, QPushButton:checked:enabled, +QToolButton:hover, QToolButton:pressed, QToolButton:checked:enabled { color: rgb(0,0,0); background: rgba(138,180,247,0.3); } diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index 8057eb2721..5f33298135 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -203,13 +203,14 @@ QScrollBar::add-line { background: transparent; } -QPushButton { +QPushButton, QToolButton { color: rgb(26,115,232); border: 1px solid rgb(218,220,224); padding: 4px 8px; border-radius: 4px; } -QPushButton:hover, QPushButton:pressed, QPushButton:checked:enabled { +QPushButton:hover, QPushButton:pressed, QPushButton:checked:enabled, +QToolButton:hover, QToolButton:pressed, QToolButton:checked:enabled { color: rgb(0,0,0); background: rgba(26,115,232,0.3); } diff --git a/src/sas/system/themes/largefont.css b/src/sas/system/themes/largefont.css index b6f36421ab..06e3fc8983 100644 --- a/src/sas/system/themes/largefont.css +++ b/src/sas/system/themes/largefont.css @@ -203,13 +203,14 @@ QScrollBar::add-line { background: transparent; } -QPushButton { +QPushButton, QToolButton { color: rgb(26,115,232); border: 1px solid rgb(218,220,224); padding: 4px 8px; border-radius: 4px; } -QPushButton:hover, QPushButton:pressed, QPushButton:checked:enabled { +QPushButton:hover, QPushButton:pressed, QPushButton:checked:enabled, +QToolButton:hover, QToolButton:pressed, QToolButton:checked:enabled { color: rgb(0,0,0); background: rgba(26,115,232,0.3); } From de6442bf43a5de8f31bbd5fdde2d8a903ce99742 Mon Sep 17 00:00:00 2001 From: krzywon Date: Tue, 31 Oct 2023 14:33:19 -0400 Subject: [PATCH 60/67] Pass parent to FileConverter to ensure styles are applied --- src/sas/qtgui/Utilities/FileConverter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sas/qtgui/Utilities/FileConverter.py b/src/sas/qtgui/Utilities/FileConverter.py index b0758040e5..4608de2acf 100644 --- a/src/sas/qtgui/Utilities/FileConverter.py +++ b/src/sas/qtgui/Utilities/FileConverter.py @@ -36,7 +36,7 @@ def __init__(self, parent=None): Parent here is the GUI Manager. Required for access to the help location and to the file loader. """ - super(FileConverterWidget, self).__init__() + super(FileConverterWidget, self).__init__(parent._parent if parent else None) self.parent = parent From 0c5166b50e169d7298d2ca6244e1b1fa76d9bcbe Mon Sep 17 00:00:00 2001 From: krzywon Date: Fri, 3 Nov 2023 15:47:42 -0400 Subject: [PATCH 61/67] Dark theme clean up for checkboxes and minimize blue color --- src/sas/system/themes/dark.css | 39 ++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/sas/system/themes/dark.css b/src/sas/system/themes/dark.css index 7935f6a19a..81c98f63f0 100644 --- a/src/sas/system/themes/dark.css +++ b/src/sas/system/themes/dark.css @@ -7,7 +7,7 @@ QWidget { background: rgb(63,64,66); color: rgb(228,231,235); selection-color: rgb(228,231,235); - selection-background-color: rgba(138,180,247,0.5); + selection-background-color: rgba(26,115,178,0.5); } QWidget:disabled { color: rgba(228,231,235,0.4); @@ -26,7 +26,7 @@ QMainWindow::separator { } QMainWindow::separator:hover, QMainWindow::separator:pressed { - background: rgb(138,180,247); + background: rgb(26,115,178); } /* QCheckBox and QRadioButton Properties */ @@ -35,9 +35,17 @@ QRadioButton { border-top: 2px solid transparent; border-bottom: 2px solid transparent; } -QCheckBox:hover, -QRadioButton:hover { - border-bottom: 2px solid; +QCheckBox::indicator:enabled, +QRadioButton::indicator:enabled { + height: 14px; + width: 14px; + border: 2px solid rgb(0,0,0); +} +QCheckBox::indicator:hover, +QRadioButton::indicator:hover { + height: 14px; + width: 14px; + border: 2px solid rgb(26,115,178); } /* QGroupBox Properties */ @@ -203,7 +211,7 @@ QScrollBar::add-line { } QPushButton, QToolButton { - color: rgb(138,180,247); + color: rgb(26,115,178); border: 1px solid rgb(42,43,66); padding: 4px 8px; border-radius: 4px; @@ -211,7 +219,7 @@ QPushButton, QToolButton { QPushButton:hover, QPushButton:pressed, QPushButton:checked:enabled, QToolButton:hover, QToolButton:pressed, QToolButton:checked:enabled { color: rgb(0,0,0); - background: rgba(138,180,247,0.3); + background: rgba(26,115,178,0.3); } /* QDialogButtonBox */ @@ -243,7 +251,7 @@ QComboBox::drop-down:editable:hover { /* Setting background color of selected item when editable is false. */ QComboBox::item:selected { border: none; /* This remove the border of indicator. */ - background: rgba(26,115,278,0.35); + background: rgba(26,115,178,0.35); border-radius: 4px; } @@ -323,7 +331,7 @@ QTabBar::tab:selected:hover:enabled { background: rgba(255,255,255,0.15); } QTabBar::tab:selected:enabled { - color: rgb(138,180,247); + color: rgba(255,255,255,0.6);; background: rgba(255,255,255,0.24); } QTabBar::tab:selected:disabled, @@ -409,7 +417,7 @@ QTableView QTableCornerButton::section { border-top-left-radius: 2px; } QTableView QTableCornerButton::section:pressed { - background: rgba(138,180,247,0.35); + background: rgba(26,115,178,0.35); } QTableView > QHeaderView { background: rgba(63,64,66,0.50); @@ -429,7 +437,7 @@ QLineEdit { border-radius: 4px; } QLineEdit:focus { - border-color: rgb(138,180,247); + border-color: rgb(26,115,178); } /* QFileDialog */ @@ -464,6 +472,15 @@ QAbstractItemView::indicator, QRadioButton::indicator { height: 18px; width: 18px; + background: rgba(245,245,245,0.6); +} +QCheckBox::indicator:checked, +QGroupBox::indicator:checked, +QAbstractItemView::indicator:checked, +QRadioButton::indicator:checked { + height: 14px; + width: 14px; + background: rgb(26,115,178); } /* Styles that are not from taken PyQtDarkTheme */ From b7575d4a36df8b8ada4f67d4e44df31c87d5ca50 Mon Sep 17 00:00:00 2001 From: krzywon Date: Fri, 3 Nov 2023 15:55:19 -0400 Subject: [PATCH 62/67] Tweaks to the default and large font themes --- src/sas/system/themes/dark.css | 2 +- src/sas/system/themes/default.css | 28 ++++++++++++++++++++++------ src/sas/system/themes/largefont.css | 28 ++++++++++++++++++++++------ 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/sas/system/themes/dark.css b/src/sas/system/themes/dark.css index 81c98f63f0..5a026a80e8 100644 --- a/src/sas/system/themes/dark.css +++ b/src/sas/system/themes/dark.css @@ -331,7 +331,7 @@ QTabBar::tab:selected:hover:enabled { background: rgba(255,255,255,0.15); } QTabBar::tab:selected:enabled { - color: rgba(255,255,255,0.6);; + color: rgba(255,255,255,0.6); background: rgba(255,255,255,0.24); } QTabBar::tab:selected:disabled, diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index 5f33298135..09b5cc8d4e 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -35,9 +35,17 @@ QRadioButton { border-top: 2px solid transparent; border-bottom: 2px solid transparent; } -QCheckBox:hover, -QRadioButton:hover { - border-bottom: 2px solid; +QCheckBox::indicator:enabled, +QRadioButton::indicator:enabled { + height: 14px; + width: 14px; + border: 2px solid rgba(0,0,0,0.25); +} +QCheckBox::indicator:hover, +QRadioButton::indicator:hover { + height: 14px; + width: 14px; + border: 2px solid rgb(26,115,178); } /* QGroupBox Properties */ @@ -324,8 +332,8 @@ QTabBar::tab:selected:hover:enabled { background: rgba(0,0,0,0.15); } QTabBar::tab:selected:enabled { - color: rgb(26,115,232); - background: rgba(0,0,0,0.24); + color: rgba(0,0,0,0.6); + background: rgba(0,0,0,0.1); } QTabBar::tab:selected:disabled, QTabBar::tab:only-one:selected:enabled { @@ -465,8 +473,16 @@ QAbstractItemView::indicator, QRadioButton::indicator { height: 18px; width: 18px; + background: rgba(245,245,245,0.6); +} +QCheckBox::indicator:checked, +QGroupBox::indicator:checked, +QAbstractItemView::indicator:checked, +QRadioButton::indicator:checked { + height: 14px; + width: 14px; + background: rgb(26,115,178); } - /* Styles that are not from taken PyQtDarkTheme */ QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} diff --git a/src/sas/system/themes/largefont.css b/src/sas/system/themes/largefont.css index 06e3fc8983..619979b317 100644 --- a/src/sas/system/themes/largefont.css +++ b/src/sas/system/themes/largefont.css @@ -35,9 +35,17 @@ QRadioButton { border-top: 2px solid transparent; border-bottom: 2px solid transparent; } -QCheckBox:hover, -QRadioButton:hover { - border-bottom: 2px solid; +QCheckBox::indicator:enabled, +QRadioButton::indicator:enabled { + height: 14px; + width: 14px; + border: 2px solid rgba(0,0,0,0.25); +} +QCheckBox::indicator:hover, +QRadioButton::indicator:hover { + height: 14px; + width: 14px; + border: 2px solid rgb(26,115,178); } /* QGroupBox Properties */ @@ -324,8 +332,8 @@ QTabBar::tab:selected:hover:enabled { background: rgba(0,0,0,0.15); } QTabBar::tab:selected:enabled { - color: rgb(26,115,232); - background: rgba(0,0,0,0.24); + color: rgba(0,0,0,0.6); + background: rgba(0,0,0,0.1); } QTabBar::tab:selected:disabled, QTabBar::tab:only-one:selected:enabled { @@ -465,8 +473,16 @@ QAbstractItemView::indicator, QRadioButton::indicator { height: 18px; width: 18px; + background: rgba(245,245,245,0.6); +} +QCheckBox::indicator:checked, +QGroupBox::indicator:checked, +QAbstractItemView::indicator:checked, +QRadioButton::indicator:checked { + height: 14px; + width: 14px; + background: rgb(26,115,178); } - /* Styles that are not from taken PyQtDarkTheme */ QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} From 96639f0fe3ba0f5e59045cf0e5c2aabab06fcfc7 Mon Sep 17 00:00:00 2001 From: krzywon Date: Mon, 6 Nov 2023 11:10:50 -0500 Subject: [PATCH 63/67] Allow user to set font size and theme independently --- .../Preferences/DisplayPreferencesWidget.py | 21 +- src/sas/system/config/config.py | 3 +- src/sas/system/style.py | 28 +- src/sas/system/themes/__init__.py | 12 +- src/sas/system/themes/classic.css | 3 - src/sas/system/themes/dark.css | 3 - src/sas/system/themes/default.css | 3 - src/sas/system/themes/largefont.css | 492 ------------------ 8 files changed, 54 insertions(+), 511 deletions(-) delete mode 100644 src/sas/system/themes/largefont.css diff --git a/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py b/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py index 9d41f556e9..b7bf1777e0 100644 --- a/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py +++ b/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py @@ -12,13 +12,17 @@ def __init__(self): 'QT_AUTO_SCREEN_SCALE_FACTOR', 'DISABLE_RESIDUAL_PLOT', 'DISABLE_POLYDISPERSITY_PLOT', - 'THEME'] + 'THEME', + 'FONT_SIZE'] self.restart_params = {'QT_SCALE_FACTOR': 'QT Screen Scale Factor', 'QT_AUTO_SCREEN_SCALE_FACTOR': "Enable Automatic Scaling"} def _addAllWidgets(self): self.theme = self.addComboBox(title="Theme", params=style.get_theme_names(), default=style.theme) self.theme.currentIndexChanged.connect(self._previewTheme) + self.font_size = self.addComboBox(title="Font Size", params=['10.0', '12.0', '14.0'], + default=str(style.font_size)) + self.font_size.currentIndexChanged.connect(self._previewFont) self.qtScaleFactor = self.addFloatInput( title="QT Screen Scale Factor", default_number=config.QT_SCALE_FACTOR) @@ -44,10 +48,19 @@ def _restoreFromConfig(self): def _previewTheme(self): # Store existing theme self._stageChange('THEME', self.theme.currentText()) + self._set_theme() + + def _previewFont(self): + self._stageChange('FONT_SIZE', float(self.font_size.currentText())) + self._set_theme() + + def _set_theme(self): theme = config.THEME - style.css = self.theme.currentText() - # The CSS getter uses the config theme, not the set theme + font = config.FONT_SIZE + # The CSS and font_size getters uses the config values, not the set theme config.THEME = self.theme.currentText() + config.FONT_SIZE = float(self.font_size.currentText()) self.parent.parent.setStyleSheet(style.css) - # Set the config theme back for easy reset + # Set the config theme items back for easy reset config.THEME = theme + config.FONT_SIZE = font diff --git a/src/sas/system/config/config.py b/src/sas/system/config/config.py index 23c8b86cbc..0fe87c23ca 100644 --- a/src/sas/system/config/config.py +++ b/src/sas/system/config/config.py @@ -208,8 +208,9 @@ def __init__(self): # Default fitting optimizer self.FITTING_DEFAULT_OPTIMIZER = 'lm' - # Default style sheet name + # Style properties self.THEME = 'Default' + self.FONT_SIZE = 10.0 # What's New variables self.LAST_WHATS_NEW_HIDDEN_VERSION = "5.0.0" diff --git a/src/sas/system/style.py b/src/sas/system/style.py index 0b1e2d200f..e277c47e6b 100644 --- a/src/sas/system/style.py +++ b/src/sas/system/style.py @@ -1,7 +1,7 @@ from typing import List from sas.system import config -from sas.system.themes import load_theme, find_available_themes +from sas.system.themes import load_theme, find_available_themes, format_font_size class StyleSheet: @@ -14,13 +14,16 @@ class StyleSheet: def __init__(self): self._available_themes = find_available_themes() self.theme = config.THEME - self._css = load_theme(self.theme) + self._font_size = config.FONT_SIZE + self._css = "" + self._create_full_theme() @property def css(self) -> str: """A property that exposes the css string to the public.""" self.theme = config.THEME - self._css = load_theme(self.theme) + self.font_size = config.FONT_SIZE + self._create_full_theme() return self._css @css.setter @@ -28,7 +31,18 @@ def css(self, theme: str): """A way to set the theme from outside the class. This attempts to load the theme and will throw an exception for undefined themes.""" self.theme = theme - self._css = load_theme(theme) + self._create_full_theme() + + @property + def font_size(self) -> float: + """A property that exposes the font size to the public.""" + self._font_size = config.FONT_SIZE + return self._font_size + + @font_size.setter + def font_size(self, font_size: float): + """Set the font size and create the theme.""" + self._font_size = font_size def update_theme_list(self): """A helper method to find the latest list of themes. @@ -39,5 +53,11 @@ def get_theme_names(self) -> List[str]: """Return a list of theme names for use by an external system.""" return list(self._available_themes.keys()) + def _create_full_theme(self): + """Private method that combines settings so users can separately set fonts and color palettes.""" + css = load_theme(self.theme) + font_str = format_font_size(self.font_size) + self._css = f"{font_str}{css}" + style_sheet = StyleSheet() diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py index 939833f20d..a6e6207637 100644 --- a/src/sas/system/themes/__init__.py +++ b/src/sas/system/themes/__init__.py @@ -13,9 +13,11 @@ 'Default': Path(os.path.join(os.path.dirname(__file__), 'default.css')), 'Dark': Path(os.path.join(os.path.dirname(__file__), 'dark.css')), 'Classic': Path(os.path.join(os.path.dirname(__file__), 'classic.css')), - 'Large Font': Path(os.path.join(os.path.dirname(__file__), 'largefont.css')), } +# A template string for setting the font size +FONT = "* {{font-size: {}pt; font-family: Helvetica, Arial, Verdana, sans-serif}}\n" + def load_theme(theme: str = None) -> str: """Using a theme name, load the associated CSS file. User themes will be based off the Classic theme. @@ -50,3 +52,11 @@ def find_available_themes() -> Dict: name = f'User:{file}' themes[name] = Path(os.path.join(user_path, file)) return themes + + +def format_font_size(font_size: float) -> str: + """Formats the FONT string to include a specific size. + + :param font_size: The font size, in pt units, to use. + :return: FONT.format(font_size)""" + return FONT.format(font_size) diff --git a/src/sas/system/themes/classic.css b/src/sas/system/themes/classic.css index 725a80a5eb..9fde0bc3b6 100644 --- a/src/sas/system/themes/classic.css +++ b/src/sas/system/themes/classic.css @@ -1,6 +1,3 @@ -/* Global Properties */ -* {font-size: 10pt; font-family: Helvetica, Arial, Verdana, sans-serif} - /* Qt Elements */ QLineEdit {background-color: white; color: black;} QLineEdit:focus {background-color: #98dbcc; color: #333333} diff --git a/src/sas/system/themes/dark.css b/src/sas/system/themes/dark.css index 5a026a80e8..ebd5be800b 100644 --- a/src/sas/system/themes/dark.css +++ b/src/sas/system/themes/dark.css @@ -1,6 +1,3 @@ -/* Global Properties */ -* {font-size: 10pt; font-family: Helvetica, Arial, Verdana, sans-serif} - /* QWidget Properties */ QWidget { diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index 09b5cc8d4e..c1e7f963fe 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -1,6 +1,3 @@ -/* Global Properties */ -* {font-size: 10pt; font-family: Helvetica, Arial, Verdana, sans-serif} - /* QWidget Properties */ QWidget { diff --git a/src/sas/system/themes/largefont.css b/src/sas/system/themes/largefont.css deleted file mode 100644 index 619979b317..0000000000 --- a/src/sas/system/themes/largefont.css +++ /dev/null @@ -1,492 +0,0 @@ -/* Global Properties */ -* {font-size: 12pt; font-family: Helvetica, Arial, Verdana, sans-serif} - -/* QWidget Properties */ - -QWidget { - background: rgb(248,249,250); - color: rgb(77,81,87); - selection-color: rgb(77,81,87); - selection-background-color: rgba(26,115,232,0.5); -} -QWidget:disabled { - color: rgba(77,81,87,0.4); - selection-background-color: rgba(77,81,87,0.25); - selection-color: rgba(77,81,87,0.4); -} -QWidget:focus { - outline: none; -} - -/* QMainWindow Properties */ -QMainWindow::separator { - width: 4px; - height: 4px; - background: rgb(218,220,224); -} -QMainWindow::separator:hover, -QMainWindow::separator:pressed { - background: rgb(26,115,232); -} - -/* QCheckBox and QRadioButton Properties */ -QCheckBox, -QRadioButton { - border-top: 2px solid transparent; - border-bottom: 2px solid transparent; -} -QCheckBox::indicator:enabled, -QRadioButton::indicator:enabled { - height: 14px; - width: 14px; - border: 2px solid rgba(0,0,0,0.25); -} -QCheckBox::indicator:hover, -QRadioButton::indicator:hover { - height: 14px; - width: 14px; - border: 2px solid rgb(26,115,178); -} - -/* QGroupBox Properties */ -QGroupBox { - font-weight: bold; - margin-top: 8px; - padding: 2px 1px 1px 1px; - border-radius: 4px; - border: 1px solid rgb(218,220,224); -} -QGroupBox::title { - subcontrol-origin: margin; - subcontrol-position: top left; - left: 7px; - margin: 0 2px 0 3px; -} -QGroupBox:flat { - border-color: transparent; -} - -/* QToolTip Properties */ -QToolTip { - font-size: 80%; - background: rgba(248,249,250,0.2); - color: rgb(77,81,87); -} - -/* QMenuBar Properties */ -QMenuBar { - padding: 2px; - border-bottom: 1px solid rgb(218,220,224); - background: rgb(248,249,250); -} -QMenuBar::item { - background: transparent; - padding: 4px; -} -QMenuBar::item:selected { - padding: 4px; - border-radius: 4px; - background: rgba(0,0,0,0.20); -} -QMenuBar::item:pressed { - padding: 4px; - margin-bottom: 0; - padding-bottom: 0; -} - -/* QToolBar */ -QToolBar { - padding: 1px; - font-weight: bold; - spacing: 2px; - margin: 1px; - background: rgb(235,235,235); - /* QToolBar must override `border-style` to set the style. */ - border-style: none; -} -QToolBar::separator { - background: rgb(218,220,224); -} -QToolBar::separator:horizontal { - width: 2px; - margin: 0 6px; -} -QToolBar::separator:vertical { - height: 2px; - margin: 6px 0; -} -QToolBar > QToolButton { - background: transparent; - padding: 3px; - border-radius: 4px; -} -QToolBar > QToolButton:hover, -QToolBar > QToolButton::menu-button:hover { - background: rgba(0,0,0,0.15); -} -QToolBar > QToolButton::menu-button { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; -} -QToolBar > QToolButton:pressed, -QToolBar > QToolButton::menu-button:pressed:enabled, -QToolBar > QToolButton:checked:enabled { - background: rgba(0,0,0,0.24); -} -QToolBar > QWidget { - background: transparent; -} - -/* Qmenu Properties */ -QMenu { - background: rgba(248,249,250,0.70); - padding: 8px 0; - border-radius: 4px; -} -QMenu::separator { - margin: 4px 0; - height: 1px; - background: rgb(218,220,224); -} -QMenu::item { - background: transparent; - padding: 4px 19px; -} -QMenu::item:selected { - background: rgba(0,0,0,0.12); -} -QMenu::icon { - padding-left: 10px; - width: 14px; - height: 14px; -} - -/* QScrollBar */ -QScrollBar { - background: rgba(0,0,0,0.40); - border-radius: 4px; -} -QScrollBar:horizontal { - height: 14px; -} -QScrollBar:vertical { -} -QScrollBar::handle { - background: rgba(0,0,0,0.40); - border-radius: 3px; -} -QScrollBar::handle:hover { - background: rgba(0,0,0,0.50); -} -QScrollBar::handle:pressed { - background: rgba(0,0,0,0.24); -} -QScrollBar::handle:disabled { - background: rgba(0,0,0,0.15); -} -QScrollBar::handle:horizontal { - min-width: 8px; - margin: 4px 14px; -} -QScrollBar::handle:horizontal:hover { - margin: 2px 14px; -} -QScrollBar::handle:vertical { - min-height: 8px; - margin: 14px 4px; -} -QScrollBar::handle:vertical:hover { - margin: 14px 2px; -} -/* -Hide QScrollBar background. -The `sub-page` and `add-page` are not colored by default on most OS, but are colored on Windows. -*/ -QScrollBar::sub-page, -QScrollBar::add-page { - background: transparent; -} -QScrollBar::sub-line, -QScrollBar::add-line { - background: transparent; -} - -QPushButton, QToolButton { - color: rgb(26,115,232); - border: 1px solid rgb(218,220,224); - padding: 4px 8px; - border-radius: 4px; -} -QPushButton:hover, QPushButton:pressed, QPushButton:checked:enabled, -QToolButton:hover, QToolButton:pressed, QToolButton:checked:enabled { - color: rgb(0,0,0); - background: rgba(26,115,232,0.3); -} - -/* QDialogButtonBox */ -QDialogButtonBox { - dialogbuttonbox-buttons-have-icons: 0; -} -QDialogButtonBox QPushButton { - min-width: 65px; -} - -/* QComboBox */ -QComboBox { - min-height: 1.5em; - padding: 0 8px 0 4px; - background: rgb(248,249,250); - border: 1px solid rgb(218,220,224); - border-radius: 4px; -} -QComboBox:hover, QComboBox::item:hover, QComboBox:focus, QComboBox:open { - border-color: rgb(26,115,232); -} -QComboBox::drop-down { - margin: 2px 2px 2px -6px; - border-radius: 4px; /* This remove default style. */ -} -QComboBox::drop-down:editable:hover { - background: rgba(0,0,0,0.13); -} -/* Setting background color of selected item when editable is false. */ -QComboBox::item:selected { - border: none; /* This remove the border of indicator. */ - background: rgba(26,115,278,0.35); - border-radius: 4px; -} - -/* QAbstractItemView in QComboBox is NoFrame. Override default settings and show border. */ -QComboBox QListView { - margin: 0; - padding: 4px; - background: rgba(248,249,250,0.25); - border-radius: 4px; -} -QComboBox QListView::item { - border-radius: 4px; -} - -/* QListView QTreeView */ -QListView { - padding: 1px -} -QListView, -QTreeView { - background: rgb(248,249,250); -} -QListView::item:hover, -QTreeView::item:hover, -QTreeView::branch:hover { - background: rgb(218,220,224); -} -QTreeView::branch:open:has-children:!has-siblings, -QTreeView::branch:open:has-children:has-siblings { - border-image: unset; - background: rgba(77,81,87,0.05); -} -QTreeView::branch:open:has-children:!has-siblings:disabled, -QTreeView::branch:open:has-children:has-siblings:disabled { - background: rgba(77,81,87,0.05); -} -QTreeView > QHeaderView { - background: rgb(248,249,250); -} -QTreeView > QHeaderView::section { - background: rgb(218,220,224); -} - -/* -Following arrow settings are for QColumnView. -QColumnView::left-arrow and QColumnView::right-arrow are not working. -*/ -QListView::left-arrow { - margin: -2px; -} -QListView::right-arrow { - margin: -2px; -} - -/* QTabWidget QTabBar */ -QTabWidget::pane { - border: 1px solid rgb(218,220,224); - border-radius: 4px; -} -QTabBar { - /* - Not filling background color when drawBase property is true. So need to set drawBase to false. - Default QTabBar is no need following declaration, but QMdiArea is need. - */ - qproperty-drawBase: 0; -} -QTabBar::close-button:hover { - background: rgba(0,0,0,0.20); - border-radius: 4px; -} -QTabBar::tab { - padding: 3px; - border-style: solid; -} -QTabBar::tab:hover, -QTabBar::tab:selected:hover:enabled { - background: rgba(0,0,0,0.15); -} -QTabBar::tab:selected:enabled { - color: rgba(0,0,0,0.6); - background: rgba(0,0,0,0.1); -} -QTabBar::tab:selected:disabled, -QTabBar::tab:only-one:selected:enabled { - border-color: rgb(218,220,224); -} -QTabBar::tab:top { - border-bottom-width: 2px; - margin: 3px 6px 0 0; - border-top-left-radius: 2px; - border-top-right-radius: 2px; -} -QTabBar::tab:bottom { - border-top-width: 2px; - margin: 0 6px 3px 0; - border-bottom-left-radius: 2px; - border-bottom-right-radius: 2px; -} -QTabBar::tab:left { - border-right-width: 2px; - margin: 0 0 6px 3px; - border-top-left-radius: 2px; - border-bottom-left-radius: 2px; -} -QTabBar::tab:right { - border-left-width: 2px; - margin-bottom: 6px; - margin: 0 3px 6px 0; - border-top-right-radius: 2px; - border-bottom-right-radius: 2px; -} -QTabBar::tab:top:first, -QTabBar::tab:top:only-one, -QTabBar::tab:bottom:first, -QTabBar::tab:bottom:only-one { - margin-left: 2px; -} -QTabBar::tab:top:last, -QTabBar::tab:top:only-one, -QTabBar::tab:bottom:last, -QTabBar::tab:bottom:only-one { - margin-right: 2px; -} -QTabBar::tab:left:first, -QTabBar::tab:left:only-one, -QTabBar::tab:right:first, -QTabBar::tab:right:only-one { - margin-top: 2px; -} -QTabBar::tab:left:last, -QTabBar::tab:left:only-one, -QTabBar::tab:right:last, -QTabBar::tab:right:only-one { - margin-bottom: 2px; -} - -/* QColumnView */ -QColumnView { - background: rgb(248,249,250); -} -QColumnViewGrip { - margin: -4px; - background: rgb(248,249,250); -} - -/* QTableView */ -QTableView { - gridline-color: rgb(218,220,224); - background: rgba(248,249,250,0.5); -} -QTableView:!active { - background: rgba(0,0,0,0.12); -} -QTableView::item:alternate { - background: rgba(0,0,0,0.12); -} -QTableView::item:selected { - background: rgba(248,249,250,0.5); -} -QTableView QTableCornerButton::section { - margin: 0 1px 1px 0; - background: rgb(218,220,224); - border-top-left-radius: 2px; -} -QTableView QTableCornerButton::section:pressed { - background: rgba(26,115,232,0.35); -} -QTableView > QHeaderView { - background: rgba(248,249,250,0.50); - border-radius: 3px; -} -QTableView > QHeaderView::section { - background: rgb(218,220,224); -} - -/* QLineEdit */ -QLineEdit { - padding: 3px 4px; - /* Adjust the min-height of QLineEdit to the height of the characters. */ - min-height: 1em; - border: 1px solid rgb(218,220,224); - background: rgb(248,249,250); - border-radius: 4px; -} -QLineEdit:focus { - border-color: rgb(26,115,232); -} - -/* QFileDialog */ -QFileDialog QFrame { - border: none; -} - -/* Check */ -QComboBox::indicator, -QMenu::indicator { - width: 18px; - height: 18px; -} -QMenu::indicator { - background: rgba(0,0,0,0.19); - margin-left: 3px; - border-radius: 4px; -} - -/* Check indicator */ -QCheckBox, -QRadioButton { - spacing: 8px; -} -QGroupBox::title, -QAbstractItemView::item { - spacing: 6px; -} -QCheckBox::indicator, -QGroupBox::indicator, -QAbstractItemView::indicator, -QRadioButton::indicator { - height: 18px; - width: 18px; - background: rgba(245,245,245,0.6); -} -QCheckBox::indicator:checked, -QGroupBox::indicator:checked, -QAbstractItemView::indicator:checked, -QRadioButton::indicator:checked { - height: 14px; - width: 14px; - background: rgb(26,115,178); -} -/* Styles that are not from taken PyQtDarkTheme */ -QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} -QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} - -QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow} -QCodeEditor {font-family: 'monospace, monospace'} -QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} From 48260c45c5077274552cc5786ecabc633aa6a2f4 Mon Sep 17 00:00:00 2001 From: krzywon Date: Wed, 8 Nov 2023 10:55:36 -0500 Subject: [PATCH 64/67] Updates to QTreeView taken out of the fitting widget --- .../Perspectives/Fitting/FittingWidget.py | 45 +++++-------------- src/sas/system/themes/classic.css | 7 ++- src/sas/system/themes/dark.css | 7 ++- src/sas/system/themes/default.css | 21 +++++++-- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py b/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py index d8a7291ba9..5d14f65850 100644 --- a/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py +++ b/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py @@ -350,12 +350,8 @@ def initializeWidgets(self): layout.addWidget(self.order_widget) self.tabOrder.setLayout(layout) - # Define bold font for use in various controls - self.boldFont = QtGui.QFont() - self.boldFont.setBold(True) - # Set data label - self.label.setFont(self.boldFont) + GuiUtils.updateProperty(self.label, 'bold', 'true') self.label.setText("No data loaded") self.lblFilename.setText("") @@ -871,23 +867,19 @@ def polyNameToParam(self, param_name): param_name += '.width' return param_name - def modifyViewOnRow(self, row, font=None, brush=None, model_key="standard"): + def modifyViewOnRow(self, row, font=None, model_key="standard"): """ Change how the given row of the main model is shown """ model = self.model_dict[model_key] fields_enabled = False - if font is None: - font = QtGui.QFont() - fields_enabled = True - if brush is None: - brush = QtGui.QBrush() - fields_enabled = True model.blockSignals(True) # Modify font and foreground of affected rows for column in range(0, model.columnCount()): - model.item(row, column).setForeground(brush) - model.item(row, column).setFont(font) + if font: + GuiUtils.updateProperty(model.item(row, column), font, 'true') + else: + GuiUtils.updateProperty(model.item(row, column), 'base', 'true') # Allow the user to interact or not with the fields depending on # whether the parameter is constrained or not model.item(row, column).setEditable(fields_enabled) @@ -956,10 +948,7 @@ def addConstraintToRow(self, constraint=None, row=0, model_key="standard"): # Set min/max to the value constrained self.constraintAddedSignal.emit([row], model_key) # Show visual hints for the constraint - font = QtGui.QFont() - font.setItalic(True) - brush = QtGui.QBrush(QtGui.QColor('blue')) - self.modifyViewOnRow(row, font=font, brush=brush, model_key=model_key) + self.modifyViewOnRow(row, font="constrained", model_key=model_key) # update the main parameter list so the constrained parameter gets # updated when fitting self.checkboxSelected(model.item(row, 0), model_key=model_key) @@ -998,10 +987,7 @@ def addSimpleConstraint(self): model.item(row, max_col).setText(str(max_v)) self.constraintAddedSignal.emit([row], model_key) # Show visual hints for the constraint - font = QtGui.QFont() - font.setItalic(True) - brush = QtGui.QBrush(QtGui.QColor('blue')) - self.modifyViewOnRow(row, font=font, brush=brush, model_key=model_key) + self.modifyViewOnRow(row, font="constrained", model_key=model_key) self.communicate.statusBarUpdateSignal.emit('Constraint added') def editConstraint(self): @@ -2628,7 +2614,6 @@ def SASModelToQModel(self, model_name, structure_factor=None): # (Re)-create headers FittingUtilities.addHeadersToModel(self._model_model) - self.lstParams.header().setFont(self.boldFont) def fromModelToQModel(self, model_name): """ @@ -2912,19 +2897,11 @@ def setParamEditableByRow(self, row, editable=True): item_value.setEditable(editable) if editable: - # reset font - item_name.setFont(QtGui.QFont()) - # reset colour - item_name.setForeground(QtGui.QBrush()) + GuiUtils.updateProperty(item_name, 'base', 'true') # make checkable item_name.setCheckable(True) else: - # change font - font = QtGui.QFont() - font.setItalic(True) - item_name.setFont(font) - # change colour - item_name.setForeground(QtGui.QBrush(QtGui.QColor(50, 50, 50))) + GuiUtils.updateProperty(item_name, 'disabled', 'true') # make not checkable (and uncheck) item_name.setCheckState(QtCore.Qt.Unchecked) item_name.setCheckable(False) @@ -4304,7 +4281,7 @@ def gatherParams(row): cons = (value, param, value_ex, validate, func) - param_list.append([param_name, param_checked, param_value,param_error, param_min, param_max, cons]) + param_list.append([param_checked, param_name, param_value, param_error, param_min, param_max, cons]) def gatherPolyParams(row): """ diff --git a/src/sas/system/themes/classic.css b/src/sas/system/themes/classic.css index 9fde0bc3b6..a033e08976 100644 --- a/src/sas/system/themes/classic.css +++ b/src/sas/system/themes/classic.css @@ -24,4 +24,9 @@ QTreeView::item {border: 1px; padding: 2px 1px;} QTreeView::item:hover {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1); border: 1px solid #bfcde4;} QTreeView::item:selected {border: 1px solid #567dbc;} QTreeView::item:selected:active{background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);} -QTreeView::item:selected:!active {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);} \ No newline at end of file +QTreeView::item:selected:!active {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);} +QLabel[bold=true] {font-weight: bold;} +QTreeView::item[base=true] {color: rgb(77,81,87); font-style: normal; font-weight: normal;} +QTreeView::item[disabled=true] {font-style: italic;} +QTreeView::item[constrained=true] {font-style: italic; color: blue;} +QHeaderView {font-weight: bold} \ No newline at end of file diff --git a/src/sas/system/themes/dark.css b/src/sas/system/themes/dark.css index ebd5be800b..4a871b4ad7 100644 --- a/src/sas/system/themes/dark.css +++ b/src/sas/system/themes/dark.css @@ -480,10 +480,13 @@ QRadioButton::indicator:checked { background: rgb(26,115,178); } -/* Styles that are not from taken PyQtDarkTheme */ QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} - QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow} QCodeEditor {font-family: 'monospace, monospace'} QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} +QLabel[bold=true] {font-weight: bold;} +QTreeView::item[base=true] {color: rgb(77,81,87); font-style: normal; font-weight: normal;} +QTreeView::item[disabled=true] {font-style: italic;} +QTreeView::item[constrained=true] {font-style: italic; color: blue;} +QHeaderView {font-weight: bold} \ No newline at end of file diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index c1e7f963fe..2630bc7a62 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -292,6 +292,12 @@ QTreeView > QHeaderView { QTreeView > QHeaderView::section { background: rgb(218,220,224); } +QTreeView::item { + height: 1.5em; + width: 100%; + margin: 4px; + padding: 2px; +} /* Following arrow settings are for QColumnView. @@ -403,14 +409,19 @@ QTableView { QTableView:!active { background: rgba(0,0,0,0.12); } +QTableView::item { + height: 125%; +} QTableView::item:alternate { + height: 200%; + margin: 4px; background: rgba(0,0,0,0.12); } QTableView::item:selected { background: rgba(248,249,250,0.5); } QTableView QTableCornerButton::section { - margin: 0 1px 1px 0; + margin: 4px; background: rgb(218,220,224); border-top-left-radius: 2px; } @@ -480,10 +491,14 @@ QRadioButton::indicator:checked { width: 14px; background: rgb(26,115,178); } -/* Styles that are not from taken PyQtDarkTheme */ + QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} - QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow} QCodeEditor {font-family: 'monospace, monospace'} QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} +QLabel[bold=true] {font-weight: bold;} +QTreeView::item[base=true] {color: rgb(77,81,87); font-style: normal; font-weight: normal;} +QTreeView::item[disabled=true] {font-style: italic;} +QTreeView::item[constrained=true] {font-style: italic; color: blue;} +QHeaderView {font-weight: bold} \ No newline at end of file From efc394576fd764d50dfae5442fc484fd90cda661 Mon Sep 17 00:00:00 2001 From: krzywon Date: Wed, 8 Nov 2023 11:39:10 -0500 Subject: [PATCH 65/67] Clean up tree view and checked heck box look --- src/sas/system/themes/dark.css | 9 +++++++++ src/sas/system/themes/default.css | 14 ++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/sas/system/themes/dark.css b/src/sas/system/themes/dark.css index 4a871b4ad7..ea5aed416e 100644 --- a/src/sas/system/themes/dark.css +++ b/src/sas/system/themes/dark.css @@ -44,6 +44,14 @@ QRadioButton::indicator:hover { width: 14px; border: 2px solid rgb(26,115,178); } +QCheckBox::indicator:checked { + color: rgba(255,255,255,0.6); + background: rgba(255,255,255,0.24); +} +QCheckBox:checked { + color: rgba(255,255,255,0.6); + background: rgba(255,255,255,0.24); +} /* QGroupBox Properties */ QGroupBox { @@ -146,6 +154,7 @@ QMenu::separator { background: rgb(42,43,66); } QMenu::item { + background: transparent; padding: 4px 19px; } QMenu::item:selected { diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index 2630bc7a62..202cb98321 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -44,6 +44,14 @@ QRadioButton::indicator:hover { width: 14px; border: 2px solid rgb(26,115,178); } +QCheckBox::indicator:checked { + color: rgba(0,0,0,0.6); + background: rgba(0,0,0,0.1); +} +QCheckBox:checked { + color: rgba(0,0,0,0.6); + background: rgba(0,0,0,0.1); +} /* QGroupBox Properties */ QGroupBox { @@ -292,12 +300,6 @@ QTreeView > QHeaderView { QTreeView > QHeaderView::section { background: rgb(218,220,224); } -QTreeView::item { - height: 1.5em; - width: 100%; - margin: 4px; - padding: 2px; -} /* Following arrow settings are for QColumnView. From 86b76859ec790b45be3cc6789b5b5b263967303e Mon Sep 17 00:00:00 2001 From: krzywon Date: Wed, 8 Nov 2023 12:03:42 -0500 Subject: [PATCH 66/67] Separate out common theme elements from light and dark only leaving color palettes in style sheets --- src/sas/system/themes/__init__.py | 145 +++++++++++++++- src/sas/system/themes/dark.css | 267 +---------------------------- src/sas/system/themes/default.css | 268 +----------------------------- 3 files changed, 145 insertions(+), 535 deletions(-) diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py index a6e6207637..b6be112b73 100644 --- a/src/sas/system/themes/__init__.py +++ b/src/sas/system/themes/__init__.py @@ -10,10 +10,11 @@ # The base dictionary mapping theme names to their location on disk. OPTIONS = { - 'Default': Path(os.path.join(os.path.dirname(__file__), 'default.css')), + 'Light': Path(os.path.join(os.path.dirname(__file__), 'default.css')), 'Dark': Path(os.path.join(os.path.dirname(__file__), 'dark.css')), 'Classic': Path(os.path.join(os.path.dirname(__file__), 'classic.css')), } +USES_STYLE_BASE = ['Light', 'Dark'] # A template string for setting the font size FONT = "* {{font-size: {}pt; font-family: Helvetica, Arial, Verdana, sans-serif}}\n" @@ -25,10 +26,10 @@ def load_theme(theme: str = None) -> str: :return: The CSS string loaded from file """ themes = find_available_themes() - css = "" if not theme or theme not in find_available_themes(): logger.warning(f"Invalid theme name provided: {theme}") - theme = 'Default' + theme = 'Light' + css = "" if theme not in USES_STYLE_BASE else STYLE_BASE # User themes should use the classic theme as a basis and build on it from there if theme.startswith('User:'): with open(themes.get('Classic').absolute()) as fd: @@ -60,3 +61,141 @@ def format_font_size(font_size: float) -> str: :param font_size: The font size, in pt units, to use. :return: FONT.format(font_size)""" return FONT.format(font_size) + + +STYLE_BASE = """ +/* QWidget Properties */ +QWidget:focus {outline: none;} + +/* QMainWindow Properties */ +QMainWindow::separator {width: 4px; height: 4px;} + +/* QCheckBox and QRadioButton Properties */ +QCheckBox, QRadioButton {border-top: 2px solid transparent; border-bottom: 2px solid transparent;} +QCheckBox::indicator:enabled, QRadioButton::indicator:enabled {height: 14px; width: 14px;} +QCheckBox::indicator:hover, QRadioButton::indicator:hover {height: 14px; width: 14px;} + +/* QGroupBox Properties */ +QGroupBox {font-weight: bold; margin-top: 8px; padding: 2px 1px 1px 1px; border-radius: 4px;} +QGroupBox::title {subcontrol-origin: margin; subcontrol-position: top left; left: 7px; margin: 0 2px 0 3px;} +QGroupBox:flat {border-color: transparent;} + +/* QToolTip Properties */ +QToolTip {font-size: 80%;} + +/* QMenuBar Properties */ +QMenuBar {padding: 2px;} +QMenuBar::item {background: transparent; padding: 4px;} +QMenuBar::item:selected {padding: 4px; border-radius: 4px;} +QMenuBar::item:pressed {padding: 4px; margin-bottom: 0; padding-bottom: 0;} + +/* QToolBar */ +/* QToolBar must override `border-style` to set the style. */ +QToolBar { padding: 1px; font-weight: bold; spacing: 2px; margin: 1px; border-style: none;} +QToolBar::separator:horizontal {width: 2px; margin: 0 6px;} +QToolBar::separator:vertical {height: 2px; margin: 6px 0;} +QToolBar > QToolButton {background: transparent; padding: 3px; border-radius: 4px;} +QToolBar > QToolButton::menu-button {border-top-right-radius: 4px; border-bottom-right-radius: 4px;} +QToolBar > QWidget {background: transparent;} + +/* Qmenu Properties */ +QMenu {padding: 8px 0; border-radius: 4px;} +QMenu::separator {margin: 4px 0; height: 1px;} +QMenu::item {background: transparent; padding: 4px 19px;} +QMenu::icon {padding-left: 10px; width: 14px; height: 14px;} + +/* QScrollBar */ +QScrollBar {border-radius: 4px;} +QScrollBar:horizontal {height: 14px;} +QScrollBar::handle {border-radius: 3px;} +QScrollBar::handle:horizontal {min-width: 8px; margin: 4px 14px;} +QScrollBar::handle:horizontal:hover {margin: 2px 14px;} +QScrollBar::handle:vertical {min-height: 8px; margin: 14px 4px;} +QScrollBar::handle:vertical:hover {margin: 14px 2px;} +/* +Hide QScrollBar background. +The `sub-page` and `add-page` are not colored by default on most OS, but are colored on Windows. +*/ +QScrollBar::sub-page, QScrollBar::add-page {background: transparent;} +QScrollBar::sub-line, QScrollBar::add-line {background: transparent;} +QPushButton, QToolButton {padding: 4px 8px; border-radius: 4px;} + +/* QDialogButtonBox */ +QDialogButtonBox {dialogbuttonbox-buttons-have-icons: 0;} +QDialogButtonBox QPushButton {min-width: 65px;} + +/* QComboBox */ +QComboBox {min-height: 1.5em; padding: 0 8px 0 4px; border-radius: 4px;} +QComboBox::drop-down {margin: 2px 2px 2px -6px; border-radius: 4px; /* This remove default style. */} +/* Setting background color of selected item when editable is false. */ +QComboBox::item:selected {border: none; /* This remove the border of indicator. */ border-radius: 4px;} + +/* QAbstractItemView in QComboBox is NoFrame. Override default settings and show border. */ +QComboBox QListView {margin: 0; padding: 4px; border-radius: 4px;} +QComboBox QListView::item {border-radius: 4px;} + +/* QListView QTreeView */ +QListView {padding: 1px} +QTreeView::branch:open:has-children:!has-siblings, QTreeView::branch:open:has-children:has-siblings {border-image: unset;} + +/* +Following arrow settings are for QColumnView. +QColumnView::left-arrow and QColumnView::right-arrow are not working. +*/ +QListView::left-arrow {margin: -2px;} +QListView::right-arrow {margin: -2px;} + +/* QTabWidget QTabBar */ +QTabWidget::pane {border-radius: 4px;} +QTabBar {qproperty-drawBase: 0;} +QTabBar::close-button:hover {border-radius: 4px;} +QTabBar::tab {padding: 3px; border-style: solid;} +QTabBar::tab:top { + border-bottom-width: 2px; + margin: 3px 6px 0 0; + border-top-left-radius: 2px; + border-top-right-radius: 2px; +} +QTabBar::tab:bottom {border-top-width: 2px; margin: 0 6px 3px 0; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px;} +QTabBar::tab:left {border-right-width: 2px; margin: 0 0 6px 3px; border-top-left-radius: 2px; border-bottom-left-radius: 2px;} +QTabBar::tab:right {border-left-width: 2px; margin-bottom: 6px; margin: 0 3px 6px 0; border-top-right-radius: 2px; border-bottom-right-radius: 2px;} +QTabBar::tab:top:first, QTabBar::tab:top:only-one, QTabBar::tab:bottom:first, QTabBar::tab:bottom:only-one {margin-left: 2px;} +QTabBar::tab:top:last, QTabBar::tab:top:only-one, QTabBar::tab:bottom:last, QTabBar::tab:bottom:only-one {margin-right: 2px;} +QTabBar::tab:left:first, QTabBar::tab:left:only-one, QTabBar::tab:right:first, QTabBar::tab:right:only-one {margin-top: 2px;} +QTabBar::tab:left:last, QTabBar::tab:left:only-one, QTabBar::tab:right:last, QTabBar::tab:right:only-one {margin-bottom: 2px;} + +/* QColumnView */ +QColumnViewGrip {margin: -4px;} + +/* QTableView */ +QTableView QTableCornerButton::section {margin: 0 1px 1px 0; border-top-left-radius: 2px;} +QTableView > QHeaderView {border-radius: 3px;} + +/* QLineEdit */ +/* Adjust the min-height of QLineEdit to the height of the characters. */ +QLineEdit {padding: 3px 4px; min-height: 1em; border-radius: 4px;} + +/* QFileDialog */ +QFileDialog QFrame {border: none;} + +/* Check */ +QComboBox::indicator, +QMenu::indicator {width: 18px; height: 18px;} +QMenu::indicator {margin-left: 3px; border-radius: 4px;} + +/* Check indicator */ +QCheckBox, QRadioButton {spacing: 8px;} +QGroupBox::title, QAbstractItemView::item {spacing: 6px;} +QCheckBox::indicator, QGroupBox::indicator, QAbstractItemView::indicator, QRadioButton::indicator {height: 18px; width: 18px;} +QCheckBox::indicator:checked, QGroupBox::indicator:checked, QAbstractItemView::indicator:checked, QRadioButton::indicator:checked {height: 14px; width: 14px;} + +QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} +QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} +QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow} +QCodeEditor {font-family: 'monospace, monospace'} +QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} +QLabel[bold=true] {font-weight: bold;} +QTreeView::item[base=true] {color: rgb(77,81,87); font-style: normal; font-weight: normal;} +QTreeView::item[disabled=true] {font-style: italic;} +QTreeView::item[constrained=true] {font-style: italic; color: blue;} +QHeaderView {font-weight: bold}""" \ No newline at end of file diff --git a/src/sas/system/themes/dark.css b/src/sas/system/themes/dark.css index ea5aed416e..d372c1bd1d 100644 --- a/src/sas/system/themes/dark.css +++ b/src/sas/system/themes/dark.css @@ -11,14 +11,9 @@ QWidget:disabled { selection-background-color: rgba(228,231,235,0.25); selection-color: rgba(228,231,235,0.4); } -QWidget:focus { - outline: none; -} /* QMainWindow Properties */ QMainWindow::separator { - width: 4px; - height: 4px; background: rgb(42,43,66); } QMainWindow::separator:hover, @@ -27,21 +22,12 @@ QMainWindow::separator:pressed { } /* QCheckBox and QRadioButton Properties */ -QCheckBox, -QRadioButton { - border-top: 2px solid transparent; - border-bottom: 2px solid transparent; -} QCheckBox::indicator:enabled, QRadioButton::indicator:enabled { - height: 14px; - width: 14px; border: 2px solid rgb(0,0,0); } QCheckBox::indicator:hover, QRadioButton::indicator:hover { - height: 14px; - width: 14px; border: 2px solid rgb(26,115,178); } QCheckBox::indicator:checked { @@ -55,130 +41,57 @@ QCheckBox:checked { /* QGroupBox Properties */ QGroupBox { - font-weight: bold; - margin-top: 8px; - padding: 2px 1px 1px 1px; - border-radius: 4px; border: 1px solid rgb(42,43,66); } -QGroupBox::title { - subcontrol-origin: margin; - subcontrol-position: top left; - left: 7px; - margin: 0 2px 0 3px; -} -QGroupBox:flat { - border-color: transparent; -} - /* QToolTip Properties */ QToolTip { - font-size: 80%; background: rgba(63,64,66,0.2); color: rgb(228,231,235); } /* QMenuBar Properties */ QMenuBar { - padding: 2px; border-bottom: 1px solid rgb(42,43,66); background: rgb(63,64,66); } -QMenuBar::item { - background: transparent; - padding: 4px; -} QMenuBar::item:selected { - padding: 4px; - border-radius: 4px; background: rgba(255,255,255,0.20); } -QMenuBar::item:pressed { - padding: 4px; - margin-bottom: 0; - padding-bottom: 0; -} /* QToolBar */ QToolBar { - padding: 1px; - font-weight: bold; - spacing: 2px; - margin: 1px; background: rgb(51,51,51); - /* QToolBar must override `border-style` to set the style. */ - border-style: none; } QToolBar::separator { background: rgb(42,43,66); } -QToolBar::separator:horizontal { - width: 2px; - margin: 0 6px; -} -QToolBar::separator:vertical { - height: 2px; - margin: 6px 0; -} -QToolBar > QToolButton { - background: transparent; - padding: 3px; - border-radius: 4px; -} QToolBar > QToolButton:hover, QToolBar > QToolButton::menu-button:hover { background: rgba(255,255,255,0.15); } -QToolBar > QToolButton::menu-button { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; -} QToolBar > QToolButton:pressed, QToolBar > QToolButton::menu-button:pressed:enabled, QToolBar > QToolButton:checked:enabled { background: rgba(255,255,255,0.24); } -QToolBar > QWidget { - background: transparent; -} /* Qmenu Properties */ QMenu { background: rgba(63,64,66,0.20); - padding: 8px 0; - border-radius: 4px; } QMenu::separator { - margin: 4px 0; - height: 1px; background: rgb(42,43,66); } -QMenu::item { - background: transparent; - padding: 4px 19px; -} QMenu::item:selected { background: rgba(255,255,255,0.12); } -QMenu::icon { - padding-left: 10px; - width: 14px; - height: 14px; -} /* QScrollBar */ QScrollBar { - background: rgba(255,255,255,0.40); - border-radius: 4px; -} -QScrollBar:horizontal { - height: 14px; -} -QScrollBar:vertical { + background: rgba(255, 255, 255, 0.40); } QScrollBar::handle { background: rgba(255,255,255,0.40); - border-radius: 3px; } QScrollBar::handle:hover { background: rgba(255,255,255,0.50); @@ -189,38 +102,9 @@ QScrollBar::handle:pressed { QScrollBar::handle:disabled { background: rgba(255,255,255,0.15); } -QScrollBar::handle:horizontal { - min-width: 8px; - margin: 4px 14px; -} -QScrollBar::handle:horizontal:hover { - margin: 2px 14px; -} -QScrollBar::handle:vertical { - min-height: 8px; - margin: 14px 4px; -} -QScrollBar::handle:vertical:hover { - margin: 14px 2px; -} -/* -Hide QScrollBar background. -The `sub-page` and `add-page` are not colored by default on most OS, but are colored on Windows. -*/ -QScrollBar::sub-page, -QScrollBar::add-page { - background: transparent; -} -QScrollBar::sub-line, -QScrollBar::add-line { - background: transparent; -} - QPushButton, QToolButton { color: rgb(26,115,178); border: 1px solid rgb(42,43,66); - padding: 4px 8px; - border-radius: 4px; } QPushButton:hover, QPushButton:pressed, QPushButton:checked:enabled, QToolButton:hover, QToolButton:pressed, QToolButton:checked:enabled { @@ -228,54 +112,22 @@ QToolButton:hover, QToolButton:pressed, QToolButton:checked:enabled { background: rgba(26,115,178,0.3); } -/* QDialogButtonBox */ -QDialogButtonBox { - dialogbuttonbox-buttons-have-icons: 0; -} -QDialogButtonBox QPushButton { - min-width: 65px; -} - /* QComboBox */ QComboBox { - min-height: 1.5em; - padding: 0 8px 0 4px; background: rgb(63,64,66); border: 1px solid rgb(42,43,66); - border-radius: 4px; } QComboBox:hover, QComboBox::item:hover, QComboBox:focus, QComboBox:open { border-color: rgb(138,180,247); } -QComboBox::drop-down { - margin: 2px 2px 2px -6px; - border-radius: 4px; /* This remove default style. */ -} QComboBox::drop-down:editable:hover { background: rgba(255,255,255,0.13); } -/* Setting background color of selected item when editable is false. */ QComboBox::item:selected { - border: none; /* This remove the border of indicator. */ background: rgba(26,115,178,0.35); - border-radius: 4px; -} - -/* QAbstractItemView in QComboBox is NoFrame. Override default settings and show border. */ -QComboBox QListView { - margin: 0; - padding: 4px; - background: rgba(63,64,66,0.25); - border-radius: 4px; -} -QComboBox QListView::item { - border-radius: 4px; } /* QListView QTreeView */ -QListView { - padding: 1px -} QListView, QTreeView { background: rgb(63,64,66); @@ -301,36 +153,12 @@ QTreeView > QHeaderView::section { background: rgb(42,43,66); } -/* -Following arrow settings are for QColumnView. -QColumnView::left-arrow and QColumnView::right-arrow are not working. -*/ -QListView::left-arrow { - margin: -2px; -} -QListView::right-arrow { - margin: -2px; -} - /* QTabWidget QTabBar */ QTabWidget::pane { border: 1px solid rgb(42,43,66); - border-radius: 4px; -} -QTabBar { - /* - Not filling background color when drawBase property is true. So need to set drawBase to false. - Default QTabBar is no need following declaration, but QMdiArea is need. - */ - qproperty-drawBase: 0; } QTabBar::close-button:hover { background: rgba(255,255,255,0.20); - border-radius: 4px; -} -QTabBar::tab { - padding: 3px; - border-style: solid; } QTabBar::tab:hover, QTabBar::tab:selected:hover:enabled { @@ -344,55 +172,6 @@ QTabBar::tab:selected:disabled, QTabBar::tab:only-one:selected:enabled { border-color: rgb(42,43,66); } -QTabBar::tab:top { - border-bottom-width: 2px; - margin: 3px 6px 0 0; - border-top-left-radius: 2px; - border-top-right-radius: 2px; -} -QTabBar::tab:bottom { - border-top-width: 2px; - margin: 0 6px 3px 0; - border-bottom-left-radius: 2px; - border-bottom-right-radius: 2px; -} -QTabBar::tab:left { - border-right-width: 2px; - margin: 0 0 6px 3px; - border-top-left-radius: 2px; - border-bottom-left-radius: 2px; -} -QTabBar::tab:right { - border-left-width: 2px; - margin-bottom: 6px; - margin: 0 3px 6px 0; - border-top-right-radius: 2px; - border-bottom-right-radius: 2px; -} -QTabBar::tab:top:first, -QTabBar::tab:top:only-one, -QTabBar::tab:bottom:first, -QTabBar::tab:bottom:only-one { - margin-left: 2px; -} -QTabBar::tab:top:last, -QTabBar::tab:top:only-one, -QTabBar::tab:bottom:last, -QTabBar::tab:bottom:only-one { - margin-right: 2px; -} -QTabBar::tab:left:first, -QTabBar::tab:left:only-one, -QTabBar::tab:right:first, -QTabBar::tab:right:only-one { - margin-top: 2px; -} -QTabBar::tab:left:last, -QTabBar::tab:left:only-one, -QTabBar::tab:right:last, -QTabBar::tab:right:only-one { - margin-bottom: 2px; -} /* QColumnView */ QColumnView { @@ -418,16 +197,13 @@ QTableView::item:selected { background: rgba(63,64,66,0.5); } QTableView QTableCornerButton::section { - margin: 0 1px 1px 0; background: rgb(42,43,66); - border-top-left-radius: 2px; } QTableView QTableCornerButton::section:pressed { background: rgba(26,115,178,0.35); } QTableView > QHeaderView { background: rgba(63,64,66,0.50); - border-radius: 3px; } QTableView > QHeaderView::section { background: rgb(42,43,66); @@ -435,67 +211,28 @@ QTableView > QHeaderView::section { /* QLineEdit */ QLineEdit { - padding: 3px 4px; - /* Adjust the min-height of QLineEdit to the height of the characters. */ - min-height: 1em; border: 1px solid rgb(42,43,66); background: rgb(63,64,66); - border-radius: 4px; } QLineEdit:focus { border-color: rgb(26,115,178); } -/* QFileDialog */ -QFileDialog QFrame { - border: none; -} - /* Check */ -QComboBox::indicator, -QMenu::indicator { - width: 18px; - height: 18px; -} QMenu::indicator { background: rgba(255,255,255,0.19); - margin-left: 3px; - border-radius: 4px; } /* Check indicator */ -QCheckBox, -QRadioButton { - spacing: 8px; -} -QGroupBox::title, -QAbstractItemView::item { - spacing: 6px; -} QCheckBox::indicator, QGroupBox::indicator, QAbstractItemView::indicator, QRadioButton::indicator { - height: 18px; - width: 18px; background: rgba(245,245,245,0.6); } QCheckBox::indicator:checked, QGroupBox::indicator:checked, QAbstractItemView::indicator:checked, QRadioButton::indicator:checked { - height: 14px; - width: 14px; background: rgb(26,115,178); -} - -QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} -QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} -QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow} -QCodeEditor {font-family: 'monospace, monospace'} -QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} -QLabel[bold=true] {font-weight: bold;} -QTreeView::item[base=true] {color: rgb(77,81,87); font-style: normal; font-weight: normal;} -QTreeView::item[disabled=true] {font-style: italic;} -QTreeView::item[constrained=true] {font-style: italic; color: blue;} -QHeaderView {font-weight: bold} \ No newline at end of file +} \ No newline at end of file diff --git a/src/sas/system/themes/default.css b/src/sas/system/themes/default.css index 202cb98321..a9b20761c9 100644 --- a/src/sas/system/themes/default.css +++ b/src/sas/system/themes/default.css @@ -11,14 +11,9 @@ QWidget:disabled { selection-background-color: rgba(77,81,87,0.25); selection-color: rgba(77,81,87,0.4); } -QWidget:focus { - outline: none; -} /* QMainWindow Properties */ QMainWindow::separator { - width: 4px; - height: 4px; background: rgb(218,220,224); } QMainWindow::separator:hover, @@ -27,21 +22,12 @@ QMainWindow::separator:pressed { } /* QCheckBox and QRadioButton Properties */ -QCheckBox, -QRadioButton { - border-top: 2px solid transparent; - border-bottom: 2px solid transparent; -} QCheckBox::indicator:enabled, QRadioButton::indicator:enabled { - height: 14px; - width: 14px; border: 2px solid rgba(0,0,0,0.25); } QCheckBox::indicator:hover, QRadioButton::indicator:hover { - height: 14px; - width: 14px; border: 2px solid rgb(26,115,178); } QCheckBox::indicator:checked { @@ -55,130 +41,58 @@ QCheckBox:checked { /* QGroupBox Properties */ QGroupBox { - font-weight: bold; - margin-top: 8px; - padding: 2px 1px 1px 1px; - border-radius: 4px; border: 1px solid rgb(218,220,224); } -QGroupBox::title { - subcontrol-origin: margin; - subcontrol-position: top left; - left: 7px; - margin: 0 2px 0 3px; -} -QGroupBox:flat { - border-color: transparent; -} /* QToolTip Properties */ QToolTip { - font-size: 80%; background: rgba(248,249,250,0.2); color: rgb(77,81,87); } /* QMenuBar Properties */ QMenuBar { - padding: 2px; border-bottom: 1px solid rgb(218,220,224); background: rgb(248,249,250); } -QMenuBar::item { - background: transparent; - padding: 4px; -} QMenuBar::item:selected { - padding: 4px; - border-radius: 4px; background: rgba(0,0,0,0.20); } -QMenuBar::item:pressed { - padding: 4px; - margin-bottom: 0; - padding-bottom: 0; -} /* QToolBar */ QToolBar { - padding: 1px; - font-weight: bold; - spacing: 2px; - margin: 1px; background: rgb(235,235,235); - /* QToolBar must override `border-style` to set the style. */ - border-style: none; } QToolBar::separator { background: rgb(218,220,224); } -QToolBar::separator:horizontal { - width: 2px; - margin: 0 6px; -} -QToolBar::separator:vertical { - height: 2px; - margin: 6px 0; -} -QToolBar > QToolButton { - background: transparent; - padding: 3px; - border-radius: 4px; -} QToolBar > QToolButton:hover, QToolBar > QToolButton::menu-button:hover { background: rgba(0,0,0,0.15); } -QToolBar > QToolButton::menu-button { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; -} QToolBar > QToolButton:pressed, QToolBar > QToolButton::menu-button:pressed:enabled, QToolBar > QToolButton:checked:enabled { background: rgba(0,0,0,0.24); } -QToolBar > QWidget { - background: transparent; -} /* Qmenu Properties */ QMenu { background: rgba(248,249,250,0.70); - padding: 8px 0; - border-radius: 4px; } QMenu::separator { - margin: 4px 0; - height: 1px; background: rgb(218,220,224); } -QMenu::item { - background: transparent; - padding: 4px 19px; -} QMenu::item:selected { background: rgba(0,0,0,0.12); } -QMenu::icon { - padding-left: 10px; - width: 14px; - height: 14px; -} /* QScrollBar */ QScrollBar { background: rgba(0,0,0,0.40); - border-radius: 4px; -} -QScrollBar:horizontal { - height: 14px; -} -QScrollBar:vertical { } QScrollBar::handle { background: rgba(0,0,0,0.40); - border-radius: 3px; } QScrollBar::handle:hover { background: rgba(0,0,0,0.50); @@ -189,38 +103,10 @@ QScrollBar::handle:pressed { QScrollBar::handle:disabled { background: rgba(0,0,0,0.15); } -QScrollBar::handle:horizontal { - min-width: 8px; - margin: 4px 14px; -} -QScrollBar::handle:horizontal:hover { - margin: 2px 14px; -} -QScrollBar::handle:vertical { - min-height: 8px; - margin: 14px 4px; -} -QScrollBar::handle:vertical:hover { - margin: 14px 2px; -} -/* -Hide QScrollBar background. -The `sub-page` and `add-page` are not colored by default on most OS, but are colored on Windows. -*/ -QScrollBar::sub-page, -QScrollBar::add-page { - background: transparent; -} -QScrollBar::sub-line, -QScrollBar::add-line { - background: transparent; -} QPushButton, QToolButton { color: rgb(26,115,232); border: 1px solid rgb(218,220,224); - padding: 4px 8px; - border-radius: 4px; } QPushButton:hover, QPushButton:pressed, QPushButton:checked:enabled, QToolButton:hover, QToolButton:pressed, QToolButton:checked:enabled { @@ -228,54 +114,28 @@ QToolButton:hover, QToolButton:pressed, QToolButton:checked:enabled { background: rgba(26,115,232,0.3); } -/* QDialogButtonBox */ -QDialogButtonBox { - dialogbuttonbox-buttons-have-icons: 0; -} -QDialogButtonBox QPushButton { - min-width: 65px; -} - /* QComboBox */ QComboBox { - min-height: 1.5em; - padding: 0 8px 0 4px; background: rgb(248,249,250); border: 1px solid rgb(218,220,224); - border-radius: 4px; } QComboBox:hover, QComboBox::item:hover, QComboBox:focus, QComboBox:open { border-color: rgb(26,115,232); } -QComboBox::drop-down { - margin: 2px 2px 2px -6px; - border-radius: 4px; /* This remove default style. */ -} QComboBox::drop-down:editable:hover { background: rgba(0,0,0,0.13); } /* Setting background color of selected item when editable is false. */ QComboBox::item:selected { - border: none; /* This remove the border of indicator. */ background: rgba(26,115,278,0.35); - border-radius: 4px; } /* QAbstractItemView in QComboBox is NoFrame. Override default settings and show border. */ QComboBox QListView { - margin: 0; - padding: 4px; background: rgba(248,249,250,0.25); - border-radius: 4px; -} -QComboBox QListView::item { - border-radius: 4px; } /* QListView QTreeView */ -QListView { - padding: 1px -} QListView, QTreeView { background: rgb(248,249,250); @@ -301,36 +161,12 @@ QTreeView > QHeaderView::section { background: rgb(218,220,224); } -/* -Following arrow settings are for QColumnView. -QColumnView::left-arrow and QColumnView::right-arrow are not working. -*/ -QListView::left-arrow { - margin: -2px; -} -QListView::right-arrow { - margin: -2px; -} - /* QTabWidget QTabBar */ QTabWidget::pane { border: 1px solid rgb(218,220,224); - border-radius: 4px; -} -QTabBar { - /* - Not filling background color when drawBase property is true. So need to set drawBase to false. - Default QTabBar is no need following declaration, but QMdiArea is need. - */ - qproperty-drawBase: 0; } QTabBar::close-button:hover { background: rgba(0,0,0,0.20); - border-radius: 4px; -} -QTabBar::tab { - padding: 3px; - border-style: solid; } QTabBar::tab:hover, QTabBar::tab:selected:hover:enabled { @@ -344,62 +180,12 @@ QTabBar::tab:selected:disabled, QTabBar::tab:only-one:selected:enabled { border-color: rgb(218,220,224); } -QTabBar::tab:top { - border-bottom-width: 2px; - margin: 3px 6px 0 0; - border-top-left-radius: 2px; - border-top-right-radius: 2px; -} -QTabBar::tab:bottom { - border-top-width: 2px; - margin: 0 6px 3px 0; - border-bottom-left-radius: 2px; - border-bottom-right-radius: 2px; -} -QTabBar::tab:left { - border-right-width: 2px; - margin: 0 0 6px 3px; - border-top-left-radius: 2px; - border-bottom-left-radius: 2px; -} -QTabBar::tab:right { - border-left-width: 2px; - margin-bottom: 6px; - margin: 0 3px 6px 0; - border-top-right-radius: 2px; - border-bottom-right-radius: 2px; -} -QTabBar::tab:top:first, -QTabBar::tab:top:only-one, -QTabBar::tab:bottom:first, -QTabBar::tab:bottom:only-one { - margin-left: 2px; -} -QTabBar::tab:top:last, -QTabBar::tab:top:only-one, -QTabBar::tab:bottom:last, -QTabBar::tab:bottom:only-one { - margin-right: 2px; -} -QTabBar::tab:left:first, -QTabBar::tab:left:only-one, -QTabBar::tab:right:first, -QTabBar::tab:right:only-one { - margin-top: 2px; -} -QTabBar::tab:left:last, -QTabBar::tab:left:only-one, -QTabBar::tab:right:last, -QTabBar::tab:right:only-one { - margin-bottom: 2px; -} /* QColumnView */ QColumnView { background: rgb(248,249,250); } QColumnViewGrip { - margin: -4px; background: rgb(248,249,250); } @@ -411,28 +197,20 @@ QTableView { QTableView:!active { background: rgba(0,0,0,0.12); } -QTableView::item { - height: 125%; -} QTableView::item:alternate { - height: 200%; - margin: 4px; background: rgba(0,0,0,0.12); } QTableView::item:selected { background: rgba(248,249,250,0.5); } QTableView QTableCornerButton::section { - margin: 4px; background: rgb(218,220,224); - border-top-left-radius: 2px; } QTableView QTableCornerButton::section:pressed { background: rgba(26,115,232,0.35); } QTableView > QHeaderView { background: rgba(248,249,250,0.50); - border-radius: 3px; } QTableView > QHeaderView::section { background: rgb(218,220,224); @@ -440,67 +218,23 @@ QTableView > QHeaderView::section { /* QLineEdit */ QLineEdit { - padding: 3px 4px; - /* Adjust the min-height of QLineEdit to the height of the characters. */ - min-height: 1em; border: 1px solid rgb(218,220,224); background: rgb(248,249,250); - border-radius: 4px; } QLineEdit:focus { border-color: rgb(26,115,232); } -/* QFileDialog */ -QFileDialog QFrame { - border: none; -} - -/* Check */ -QComboBox::indicator, -QMenu::indicator { - width: 18px; - height: 18px; -} -QMenu::indicator { - background: rgba(0,0,0,0.19); - margin-left: 3px; - border-radius: 4px; -} - /* Check indicator */ -QCheckBox, -QRadioButton { - spacing: 8px; -} -QGroupBox::title, -QAbstractItemView::item { - spacing: 6px; -} QCheckBox::indicator, QGroupBox::indicator, QAbstractItemView::indicator, QRadioButton::indicator { - height: 18px; - width: 18px; background: rgba(245,245,245,0.6); } QCheckBox::indicator:checked, QGroupBox::indicator:checked, QAbstractItemView::indicator:checked, QRadioButton::indicator:checked { - height: 14px; - width: 14px; background: rgb(26,115,178); -} - -QProgressBar {border: 2px solid grey; border-radius: 5px; text-align: center} -QProgressBar::chunk {background-color: #b1daf9; width: 10px; margin: 1px;} -QTextBrowser[warning=true] {border: 5px solid red; background-color: lightyellow} -QCodeEditor {font-family: 'monospace, monospace'} -QCodeEditor[warning=true] {border: 5px solid red; background-color: lightyellow} -QLabel[bold=true] {font-weight: bold;} -QTreeView::item[base=true] {color: rgb(77,81,87); font-style: normal; font-weight: normal;} -QTreeView::item[disabled=true] {font-style: italic;} -QTreeView::item[constrained=true] {font-style: italic; color: blue;} -QHeaderView {font-weight: bold} \ No newline at end of file +} \ No newline at end of file From 22aaeac561d0e42d3b634c6de84fa0a60533fbbd Mon Sep 17 00:00:00 2001 From: krzywon Date: Wed, 8 Nov 2023 14:01:13 -0500 Subject: [PATCH 67/67] Update user and developer documentation to match current features --- src/sas/qtgui/MainWindow/media/preferences_help.rst | 3 +++ .../Utilities/Preferences/DisplayPreferencesWidget.py | 2 ++ src/sas/system/style.py | 10 +++++++++- src/sas/system/themes/__init__.py | 3 +++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/sas/qtgui/MainWindow/media/preferences_help.rst b/src/sas/qtgui/MainWindow/media/preferences_help.rst index 4c9b6f9479..7f09823306 100644 --- a/src/sas/qtgui/MainWindow/media/preferences_help.rst +++ b/src/sas/qtgui/MainWindow/media/preferences_help.rst @@ -45,6 +45,9 @@ use the `Classic` theme as a fall back for any styles not defined in the stylesh is a stylesheet. For more information on writing Qt stylesheets, please see the `Qt style sheet reference `_ *persistent* +**Font Size** Select the font size that will be used throughout the SasView application. Font sizes defined in User themes +will override this setting. + **QT Screen Scale Factor**: A percent scaling factor that is applied all element sizes within the GUI. A restart of SasView is required to take effect. *persistent* diff --git a/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py b/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py index b7bf1777e0..fc7613b4fb 100644 --- a/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py +++ b/src/sas/qtgui/Utilities/Preferences/DisplayPreferencesWidget.py @@ -18,11 +18,13 @@ def __init__(self): 'QT_AUTO_SCREEN_SCALE_FACTOR': "Enable Automatic Scaling"} def _addAllWidgets(self): + self.addHorizontalLine() self.theme = self.addComboBox(title="Theme", params=style.get_theme_names(), default=style.theme) self.theme.currentIndexChanged.connect(self._previewTheme) self.font_size = self.addComboBox(title="Font Size", params=['10.0', '12.0', '14.0'], default=str(style.font_size)) self.font_size.currentIndexChanged.connect(self._previewFont) + self.addHorizontalLine() self.qtScaleFactor = self.addFloatInput( title="QT Screen Scale Factor", default_number=config.QT_SCALE_FACTOR) diff --git a/src/sas/system/style.py b/src/sas/system/style.py index e277c47e6b..05694155d4 100644 --- a/src/sas/system/style.py +++ b/src/sas/system/style.py @@ -9,6 +9,14 @@ class StyleSheet: Class used to manage all available themes. Built-in themes are available in sas.system.themes. User themes should live in ~/.sasview/themes. + + *CSS Order of operations:* + Each operation overrides any previous operation to allow user themes to take precedence over any built-in thematic + elements. + 1. The default font size and fonts are set. + 2. The base style sheet is set -> typically either classic.css for user themes or themes.STYLE_BASE for built-in + 3. Color palettes are applied (Dark or Light), if applicable. + 4. User theme elements are applied. """ def __init__(self): @@ -54,7 +62,7 @@ def get_theme_names(self) -> List[str]: return list(self._available_themes.keys()) def _create_full_theme(self): - """Private method that combines settings so users can separately set fonts and color palettes.""" + """Private method that combines settings to allow fonts and color palettes to be set separately.""" css = load_theme(self.theme) font_str = format_font_size(self.font_size) self._css = f"{font_str}{css}" diff --git a/src/sas/system/themes/__init__.py b/src/sas/system/themes/__init__.py index b6be112b73..02910a0600 100644 --- a/src/sas/system/themes/__init__.py +++ b/src/sas/system/themes/__init__.py @@ -14,6 +14,7 @@ 'Dark': Path(os.path.join(os.path.dirname(__file__), 'dark.css')), 'Classic': Path(os.path.join(os.path.dirname(__file__), 'classic.css')), } +# A list of style sheets that use the base style given in the STYLE_BASE USES_STYLE_BASE = ['Light', 'Dark'] # A template string for setting the font size @@ -63,6 +64,8 @@ def format_font_size(font_size: float) -> str: return FONT.format(font_size) +# STYLE_BASE defines the base sizes and behaviors of all widgets and interactive elements for the Light and Dark themes. +# The styles are here, so they are not considered as a separate style sheet when looking at built-in themes. STYLE_BASE = """ /* QWidget Properties */ QWidget:focus {outline: none;}