Loading src/gui.py +16 −165 Original line number Diff line number Diff line Loading @@ -50,7 +50,8 @@ class Ui(QtWidgets.QMainWindow): # Import config try: with open("config", 'r') as f: file_config = utils.args.config with open(file_config, 'r') as f: config:dict = json.loads(f.read()) except: raise Loading Loading @@ -108,8 +109,10 @@ class Ui(QtWidgets.QMainWindow): for tconf in config: tconf:dict cols = 2 # default cols inside each widget count = 0 # pointer to current col inside widget # cols = 2 # default cols inside each widget # count = 0 # pointer to current col inside widget # self._cols = cols # self._count = count try: # check basic define params if 'id' in tconf.keys(): Loading @@ -126,112 +129,28 @@ class Ui(QtWidgets.QMainWindow): # size policy if wcount%wcols == 0: # first column wpol = QtWidgets.QSizePolicy(policy.Preferred, policy.Preferred) elif wcols-(wcount%wcols) == 1: # last column elif wcount%wcols == wcols-1: # last column wpol = QtWidgets.QSizePolicy(policy.Maximum, policy.Preferred) else: wpol = QtWidgets.QSizePolicy(policy.Minimum, policy.Preferred) gb = newGroupBox(id, name, wpol) # COMMENTBOX if tconf['type'] == 'text': widget = QtWidgets.QPlainTextEdit(None) widget.setObjectName(f"tb_{id}") widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Expanding, policy.Preferred)) addTextBoxTexts(widget, tconf) widget.installEventFilter(self) # Set enter as save gb.layout().addWidget(widget) self.commentBox = widget self.tb[id] = widget gb = widgets.CommentBox(self, tconf, wpol) # CHECKBOX elif tconf['type'] == 'checkbox': if 'ncolumns' in tconf.keys(): cols = tconf['ncolumns'] if 'elements' in tconf and len(tconf['elements']) > 0: self.cb[id] = {} for element in tconf['elements']: try: eid = element['id'] wid = f"cb_{eid}" # add checkbox widget = QtWidgets.QCheckBox(None) widget.setObjectName(wid) widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Minimum, policy.Fixed)) addCheckBoxTexts(widget, element) addToolTip(widget, element) gb.layout().addWidget(widget, count//cols, count%cols) count += 1 # save widget self.cb[id][eid] = widget # self.cbColumns.append(eid) # self.cbNames.append(wid) except KeyError as e: print(f"KeyError: {e}") gb = widgets.CheckBoxGroup(self, tconf, wpol) # RADIOBUTTON TYPE elif tconf['type'] == 'radiobutton': if 'ncolumns' in tconf.keys(): cols = tconf['ncolumns']*2 # *2 -> shortcut and name in 2 rows gbb = QtWidgets.QButtonGroup() gbb.setObjectName(f"gbb_{id}") if 'elements' in tconf and len(tconf['elements']) > 0: self.rb[id] = {} for element in tconf['elements']: element:dict try: eid = element['id'] wid = f"rb_{eid}" # radiobutton widget = QtWidgets.QRadioButton(None) widget.setObjectName(wid) widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Minimum, policy.Fixed)) addRadioButtonTexts(widget, element) addToolTip(widget, element) gbb.addButton(widget) gb.layout().addWidget(widget, count//cols, count%cols) count += 1 # save widget self.rb[id][eid] = widget # self.rbTypes.append(eid) # self.rbNames.append(wid) # shortcut label if 'shortcut' in element.keys(): widget = QtWidgets.QLabel(None) widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Preferred, policy.Preferred)) widget.setText(f"[{element['shortcut']}]") gb.layout().addWidget(widget, count//cols, count%cols) count += 1 except KeyError as e: print(f"KeyError: {e}") if 'add_clear' in tconf.keys() and tconf['add_clear'] is True: widget = QtWidgets.QPushButton(None) widget.setObjectName(f"pb_clear_{id}") widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Minimum, policy.Fixed)) text = f"Clear" if 'clear_shortcut' in tconf.keys(): text += f" [{tconf['clear_shortcut']}]" widget.setText(text) widget.clicked.connect(lambda: self.clear_ButtonGroup(gbb)) gb.layout().addWidget(widget, count//cols, count%cols, 1, cols) self.rbg[id] = gbb gb = widgets.RadioButtonGroup(self, tconf, wpol) else: print(f"{tconf['type']} not implemented") # gb_img.layout().addWidget(gb, wcount//wcols, wcount%wcols) frame.layout().addWidget(gb, wcount//wcols, wcount%wcols) wcount += 1 except: raise # Dynamic COLUMNS utils.IDS['FILE'] = list(df.columns) Loading Loading @@ -487,7 +406,8 @@ class Ui(QtWidgets.QMainWindow): # radiobuttons for id, bg in self.rbg.items(): self.clear_ButtonGroup(bg) bg.clear_ButtonGroup() # self.clear_ButtonGroup(bg) selected = item[id].item() if selected in self.rb[id].keys(): # idChecked = self.rbNames[self.rbTypes.index(selected)] # refactor rbTypes and rbNames? Loading Loading @@ -545,16 +465,6 @@ class Ui(QtWidgets.QMainWindow): self.fileList.selectRow(index-1) def clear_ButtonGroup(self, bg:QtWidgets.QButtonGroup) -> None: # for i, cb in enumerate(self.rbNames): # self.rb[self.rbTypes[i]].setAutoExclusive(False) # self.rb[self.rbTypes[i]].setChecked(False) # self.rb[self.rbTypes[i]].setAutoExclusive(True) if bg.checkedButton() is not None: bg.setExclusive(False) bg.checkedButton().setChecked(False) bg.setExclusive(True) # Actions helpers def exit(self) -> None: Loading Loading @@ -648,62 +558,3 @@ class Ui(QtWidgets.QMainWindow): def splitterResizeEvent(self, pos, index) -> None: # Re-draw image: self.showImage(self.imgPath) # Widget ops def newGroupBox(id:str, name:str, policy:QtWidgets.QSizePolicy) -> QtWidgets.QGroupBox: gb = QtWidgets.QGroupBox(name) gb.setObjectName(f"gb_{id}") gb.setSizePolicy(policy) #gb.setMinimumSize(50, 150) gb.setLayout(QtWidgets.QGridLayout()) return gb def addToolTip(widget: QtWidgets.QWidget, element:dict) -> None: try: widget.setToolTip(f"{element['description']}") except KeyError as e: print(f"KeyError: {e}") def addTextBoxTexts(widget: QtWidgets.QPlainTextEdit, element:dict) -> None: shortcut = None try: shortcut = element['shortcut'] except KeyError as e: print(f"KeyError: {e}") finally: if shortcut is None: widget.setPlaceholderText(f"Press [Enter] to save, and [Esc] to discard.") else: widget.setPlaceholderText(f"Press [{shortcut}] to insert comments. Press [Enter] to save, and [Esc] to discard.") # add shortcut ws = QtWidgets.QShortcut(shortcut, widget) ws.activated.connect(widget.setFocus) def addCheckBoxTexts(widget: QtWidgets.QCheckBox, element:dict) -> None: id, name, shortcut = None, None, None try: id, name, shortcut = element['id'], element['name'], element['shortcut'] except KeyError as e: if name is None: name = id.capitalize() print(f"KeyError: {e}") finally: if shortcut is None: widget.setText(name) else: widget.setText(f"[{shortcut}] {name}") widget.setShortcut(shortcut) def addRadioButtonTexts(widget: QtWidgets.QRadioButton, element:dict) -> None: id, name, shortcut = None, None, None try: id, name, shortcut = element['id'], element['name'], element['shortcut'] except KeyError as e: if name is None: name = id.capitalize() print(f"KeyError: {e}") finally: widget.setText(name) if shortcut is not None: widget.setShortcut(shortcut) No newline at end of file src/widgets.py +228 −2 Original line number Diff line number Diff line from PyQt5 import QtWidgets import typing from PyQt5 import QtCore, QtWidgets from PyQt5.QtCore import Qt import pandas as pd import numpy as np Loading Loading @@ -156,3 +157,228 @@ class StaticImage(QtWidgets.QLabel): w = self.width() h = self.height() self.setPixmap(pixmap.scaled(w, h, Qt.KeepAspectRatio, Qt.SmoothTransformation)) class BaseWidgetGroup(QtWidgets.QGroupBox): def __init__(self, wconf:dict, wpolicy:QtWidgets.QSizePolicy) -> QtWidgets.QGroupBox: cols = 2 # default cols inside each widget count = 0 # pointer to current col inside widget if 'id' not in wconf.keys(): raise KeyError('id is mandatory') # check basic define params id:str = wconf['id'] name = id.capitalize() if 'name' in wconf.keys(): name:str = wconf['name'] # if 'type' not in wconf.keys(): # print(f"type of {id}:{name} not specified") # continue # # size policy # if wcount%wcols == 0: # first column # wpol = QtWidgets.QSizePolicy(policy.Preferred, policy.Preferred) # elif wcols-(wcount%wcols) == 1: # last column # wpol = QtWidgets.QSizePolicy(policy.Maximum, policy.Preferred) # else: # wpol = QtWidgets.QSizePolicy(policy.Minimum, policy.Preferred) super(BaseWidgetGroup, self).__init__(name) self.setObjectName(f"gb_{id}") self.setSizePolicy(wpolicy) #gb.setMinimumSize(50, 150) self.setLayout(QtWidgets.QGridLayout()) self._id = id self._cols = cols self._count = count def addToolTip(self, widget: QtWidgets.QWidget, element:dict) -> None: try: widget.setToolTip(f"{element['description']}") except KeyError as e: print(f"KeyError: {e}") def addTexts(widget:any, element:dict) -> None: Warning("Implemented in each child") class CheckBoxGroup(BaseWidgetGroup): def __init__(self, parent, wconf:dict, wpolicy:QtWidgets.QSizePolicy, *args, **kwargs): super(CheckBoxGroup, self).__init__(wconf, wpolicy, *args, **kwargs) cols = self._cols count = self._count if 'ncolumns' in wconf.keys(): cols = wconf['ncolumns'] id = self._id if 'elements' in wconf and len(wconf['elements']) > 0: parent.cb[id] = {} for element in wconf['elements']: try: eid = element['id'] wid = f"cb_{eid}" # add checkbox widget = QtWidgets.QCheckBox(None) widget.setObjectName(wid) widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Minimum, policy.Fixed)) self.addTexts(widget, element) self.addToolTip(widget, element) self.layout().addWidget(widget, count//cols, count%cols) count += 1 # save widget parent.cb[id][eid] = widget # self.cbColumns.append(eid) # self.cbNames.append(wid) except KeyError as e: print(f"KeyError: {e}") def addTexts(self, widget: QtWidgets.QCheckBox, element:dict) -> None: id, name, shortcut = None, None, None try: id, name, shortcut = element['id'], element['name'], element['shortcut'] except KeyError as e: if name is None: name = id.capitalize() print(f"KeyError: {e}") finally: if shortcut is None: widget.setText(name) else: widget.setText(f"[{shortcut}] {name}") widget.setShortcut(shortcut) class CustomButtonGroup(QtWidgets.QButtonGroup): def __init__(self, id) -> None: super().__init__() self.setObjectName(f"gbb_{id}") def clear_ButtonGroup(self) -> None: if self.checkedButton() is not None: self.setExclusive(False) self.checkedButton().setChecked(False) self.setExclusive(True) class RadioButtonGroup(BaseWidgetGroup): def __init__(self, parent, wconf:dict, wpolicy:QtWidgets.QSizePolicy, *args, **kwargs): super(RadioButtonGroup, self).__init__(wconf, wpolicy, *args, **kwargs) cols = self._cols count = self._count if 'ncolumns' in wconf.keys(): cols = wconf['ncolumns']*2 # *2 -> shortcut and name in 2 rows id = self._id gbb = CustomButtonGroup(id) if 'elements' in wconf and len(wconf['elements']) > 0: parent.rb[id] = {} for element in wconf['elements']: element:dict try: eid = element['id'] wid = f"rb_{eid}" # radiobutton widget = QtWidgets.QRadioButton(None) widget.setObjectName(wid) widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Minimum, policy.Fixed)) self.addTexts(widget, element) self.addToolTip(widget, element) gbb.addButton(widget) self.layout().addWidget(widget, count//cols, count%cols) count += 1 # save widget parent.rb[id][eid] = widget # self.rbTypes.append(eid) # self.rbNames.append(wid) # shortcut label if 'shortcut' in element.keys(): widget = QtWidgets.QLabel(None) widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Preferred, policy.Preferred)) widget.setText(f"[{element['shortcut']}]") self.layout().addWidget(widget, count//cols, count%cols) count += 1 except KeyError as e: print(f"KeyError: {e}") if 'add_clear' in wconf.keys() and wconf['add_clear'] is True: widget = QtWidgets.QPushButton(None) widget.setObjectName(f"pb_clear_{id}") widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Minimum, policy.Fixed)) text = f"Clear" if 'clear_shortcut' in wconf.keys(): shortcut = wconf['clear_shortcut'] text += f" [{shortcut}]" widget.setText(text) if shortcut is not None: widget.setShortcut(shortcut) widget.clicked.connect(gbb.clear_ButtonGroup) self.layout().addWidget(widget, count//cols, count%cols, 1, cols) parent.rbg[id] = gbb def addTexts(self, widget: QtWidgets.QRadioButton, element:dict) -> None: id, name, shortcut = None, None, None try: id, name, shortcut = element['id'], element['name'], element['shortcut'] except KeyError as e: if name is None: name = id.capitalize() print(f"KeyError: {e}") finally: widget.setText(name) if shortcut is not None: widget.setShortcut(shortcut) class CommentBox(BaseWidgetGroup): def __init__(self, parent, wconf:dict, wpolicy:QtWidgets.QSizePolicy, *args, **kwargs): super(CommentBox, self).__init__(wconf, wpolicy, *args, **kwargs) # configure internal widget widget = QtWidgets.QPlainTextEdit(None) widget.setObjectName(f"tb_{self._id}") widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Expanding, policy.Preferred)) self.addTexts(widget, wconf) widget.installEventFilter(parent) # Set enter as save self.layout().addWidget(widget) # add to parents textbox list parent.tb[self._id] = widget def addTexts(self, widget: QtWidgets.QPlainTextEdit, element:dict) -> None: shortcut = None try: shortcut = element['shortcut'] except KeyError as e: print(f"KeyError: {e}") finally: if shortcut is None: widget.setPlaceholderText(f"Press [Enter] to save, and [Esc] to discard.") else: widget.setPlaceholderText(f"Press [{shortcut}] to insert comments. Press [Enter] to save, and [Esc] to discard.") # add shortcut ws = QtWidgets.QShortcut(shortcut, widget) ws.activated.connect(widget.setFocus) No newline at end of file Loading
src/gui.py +16 −165 Original line number Diff line number Diff line Loading @@ -50,7 +50,8 @@ class Ui(QtWidgets.QMainWindow): # Import config try: with open("config", 'r') as f: file_config = utils.args.config with open(file_config, 'r') as f: config:dict = json.loads(f.read()) except: raise Loading Loading @@ -108,8 +109,10 @@ class Ui(QtWidgets.QMainWindow): for tconf in config: tconf:dict cols = 2 # default cols inside each widget count = 0 # pointer to current col inside widget # cols = 2 # default cols inside each widget # count = 0 # pointer to current col inside widget # self._cols = cols # self._count = count try: # check basic define params if 'id' in tconf.keys(): Loading @@ -126,112 +129,28 @@ class Ui(QtWidgets.QMainWindow): # size policy if wcount%wcols == 0: # first column wpol = QtWidgets.QSizePolicy(policy.Preferred, policy.Preferred) elif wcols-(wcount%wcols) == 1: # last column elif wcount%wcols == wcols-1: # last column wpol = QtWidgets.QSizePolicy(policy.Maximum, policy.Preferred) else: wpol = QtWidgets.QSizePolicy(policy.Minimum, policy.Preferred) gb = newGroupBox(id, name, wpol) # COMMENTBOX if tconf['type'] == 'text': widget = QtWidgets.QPlainTextEdit(None) widget.setObjectName(f"tb_{id}") widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Expanding, policy.Preferred)) addTextBoxTexts(widget, tconf) widget.installEventFilter(self) # Set enter as save gb.layout().addWidget(widget) self.commentBox = widget self.tb[id] = widget gb = widgets.CommentBox(self, tconf, wpol) # CHECKBOX elif tconf['type'] == 'checkbox': if 'ncolumns' in tconf.keys(): cols = tconf['ncolumns'] if 'elements' in tconf and len(tconf['elements']) > 0: self.cb[id] = {} for element in tconf['elements']: try: eid = element['id'] wid = f"cb_{eid}" # add checkbox widget = QtWidgets.QCheckBox(None) widget.setObjectName(wid) widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Minimum, policy.Fixed)) addCheckBoxTexts(widget, element) addToolTip(widget, element) gb.layout().addWidget(widget, count//cols, count%cols) count += 1 # save widget self.cb[id][eid] = widget # self.cbColumns.append(eid) # self.cbNames.append(wid) except KeyError as e: print(f"KeyError: {e}") gb = widgets.CheckBoxGroup(self, tconf, wpol) # RADIOBUTTON TYPE elif tconf['type'] == 'radiobutton': if 'ncolumns' in tconf.keys(): cols = tconf['ncolumns']*2 # *2 -> shortcut and name in 2 rows gbb = QtWidgets.QButtonGroup() gbb.setObjectName(f"gbb_{id}") if 'elements' in tconf and len(tconf['elements']) > 0: self.rb[id] = {} for element in tconf['elements']: element:dict try: eid = element['id'] wid = f"rb_{eid}" # radiobutton widget = QtWidgets.QRadioButton(None) widget.setObjectName(wid) widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Minimum, policy.Fixed)) addRadioButtonTexts(widget, element) addToolTip(widget, element) gbb.addButton(widget) gb.layout().addWidget(widget, count//cols, count%cols) count += 1 # save widget self.rb[id][eid] = widget # self.rbTypes.append(eid) # self.rbNames.append(wid) # shortcut label if 'shortcut' in element.keys(): widget = QtWidgets.QLabel(None) widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Preferred, policy.Preferred)) widget.setText(f"[{element['shortcut']}]") gb.layout().addWidget(widget, count//cols, count%cols) count += 1 except KeyError as e: print(f"KeyError: {e}") if 'add_clear' in tconf.keys() and tconf['add_clear'] is True: widget = QtWidgets.QPushButton(None) widget.setObjectName(f"pb_clear_{id}") widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Minimum, policy.Fixed)) text = f"Clear" if 'clear_shortcut' in tconf.keys(): text += f" [{tconf['clear_shortcut']}]" widget.setText(text) widget.clicked.connect(lambda: self.clear_ButtonGroup(gbb)) gb.layout().addWidget(widget, count//cols, count%cols, 1, cols) self.rbg[id] = gbb gb = widgets.RadioButtonGroup(self, tconf, wpol) else: print(f"{tconf['type']} not implemented") # gb_img.layout().addWidget(gb, wcount//wcols, wcount%wcols) frame.layout().addWidget(gb, wcount//wcols, wcount%wcols) wcount += 1 except: raise # Dynamic COLUMNS utils.IDS['FILE'] = list(df.columns) Loading Loading @@ -487,7 +406,8 @@ class Ui(QtWidgets.QMainWindow): # radiobuttons for id, bg in self.rbg.items(): self.clear_ButtonGroup(bg) bg.clear_ButtonGroup() # self.clear_ButtonGroup(bg) selected = item[id].item() if selected in self.rb[id].keys(): # idChecked = self.rbNames[self.rbTypes.index(selected)] # refactor rbTypes and rbNames? Loading Loading @@ -545,16 +465,6 @@ class Ui(QtWidgets.QMainWindow): self.fileList.selectRow(index-1) def clear_ButtonGroup(self, bg:QtWidgets.QButtonGroup) -> None: # for i, cb in enumerate(self.rbNames): # self.rb[self.rbTypes[i]].setAutoExclusive(False) # self.rb[self.rbTypes[i]].setChecked(False) # self.rb[self.rbTypes[i]].setAutoExclusive(True) if bg.checkedButton() is not None: bg.setExclusive(False) bg.checkedButton().setChecked(False) bg.setExclusive(True) # Actions helpers def exit(self) -> None: Loading Loading @@ -648,62 +558,3 @@ class Ui(QtWidgets.QMainWindow): def splitterResizeEvent(self, pos, index) -> None: # Re-draw image: self.showImage(self.imgPath) # Widget ops def newGroupBox(id:str, name:str, policy:QtWidgets.QSizePolicy) -> QtWidgets.QGroupBox: gb = QtWidgets.QGroupBox(name) gb.setObjectName(f"gb_{id}") gb.setSizePolicy(policy) #gb.setMinimumSize(50, 150) gb.setLayout(QtWidgets.QGridLayout()) return gb def addToolTip(widget: QtWidgets.QWidget, element:dict) -> None: try: widget.setToolTip(f"{element['description']}") except KeyError as e: print(f"KeyError: {e}") def addTextBoxTexts(widget: QtWidgets.QPlainTextEdit, element:dict) -> None: shortcut = None try: shortcut = element['shortcut'] except KeyError as e: print(f"KeyError: {e}") finally: if shortcut is None: widget.setPlaceholderText(f"Press [Enter] to save, and [Esc] to discard.") else: widget.setPlaceholderText(f"Press [{shortcut}] to insert comments. Press [Enter] to save, and [Esc] to discard.") # add shortcut ws = QtWidgets.QShortcut(shortcut, widget) ws.activated.connect(widget.setFocus) def addCheckBoxTexts(widget: QtWidgets.QCheckBox, element:dict) -> None: id, name, shortcut = None, None, None try: id, name, shortcut = element['id'], element['name'], element['shortcut'] except KeyError as e: if name is None: name = id.capitalize() print(f"KeyError: {e}") finally: if shortcut is None: widget.setText(name) else: widget.setText(f"[{shortcut}] {name}") widget.setShortcut(shortcut) def addRadioButtonTexts(widget: QtWidgets.QRadioButton, element:dict) -> None: id, name, shortcut = None, None, None try: id, name, shortcut = element['id'], element['name'], element['shortcut'] except KeyError as e: if name is None: name = id.capitalize() print(f"KeyError: {e}") finally: widget.setText(name) if shortcut is not None: widget.setShortcut(shortcut) No newline at end of file
src/widgets.py +228 −2 Original line number Diff line number Diff line from PyQt5 import QtWidgets import typing from PyQt5 import QtCore, QtWidgets from PyQt5.QtCore import Qt import pandas as pd import numpy as np Loading Loading @@ -156,3 +157,228 @@ class StaticImage(QtWidgets.QLabel): w = self.width() h = self.height() self.setPixmap(pixmap.scaled(w, h, Qt.KeepAspectRatio, Qt.SmoothTransformation)) class BaseWidgetGroup(QtWidgets.QGroupBox): def __init__(self, wconf:dict, wpolicy:QtWidgets.QSizePolicy) -> QtWidgets.QGroupBox: cols = 2 # default cols inside each widget count = 0 # pointer to current col inside widget if 'id' not in wconf.keys(): raise KeyError('id is mandatory') # check basic define params id:str = wconf['id'] name = id.capitalize() if 'name' in wconf.keys(): name:str = wconf['name'] # if 'type' not in wconf.keys(): # print(f"type of {id}:{name} not specified") # continue # # size policy # if wcount%wcols == 0: # first column # wpol = QtWidgets.QSizePolicy(policy.Preferred, policy.Preferred) # elif wcols-(wcount%wcols) == 1: # last column # wpol = QtWidgets.QSizePolicy(policy.Maximum, policy.Preferred) # else: # wpol = QtWidgets.QSizePolicy(policy.Minimum, policy.Preferred) super(BaseWidgetGroup, self).__init__(name) self.setObjectName(f"gb_{id}") self.setSizePolicy(wpolicy) #gb.setMinimumSize(50, 150) self.setLayout(QtWidgets.QGridLayout()) self._id = id self._cols = cols self._count = count def addToolTip(self, widget: QtWidgets.QWidget, element:dict) -> None: try: widget.setToolTip(f"{element['description']}") except KeyError as e: print(f"KeyError: {e}") def addTexts(widget:any, element:dict) -> None: Warning("Implemented in each child") class CheckBoxGroup(BaseWidgetGroup): def __init__(self, parent, wconf:dict, wpolicy:QtWidgets.QSizePolicy, *args, **kwargs): super(CheckBoxGroup, self).__init__(wconf, wpolicy, *args, **kwargs) cols = self._cols count = self._count if 'ncolumns' in wconf.keys(): cols = wconf['ncolumns'] id = self._id if 'elements' in wconf and len(wconf['elements']) > 0: parent.cb[id] = {} for element in wconf['elements']: try: eid = element['id'] wid = f"cb_{eid}" # add checkbox widget = QtWidgets.QCheckBox(None) widget.setObjectName(wid) widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Minimum, policy.Fixed)) self.addTexts(widget, element) self.addToolTip(widget, element) self.layout().addWidget(widget, count//cols, count%cols) count += 1 # save widget parent.cb[id][eid] = widget # self.cbColumns.append(eid) # self.cbNames.append(wid) except KeyError as e: print(f"KeyError: {e}") def addTexts(self, widget: QtWidgets.QCheckBox, element:dict) -> None: id, name, shortcut = None, None, None try: id, name, shortcut = element['id'], element['name'], element['shortcut'] except KeyError as e: if name is None: name = id.capitalize() print(f"KeyError: {e}") finally: if shortcut is None: widget.setText(name) else: widget.setText(f"[{shortcut}] {name}") widget.setShortcut(shortcut) class CustomButtonGroup(QtWidgets.QButtonGroup): def __init__(self, id) -> None: super().__init__() self.setObjectName(f"gbb_{id}") def clear_ButtonGroup(self) -> None: if self.checkedButton() is not None: self.setExclusive(False) self.checkedButton().setChecked(False) self.setExclusive(True) class RadioButtonGroup(BaseWidgetGroup): def __init__(self, parent, wconf:dict, wpolicy:QtWidgets.QSizePolicy, *args, **kwargs): super(RadioButtonGroup, self).__init__(wconf, wpolicy, *args, **kwargs) cols = self._cols count = self._count if 'ncolumns' in wconf.keys(): cols = wconf['ncolumns']*2 # *2 -> shortcut and name in 2 rows id = self._id gbb = CustomButtonGroup(id) if 'elements' in wconf and len(wconf['elements']) > 0: parent.rb[id] = {} for element in wconf['elements']: element:dict try: eid = element['id'] wid = f"rb_{eid}" # radiobutton widget = QtWidgets.QRadioButton(None) widget.setObjectName(wid) widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Minimum, policy.Fixed)) self.addTexts(widget, element) self.addToolTip(widget, element) gbb.addButton(widget) self.layout().addWidget(widget, count//cols, count%cols) count += 1 # save widget parent.rb[id][eid] = widget # self.rbTypes.append(eid) # self.rbNames.append(wid) # shortcut label if 'shortcut' in element.keys(): widget = QtWidgets.QLabel(None) widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Preferred, policy.Preferred)) widget.setText(f"[{element['shortcut']}]") self.layout().addWidget(widget, count//cols, count%cols) count += 1 except KeyError as e: print(f"KeyError: {e}") if 'add_clear' in wconf.keys() and wconf['add_clear'] is True: widget = QtWidgets.QPushButton(None) widget.setObjectName(f"pb_clear_{id}") widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Minimum, policy.Fixed)) text = f"Clear" if 'clear_shortcut' in wconf.keys(): shortcut = wconf['clear_shortcut'] text += f" [{shortcut}]" widget.setText(text) if shortcut is not None: widget.setShortcut(shortcut) widget.clicked.connect(gbb.clear_ButtonGroup) self.layout().addWidget(widget, count//cols, count%cols, 1, cols) parent.rbg[id] = gbb def addTexts(self, widget: QtWidgets.QRadioButton, element:dict) -> None: id, name, shortcut = None, None, None try: id, name, shortcut = element['id'], element['name'], element['shortcut'] except KeyError as e: if name is None: name = id.capitalize() print(f"KeyError: {e}") finally: widget.setText(name) if shortcut is not None: widget.setShortcut(shortcut) class CommentBox(BaseWidgetGroup): def __init__(self, parent, wconf:dict, wpolicy:QtWidgets.QSizePolicy, *args, **kwargs): super(CommentBox, self).__init__(wconf, wpolicy, *args, **kwargs) # configure internal widget widget = QtWidgets.QPlainTextEdit(None) widget.setObjectName(f"tb_{self._id}") widget.setSizePolicy(QtWidgets.QSizePolicy(policy.Expanding, policy.Preferred)) self.addTexts(widget, wconf) widget.installEventFilter(parent) # Set enter as save self.layout().addWidget(widget) # add to parents textbox list parent.tb[self._id] = widget def addTexts(self, widget: QtWidgets.QPlainTextEdit, element:dict) -> None: shortcut = None try: shortcut = element['shortcut'] except KeyError as e: print(f"KeyError: {e}") finally: if shortcut is None: widget.setPlaceholderText(f"Press [Enter] to save, and [Esc] to discard.") else: widget.setPlaceholderText(f"Press [{shortcut}] to insert comments. Press [Enter] to save, and [Esc] to discard.") # add shortcut ws = QtWidgets.QShortcut(shortcut, widget) ws.activated.connect(widget.setFocus) No newline at end of file