/*
http://doc.qt.io/qt-5/stylesheet-syntax.html
REMEMBER: Layouts don't have CSS. Widgets do.
http://doc.qt.io/qt-5/stylesheet.html
https://bugreports.qt.io/browse/QTBUG-22862
BUT layouts do have spacing; use e.g.
setSpacing() -- between widgets inside the layout
... typically leave this one
setContentsMargins() -- around the whole set of widgets
... typically reduce this one
Avoid restyling QWidget/QLabel in any major way, except for debugging;
for example, the "About Qt" dialog uses QLabel.
You'd hope that you could specify a base font here (e.g. by text
substitution) and then have all other fonts specified relative to it.
In Qt 4.8, there was no way to do that: pt or px only. And that
remains true for font sizes:
http://doc.qt.io/qt-5.7/stylesheet-reference.html#font-size
http://doc.qt.io/qt-5.7/stylesheet-reference.html#length
So, since one can't use percentages or "1.2em", there are two options:
(1) all elements using fonts need custom CSS, done in code. Silly!
(2) We do it in CSS but with multiple search/replace - better.
We will do a replacement that uses Qt QString arg format, with percentages,
with the following mapping:
%1 normal font size (pt)
%2 big font size (pt)
%3 heading font size (pt)
%4 title font size (pt)
%5 base menu font size (pt)
%6 slider groove size, perpendicular to the slider direction (px)
%7 slider handle size, parallel to the slider direction (px)
%8 slider groove margin, parallel to the slider direction (px)
ALL CSS USING CamcopsApp::getSubstitutedCss MUST PROVIDE AT LEAST ONE
PLACEHOLDER FOR EACH OF THESE, e.g. in a comment if not otherwise used
(or you get "QString::arg: Argument missing").
... plus custom code-applied CSS for text whose size is determined
dynamically.
Selector mechanisms include:
classname
... applies to this class and any C++ derived classes
... BUT: doesn't apply to "child widgets" of another C++ class
.classname
... this C++ class but not its derived classes
parent child
... applies to child class that's within a parent widget
classname[property="value"]
... specific property
*[property="value"]
... general property
.customproperty
... ? http://stackoverflow.com/questions/4596903
A, B
either A or B
#id
... matches by setObjectName()
Colour names:
https://www.w3.org/TR/SVG/types.html#ColorKeywords
https://convertingcolors.com/
UK and US spellings are supported; see qtbase/src/gui/painting/qcolor.cpp.
Prefer colour names to numbers, and UK to US names.
Test colours at:
https://www.w3schools.com/colors/colors_picker.asp
http://jscolor.com/
*/
/* =========================================================================
General styling
========================================================================= */
QWidget {
/*
Don't set these on QWidget -- they mess up e.g. QCalendarWidget,
spinbox arrows, and all sorts of stuff like that.
color: black;
border: 0;
margin: 0;
padding: 0;
*/
font-size: %1pt;
}
BaseWidget {
border: 0;
margin: 0;
padding: 0;
font-size: %1pt;
background-color: transparent;
/* Making this explicitly "transparent" fixes the background colour problem
when used as the page widget in a questionnaire via ZoomableWidget. */
}
/* For debugging */
/*
QLabel {
background-color: green;
}
*/
/* =========================================================================
Modifiers, using dynamic properties
========================================================================= */
*[missing="true"] {
background-color: yellow;
}
*[italic="true"] {
font-style: italic;
}
/* =========================================================================
Things that look or behave like buttons
=========================================================================
- Actual QPushButton: e.g. countdown buttons
- Others, e.g. QuButton, use ClickableLabelWordWrapWide, with a "button"
ID, i.e. ClickableLabelWordWrapWide#button.
- Note that ClickableLabelNoWrap and ClickableLabelWordWrapWide inherit
from QPushButton.
- Note that ClickableLabelWordWrapWide *contains* a LabelWordWrapWide.
- Note that if you set ClickableLabel* and *then* QPushButton CSS, then
the latter overrides the former (even though you would think child classes
are more specific than parent classes). As per
http://doc.qt.io/qt-5/stylesheet-syntax.html
*/
QPushButton,
QComboBox#picker_inline,
ClickableLabelWordWrapWide#picker_popup,
ClickableLabelWordWrapWide#button,
ClickableLabelWordWrapWide#diagnostic_code,
BooleanWidget ClickableLabelWordWrapWide,
NvpChoiceDialog ClickableLabelWordWrapWide,
PagePickerDialog ClickableLabelWordWrapWide {
font-weight: bold;
background-color: lightgrey;
border-style: solid;
border-width: 2px;
border-radius: 10px;
border-color: darkgrey;
padding: 5px;
}
LabelWordWrapWide#diagnostic_code {
/* Text displayed as part of the diagnostic code */
color: blue;
}
QPushButton:pressed,
QComboBox#picker_inline:pressed,
ClickableLabel:pressed,
ClickableLabelWordWrapWide:pressed,
ClickableLabelWordWrapWide#button:pressed,
ClickableLabelWordWrapWide#diagnostic_code:pressed {
background-color: rgba(100, 100, 255, 200); /* blue */ /* to match BUTTON_PRESSED_COLOUR */
}
/* The above will override the generic dynamic modifiers, so we re-specify... */
ClickableLabelWordWrapWide#picker_popup[missing="true"],
QComboBox#picker_inline[missing="true"] {
background-color: yellow;
}
QPushButton {
color: black;
}
QPushButton:disabled {
/* NB is NOT the colour of disabled MCQ text (etc.) */
color: rgb(64, 64, 64); /* grey */
background-color: silver;
}
ClickableLabelWordWrapWide#button:disabled,
ClickableLabelWordWrapWide#diagnostic_code:disabled {
/* Override QPushButton:disabled */
color: rgb(64, 64, 64); /* grey */
background-color: silver;
}
/* Slightly different styling for QuPickerPopup */
ClickableLabelWordWrapWide#picker_popup {
color: blue;
}
/* =========================================================================
Things that look or behave like text.
=========================================================================
Note that these must come AFTER the "button-like" attributes of
ClickableLabelWordWrapWide, otherwise text-like stuff gets the background
colours.
*/
ClickableLabelNoWrap,
ClickableLabelWordWrapWide {
color: black;
font-weight: normal;
background-color: transparent;
border: 1px black;
border-radius: 0;
padding: 0;
margin: 0;
}
ClickableLabelWordWrapWide:disabled { /* e.g. MCQ facsimiles */
background-color: transparent;
}
LabelWordWrapWide {
color: black;
background-color: transparent;
}
LabelWordWrapWide:disabled {
/* Includes disabled things containing this, which is quite a lot;
e.g. QuButton, QuMCQ. */
color: gray;
background-color: transparent;
}
/* =========================================================================
QComboBox
=========================================================================
- For QuPickerInline
- http://stackoverflow.com/questions/29939990
- http://doc.qt.io/qt-4.8/stylesheet-examples.html#customizing-qcombobox
- http://doc.qt.io/qt-5/stylesheet-syntax.html#sub-controls
- http://doc.qt.io/qt-5/stylesheet-reference.html#list-of-stylable-widgets
- http://stackoverflow.com/questions/13308341/qcombobox-abstractitemviewitem
- QComboBox gets the "on" state when the popup is open
- "::drop-down" is the arrow at the right (typically) with which to open
the popup
- ":item:selected" means (e.g.) selected with the arrow keys, not "chosen"
- ":item:checked" means "chosen"
*/
QCalendarWidget QComboBox::drop-down,
QCalendarWidget QComboBox::down-arrow {
width: 60px;
}
QComboBox#picker_inline {
color: blue;
selection-color: red;
}
QComboBox#picker_inline:item {
/*
- using pt as a unit doesn't work here
- not specifying height doesn't work; heights get *much* too big
- Qt knows about px, ex (?), em, pt; see qcssparser.cpp
... [ex: http://stackoverflow.com/questions/918612/what-is-the-value-of-the-css-ex-unit]
... though px/ex/em in one function (for general use)
and pt/px in another (for fonts)
- em works well (e.g. 3em)
- ex also works well (e.g. 6ex)
*/
height: 6ex;
padding-left: 20px; /* move text right to make room for tick mark */
}
QComboBox#picker_inline:item:selected {
border: 2px solid black;
}
QComboBox#picker_inline:item:checked {
font-weight: bold;
}
/* Read-only version of QuPickerInline */
QLabel#picker_inline {
color: blue;
font-weight: bold;
}
/* =========================================================================
Editors
========================================================================= */
GrowingPlainTextEdit,
GrowingTextEdit,
QDateTimeEdit,
QDoubleSpinBox,
QLineEdit,
QPlainTextEdit,
QSpinBox,
QTextEdit {
color: black;
background-color: rgb(210, 240, 170); /* greenish */
}
GrowingPlainTextEdit:focus,
GrowingTextEdit:focus,
QDateTimeEdit:focus,
QDoubleSpinBox:focus,
QLineEdit:focus,
QPlainTextEdit:focus,
QSpinBox:focus,
QTextEdit:focus {
background-color: rgb(255, 215, 128); /* light orange */
}
GrowingPlainTextEdit:disabled,
GrowingTextEdit:disabled,
QDateTimeEdit:disabled,
QDoubleSpinBox:disabled,
QLineEdit:disabled,
QPlainTextEdit:disabled,
QSpinBox:disabled,
QTextEdit:disabled {
color: black; /* black */
background-color: gainsboro; /* a light grey */
}
/* =========================================================================
Outer containers
========================================================================= */
#questionnaire_outer_object {
/* background-color ignored, for unclear QStackedWidget reason */
}
#questionnaire_background_patient {
background-color: white;
}
#questionnaire_background_clinician {
background-color: #FFFFD0; /* pale yellow */
}
#questionnaire_background_config {
background-color: #E6E6FA; /* lavender */
}
/* =========================================================================
Questionnaire header
========================================================================= */
QuestionnaireHeader QLabel {
font-size: %4pt;
color: grey;
}
#header_horizontal_line {
background-color: black;
}
/* =========================================================================
Questionnaire header
========================================================================= */
#questionnaire_horizontal_line {
background-color: black;
}
/* =========================================================================
Widgets
========================================================================= */
/* BooleanWidget in its Text appearance */
/* Previously, everything done with #boolean_widget. Now, sub-widgets within
a BooleanWidget. That is, replaced
#boolean_widget[state...]:pseudo {}
with
BooleanWidget ClickableLabelWordWrapWide[state...]:pseudo {}
*/
BooleanWidget ClickableLabelWordWrapWide[state="disabled"] {
background-color: darkgrey;
}
BooleanWidget ClickableLabelWordWrapWide[state="null"] {
background-color: white;
}
BooleanWidget ClickableLabelWordWrapWide[state="nullrequired"] {
background-color: yellow;
}
BooleanWidget ClickableLabelWordWrapWide[state="false"] {
background-color: white;
}
BooleanWidget ClickableLabelWordWrapWide[state="true"] {
background-color: #FF6666; /* red */
}
BooleanWidget ClickableLabelWordWrapWide[state="true"] LabelWordWrapWide {
/* Have to drill down to LabelWordWrapWide for the text color */
/* color: white; */ /* Works but would need some more tweaks, and isn't much better visually */
}
BooleanWidget ClickableLabelWordWrapWide[readonly="true"]:pressed {
background-color: grey;
}
BooleanWidget ClickableLabelWordWrapWide[readonly="false"]:pressed {
background-color: rgba(100, 100, 255, 200);
}
/* ... to match BUTTON_PRESSED_COLOUR */
#countdown_label {
font-weight: bold;
}
#quheading {
background-color: lightskyblue;
}
#mcq_instruction {
color: grey;
font-weight: bold;
}
/*
For QuSlider
- this is quite hard
- http://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qslider
- http://thesmithfam.org/blog/2010/03/10/fancy-qslider-stylesheet/
- https://forum.qt.io/topic/52150/proportions-of-elemnts-like-sliders
groove border not always shown; apply the border to the sub-page/add-page
sub-page:
The part of the slider to the LEFT or ABOVE the handle.
This makes sense for scrollbars that control pages (down -> +),
but we have to invert it for sliders where up is more.
hover colour: to match BUTTON_PRESSED_COLOUR, except not transparent
QSlider padding is essential to get the handle outside the groove
four-dimensional CSS parameters are: top, right, bottom, left
three-dimensional CSS parameters are: top, right/left, bottom
two-dimensional CSS parameters are: vertical, horizontal
handle:
- uses QStyle::SC_SliderHandle
- see qtbase/src/widgets/widgets/qslider.cpp
- see qtbase/src/widgets/styles/qstylesheetstyle.cpp
- QStyleSheetStyle::drawComplexControl
- see qtbase/src/gui/text/qcssparser.cpp
- maps e.g. "background-color" (CSS) to BackgroundColor (C++)
- https://stackoverflow.com/questions/11392089/horizontal-line-in-background-using-css3
known elements are listed in
- qtbase/src/widgets/styles/qstylesheetstyle.cpp
*/
/*
QSlider {
background-color: green;
}
*/
QSlider:horizontal {
padding: %6px 0;
}
QSlider:vertical {
padding: 0 %6px;
}
QSlider::groove {
border: 2px solid black;
background: lightgrey;
}
QSlider::groove:horizontal {
height: %6px;
margin: %8px 0;
}
QSlider::groove:vertical {
width: %6px;
margin: 0 %8px;
}
QSlider::add-page,
QSlider::sub-page {
border-width: 2px;
border-style: solid;
}
/* The slider's "mark" is the junction of the add-page/sub-page borders. */
QSlider::sub-page:horizontal { /* Left of the centre */
/* border-color: black red black black; */
border-color: black;
}
QSlider::add-page:horizontal { /* Right of the centre */
/* border-color: black black black red; */
border-color: black;
}
QSlider::add-page:vertical { /* Below the centre */
/* border-color: red black black black; */
border-color: black;
}
QSlider::sub-page:vertical { /* Above the centre */
/* border-color: black black red black; */
border-color: black;
}
QSlider::sub-page:horizontal,
QSlider::add-page:vertical {
background: red;
}
QSlider#slider_symmetric::sub-page:horizontal,
QSlider#slider_symmetric::add-page:vertical {
/* The version with no red on the slider groove "below" the slider handle */
background: white;
}
QSlider::add-page:horizontal,
QSlider::sub-page:vertical {
background: white;
}
QSlider::handle {
background: rgba(100, 100, 100, 150);
border: 2px solid black;
border-radius: %6px;
}
QSlider::handle:horizontal {
width: %7px;
margin: -%6px 0;
}
QSlider::handle:vertical {
height: %7px;
margin: 0 -%6px;
}
QSlider::handle:horizontal:hover,
QSlider::handle:vertical:hover {
background: rgba(50, 50, 255, 150);
}
QSlider::handle:disabled {
background: rgba(200, 200, 200, 150);
border-color: #aaa;
}
/* The value label */
QLabel#slider {
color: red;
font-weight: bold;
}
CanvasWidget {
/* in practice: is overridden in code */
border: 2px solid grey;
}
/* QuPhoto */
AspectRatioPixmap {
background-color: lightgrey;
}
/* Background colours */
#option_background {
background-color: lightgrey;
}
#stripe_background_even {
background-color: rgba(200, 200, 255, 50);
}
#stripe_background_odd {
background-color: rgba(255, 255, 255, 0);
}
/* QuMCQGrid */
#mcq_grid #question {
font-weight: bold;
padding: 5px;
}
#mcq_grid #option {
padding: 5px;
}
#mcq_grid #title {
font-weight: bold;
padding: 5px;
}
#mcq_grid #subtitle {
font-weight: bold;
padding: 5px;
}
#mcq_grid #vline {
background-color: darkgrey;
}
/* QuMCQGridDouble */
#mcq_grid_double #option_background {
background-color: lightgrey;
}
#mcq_grid_double #stripe_background_even {
background-color: rgba(200, 200, 255, 50);
}
#mcq_grid_double #stripe_background_odd {
background-color: rgba(255, 255, 255, 0);
}
#mcq_grid_double #question {
font-weight: bold;
padding: 5px;
}
#mcq_grid_double #option {
padding: 5px;
}
#mcq_grid_double #title {
font-weight: bold;
padding: 5px;
}
#mcq_grid_double #stem {
font-weight: bold;
padding: 5px;
}
#mcq_grid_double #subtitle {
font-weight: bold;
padding: 5px;
}
#mcq_grid_double #vline {
background-color: darkgrey;
}
/* QuMCQGridSingleBoolean */
#mcq_grid_single_boolean #option_background {
background-color: lightgrey;
}
#mcq_grid_single_boolean #stripe_background_even {
background-color: rgba(200, 200, 255, 50);
}
#mcq_grid_single_boolean #stripe_background_odd {
background-color: rgba(255, 255, 255, 0);
}
#mcq_grid_single_boolean #question {
font-weight: bold;
padding: 5px;
}
#mcq_grid_single_boolean #option {
padding: 5px;
}
#mcq_grid_single_boolean #title {
font-weight: bold;
padding: 5px;
}
#mcq_grid_single_boolean #subtitle {
font-weight: bold;
padding: 5px;
}
#mcq_grid_single_boolean #vline {
background-color: darkgray;
}
/* =========================================================================
QCalendarWidget
========================================================================= */
/* Not supported? Very partially supported? */
QCalendarWidget QAbstractItemView:disabled {
/*
https://stackoverflow.com/questions/30915620/qcalendar-styling-attribute-for-disabled-items
This works.
Styles the dates that aren't part of the current month (last month,
next month).
*/
color: lightgray;
}
QCalendarWidget QAbstractItemView {
font-size: %2pt;
}
/* =========================================================================
Debugging
========================================================================= */
#debug_green {
background-color: green;
}
#debug_red {
background-color: red;
}
#debug_blue {
background-color: blue;
}
#debug_yellow {
background-color: yellow;
}
#debug_pink {
background-color: pink;
}
/*
BaseWidget {
background-color: yellow;
}
*/
/*
LabelWordWrapWide {
padding: 5px;
}
*/