Skip to content

Commit

Permalink
path selection button
Browse files Browse the repository at this point in the history
  • Loading branch information
JoschD committed Nov 17, 2023
1 parent d716aa3 commit 018339c
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 34 deletions.
28 changes: 14 additions & 14 deletions omc3_gui/segment_by_segment/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from omc3_gui.utils.base_classes import View
from omc3_gui.utils.counter import HorizontalGridLayoutFiller
from omc3_gui.utils.widgets import EditButton, OpenButton, RemoveButton, RunButton
from omc3_gui.utils import colors

LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -235,28 +236,27 @@ def __init__(self):
self.setModel(MeasurementListModel())
self.setItemDelegate(ColoredItemDelegate())
self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
tooltip_style = """
QToolTip {
background-color: #F0F0F0; /* Light gray background */
color: #333333; /* Dark gray text */
border: 1px solid #808080; /* Gray border */
tooltip_style = f"""
QToolTip {{
background-color: {colors.TOOLTIP_BACKGROUND}; /* Light gray background */
color: {colors.TOOLTIP_TEXT}; /* Dark gray text */
border: 1px solid {colors.TOOLTIP_BORDER}; /* Gray border */
font-family: "Courier New", monospace; /* Monospaced font */
}
}}
"""
self.setStyleSheet(tooltip_style)


class ColoredItemDelegate(QtWidgets.QStyledItemDelegate):

COLOR_MAP = {
MeasurementListModel.ColorIDs.NONE: "#000000",
MeasurementListModel.ColorIDs.BEAM1: "#0000ff",
MeasurementListModel.ColorIDs.BEAM2: "#ff0000",
# todo: what are the PSB ring colors?
MeasurementListModel.ColorIDs.RING1: "#4CAF50",
MeasurementListModel.ColorIDs.RING2: "#FF9800",
MeasurementListModel.ColorIDs.RING3: "#673AB7",
MeasurementListModel.ColorIDs.RING4: "#E91E63",
MeasurementListModel.ColorIDs.NONE: colors.TEXT_DARK,
MeasurementListModel.ColorIDs.BEAM1: colors.BEAM1,
MeasurementListModel.ColorIDs.BEAM2: colors.BEAM2,
MeasurementListModel.ColorIDs.RING1: colors.RING1,
MeasurementListModel.ColorIDs.RING2: colors.RING2,
MeasurementListModel.ColorIDs.RING3: colors.RING3,
MeasurementListModel.ColorIDs.RING4: colors.RING4,
}
def paint(self, painter, option, index):
# Customize the text color
Expand Down
40 changes: 40 additions & 0 deletions omc3_gui/utils/colors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
BLACK_87 = "#212121"
BLACK_54 = "#757575"
BLACK_38 = "#9e9e9e"
BLACK_26 = "#bdbdbd"
BLACK_12 = "#e1e1e1"
WHITE = "#FFFFFF"

GREEN_DARK = "#28642A"
GREEN_LIGHT = "#4CAF50"

RED_DARK = "#B71C1C"
RED_LIGHT = "#F44336"

BLUE_DARK = "#0D47A1"
BLUE_LIGHT = "#2196F3"

# Machine Colors ---
# LHC Colors
BEAM1 = "#0000ff"
BEAM2 = "#ff0000"

# PSB Ring Colors (TODO?)
RING1 = "#4CAF50"
RING2 = "#FF9800"
RING3 = "#673AB7"
RING4 = "#E91E63"

# Light Background, dark text ---
TEXT_DARK = BLACK_87
SECONDARY_TEXT_DARK = BLACK_54
GREYED_OUT_TEXT_DARK = BLACK_26

# Dark Background, light text ---
TEXT_LIGHT = WHITE
SECONDARY_TEXT_LIGHT = BLACK_12

# Tooltips ---
TOOLTIP_TEXT = BLACK_87
TOOLTIP_BACKGROUND = BLACK_12
TOOLTIP_BORDER = BLACK_38
42 changes: 36 additions & 6 deletions omc3_gui/utils/dataclass_ui.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from functools import partial
import inspect
import re
from dataclasses import MISSING, Field, dataclass, field, fields
from pathlib import Path
from typing import Callable, Dict, Optional, Sequence, Tuple, Union
from PyQt5.QtWidgets import QWidget
from omc3_gui.utils import file_dialogs

from qtpy import QtWidgets

from omc3_gui.utils.widgets import HorizontalSeparator
from omc3_gui.utils import colors
import logging

LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -71,7 +73,7 @@ class FieldUI:
label: QtWidgets.QLabel # label-widget of the field
get_value: Callable # getter for the widget value, returns the value as appropriate type for the dataclass
set_value: Callable # setter for the widget value
text_color: Optional[str] = "black" # default text-color for both widget and label
text_color: Optional[str] = colors.TEXT_DARK # default text-color for both widget and label
modified: bool = False # flag indicating if the widget-content has been modified by the user

def __post_init__(self):
Expand All @@ -85,7 +87,7 @@ def __post_init__(self):

def has_changed(self):
""" Triggered when the widget has been modified.
Sets then the label font to italic.
Sets then the modified flag and changes label font.
"""
self.modified = True
font = self.label.font()
Expand Down Expand Up @@ -201,18 +203,40 @@ def build_dataclass_ui(cls,
except AttributeError:
widget.setEnabled(field.editable)

layout.addWidget(widget, idx_row, 1)

get_value, set_value = build_getter_setter(widget, field_type)
dataclass_ui.fields[field.name] = FieldUI(
widget=widget,
label=qlabel,
set_value=set_value,
get_value=get_value,
text_color="#000000" if field.editable else "#bbbbbb"
text_color=colors.TEXT_DARK if field.editable else colors.GREYED_OUT_TEXT_DARK
)

if not issubclass(field_type, Path) or not field.editable:
layout.addWidget(widget, idx_row, 1, 1, 2)
else:
layout.addWidget(widget, idx_row, 1)
# Add Path selection button ---
button = QtWidgets.QPushButton("...")
button.setFixedWidth(30)

if field_type is FilePath:
dialog = file_dialogs.OpenFileDialog

elif field_type is DirectoryPath:
dialog = file_dialogs.OpenDirectoryDialog

else:
dialog = file_dialogs.OpenAnySingleDialog

button.clicked.connect(partial(
run_dialog,
dialog=dialog,
get_value=get_value,
set_value=set_value))
layout.addWidget(button, idx_row, 2)

# TODO: add path button
return dataclass_ui


Expand Down Expand Up @@ -264,6 +288,12 @@ def set_value(value):
return get_value, set_value


def run_dialog(dialog: file_dialogs.OpenFilesDialog, get_value: Callable, set_value: Callable):
""" Asks the user to select a directory/file. """
path = dialog(directory=get_value().parent).run_selection_dialog()
if path is not None:
set_value(path)


# Other ------------------------------------------------------------------------

Expand Down
67 changes: 58 additions & 9 deletions omc3_gui/utils/file_dialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@


# Open Dialog Windows ----------------------------------------------------------
class OpenAnyFileDialog(QFileDialog):
class OpenFilesDialog(QFileDialog):
""" Quick dialog to open any kind of file.
Modifies QFileDialog, and allows only kwargs to be passed.
"""

def __init__(self, **kwargs) -> None:
""" Quick dialog to open any kind of file.
Modifies QFileDialog, and allows only kwargs to be passed.
"""
if "directory" in kwargs and isinstance(kwargs["directory"], Path):
kwargs["directory"] = str(kwargs["directory"]) # allow giving Paths

super().__init__(**kwargs) # parent, caption, directory, filter, options
self.setOption(QFileDialog.Option.DontUseNativeDialog, True)

Expand All @@ -24,7 +27,23 @@ def run_selection_dialog(self) -> List[Path]:
return []


class OpenDirectoriesDialog(OpenAnyFileDialog):
class OpenFileDialog(OpenFilesDialog):
""" Open a single file. """

def __init__(self, caption = "Select File", **kwargs) -> None:
super().__init__(caption=caption, **kwargs) # parent, directory, filter, options
self.setFileMode(QFileDialog.ExistingFile)

def run_selection_dialog(self) -> Path:
selected = super().run_selection_dialog()
if selected:
return selected[0]
return None


class OpenDirectoriesDialog(OpenFilesDialog):
""" Open multiple directories. """

def __init__(self, caption = "Select Folders", **kwargs) -> None:
super().__init__(caption=caption, **kwargs) # parent, directory, filter, options
icon = QApplication.style().standardIcon(QStyle.SP_DirIcon)
Expand All @@ -46,17 +65,47 @@ def accept(self):


class OpenDirectoryDialog(OpenDirectoriesDialog):
""" Open a single directory. """

def __init__(self, caption = "Select Folder", **kwargs) -> None:
super().__init__(caption=caption, **kwargs) # parent, directory, filter, options
self.setFileMode(QFileDialog.DirectoryOnly)

def run_selection_dialog(self) -> Path:
return super().run_selection_dialog()[0]
selected = super().run_selection_dialog()
if selected:
return selected[0]
return None


class OpenFilesDialog(OpenAnyFileDialog):
class OpenAnyMultiDialog(OpenFilesDialog):
""" Open multiple files/folders. """

def __init__(self, caption = "Select Files", **kwargs) -> None:
super().__init__(caption=caption, **kwargs) # parent, directory, filter, options
self.setFileMode(QFileDialog.ExistingFiles)
icon = QApplication.style().standardIcon(QStyle.SP_FileIcon)
self.setWindowIcon(icon)

def accept(self):
"""This function is called when the user clicks on "Open".
Normally, when selecting a directories, the first directory is followed/opened inside the dialog,
i.e. its content is shown. Overwrite super().accept() to prevent that and close the dialog instead.
"""
if not self.selectedFiles():
LOGGER.warning(f"Nothing selected. Try again or cancel.")
return

self.done(QFileDialog.Accepted)


class OpenAnySingleDialog(OpenAnyMultiDialog):
""" Open a single file/folder. """

def __init__(self, caption = "Select File", **kwargs) -> None:
super().__init__(caption=caption, **kwargs) # parent, directory, filter, options
self.setFileMode(QFileDialog.ExistingFile)

def run_selection_dialog(self) -> Path:
selected = super().run_selection_dialog()
if selected:
return selected[0]
return None
11 changes: 6 additions & 5 deletions omc3_gui/utils/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"""

