15.1.555. tablet_qt/resources/camcops/stylesheets/questionnaire.css

/*
    https://doc.qt.io/qt-6.5/stylesheet-syntax.html

    REMEMBER: Layouts don't have CSS. Widgets do.
        https://doc.qt.io/qt-6.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:

    https://doc.qt.io/qt-6.5/stylesheet-reference.html#font-size
    https://doc.qt.io/qt-6.5/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
     https://doc.qt.io/qt-6.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
   - https://doc.qt.io/qt-6.5/stylesheet-examples.html#customizing-qcombobox
   - https://doc.qt.io/qt-6.5/stylesheet-syntax.html#sub-controls
   - https://doc.qt.io/qt-6.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
    - https://doc.qt.io/qt-6.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;
}
*/