diff --git a/src/surface/gui/gui/app.py b/src/surface/gui/gui/app.py
index f800e24a..cc5ef2ce 100644
--- a/src/surface/gui/gui/app.py
+++ b/src/surface/gui/gui/app.py
@@ -1,9 +1,12 @@
import atexit
import signal
+from pathlib import Path
from threading import Thread
import rclpy.utilities
+from ament_index_python import get_package_share_directory
from PyQt6.QtWidgets import QApplication, QWidget
+from qt_material import apply_stylesheet
from rclpy.executors import MultiThreadedExecutor
from gui.gui_node import GUINode
@@ -29,18 +32,27 @@ def run_gui(self) -> None:
# Kills with Control + C
signal.signal(signal.SIGINT, signal.SIG_DFL)
- # TODO: New method of dark mode
+ extra_blue = {'success': '#040444', 'danger': '#040444', 'warning': '#040444'}
+ extra_watermelon = {'success': '#341616', 'danger': '#341616', 'warning': '#341616'}
# Apply theme
- # theme_param = self.theme_param.get_parameter_value().string_value
- # theme_path = Path(get_package_share_directory('gui')) / 'styles' / (theme_param + '.qss')
-
- # base_theme = 'dark' if theme_param == 'dark' else 'light'
- # custom_styles = '\n'
- # if theme_path.exists():
- # with theme_path.open(encoding='utf-8') as theme_file:
- # custom_styles += theme_file.read()
-
- # qdarktheme.setup_theme(base_theme, additional_qss=custom_styles)
+ theme_param = self.theme_param.get_parameter_value().string_value
+
+ match theme_param:
+ case 'dark':
+ base_theme = 'dark_blue.xml'
+ case 'light':
+ base_theme = 'light_blue.xml'
+ case 'watermelon':
+ base_path = Path(get_package_share_directory('gui')) / 'styles' / ('watermelon.xml')
+ base_theme = base_path.as_posix()
+ case _:
+ base_theme = 'dark_blue.xml'
+ self.node.get_logger().info(
+ 'Theme ' + theme_param + ' not found, defaulting to dark.'
+ )
+
+ extra = extra_watermelon if theme_param == 'watermelon' else extra_blue
+ apply_stylesheet(self, theme=base_theme, style='', extra=extra)
executor = MultiThreadedExecutor()
executor.add_node(self.node)
diff --git a/src/surface/gui/gui/styles/custom_styles.py b/src/surface/gui/gui/styles/custom_styles.py
index aa034175..bfb59198 100644
--- a/src/surface/gui/gui/styles/custom_styles.py
+++ b/src/surface/gui/gui/styles/custom_styles.py
@@ -15,10 +15,16 @@ class IndicatorMixin(QWidget):
# The stylesheets that correspond to each widget state
_STYLESHEETS: Final[dict[WidgetState, str]] = {
# Stylesheet for when a component is running, enabled, or armed
- WidgetState.ON: 'QWidget { background-color: limegreen; }',
+ WidgetState.ON: """
+ QWidget { background-color: limegreen; }
+ QWidget:hover { background-color: #5bd75b; }
+ """,
# Stylesheet for when a component is disabled, not running, or disarmed, but could be
# enabled through this widget
- WidgetState.OFF: 'QWidget { background-color: red; }',
+ WidgetState.OFF: """
+ QWidget { background-color: red; }
+ QWidget:hover { background-color: #ff3333; }
+ """,
# Stylesheet for when a component is disabled, not expected to have any effect or perform
# its function because of some external factor, either another widget or something
# external to the gui. For example, a the arm button when the pi is not connected
@@ -48,6 +54,13 @@ def set_state(self, new_state: WidgetState) -> None:
The new state for the widget
"""
self.current_state = new_state
+ match self.current_state:
+ case WidgetState.OFF:
+ self.setProperty('class', 'danger')
+ case WidgetState.ON:
+ self.setProperty('class', 'success')
+ case _:
+ self.setProperty('class', 'warning')
self.setStyleSheet(self._original_stylesheet + self._STYLESHEETS[self.current_state])
diff --git a/src/surface/gui/gui/styles/watermelon.xml b/src/surface/gui/gui/styles/watermelon.xml
new file mode 100644
index 00000000..238ca8e8
--- /dev/null
+++ b/src/surface/gui/gui/styles/watermelon.xml
@@ -0,0 +1,10 @@
+
+
+ #ff4d4e
+ #bf0002
+ #6f0001
+ #31363b
+ #1b5e1a
+ #ffffff
+ #ffffff
+
\ No newline at end of file
diff --git a/src/surface/gui/package.xml b/src/surface/gui/package.xml
index a89af075..54d33fa1 100644
--- a/src/surface/gui/package.xml
+++ b/src/surface/gui/package.xml
@@ -13,6 +13,7 @@
python3-numpy
cv_bridge
+ python3-qt-material-pip
python3-pyqtgraph
pyqt6-dev-tools
python3-pyqt6.qtmultimedia
diff --git a/src/surface/gui/setup.py b/src/surface/gui/setup.py
index 46a75c5f..ca253db3 100644
--- a/src/surface/gui/setup.py
+++ b/src/surface/gui/setup.py
@@ -27,7 +27,7 @@
# Include all style files.
(
str(Path('share') / PACKAGE_NAME / 'styles'),
- [str(path) for path in (Path('gui') / 'styles').glob('*.qss')],
+ [str(path) for path in (Path('gui') / 'styles').glob('*.xml')],
),
# Include all images.
(