from qtpy import QtWidgets
from qtpy import QtCore
from omc3_gui.utils import colors

# Buttons ----------------------------------------------------------------------

Expand All @@ -17,7 +17,7 @@ def __init__(self, *args, **kwargs):
if not args and not "text" in kwargs:
self.setText("Run")

self.setStyleSheet("background-color: #28642A; color: #fff;")
self.setStyleSheet(f"background-color: {colors.GREEN_DARK}; color: {colors.TEXT_LIGHT};")


class OpenButton(QtWidgets.QPushButton):
Expand All @@ -27,7 +27,7 @@ def __init__(self, *args, **kwargs):
if not args and not "text" in kwargs:
self.setText("Open")

self.setStyleSheet("background-color: #4CAF50; color: #000000;")
self.setStyleSheet(f"background-color: {colors.GREEN_LIGHT}; color: {colors.TEXT_DARK};")


class RemoveButton(QtWidgets.QPushButton):
Expand All @@ -36,8 +36,9 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not args and not "text" in kwargs:
self.setText("Remove")

self.setStyleSheet(f"background-color: {colors.RED_LIGHT}; color: {colors.TEXT_DARK};")

self.setStyleSheet("background-color: #f44336; color: #000000;")


class EditButton(QtWidgets.QPushButton):
Expand All @@ -47,7 +48,7 @@ def __init__(self, *args, **kwargs):
if not args and not "text" in kwargs:
self.setText("Edit")

self.setStyleSheet("background-color: #2196F3; color: #fff;")
self.setStyleSheet(f"background-color: {colors.BLUE_DARK}; color: {colors.TEXT_LIGHT};")


# Filler -----------------------------------------------------------------------
Expand Down

0 comments on commit 018339c

Please sign in to comment.