Skip to content

Commit

Permalink
gui/experiments: add custom color themes for experiment windows
Browse files Browse the repository at this point in the history
Signed-off-by: Florian Agbuya <[email protected]>
  • Loading branch information
fsagbuya committed Oct 9, 2024
1 parent 333623e commit 2bccb54
Showing 1 changed file with 84 additions and 2 deletions.
86 changes: 84 additions & 2 deletions artiq/dashboard/experiments.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class _ArgumentEditor(EntryTreeWidget):
def __init__(self, manager, dock, expurl):
self.manager = manager
self.expurl = expurl
self.dock = dock

EntryTreeWidget.__init__(self)

Expand Down Expand Up @@ -78,6 +79,25 @@ async def _recompute_argument(self, name):
argument["desc"] = procdesc
argument["state"] = state
self.update_argument(name, argument)
self.reapply_theme()

def reapply_theme(self):
palette, color = self.dock.get_current_theme()
self.apply_theme(palette, color)

def apply_theme(self, palette, color):
self.setPalette(palette)
for child in self.findChildren(QtWidgets.QWidget):
child.setPalette(palette)
child.setAutoFillBackground(True)
for i in range(self.topLevelItemCount()):
self._set_item_color(self.topLevelItem(i), color)

def _set_item_color(self, item, color):
for col in range(item.columnCount()):
item.setBackground(col, QtGui.QBrush() if color is None else QtGui.QColor(color))
for child_index in range(item.childCount()):
self._set_item_color(item.child(child_index), color)

# Hooks that allow user-supplied argument editors to react to imminent user
# actions. Here, we always keep the manager-stored submission arguments
Expand Down Expand Up @@ -303,14 +323,66 @@ async def _recompute_arguments_task(self, overrides=dict()):
self.argeditor = editor_class(self.manager, self, self.expurl)
self.layout.addWidget(self.argeditor, 0, 0, 1, 5)
self.argeditor.restore_state(argeditor_state)
self.argeditor.reapply_theme()

def contextMenuEvent(self, event):
menu = QtWidgets.QMenu(self)
select_theme = menu.addAction("Select color theme")
reset_theme = menu.addAction("Reset to default theme")
menu.addSeparator()
reset_sched = menu.addAction("Reset scheduler settings")
action = menu.exec(self.mapToGlobal(event.pos()))
if action == reset_sched:
if action == select_theme:
self.select_theme()
elif action == reset_theme:
self.reset_theme()
elif action == reset_sched:
asyncio.ensure_future(self._recompute_sched_options_task())

def select_theme(self):
color = QtWidgets.QColorDialog.getColor()
if color.isValid():
self.set_theme(color.name())
self.manager.set_theme(self.expurl, color.name())

def set_theme(self, color):
palette = self.modify_theme_palette(color)
self.setPalette(palette)
self.argeditor.apply_theme(palette, color)

def modify_theme_palette(self, color):
if color is None:
return QtWidgets.QApplication.palette()
palette = self.palette()
qcolor = QtGui.QColor(color)
palette.setColor(QtGui.QPalette.ColorRole.Window, qcolor)
palette.setColor(QtGui.QPalette.ColorRole.Highlight, qcolor)
palette.setColor(QtGui.QPalette.ColorRole.Base, qcolor)
palette.setColor(QtGui.QPalette.ColorRole.Button, qcolor)
luminance = (0.299 * qcolor.red() + 0.587 * qcolor.green() + 0.114 * qcolor.blue()) / 255
text_color = QtGui.QColor(0, 0, 0) if luminance > 0.5 else QtGui.QColor(255, 255, 255)
palette.setColor(QtGui.QPalette.ColorRole.WindowText, text_color)
palette.setColor(QtGui.QPalette.ColorRole.Text, text_color)
palette.setColor(QtGui.QPalette.ColorRole.ButtonText, text_color)
palette.setColor(QtGui.QPalette.ColorRole.PlaceholderText, text_color)
return palette

def get_current_theme(self):
color = self.manager.get_theme(self.expurl)
palette = self.modify_theme_palette(color)
return palette, color

def apply_theme(self):
color = self.manager.get_theme(self.expurl)
if color:
self.set_theme(color)
else:
self.set_theme(None)

def reset_theme(self):
self.set_theme(None)
self.manager.set_theme(self.expurl, None)

async def _recompute_sched_options_task(self):
try:
expdesc, _ = await self.manager.compute_expdesc(self.expurl)
Expand Down Expand Up @@ -457,6 +529,7 @@ def __init__(self, main_window, dataset_sub,
self.submission_options = dict()
self.submission_arguments = dict()
self.argument_ui_names = dict()
self.themes = dict()

self.datasets = dict()
dataset_sub.add_setmodel_callback(self.set_dataset_model)
Expand All @@ -483,6 +556,12 @@ def set_explist_model(self, model):
def set_schedule_model(self, model):
self.schedule = model.backing_store

def get_theme(self, expurl):
return self.themes.get(expurl)

def set_theme(self, expurl, color):
self.themes[expurl] = color

def resolve_expurl(self, expurl):
if expurl[:5] == "repo:":
expinfo = self.explist[expurl[5:]]
Expand Down Expand Up @@ -592,6 +671,7 @@ def open_experiment(self, expurl):
self.open_experiments[expurl] = dock
dock.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose)
self.main_window.centralWidget().addSubWindow(dock)
dock.apply_theme()
dock.show()
dock.sigClosed.connect(partial(self.on_dock_closed, expurl))
if expurl in self.dock_states:
Expand Down Expand Up @@ -708,7 +788,8 @@ def save_state(self):
"arguments": self.submission_arguments,
"docks": self.dock_states,
"argument_uis": self.argument_ui_names,
"open_docks": set(self.open_experiments.keys())
"open_docks": set(self.open_experiments.keys()),
"themes": self.themes
}

def restore_state(self, state):
Expand All @@ -719,6 +800,7 @@ def restore_state(self, state):
self.submission_options = state["options"]
self.submission_arguments = state["arguments"]
self.argument_ui_names = state.get("argument_uis", {})
self.themes = state.get("themes", {})
for expurl in state["open_docks"]:
self.open_experiment(expurl)

Expand Down

0 comments on commit 2bccb54

Please sign in to comment.