def save_to_filewriter_json(self): filename = file_dialog(True, "Save Filewriter JSON File", JSON_FILE_TYPES) if filename: dialog = QDialog() dialog.setModal(True) dialog.setLayout(QGridLayout()) command_widget = FilewriterCommandWidget() dialog.layout().addWidget(command_widget) dialog.exec_() ( nexus_file_name, broker, start_time, stop_time, service_id, abort_on_uninitialised_stream, use_swmr, ) = command_widget.get_arguments() with open(filename, "w") as file: filewriter_json_writer.generate_json( self.instrument, file, nexus_file_name=nexus_file_name, broker=broker, start_time=start_time, stop_time=stop_time, service_id=service_id, abort_uninitialised=abort_on_uninitialised_stream, use_swmr=use_swmr, )
def _open_position_dialog(self, item: FSTTreeItem): window = Ui_NodeFieldWindow() dialog = QDialog( self, Qt.WindowSystemMenuHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint) window.setupUi(dialog) dialog.setWindowTitle(item.text(0)) dialog.setModal(True) window.label.setText("Position:") if item.node._position: window.plainTextEdit.setPlainText(f"0x{item.node._position:X}") else: window.plainTextEdit.setPlainText("-1") dialog.show() if dialog.exec_() != QFileDialog.Accepted: return False, "" text = window.plainTextEdit.toPlainText() try: if text.startswith("0x"): position = int(text, 16) else: position = int(text) except ValueError: dialog = JobFailedDialog(self) dialog.setText( f"Invalid input \"{text}\" could not be converted to int") return False, dialog if position < 0: if item.node._position: item.node._position = None self.iso.pre_calc_metadata(self.iso.MaxSize - self.iso.get_auto_blob_size()) self.ui.fileSystemStartInfoTextBox.setPlainText( f"0x{item.node._fileoffset:X}") return True, "" else: newPos = min(position, self.iso.MaxSize - 4) & -4 if item.node._position != newPos: item.node._position = newPos self.iso.pre_calc_metadata(self.iso.MaxSize - self.iso.get_auto_blob_size()) self.ui.fileSystemStartInfoTextBox.setPlainText( f"0x{item.node._position:X}") return True, ""
def _open_alignment_dialog(self, item: FSTTreeItem): window = Ui_NodeFieldWindow() dialog = QDialog( self, Qt.WindowSystemMenuHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint) window.setupUi(dialog) dialog.setWindowTitle(item.text(0)) dialog.setModal(True) window.label.setText("Alignment:") if item.node._alignment: window.plainTextEdit.setPlainText(str(item.node._alignment)) else: window.plainTextEdit.setPlainText("4") dialog.show() if dialog.exec_() != QFileDialog.Accepted: return False, "" text = window.plainTextEdit.toPlainText() try: if text.startswith("0x"): alignment = int(text, 16) else: alignment = int(text) except ValueError: dialog = JobFailedDialog(self) dialog.setText( f"Invalid input \"{text}\" could not be converted to int") return False, dialog alignment = _round_up_to_power_of_2(max(4, min(alignment, 32768))) if item.node.is_file() and item.node._alignment != alignment: item.node._alignment = alignment self.iso.pre_calc_metadata(self.iso.MaxSize - self.iso.get_auto_blob_size()) self.ui.fileSystemStartInfoTextBox.setPlainText( f"0x{item.node._fileoffset:X}") if item.node.is_dir(): for child in item.node.rchildren(): child._alignment = _round_up_to_power_of_2(alignment) self.iso.pre_calc_metadata(self.iso.MaxSize - self.iso.get_auto_blob_size()) return True, ""
def notify_update(self): newestRelease = self.updater.get_newest_release() dialog = QDialog( self, Qt.WindowSystemMenuHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint) updateWindow = Ui_UpdateDialog() updateWindow.setupUi(dialog) dialog.setModal(True) updateWindow.updateLabel.setText( f"pyisotools {newestRelease.tag_name} available!") updateWindow.changelogTextEdit.setMarkdown( self.updater.compile_changelog_from(__version__)) self.updater.blockSignals(True) if dialog.exec_() == QDialog.Accepted: self.updater.view(newestRelease) self.updater.blockSignals(False)
def handle_lottoEnterButton(self): # method to handle the okay button when it is pressed def handle_okayButton(): gross_sales_value = H.char_remover(self, gross_sales.text()) instants_comm_value = H.char_remover(self, instants_comm.text()) instants_net_value = H.char_remover(self, instants_net.text()) global_temp_dict['gross sales'] = H.dollar_adder( self, gross_sales_value) global_temp_dict['instants comm'] = H.dollar_adder( self, instants_comm_value) global_temp_dict['instants net'] = H.dollar_adder( self, instants_net_value) if (gross_sales_value and instants_comm_value and instants_net_value) != None: lotto_total = gross_sales_value - instants_comm_value - instants_net_value ftd_lotto_total = H.dollar_adder(self, lotto_total) if ftd_lotto_total == '-': self.lottoEnterButton.setText('Enter Values') else: self.lottoEnterButton.setText(ftd_lotto_total) popup.accept() else: self.lottoEnterButton.setText('Enter Values') popup.reject() # method to handle the cancel button when it is pressed def handle_cancelButton(): popup.reject() # initialise the dialog popup = QDialog() popup.setWindowTitle('Enter Lotto Values') # create the widgets and connect them to functions gross_sales_label = QLabel() gross_sales_label.setText('Gross Sales') gross_sales = QLineEdit() instants_comm_label = QLabel() instants_comm_label.setText('Instants Commission') instants_comm = QLineEdit() instants_net_label = QLabel() instants_net_label.setText('Instants Net') instants_net = QLineEdit() okayButton = QPushButton('Okay') okayButton.clicked.connect(handle_okayButton) cancelButton = QPushButton('Cancel') cancelButton.clicked.connect(handle_cancelButton) # initialise values gross_sales.setText(global_temp_dict['gross sales']) instants_comm.setText(global_temp_dict['instants comm']) instants_net.setText(global_temp_dict['instants net']) # initialise the layout manager layout = QGridLayout() # add the widgets to the layout manager layout.addWidget(gross_sales_label, 0, 0) layout.addWidget(gross_sales, 0, 1) layout.addWidget(instants_comm_label, 1, 0) layout.addWidget(instants_comm, 1, 1) layout.addWidget(instants_net_label, 2, 0) layout.addWidget(instants_net, 2, 1) layout.addWidget(cancelButton, 3, 0, 1, 2) layout.addWidget(okayButton, 4, 0, 1, 2) popup.setLayout(layout) # set the dialog as modal so that the user cannot interact with the main window when the dialog is open popup.setModal(True) popup.show() popup.exec_()
def handle_lottoPayEnterButton(self): # method to handle the okay button when it is pressed def handle_okayButton(): instants_cash_value = H.char_remover(self, instants_cash.text()) prizes_paid_value = H.char_remover(self, prizes_paid.text()) global_temp_dict['instants cash'] = H.dollar_adder( self, instants_cash_value) global_temp_dict['total prizes'] = H.dollar_adder( self, prizes_paid_value) if (prizes_paid_value and instants_cash_value) != None: lotto_pay_total = prizes_paid_value - instants_cash_value ftd_lotto_pay_total = H.dollar_adder(self, lotto_pay_total) if ftd_lotto_pay_total == '-': self.lottoPayEnterButton.setText('Enter Values') else: self.lottoPayEnterButton.setText(ftd_lotto_pay_total) popup.accept() else: self.lottoPayEnterButton.setText('Enter Values') popup.reject() # method to handle the cancel button when it is pressed def handle_cancelButton(): popup.reject() # initialise the dialog popup = QDialog() popup.setWindowTitle('Enter Lotto Payout Values') # create the widgets and connect them to functions instants_cash_label = QLabel() instants_cash_label.setText('Instants Cash') instants_cash = QLineEdit() prizes_paid_label = QLabel() prizes_paid_label.setText('Total Prizes Paid') prizes_paid = QLineEdit() okayButton = QPushButton('Okay') okayButton.clicked.connect(handle_okayButton) cancelButton = QPushButton('Cancel') cancelButton.clicked.connect(handle_cancelButton) # initialise values instants_cash.setText(global_temp_dict['instants cash']) prizes_paid.setText(global_temp_dict['total prizes']) # initialise the layout manager layout = QGridLayout() # add the widgets to the layout manager layout.addWidget(prizes_paid_label, 0, 0) layout.addWidget(prizes_paid, 0, 1) layout.addWidget(instants_cash_label, 1, 0) layout.addWidget(instants_cash, 1, 1) layout.addWidget(cancelButton, 2, 0, 1, 2) layout.addWidget(okayButton, 3, 0, 1, 2) popup.setLayout(layout) # set the dialog as modal so that the user cannot interact with the main window when the dialog is open popup.setModal(True) popup.show() popup.exec_()
def handle_scratchiesPayEnterButton(self): # method to handle the okay button when it is pressed def handle_okayButton(): instants_cash_value = H.char_remover(self, instants_cash.text()) free_instants_value = H.char_remover(self, free_instants.text()) global_temp_dict['instants cash'] = H.dollar_adder( self, instants_cash_value) global_temp_dict['free instants'] = H.dollar_adder( self, free_instants_value) scratchies_pay_arr = [instants_cash_value, free_instants_value] scratchies_pay_total = 0 for value in scratchies_pay_arr: if value != None: scratchies_pay_total += value ftd_scratchies_pay_total = H.dollar_adder(self, scratchies_pay_total) if ftd_scratchies_pay_total == '-': self.scratchiesPayEnterButton.setText('Enter Values') else: self.scratchiesPayEnterButton.setText(ftd_scratchies_pay_total) popup.accept() # method to handle the cancel button when it is pressed def handle_cancelButton(): popup.reject() # initialise the dialog popup = QDialog() popup.setWindowTitle('Enter Scratchies Payout Values') # create the widgets and connect them to functions instants_cash_label = QLabel() instants_cash_label.setText('Instants Cash') instants_cash = QLineEdit() free_instants_label = QLabel() free_instants_label.setText('Free Instants') free_instants = QLineEdit() okayButton = QPushButton('Okay') okayButton.clicked.connect(handle_okayButton) cancelButton = QPushButton('Cancel') cancelButton.clicked.connect(handle_cancelButton) # initialise values instants_cash.setText(global_temp_dict['instants cash']) free_instants.setText(global_temp_dict['free instants']) # initialise the layout manager layout = QGridLayout() # add the widgets to the layout manager layout.addWidget(instants_cash_label, 0, 0) layout.addWidget(instants_cash, 0, 1) layout.addWidget(free_instants_label, 1, 0) layout.addWidget(free_instants, 1, 1) layout.addWidget(cancelButton, 2, 0, 1, 2) layout.addWidget(okayButton, 3, 0, 1, 2) popup.setLayout(layout) # set the dialog as modal so that the user cannot interact with the main window when the dialog is open popup.setModal(True) popup.show() popup.exec_()
def handle_eftEnterButton(self): # method to handle the okay button when it is pressed def handle_okayButton(): machine_1_value = H.char_remover(self, machine_1.text()) machine_2_value = H.char_remover(self, machine_2.text()) machine_3_value = H.char_remover(self, machine_3.text()) machine_prev_value = H.char_remover(self, machine_prev.text()) global_temp_dict['eftpos 1'] = H.dollar_adder( self, machine_1_value) global_temp_dict['eftpos 2'] = H.dollar_adder( self, machine_2_value) global_temp_dict['eftpos 3'] = H.dollar_adder( self, machine_3_value) global_temp_dict['eftpos prev'] = H.dollar_adder( self, machine_prev_value) eft_arr = [machine_1_value, machine_2_value, machine_3_value] eft_total = 0 for value in eft_arr: if value != None: eft_total += value if machine_prev_value != None: eft_total -= machine_prev_value ftd_eft_total = H.dollar_adder(self, eft_total) if ftd_eft_total == '-': self.eftEnterButton.setText('Enter Values') else: self.eftEnterButton.setText(ftd_eft_total) popup.accept() # method to handle the cancel button when it is pressed def handle_cancelButton(): popup.reject() # initialise the dialog popup = QDialog() popup.setWindowTitle('Enter Eftpos Machine Values') # create the widgets and connect them to functions machine_1_label = QLabel() machine_1_label.setText('Eftpos Machine 1') machine_1 = QLineEdit() machine_2_label = QLabel() machine_2_label.setText('Eftpos Machine 2') machine_2 = QLineEdit() machine_3_label = QLabel() machine_3_label.setText('Eftpos Machine 3') machine_3 = QLineEdit() machine_prev_label = QLabel() machine_prev_label.setText('Previous Day\'s Eftpos (if applicable)') machine_prev = QLineEdit() okayButton = QPushButton('Okay') okayButton.clicked.connect(handle_okayButton) cancelButton = QPushButton('Cancel') cancelButton.clicked.connect(handle_cancelButton) # initialise values machine_1.setText(global_temp_dict['eftpos 1']) machine_2.setText(global_temp_dict['eftpos 2']) machine_3.setText(global_temp_dict['eftpos 3']) machine_prev.setText(global_temp_dict['eftpos prev']) # initialise the layout manager layout = QGridLayout() # add the widgets to the layout manager layout.addWidget(machine_1_label, 0, 0) layout.addWidget(machine_1, 0, 1) layout.addWidget(machine_2_label, 1, 0) layout.addWidget(machine_2, 1, 1) layout.addWidget(machine_3_label, 2, 0) layout.addWidget(machine_3, 2, 1) layout.addWidget(machine_prev_label, 3, 0) layout.addWidget(machine_prev, 3, 1) layout.addWidget(cancelButton, 4, 0, 1, 2) layout.addWidget(okayButton, 5, 0, 1, 2) popup.setLayout(layout) # set the dialog as modal so that the user cannot interact with the main window when the dialog is open popup.setModal(True) popup.show() popup.exec_()
class FieldWidget(QFrame): # Used for deletion of field something_clicked = Signal() enable_3d_value_spinbox = Signal(bool) def dataset_type_changed(self, _): self.value_line_edit.validator( ).dataset_type_combo = self.value_type_combo self.value_line_edit.validator( ).field_type_combo = self.field_type_combo self.value_line_edit.validator().validate(self.value_line_edit.text(), 0) def __init__( self, node_parent, possible_fields=None, parent: QListWidget = None, parent_dataset: Dataset = None, hide_name_field: bool = False, show_only_f142_stream: bool = False, ): super(FieldWidget, self).__init__(parent) possible_field_names = [] self.default_field_types_dict = {} self.streams_widget: StreamFieldsWidget = None if possible_fields: possible_field_names, default_field_types = zip(*possible_fields) self.default_field_types_dict = dict( zip(possible_field_names, default_field_types)) self._show_only_f142_stream = show_only_f142_stream self._node_parent = node_parent self.edit_dialog = QDialog(parent=self) self.attrs_dialog = FieldAttrsDialog(parent=self) if self.parent() is not None and self.parent().parent() is not None: self.parent().parent().destroyed.connect(self.edit_dialog.close) self.parent().parent().destroyed.connect(self.attrs_dialog.close) self.field_name_edit = FieldNameLineEdit(possible_field_names) if self.default_field_types_dict: self.field_name_edit.textChanged.connect(self.update_default_type) self.hide_name_field = hide_name_field if hide_name_field: self.name = str(uuid.uuid4()) self.units_line_edit = QLineEdit() self.unit_validator = UnitValidator() self.units_line_edit.setValidator(self.unit_validator) self.units_line_edit.setMinimumWidth(20) self.units_line_edit.setMaximumWidth(50) unit_size_policy = QSizePolicy() unit_size_policy.setHorizontalPolicy(QSizePolicy.Preferred) unit_size_policy.setHorizontalStretch(1) self.units_line_edit.setSizePolicy(unit_size_policy) self.unit_validator.is_valid.connect( partial(validate_line_edit, self.units_line_edit)) self.units_line_edit.setPlaceholderText(CommonAttrs.UNITS) self.field_type_combo: QComboBox = QComboBox() self.field_type_combo.addItems([item.value for item in FieldType]) self.field_type_combo.currentIndexChanged.connect( self.field_type_changed) fix_horizontal_size = QSizePolicy() fix_horizontal_size.setHorizontalPolicy(QSizePolicy.Fixed) self.field_type_combo.setSizePolicy(fix_horizontal_size) self.value_type_combo: QComboBox = QComboBox() self.value_type_combo.addItems(list(VALUE_TYPE_TO_NP)) for i, item in enumerate(VALUE_TYPE_TO_NP.keys()): if item == ValueTypes.DOUBLE: self.value_type_combo.setCurrentIndex(i) break self.value_type_combo.currentIndexChanged.connect( self.dataset_type_changed) self.value_line_edit: QLineEdit = QLineEdit() self.value_line_edit.setPlaceholderText("value") value_size_policy = QSizePolicy() value_size_policy.setHorizontalPolicy(QSizePolicy.Preferred) value_size_policy.setHorizontalStretch(2) self.value_line_edit.setSizePolicy(value_size_policy) self._set_up_value_validator(False) self.dataset_type_changed(0) self.nx_class_combo = QComboBox() self.edit_button = QPushButton("Edit") edit_button_size = 50 self.edit_button.setMaximumSize(edit_button_size, edit_button_size) self.edit_button.setSizePolicy(fix_horizontal_size) self.edit_button.clicked.connect(self.show_edit_dialog) self.attrs_button = QPushButton("Attrs") self.attrs_button.setMaximumSize(edit_button_size, edit_button_size) self.attrs_button.setSizePolicy(fix_horizontal_size) self.attrs_button.clicked.connect(self.show_attrs_dialog) self.layout = QHBoxLayout() self.layout.addWidget(self.field_name_edit) self.layout.addWidget(self.field_type_combo) self.layout.addWidget(self.value_line_edit) self.layout.addWidget(self.nx_class_combo) self.layout.addWidget(self.edit_button) self.layout.addWidget(self.value_type_combo) self.layout.addWidget(self.units_line_edit) self.layout.addWidget(self.attrs_button) self.layout.setAlignment(Qt.AlignLeft) self.setLayout(self.layout) self.setFrameShadow(QFrame.Raised) self.setFrameShape(QFrame.StyledPanel) # Allow selecting this field widget in a list by clicking on it's contents self.field_name_edit.installEventFilter(self) existing_objects = [] emit = False if isinstance(parent, QListWidget): for i in range(self.parent().count()): new_field_widget = self.parent().itemWidget( self.parent().item(i)) if new_field_widget is not self and hasattr( new_field_widget, "name"): existing_objects.append(new_field_widget) elif isinstance(self._node_parent, Group): for child in self._node_parent.children: if child is not parent_dataset and hasattr(child, "name"): existing_objects.append(child) emit = True self._set_up_name_validator(existing_objects=existing_objects) self.field_name_edit.validator().is_valid.emit(emit) self.value_line_edit.installEventFilter(self) self.nx_class_combo.installEventFilter(self) # These cause odd double-clicking behaviour when using an event filter so just connecting to the clicked() signals instead. self.edit_button.clicked.connect(self.something_clicked) self.value_type_combo.highlighted.connect(self.something_clicked) self.field_type_combo.highlighted.connect(self.something_clicked) # Set the layout for the default field type self.field_type_changed() def _set_up_name_validator( self, existing_objects: List[Union["FieldWidget", FileWriterModule]]): self.field_name_edit.setValidator( NameValidator(existing_objects, invalid_names=INVALID_FIELD_NAMES)) self.field_name_edit.validator().is_valid.connect( partial( validate_line_edit, self.field_name_edit, tooltip_on_accept="Field name is valid.", tooltip_on_reject="Field name is not valid", )) @property def field_type(self) -> FieldType: return FieldType(self.field_type_combo.currentText()) @field_type.setter def field_type(self, field_type: FieldType): self.field_type_combo.setCurrentText(field_type.value) self.field_type_changed() @property def name(self) -> str: return self.field_name_edit.text() @name.setter def name(self, name: str): self.field_name_edit.setText(name) @property def dtype(self) -> str: return self.value_type_combo.currentText() @dtype.setter def dtype(self, dtype: str): self.value_type_combo.setCurrentText(dtype) @property def attrs(self): return self.value.attributes @attrs.setter def attrs(self, field: Dataset): self.attrs_dialog.fill_existing_attrs(field) @property def value(self) -> Union[FileWriterModule, None]: dtype = self.value_type_combo.currentText() return_object: FileWriterModule if self.field_type == FieldType.scalar_dataset: val = self.value_line_edit.text() return_object = Dataset( parent_node=self._node_parent, name=self.name, type=dtype, values=val, ) elif self.field_type == FieldType.array_dataset: # Squeeze the array so 1D arrays can exist. Should not affect dimensional arrays. array = np.squeeze(self.table_view.model.array) return_object = Dataset( parent_node=self._node_parent, name=self.name, type=dtype, values=array, ) elif self.field_type == FieldType.kafka_stream: return_object = self.streams_widget.get_stream_module( self._node_parent) elif self.field_type == FieldType.link: return_object = Link( parent_node=self._node_parent, name=self.name, source=self.value_line_edit.text(), ) else: logging.error(f"unknown field type: {self.name}") return None if self.field_type != FieldType.link: for name, value, dtype in self.attrs_dialog.get_attrs(): return_object.attributes.set_attribute_value( attribute_name=name, attribute_value=value, attribute_type=dtype, ) if self.units and self.units is not None: return_object.attributes.set_attribute_value( CommonAttrs.UNITS, self.units) return return_object @value.setter def value(self, value): if self.field_type == FieldType.scalar_dataset: self.value_line_edit.setText(to_string(value)) elif self.field_type == FieldType.array_dataset: self.table_view.model.array = value elif self.field_type == FieldType.link: self.value_line_edit.setText(value) @property def units(self) -> str: return self.units_line_edit.text() @units.setter def units(self, new_units: str): self.units_line_edit.setText(new_units) def update_default_type(self): self.value_type_combo.setCurrentText( self.default_field_types_dict.get(self.field_name_edit.text(), "double")) def eventFilter(self, watched: QObject, event: QEvent) -> bool: if event.type() == QEvent.MouseButtonPress: self.something_clicked.emit() return True else: return False def field_type_is_scalar(self) -> bool: return self.field_type == FieldType.scalar_dataset def field_type_changed(self): self.edit_dialog = QDialog(parent=self) self.edit_dialog.setModal(True) self._set_up_value_validator(False) self.enable_3d_value_spinbox.emit(not self.field_type_is_scalar()) if self.field_type == FieldType.scalar_dataset: self.set_visibility(True, False, False, True) elif self.field_type == FieldType.array_dataset: self.set_visibility(False, False, True, True) self.table_view = ArrayDatasetTableWidget() elif self.field_type == FieldType.kafka_stream: self.set_visibility(False, False, True, False, show_name_line_edit=True) self.streams_widget = StreamFieldsWidget( self.edit_dialog, show_only_f142_stream=self._show_only_f142_stream) elif self.field_type == FieldType.link: self.set_visibility( True, False, False, False, show_unit_line_edit=False, show_attrs_edit=False, ) self._set_up_value_validator(False) def _set_up_value_validator(self, is_link: bool): self.value_line_edit.setValidator(None) if is_link: return else: self.value_line_edit.setValidator( FieldValueValidator( self.field_type_combo, self.value_type_combo, FieldType.scalar_dataset.value, )) tooltip_on_accept = "Value is cast-able to numpy type." tooltip_on_reject = "Value is not cast-able to selected numpy type." self.value_line_edit.validator().is_valid.connect( partial( validate_line_edit, self.value_line_edit, tooltip_on_accept=tooltip_on_accept, tooltip_on_reject=tooltip_on_reject, )) self.value_line_edit.validator().validate(self.value_line_edit.text(), None) def set_visibility( self, show_value_line_edit: bool, show_nx_class_combo: bool, show_edit_button: bool, show_value_type_combo: bool, show_name_line_edit: bool = True, show_attrs_edit: bool = True, show_unit_line_edit: bool = True, ): self.value_line_edit.setVisible(show_value_line_edit) self.nx_class_combo.setVisible(show_nx_class_combo) self.edit_button.setVisible(show_edit_button) self.value_type_combo.setVisible(show_value_type_combo) self.units_line_edit.setVisible(show_unit_line_edit) self.attrs_button.setVisible(show_attrs_edit) self.field_name_edit.setVisible(show_name_line_edit and not self.hide_name_field) def show_edit_dialog(self): if self.field_type == FieldType.array_dataset: self.edit_dialog.setLayout(QGridLayout()) self.table_view.model.update_array_dtype( VALUE_TYPE_TO_NP[self.value_type_combo.currentText()]) self.edit_dialog.layout().addWidget(self.table_view) self.edit_dialog.setWindowTitle( f"Edit {self.value_type_combo.currentText()} Array field") elif self.field_type == FieldType.kafka_stream: self.edit_dialog.setLayout(QFormLayout()) self.edit_dialog.layout().addWidget(self.streams_widget) if self.edit_dialog.isVisible(): self.edit_dialog.raise_() else: self.edit_dialog.show() def show_attrs_dialog(self): self.attrs_dialog.show()
class Settings(object): class _MigrationFailed(ExpectedError): pass def __init__(self, cfg, main_cfg, start_service, exit_service, parent=None, size=None, migrate=False, dp=1, get_offline_dirs=lambda: None, set_offline_dirs=lambda o, no: None): super(Settings, self).__init__() self._cfg = cfg self._main_cfg = main_cfg self._start_service = start_service self._exit_service = exit_service self._parent = parent self._size = size self._dp = dp self._get_offline_dirs = get_offline_dirs self._set_offline_dirs = set_offline_dirs self._dialog = QDialog(parent) self._dialog.setWindowIcon(QIcon(':/images/icon.png')) self._dialog.setAttribute(Qt.WA_MacFrameworkScaled) self._ui = settings.Ui_Dialog() self._ui.setupUi(self._dialog) self._max_root_len = get_max_root_len(self._cfg) self._migrate = migrate self._migration = None self._migration_cancelled = False try: self._ui.account_type.setText( license_display_name_from_constant(self._cfg.license_type)) self._ui.account_type.setVisible(True) self._ui.account_type_header.setVisible(True) self._ui.account_upgrade.setVisible(True) except KeyError: pass upgrade_license_types = (FREE_LICENSE, FREE_TRIAL_LICENSE) if self._cfg.license_type in upgrade_license_types: self._ui.account_upgrade.setText('<a href="{}">{}</a>'.format( GET_PRO_URI.format(self._cfg.host), tr('Upgrade'))) self._ui.account_upgrade.setTextFormat(Qt.RichText) self._ui.account_upgrade.setTextInteractionFlags( Qt.TextBrowserInteraction) self._ui.account_upgrade.setOpenExternalLinks(True) self._ui.account_upgrade.setAlignment(Qt.AlignLeft) else: self._ui.account_upgrade.setText("") self._ui.centralWidget.setFrameShape(QFrame.NoFrame) self._ui.centralWidget.setLineWidth(1) self._ui.language_comboBox.addItem(tr('English')) self._ui.language_comboBox.setEnabled(False) self._connect_slots() self._set_fonts() self._ui.tabWidget.setCurrentIndex(0) self._smart_sync_dialog = None self.logged_out = Signal(bool) self.logging_disabled_changed = Signal(bool) # FIXMe: without line below app crashes on exit after settings opened self._dialog.mousePressEvent = self.on_mouse_press_event def on_mouse_press_event(self, ev): pass def _connect_slots(self): ui = self._ui ui.logout_button.clicked.connect(self._logout) ui.download_auto_radioButton.clicked.connect( lambda: ui.download_limit_edit.setEnabled( False) or ui.download_limit_edit.clear()) ui.download_limit_radioButton.clicked.connect( lambda: ui.download_limit_edit.setEnabled(True)) ui.upload_auto_radioButton.clicked.connect( lambda: ui.upload_limit_edit.setEnabled( False) or ui.upload_limit_edit.clear()) ui.upload_limit_radioButton.clicked.connect( lambda: ui.upload_limit_edit.setEnabled(True)) ui.buttonBox.accepted.connect(self._dialog.accept) ui.buttonBox.rejected.connect(self._dialog.reject) ui.smart_sync_button.clicked.connect( self._on_smart_sync_button_clicked) ui.location_button.clicked.connect( self._on_sync_folder_location_button_clicked) ui.location_button.enterEvent = lambda _: \ ui.location_button.setIcon(QIcon( ':/images/settings/pencil_hovered.svg')) ui.location_button.leaveEvent = lambda _: \ ui.location_button.setIcon(QIcon( ':/images/settings/pencil.svg')) ui.smart_sync_button.enterEvent = lambda _: \ ui.smart_sync_button.setIcon(QIcon( ':/images/settings/folder_sync_hovered.svg')) ui.smart_sync_button.leaveEvent = lambda _: \ ui.smart_sync_button.setIcon(QIcon( ':/images/settings/folder_sync.svg')) ui.logout_button.enterEvent = lambda _: \ ui.logout_button.setIcon(QIcon( ':/images/settings/logout_hovered.svg')) ui.logout_button.leaveEvent = lambda _: \ ui.logout_button.setIcon(QIcon( ':/images/settings/logout.svg')) def _set_fonts(self): ui = self._ui controls = [ui.tabWidget, ui.language_comboBox] controls.extend([c for c in ui.tabWidget.findChildren(QLabel)]) controls.extend([c for c in ui.tabWidget.findChildren(QLineEdit)]) controls.extend([c for c in ui.tabWidget.findChildren(QPushButton)]) controls.extend([c for c in ui.tabWidget.findChildren(QCheckBox)]) controls.extend([c for c in ui.tabWidget.findChildren(QRadioButton)]) for control in controls: font = control.font() font_size = control.font().pointSize() * self._dp if font_size > 0: control_font = QFont(font.family(), font_size) control_font.setBold(font.bold()) control.setFont(control_font) def _logout(self): userAnswer = msgbox(tr('Keep local files on device?'), buttons=[ (tr('Clear all'), 'Wipe'), (tr('Keep'), 'Keep'), ], parent=self._dialog, default_index=1, enable_close_button=True) if userAnswer == '': return wipe_all = userAnswer == 'Wipe' if not wipe_all: self._cfg.set_settings({'user_password_hash': ""}) self.logged_out.emit(wipe_all) self._dialog.reject() def show(self, on_finished): def finished(): if self._dialog.result() == QDialog.Accepted: self._apply_settings() self._dialog.finished.disconnect(finished) on_finished() self._setup_to_ui() if self._migrate: self._ui.tabWidget.setCurrentIndex(1) # Account page QTimer.singleShot(100, self._on_sync_folder_location_button_clicked) self._dialog.finished.connect(finished) self._dialog.raise_() self._dialog.setModal(True) self._dialog.show() def _setup_to_ui(self): ui = self._ui cfg = self._cfg portable = is_portable() if cfg.get_setting('lang', None) is None: self._ui.language_comboBox.setCurrentIndex(0) else: lang = cfg.lang if cfg.lang in get_available_languages() else 'en' assert lang in get_available_languages() for i in range(1, ui.language_comboBox.count()): if ui.language_comboBox.itemText(i) == lang: ui.language_comboBox.setCurrentIndex(i) break ui.location_edit.setText( FilePath(cfg.sync_directory) if cfg.sync_directory else '') ui.location_button.setEnabled(not portable) if portable: ui.location_button.setToolTip(tr("Disabled in portable version")) ui.email_label.setText(cfg.user_email if cfg.user_email else '') def set_limit(limit, auto_btn, manual_btn, edit): edit.setValidator(QRegExpValidator(QRegExp("\\d{1,9}"))) if limit: manual_btn.setChecked(True) edit.setText(str(limit)) else: auto_btn.setChecked(True) auto_btn.click() set_limit(limit=cfg.download_limit, auto_btn=ui.download_auto_radioButton, manual_btn=ui.download_limit_radioButton, edit=ui.download_limit_edit) set_limit(limit=cfg.upload_limit, auto_btn=ui.upload_auto_radioButton, manual_btn=ui.upload_limit_radioButton, edit=ui.upload_limit_edit) ui.autologin_checkbox.setChecked(self._main_cfg.autologin) ui.autologin_checkbox.setEnabled(not portable) if portable: ui.autologin_checkbox.setToolTip( tr("Disabled in portable version")) ui.tracking_checkbox.setChecked(cfg.send_statistics) ui.autoupdate_checkbox.setChecked(self._main_cfg.autoupdate) ui.download_backups_checkBox.setChecked(cfg.download_backups) ui.is_smart_sync_checkBox.setChecked(cfg.smart_sync) ui.disable_logging_checkBox.setChecked(self._main_cfg.logging_disabled) # Disable smart sync for free license if not cfg.license_type or cfg.license_type == FREE_LICENSE: ui.is_smart_sync_checkBox.setText( tr("SmartSync+ is not available for your license")) ui.is_smart_sync_checkBox.setChecked(False) ui.is_smart_sync_checkBox.setCheckable(False) ui.smart_sync_button.setEnabled(False) ui.startup_checkbox.setChecked(is_in_system_startup()) ui.startup_checkbox.setEnabled(not portable) if portable: ui.startup_checkbox.setToolTip(tr("Disabled in portable version")) def _apply_settings(self): service_settings, main_settings = self._get_configs_from_ui() if main_settings['logging_disabled'] != \ self._main_cfg.logging_disabled: self.logging_disabled_changed.emit( main_settings['logging_disabled']) self._cfg.set_settings(service_settings) self._main_cfg.set_settings(main_settings) if self._ui.startup_checkbox.isChecked(): if not is_in_system_startup(): add_to_system_startup() else: if is_in_system_startup(): remove_from_system_startup() def _config_is_changed(self): service_settings, main_settings = self._get_configs_from_ui() for param, value in service_settings.items(): if self._cfg.get_setting(param) != value: return True for param, value in main_settings.items(): if self._main_cfg.get_setting(param) != value: return True return False def _get_configs_from_ui(self): ui = self._ui return { 'lang': (str(ui.language_comboBox.currentText()) if ui.language_comboBox.currentIndex() > 0 else None), 'upload_limit': (0 if ui.upload_auto_radioButton.isChecked() or not ui.upload_limit_edit.text() else int( ui.upload_limit_edit.text())), 'download_limit': (0 if ui.download_auto_radioButton.isChecked() or not ui.download_limit_edit.text() else int( ui.download_limit_edit.text())), 'send_statistics': bool(ui.tracking_checkbox.isChecked()), 'download_backups': bool(ui.download_backups_checkBox.isChecked()), 'smart_sync': bool(ui.is_smart_sync_checkBox.isChecked()), 'autologin': bool(ui.autologin_checkbox.isChecked()), }, { 'autologin': bool(ui.autologin_checkbox.isChecked()), 'autoupdate': bool(ui.autoupdate_checkbox.isChecked()), 'logging_disabled': bool(ui.disable_logging_checkBox.isChecked()), 'download_backups': bool(ui.download_backups_checkBox.isChecked()), } def _on_smart_sync_button_clicked(self): self._get_offline_dirs() root = str(self._ui.location_edit.text()) self._smart_sync_dialog = SmartSyncDialog(self._dialog) offline, online = self._smart_sync_dialog.show(root_path=root, hide_dotted=True) if offline or online: logger.info("Directories set to be offline: (%s)", ", ".join(map(lambda s: u"'%s'" % s, offline))) self._set_offline_dirs(offline, online) def offline_dirs(self, offline_dirs): root = str(self._ui.location_edit.text()) pc = PathConverter(root) offline_dirs_abs_paths = set( map(lambda p: pc.create_abspath(p), offline_dirs)) if self._smart_sync_dialog: self._smart_sync_dialog.set_offline_paths(offline_dirs_abs_paths) def _on_sync_folder_location_button_clicked(self): selected_folder = QFileDialog.getExistingDirectory( self._dialog, tr('Choose Pvtbox folder location'), get_parent_dir(FilePath(self._cfg.sync_directory))) selected_folder = ensure_unicode(selected_folder) try: if not selected_folder: raise self._MigrationFailed("Folder is not selected") if len(selected_folder + "/Pvtbox") > self._max_root_len: if not self._migrate: msgbox(tr("Destination path too long. " "Please select shorter path."), tr("Path too long"), parent=self._dialog) raise self._MigrationFailed("Destination path too long") free_space = get_free_space(selected_folder) selected_folder = get_data_dir(dir_parent=selected_folder, create=False) if FilePath(selected_folder) == FilePath(self._cfg.sync_directory): raise self._MigrationFailed("Same path selected") if FilePath(selected_folder) in FilePath(self._cfg.sync_directory): msgbox(tr("Can't migrate into existing Pvtbox folder.\n" "Please choose other location"), tr("Invalid Pvtbox folder location"), parent=self._dialog) raise self._MigrationFailed( "Can't migrate into existing Pvtbox folder") if self._size and free_space < self._size: logger.debug( "No disk space in %s. Free space: %s. Needed: %s.", selected_folder, free_space, self._size) msgbox(tr( "Insufficient disk space for migration to\n{}.\n" "Please clean disk", selected_folder), tr("No disk space"), parent=self._dialog) raise self._MigrationFailed( "Insufficient disk space for migration") self._migration_cancelled = False dialog = QProgressDialog(self._dialog) dialog.setWindowTitle(tr('Migrating to new Pvtbox folder')) dialog.setWindowIcon(QIcon(':/images/icon.svg')) dialog.setModal(True) dialog.setMinimum(0) dialog.setMaximum(100) dialog.setMinimumSize(400, 80) dialog.setAutoClose(False) def progress(value): logger.debug("Migration dialog progress received: %s", value) dialog.setValue(value) def migration_failed(error): logger.warning("Migration failed with error: %s", error) msgbox(error, tr('Migration to new Pvtbox folder error'), parent=dialog) dialog.cancel() self._migration_cancelled = True done() def cancel(): logger.debug("Migration dialog cancelled") self._migration_cancelled = True self._migration.cancel() def done(): logger.debug("Migration done") try: self._migration.progress.disconnect(progress) self._migration.failed.disconnect(migration_failed) self._migration.done.disconnect(done) dialog.canceled.disconnect(cancel) except Exception as e: logger.warning("Can't disconnect signal %s", e) dialog.hide() dialog.done(QDialog.Accepted) dialog.close() self._migration = SyncDirMigration(self._cfg, parent=self._dialog) self._migration.progress.connect(progress, Qt.QueuedConnection) self._migration.failed.connect(migration_failed, Qt.QueuedConnection) self._migration.done.connect(done, Qt.QueuedConnection) dialog.canceled.connect(cancel) self._exit_service() old_dir = self._cfg.sync_directory self._migration.migrate(old_dir, selected_folder) def on_finished(): logger.info("Migration dialog closed") if not self._migration_cancelled: logger.debug("Setting new location") self._ui.location_edit.setText(FilePath(selected_folder)) disable_file_logging(logger) shutil.rmtree(op.join(old_dir, '.pvtbox'), ignore_errors=True) set_root_directory(FilePath(selected_folder)) enable_file_logging(logger) make_dir_hidden(get_patches_dir(selected_folder)) self._start_service() dialog.finished.connect(on_finished) dialog.show() except self._MigrationFailed as e: logger.warning("Sync dir migration failed. Reason: %s", e) finally: if self._migrate: self._dialog.accept()
def createRawImportDialog(main_window, fname, output_image, info_var, resample, target_size, crop_image, origin, target_z_extent, finish_fn): dialog = QDialog(main_window) ui = generateUIFormView() groupBox = ui['groupBox'] formLayout = ui['groupBoxFormLayout'] widgetno = 1 title = "Config for " + os.path.basename(fname) dialog.setWindowTitle(title) # dimensionality dimensionalityLabel = QLabel(groupBox) dimensionalityLabel.setText("Dimensionality") formLayout.setWidget(widgetno, QFormLayout.LabelRole, dimensionalityLabel) dimensionalityValue = QComboBox(groupBox) dimensionalityValue.addItem("3D") dimensionalityValue.addItem("2D") dimensionalityValue.setCurrentIndex(0) # dimensionalityValue.currentIndexChanged.connect(lambda: \ # main_window.overlapZValueEntry.setEnabled(True) \ # if main_window.dimensionalityValue.currentIndex() == 0 else \ # main_window.overlapZValueEntry.setEnabled(False)) formLayout.setWidget(widgetno, QFormLayout.FieldRole, dimensionalityValue) widgetno += 1 validator = QtGui.QIntValidator() # Add X size dimXLabel = QLabel(groupBox) dimXLabel.setText("Size X") formLayout.setWidget(widgetno, QFormLayout.LabelRole, dimXLabel) dimXValueEntry = QLineEdit(groupBox) dimXValueEntry.setValidator(validator) dimXValueEntry.setText("0") formLayout.setWidget(widgetno, QFormLayout.FieldRole, dimXValueEntry) widgetno += 1 # Add Y size dimYLabel = QLabel(groupBox) dimYLabel.setText("Size Y") formLayout.setWidget(widgetno, QFormLayout.LabelRole, dimYLabel) dimYValueEntry = QLineEdit(groupBox) dimYValueEntry.setValidator(validator) dimYValueEntry.setText("0") formLayout.setWidget(widgetno, QFormLayout.FieldRole, dimYValueEntry) widgetno += 1 # Add Z size dimZLabel = QLabel(groupBox) dimZLabel.setText("Size Z") formLayout.setWidget(widgetno, QFormLayout.LabelRole, dimZLabel) dimZValueEntry = QLineEdit(groupBox) dimZValueEntry.setValidator(validator) dimZValueEntry.setText("0") formLayout.setWidget(widgetno, QFormLayout.FieldRole, dimZValueEntry) widgetno += 1 # Data Type dtypeLabel = QLabel(groupBox) dtypeLabel.setText("Data Type") formLayout.setWidget(widgetno, QFormLayout.LabelRole, dtypeLabel) dtypeValue = QComboBox(groupBox) # , "int32", "uint32", "float32", "float64"]) dtypeValue.addItems(["int8", "uint8", "int16", "uint16"]) dtypeValue.setCurrentIndex(1) formLayout.setWidget(widgetno, QFormLayout.FieldRole, dtypeValue) widgetno += 1 # Endiannes endiannesLabel = QLabel(groupBox) endiannesLabel.setText("Byte Ordering") formLayout.setWidget(widgetno, QFormLayout.LabelRole, endiannesLabel) endiannes = QComboBox(groupBox) endiannes.addItems(["Big Endian", "Little Endian"]) endiannes.setCurrentIndex(1) formLayout.setWidget(widgetno, QFormLayout.FieldRole, endiannes) widgetno += 1 # Fortran Ordering fortranLabel = QLabel(groupBox) fortranLabel.setText("Fortran Ordering") formLayout.setWidget(widgetno, QFormLayout.LabelRole, fortranLabel) fortranOrder = QComboBox(groupBox) fortranOrder.addItem("Fortran Order: XYZ") fortranOrder.addItem("C Order: ZYX") fortranOrder.setCurrentIndex(0) # dimensionalityValue.currentIndexChanged.connect(lambda: \ # main_window.overlapZValueEntry.setEnabled(True) \ # if main_window.dimensionalityValue.currentIndex() == 0 else \ # main_window.overlapZValueEntry.setEnabled(False)) formLayout.setWidget(widgetno, QFormLayout.FieldRole, fortranOrder) widgetno += 1 buttonbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonbox.accepted.connect(lambda: createConvertRawImageWorker( main_window, fname, output_image, info_var, resample, target_size, crop_image, origin, target_z_extent, finish_fn)) buttonbox.rejected.connect(dialog.close) formLayout.addWidget(buttonbox) dialog.setLayout(ui['verticalLayout']) dialog.setModal(True) return { 'dialog': dialog, 'ui': ui, 'dimensionality': dimensionalityValue, 'dimX': dimXValueEntry, 'dimY': dimYValueEntry, 'dimZ': dimZValueEntry, 'dtype': dtypeValue, 'endiannes': endiannes, 'isFortran': fortranOrder, 'buttonBox': buttonbox }