class RigViewer(QWidget): def __init__(self): super().__init__() rescanButton = QPushButton("Rescan") rescanButton.clicked.connect(self.Rescan) self._deviceLayout = QVBoxLayout() self._deviceLayout.addWidget(rescanButton) self.setLayout(self._deviceLayout) self._deviceItems: List[DeviceItem] = [] self.UpdateList() def Rescan(self): AppGlobals.Rig().Rescan() self.UpdateList() def UpdateList(self): for item in self._deviceItems: item.deleteLater() self._deviceItems = [] for device in AppGlobals.Rig().savedDevices: if device.IsDeviceAvailable() and \ device not in [deviceItem.device for deviceItem in self._deviceItems]: newItem = DeviceItem(device) newItem.numberChanged.connect(self.SortList) self._deviceItems.append(newItem) self._deviceLayout.addWidget(newItem) self.SortList() def SortList(self): self._deviceItems.sort( key=lambda deviceItem: deviceItem.device.startNumber) for item in self._deviceItems: self._deviceLayout.removeWidget(item) for item in self._deviceItems: self._deviceLayout.addWidget(item)
class ArrayRequirementEditor: def __init__(self, parent: QWidget, parent_layout: QVBoxLayout, line_layout: QHBoxLayout, resource_database: ResourceDatabase, requirement: RequirementArrayBase): self._editors = [] self.resource_database = resource_database self._array_type = type(requirement) # the parent is added to a layout which is added to parent_layout, so we index = parent_layout.indexOf(line_layout) + 1 self.group_box = QGroupBox(parent) self.group_box.setStyleSheet("QGroupBox { margin-top: 2px; }") parent_layout.insertWidget(index, self.group_box) self.item_layout = QVBoxLayout(self.group_box) self.item_layout.setContentsMargins(8, 2, 2, 6) self.item_layout.setAlignment(Qt.AlignTop) self.new_item_button = QPushButton(self.group_box) self.new_item_button.setMaximumWidth(75) self.new_item_button.setText("New Row") self.new_item_button.clicked.connect(self.new_item) self.comment_text_box = QLineEdit(parent) self.comment_text_box.setText(requirement.comment or "") self.comment_text_box.setPlaceholderText("Comment") line_layout.addWidget(self.comment_text_box) for item in requirement.items: self._create_item(item) self.item_layout.addWidget(self.new_item_button) def _create_item(self, item: Requirement): def on_remove(): self._editors.remove(nested_editor) nested_editor.deleteLater() nested_editor = RequirementEditor(self.group_box, self.item_layout, self.resource_database, on_remove=on_remove) nested_editor.create_specialized_editor(item) self._editors.append(nested_editor) def new_item(self): self._create_item( _create_default_resource_requirement(self.resource_database)) self.item_layout.removeWidget(self.new_item_button) self.item_layout.addWidget(self.new_item_button) def deleteLater(self): self.group_box.deleteLater() self.comment_text_box.deleteLater() for editor in self._editors: editor.deleteLater() self.new_item_button.deleteLater() @property def current_requirement(self) -> RequirementArrayBase: comment = self.comment_text_box.text().strip() if comment == "": comment = None return self._array_type( [editor.current_requirement for editor in self._editors], comment=comment, )
class ParameterEditor(QWidget): onParametersChanged = Signal() def __init__(self, program: Program): super().__init__() self._program = program parametersLabel = QLabel("Parameters") newParameterButton = QPushButton("Add Parameter") newParameterButton.clicked.connect(self.AddParameter) layout = QVBoxLayout() titleLayout = QHBoxLayout() titleLayout.addWidget(parametersLabel) titleLayout.addWidget(newParameterButton) layout.addLayout(titleLayout) self._listArea = QScrollArea() self._listArea.setWidgetResizable(True) self._listArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._listArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) layout.addWidget(self._listArea, stretch=1) listWidget = QWidget() self._itemLayout = QVBoxLayout() self._itemLayout.setAlignment(Qt.AlignTop) listWidget.setLayout(self._itemLayout) self.setLayout(layout) self._listArea.setWidget(listWidget) self.items: List[ParameterEditorItem] = [] self._temporaryParameters = program.parameters.copy() self.Populate() def AddParameter(self): newParameter = Parameter() self._temporaryParameters.append(newParameter) self.onParametersChanged.emit() self.AddToList(newParameter) def Populate(self): for parameter in self._temporaryParameters: self.AddToList(parameter) self._listArea.updateGeometry() def AddToList(self, parameter: Parameter): newItem = ParameterEditorItem(parameter) newItem.onRemoveParameter.connect(self.RemoveParameter) newItem.onMoveParameterUp.connect(self.MoveParameterUp) newItem.onMoveParameterDown.connect(self.MoveParameterDown) newItem.onChanged.connect(self.onParametersChanged.emit) self._itemLayout.addWidget(newItem) self.items.append(newItem) def RemoveFromList(self, parameter: Parameter): item = [item for item in self.items if item.parameter is parameter] item[0].deleteLater() self.items.remove(item[0]) def RemoveParameter(self, parameter: Parameter): self._temporaryParameters.remove(parameter) self.onParametersChanged.emit() self.RemoveFromList(parameter) def Reorder(self, parameter: Parameter, newPosition: int): item = [item for item in self.items if item.parameter is parameter][0] self._itemLayout.removeWidget(item) self._itemLayout.insertWidget(newPosition, item) self.items.remove(item) self.items.insert(newPosition, item) self._temporaryParameters.remove(parameter) self._temporaryParameters.insert(newPosition, parameter) self.onParametersChanged.emit() def MoveParameterUp(self, parameter: Parameter): index = self._temporaryParameters.index(parameter) self.Reorder(parameter, index - 1) def MoveParameterDown(self, parameter: Parameter): index = self._temporaryParameters.index(parameter) self.Reorder(parameter, index + 1) def Save(self): self._program.parameters = self._temporaryParameters self._temporaryParameters = self._program.parameters.copy() for item in self.items: item.UpdateParameter()
class ValidationPanel(logging.Handler): table_headers = ["Validator", "Group", "Field", "Value", "Operator"] def __init__(self, main_window): super().__init__() self.layout = QVBoxLayout() # setup tables self.tables = {} self.setup_tables(main_window.config) main_window.config_changed.connect(self.setup_tables) def setup_tables(self, config): for table in self.tables.values(): if table is not None: self.layout.removeWidget(table) table.deleteLater() if config.has_acc: self.tables["acc"] = ValidationTable("Account") else: self.tables["acc"] = None if config.has_loc: self.tables["loc"] = ValidationTable("Location") else: self.tables["loc"] = None if config.has_ri: self.tables["ri"] = ValidationTable("Reinsurance") else: self.tables["ri"] = None for table in self.tables.values(): if table is not None: self.layout.addWidget(table) def emit(self, record): parsed = yaml.safe_load(record.msg) if not isinstance(parsed[0], dict): return log_entry: ValidationLogEntry = parsed[0] validations: ValidationResult = parsed[0]["validations"] rows = [] row = ["", "", "", "", ""] for validation in validations: row[0] = validation["name"] for entry in validation["entries"]: groups = entry.get("groups", None) or {} row[1] = ", ".join( map(lambda g: f"{g[0]}={g[1]}", groups.items()) ) row[2] = entry.get("field") or "" row[3] = entry.get("error") or entry.get("value") or "" row[4] = str(validation.get("operator")) rows.append(row) row = ["", "", "", "", ""] self.tables[log_entry["file_type"]].redraw_table(rows) def clear(self): for table in self.tables.values(): if table is not None: table.clear()