class ArrayRequirementEditor: def __init__(self, parent: QWidget, parent_layout: QVBoxLayout, resource_database: ResourceDatabase, requirement: Union[RequirementOr, RequirementAnd]): self._editors = [] self.resource_database = resource_database self._array_type = type(requirement) self.group_box = QGroupBox(parent) self.group_box.setStyleSheet("QGroupBox { margin-top: 2px; }") parent_layout.addWidget(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) 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() for editor in self._editors: editor.deleteLater() self.new_item_button.deleteLater() @property def current_requirement(self) -> Union[RequirementOr, RequirementAnd]: return self._array_type( [editor.current_requirement for editor in self._editors])
class ItemRow: def __init__(self, parent: QWidget, parent_layout: QVBoxLayout, resource_database: ResourceDatabase, item: ResourceRequirement, rows: List["ItemRow"]): self.parent = parent self.resource_database = resource_database self._rows = rows rows.append(self) self.layout = QHBoxLayout() self.layout.setObjectName(f"Box layout for {item.resource.long_name}") parent_layout.addLayout(self.layout) self.resource_type_combo = _create_resource_type_combo( item.resource.resource_type, parent) self.resource_type_combo.setMinimumWidth(75) self.resource_type_combo.setMaximumWidth(75) self.resource_name_combo = _create_resource_name_combo( self.resource_database, item.resource.resource_type, item.resource, self.parent) self.negate_combo = QComboBox(parent) self.negate_combo.addItem("≥", False) self.negate_combo.addItem("<", True) self.negate_combo.setCurrentIndex(int(item.negate)) self.negate_combo.setMinimumWidth(40) self.negate_combo.setMaximumWidth(40) self.amount_edit = QLineEdit(parent) self.amount_edit.setValidator(QIntValidator(1, 10000)) self.amount_edit.setText(str(item.amount)) self.amount_edit.setMinimumWidth(45) self.amount_edit.setMaximumWidth(45) self.remove_button = QPushButton(parent) self.remove_button.setText("X") self.remove_button.setMaximumWidth(20) self.layout.addWidget(self.resource_type_combo) self.layout.addWidget(self.resource_name_combo) self.layout.addWidget(self.negate_combo) self.layout.addWidget(self.amount_edit) self.layout.addWidget(self.remove_button) self.resource_type_combo.currentIndexChanged.connect(self._update_type) self.remove_button.clicked.connect(self._delete_row) def _update_type(self): old_combo = self.resource_name_combo self.resource_name_combo = _create_resource_name_combo( self.resource_database, self.resource_type_combo.currentData(), None, self.parent) self.layout.replaceWidget(old_combo, self.resource_name_combo) old_combo.deleteLater() def _delete_row(self): self.resource_type_combo.deleteLater() self.resource_name_combo.deleteLater() self.negate_combo.deleteLater() self.amount_edit.deleteLater() self.remove_button.deleteLater() self.layout.deleteLater() self._rows.remove(self) @property def current_individual(self) -> ResourceRequirement: return ResourceRequirement(self.resource_name_combo.currentData(), int(self.amount_edit.text()), self.negate_combo.currentData())
class mainScreen(QWidget): def __init__(self): QWidget.__init__(self) self.driveLabel = QLabel('Serial Number:') self.sizeLabel = QLabel('Size:') self.statusLabel = QLabel('Status:') self.partitionLabel = QLabel('Partitions:') self.indexLabel = QLabel('Index:') self.checkLabel = QLabel('Master:') self.progress = QProgressBar() self.wipeButton = QPushButton('Wipe') self.cancelButton = QPushButton('Cancel') self.bottomStatus = QLabel('Ready to Wipe') self.refactor = QPushButton('Refactor') # TODO: Add a group box to make this look better # EDIT TODO: Use GUI application to build a really good looking app! # TODO: Add selection of wipe method, verification, and certificate output self.layout = QGridLayout() self.layout.addWidget(self.driveLabel, 0, 0, 1, 2) self.layout.addWidget(self.sizeLabel, 0, 3) self.layout.addWidget(self.statusLabel, 0, 5, 1, 2) self.layout.addWidget(self.partitionLabel, 0, 7) self.layout.addWidget(self.indexLabel, 0, 8) self.layout.addWidget(self.checkLabel, 0, 9) self.layout.addWidget(self.progress, 26, 0, 1, 10) self.layout.addWidget(self.wipeButton, 27, 2, 1, 2) self.layout.addWidget(self.cancelButton, 27, 4, 1, 2) self.layout.addWidget(self.bottomStatus, 28, 0, 1, 10) self.layout.addWidget(self.refactor, 27, 0, 1, 2) self.drivesSet = 0 self.driveNames = [] self.driveStatus = [] self.driveSize = [] self.drivePartitions = [] self.driveIndex = [] self.masterRadio = [] self.master = self.getMaster() self.progressInt = 10 for i in range(25): toAdd = QLabel('') self.driveNames.append(toAdd) toAdd2 = QLabel('') self.driveSize.append(toAdd2) toAdd3 = QLabel('') self.driveStatus.append(toAdd3) toAdd4 = QLabel('') self.drivePartitions.append(toAdd4) toAdd5 = QLabel('') self.driveIndex.append(toAdd5) self.setWindowTitle('Auto Kill Disk') #icon = #self.setWindowIcon() self.wipeButton.clicked.connect(self.startButtonClicked) self.refactor.clicked.connect(self.refactorDrives) self.worker = refactorThread() self.worker.refSig.connect(self.refactorDrives) self.worker.start() def addDrive(self, name, status, size, partitions, index): self.driveNames[self.drivesSet].setText(name) self.driveStatus[self.drivesSet].setText(status) self.driveSize[self.drivesSet].setText(size + ' GB') self.drivePartitions[self.drivesSet].setText(str(partitions)) self.driveIndex[self.drivesSet].setText(str(index)) toAdd = QRadioButton() self.masterRadio.append(toAdd) self.layout.addWidget(self.masterRadio[self.drivesSet], self.drivesSet + 1, 9) if int(index) == int(self.master): self.masterRadio[self.drivesSet].setChecked(True) self.drivesSet += 1 def addPayloadNames(self): for i in range(25): self.layout.addWidget(self.driveNames[i], i + 1, 0, 1, 2) self.layout.addWidget(self.driveStatus[i], i + 1, 5, 1, 2) self.layout.addWidget(self.driveSize[i], i + 1, 3) self.layout.addWidget(self.drivePartitions[i], i + 1, 7) self.layout.addWidget(self.driveIndex[i], i + 1, 8) def resetSpacing(self): self.layout.setContentsMargins(10, 10, 0, 10) def startButtonClicked(self): self.bottomStatus.setText('Are you sure you want to wipe?') self.confirmButton = QPushButton('Confirm') self.layout.addWidget(self.confirmButton, 27, 6, 1, 2) self.setLayout(self.layout) self.confirmButton.clicked.connect(self.getIndex) def setText(self): self.bottomStatus.setText('Ready to Wipe') def getIndex(self): self.confirmButton.deleteLater() self.bottomStatus.setText('Starting Wipe') self.indexToWipe = [] self.serialToWipe = [] for i in range(len(self.masterRadio)): if not self.masterRadio[i].isChecked(): self.indexToWipe.append(self.index[i]) self.serialToWipe.append(self.serial[i]) if len(self.indexToWipe) == len(self.index): self.bottomStatus.setText('Error: No master drive selected!') self.refactorDrives() t = Timer(3, self.setText) t.start() return None elif len(self.indexToWipe) == 0: self.refactorDrives() self.bottomStatus.setText('No drives available to wipe!') t = Timer(3, self.setText) t.start() else: serialString = self.serialToWipe[0] for i in range(1, len(self.serialToWipe)): serialString += ', ' + self.serialToWipe[i] self.bottomStatus.setText('Wiping Drives:' + serialString) self.progress.setValue(self.progressInt) for i in range(len(self.masterRadio)): # TODO: Figure out which index is the master so we don't wipe it if self.masterRadio[i].isChecked(): self.driveStatus[i].setText('MASTER') else: self.driveStatus[i].setText('WIPING') wipeDrives(self, self.indexToWipe) def refactorDrives(self): pythoncom.CoInitialize() for i in range(len(self.driveNames)): self.driveNames[i].setText('') self.driveStatus[i].setText('') self.driveSize[i].setText('') self.drivePartitions[i].setText('') self.driveIndex[i].setText('') for i in range(len(self.masterRadio)): self.masterRadio[i].deleteLater() self.setLayout(self.layout) del self.masterRadio self.masterRadio = [] self.drivesSet = 0 for i in range(25): toAdd = QLabel('') self.driveNames.append(toAdd) toAdd2 = QLabel('') self.driveSize.append(toAdd2) toAdd3 = QLabel('') self.driveStatus.append(toAdd3) toAdd4 = QLabel('') self.drivePartitions.append(toAdd4) toAdd5 = QLabel('') self.driveIndex.append(toAdd5) self.addPayloadNames() self.setLayout(self.layout) getDisks(self) self.addPayloadNames() self.setLayout(self.layout) def getMaster(self): exists = os.path.isfile('config.txt') if not exists: self.bottomStatus.setText( 'Error: Config file not found. Defaulting to master drive with index 0.' ) t = Timer(5, self.setText) t.start() return 0 with open('config.txt', 'r') as fh: for line in fh: toSet = line.strip(' ') self.bottomStatus.setText('Loading complete') t = Timer(5, self.setText) t.start() return toSet
class RequirementEditor: _editor: Union[None, ResourceRequirementEditor, ArrayRequirementEditor, TemplateRequirementEditor] def __init__(self, parent: QWidget, parent_layout: QVBoxLayout, resource_database: ResourceDatabase, *, on_remove=None): self.parent = parent self.parent_layout = parent_layout self.resource_database = resource_database self._editor = None self._last_resource = None self._last_items = () self.line_layout = QHBoxLayout() self.line_layout.setAlignment(Qt.AlignLeft) self.parent_layout.addLayout(self.line_layout) if on_remove is not None: self.remove_button = QPushButton(parent) self.remove_button.setText("X") self.remove_button.setMaximumWidth(20) self.remove_button.clicked.connect(on_remove) self.line_layout.addWidget(self.remove_button) else: self.remove_button = None self.requirement_type_combo = QComboBox(parent) self.requirement_type_combo.addItem("Resource", ResourceRequirement) self.requirement_type_combo.addItem("Or", RequirementOr) self.requirement_type_combo.addItem("And", RequirementAnd) self.requirement_type_combo.addItem("Template", RequirementTemplate) self.requirement_type_combo.setMaximumWidth(75) self.requirement_type_combo.activated.connect( self._on_change_requirement_type) self.line_layout.addWidget(self.requirement_type_combo) def create_specialized_editor(self, requirement: Requirement): self.requirement_type_combo.setCurrentIndex( self.requirement_type_combo.findData(type(requirement))) if isinstance(requirement, ResourceRequirement): self._editor = ResourceRequirementEditor(self.parent, self.line_layout, self.resource_database, requirement) elif isinstance(requirement, (RequirementOr, RequirementAnd)): self._editor = ArrayRequirementEditor(self.parent, self.parent_layout, self.resource_database, requirement) elif isinstance(requirement, RequirementTemplate): self._editor = TemplateRequirementEditor(self.parent, self.line_layout, self.resource_database, requirement) else: raise RuntimeError( f"Unknown requirement type: {type(requirement)} - {requirement}" ) def _on_change_requirement_type(self): current_requirement = self.current_requirement self._editor.deleteLater() if isinstance(current_requirement, ResourceRequirement): self._last_resource = current_requirement elif isinstance(current_requirement, (RequirementOr, RequirementAnd)): self._last_items = current_requirement.items elif isinstance(current_requirement, RequirementTemplate): pass else: raise RuntimeError( f"Unknown requirement type: {type(current_requirement)} - {current_requirement}" ) new_class = self.requirement_type_combo.currentData() if new_class == ResourceRequirement: if self._last_resource is None: new_requirement = _create_default_resource_requirement( self.resource_database) else: new_requirement = self._last_resource elif new_class == RequirementTemplate: new_requirement = _create_default_template_requirement( self.resource_database) else: new_requirement = new_class(self._last_items) self.create_specialized_editor(new_requirement) def deleteLater(self): if self.remove_button is not None: self.remove_button.deleteLater() self.requirement_type_combo.deleteLater() if self._editor is not None: self._editor.deleteLater() @property def current_requirement(self) -> Requirement: return self._editor.current_requirement
def deleteButton(self, button: QPushButton): self.signalBtnDeleted.emit(button) # 发送删除信号 # self.layUp.removeWidget(button) # 移除控件 button.deleteLater() # 删除控件
class Object(): number_of_objects = 0; def __init__(self, name, ID, interaction_IDs, parent_application): Object.number_of_objects += 1 self.highlighted = False self.parent_application = parent_application self.name = name self.ID = ID self.max_number_of_interactions = 4 self.interaction = [None]*self.max_number_of_interactions self.classifier = None for index in range(0,self.max_number_of_interactions): self.interaction[index] = Interaction("Interaction {0}".format(index+1), interaction_IDs[index], parent_application) self.label = EditableLabel(self.name, self) # passes also a reference to the parent object self.btn_delete = QPushButton() self.layout = QHBoxLayout() self.icon_delete = QIcon("icons/delete_icon.jpg") self.label.setFixedSize(300, 100) self.label.setReadOnly(True) self.label.setFrame(False) self.label.setAlignment(Qt.AlignCenter) self.label.setStyleSheet(styles.objectNameLabel) # defines the style of the buttons self.btn_delete = QPushButton() self.btn_delete.setFixedSize(100, 100) self.btn_delete.setIcon(self.icon_delete) self.btn_delete.setStyleSheet(styles.calibrateButton) self.btn_delete.clicked.connect(lambda: self.parent_application.delete_object(self)) self.layout = QHBoxLayout() self.layout.addWidget(self.btn_delete) self.layout.addWidget(self.label) for interaction in self.interaction: self.layout.addWidget(interaction.button) self.layout.addSpacerItem(QSpacerItem(0,0, QSizePolicy.Expanding, QSizePolicy.Expanding)) # adds a white spacer on the right self.layout.setContentsMargins(0,0,0,0) self.layout.setSpacing(0) # changes the name of the object (actually not very useful) def set_name(self, new_name): self.name = new_name self.label.setText(new_name) # Returns an object of type "Interaction" with the corresponding ID def get_interaction_by_ID(self, interaction_ID): for interaction in self.interaction: if interaction_ID == interaction.ID: return interaction # It changes the color of the object. Useful to show that this is the active object. def set_highlighted(self, value): if value is False: self.highlighted = False self.label.setStyleSheet(styles.objectNameLabel) self.btn_delete.setStyleSheet(styles.calibrateButton) for interaction in self.interaction: if interaction.calibrated: interaction.button.setStyleSheet(styles.calibrateButton_calibrated) else: interaction.button.setStyleSheet(styles.calibrateButton) elif value is True: self.highlighted = True self.label.setStyleSheet(styles.objectNameLabel_highlighted) self.btn_delete.setStyleSheet(styles.calibrateButton_highlighted) for interaction in self.interaction: if interaction.calibrated: interaction.button.setStyleSheet(styles.calibrateButton_calibrated_highlighted) else: interaction.button.setStyleSheet(styles.calibrateButton_highlighted) else: return # Deletes the object and all the graphical elements inside it. def delete(self): Object.number_of_objects -= 1 self.btn_delete.deleteLater() self.label.deleteLater(); for interaction in self.interaction: interaction.button.deleteLater() self.layout.deleteLater() del self;