def _dock_add_spin_box(self, name, value, rng, callback, *, compact=True, double=True, step=None, tooltip=None, layout=None): layout = self._dock_named_layout(name=name, layout=layout, compact=compact) value = value if double else int(value) widget = QDoubleSpinBox() if double else QSpinBox() _set_widget_tooltip(widget, tooltip) widget.setAlignment(Qt.AlignCenter) widget.setMinimum(rng[0]) widget.setMaximum(rng[1]) widget.setKeyboardTracking(False) if step is None: inc = (rng[1] - rng[0]) / 20. inc = max(int(round(inc)), 1) if not double else inc widget.setSingleStep(inc) else: widget.setSingleStep(step) widget.setValue(value) widget.valueChanged.connect(callback) self._layout_add_widget(layout, widget) return _QtWidget(widget)
def __clean_and_load_bookings__(self, working_date: str=None): """ Cleans booking table when switch working day. :param working_date: :return: """ row = 0 t: QTableWidget = self.ui.table_bookings clean_table(t) bookings = list() if working_date is not None: bookings = self.time_capture_service.load_bookings(working_date) else: bookings = self.__convert_entities_to_bookings__() for b in bookings: t.insertRow(row) qcb = QCheckBox(self.ui.table_bookings) qcb.setChecked(b[bk.BOOKED]) t.setCellWidget(row, B_BOOKED, qcb) qcb = QCheckBox(self.ui.table_bookings) qcb.setChecked(b[bk.LOGGED]) t.setCellWidget(row, B_LOGGED, qcb) qdsb = QDoubleSpinBox(self.ui.table_bookings) qdsb.setValue(b[bk.HOURS]) t.setCellWidget(row, B_HOURS, qdsb) t.setItem(row, B_ORDER, QTableWidgetItem(b[bk.ORDER])) t.setItem(row, B_COMMENT, QTableWidgetItem(b[bk.COMMENT])) t.resizeRowsToContents() row += 1
def _get_actor_widget(actor: vtkActor) -> QWidget: widget = QWidget() layout = QVBoxLayout() prop = actor.GetProperty() # visibility visibility = QCheckBox("Visibility") visibility.setChecked(actor.GetVisibility()) visibility.toggled.connect(actor.SetVisibility) layout.addWidget(visibility) if prop is not None: # opacity tmp_layout = QHBoxLayout() opacity = QDoubleSpinBox() opacity.setMaximum(1.0) opacity.setValue(prop.GetOpacity()) opacity.valueChanged.connect(prop.SetOpacity) tmp_layout.addWidget(QLabel("Opacity")) tmp_layout.addWidget(opacity) layout.addLayout(tmp_layout) widget.setLayout(layout) return widget
class DxfOutputDialog(OutputDialog): """Dialog for DXF format.""" format_name = "DXF" format_icon = "dxf.png" assembly_description = "The sketch of the parts will include in the file." frame_description = "There is only wire frame will be generated." def __init__(self, *args): """Type name: "DXF module".""" super(DxfOutputDialog, self).__init__(*args) # DXF version option version_label = QLabel("DXF version:", self) self.version_option = QComboBox(self) self.version_option.addItems( sorted((f"{name} - {DXF_VERSIONS_MAP[name]}" for name in DXF_VERSIONS), key=lambda v: v.split()[-1])) self.version_option.setCurrentIndex(self.version_option.count() - 1) self.version_option.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) layout = QHBoxLayout() layout.addWidget(version_label) layout.addWidget(self.version_option) self.main_layout.insertLayout(3, layout) # Parts interval self.use_interval = QCheckBox("Parts interval:", self) self.use_interval.setCheckState(Qt.Checked) self.use_interval.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) self.interval_option = QDoubleSpinBox(self) self.interval_option.setValue(10) self.use_interval.stateChanged.connect(self.interval_option.setEnabled) layout = QHBoxLayout() layout.addWidget(self.use_interval) layout.addWidget(self.interval_option) layout.addItem( QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Preferred)) self.assembly_layout.insertLayout(2, layout) def do(self, dir_str: QDir) -> bool: """Output types: + Boundary + Frame """ file_name = dir_str.filePath(_get_name(self.filename_edit) + '.dxf') if isfile(file_name) and self.warn_radio.isChecked(): self.exist_warning(file_name) return False version = self.version_option.currentText().split()[0] if self.frame_radio.isChecked(): # Frame dxf_frame(self.vpoints, self.v_to_slvs, version, file_name) elif self.assembly_radio.isChecked(): # Boundary dxf_boundary( self.vpoints, self.link_radius.value(), self.interval_option.value() if self.use_interval.isChecked() else 0., version, file_name) return True
class ResultImageView(ImageView): """ :type _settings PartSettings: """ def __init__(self, settings: PartSettings, channel_property: ChannelProperty, name: str): super().__init__(settings, channel_property, name) self._channel_control_top = True self.only_border = QCheckBox("") self.image_state.only_borders = False self.only_border.setChecked(self.image_state.only_borders) self.only_border.stateChanged.connect(self.image_state.set_borders) self.opacity = QDoubleSpinBox() self.opacity.setRange(0, 1) self.opacity.setValue(self.image_state.opacity) self.opacity.setSingleStep(0.1) self.opacity.valueChanged.connect(self.image_state.set_opacity) self.opacity.setMinimumWidth(500) self.label1 = QLabel("Borders:") self.label2 = QLabel("Opacity:") self.btn_layout.insertWidget(3, self.label1) self.btn_layout.insertWidget(4, self.only_border) self.btn_layout.insertWidget(5, self.label2) self.btn_layout.insertWidget(6, self.opacity) self.label1.setVisible(False) self.label2.setVisible(False) self.opacity.setVisible(False) self.only_border.setVisible(False) def any_segmentation(self): for image_info in self.image_info.values(): if image_info.segmentation is not None: return True return False @Slot() @Slot(SegmentationInfo) def set_segmentation(self, segmentation_info: Optional[SegmentationInfo] = None, image: Optional[Image] = None) -> None: super().set_segmentation(segmentation_info, image) show = self.any_segmentation() self.label1.setVisible(show) self.label2.setVisible(show) self.opacity.setVisible(show) self.only_border.setVisible(show) def resizeEvent(self, event: QResizeEvent): if event.size().width() > 700 and not self._channel_control_top: w = self.btn_layout2.takeAt(0).widget() self.btn_layout.takeAt(2) # noinspection PyArgumentList self.btn_layout.insertWidget(2, w) self._channel_control_top = True elif event.size().width() <= 700 and self._channel_control_top: w = self.btn_layout.takeAt(2).widget() self.btn_layout.insertStretch(2, 1) # noinspection PyArgumentList self.btn_layout2.insertWidget(0, w) self._channel_control_top = False
def createDoubleSpinBox(self, variable_name, variable_value, variable_type, analysis_module_variables_model): spinner = QDoubleSpinBox() spinner.setDecimals(6) spinner.setMinimumWidth(75) spinner.setMaximum(analysis_module_variables_model.getVariableMaximumValue(variable_name)) spinner.setMinimum(analysis_module_variables_model.getVariableMinimumValue(variable_name)) spinner.setSingleStep(analysis_module_variables_model.getVariableStepValue(variable_name)) spinner.setValue(variable_value) spinner.valueChanged.connect(partial(self.valueChanged, variable_name, variable_type, spinner)) return spinner
def __add_option(self, name: str, option: QDoubleSpinBox) -> None: """Add widgets for option.""" layout = QHBoxLayout() label = QLabel(name, self) option.setValue(1) option.setMaximum(10000) option.setMinimum(0.01) layout.addWidget(label) layout.addWidget(option) self.main_layout.addLayout(layout)
def create_input_float(obj, ob2=None): if ob2 is not None: val = obj obj = ob2 else: val = 0 res = QDoubleSpinBox(obj) res.setRange(-1000000, 1000000) res.setValue(val) return res
def __init__(self, vpoints: Sequence[VPoint], vlinks: Sequence[VLink], path: _Paths, slider_path: _SliderPaths, monochrome: bool, parent: QWidget): super(AnimateDialog, self).__init__(parent) self.setWindowTitle("Vector Animation") self.setWindowFlags(self.windowFlags() | Qt.WindowMaximizeButtonHint & ~Qt.WindowContextHelpButtonHint) self.setMinimumSize(800, 600) self.setModal(True) main_layout = QVBoxLayout(self) self.canvas = _DynamicCanvas(vpoints, vlinks, path, slider_path, self) self.canvas.set_monochrome_mode(monochrome) self.canvas.update_pos.connect(self.__set_pos) layout = QHBoxLayout(self) pt_option = QComboBox(self) pt_option.addItems([f"P{p}" for p in range(len(vpoints))]) layout.addWidget(pt_option) value_label = QLabel(self) @Slot(int) def show_values(ind: int): vel, vel_deg = self.canvas.get_vel(ind) acc, acc_deg = self.canvas.get_acc(ind) value_label.setText( f"Velocity: {vel:.04f} ({vel_deg:.04f}deg) | " f"Acceleration: {acc:.04f} ({acc_deg:.04f}deg)") pt_option.currentIndexChanged.connect(show_values) layout.addWidget(value_label) self.pos_label = QLabel(self) layout.addItem( QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)) layout.addWidget(self.pos_label) main_layout.addLayout(layout) main_layout.addWidget(self.canvas) layout = QHBoxLayout(self) self.play = QPushButton(QIcon(QPixmap(":/icons/play.png")), "", self) self.play.setCheckable(True) self.play.clicked.connect(self.__play) layout.addWidget(self.play) self.slider = QSlider(Qt.Horizontal, self) self.slider.setMaximum(max(len(p) for p in path) - 1) self.slider.valueChanged.connect(self.canvas.set_index) layout.addWidget(self.slider) layout.addWidget(QLabel("Total times:", self)) factor = QDoubleSpinBox(self) factor.valueChanged.connect(self.canvas.set_factor) factor.setSuffix('s') factor.setRange(0.01, 999999) factor.setValue(10) layout.addWidget(factor) main_layout.addLayout(layout) self.timer = QTimer() self.timer.setInterval(10) self.timer.timeout.connect(self.__move_ind)
def spinbox(v: float = 0., *, minimum: float = 0., maximum: float = 9999., prefix: bool = False) -> QDoubleSpinBox: double_spinbox = QDoubleSpinBox() double_spinbox.setMinimum(minimum) double_spinbox.setMaximum(maximum) double_spinbox.setValue(v) if prefix: double_spinbox.setPrefix("±") return double_spinbox
class MaskControl(QWidget): def __init__(self, settings: ViewSettings): super().__init__() self.settings = settings self.color_picker = QColorDialog() self.color_picker.setWindowFlag(Qt.Widget) self.color_picker.setOptions(QColorDialog.DontUseNativeDialog | QColorDialog.NoButtons) self.opacity_spin = QDoubleSpinBox() self.opacity_spin.setRange(0, 1) self.opacity_spin.setSingleStep(0.1) self.opacity_spin.setDecimals(2) self.change_mask_color_btn = QPushButton("Change mask color") self.current_mask_color_preview = ColorShow( self.settings.get_from_profile("mask_presentation_color", [255, 255, 255])) self.opacity_spin.setValue( self.settings.get_from_profile("mask_presentation_opacity", 1)) self.current_mask_color_preview.setAutoFillBackground(True) self.change_mask_color_btn.clicked.connect(self.change_color) self.opacity_spin.valueChanged.connect(self.change_opacity) layout = QVBoxLayout() layout.addWidget(self.color_picker) layout2 = QHBoxLayout() layout2.addWidget(self.change_mask_color_btn) layout2.addWidget(self.current_mask_color_preview, 1) layout2.addWidget(QLabel("Mask opacity")) layout2.addWidget(self.opacity_spin) layout.addLayout(layout2) self.setLayout(layout) def set_color_preview(self, color): self.current_mask_color_preview.set_color(color) def change_color(self): color = self.color_picker.currentColor() color = (color.red(), color.green(), color.blue()) self.settings.set_in_profile("mask_presentation_color", color) self.settings.mask_representation_changed_emit() self.set_color_preview(color) def change_opacity(self): self.settings.set_in_profile("mask_presentation_opacity", self.opacity_spin.value()) self.settings.mask_representation_changed_emit()
def add_float_box(layout, default, minimum, maximum, label, step, row, column=0): box = QDoubleSpinBox() box.setMinimum(minimum) box.setMaximum(maximum) box.setValue(default) box.setSingleStep(step) layout.addWidget(QLabel(label), row, column) layout.addWidget(box, row, column + 1) return box
class PMGNumberSpinCtrl(BaseExtendedWidget): """ 利用spinbox的控制面板,当最大值、最小值、初始值和步长均为整数的时候,类型为整数;、反之只要有任意一个是float, 类型就是浮点数了。 """ def __init__(self, layout_dir: str, title: str, initial_value: Union[int, float], unit: str = '', val_range: Tuple[Union[float, int], Union[float, int]] = (None, None), step: int = 1): super().__init__(layout_dir) self.on_check_callback = None self.prefix = QLabel(text=title) entryLayout = QHBoxLayout() entryLayout.setContentsMargins(0, 0, 0, 0) self.min, self.max = val_range self.step = step if isinstance(self.min, int) and isinstance(self.max, int) and isinstance(self.step, int) \ and isinstance(initial_value, int): self.ctrl = QSpinBox() else: self.ctrl = QDoubleSpinBox() self.ctrl.valueChanged.connect(self.on_value_changed) self.postfix = QLabel(text=unit) # self.central_layout.addWidget(self.prefix) self.central_layout.addLayout(entryLayout) entryLayout.addWidget(self.prefix) entryLayout.addWidget(self.ctrl) entryLayout.addWidget(self.postfix) if self.min is not None: self.ctrl.setMinimum(self.min) if self.max is not None: self.ctrl.setMaximum(self.max) self.ctrl.setSingleStep(step) self.accury = initial_value self.set_value(initial_value) def set_value(self, value: Union[float, int]) -> None: self.ctrl.setValue(value) def get_value(self) -> Union[int, float]: return self.ctrl.value() def on_value_changed(self): self.signal_param_changed.emit(self.name)
def switch_rows(table: QTableWidget, old_position, new_position): """ Helper function to switch a row in a table. Works for booking and entry table. :param table: :param old_position: :param new_position: :return: """ for col_index in range(table.columnCount()): old_item = table.item(old_position, col_index) new_item = table.item(new_position, col_index) if old_item is not None and new_item is not None: old_text = old_item.text() new_text = new_item.text() table.setItem(old_position, col_index, QTableWidgetItem(new_text)) table.setItem(new_position, col_index, QTableWidgetItem(old_text)) else: old_cell_widget = table.cellWidget(old_position, col_index) new_cell_widget = table.cellWidget(new_position, col_index) if old_cell_widget is not None and new_cell_widget is not None: if isinstance(old_cell_widget, QTimeEdit) and isinstance(new_cell_widget, QTimeEdit): qte = QTimeEdit(table) qte.setTime(new_cell_widget.time()) table.setCellWidget(old_position, col_index, qte) qte = QTimeEdit(table) qte.setTime(old_cell_widget.time()) table.setCellWidget(new_position, col_index, qte) if isinstance(old_cell_widget, QDoubleSpinBox) and isinstance(new_cell_widget, QDoubleSpinBox): qdsb = QDoubleSpinBox(table) qdsb.setValue(new_cell_widget.value()) table.setCellWidget(old_position, col_index, qdsb) qdsb = QDoubleSpinBox(table) qdsb.setValue(old_cell_widget.value()) table.setCellWidget(new_position, col_index, qdsb) if isinstance(old_cell_widget, QCheckBox) and isinstance(new_cell_widget, QCheckBox): qcb = QCheckBox(table) qcb.setChecked(new_cell_widget.isChecked()) table.setCellWidget(old_position, col_index, qcb) qcb = QCheckBox(table) qcb.setChecked(old_cell_widget.isChecked()) table.setCellWidget(new_position, col_index, qcb)
def setupParameters(self, model): pBias = model.biasParameters() pSpecific = model.modelSpecificParameters() parameters = pBias + pSpecific self.setRowCount(len(parameters)) self.siScale = {} self.rowMap = {} for row, parameter in enumerate(parameters): name, latex, unit, siScale, minimum, maximum, text = parameter guessSb = QDoubleSpinBox() if len(unit): guessSb.setSuffix(' %s' % unit) guessSb.setMinimum(minimum) guessSb.setMaximum(maximum) guessSb.setKeyboardTracking(False) item = QTableWidgetItem(name) item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEditable | Qt.ItemIsEnabled) item.setCheckState(Qt.Checked) item.setToolTip(text) self.setItem(row, 0, item) self.setCellWidget(row, 1, guessSb) minSb = QDoubleSpinBox() maxSb = QDoubleSpinBox() minSb.setMinimum(minimum) minSb.setMaximum(maximum) minSb.setValue(minimum) maxSb.setMinimum(minimum) maxSb.setMaximum(maximum) maxSb.setValue(maximum) minSb.setKeyboardTracking(False) maxSb.setKeyboardTracking(False) maxSb.valueChanged.connect(minSb.setMaximum) maxSb.valueChanged.connect(guessSb.setMaximum) minSb.valueChanged.connect(maxSb.setMinimum) minSb.valueChanged.connect(guessSb.setMinimum) self.setCellWidget(row, 2, minSb) self.setCellWidget(row, 3, maxSb) guessSb.valueChanged.connect(self.parameterGuessChanged) self.siScale[name] = siScale self.rowMap[name] = row
class ControlsWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self) self.tfPlot = TransferFunctionPlot() self.modelCombo = QComboBox() self.modelCombo.addItems(AvailableModels) self.quantityCombo = QComboBox() self.quantityCombo.addItems(['Impedance', 'Admittance']) self.fMinSb = QDoubleSpinBox() self.fMinSb.setRange(0.1, 1E6) self.fMaxSb = QDoubleSpinBox() self.fMaxSb.setRange(10, 1E6) self.fMinSb.setKeyboardTracking(False) self.fMaxSb.setKeyboardTracking(False) self.fMinSb.valueChanged.connect(self.fMinSb.setMinimum) self.fMaxSb.valueChanged.connect(self.fMaxSb.setMaximum) self.fMinSb.setValue(1) self.fMaxSb.setValue(250E3) self.shuntSb = QDoubleSpinBox() self.shuntSb.setDecimals(4) self.shuntSb.setKeyboardTracking(False) self.shuntSb.setRange(0.010, 10) self.shuntSb.setSuffix(u' m\u03A9') self.shuntSb.setValue(0.257) l = QFormLayout() l.addRow('Model', self.modelCombo) l.addRow('Quantity', self.quantityCombo) l.addRow('f (min)', self.fMinSb) l.addRow('f (max)', self.fMaxSb) l.addRow('Shunt resistance', self.shuntSb) self.setLayout(l)
class InterpolateBadsDialog(QDialog): def __init__(self, parent): super().__init__(parent) self.setWindowTitle("Interpolate bad channels") vbox = QVBoxLayout(self) grid = QGridLayout() grid.addWidget(QLabel("Reset bads:"), 0, 0) self.reset_bads_checkbox = QCheckBox() self.reset_bads_checkbox.setChecked(True) grid.addWidget(self.reset_bads_checkbox, 0, 1) grid.addWidget(QLabel("Mode:"), 1, 0) self.mode_select = QComboBox() self.modes = {"Accurate": "accurate", "Fast": "fast"} self.mode_select.addItems(self.modes.keys()) self.mode_select.setCurrentText("Accurate") grid.addWidget(self.mode_select, 1, 1) grid.addWidget(QLabel("Origin (x, y, z):"), 2, 0) hbox = QHBoxLayout() self.x = QDoubleSpinBox() self.x.setValue(0) self.x.setDecimals(3) hbox.addWidget(self.x) self.y = QDoubleSpinBox() self.y.setValue(0) self.y.setDecimals(3) hbox.addWidget(self.y) self.z = QDoubleSpinBox() self.z.setValue(0.04) self.z.setDecimals(3) hbox.addWidget(self.z) grid.addLayout(hbox, 2, 1) vbox.addLayout(grid) buttonbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) vbox.addWidget(buttonbox) buttonbox.accepted.connect(self.accept) buttonbox.rejected.connect(self.reject) vbox.setSizeConstraint(QVBoxLayout.SetFixedSize) @property def origin(self): x = float(self.x.value()) y = float(self.y.value()) z = float(self.z.value()) return x, y, z @property def mode(self): return self.mode_select.currentText() @property def reset_bads(self): return self.reset_bads_checkbox.isChecked()
class Dimension(QWidget): stateChanged = Signal(int) valueChanged = Signal() """ pass in dimension state: one of (State.X, State.Y, State.NONE, State.DISABLE) Can be run independently by: from mantidqt.widgets.sliceviewer.dimensionwidget import Dimension from qtpy.QtWidgets import QApplication app = QApplication([]) window = Dimension({'minimum':-1.1, 'number_of_bins':11, 'width':0.2, 'name':'Dim0', 'units':'A'}) window.show() app.exec_() """ def __init__(self, dim_info, number=0, state=State.NONE, parent=None): super().__init__(parent) self.minimum = dim_info['minimum'] self.nbins = dim_info['number_of_bins'] self.width = dim_info['width'] self.number = number self.layout = QHBoxLayout(self) self.name = QLabel(dim_info['name']) self.units = QLabel(dim_info['units']) self.x = QPushButton('X') self.x.setFixedSize(32, 32) self.x.setCheckable(True) self.x.clicked.connect(self.x_clicked) self.y = QPushButton('Y') self.y.setFixedSize(32, 32) self.y.setCheckable(True) self.y.clicked.connect(self.y_clicked) self.slider = QSlider(Qt.Horizontal) self.slider.setRange(0, self.nbins - 1) self.slider.valueChanged.connect(self.slider_changed) self.spinbox = QDoubleSpinBox() self.spinbox.setDecimals(3) self.spinbox.setRange(self.get_bin_center(0), self.get_bin_center(self.nbins - 1)) self.spinbox.setSingleStep(self.width) self.spinbox.editingFinished.connect(self.spinbox_changed) self.layout.addWidget(self.name) self.layout.addWidget(self.x) self.layout.addWidget(self.y) self.layout.addWidget(self.slider, stretch=1) self.layout.addStretch(0) self.layout.addWidget(self.spinbox) self.layout.addWidget(self.units) self.set_value(0) if self.nbins < 2: state = State.DISABLE self.set_state(state) def set_state(self, state): self.state = state if self.state == State.X: self.x.setChecked(True) self.y.setChecked(False) self.slider.hide() self.spinbox.hide() self.units.hide() elif self.state == State.Y: self.x.setChecked(False) self.y.setChecked(True) self.slider.hide() self.spinbox.hide() self.units.hide() elif self.state == State.NONE: self.x.setChecked(False) self.y.setChecked(False) self.slider.show() self.spinbox.show() self.units.show() else: self.x.setChecked(False) self.x.setDisabled(True) self.y.setChecked(False) self.y.setDisabled(True) self.slider.hide() self.spinbox.show() self.spinbox.setDisabled(True) self.units.show() def get_state(self): return self.state def x_clicked(self): old_state = self.state self.set_state(State.X) if self.state != old_state: self.stateChanged.emit(self.number) def y_clicked(self): old_state = self.state self.set_state(State.Y) if self.state != old_state: self.stateChanged.emit(self.number) def spinbox_changed(self): self.value = self.spinbox.value() self.update_slider() def slider_changed(self): self.value = self.get_bin_center(self.slider.value()) self.update_spinbox() self.valueChanged.emit() def get_bin_center(self, n): return (n + 0.5) * self.width + self.minimum def update_slider(self): i = (self.value - self.minimum) / self.width self.slider.setValue(int(min(max(i, 0), self.nbins - 1))) def update_spinbox(self): self.spinbox.setValue(self.value) def set_value(self, value): self.value = value self.update_slider() self.update_spinbox() def get_value(self): return self.value
class ShearMomentTorqueWindow(PyDialog): """ +-------------------------+ | ShearMomentTorqueWindow | +-------------------------+ | Origin cid x y z | | P2 cid x y z | | z-axis cid x y z | | tol cid x y z | | | | Apply OK Cancel | +-------------------------+ """ def __init__(self, data, win_parent=None): """ Saves the data members from data and performs type checks """ PyDialog.__init__(self, data, win_parent) self._updated_preference = False self._default_font_size = data['font_size'] #self.dim_max = data['dim_max'] self.model_name = data['model_name'] self.cids = data['cids'] self.gpforce = data['gpforce'] #self._origin = data['origin'] #self._p1 = data['origin'] #self._p2 = data['origin'] #self.out_data = data self.plane_color_float, self.plane_color_int = check_color( data['plane_color']) self.plane_opacity = data['plane_opacity'] self.methods = ['Z-Axis Projection', 'CORD2R'] self.zaxis_methods = ['Global Z', 'Camera Normal', 'Manual'] self._zaxis_method = 0 # Global Z self.setWindowTitle('Shear, Moment, Torque') self.create_widgets() self.create_layout() self.set_connections() self.on_font(self._default_font_size) #self.on_gradient_scale() #self.show() def on_font(self, value=None): """update the font for the current window""" if value is None: value = self.font_size_edit.value() font = QtGui.QFont() font.setPointSize(value) self.setFont(font) def set_font_size(self, font_size): """ Updates the font size of all objects in the PyDialog Parameters ---------- font_size : int the font size """ if self.font_size == font_size: return self.font_size = font_size font = make_font(font_size, is_bold=False) self.setFont(font) self.set_bold_font(font_size) def set_bold_font(self, font_size): """ Updates the font size of all bolded objects in the dialog Parameters ---------- font_size : int the font size """ bold_font = make_font(font_size, is_bold=True) self.additional_params_label.setFont(bold_font) self.case_info_label.setFont(bold_font) self.plane_label.setFont(bold_font) self.location_label.setFont(bold_font) self.cid_label.setFont(bold_font) self.x_label.setFont(bold_font) self.y_label.setFont(bold_font) self.z_label.setFont(bold_font) def create_widgets(self): """creates the display window""" # CORD2R #self.origin_label = QLabel("Origin:") #self.zaxis_label = QLabel("Z Axis:") #self.xz_plane_label = QLabel("XZ Plane:") # Z-Axis Projection self.p1_label = QLabel("Origin:") self.p3_label = QLabel("End:") self.p2_label = QLabel("XZ Plane:") self.p1_label.setToolTip( 'Defines the starting point for the shear, moment, torque plot') self.p3_label.setToolTip( 'Defines the end point for the shear, moment, torque plot') self.p2_label.setToolTip('Defines the XZ plane for the shears/moments') self.zaxis_label = QLabel("Z Axis:") self.method_pulldown = QComboBox() for method in self.methods: self.method_pulldown.addItem(method) self.zaxis_method_pulldown = QComboBox() for method in self.zaxis_methods: self.zaxis_method_pulldown.addItem(method) self.cid_label = QLabel("Coordinate System:") self.p1_cid_pulldown = QComboBox() self.p2_cid_pulldown = QComboBox() self.p3_cid_pulldown = QComboBox() self.zaxis_cid_pulldown = QComboBox() cid_global_str = '0/Global' for cid in sorted(self.cids): if cid == 0: cid_str = cid_global_str else: cid_str = str(cid) #print('cid_str = %r' % cid_str) self.p1_cid_pulldown.addItem(cid_str) self.p2_cid_pulldown.addItem(cid_str) self.p3_cid_pulldown.addItem(cid_str) self.zaxis_cid_pulldown.addItem(cid_str) self.p1_cid_pulldown.setCurrentIndex(0) self.p2_cid_pulldown.setCurrentIndex(0) self.p3_cid_pulldown.setCurrentIndex(0) self.zaxis_cid_pulldown.setCurrentIndex(0) if len(self.cids) == 1: self.p1_cid_pulldown.setEnabled(False) self.p2_cid_pulldown.setEnabled(False) self.p3_cid_pulldown.setEnabled(False) self.zaxis_cid_pulldown.setEnabled(False) #self.p1_cid_pulldown.setItemText(0, cid_str) #self.p2_cid_pulldown.setItemText(0, cid_str) #self.zaxis_cid_pulldown.setItemText(0, cid_str) self.p1_cid_pulldown.setToolTip( 'Defines the coordinate system for Point P1') self.p2_cid_pulldown.setToolTip( 'Defines the coordinate system for Point P2') self.p3_cid_pulldown.setToolTip( 'Defines the coordinate system for Point P3') self.zaxis_cid_pulldown.setToolTip( 'Defines the coordinate system for the Z Axis') self.p1_x_edit = QFloatEdit('') self.p1_y_edit = QFloatEdit('') self.p1_z_edit = QFloatEdit('') self.p2_x_edit = QFloatEdit('') self.p2_y_edit = QFloatEdit('') self.p2_z_edit = QFloatEdit('') self.p3_x_edit = QFloatEdit('') self.p3_y_edit = QFloatEdit('') self.p3_z_edit = QFloatEdit('') self.zaxis_x_edit = QFloatEdit('') self.zaxis_y_edit = QFloatEdit('') self.zaxis_z_edit = QFloatEdit('') self.additional_params_label = QLabel('Plane Parameters:') self.case_info_label = QLabel('Case Info:') self.p2_label = QLabel("XZ Plane:") # Plane Color self.plane_color_label = QLabel("Plane Color:") self.plane_color_edit = QPushButtonColor(self.plane_color_int) self.plane_opacity_label = QLabel("Plane Opacity:") self.plane_opacity_edit = QDoubleSpinBox() self.plane_opacity_edit.setRange(0.1, 1.0) self.plane_opacity_edit.setDecimals(1) self.plane_opacity_edit.setSingleStep(0.1) self.plane_opacity_edit.setValue(self.plane_opacity) self.flip_coord_label = QLabel("Flip Coordinate System:") self.flip_coord_checkbox = QCheckBox() #----------------------------------------------------------------------- self.time_label = QLabel('Time:') if self.gpforce is None: times = ['0.', '0.5', '1.', '1.5', '2.'] time = '0.' else: times = [func_str(time) for time in self.gpforce._times] time = times[0] self.times_pulldown = make_combo_box(times, time) self.time_label.setEnabled(False) self.times_pulldown.setEnabled(False) #self.node_label = QLabel('Nodes:') #self.node_edit = QNodeEdit(self.win_parent, self.model_name, parent=self.gui, #pick_style='area', tab_to_next=False) #self.element_label = QLabel('Elements:') #self.element_edit = QElementEdit(self.win_parent, self.model_name, parent=self.gui, #pick_style='area', tab_to_next=False) #self.node_element_label = QLabel('Nodes/Elements:') #self.node_element_edit = QLineEdit() #self.node_element_edit.setReadOnly(True) self.nplanes_label = QLabel('Num Planes:') self.nplanes_spinner = QSpinBox() self.nplanes_spinner.setMinimum(2) self.nplanes_spinner.setMaximum(500) self.nplanes_spinner.setValue(20) #----------------------------------------------------------------------- self.method_label = QLabel('Method:') self.plane_label = QLabel('Plane:') self.location_label = QLabel('Location:') self.zaxis_method_label = QLabel('Z-Axis Method:') self.cid_label = QLabel('Coordinate System:') self.x_label = QLabel('X') self.y_label = QLabel('Y') self.z_label = QLabel('Z') #self.location_label.setAlignment(Qt.AlignCenter) self.cid_label.setAlignment(Qt.AlignCenter) self.x_label.setAlignment(Qt.AlignCenter) self.y_label.setAlignment(Qt.AlignCenter) self.z_label.setAlignment(Qt.AlignCenter) self.export_checkbox = QCheckBox() self.csv_label = QLabel('CSV Filename:') self.csv_edit = QLineEdit() self.csv_button = QPushButton('Browse...') self.csv_label.setEnabled(False) self.csv_edit.setEnabled(False) self.csv_button.setEnabled(False) #----------------------------------------------------------------------- # nodes self.add_button = QPushButton('Add') self.remove_button = QPushButton('Remove') # elements self.add2_button = QPushButton('Add') self.remove2_button = QPushButton('Remove') #----------------------------------------------------------------------- # closing self.apply_button = QPushButton('Apply') self.cancel_button = QPushButton('Cancel') self.set_bold_font(self._default_font_size) @property def gui(self): if self.win_parent is None: return None return self.win_parent.parent.gui def create_layout(self): """sets up the window""" grid = self._make_grid_layout() #hbox_csv = QHBoxLayout() grid2 = QGridLayout() #irow = 0 #grid2.addWidget(self.node_label, irow, 0) #grid2.addWidget(self.node_edit, irow, 1) #grid2.addWidget(self.add_button, irow, 2) #grid2.addWidget(self.remove_button, irow, 3) #irow += 1 #grid2.addWidget(self.element_label, irow, 0) #grid2.addWidget(self.element_edit, irow, 1) #grid2.addWidget(self.add2_button, irow, 2) #grid2.addWidget(self.remove2_button, irow, 3) #irow += 1 #grid2.addWidget(self.node_element_label, irow, 0) #grid2.addWidget(self.node_element_edit, irow, 1) #irow += 1 hbox_csv = QHBoxLayout() hbox_csv.addWidget(self.export_checkbox) hbox_csv.addWidget(self.csv_label) hbox_csv.addWidget(self.csv_edit) hbox_csv.addWidget(self.csv_button) #---------------------------------------------- ok_cancel_box = QHBoxLayout() ok_cancel_box.addWidget(self.apply_button) ok_cancel_box.addWidget(self.cancel_button) vbox = QVBoxLayout() vbox.addLayout(grid) vbox.addLayout(grid2) #vbox.addStretch() vbox.addLayout(hbox_csv) vbox.addStretch() #----------------------- #vbox.addLayout(add_remove_box) vbox.addLayout(ok_cancel_box) self.on_method(0) self.on_zaxis_method(0) self.setLayout(vbox) def on_export_checkbox(self): """this is called when the checkbox is clicked""" is_checked = self.export_checkbox.isChecked() self.csv_label.setEnabled(is_checked) self.csv_edit.setEnabled(is_checked) self.csv_button.setEnabled(is_checked) def on_browse_csv(self): """opens a file dialog""" default_dirname = os.getcwd() csv_filename, wildcard = save_file_dialog( self, 'Select the file name for export', default_dirname, wildcard_csv) if not csv_filename: return self.csv_edit.setText(csv_filename) def _make_grid_layout(self): """builds the QGridLayout""" grid = QGridLayout() irow = 0 #------------------------- grid.addWidget(self.location_label, irow, 0) grid.addWidget(self.cid_label, irow, 1) grid.addWidget(self.x_label, irow, 2) grid.addWidget(self.y_label, irow, 3) grid.addWidget(self.z_label, irow, 4) irow += 1 add_row(irow, grid, self.p1_label, self.p1_cid_pulldown, self.p1_x_edit, self.p1_y_edit, self.p1_z_edit) irow += 1 add_row(irow, grid, self.p3_label, self.p3_cid_pulldown, self.p3_x_edit, self.p3_y_edit, self.p3_z_edit) irow += 1 grid.addWidget(self.plane_label, irow, 0) irow += 1 grid.addWidget(self.method_label, irow, 0) grid.addWidget(self.method_pulldown, irow, 1) irow += 1 grid.addWidget(self.zaxis_method_label, irow, 0) grid.addWidget(self.zaxis_method_pulldown, irow, 1) irow += 1 add_row(irow, grid, self.zaxis_label, self.zaxis_cid_pulldown, self.zaxis_x_edit, self.zaxis_y_edit, self.zaxis_z_edit) irow += 1 add_row(irow, grid, self.p2_label, self.p2_cid_pulldown, self.p2_x_edit, self.p2_y_edit, self.p2_z_edit) irow += 1 #----------------------------------------- grid.addWidget(self.case_info_label, irow, 0) irow += 1 grid.addWidget(self.time_label, irow, 0) grid.addWidget(self.times_pulldown, irow, 1) irow += 1 grid.addWidget(self.nplanes_label, irow, 0) grid.addWidget(self.nplanes_spinner, irow, 1) irow += 1 #----------------------------------------- grid.addWidget(self.additional_params_label, irow, 0) irow += 1 grid.addWidget(self.plane_color_label, irow, 0) grid.addWidget(self.plane_color_edit, irow, 1) irow += 1 grid.addWidget(self.plane_opacity_label, irow, 0) grid.addWidget(self.plane_opacity_edit, irow, 1) irow += 1 #---------------------------------------------- return grid def set_connections(self): """creates the actions for the menu""" self.method_pulldown.currentIndexChanged.connect(self.on_method) self.zaxis_method_pulldown.currentIndexChanged.connect( self.on_zaxis_method) self.plane_color_edit.clicked.connect(self.on_plane_color) self.export_checkbox.clicked.connect(self.on_export_checkbox) self.csv_button.clicked.connect(self.on_browse_csv) self.apply_button.clicked.connect(self.on_apply) self.cancel_button.clicked.connect(self.on_cancel) def on_method(self, method_int=None): method = get_pulldown_text(method_int, self.methods, self.method_pulldown) if method == 'Z-Axis Projection': is_cord2r = False elif method == 'CORD2R': is_cord2r = True else: raise NotImplementedError(method) if is_cord2r: self._zaxis_method = self.zaxis_method_pulldown.currentIndex() # set to manual #self.on_zaxis_method(method_int=2) # manual self.zaxis_method_pulldown.setCurrentIndex(2) self.on_zaxis_method() # update else: self.zaxis_method_pulldown.setCurrentIndex(self._zaxis_method) self.on_zaxis_method() # update # works self.zaxis_method_pulldown.setEnabled(not is_cord2r) self.zaxis_method_pulldown.setVisible(not is_cord2r) self.zaxis_method_label.setEnabled(not is_cord2r) def on_zaxis_method(self, method_int=None): method = get_pulldown_text(method_int, self.zaxis_methods, self.zaxis_method_pulldown) if method == 'Global Z': is_visible = False elif method == 'Camera Normal': is_visible = False elif method == 'Manual': is_visible = True else: raise NotImplementedError(method) self.zaxis_cid_pulldown.setVisible(is_visible) self.zaxis_x_edit.setVisible(is_visible) self.zaxis_y_edit.setVisible(is_visible) self.zaxis_z_edit.setVisible(is_visible) def on_plane_color(self): """ Choose a plane color""" title = "Choose a cutting plane color" rgb_color_ints = self.plane_color_int color_edit = self.plane_color_edit func_name = 'set_plane_color' passed, rgb_color_ints, rgb_color_floats = self._background_color( title, color_edit, rgb_color_ints, func_name) if passed: self.plane_color_int = rgb_color_ints self.plane_color_float = rgb_color_floats def _background_color(self, title, color_edit, rgb_color_ints, func_name): """helper method for ``on_background_color`` and ``on_background_color2``""" passed, rgb_color_ints, rgb_color_floats = self.on_color( color_edit, rgb_color_ints, title) if passed and 0: if self.win_parent is not None: settings = self.win_parent.settings func_background_color = getattr(settings, func_name) func_background_color(rgb_color_floats) return passed, rgb_color_ints, rgb_color_floats def on_color(self, color_edit, rgb_color_ints, title): """pops a color dialog""" col = QColorDialog.getColor(QtGui.QColor(*rgb_color_ints), self, title) if not col.isValid(): return False, rgb_color_ints, None color_float = col.getRgbF()[:3] # floats color_int = [int(colori * 255) for colori in color_float] assert isinstance(color_float[0], float), color_float assert isinstance(color_int[0], int), color_int color_edit.setStyleSheet("QPushButton {" "background-color: rgb(%s, %s, %s);" % tuple(color_int) + #"border:1px solid rgb(255, 170, 255); " "}") return True, color_int, color_float #--------------------------------------------------------------------------- def on_validate(self): p1_cidi = self.p1_cid_pulldown.currentText() p2_cidi = self.p2_cid_pulldown.currentText() p3_cidi = self.p3_cid_pulldown.currentText() zaxis_cidi = self.zaxis_cid_pulldown.currentText() p1_cid = int(p1_cidi) if 'Global' not in p1_cidi else 0 p2_cid = int(p2_cidi) if 'Global' not in p2_cidi else 0 p3_cid = int(p3_cidi) if 'Global' not in p3_cidi else 0 zaxis_cid = int(zaxis_cidi) if 'Global' not in zaxis_cidi else 0 #print('p1_cidi=%r p2_cidi=%r p3_cidi=%r' % (p1_cidi, p2_cidi, zaxis_cidi)) #print('p2_cid=%r p2_cid=%r p3_cidi=%r' % (p2_cid, p2_cid, zaxis_cid)) p1_x, flag1 = check_float(self.p1_x_edit) p1_y, flag2 = check_float(self.p1_y_edit) p1_z, flag3 = check_float(self.p1_z_edit) p2_x, flag4 = check_float(self.p2_x_edit) p2_y, flag5 = check_float(self.p2_y_edit) p2_z, flag6 = check_float(self.p2_z_edit) p3_x, flag7 = check_float(self.p3_x_edit) p3_y, flag8 = check_float(self.p3_y_edit) p3_z, flag9 = check_float(self.p3_z_edit) p1 = [p1_x, p1_y, p1_z] p2 = [p2_x, p2_y, p2_z] p3 = [p3_x, p3_y, p3_z] flag10, flag11, flag12, zaxis_cid, zaxis = get_zaxis( self.win_parent, # for camera self.zaxis_method_pulldown, self.zaxis_x_edit, self.zaxis_y_edit, self.zaxis_z_edit) method = self.method_pulldown.currentText() assert method in self.methods, 'method=%r' % method flag13 = True plane_opacity = self.plane_opacity_edit.value() nplanes = self.nplanes_spinner.value() csv_filename = None flag14 = True if self.export_checkbox.isChecked(): csv_filename, flag14 = check_save_path(self.csv_edit) flags = [ flag1, flag2, flag3, flag4, flag5, flag6, flag7, flag8, flag9, flag10, flag11, flag12, flag13, flag14 ] if all(flags): self.out_data['method'] = method self.out_data['p1'] = [p1_cid, p1] self.out_data['p2'] = [p2_cid, p2] self.out_data['p3'] = [p3_cid, p3] self.out_data['zaxis'] = [zaxis_cid, zaxis] self.out_data['plane_color'] = self.plane_color_float self.out_data['plane_opacity'] = plane_opacity self.out_data['nplanes'] = nplanes self.out_data['csv_filename'] = csv_filename self.out_data['clicked_ok'] = True return True return False def on_apply(self): passed = self.on_validate() if passed and self.win_parent is not None: self.win_parent.shear_moment_torque_obj.make_smt_from_data( self.out_data, show=True) #self.win_parent.make_smt_from_data(self.out_data) return passed def on_cancel(self): self.out_data['close'] = True self.close()
class AnimationWindow(PyDialog): """ +-------------------+ | Animation | +-------------------------+ | icase ______ | | scale ______ Default | | time ______ Default | | | | nframes ______ Default | | resolu. ______ Default | | Dir ______ Browse | | iFrame ______ | | | | Animations: | | o Scale, Phase, Time | | | | x delete images | | x repeat | # TODO: change to an integer | x make gif | | | | Step, RunAll | | Close | +-------------------------+ TODO: add key-frame support """ def __init__(self, data, win_parent=None): PyDialog.__init__(self, data, win_parent) self.set_font_size(data['font_size']) self.istep = 0 self._animate_type = 'time' self._updated_animation = False self._active_deformation = 0. self._icase_fringe = data['icase_fringe'] self._icase_disp = data['icase_disp'] self._icase_vector = data['icase_vector'] self._default_name = data['name'] self._default_time = data['time'] self._default_fps = data['frames/sec'] self._default_resolution = data['resolution'] self._scale = data['scale'] self._default_scale = data['default_scale'] self._default_is_scale = data['is_scale'] self._arrow_scale = data['arrow_scale'] self._default_arrow_scale = data['default_arrow_scale'] self._phase = data['phase'] self._default_phase = data['default_phase'] self._default_dirname = data['dirname'] self._default_gif_name = os.path.join(self._default_dirname, data['name'] + '.gif') self.animation_types = [ 'Animate Scale', ] #'Animate Phase', #'Animate Time', #'Animate Frequency Sweep' #] self.setWindowTitle('Animate Model') self.create_widgets() self.create_layout() self.set_connections() self.is_gui = False if hasattr(self.win_parent, '_updated_legend'): self.win_parent.is_animate_open = True self.is_gui = True self.on_update_min_max_defaults() def create_widgets(self): """creates the menu objects""" self.box_scale = QGroupBox('Animate Scale') self.box_time = QGroupBox('Animate Time') icase_max = 1000 # TODO: update 1000 self.checkbox_fringe = QCheckBox('Animate') self.checkbox_fringe.setToolTip( 'Animate the fringe in addition to the deflection') #self.checkbox_disp = QCheckBox('Animate') self.checkbox_fringe.setEnabled(False) self.icase_fringe_label = QLabel("iCase (Fringe):") self.icase_fringe_edit = QSpinBox(self) self.icase_fringe_edit.setRange(0, icase_max) self.icase_fringe_edit.setSingleStep(1) if self._icase_fringe is not None: self.icase_fringe_edit.setValue(self._icase_fringe) self.icase_fringe_edit.setToolTip( 'Case Number for the Scale/Phase Animation Type.\n' 'Defaults to the result you had shown when you clicked "Create Animation".\n' 'iCase can be seen by clicking "Apply" on a result.') self.icase_disp_label = QLabel("iCase (Disp):") self.icase_disp_edit = QSpinBox(self) self.icase_disp_edit.setRange(1, icase_max) self.icase_disp_edit.setSingleStep(1) if self._icase_disp is not None: self.icase_disp_edit.setValue(self._icase_disp) self.checkbox_vector = QCheckBox('Animate') self.checkbox_vector.setToolTip( 'Animate the vector in addition to the deflection') self.checkbox_vector.hide() #self.checkbox_disp = QCheckBox('Animate') self.icase_vector_label = QLabel("iCase (Vector):") self.icase_vector_edit = QSpinBox(self) self.icase_vector_edit.setRange(1, icase_max) self.icase_vector_edit.setSingleStep(1) if self._icase_vector is not None: self.icase_vector_edit.setValue(self._icase_vector) self.scale_label = QLabel("True Scale:") self.scale_edit = QLineEdit(str(self._scale)) self.scale_button = QPushButton("Default") self.scale_edit.setToolTip('Scale factor of the "deflection"') self.scale_button.setToolTip('Sets the scale factor of the gif to %s' % self._scale) self.arrow_scale_label = QLabel("Arrow Scale:") self.arrow_scale_edit = QLineEdit(str(self._scale)) self.arrow_scale_button = QPushButton("Default") self.arrow_scale_edit.setToolTip('Scale factor of the "arrows"') self.arrow_scale_button.setToolTip( 'Sets the arrow scale factor of the gif to %s' % self._arrow_scale) self.arrow_scale_label.setVisible(False) self.arrow_scale_edit.setVisible(False) self.arrow_scale_button.setVisible(False) self.time_label = QLabel("Total Time (sec):") self.time_edit = QDoubleSpinBox(self) self.time_edit.setValue(self._default_time) self.time_edit.setRange(0.1, 5. * 60.) self.time_edit.setDecimals(2) self.time_edit.setSingleStep(0.1) self.time_button = QPushButton("Default") self.time_edit.setToolTip("Total time of the gif") self.time_button.setToolTip('Sets the total time of the gif to %.2f' % self._default_time) self.fps_label = QLabel("Frames/Second:") self.fps_edit = QSpinBox(self) self.fps_edit.setRange(1, 60) self.fps_edit.setSingleStep(1) self.fps_edit.setValue(self._default_fps) self.fps_button = QPushButton("Default") self.fps_edit.setToolTip( "A higher FPS is smoother, but may not play well for large gifs") self.fps_button.setToolTip('Sets the FPS to %s' % self._default_fps) self.resolution_label = QLabel("Resolution Scale:") self.resolution_edit = QSpinBox(self) self.resolution_edit.setRange(1, 5) self.resolution_edit.setSingleStep(1) self.resolution_edit.setValue(self._default_resolution) self.resolution_button = QPushButton("Default") self.resolution_edit.setToolTip( 'Scales the window resolution by an integer factor') self.resolution_button.setToolTip('Sets the resolution to %s' % self._default_resolution) #----------------- # Time plot self.fringe_label = QLabel("Fringe") self.icase_fringe_start_edit = QSpinBox(self) self.icase_fringe_start_edit.setRange(0, icase_max) self.icase_fringe_start_edit.setSingleStep(1) self.icase_fringe_start_edit.setValue(self._icase_fringe) self.icase_fringe_start_button = QPushButton("Default") self.icase_fringe_end_edit = QSpinBox(self) self.icase_fringe_end_edit.setRange(0, icase_max) self.icase_fringe_end_edit.setSingleStep(1) self.icase_fringe_end_edit.setValue(self._icase_fringe) self.icase_fringe_end_button = QPushButton("Default") self.icase_fringe_delta_edit = QSpinBox(self) self.icase_fringe_delta_edit.setRange(1, icase_max) self.icase_fringe_delta_edit.setSingleStep(1) self.icase_fringe_delta_edit.setValue(1) self.icase_fringe_delta_button = QPushButton("Default") self.displacement_label = QLabel("Displacement") self.icase_start = QLabel("iCase Start:") self.icase_disp_start_edit = QSpinBox(self) self.icase_disp_start_edit.setRange(0, icase_max) self.icase_disp_start_edit.setSingleStep(1) self.icase_disp_start_edit.setValue(self._icase_fringe) self.icase_disp_start_button = QPushButton("Default") self.icase_end_label = QLabel("iCase End:") self.icase_disp_end_edit = QSpinBox(self) self.icase_disp_end_edit.setRange(0, icase_max) self.icase_disp_end_edit.setSingleStep(1) self.icase_disp_end_edit.setValue(self._icase_fringe) self.icase_disp_end_button = QPushButton("Default") self.icase_delta_label = QLabel("iCase Delta:") self.icase_disp_delta_edit = QSpinBox(self) self.icase_disp_delta_edit.setRange(1, icase_max) self.icase_disp_delta_edit.setSingleStep(1) self.icase_disp_delta_edit.setValue(1) self.icase_disp_delta_button = QPushButton("Default") self.min_value_enable = QCheckBox() self.min_value_label = QLabel("Min Value:") self.min_value_edit = QLineEdit('') #self.min_value_edit.setRange(1, 1000) #self.min_value_edit.setSingleStep(1) #self.min_value_edit.setValue(1) self.min_value_button = QPushButton("Default") self.max_value_enable = QCheckBox() self.max_value_label = QLabel("Max Value:") self.max_value_edit = QLineEdit('') #self.min_value_edit.setRange(1, 1000) # TODO: update 1000 #self.min_value_edit.setSingleStep(1) #self.min_value_edit.setValue(1) self.max_value_button = QPushButton("Default") # TODO: enable this (uncomment) ------------------------------------------ #self.min_value_enable.hide() #self.min_value.hide() #self.min_value_edit.hide() #self.min_value_button.hide() #self.max_value_enable.hide() #self.max_value.hide() #self.max_value_edit.hide() #self.max_value_button.hide() # TODO: enable this (uncomment) ------------------------------------------ self.icase_disp_start_edit.setToolTip( 'The first frame of the animation') self.icase_disp_end_edit.setToolTip( 'The last frame of the animation\n' 'Assumes icase_start + nframes * icase_delta = icase_end') self.icase_disp_delta_edit.setToolTip( 'The frame step size (to skip non-consecutive results).\n' 'Frame skipping can be used to:\n' " - skip across results that you don't want to plot\n" ' - adjust the FPS') self.min_value_edit.setToolTip( 'Min value of the legend (not supported)') self.max_value_edit.setToolTip( 'Max value of the legend (not supported)') #'time' : 0., #'default_time' : 0, #'icase_start' : 10, #'icase_delta' : 3, #'min_value' : 0., #'max_value' : 1000., self.browse_folder_label = QLabel('Output Directory:') self.browse_folder_edit = QLineEdit(str(self._default_dirname)) self.browse_folder_button = QPushButton('Browse') self.browse_folder_edit.setToolTip( 'Location to save the png/gif files') self.gif_label = QLabel("Gif Filename:") self.gif_edit = QLineEdit(str(self._default_name + '.gif')) self.gif_button = QPushButton('Default') self.gif_edit.setToolTip('Name of the gif') self.gif_button.setToolTip('Sets the name of the gif to %s.gif' % self._default_name) # scale / phase if 1: # pragma: no cover self.animate_scale_radio = QRadioButton("Animate Scale") self.animate_phase_radio = QRadioButton("Animate Phase") self.animate_time_radio = QRadioButton("Animate Time") self.animate_freq_sweeep_radio = QRadioButton( "Animate Frequency Sweep") self.animate_scale_radio.setToolTip( 'Animates the scale factor based on the "Animation Type"') self.animate_time_radio.setToolTip( 'Animates the time/load/mode step') self.animate_scale_radio.setChecked(self._default_is_scale) self.animate_phase_radio.setChecked(not self._default_is_scale) self.animate_time_radio.setChecked(False) msg = 'Scale : Animates the scale factor based on the "Animation Profile"\n' if self._default_phase is None: self.animate_phase_radio.setDisabled(True) self.animate_phase_radio.setToolTip( 'Animates the phase angle ' '(only for complex results)') msg += 'Phase : Animates the phase angle (only for complex results)\n' else: self.animate_phase_radio.setToolTip("Animates the phase angle") msg += 'Phase : Animates the phase angle\n' msg += ( 'Time : Animates the time/load/mode step\n' 'Freq Sweep : Animates a complex result across a range of frequencies ' '(not supported)\n') self.animate_freq_sweeep_radio.setDisabled(True) self.animate_freq_sweeep_radio.setToolTip( 'Animates a complex result across a range of frequencies (not supported)' ) else: msg = 'Scale : Animates the scale factor based on the "Animation Profile"\n' if self._default_phase is None: #self.animate_phase_radio.setDisabled(True) #self.animate_phase_radio.setToolTip('Animates the phase angle ' #'(only for complex results)') msg += 'Phase : Animates the phase angle (only for complex results)\n' else: #self.animate_phase_radio.setToolTip("Animates the phase angle") msg += 'Phase : Animates the phase angle\n' msg += ( 'Time : Animates the time/load/mode step\n' 'Freq Sweep : Animates a complex result across a range of frequencies ' '(not supported)\n') self.animation_type = QLabel("Animation Type:") animation_type = OrderedDict() #scale_msg = 'Scale\n' #phase_msg = 'Phase\n' #time_msg = 'Time\n' #animation_types = [ #('Animate Scale', scale_msg), #('Animate Phase', phase_msg), #('Animate Time', time_msg), ##'Animate Frequency Sweep' #] if self._phase is not None: self.animation_types.append('Animate Phase') self.animation_types.append('Animate Time') self.animation_profile_label = QLabel("Animation Profile:") self.animation_profile_edit = QComboBox() for animation_profile in ANIMATION_PROFILES: self.animation_profile_edit.addItem(animation_profile) self.animation_profile_edit.setToolTip('The profile for a scaled GIF') self.animation_type_edit = QComboBox() # TODO: add a tooltip for each item for animation_type in self.animation_types: self.animation_type_edit.addItem(animation_type) #self.animation_type_edit.setToolTip('The profile for a scaled GIF') self.animation_type_edit.setToolTip(msg.rstrip()) self.csv_profile_label = QLabel("CSV profile:") self.csv_profile_edit = QLineEdit() self.csv_profile_browse_button = QPushButton('Browse') self.csv_profile_edit.setToolTip( 'The path to the CSV file of (Scale1, Scale2, Scale3, ...)') #widget = QWidget(self) #horizontal_vertical_group = QButtonGroup(widget) #horizontal_vertical_group.addButton(self.animate_scale_radio) #horizontal_vertical_group.addButton(self.animate_phase_radio) #horizontal_vertical_group.addButton(self.animate_time_radio) #horizontal_vertical_group.addButton(self.animate_freq_sweeep_radio) # animate in gui self.animate_in_gui_checkbox = QCheckBox("Animate In GUI?") self.animate_in_gui_checkbox.setChecked(True) # make images self.make_images_checkbox = QCheckBox("Make images?") self.make_images_checkbox.setChecked(True) # make images self.overwrite_images_checkbox = QCheckBox("Overwrite images?") self.overwrite_images_checkbox.setChecked(True) # delete images when finished self.delete_images_checkbox = QCheckBox("Delete images when finished?") self.delete_images_checkbox.setChecked(True) # endless loop self.repeat_checkbox = QCheckBox("Repeat?") self.repeat_checkbox.setChecked(True) self.repeat_checkbox.setToolTip( "Repeating creates an infinitely looping gif") # endless loop self.make_gif_checkbox = QCheckBox("Make Gif?") if IS_IMAGEIO: self.make_gif_checkbox.setChecked(True) else: self.make_gif_checkbox.setChecked(False) self.make_gif_checkbox.setEnabled(False) self.make_gif_checkbox.setToolTip( 'imageio is not available; install it') # bottom buttons self.step_button = QPushButton("Step") self.wipe_button = QPushButton("Wipe Deformed Shape") self.stop_button = QPushButton("Stop") self.run_button = QPushButton("Run") self.step_button.setToolTip( 'Steps through the animation (for testing)') self.wipe_button.setToolTip( 'Removes the existing "deflecton" from the animation') self.stop_button.setToolTip('Stops the animation') self.run_button.setToolTip('Creates the animation') self.step_button.hide() self.wipe_button.hide() self.wipe_button.setEnabled(False) #self.wipe_button.hide() self.stop_button.setEnabled(False) self.cancel_button = QPushButton("Close") #self.set_grid_time(enabled=False) #self.set_grid_scale(enabled=self._default_is_scale) if self._default_phase: self.on_animate_phase(force=True) set_combo_box_text(self.animation_type_edit, 'Animate Phase') else: self.on_animate_scale(force=True) def set_connections(self): """creates button actions""" self.checkbox_vector.clicked.connect(self.on_checkbox_vector) self.scale_button.clicked.connect(self.on_default_scale) self.arrow_scale_button.clicked.connect(self.on_default_arrow_scale) self.time_button.clicked.connect(self.on_default_time) self.fps_button.clicked.connect(self.on_default_fps) self.resolution_button.clicked.connect(self.on_default_resolution) self.browse_folder_button.clicked.connect(self.on_browse_folder) self.csv_profile_browse_button.clicked.connect(self.on_browse_csv) self.gif_button.clicked.connect(self.on_default_name) self.step_button.clicked.connect(self.on_step) self.wipe_button.clicked.connect(self.on_wipe) self.stop_button.clicked.connect(self.on_stop) self.run_button.clicked.connect(self.on_run) self.min_value_enable.clicked.connect(self.on_min_value_enable) self.max_value_enable.clicked.connect(self.on_max_value_enable) self.min_value_button.clicked.connect(self.on_min_value_default) self.max_value_button.clicked.connect(self.on_max_value_default) self.icase_disp_start_button.clicked.connect( self.on_update_min_max_defaults) #self.animate_scale_radio.clicked.connect(self.on_animate_scale) #self.animate_phase_radio.clicked.connect(self.on_animate_phase) #self.animate_time_radio.clicked.connect(self.on_animate_time) self.animation_type_edit.currentIndexChanged.connect(self.on_animate) #self.animate_freq_sweeep_radio self.cancel_button.clicked.connect(self.on_cancel) self.animate_in_gui_checkbox.clicked.connect(self.on_animate_in_gui) self.animate_in_gui_checkbox.setChecked(True) self.on_animate_in_gui() def on_checkbox_vector(self): is_enabled = self.checkbox_vector.isEnabled() is_checked = self.checkbox_vector.isChecked() enable_edit = is_enabled and is_checked self.icase_vector_label.setEnabled(is_checked) self.icase_vector_edit.setEnabled(enable_edit) def on_animate_in_gui(self): animate_in_gui = self.animate_in_gui_checkbox.isChecked() enable = not animate_in_gui if HIDE_WHEN_INACTIVE: self.make_images_checkbox.setVisible(enable) self.delete_images_checkbox.setVisible(enable) self.make_gif_checkbox.setVisible(enable) self.repeat_checkbox.setVisible(enable) self.resolution_button.setVisible(enable) self.resolution_label.setVisible(enable) self.resolution_edit.setVisible(enable) self.gif_label.setVisible(enable) self.gif_edit.setVisible(enable) self.gif_button.setVisible(enable) self.browse_folder_label.setVisible(enable) self.browse_folder_button.setVisible(enable) self.browse_folder_edit.setVisible(enable) self.step_button.setEnabled(enable) self.make_images_checkbox.setEnabled(enable) self.delete_images_checkbox.setEnabled(enable) self.make_gif_checkbox.setEnabled(enable) self.repeat_checkbox.setEnabled(enable) self.resolution_button.setEnabled(enable) self.resolution_edit.setEnabled(enable) self.gif_edit.setEnabled(enable) self.gif_button.setEnabled(enable) self.browse_folder_button.setEnabled(enable) self.browse_folder_edit.setEnabled(enable) self.step_button.setEnabled(enable) #wipe_button def on_animate(self, value): """ animate pulldown Parameters ---------- value : int index in animation_types """ #animation_types = ['Animate Scale', 'Animate Phase', 'Animate Time', #'Animate Frequency Sweep'] animation_type = self.animation_types[value] if animation_type == 'Animate Scale': self.on_animate_scale() elif animation_type == 'Animate Phase': self.on_animate_phase() elif animation_type == 'Animate Time': self.on_animate_time() else: raise NotImplementedError('value = ', value) def on_animate_time(self, force=False): """enables the secondary input""" #print('on_animate_time') if self._animate_type == 'scale' or force: self.set_grid_scale(False, 'time') self.set_grid_time(True, 'time') self._animate_type = 'time' def on_animate_scale(self, force=False): """enables the secondary input""" #print('on_animate_scale') self.set_grid_scale(True, 'scale') if self._animate_type == 'time' or force: self.set_grid_time(False, 'scale') self._animate_type = 'scale' def on_animate_phase(self, force=False): """enables the secondary input""" #print('on_animate_phase') if self._animate_type == 'scale' or force: self.set_grid_scale(False, 'phase') if self._animate_type == 'time' or force: self.set_grid_time(False, 'phase') self._animate_type = 'phase' def set_grid_scale(self, enabled=True, word=''): """enables/disables the secondary input""" #print('%s-set_grid_scale; enabled = %r' % (word, enabled)) if HIDE_WHEN_INACTIVE: self.box_scale.setVisible(enabled) self.animation_profile_label.setVisible(enabled) self.animation_profile_edit.setVisible(enabled) #self.min_value_enable.setVisible(enabled) #self.max_value_enable.setVisible(enabled) self.animation_profile_label.setEnabled(enabled) self.animation_profile_edit.setEnabled(enabled) # TODO: doesn't work... #self.csv_profile.setEnabled(enabled) #self.csv_profile_edit.setEnabled(enabled) #self.csv_profile_button.setEnabled(enabled) self.min_value_enable.setEnabled(enabled) self.max_value_enable.setEnabled(enabled) self.on_min_value_enable() self.on_max_value_enable() def set_grid_time(self, enabled=True, word=''): """enables/disables the secondary input""" #print('%s-set_grid_time; enabled = %r' % (word, enabled)) if HIDE_WHEN_INACTIVE: self.box_time.setVisible(enabled) self.checkbox_fringe.setVisible(not enabled) self.icase_fringe_label.setVisible(not enabled) self.icase_fringe_edit.setVisible(not enabled) self.icase_disp_label.setVisible(not enabled) self.icase_disp_edit.setVisible(not enabled) self.icase_vector_label.setVisible(not enabled) self.icase_vector_edit.setVisible(not enabled) #self.icase_fringe_delta_edit.setVisible(enabled) self.icase_disp_delta_edit.setVisible(enabled) self.icase_disp_delta_edit.setVisible(enabled) self.fps_label.setVisible(enabled) self.fps_edit.setVisible(enabled) self.fps_button.setVisible(enabled) self.displacement_label.setEnabled(enabled) self.fringe_label.setEnabled(enabled) self.icase_start.setEnabled(enabled) self.icase_disp_start_edit.setEnabled(enabled) self.icase_disp_start_button.setEnabled(enabled) self.icase_fringe_start_edit.setEnabled(enabled) self.icase_fringe_start_button.setEnabled(enabled) self.icase_end_label.setEnabled(enabled) self.icase_disp_end_edit.setEnabled(enabled) self.icase_disp_end_button.setEnabled(enabled) self.icase_fringe_end_edit.setEnabled(enabled) self.icase_fringe_end_button.setEnabled(enabled) self.icase_delta_label.setEnabled(enabled) self.icase_disp_delta_edit.setEnabled(enabled) self.icase_disp_delta_button.setEnabled(enabled) self.icase_fringe_delta_edit.setEnabled(enabled) self.icase_fringe_delta_button.setEnabled(enabled) #----------------------------------------------------------------------- is_min_enabled = self.min_value_enable.isChecked() self.min_value_label.setEnabled(is_min_enabled) self.min_value_edit.setEnabled(is_min_enabled) self.min_value_button.setEnabled(is_min_enabled) is_max_enabled = self.max_value_enable.isChecked() self.max_value_label.setEnabled(is_max_enabled) self.max_value_edit.setEnabled(is_max_enabled) self.max_value_button.setEnabled(is_max_enabled) self.min_value_enable.setEnabled(enabled) self.on_min_value_enable() #self.min_value.setEnabled(enabled) #self.min_value_edit.setEnabled(enabled) #self.min_value_button.setEnabled(enabled) self.max_value_enable.setEnabled(enabled) self.on_max_value_enable() #self.max_value.setEnabled(enabled) #self.max_value_edit.setEnabled(enabled) #self.max_value_button.setEnabled(enabled) self.icase_fringe_label.setEnabled(not enabled) self.icase_fringe_edit.setEnabled(not enabled) self.checkbox_fringe.setEnabled(not enabled) self.icase_disp_label.setEnabled(not enabled) self.icase_disp_edit.setEnabled(not enabled) self.icase_vector_label.setEnabled(not enabled) self.icase_vector_edit.setEnabled(not enabled) self.checkbox_vector.setEnabled(not enabled) self.on_checkbox_vector() self.fps_label.setEnabled(not enabled) self.fps_edit.setEnabled(not enabled) self.fps_button.setEnabled(not enabled) def on_min_value_enable(self): """ The min edit value box is enabled when we switch to time and the box is checked """ is_min_enabled = self.min_value_enable.isChecked( ) and self.min_value_enable.isEnabled() self.min_value_label.setEnabled(is_min_enabled) self.min_value_edit.setEnabled(is_min_enabled) self.min_value_button.setEnabled(is_min_enabled) def on_max_value_enable(self): """ The max edit value box is enabled when we switch to time and the box is checked """ is_max_enabled = self.max_value_enable.isChecked( ) and self.max_value_enable.isEnabled() self.max_value_label.setEnabled(is_max_enabled) self.max_value_edit.setEnabled(is_max_enabled) self.max_value_button.setEnabled(is_max_enabled) def on_update_min_max_defaults(self): """ When the icase is changed, the min/max value default message is changed """ icase = self.icase_disp_start_edit.value() min_value, max_value = self.get_min_max(icase) self.min_value_button.setToolTip('Sets the min value to %g' % min_value) self.max_value_button.setToolTip('Sets the max value to %g' % max_value) def on_min_value_default(self): """When min default icase is pressued, update the value""" icase = self.icase_disp_start_edit.value() min_value = self.get_min_max(icase)[0] self.min_value_edit.setText(str(min_value)) self.min_value_edit.setStyleSheet("QLineEdit{background: white;}") def on_max_value_default(self): """When max default icase is pressued, update the value""" icase = self.icase_disp_start_edit.value() max_value = self.get_min_max(icase)[1] self.max_value_edit.setText(str(max_value)) self.max_value_edit.setStyleSheet("QLineEdit{background: white;}") def on_browse_folder(self): """opens a folder dialog""" dirname = getexistingdirectory(parent=self, caption='Select a Directory', basedir='', options=QFileDialog.ShowDirsOnly) if not dirname: return self.browse_folder_edit.setText(dirname) def on_browse_csv(self): """opens a file dialog""" default_filename = '' file_types = 'Delimited Text (*.txt; *.dat; *.csv)' dirname = open_file_dialog(self, 'Select a CSV File', default_filename, file_types) if not dirname: return self.csv_profile_browse_button.setText(dirname) def on_default_name(self): """sets the default gif name""" self.gif_edit.setText(self._default_name + '.gif') def on_default_scale(self): """sets the default displacement scale factor""" self.scale_edit.setText(str(self._default_scale)) self.scale_edit.setStyleSheet("QLineEdit{background: white;}") def on_default_arrow_scale(self): """sets the default arrow scale factor""" self.arrow_scale_edit.setText(str(self._default_arrow_scale)) self.arrow_scale_edit.setStyleSheet("QLineEdit{background: white;}") def on_default_time(self): """sets the default gif time""" self.time_edit.setValue(self._default_time) def on_default_fps(self): """sets the default FPS""" self.fps_edit.setValue(self._default_fps) def on_default_resolution(self): """sets the default image resolution scale factor""" self.resolution_edit.setValue(self._default_resolution) def create_layout(self): """displays the menu objects""" grid = QGridLayout() irow = 0 grid.addWidget(self.icase_fringe_label, irow, 0) grid.addWidget(self.icase_fringe_edit, irow, 1) grid.addWidget(self.checkbox_fringe, irow, 2) irow += 1 grid.addWidget(self.icase_disp_label, irow, 0) grid.addWidget(self.icase_disp_edit, irow, 1) #grid.addWidget(self.checkbox_disp, irow, 2) irow += 1 grid.addWidget(self.icase_vector_label, irow, 0) grid.addWidget(self.icase_vector_edit, irow, 1) grid.addWidget(self.checkbox_vector, irow, 2) irow += 1 grid.addWidget(self.scale_label, irow, 0) grid.addWidget(self.scale_edit, irow, 1) grid.addWidget(self.scale_button, irow, 2) irow += 1 grid.addWidget(self.arrow_scale_label, irow, 0) grid.addWidget(self.arrow_scale_edit, irow, 1) grid.addWidget(self.arrow_scale_button, irow, 2) irow += 1 grid.addWidget(self.time_label, irow, 0) grid.addWidget(self.time_edit, irow, 1) grid.addWidget(self.time_button, irow, 2) irow += 1 # spacer spacer = QLabel('') grid.addWidget(self.fps_label, irow, 0) grid.addWidget(self.fps_edit, irow, 1) grid.addWidget(self.fps_button, irow, 2) irow += 1 grid.addWidget(self.animation_type, irow, 0) grid.addWidget(self.animation_type_edit, irow, 1) irow += 1 grid.addWidget(spacer, irow, 0) irow += 1 #---------- #Time grid_time = QGridLayout() jrow = 0 self.fringe_label.setAlignment(Qt.AlignCenter) self.displacement_label.setAlignment(Qt.AlignCenter) if not IS_TIME_FRINGE: self.fringe_label.hide() self.icase_fringe_delta_edit.hide() self.icase_fringe_start_edit.hide() self.icase_fringe_end_edit.hide() self.icase_fringe_delta_button.hide() grid_time.addWidget(self.displacement_label, jrow, 1) grid_time.addWidget(self.fringe_label, jrow, 2) jrow += 1 grid_time.addWidget(self.icase_start, jrow, 0) grid_time.addWidget(self.icase_disp_start_edit, jrow, 1) grid_time.addWidget(self.icase_fringe_start_edit, jrow, 2) #grid_time.addWidget(self.icase_disp_start_button, jrow, 2) jrow += 1 grid_time.addWidget(self.icase_end_label, jrow, 0) grid_time.addWidget(self.icase_disp_end_edit, jrow, 1) grid_time.addWidget(self.icase_fringe_end_edit, jrow, 2) #grid_time.addWidget(self.icase_end_button, jrow, 2) jrow += 1 grid_time.addWidget(self.icase_delta_label, jrow, 0) grid_time.addWidget(self.icase_disp_delta_edit, jrow, 1) grid_time.addWidget(self.icase_fringe_delta_edit, jrow, 2) #grid_time.addWidget(self.icase_delta_button, jrow, 2) jrow += 1 hbox_min = QHBoxLayout() hbox_min.addWidget(self.min_value_enable) hbox_min.addWidget(self.min_value_label) grid_time.addLayout(hbox_min, jrow, 0) grid_time.addWidget(self.min_value_edit, jrow, 1) grid_time.addWidget(self.min_value_button, jrow, 2) jrow += 1 hbox_max = QHBoxLayout() hbox_max.addWidget(self.max_value_enable) hbox_max.addWidget(self.max_value_label) grid_time.addLayout(hbox_max, jrow, 0) grid_time.addWidget(self.max_value_edit, jrow, 1) grid_time.addWidget(self.max_value_button, jrow, 2) jrow += 1 grid_time.addWidget(spacer, jrow, 0) jrow += 1 #-------------- grid_scale = QGridLayout() grid_scale.addWidget(self.animation_profile_label, 0, 0) grid_scale.addWidget(self.animation_profile_edit, 0, 1) #grid_scale.addWidget(self.csv_profile, 1, 0) #grid_scale.addWidget(self.csv_profile_edit, 1, 1) #grid_scale.addWidget(self.csv_profile_browse_button, 1, 2) self.csv_profile = QLabel("CSV profile:") self.csv_profile_edit = QLineEdit() self.csv_profile_button = QPushButton('Browse') #box_time = QVBoxLayout() # TODO: It's super annoying that the animate time box doesn't # line up with the previous box self.box_scale.setLayout(grid_scale) self.box_time.setLayout(grid_time) #---------- grid2 = QGridLayout() irow = 0 #grid2.addWidget(self.animate_scale_radio, 8, 0) #grid2.addWidget(self.animate_phase_radio, 8, 1) #grid2.addWidget(self.animate_time_radio, 8, 2) #grid2.addWidget(self.animate_freq_sweeep_radio, 8, 3) grid2.addWidget(self.animate_in_gui_checkbox, irow, 0) irow += 1 grid2.addWidget(self.resolution_label, irow, 0) grid2.addWidget(self.resolution_edit, irow, 1) grid2.addWidget(self.resolution_button, irow, 2) irow += 1 grid2.addWidget(self.browse_folder_label, irow, 0) grid2.addWidget(self.browse_folder_edit, irow, 1) grid2.addWidget(self.browse_folder_button, irow, 2) irow += 1 grid2.addWidget(self.gif_label, irow, 0) grid2.addWidget(self.gif_edit, irow, 1) grid2.addWidget(self.gif_button, irow, 2) irow += 1 grid2.addWidget(self.make_images_checkbox, irow, 0) #grid2.addWidget(self.overwrite_images_checkbox, irow, 0) grid2.addWidget(self.delete_images_checkbox, irow, 1) grid2.addWidget(self.make_gif_checkbox, irow, 2) irow += 1 grid2.addWidget(self.repeat_checkbox, irow, 0) irow += 1 grid2.addWidget(spacer, irow, 0) grid_hbox = QHBoxLayout() grid_hbox.addWidget(spacer) grid_hbox.addLayout(grid2) grid_hbox.addWidget(spacer) # bottom buttons step_run_box = QHBoxLayout() step_run_box.addWidget(self.step_button) step_run_box.addWidget(self.wipe_button) step_run_box.addWidget(self.stop_button) step_run_box.addWidget(self.run_button) ok_cancel_box = QHBoxLayout() ok_cancel_box.addWidget(self.cancel_button) vbox = QVBoxLayout() vbox.addLayout(grid) vbox.addWidget(self.box_scale) vbox.addWidget(self.box_time) #vbox.addLayout(checkboxes) vbox.addLayout(grid_hbox) vbox.addStretch() vbox.addLayout(step_run_box) vbox.addLayout(ok_cancel_box) self.setLayout(vbox) def on_step(self): """click the Step button""" passed, validate_out = self.on_validate() if passed: try: self._make_gif(validate_out, istep=self.istep) self.istep += 1 except IndexError: self._make_gif(validate_out, istep=0) self.istep += 1 self.wipe_button.setEnabled(True) def on_wipe(self): """click the Wipe button""" passed, validate_out = self.on_validate(wipe=True) if passed: self.istep = 0 self._make_gif(validate_out, istep=self.istep) self.wipe_button.setEnabled(False) self.stop_button.setEnabled(False) def on_stop(self): """click the Stop button""" #passed, validate_out = self.on_validate() #if passed: #self._make_gif(validate_out, stop_animation=True) if self.is_gui: self.win_parent.win_parent.stop_animation() self.wipe_button.setEnabled(True) self.stop_button.setEnabled(False) def on_run(self): """click the Run button""" self.istep = 0 self.wipe_button.setEnabled(False) self.stop_button.setEnabled(True) passed, validate_out = self.on_validate() if passed: self._make_gif(validate_out, istep=None) return passed def _make_gif(self, validate_out, istep=None, stop_animation=False): """interface for making the gif""" (icase_fringe, icase_disp, icase_vector, scale, time, fps, animate_in_gui, magnify, output_dir, gifbase, min_value, max_value) = validate_out fps = int(fps) gif_filename = None if not stop_animation and not animate_in_gui and gifbase is not None: if gifbase.lower().endswith('.gif'): gifbase = gifbase[:-4] gif_filename = os.path.join(output_dir, gifbase + '.gif') animate_fringe = self.checkbox_fringe.isChecked() animate_vector = self.checkbox_vector.isChecked() animate_scale = self.animate_scale_radio.isChecked() animate_phase = self.animate_phase_radio.isChecked() animate_time = self.animate_time_radio.isChecked() if not self.checkbox_vector.isEnabled(): icase_vector = None animate_scale = False animate_phase = False animate_time = False if self._animate_type == 'scale': animate_scale = True elif self._animate_type == 'phase': animate_phase = True elif self._animate_type == 'time': animate_time = True else: raise NotImplementedError(self._animate_type) make_images = self.make_images_checkbox.isChecked() delete_images = self.delete_images_checkbox.isChecked() make_gif = self.make_gif_checkbox.isChecked() animation_profile = str(self.animation_profile_edit.currentText()) icase_disp_start = self.icase_disp_start_edit.value() icase_disp_end = self.icase_disp_end_edit.value() icase_disp_delta = self.icase_disp_delta_edit.value() bool_repeat = self.repeat_checkbox.isChecked( ) # TODO: change this to an integer if bool_repeat: nrepeat = 0 else: nrepeat = 1 #self.out_data['is_shown'] = self.show_radio.isChecked() #icase = self._icase if self.is_gui: self.win_parent.win_parent.make_gif( gif_filename, scale, istep=istep, animate_scale=animate_scale, animate_phase=animate_phase, animate_time=animate_time, icase_fringe=icase_fringe, icase_disp=icase_disp, icase_vector=icase_vector, animate_fringe=animate_fringe, animate_vector=animate_vector, icase_start=icase_disp_start, icase_end=icase_disp_end, icase_delta=icase_disp_delta, time=time, animation_profile=animation_profile, nrepeat=nrepeat, fps=fps, magnify=magnify, make_images=make_images, delete_images=delete_images, make_gif=make_gif, stop_animation=stop_animation, animate_in_gui=animate_in_gui, min_value=min_value, max_value=max_value, ) self.out_data['clicked_ok'] = True self.out_data['close'] = True def get_min_max(self, icase): if self.is_gui: (obj, (i, name)) = self.win_parent.win_parent.result_cases[icase] min_value, max_value = obj.get_min_max(i, name) else: return 0., 1.0 return min_value, max_value def on_validate(self, wipe=False): """checks to see if the input is valid""" # requires no special validation icase_fringe, flag0 = check_int(self.icase_fringe_edit) icase_disp, unused_flaga = check_int(self.icase_disp_edit) icase_vector, unused_flagb = check_int(self.icase_vector_edit) #icase_disp = self._icase_disp #icase_vector = self._icase_vector scale, flag1 = check_float(self.scale_edit) time, flag2 = check_float(self.time_edit) fps, flag3 = check_float(self.fps_edit) min_value = max_value = None flag4 = flag5 = True if self.min_value_edit.isEnabled(): min_value, flag4 = check_float(self.min_value_edit) if self.max_value_edit.isEnabled(): max_value, flag5 = check_float(self.max_value_edit) if wipe: animate_in_gui = False scale = 0. flag1 = True else: animate_in_gui = self.animate_in_gui_checkbox.isChecked() if animate_in_gui or wipe: passed = all([flag0, flag1, flag2, flag3, flag4, flag5]) magnify, output_dir, gifbase = None, None, None else: magnify, flag6 = check_int(self.resolution_edit) output_dir, flag7 = self.check_path(self.browse_folder_edit) gifbase, flag8 = self.check_name(self.gif_edit) passed = all([ flag0, flag1, flag2, flag3, flag4, flag5, flag6, flag7, flag8 ]) return passed, (icase_fringe, icase_disp, icase_vector, scale, time, fps, animate_in_gui, magnify, output_dir, gifbase, min_value, max_value) @staticmethod def check_name(cell): """verifies that the data is string-able""" cell_value = cell.text() try: text = str(cell_value).strip() except UnicodeEncodeError: cell.setStyleSheet("QLineEdit{background: red;}") return None, False if len(text): cell.setStyleSheet("QLineEdit{background: white;}") return text, True else: cell.setStyleSheet("QLineEdit{background: red;}") return None, False def check_path(self, cell): """verifies that the path exists""" text, passed = self.check_name(cell) if not passed: return None, False if os.path.exists(text): cell.setStyleSheet("QLineEdit{background: white;}") return text, True else: cell.setStyleSheet("QLineEdit{background: red;}") return None, False #def on_ok(self): #"""click the OK button""" #passed = self.on_apply() #if passed: #self.win_parent._animation_window_shown = False #self.close() ##self.destroy() def on_cancel(self): """click the Cancel button""" self.on_stop() self.out_data['close'] = True self.close()
class ChannelProperty(QWidget): """ For manipulate chanel properties. 1. Apply gaussian blur to channel 2. Fixed range for coloring In future should be extended :param settings: for storing internal state. allow keep state between sessions :param start_name: name used to select proper information from settings object. Introduced for case with multiple image view. """ def __init__(self, settings: ViewSettings, start_name: str): if start_name == "": raise ValueError( "ChannelProperty should have non empty start_name") super().__init__() self.current_name = start_name self.current_channel = 0 self._settings = settings self.widget_dict: typing.Dict[str, ColorComboBoxGroup] = {} self.minimum_value = CustomSpinBox(self) self.minimum_value.setRange(-(10**6), 10**6) self.minimum_value.valueChanged.connect(self.range_changed) self.maximum_value = CustomSpinBox(self) self.maximum_value.setRange(-(10**6), 10**6) self.maximum_value.valueChanged.connect(self.range_changed) self.fixed = QCheckBox("Fix range") self.fixed.stateChanged.connect(self.lock_channel) self.use_filter = QEnumComboBox(enum_class=NoiseFilterType) self.use_filter.setToolTip("Only current channel") self.filter_radius = QDoubleSpinBox() self.filter_radius.setSingleStep(0.1) self.filter_radius.valueChanged.connect(self.gauss_radius_changed) self.use_filter.currentIndexChanged.connect(self.gauss_use_changed) self.gamma_value = QDoubleSpinBox() self.gamma_value.setRange(0.01, 100) self.gamma_value.setSingleStep(0.1) self.gamma_value.valueChanged.connect(self.gamma_value_changed) self.collapse_widget = CollapseCheckbox("Channel property") self.collapse_widget.add_hide_element(self.minimum_value) self.collapse_widget.add_hide_element(self.maximum_value) self.collapse_widget.add_hide_element(self.fixed) self.collapse_widget.add_hide_element(self.use_filter) self.collapse_widget.add_hide_element(self.filter_radius) self.collapse_widget.add_hide_element(self.gamma_value) layout = QGridLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.collapse_widget, 0, 0, 1, 4) label1 = QLabel("Min bright:") layout.addWidget(label1, 1, 0) layout.addWidget(self.minimum_value, 1, 1) label2 = QLabel("Max bright:") layout.addWidget(label2, 2, 0) layout.addWidget(self.maximum_value, 2, 1) layout.addWidget(self.fixed, 1, 2, 1, 2) label3 = QLabel("Filter:") layout.addWidget(label3, 3, 0, 1, 1) layout.addWidget(self.use_filter, 3, 1, 1, 1) layout.addWidget(self.filter_radius, 3, 2, 1, 1) label4 = QLabel("Gamma:") layout.addWidget(label4, 4, 0, 1, 1) layout.addWidget(self.gamma_value, 4, 1, 1, 1) self.setLayout(layout) self.collapse_widget.add_hide_element(label1) self.collapse_widget.add_hide_element(label2) self.collapse_widget.add_hide_element(label3) self.collapse_widget.add_hide_element(label4) def send_info(self): """send info to""" widget = self.widget_dict[self.current_name] widget.parameters_changed(self.current_channel) def register_widget(self, widget: "ColorComboBoxGroup") -> None: """ Register new viewer by its color combo box group :param ColorComboBoxGroup widget: viewer widget for color control """ if widget.viewer_name in self.widget_dict: raise ValueError(f"name {widget.viewer_name} already register") self.widget_dict[widget.viewer_name] = widget self._settings.connect_to_profile(widget.viewer_name, self.refresh_values) self.change_current(widget.viewer_name, 0) def refresh_values(self, path: typing.Optional[str]): if path is None or path.startswith(self.current_name): self.change_current(self.current_name, self.current_channel) def change_current(self, name: str, channel: int) -> None: """ Change to show values connected with channel `channel` from viewer `viewer` :param str name: name of viewer :param int channel: channel to which data should be presented :rtype: None """ if name not in self.widget_dict: raise ValueError(f"name {name} not in register") self.current_name = name self.current_channel = channel block = self.blockSignals(True) self.minimum_value.blockSignals(True) self.minimum_value.setValue( self._settings.get_from_profile( f"{self.current_name}.range_{self.current_channel}", (0, 65000))[0]) self.minimum_value.blockSignals(False) self.maximum_value.setValue( self._settings.get_from_profile( f"{self.current_name}.range_{self.current_channel}", (0, 65000))[1]) self.use_filter.setCurrentEnum( self._settings.get_from_profile( f"{self.current_name}.use_filter_{self.current_channel}", NoiseFilterType.No)) self.filter_radius.setValue( self._settings.get_from_profile( f"{self.current_name}.filter_radius_{self.current_channel}", 1)) self.fixed.setChecked( self._settings.get_from_profile( f"{self.current_name}.lock_{self.current_channel}", False)) self.gamma_value.setValue( self._settings.get_from_profile( f"{self.current_name}.gamma_value_{self.current_channel}", 1)) self.blockSignals(block) def gamma_value_changed(self): self._settings.set_in_profile( f"{self.current_name}.gamma_value_{self.current_channel}", self.gamma_value.value()) self.send_info() def gauss_radius_changed(self): self._settings.set_in_profile( f"{self.current_name}.filter_radius_{self.current_channel}", self.filter_radius.value()) if self.use_filter.currentEnum() != NoiseFilterType.No: self.send_info() def gauss_use_changed(self): self._settings.set_in_profile( f"{self.current_name}.use_filter_{self.current_channel}", self.use_filter.currentEnum()) if self.use_filter.currentEnum() == NoiseFilterType.Median: self.filter_radius.setDecimals(0) self.filter_radius.setSingleStep(1) else: self.filter_radius.setDecimals(2) self.filter_radius.setSingleStep(0.1) self.send_info() def lock_channel(self, value): self._settings.set_in_profile( f"{self.current_name}.lock_{self.current_channel}", value) self.send_info() def range_changed(self): self._settings.set_in_profile( f"{self.current_name}.range_{self.current_channel}", (self.minimum_value.value(), self.maximum_value.value()), ) if self.fixed.isChecked(): self.send_info()
class PreferencesWindow(PyDialog): """ +-------------+ | Preferences | +---------------------------------+ | Text Size ______ Default | | Annotation Color ______ | | Annotation Size ______ | | Picker Size ______ | | Back Color ______ | | Text Color ______ | | | | Apply OK Cancel | +---------------------------------+ """ def __init__(self, data, win_parent=None): """ Saves the data members from data and performs type checks """ PyDialog.__init__(self, data, win_parent) self._updated_preference = False self._default_font_size = data['font_size'] self._default_text_size = 14 self._default_annotation_size = 18 self._default_coord_scale = 0.05 * 100. self._default_coord_text_scale = 0.5 * 100. self._default_clipping_min = data['min_clip'] self._default_clipping_max = data['max_clip'] #self._default_annotation_size = data['annotation_size'] # int #self.default_magnify = data['magnify'] self.dim_max = data['dim_max'] self._use_gradient_background = data['use_gradient_background'] # bool self._show_corner_coord = data['show_corner_coord'] self._annotation_size = data['annotation_size'] # int #self.out_data = data self._picker_size = data['picker_size'] * 100. self._coord_scale = data['coord_scale'] * 100. self._coord_text_scale = data['coord_text_scale'] * 100. self._magnify = data['magnify'] self._text_size = data['text_size'] self._highlight_opacity = data['highlight_opacity'] self.annotation_color_float, self.annotation_color_int = _check_color( data['annotation_color']) self.background_color_float, self.background_color_int = _check_color( data['background_color']) self.background_color2_float, self.background_color2_int = _check_color( data['background_color2']) self.text_color_float, self.text_color_int = _check_color( data['text_color']) self.highlight_color_float, self.highlight_color_int = _check_color( data['highlight_color']) self._nastran_is_element_quality = data['nastran_is_element_quality'] self._nastran_is_properties = data['nastran_is_properties'] self._nastran_is_3d_bars = data['nastran_is_3d_bars'] self._nastran_is_3d_bars_update = data['nastran_is_3d_bars_update'] self._nastran_is_bar_axes = data['nastran_is_bar_axes'] self._nastran_create_coords = data['nastran_create_coords'] self.setWindowTitle('Preferences') self.create_widgets() self.create_layout() self.set_connections() self.on_font(self._default_font_size) self.on_gradient_scale() #self.show() def create_widgets(self): """creates the display window""" # Text Size self.font_size_label = QLabel("Font Size:") self.font_size_edit = QSpinBox(self) self.font_size_edit.setValue(self._default_font_size) self.font_size_edit.setRange(7, 20) self.font_size_button = QPushButton("Default") #----------------------------------------------------------------------- # Annotation Color self.annotation_color_label = QLabel("Annotation Color:") self.annotation_color_edit = QPushButtonColor( self.annotation_color_int) self.annotation_color_label.hide() self.annotation_color_edit.hide() #----------------------------------------------------------------------- # Text Color self.text_size_label = QLabel("Text Size:") self.text_size_edit = QSpinBox(self) self.text_size_edit.setValue(self._default_text_size) self.text_size_edit.setRange(7, 30) self.text_size_button = QPushButton("Default") # Text Color self.text_color_label = QLabel("Text Color:") self.text_color_edit = QPushButtonColor(self.text_color_int) #----------------------------------------------------------------------- # Highlight Color self.highlight_opacity_label = QLabel("Highlight Opacity:") self.highlight_opacity_edit = QDoubleSpinBox(self) self.highlight_opacity_edit.setValue(self._highlight_opacity) self.highlight_opacity_edit.setRange(0.1, 1.0) self.highlight_opacity_edit.setDecimals(1) self.highlight_opacity_edit.setSingleStep(0.1) self.highlight_opacity_button = QPushButton("Default") # Text Color self.highlight_color_label = QLabel("Highlight Color:") self.highlight_color_edit = QPushButtonColor(self.highlight_color_int) #----------------------------------------------------------------------- # Background Color self.background_color_label = QLabel("Btm Background Color:") self.background_color_edit = QPushButtonColor( self.background_color_int) # Background Color2 self.gradient_scale_label = QLabel("Gradient Background:") self.gradient_scale_checkbox = QCheckBox() self.gradient_scale_checkbox.setChecked(self._use_gradient_background) self.background_color2_label = QLabel("Top Background Color:") self.background_color2_edit = QPushButtonColor( self.background_color2_int) #----------------------------------------------------------------------- # Annotation Size self.annotation_size_label = QLabel("Annotation Size:") self.annotation_size_edit = QSpinBox(self) self.annotation_size_edit.setRange(1, 500) self.annotation_size_edit.setValue(self._annotation_size) self.annotation_size_button = QPushButton("Default") #----------------------------------------------------------------------- # Picker Size self.picker_size_label = QLabel("Picker Size (% of Screen):") self.picker_size_edit = QDoubleSpinBox(self) self.picker_size_edit.setRange(0., 10.) log_dim = log10(self.dim_max) decimals = int(ceil(abs(log_dim))) decimals = max(6, decimals) self.picker_size_edit.setDecimals(decimals) self.picker_size_edit.setSingleStep(10. / 5000.) self.picker_size_edit.setValue(self._picker_size) #----------------------------------------------------------------------- # Clipping Min self.clipping_min_label = QLabel("Clipping Min:") self.clipping_min_edit = QLineEdit(str(self._default_clipping_min)) self.clipping_min_button = QPushButton("Default") # Clipping Max self.clipping_max_label = QLabel("Clipping Max:") self.clipping_max_edit = QLineEdit(str(self._default_clipping_max)) self.clipping_max_button = QPushButton("Default") #----------------------------------------------------------------------- self.coord_scale_label = QLabel('Coordinate System Scale:') self.coord_scale_button = QPushButton("Default") self.coord_scale_edit = QDoubleSpinBox(self) self.coord_scale_edit.setRange(0.1, 1000.) self.coord_scale_edit.setDecimals(3) self.coord_scale_edit.setSingleStep(2.5) self.coord_scale_edit.setValue(self._coord_scale) self.coord_text_scale_label = QLabel('Coordinate System Text Scale:') self.coord_text_scale_button = QPushButton("Default") self.coord_text_scale_edit = QDoubleSpinBox(self) self.coord_text_scale_edit.setRange(0.1, 2000.) self.coord_text_scale_edit.setDecimals(3) self.coord_text_scale_edit.setSingleStep(2.5) self.coord_text_scale_edit.setValue(self._coord_text_scale) # Show corner coord self.corner_coord_label = QLabel("Show Corner Coordinate System:") self.corner_coord_checkbox = QCheckBox() self.corner_coord_checkbox.setChecked(self._show_corner_coord) #----------------------------------------------------------------------- self.magnify_label = QLabel('Screenshot Magnify:') self.magnify_edit = QSpinBox(self) self.magnify_edit.setMinimum(1) self.magnify_edit.setMaximum(10) self.magnify_edit.setValue(self._magnify) #----------------------------------------------------------------------- self.nastran_is_element_quality_checkbox = QCheckBox('Element Quality') self.nastran_is_properties_checkbox = QCheckBox('Properties') self.nastran_is_3d_bars_checkbox = QCheckBox('3D Bars') self.nastran_is_3d_bars_update_checkbox = QCheckBox('Update 3D Bars') self.nastran_create_coords_checkbox = QCheckBox('Coords') self.nastran_is_bar_axes_checkbox = QCheckBox('Bar Axes') self.nastran_is_3d_bars_checkbox.setDisabled(True) self.nastran_is_3d_bars_update_checkbox.setDisabled(True) #self.nastran_is_bar_axes_checkbox.setDisabled(True) self.nastran_is_element_quality_checkbox.setChecked( self._nastran_is_element_quality) self.nastran_is_properties_checkbox.setChecked( self._nastran_is_properties) self.nastran_is_3d_bars_checkbox.setChecked(self._nastran_is_3d_bars) #self.nastran_is_3d_bars_update_checkbox.setChecked(self._nastran_is_3d_bars_update) self.nastran_is_3d_bars_update_checkbox.setChecked(False) self.nastran_is_bar_axes_checkbox.setChecked(self._nastran_is_bar_axes) self.nastran_create_coords_checkbox.setChecked( self._nastran_create_coords) #----------------------------------------------------------------------- # closing self.apply_button = QPushButton("Apply") self.ok_button = QPushButton("OK") self.cancel_button = QPushButton("Cancel") #def create_legend_widgets(self): #""" #Creates the widgets for the legend control #Name Itailic Bold Font #==== ======= ===== ======== #Title check check pulldown #Label check check pulldown #""" #self.name_label = QLabel("Name:") #self.italic_label = QLabel("Italic:") #self.bold_label = QLabel("Bold:") #self.font_label = QLabel("Font:") #self.legend_label = QLabel("Legend:") #self.legend_title_name = QLabel("Title") #self.legend_title_italic_check = QCheckBox() #self.legend_title_bold_check = QCheckBox() #self.legend_title_font_edit = QComboBox() #self.legend_title_font_edit.addItems(['cat', 'dog', 'frog']) #self.legend_label_italic_name = QLabel("Label") #self.legend_label_italic_check = QCheckBox() #self.legend_label_bold_check = QCheckBox() #self.legend_label_font_edit = QComboBox() #self.legend_label_font_edit.addItems(['cat2', 'dog2', 'frog2']) #def create_legend_layout(self): #""" #Creates the layout for the legend control #Name Itailic Bold Font #==== ======= ===== ======== #Title check check pulldown #Label check check pulldown #""" #grid2 = QGridLayout() #grid2.addWidget(self.legend_label, 0, 0) #grid2.addWidget(self.name_label, 1, 0) #grid2.addWidget(self.italic_label, 1, 1) #grid2.addWidget(self.bold_label, 1, 2) #grid2.addWidget(self.font_label, 1, 3) #grid2.addWidget(self.legend_title_name, 2, 0) #grid2.addWidget(self.legend_title_italic_check, 2, 1) #grid2.addWidget(self.legend_title_bold_check, 2, 2) #grid2.addWidget(self.legend_title_font_edit, 2, 3) #grid2.addWidget(self.legend_label_italic_name, 3, 0) #grid2.addWidget(self.legend_label_italic_check, 3, 1) #grid2.addWidget(self.legend_label_bold_check, 3, 2) #grid2.addWidget(self.legend_label_font_edit, 3, 3) #return grid2 def create_layout(self): grid = QGridLayout() irow = 0 grid.addWidget(self.font_size_label, irow, 0) grid.addWidget(self.font_size_edit, irow, 1) grid.addWidget(self.font_size_button, irow, 2) irow += 1 grid.addWidget(self.gradient_scale_label, irow, 0) grid.addWidget(self.gradient_scale_checkbox, irow, 1) irow += 1 grid.addWidget(self.background_color2_label, irow, 0) grid.addWidget(self.background_color2_edit, irow, 1) irow += 1 grid.addWidget(self.background_color_label, irow, 0) grid.addWidget(self.background_color_edit, irow, 1) irow += 1 grid.addWidget(self.highlight_color_label, irow, 0) grid.addWidget(self.highlight_color_edit, irow, 1) irow += 1 grid.addWidget(self.highlight_opacity_label, irow, 0) grid.addWidget(self.highlight_opacity_edit, irow, 1) irow += 1 grid.addWidget(self.text_color_label, irow, 0) grid.addWidget(self.text_color_edit, irow, 1) irow += 1 grid.addWidget(self.text_size_label, irow, 0) grid.addWidget(self.text_size_edit, irow, 1) grid.addWidget(self.text_size_button, irow, 2) irow += 1 grid.addWidget(self.annotation_color_label, irow, 0) grid.addWidget(self.annotation_color_edit, irow, 1) irow += 1 grid.addWidget(self.annotation_size_label, irow, 0) grid.addWidget(self.annotation_size_edit, irow, 1) grid.addWidget(self.annotation_size_button, irow, 2) irow += 1 #grid.addWidget(self.clipping_min_label, irow, 0) #grid.addWidget(self.clipping_min_edit, irow, 1) #grid.addWidget(self.clipping_min_button, irow, 2) #irow += 1 #grid.addWidget(self.clipping_max_label, irow, 0) #grid.addWidget(self.clipping_max_edit, irow, 1) #grid.addWidget(self.clipping_max_button, irow, 2) #irow += 1 grid.addWidget(self.corner_coord_label, irow, 0) grid.addWidget(self.corner_coord_checkbox, irow, 1) irow += 1 grid.addWidget(self.coord_scale_label, irow, 0) grid.addWidget(self.coord_scale_edit, irow, 1) grid.addWidget(self.coord_scale_button, irow, 2) irow += 1 grid.addWidget(self.coord_text_scale_label, irow, 0) grid.addWidget(self.coord_text_scale_edit, irow, 1) grid.addWidget(self.coord_text_scale_button, irow, 2) irow += 1 #----------------------------------------------- grid.addWidget(self.magnify_label, irow, 0) grid.addWidget(self.magnify_edit, irow, 1) irow += 1 grid.addWidget(self.picker_size_label, irow, 0) grid.addWidget(self.picker_size_edit, irow, 1) irow += 1 #-------------------------------------------------- grid_nastran = QGridLayout() irow = 0 grid_nastran.addWidget(self.nastran_create_coords_checkbox, irow, 0) irow += 1 grid_nastran.addWidget(self.nastran_is_element_quality_checkbox, irow, 0) grid_nastran.addWidget(self.nastran_is_properties_checkbox, irow, 1) irow += 1 grid_nastran.addWidget(self.nastran_is_bar_axes_checkbox, irow, 0) irow += 1 grid_nastran.addWidget(self.nastran_is_3d_bars_checkbox, irow, 0) grid_nastran.addWidget(self.nastran_is_3d_bars_update_checkbox, irow, 1) irow += 1 #bold_font = make_font(self._default_font_size, is_bold=True) vbox_nastran = QVBoxLayout() self.nastran_label = QLabel('Nastran:') vbox_nastran.addWidget(self.nastran_label) vbox_nastran.addLayout(grid_nastran) #self.create_legend_widgets() #grid2 = self.create_legend_layout() ok_cancel_box = QHBoxLayout() ok_cancel_box.addWidget(self.apply_button) ok_cancel_box.addWidget(self.ok_button) ok_cancel_box.addWidget(self.cancel_button) vbox = QVBoxLayout() vbox.addLayout(grid) vbox.addLayout(vbox_nastran) #vbox.addStretch() #vbox.addLayout(grid2) vbox.addStretch() vbox.addLayout(ok_cancel_box) self.setLayout(vbox) def set_connections(self): """creates the actions for the menu""" self.font_size_button.clicked.connect(self.on_default_font_size) self.font_size_edit.valueChanged.connect(self.on_font) self.annotation_size_edit.editingFinished.connect( self.on_annotation_size) self.annotation_size_edit.valueChanged.connect(self.on_annotation_size) self.annotation_color_edit.clicked.connect(self.on_annotation_color) self.annotation_size_button.clicked.connect( self.on_default_annotation_size) self.background_color_edit.clicked.connect(self.on_background_color) self.background_color2_edit.clicked.connect(self.on_background_color2) self.gradient_scale_checkbox.clicked.connect(self.on_gradient_scale) self.highlight_color_edit.clicked.connect(self.on_highlight_color) self.highlight_opacity_edit.valueChanged.connect( self.on_highlight_opacity) self.text_color_edit.clicked.connect(self.on_text_color) self.text_size_edit.valueChanged.connect(self.on_text_size) self.text_size_button.clicked.connect(self.on_default_text_size) self.picker_size_edit.valueChanged.connect(self.on_picker_size) self.picker_size_edit.editingFinished.connect(self.on_picker_size) self.coord_scale_edit.valueChanged.connect(self.on_coord_scale) self.coord_scale_edit.editingFinished.connect(self.on_coord_scale) self.coord_scale_button.clicked.connect(self.on_default_coord_scale) self.corner_coord_checkbox.clicked.connect(self.on_corner_coord) self.coord_text_scale_edit.valueChanged.connect( self.on_coord_text_scale) self.coord_text_scale_edit.editingFinished.connect( self.on_coord_text_scale) self.coord_text_scale_button.clicked.connect( self.on_default_coord_text_scale) self.magnify_edit.valueChanged.connect(self.on_magnify) self.magnify_edit.editingFinished.connect(self.on_magnify) self.clipping_min_button.clicked.connect(self.on_default_clipping_min) self.clipping_max_button.clicked.connect(self.on_default_clipping_max) #------------------------------------ # format-specific self.nastran_is_element_quality_checkbox.clicked.connect( self.on_nastran_is_element_quality) self.nastran_is_properties_checkbox.clicked.connect( self.on_nastran_is_properties) self.nastran_is_3d_bars_checkbox.clicked.connect( self.on_nastran_is_3d_bars) self.nastran_is_3d_bars_update_checkbox.clicked.connect( self.on_nastran_is_3d_bars) self.nastran_is_bar_axes_checkbox.clicked.connect( self.on_nastran_is_bar_axes) self.nastran_create_coords_checkbox.clicked.connect( self.on_nastran_create_coords) #------------------------------------ self.apply_button.clicked.connect(self.on_apply) self.ok_button.clicked.connect(self.on_ok) self.cancel_button.clicked.connect(self.on_cancel) # closeEvent def on_nastran_is_element_quality(self): """set the nastran element quality preferences""" is_checked = self.nastran_is_element_quality_checkbox.isChecked() if self.win_parent is not None: self.win_parent.settings.nastran_is_element_quality = is_checked def on_nastran_is_properties(self): """set the nastran properties preferences""" is_checked = self.nastran_is_properties_checkbox.isChecked() if self.win_parent is not None: self.win_parent.settings.nastran_is_properties = is_checked def on_nastran_is_3d_bars(self): """set the nastran properties preferences""" is_checked = self.nastran_is_3d_bars_checkbox.isChecked() if self.win_parent is not None: self.win_parent.settings.nastran_is_3d_bars = is_checked def on_nastran_is_3d_bars_update(self): """set the nastran properties preferences""" is_checked = self.nastran_is_3d_bars_update_checkbox.isChecked() if self.win_parent is not None: self.win_parent.settings.nastran_is_3d_bars_update = is_checked def on_nastran_is_bar_axes(self): """set the nastran properties preferences""" is_checked = self.nastran_is_bar_axes_checkbox.isChecked() if self.win_parent is not None: self.win_parent.settings.nastran_is_bar_axes = is_checked def on_nastran_create_coords(self): """set the nastran properties preferences""" is_checked = self.nastran_create_coords_checkbox.isChecked() if self.win_parent is not None: self.win_parent.settings.nastran_create_coords = is_checked def on_font(self, value=None): """update the font for the current window""" if value is None: value = self.font_size_edit.value() font = QtGui.QFont() font.setPointSize(value) self.setFont(font) bold_font = make_font(value, is_bold=True) self.nastran_label.setFont(bold_font) def on_annotation_size(self, value=None): """update the annotation size""" if value is None: value = int(self.annotation_size_edit.text()) self._annotation_size = value #self.on_apply(force=True) #self.min_edit.setText(str(self._default_min)) #self.min_edit.setStyleSheet("QLineEdit{background: white;}") self.update_annotation_size_color() def update_annotation_size_color(self): if self.win_parent is not None: self.win_parent.settings.set_annotation_size_color( size=self._annotation_size) def on_gradient_scale(self): is_checked = self.gradient_scale_checkbox.isChecked() self.background_color2_label.setEnabled(is_checked) self.background_color2_edit.setEnabled(is_checked) if self.win_parent is not None: self.win_parent.settings.set_gradient_background( use_gradient_background=is_checked) def on_corner_coord(self): is_checked = self.corner_coord_checkbox.isChecked() if self.win_parent is not None: self.win_parent.set_corner_axis_visiblity(is_checked, render=True) def on_annotation_color(self): rgb_color_ints = self.annotation_color_int title = "Choose an annotation color" passed, rgb_color_ints, rgb_color_floats = self.on_color( self.annotation_color_edit, rgb_color_ints, title) if passed: self.annotation_color_int = rgb_color_ints self.annotation_color_float = rgb_color_floats self.update_annotation_size_color() def on_background_color(self): """ Choose a background color""" title = "Choose a primary background color" rgb_color_ints = self.background_color_int color_edit = self.background_color_edit func_name = 'set_background_color' passed, rgb_color_ints, rgb_color_floats = self._background_color( title, color_edit, rgb_color_ints, func_name) if passed: self.background_color_int = rgb_color_ints self.background_color_float = rgb_color_floats def on_background_color2(self): """ Choose a background color""" title = "Choose a secondary background color" rgb_color_ints = self.background_color2_int color_edit = self.background_color2_edit func_name = 'set_background_color2' passed, rgb_color_ints, rgb_color_floats = self._background_color( title, color_edit, rgb_color_ints, func_name) if passed: self.background_color2_int = rgb_color_ints self.background_color2_float = rgb_color_floats def on_highlight_color(self): """ Choose a highlight color""" title = "Choose a highlight color" rgb_color_ints = self.highlight_color_int color_edit = self.highlight_color_edit func_name = 'set_highlight_color' passed, rgb_color_ints, rgb_color_floats = self._background_color( title, color_edit, rgb_color_ints, func_name) if passed: self.highlight_color_int = rgb_color_ints self.highlight_color_float = rgb_color_floats def on_highlight_opacity(self, value=None): if value is None: value = self.highlight_opacity_edit.value() self._highlight_opacity = value if self.win_parent is not None: self.win_parent.settings.set_highlight_opacity(value) def _background_color(self, title, color_edit, rgb_color_ints, func_name): """helper method for ``on_background_color`` and ``on_background_color2``""" passed, rgb_color_ints, rgb_color_floats = self.on_color( color_edit, rgb_color_ints, title) if passed: if self.win_parent is not None: settings = self.win_parent.settings func_background_color = getattr(settings, func_name) func_background_color(rgb_color_floats) return passed, rgb_color_ints, rgb_color_floats def on_text_color(self): """ Choose a text color """ rgb_color_ints = self.text_color_int title = "Choose a text color" passed, rgb_color_ints, rgb_color_floats = self.on_color( self.text_color_edit, rgb_color_ints, title) if passed: self.text_color_int = rgb_color_ints self.text_color_float = rgb_color_floats if self.win_parent is not None: self.win_parent.settings.set_text_color(rgb_color_floats) def on_default_text_size(self): self.text_size_edit.setValue(self._default_text_size) self.on_text_size(self._default_text_size) def on_text_size(self, value=None): if value is None: value = self.text_size_edit.value() self._text_size = value if self.win_parent is not None: self.win_parent.settings.set_text_size(value) def on_color(self, color_edit, rgb_color_ints, title): """pops a color dialog""" col = QColorDialog.getColor(QtGui.QColor(*rgb_color_ints), self, title) if not col.isValid(): return False, rgb_color_ints, None color_float = col.getRgbF()[:3] # floats color_int = [int(colori * 255) for colori in color_float] assert isinstance(color_float[0], float), color_float assert isinstance(color_int[0], int), color_int color_edit.setStyleSheet("QPushButton {" "background-color: rgb(%s, %s, %s);" % tuple(color_int) + #"border:1px solid rgb(255, 170, 255); " "}") return True, color_int, color_float def on_picker_size(self): self._picker_size = float(self.picker_size_edit.text()) if self.win_parent is not None: self.win_parent.element_picker_size = self._picker_size / 100. #self.on_apply(force=True) def on_magnify(self, value=None): if value is None: value = self.magnify_edit.value() self._magnify = value if self.win_parent is not None: self.win_parent.settings.set_magnify(value) #--------------------------------------------------------------------------- def on_coord_scale(self, value=None): if value is None: value = self.coord_scale_edit.value() self._coord_scale = value if self.win_parent is not None: self.win_parent.settings.set_coord_scale(value / 100.) def on_default_coord_scale(self): self.coord_scale_edit.setValue(self._default_coord_scale) self.on_coord_scale(self._default_coord_scale) def on_coord_text_scale(self, value=None): if value is None: value = self.coord_text_scale_edit.value() self._coord_text_scale = value if self.win_parent is not None: self.win_parent.settings.set_coord_text_scale(value / 100.) def on_default_coord_text_scale(self): self.coord_text_scale_edit.setValue(self._default_coord_text_scale) self.on_coord_text_scale(self._default_coord_text_scale) #--------------------------------------------------------------------------- def on_default_font_size(self): self.font_size_edit.setValue(self._default_font_size) self.on_font(self._default_font_size) def on_default_annotation_size(self): self.annotation_size_edit.setValue(self._default_annotation_size) self.on_annotation_size(self._default_annotation_size) def on_default_clipping_min(self): self.clipping_min_edit.setText(str(self._default_clipping_min)) self.clipping_min_edit.setStyleSheet("QLineEdit{background: white;}") def on_default_clipping_max(self): self.clipping_max_edit.setText(str(self._default_clipping_max)) self.clipping_max_edit.setStyleSheet("QLineEdit{background: white;}") def on_validate(self): font_size_value, flag0 = check_float(self.font_size_edit) annotation_size_value, flag1 = check_float(self.annotation_size_edit) assert isinstance(self.annotation_color_float[0], float), self.annotation_color_float assert isinstance(self.annotation_color_int[0], int), self.annotation_color_int picker_size_value, flag2 = check_float(self.picker_size_edit) clipping_min_value, flag3 = check_label_float(self.clipping_min_edit) clipping_max_value, flag4 = check_label_float(self.clipping_max_edit) if all([flag0, flag1, flag2, flag3, flag4]): self._annotation_size = annotation_size_value self._picker_size = picker_size_value self.out_data['font_size'] = int(font_size_value) self.out_data['min_clip'] = min(clipping_min_value, clipping_max_value) self.out_data['max_clip'] = max(clipping_min_value, clipping_max_value) self.out_data['clicked_ok'] = True return True return False def on_apply(self, force=False): passed = self.on_validate() if (passed or force) and self.win_parent is not None: self.win_parent.settings.on_set_font_size( self.out_data['font_size']) #self.win_parent.settings.set_annotation_size_color(self._annotation_size) #self.win_parent.element_picker_size = self._picker_size / 100. if passed and self.win_parent is not None: self.win_parent.clipping_obj.apply_clipping(self.out_data) return passed def on_ok(self): passed = self.on_apply() if passed: self.close() #self.destroy() def on_cancel(self): self.out_data['close'] = True self.close()
class Dimension(QWidget): stateChanged = Signal(int) valueChanged = Signal() """ pass in dimension state: one of (State.X, State.Y, State.NONE, State.DISBALE) Can be run independently by: from mantidqt.widgets.sliceviewer.dimensionwidget import Dimension from qtpy.QtWidgets import QApplication app = QApplication([]) window = Dimension({'minimum':-1.1, 'number_of_bins':11, 'width':0.2, 'name':'Dim0', 'units':'A'}) window.show() app.exec_() """ def __init__(self, dim_info, number=0, state=State.NONE, parent=None): super(Dimension, self).__init__(parent) self.minimum = dim_info['minimum'] self.nbins = dim_info['number_of_bins'] self.width = dim_info['width'] self.number = number self.layout = QHBoxLayout(self) self.name = QLabel(dim_info['name']) self.units = QLabel(dim_info['units']) self.x = QPushButton('X') self.x.setFixedSize(32,32) self.x.setCheckable(True) self.x.clicked.connect(self.x_clicked) self.y = QPushButton('Y') self.y.setFixedSize(32,32) self.y.setCheckable(True) self.y.clicked.connect(self.y_clicked) self.slider = QSlider(Qt.Horizontal) self.slider.setRange(0, self.nbins-1) self.slider.valueChanged.connect(self.slider_changed) self.spinbox = QDoubleSpinBox() self.spinbox.setDecimals(3) self.spinbox.setRange(self.get_bin_center(0), self.get_bin_center(self.nbins-1)) self.spinbox.setSingleStep(self.width) self.spinbox.valueChanged.connect(self.spinbox_changed) self.layout.addWidget(self.name) self.layout.addWidget(self.x) self.layout.addWidget(self.y) self.layout.addWidget(self.slider, stretch=1) self.layout.addStretch(0) self.layout.addWidget(self.spinbox) self.layout.addWidget(self.units) self.set_value(0) if self.nbins < 2: state = State.DISABLE self.set_state(state) def set_state(self, state): self.state = state if self.state == State.X: self.x.setChecked(True) self.y.setChecked(False) self.slider.hide() self.spinbox.hide() self.units.hide() elif self.state == State.Y: self.x.setChecked(False) self.y.setChecked(True) self.slider.hide() self.spinbox.hide() self.units.hide() elif self.state == State.NONE: self.x.setChecked(False) self.y.setChecked(False) self.slider.show() self.spinbox.show() self.units.show() else: self.x.setChecked(False) self.x.setDisabled(True) self.y.setChecked(False) self.y.setDisabled(True) self.slider.hide() self.spinbox.show() self.spinbox.setDisabled(True) self.units.show() def get_state(self): return self.state def x_clicked(self): old_state = self.state self.set_state(State.X) if self.state != old_state: self.stateChanged.emit(self.number) def y_clicked(self): old_state = self.state self.set_state(State.Y) if self.state != old_state: self.stateChanged.emit(self.number) def spinbox_changed(self): self.value = self.spinbox.value() self.update_slider() self.valueChanged.emit() def slider_changed(self): self.value = self.get_bin_center(self.slider.value()) self.update_spinbox() self.valueChanged.emit() def get_bin_center(self, n): return (n+0.5)*self.width+self.minimum def update_slider(self): i = (self.value-self.minimum)/self.width self.slider.setValue(int(min(max(i, 0), self.nbins-1))) def update_spinbox(self): self.spinbox.setValue(self.value) def set_value(self, value): self.value = value self.update_slider() self.update_spinbox() def get_value(self): return self.value
class HighlightWindow(PyDialog): """ +-----------+ | Highlight | +--------------------------+ | Nodes ______ | | Elements ______ | | | | Highlight Close | +--------------------------+ """ def __init__(self, data, win_parent=None): """ Saves the data members from data and performs type checks """ PyDialog.__init__(self, data, win_parent) gui = win_parent if gui is None: # pragma: no cover self.highlight_color_float = [0., 0., 0.] self.highlight_color_int = [0, 0, 0] self._highlight_opacity = 0.9 self._point_size = 10 self._label_size = 10.0 self._default_text_size = 10.0 else: #self.highlight_color_float = gui.settings.highlight_color #self.highlight_color_int = [int(val) for val in self.highlight_color_float] self.highlight_color_float, self.highlight_color_int = _check_color( gui.settings.highlight_color) #self.highlight_color_int = gui.settings.highlight_color_int self._highlight_opacity = gui.settings.highlight_opacity self._point_size = 10 self._label_size = 10.0 self._default_text_size = 10.0 self._updated_highlight = False self.actors = [] self._default_font_size = data['font_size'] self.model_name = data['model_name'] assert len(self.model_name) > 0, self.model_name #self._default_annotation_size = data['annotation_size'] # int #self.default_magnify = data['magnify'] if 'nodes_pound' in data: # testing nodes_pound = data['nodes_pound'] elements_pound = data['elements_pound'] nodes = np.arange(1, nodes_pound + 1) elements = np.arange(1, elements_pound + 1) else: # gui nodes = gui.get_node_ids(model_name=self.model_name) elements = gui.get_element_ids(model_name=self.model_name) nodes_pound = nodes.max() elements_pound = elements.max() self.nodes = nodes self.elements = elements self._nodes_pound = nodes_pound self._elements_pound = elements_pound self.setWindowTitle('Highlight') self.create_widgets() self.create_layout() self.set_connections() self.on_font(self._default_font_size) #self.show() def create_widgets(self): """creates the display window""" # Text Size model_name = self.model_name self.nodes_label = QLabel("Nodes:") self.nodes_edit = QNodeEdit(self, model_name, pick_style='area', cleanup=True, tab_to_next=False) self.elements_label = QLabel("Elements:") self.elements_edit = QElementEdit(self, model_name, pick_style='area', cleanup=True, tab_to_next=False) #----------------------------------------------------------------------- # Highlight Color self.highlight_opacity_label = QLabel("Highlight Opacity:") self.highlight_opacity_edit = QDoubleSpinBox(self) self.highlight_opacity_edit.setValue(self._highlight_opacity) self.highlight_opacity_edit.setRange(0.1, 1.0) self.highlight_opacity_edit.setDecimals(1) self.highlight_opacity_edit.setSingleStep(0.1) self.highlight_opacity_button = QPushButton("Default") # Text Color self.highlight_color_label = QLabel("Highlight Color:") self.highlight_color_edit = QPushButtonColor(self.highlight_color_int) self.point_size_label = QLabel("Point Size:") self.point_size_edit = QSpinBox(self) self.point_size_edit.setValue(self._point_size) self.point_size_edit.setRange(7, 30) #self.point_size_button = QPushButton("Default") self.label_size_label = QLabel("Label Size:") self.label_size_edit = QSpinBox(self) self.label_size_edit.setValue(self._default_text_size) self.label_size_edit.setRange(7, 30) #self.label_size_button = QPushButton("Default") #----------------------------------------------------------------------- # closing self.show_button = QPushButton("Show") self.mark_button = QCheckBox("Mark") self.clear_button = QPushButton("Clear") self.close_button = QPushButton("Close") def create_layout(self): """displays the menu objects""" grid = QGridLayout() irow = 0 grid.addWidget(self.nodes_label, irow, 0) grid.addWidget(self.nodes_edit, irow, 1) irow += 1 grid.addWidget(self.elements_label, irow, 0) grid.addWidget(self.elements_edit, irow, 1) irow += 1 # TODO: enable me grid.addWidget(self.highlight_color_label, irow, 0) grid.addWidget(self.highlight_color_edit, irow, 1) self.highlight_color_label.setEnabled(False) self.highlight_color_edit.setEnabled(False) irow += 1 # TODO: enable me grid.addWidget(self.highlight_opacity_label, irow, 0) grid.addWidget(self.highlight_opacity_edit, irow, 1) self.highlight_opacity_label.setEnabled(False) self.highlight_opacity_edit.setEnabled(False) irow += 1 # TODO: enable me grid.addWidget(self.point_size_label, irow, 0) grid.addWidget(self.point_size_edit, irow, 1) self.point_size_label.setEnabled(False) self.point_size_edit.setEnabled(False) irow += 1 # TODO: enable me grid.addWidget(self.label_size_label, irow, 0) grid.addWidget(self.label_size_edit, irow, 1) self.label_size_label.setEnabled(False) self.label_size_edit.setEnabled(False) irow += 1 self.mark_button.setEnabled(False) #self.create_legend_widgets() #grid2 = self.create_legend_layout() ok_cancel_box = QHBoxLayout() ok_cancel_box.addWidget(self.mark_button) ok_cancel_box.addWidget(self.show_button) ok_cancel_box.addWidget(self.clear_button) ok_cancel_box.addWidget(self.close_button) vbox = QVBoxLayout() vbox.addLayout(grid) #vbox.addStretch() #vbox.addLayout(grid2) vbox.addStretch() vbox.addLayout(ok_cancel_box) self.setLayout(vbox) def set_connections(self): """creates the actions for the menu""" self.highlight_color_edit.clicked.connect(self.on_highlight_color) self.highlight_opacity_edit.valueChanged.connect( self.on_highlight_opacity) self.nodes_edit.textChanged.connect(self.on_validate) self.elements_edit.textChanged.connect(self.on_validate) self.show_button.clicked.connect(self.on_show) self.clear_button.clicked.connect(self.on_remove_actors) self.close_button.clicked.connect(self.on_close) # closeEvent def on_font(self, value=None): """update the font for the current window""" if value is None: value = self.font_size_edit.value() font = QtGui.QFont() font.setPointSize(value) self.setFont(font) def on_highlight_color(self): """ Choose a highlight color TODO: not implemented """ title = "Choose a highlight color" rgb_color_ints = self.highlight_color_int color_edit = self.highlight_color_edit func_name = 'set_highlight_color' passed, rgb_color_ints, rgb_color_floats = self._background_color( title, color_edit, rgb_color_ints, func_name) if passed: self.highlight_color_int = rgb_color_ints self.highlight_color_float = rgb_color_floats def on_highlight_opacity(self, value=None): """ update the highlight opacity TODO: not implemented """ if value is None: value = self.highlight_opacity_edit.value() self._highlight_opacity = value if self.win_parent is not None: self.win_parent.settings.set_highlight_opacity(value) def _background_color(self, title, color_edit, rgb_color_ints, func_name): """helper method for ``on_background_color`` and ``on_background_color2``""" passed, rgb_color_ints, rgb_color_floats = self.on_color( color_edit, rgb_color_ints, title) if passed: if self.win_parent is not None: settings = self.win_parent.settings func_background_color = getattr(settings, func_name) func_background_color(rgb_color_floats) return passed, rgb_color_ints, rgb_color_floats def on_color(self, color_edit, rgb_color_ints, title): """pops a color dialog""" col = QColorDialog.getColor(QtGui.QColor(*rgb_color_ints), self, title) if not col.isValid(): return False, rgb_color_ints, None color_float = col.getRgbF()[:3] # floats color_int = [int(colori * 255) for colori in color_float] assert isinstance(color_float[0], float), color_float assert isinstance(color_int[0], int), color_int color_edit.setStyleSheet("QPushButton {" "background-color: rgb(%s, %s, %s);" % tuple(color_int) + #"border:1px solid rgb(255, 170, 255); " "}") return True, color_int, color_float #--------------------------------------------------------------------------- def on_validate(self): """makes sure that all attributes are valid before doing any actions""" unused_nodes, flag1 = check_patran_syntax(self.nodes_edit, pound=self._nodes_pound) unused_elements, flag2 = check_patran_syntax( self.elements_edit, pound=self._elements_pound) if all([flag1, flag2]): self.out_data['clicked_ok'] = True return True return False def on_show(self): """show the highlight""" passed = self.on_validate() self.parent().mouse_actions.get_grid_selected(self.model_name) if passed and self.win_parent is not None: nodes, unused_flag1 = check_patran_syntax(self.nodes_edit, pound=self._nodes_pound) elements, unused_flag2 = check_patran_syntax( self.elements_edit, pound=self._elements_pound) if len(nodes) == 0 and len(elements) == 0: return False nodes_filtered = np.intersect1d(self.nodes, nodes) elements_filtered = np.intersect1d(self.elements, elements) nnodes = len(nodes_filtered) nelements = len(elements_filtered) if nnodes == 0 and nelements == 0: return False self.on_remove_actors() gui = self.parent() mouse_actions = gui.mouse_actions grid = mouse_actions.get_grid_selected(self.model_name) actors = create_highlighted_actors(gui, grid, all_nodes=self.nodes, nodes=nodes_filtered, set_node_scalars=True, all_elements=self.elements, elements=elements_filtered, set_element_scalars=True) iactor = 0 make_element_labels = True make_node_labels = True if make_node_labels and nnodes: mapper = actors[iactor].GetMapper() mygrid = mapper.GetInput() point_id_filter = get_ids_filter(mygrid, idsname='Ids_points', is_nids=True, is_eids=False) point_id_filter.SetFieldData(1) point_id_filter.SetPointIds(0) point_id_filter.FieldDataOn() label_actor = create_node_labels(point_id_filter, mygrid, gui.rend, label_size=self._label_size) actors.append(label_actor) iactor += 1 if make_element_labels and nelements: mapper = actors[iactor].GetMapper() mygrid = mapper.GetInput() element_id_filter = get_ids_filter(mygrid, idsname='Ids_cells', is_nids=False, is_eids=True) element_id_filter.SetFieldData(1) element_id_filter.SetCellIds(0) element_id_filter.FieldDataOn() # Create labels for cells cell_centers = vtk.vtkCellCenters() cell_centers.SetInputConnection( element_id_filter.GetOutputPort()) cell_mapper = vtk.vtkLabeledDataMapper() cell_mapper.SetInputConnection(cell_centers.GetOutputPort()) cell_mapper.SetLabelModeToLabelScalars() label_actor = vtk.vtkActor2D() label_actor.SetMapper(cell_mapper) actors.append(label_actor) iactor += 1 if actors: add_actors_to_gui(gui, actors, render=True) self.actors = actors return passed def on_remove_actors(self): """removes multiple vtk actors""" gui = self.parent() if gui is not None: if self.nodes_edit.style is not None: self.nodes_edit.style.remove_actors() if self.elements_edit.style is not None: self.elements_edit.style.remove_actors() remove_actors_from_gui(gui, self.actors, render=True, force_render=True) self.actors = [] def on_close(self): """close the window""" self.on_remove_actors() self.out_data['close'] = True self.close()
class ImageRotationDialog(ExToolWindow): def __init__(self, signal, axes, parent, plugin): super(ImageRotationDialog, self).__init__(parent) self.ui = parent self.create_controls() self.accepted.connect(self.ok) self.rejected.connect(self.close_new) self.signal = signal self.plugin = plugin self.new_out = None self._connected_updates = False if isinstance(axes, str): axm = signal.signal.axes_manager if axes.startswith("nav"): axes = (axm._axes.index(axm.navigation_axes[0]), axm._axes.index(axm.navigation_axes[1])) elif axes.startswith("sig"): axes = (axm._axes.index(axm.signal_axes[0]), axm._axes.index(axm.signal_axes[1])) self.axes = axes self.setWindowTitle(tr("Rotate")) # TODO: TAG: Functionality check if not hasattr(signal.signal, 'events'): self.gbo_preview.setVisible(False) # TODO: Add dynamic rotation, e.g. one that rotates when source # signal's data_changed event triggers def connect(self): # TODO: Don't have to con/dis those in gbo self.opt_new.toggled.connect(self.close_new) self.num_angle.valueChanged.connect(self.update) self.chk_grid.toggled.connect(self.update) self.num_grid.valueChanged.connect(self.update) self.chk_reshape.toggled.connect(self.update) self.opt_new.toggled.connect(self.update) self.opt_replace.toggled.connect(self.update) def disconnect(self): self.num_angle.valueChanged.disconnect(self.update) self.chk_grid.toggled.disconnect(self.update) self.num_grid.valueChanged.disconnect(self.update) self.chk_reshape.toggled.disconnect(self.update) self.opt_new.toggled.disconnect(self.update) self.opt_replace.toggled.disconnect(self.update) def ok(self): # Draw figure if not already done # TODO: TAG: Functionality check if not hasattr(self.signal.signal, 'events') or \ not self.gbo_preview.isChecked(): self.update() angle = self.num_angle.value() reshape = self.chk_reshape.isChecked() self.plugin.record_code( r"<p>.rotate_signal({0}, reshape={1}, axes={2})".format( angle, reshape, self.axes)) # Clean up event connections if self.new_out is not None: self.connect_update_plot(self.new_out.signal, disconnect=True) def close_new(self, value=False): if self.new_out is not None and not value: self.new_out.close() self.new_out = None self._connected_updates = False def set_preview(self, value): if not hasattr(self.signal.signal, 'events'): return if value: self.connect() self.update() else: self.disconnect() self.close_new() def _axes_in_nav(self): axm = self.signal.signal.axes_manager navidx = [axm._axes.index(ax) for ax in axm.navigation_axes] if self.axes[0] in navidx: return True return False def connect_update_plot(self, signal, disconnect=False): if self._connected_updates != disconnect: return # Nothing to do, prevent double connections if self._axes_in_nav(): f = signal._plot.navigator_plot.update else: f = signal._plot.signal_plot.update # TODO: TAG: Functionality check if hasattr(signal, 'events') and hasattr(signal.events, 'data_changed'): if disconnect: signal.events.data_changed.disconnect(f) else: signal.events.data_changed.connect(f, []) self._connected_updates = not disconnect def update(self): angle = self.num_angle.value() reshape = self.chk_reshape.isChecked() if self.opt_new.isChecked(): if self.new_out is None: out = None else: out = self.new_out.signal elif self.opt_replace.isChecked(): out = self.signal.signal else: return # Indeterminate state, do nothing s = self.plugin.rotate_signal(angle, self.signal.signal, record=False, reshape=reshape, out=out, axes=self.axes) if out is None: s.metadata.General.title = self.signal.name + "[Rotated]" s.plot() self.connect_update_plot(s) if (self.gbo_preview.isChecked() and self.opt_new.isChecked() and self.new_out is None): self.new_out = self.ui.lut_signalwrapper[s] else: s = out if self.chk_grid.isChecked() is True: pass # TODO: Draw grid def create_controls(self): """ Create UI controls. """ vbox = QVBoxLayout() form = QFormLayout() self.num_angle = QDoubleSpinBox() self.num_angle.setValue(0.0) self.num_angle.setMinimum(-360) self.num_angle.setMaximum(360) form.addRow(tr("Angle:"), self.num_angle) vbox.addLayout(form) self.gbo_preview = QGroupBox(tr("Preview")) self.gbo_preview.setCheckable(True) self.gbo_preview.setChecked(False) gbo_vbox = QVBoxLayout() self.chk_grid = QCheckBox(tr("Grid")) self.chk_grid.setChecked(False) self.num_grid = QSpinBox() self.num_grid.setValue(4) self.num_grid.setMinimum(1) self.num_grid.setEnabled(False) self.chk_grid.toggled[bool].connect(self.num_grid.setEnabled) gbo_vbox.addWidget(self.chk_grid) gbo_vbox.addWidget(self.num_grid) self.gbo_preview.setLayout(gbo_vbox) vbox.addWidget(self.gbo_preview) self.gbo_preview.toggled[bool].connect(self.set_preview) self.gbo_output = QGroupBox(tr("Output")) self.opt_new = QRadioButton(tr("New signal")) self.opt_replace = QRadioButton(tr("In place")) self.opt_new.setChecked(True) gbo_vbox2 = QVBoxLayout() gbo_vbox2.addWidget(self.opt_new) gbo_vbox2.addWidget(self.opt_replace) self.gbo_output.setLayout(gbo_vbox2) vbox.addWidget(self.gbo_output) self.chk_reshape = QCheckBox(tr("Resize to fit")) self.chk_reshape.setChecked(False) vbox.addWidget(self.chk_reshape) self.btn_ok = QPushButton(tr("&OK")) self.btn_ok.setDefault(True) self.btn_ok.clicked.connect(self.accept) self.btn_cancel = QPushButton(tr("&Cancel")) self.btn_cancel.clicked.connect(self.reject) hbox = QHBoxLayout() hbox.addWidget(self.btn_ok) hbox.addWidget(self.btn_cancel) vbox.addLayout(hbox) vbox.addStretch(1) self.setLayout(vbox)
class livestream(QWidget): i = 0 def __init__(self,qnd,images = None,annotations_on = True,annotate_coords = None,threshold_switch = False): QWidget.__init__(self) self.threshold_switch = threshold_switch self.video = images #frames buffer self.videobox = Label() if annotations_on and annotate_coords is not None: self.coords = annotate_coords self.videobox.switch = annotations_on self.videobox.activecoord = self.coords[0] if self.video is not None: self.videobox.activeframe = self.video[0] self.videobox.maxintens = self.video.shape[0] else: self.videobox.activeframe = np.loadtxt(os.getcwd() + '/defaultimage.txt') print(self.videobox.activeframe.shape) self.videobox.maxintens = np.max(self.videobox.activeframe) self.videobox.setGeometry(QtCore.QRect(70, 80, 310, 310)) self.videobox.h = 310 self.videobox.w = 310 self.lyt = QVBoxLayout() self.lyt.addWidget(self.videobox,5) self.setLayout(self.lyt) self.sl = QSlider(Qt.Horizontal) self.sl.setMinimum(0.0) if self.video is not None: self.sl.setMaximum(self.video.shape[0]) self.sl.valueChanged.connect(self.whenslidechanges) self.sl.setTickPosition(QSlider.TicksAbove) self.sl.setTracking(True) self.sl.setTickInterval(100) self.frame_counter = QDoubleSpinBox() if images is not None: self.frame = images[0] self.frame_counter.valueChanged.connect(self.video_time_update) self.frame_counter.setSingleStep(1) self.frame_counter.setRange(self.sl.minimum(),self.sl.maximum()) self.frame_counter.valueChanged.connect(self.sl.setValue) self.video_time = QDoubleSpinBox() self.video_time.setSingleStep(30) self.video_time.setRange(self.sl.minimum(),30*self.sl.maximum()) self.frameratetimer = QTimer() self.frameratetimer.setInterval(30) if self.video is not None: self.frameratetimer.timeout.connect(self.update_display) self.play_button = QPushButton('Play Video') self.play_button.clicked.connect(self.frameratetimer.start) self.stop_button = QPushButton('Stop Video') self.stop_button.clicked.connect(self.frameratetimer.stop) if self.video is not None: self.sl.valueChanged.connect(self.whenslidechanges) self.lyt.addWidget(self.play_button,0) self.lyt.addWidget(self.stop_button,1) self.lyt.addWidget(self.sl,2) self.lyt.addWidget(self.frame_counter,3) self.lyt.addWidget(self.video_time,4) self.show() def assign_images(self,images,centres = None): '''#first disconnect signals from eachother so nothing should change whilst video data is being updated self.sl.valueChanged.disconnect(self.video_time_update) self.frameratetimer.timeout.disconnect(self.update_display) self.frame_counter.valueChanged.disconnect(self.whenslidechanges) ''' self.video = images self.coords = centres self.videobox.activeframe = self.video[0] if self.coords is not None: self.videobox.activecoord = self.coords[0] #readjust slider and ticker values to dimensions of video self.sl.setMaximum(len(self.video)-1) self.frame_counter.setRange(self.sl.minimum(),self.sl.maximum()) self.video_time.setRange(self.sl.minimum(),30*self.sl.maximum()) #connect slider and timer etc. self.sl.valueChanged.connect(self.whenslidechanges) self.frameratetimer.timeout.connect(self.update_display) self.frame_counter.valueChanged.connect(self.video_time_update) self.videobox.maxintens = np.max(self.video) self.videobox.update() def update_display(self): if self.threshold_switch: frame = self.video[livestream.i] threshold = threshold_otsu(frame) mask = np.zeros_like(frame) mask[frame > threshold] = 1 self.videobox.maxintens = 1 self.videobox.activeframe = mask else: #if threshold switch is off display usual video, so change active frame source and reset maximum intensity for passing to qimage2ndarray self.videobox.activeframe = self.video[livestream.i] self.videobox.maxintens = np.max(self.video) try: self.videobox.activecoord = self.coords[livestream.i] if not self.videobox.switch: self.videobox.switch = True except: self.videobox.activecoord = None self.videobox.switch = False self.videobox.update() self.frame_counter.setValue(float(livestream.i)) livestream.i+=1 def whenslidechanges(self): if self.frameratetimer.isActive(): self.frameratetimer.stop() livestream.i = self.sl.value() self.update_display() livestream.i -=1 self.frameratetimer.start() else: livestream.i = self.sl.value() self.update_display() livestream.i -=1 def video_time_update(self): self.video_time.setValue(30*self.frame_counter.value()) def turn_on_threshold(self,threshold_switch): self.threshold_switch = threshold_switch self.update_display()
class ImageRotationDialog(ExToolWindow): def __init__(self, signal, axes, parent, plugin): super(ImageRotationDialog, self).__init__(parent) self.ui = parent self.create_controls() self.accepted.connect(self.ok) self.rejected.connect(self.close_new) self.signal = signal self.plugin = plugin self.new_out = None self._connected_updates = False if isinstance(axes, str): axm = signal.signal.axes_manager if axes.startswith("nav"): axes = (axm._axes.index(axm.navigation_axes[0]), axm._axes.index(axm.navigation_axes[1])) elif axes.startswith("sig"): axes = (axm._axes.index(axm.signal_axes[0]), axm._axes.index(axm.signal_axes[1])) self.axes = axes self.setWindowTitle(tr("Rotate")) # TODO: TAG: Functionality check if not hasattr(signal.signal, 'events'): self.gbo_preview.setVisible(False) # TODO: Add dynamic rotation, e.g. one that rotates when source # signal's data_changed event triggers def connect(self): # TODO: Don't have to con/dis those in gbo self.opt_new.toggled.connect(self.close_new) self.num_angle.valueChanged.connect(self.update) self.chk_grid.toggled.connect(self.update) self.num_grid.valueChanged.connect(self.update) self.chk_reshape.toggled.connect(self.update) self.opt_new.toggled.connect(self.update) self.opt_replace.toggled.connect(self.update) def disconnect(self): self.num_angle.valueChanged.disconnect(self.update) self.chk_grid.toggled.disconnect(self.update) self.num_grid.valueChanged.disconnect(self.update) self.chk_reshape.toggled.disconnect(self.update) self.opt_new.toggled.disconnect(self.update) self.opt_replace.toggled.disconnect(self.update) def ok(self): # Draw figure if not already done # TODO: TAG: Functionality check if not hasattr(self.signal.signal, 'events') or \ not self.gbo_preview.isChecked(): self.update() angle = self.num_angle.value() reshape = self.chk_reshape.isChecked() self.plugin.record_code( r"<p>.rotate_signal({0}, reshape={1}, axes={2})".format( angle, reshape, self.axes)) # Clean up event connections if self.new_out is not None: self.connect_update_plot(self.new_out.signal, disconnect=True) def close_new(self, value=False): if self.new_out is not None and not value: self.new_out.close() self.new_out = None self._connected_updates = False def set_preview(self, value): if not hasattr(self.signal.signal, 'events'): return if value: self.connect() self.update() else: self.disconnect() self.close_new() def _axes_in_nav(self): axm = self.signal.signal.axes_manager navidx = [axm._axes.index(ax) for ax in axm.navigation_axes] if self.axes[0] in navidx: return True return False def connect_update_plot(self, signal, disconnect=False): if self._connected_updates != disconnect: return # Nothing to do, prevent double connections if self._axes_in_nav(): f = signal._plot.navigator_plot.update else: f = signal._plot.signal_plot.update # TODO: TAG: Functionality check if hasattr(signal, 'events') and hasattr( signal.events, 'data_changed'): if disconnect: signal.events.data_changed.disconnect(f) else: signal.events.data_changed.connect(f, []) self._connected_updates = not disconnect def update(self): angle = self.num_angle.value() reshape = self.chk_reshape.isChecked() if self.opt_new.isChecked(): if self.new_out is None: out = None else: out = self.new_out.signal elif self.opt_replace.isChecked(): out = self.signal.signal else: return # Indeterminate state, do nothing s = self.plugin.rotate_signal(angle, self.signal.signal, record=False, reshape=reshape, out=out, axes=self.axes) if out is None: s.metadata.General.title = self.signal.name + "[Rotated]" s.plot() self.connect_update_plot(s) if (self.gbo_preview.isChecked() and self.opt_new.isChecked() and self.new_out is None): self.new_out = self.ui.lut_signalwrapper[s] else: s = out if self.chk_grid.isChecked() is True: pass # TODO: Draw grid def create_controls(self): """ Create UI controls. """ vbox = QVBoxLayout() form = QFormLayout() self.num_angle = QDoubleSpinBox() self.num_angle.setValue(0.0) self.num_angle.setMinimum(-360) self.num_angle.setMaximum(360) form.addRow(tr("Angle:"), self.num_angle) vbox.addLayout(form) self.gbo_preview = QGroupBox(tr("Preview")) self.gbo_preview.setCheckable(True) self.gbo_preview.setChecked(False) gbo_vbox = QVBoxLayout() self.chk_grid = QCheckBox(tr("Grid")) self.chk_grid.setChecked(False) self.num_grid = QSpinBox() self.num_grid.setValue(4) self.num_grid.setMinimum(1) self.num_grid.setEnabled(False) self.chk_grid.toggled[bool].connect(self.num_grid.setEnabled) gbo_vbox.addWidget(self.chk_grid) gbo_vbox.addWidget(self.num_grid) self.gbo_preview.setLayout(gbo_vbox) vbox.addWidget(self.gbo_preview) self.gbo_preview.toggled[bool].connect(self.set_preview) self.gbo_output = QGroupBox(tr("Output")) self.opt_new = QRadioButton(tr("New signal")) self.opt_replace = QRadioButton(tr("In place")) self.opt_new.setChecked(True) gbo_vbox2 = QVBoxLayout() gbo_vbox2.addWidget(self.opt_new) gbo_vbox2.addWidget(self.opt_replace) self.gbo_output.setLayout(gbo_vbox2) vbox.addWidget(self.gbo_output) self.chk_reshape = QCheckBox(tr("Resize to fit")) self.chk_reshape.setChecked(False) vbox.addWidget(self.chk_reshape) self.btn_ok = QPushButton(tr("&OK")) self.btn_ok.setDefault(True) self.btn_ok.clicked.connect(self.accept) self.btn_cancel = QPushButton(tr("&Cancel")) self.btn_cancel.clicked.connect(self.reject) hbox = QHBoxLayout() hbox.addWidget(self.btn_ok) hbox.addWidget(self.btn_cancel) vbox.addLayout(hbox) vbox.addStretch(1) self.setLayout(vbox)
class EditGeometryProperties(PyDialog): force = True def __init__(self, data, win_parent=None): """ +------------------+ | Edit Actor Props | +------------------+------+ | Name1 | | Name2 | | Name3 | | Name4 | | | | Active_Name main | | Color box | | Line_Width 2 | | Point_Size 2 | | Bar_Scale 2 | | Opacity 0.5 | | Show/Hide | | | | Apply OK Cancel | +-------------------------+ """ PyDialog.__init__(self, data, win_parent) self.set_font_size(data['font_size']) del self.out_data['font_size'] self.setWindowTitle('Edit Geometry Properties') self.allow_update = True #default #self.win_parent = win_parent #self.out_data = data self.keys = sorted(data.keys()) self.keys = data.keys() keys = self.keys #nrows = len(keys) self.active_key = 'main' items = list(keys) header_labels = ['Groups'] table_model = Model(items, header_labels, self) view = SingleChoiceQTableView(self) #Call your custom QTableView here view.setModel(table_model) #if qt_version == 4: #view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.table = view #self.opacity_edit.valueChanged.connect(self.on_opacity) #mListWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(itemClicked(QListWidgetItem*))); #self.table.itemClicked.connect(self.table.mouseDoubleClickEvent) actor_obj = data[self.active_key] name = actor_obj.name line_width = actor_obj.line_width point_size = actor_obj.point_size bar_scale = actor_obj.bar_scale opacity = actor_obj.opacity color = actor_obj.color show = actor_obj.is_visible self.representation = actor_obj.representation # table header = self.table.horizontalHeader() header.setStretchLastSection(True) self._default_is_apply = False self.name = QLabel("Name:") self.name_edit = QLineEdit(str(name)) self.name_edit.setDisabled(True) self.color = QLabel("Color:") self.color_edit = QPushButton() #self.color_edit.setFlat(True) color = self.out_data[self.active_key].color qcolor = QtGui.QColor() qcolor.setRgb(*color) #print('color =%s' % str(color)) palette = QtGui.QPalette(self.color_edit.palette()) # make a copy of the palette #palette.setColor(QtGui.QPalette.Active, QtGui.QPalette.Base, \ #qcolor) palette.setColor(QtGui.QPalette.Background, QtGui.QColor('blue')) # ButtonText self.color_edit.setPalette(palette) self.color_edit.setStyleSheet("QPushButton {" "background-color: rgb(%s, %s, %s);" % tuple(color) + #"border:1px solid rgb(255, 170, 255); " "}") self.use_slider = True self.is_opacity_edit_active = False self.is_opacity_edit_slider_active = False self.is_line_width_edit_active = False self.is_line_width_edit_slider_active = False self.is_point_size_edit_active = False self.is_point_size_edit_slider_active = False self.is_bar_scale_edit_active = False self.is_bar_scale_edit_slider_active = False self.opacity = QLabel("Opacity:") self.opacity_edit = QDoubleSpinBox(self) self.opacity_edit.setRange(0.1, 1.0) self.opacity_edit.setDecimals(1) self.opacity_edit.setSingleStep(0.1) self.opacity_edit.setValue(opacity) if self.use_slider: self.opacity_slider_edit = QSlider(QtCore.Qt.Horizontal) self.opacity_slider_edit.setRange(1, 10) self.opacity_slider_edit.setValue(opacity * 10) self.opacity_slider_edit.setTickInterval(1) self.opacity_slider_edit.setTickPosition(QSlider.TicksBelow) self.line_width = QLabel("Line Width:") self.line_width_edit = QSpinBox(self) self.line_width_edit.setRange(1, MAX_LINE_WIDTH) self.line_width_edit.setSingleStep(1) self.line_width_edit.setValue(line_width) if self.use_slider: self.line_width_slider_edit = QSlider(QtCore.Qt.Horizontal) self.line_width_slider_edit.setRange(1, MAX_LINE_WIDTH) self.line_width_slider_edit.setValue(line_width) self.line_width_slider_edit.setTickInterval(1) self.line_width_slider_edit.setTickPosition(QSlider.TicksBelow) if self.representation in ['point', 'surface']: self.line_width.setEnabled(False) self.line_width_edit.setEnabled(False) self.line_width_slider_edit.setEnabled(False) self.point_size = QLabel("Point Size:") self.point_size_edit = QSpinBox(self) self.point_size_edit.setRange(1, MAX_POINT_SIZE) self.point_size_edit.setSingleStep(1) self.point_size_edit.setValue(point_size) self.point_size.setVisible(False) self.point_size_edit.setVisible(False) if self.use_slider: self.point_size_slider_edit = QSlider(QtCore.Qt.Horizontal) self.point_size_slider_edit.setRange(1, MAX_POINT_SIZE) self.point_size_slider_edit.setValue(point_size) self.point_size_slider_edit.setTickInterval(1) self.point_size_slider_edit.setTickPosition(QSlider.TicksBelow) self.point_size_slider_edit.setVisible(False) if self.representation in ['wire', 'surface']: self.point_size.setEnabled(False) self.point_size_edit.setEnabled(False) if self.use_slider: self.point_size_slider_edit.setEnabled(False) self.bar_scale = QLabel("Bar Scale:") self.bar_scale_edit = QDoubleSpinBox(self) #self.bar_scale_edit.setRange(0.01, 1.0) # was 0.1 #self.bar_scale_edit.setRange(0.05, 5.0) self.bar_scale_edit.setDecimals(1) #self.bar_scale_edit.setSingleStep(bar_scale / 10.) self.bar_scale_edit.setSingleStep(0.1) self.bar_scale_edit.setValue(bar_scale) #if self.use_slider: #self.bar_scale_slider_edit = QSlider(QtCore.Qt.Horizontal) #self.bar_scale_slider_edit.setRange(1, 100) # 1/0.05 = 100/5.0 #self.bar_scale_slider_edit.setValue(opacity * 0.05) #self.bar_scale_slider_edit.setTickInterval(10) #self.bar_scale_slider_edit.setTickPosition(QSlider.TicksBelow) if self.representation != 'bar': self.bar_scale.setEnabled(False) self.bar_scale_edit.setEnabled(False) self.bar_scale.setVisible(False) self.bar_scale_edit.setVisible(False) #self.bar_scale_slider_edit.setVisible(False) #self.bar_scale_slider_edit.setEnabled(False) # show/hide self.checkbox_show = QCheckBox("Show") self.checkbox_hide = QCheckBox("Hide") self.checkbox_show.setChecked(show) self.checkbox_hide.setChecked(not show) if name == 'main': self.color.setEnabled(False) self.color_edit.setEnabled(False) self.point_size.setEnabled(False) self.point_size_edit.setEnabled(False) if self.use_slider: self.point_size_slider_edit.setEnabled(False) self.cancel_button = QPushButton("Close") self.create_layout() self.set_connections() def on_delete(self, irow): """deletes an actor based on the row number""" if irow == 0: # main return nkeys = len(self.keys) if nkeys in [0, 1]: return name = self.keys[irow] nrows = nkeys - 1 self.keys.pop(irow) header_labels = ['Groups'] table_model = Model(self.keys, header_labels, self) self.table.setModel(table_model) if len(self.keys) == 0: self.update() self.set_as_null() return if irow == nrows: irow -= 1 new_name = self.keys[irow] self.update_active_name(new_name) if self.is_gui: self.win_parent.delete_actor(name) def set_as_null(self): """sets the null case""" self.name.setVisible(False) self.name_edit.setVisible(False) self.color.setVisible(False) self.color_edit.setVisible(False) self.line_width.setVisible(False) self.line_width_edit.setVisible(False) self.point_size.setVisible(False) self.point_size_edit.setVisible(False) self.bar_scale.setVisible(False) self.bar_scale_edit.setVisible(False) self.opacity.setVisible(False) self.opacity_edit.setVisible(False) self.opacity_slider_edit.setVisible(False) self.point_size_slider_edit.setVisible(False) self.line_width_slider_edit.setVisible(False) self.checkbox_show.setVisible(False) self.checkbox_hide.setVisible(False) def on_update_geometry_properties_window(self, data): """Not Implemented""" return #new_keys = sorted(data.keys()) #if self.active_key in new_keys: #i = new_keys.index(self.active_key) #else: #i = 0 #self.table.update_data(new_keys) #self.out_data = data #self.update_active_key(i) def update_active_key(self, index): """ Parameters ---------- index : PyQt4.QtCore.QModelIndex the index of the list Internal Parameters ------------------- name : str the name of obj obj : CoordProperties, AltGeometry the storage object for things like line_width, point_size, etc. """ name = str(index.data()) #print('name = %r' % name) #i = self.keys.index(self.active_key) self.update_active_name(name) def update_active_name(self, name): self.active_key = name self.name_edit.setText(name) obj = self.out_data[name] if isinstance(obj, CoordProperties): opacity = 1.0 representation = 'coord' is_visible = obj.is_visible elif isinstance(obj, AltGeometry): line_width = obj.line_width point_size = obj.point_size bar_scale = obj.bar_scale opacity = obj.opacity representation = obj.representation is_visible = obj.is_visible self.color_edit.setStyleSheet("QPushButton {" "background-color: rgb(%s, %s, %s);" % tuple(obj.color) + #"border:1px solid rgb(255, 170, 255); " "}") self.allow_update = False self.force = False self.line_width_edit.setValue(line_width) self.point_size_edit.setValue(point_size) self.bar_scale_edit.setValue(bar_scale) self.force = True self.allow_update = True else: raise NotImplementedError(obj) #allowed_representations = [ #'main', 'surface', 'coord', 'toggle', 'wire', 'point', 'bar'] if self.representation != representation: self.representation = representation #if representation not in allowed_representations: #msg = 'name=%r; representation=%r is invalid\nrepresentations=%r' % ( #name, representation, allowed_representations) if self.representation == 'coord': self.color.setVisible(False) self.color_edit.setVisible(False) self.line_width.setVisible(False) self.line_width_edit.setVisible(False) self.point_size.setVisible(False) self.point_size_edit.setVisible(False) self.bar_scale.setVisible(False) self.bar_scale_edit.setVisible(False) self.opacity.setVisible(False) self.opacity_edit.setVisible(False) if self.use_slider: self.opacity_slider_edit.setVisible(False) self.point_size_slider_edit.setVisible(False) self.line_width_slider_edit.setVisible(False) #self.bar_scale_slider_edit.setVisible(False) else: self.color.setVisible(True) self.color_edit.setVisible(True) self.line_width.setVisible(True) self.line_width_edit.setVisible(True) self.point_size.setVisible(True) self.point_size_edit.setVisible(True) self.bar_scale.setVisible(True) #self.bar_scale_edit.setVisible(True) self.opacity.setVisible(True) self.opacity_edit.setVisible(True) if self.use_slider: self.opacity_slider_edit.setVisible(True) self.line_width_slider_edit.setVisible(True) self.point_size_slider_edit.setVisible(True) #self.bar_scale_slider_edit.setVisible(True) if name == 'main': self.color.setEnabled(False) self.color_edit.setEnabled(False) self.point_size.setEnabled(False) self.point_size_edit.setEnabled(False) self.line_width.setEnabled(True) self.line_width_edit.setEnabled(True) self.bar_scale.setEnabled(False) self.bar_scale_edit.setEnabled(False) show_points = False show_line_width = True show_bar_scale = False if self.use_slider: self.line_width_slider_edit.setEnabled(True) #self.bar_scale_slider_edit.setVisible(False) else: self.color.setEnabled(True) self.color_edit.setEnabled(True) show_points = False if self.representation in ['point', 'wire+point']: show_points = True show_line_width = False if self.representation in ['wire', 'wire+point', 'bar', 'toggle']: show_line_width = True if representation == 'bar': show_bar_scale = True else: show_bar_scale = False #self.bar_scale_button.setVisible(show_bar_scale) #self.bar_scale_edit.setSingleStep(bar_scale / 10.) #if self.use_slider: #self.bar_scale_slider_edit.setEnabled(False) self.point_size.setEnabled(show_points) self.point_size_edit.setEnabled(show_points) self.point_size.setVisible(show_points) self.point_size_edit.setVisible(show_points) self.line_width.setEnabled(show_line_width) self.line_width_edit.setEnabled(show_line_width) self.bar_scale.setEnabled(show_bar_scale) self.bar_scale_edit.setEnabled(show_bar_scale) self.bar_scale.setVisible(show_bar_scale) self.bar_scale_edit.setVisible(show_bar_scale) if self.use_slider: self.point_size_slider_edit.setEnabled(show_points) self.point_size_slider_edit.setVisible(show_points) self.line_width_slider_edit.setEnabled(show_line_width) #if self.representation in ['wire', 'surface']: self.opacity_edit.setValue(opacity) #if self.use_slider: #self.opacity_slider_edit.setValue(opacity*10) self.checkbox_show.setChecked(is_visible) self.checkbox_hide.setChecked(not is_visible) passed = self.on_validate() #self.on_apply(force=True) # TODO: was turned on...do I want this??? #self.allow_update = True def create_layout(self): ok_cancel_box = QHBoxLayout() ok_cancel_box.addWidget(self.cancel_button) grid = QGridLayout() irow = 0 grid.addWidget(self.name, irow, 0) grid.addWidget(self.name_edit, irow, 1) irow += 1 grid.addWidget(self.color, irow, 0) grid.addWidget(self.color_edit, irow, 1) irow += 1 grid.addWidget(self.opacity, irow, 0) if self.use_slider: grid.addWidget(self.opacity_edit, irow, 2) grid.addWidget(self.opacity_slider_edit, irow, 1) else: grid.addWidget(self.opacity_edit, irow, 1) irow += 1 grid.addWidget(self.line_width, irow, 0) if self.use_slider: grid.addWidget(self.line_width_edit, irow, 2) grid.addWidget(self.line_width_slider_edit, irow, 1) else: grid.addWidget(self.line_width_edit, irow, 1) irow += 1 grid.addWidget(self.point_size, irow, 0) if self.use_slider: grid.addWidget(self.point_size_edit, irow, 2) grid.addWidget(self.point_size_slider_edit, irow, 1) else: grid.addWidget(self.point_size_edit, irow, 1) irow += 1 grid.addWidget(self.bar_scale, irow, 0) if self.use_slider and 0: grid.addWidget(self.bar_scale_edit, irow, 2) grid.addWidget(self.bar_scale_slider_edit, irow, 1) else: grid.addWidget(self.bar_scale_edit, irow, 1) irow += 1 checkboxs = QButtonGroup(self) checkboxs.addButton(self.checkbox_show) checkboxs.addButton(self.checkbox_hide) vbox = QVBoxLayout() vbox.addWidget(self.table, stretch=1) vbox.addLayout(grid) vbox1 = QVBoxLayout() vbox1.addWidget(self.checkbox_show) vbox1.addWidget(self.checkbox_hide) vbox.addLayout(vbox1) vbox.addStretch() #vbox.addWidget(self.check_apply) vbox.addLayout(ok_cancel_box) self.setLayout(vbox) def set_connections(self): self.opacity_edit.valueChanged.connect(self.on_opacity) self.line_width_edit.valueChanged.connect(self.on_line_width) self.point_size_edit.valueChanged.connect(self.on_point_size) self.bar_scale_edit.valueChanged.connect(self.on_bar_scale) if self.use_slider: self.opacity_slider_edit.valueChanged.connect(self.on_opacity_slider) self.line_width_slider_edit.valueChanged.connect(self.on_line_width_slider) self.point_size_slider_edit.valueChanged.connect(self.on_point_size_slider) #self.bar_scale_slider_edit.valueChanged.connect(self.on_bar_scale_slider) # self.connect(self.opacity_edit, QtCore.SIGNAL('clicked()'), self.on_opacity) # self.connect(self.line_width, QtCore.SIGNAL('clicked()'), self.on_line_width) # self.connect(self.point_size, QtCore.SIGNAL('clicked()'), self.on_point_size) if qt_version == 4: self.connect(self, QtCore.SIGNAL('triggered()'), self.closeEvent) self.color_edit.clicked.connect(self.on_color) self.checkbox_show.clicked.connect(self.on_show) self.checkbox_hide.clicked.connect(self.on_hide) self.cancel_button.clicked.connect(self.on_cancel) # closeEvent def keyPressEvent(self, event): if event.key() == QtCore.Qt.Key_Escape: self.close() def closeEvent(self, event): self.on_cancel() def on_color(self): """called when the user clicks on the color box""" name = self.active_key obj = self.out_data[name] rgb_color_ints = obj.color msg = name col = QColorDialog.getColor(QtGui.QColor(*rgb_color_ints), self, "Choose a %s color" % msg) if col.isValid(): color_float = col.getRgbF()[:3] obj.color = color_float color_int = [int(colori * 255) for colori in color_float] self.color_edit.setStyleSheet("QPushButton {" "background-color: rgb(%s, %s, %s);" % tuple(color_int) + #"border:1px solid rgb(255, 170, 255); " "}") self.on_apply(force=self.force) #print(self.allow_update) def on_show(self): """shows the actor""" name = self.active_key is_checked = self.checkbox_show.isChecked() self.out_data[name].is_visible = is_checked self.on_apply(force=self.force) def on_hide(self): """hides the actor""" name = self.active_key is_checked = self.checkbox_hide.isChecked() self.out_data[name].is_visible = not is_checked self.on_apply(force=self.force) def on_line_width(self): """increases/decreases the wireframe (for solid bodies) or the bar thickness""" self.is_line_width_edit_active = True name = self.active_key line_width = self.line_width_edit.value() self.out_data[name].line_width = line_width if not self.is_line_width_edit_slider_active: if self.use_slider: self.line_width_slider_edit.setValue(line_width) self.is_line_width_edit_active = False self.on_apply(force=self.force) self.is_line_width_edit_active = False def on_line_width_slider(self): """increases/decreases the wireframe (for solid bodies) or the bar thickness""" self.is_line_width_edit_slider_active = True #name = self.active_key line_width = self.line_width_slider_edit.value() if not self.is_line_width_edit_active: self.line_width_edit.setValue(line_width) self.is_line_width_edit_slider_active = False def on_point_size(self): """increases/decreases the point size""" self.is_point_size_edit_active = True name = self.active_key point_size = self.point_size_edit.value() self.out_data[name].point_size = point_size if not self.is_point_size_edit_slider_active: if self.use_slider: self.point_size_slider_edit.setValue(point_size) self.is_point_size_edit_active = False self.on_apply(force=self.force) self.is_point_size_edit_active = False def on_point_size_slider(self): """increases/decreases the point size""" self.is_point_size_edit_slider_active = True #name = self.active_key point_size = self.point_size_slider_edit.value() if not self.is_point_size_edit_active: self.point_size_edit.setValue(point_size) self.is_point_size_edit_slider_active = False def on_bar_scale(self): """ Vectors start at some xyz coordinate and can increase in length. Increases/decreases the length scale factor. """ self.is_bar_scale_edit_active = True name = self.active_key float_bar_scale = self.bar_scale_edit.value() self.out_data[name].bar_scale = float_bar_scale if not self.is_bar_scale_edit_slider_active: #int_bar_scale = int(round(float_bar_scale * 20, 0)) #if self.use_slider: #self.bar_scale_slider_edit.setValue(int_bar_scale) self.is_bar_scale_edit_active = False self.on_apply(force=self.force) self.is_bar_scale_edit_active = False def on_bar_scale_slider(self): """ Vectors start at some xyz coordinate and can increase in length. Increases/decreases the length scale factor. """ self.is_bar_scale_edit_slider_active = True #name = self.active_key int_bar_scale = self.bar_scale_slider_edit.value() if not self.is_bar_scale_edit_active: float_bar_scale = int_bar_scale / 20. self.bar_scale_edit.setValue(float_bar_scale) self.is_bar_scale_edit_slider_active = False def on_opacity(self): """ opacity = 1.0 (solid/opaque) opacity = 0.0 (invisible) """ self.is_opacity_edit_active = True name = self.active_key float_opacity = self.opacity_edit.value() self.out_data[name].opacity = float_opacity if not self.is_opacity_edit_slider_active: int_opacity = int(round(float_opacity * 10, 0)) if self.use_slider: self.opacity_slider_edit.setValue(int_opacity) self.is_opacity_edit_active = False self.on_apply(force=self.force) self.is_opacity_edit_active = False def on_opacity_slider(self): """ opacity = 1.0 (solid/opaque) opacity = 0.0 (invisible) """ self.is_opacity_edit_slider_active = True #name = self.active_key int_opacity = self.opacity_slider_edit.value() if not self.is_opacity_edit_active: float_opacity = int_opacity / 10. self.opacity_edit.setValue(float_opacity) self.is_opacity_edit_slider_active = False def on_validate(self): self.out_data['clicked_ok'] = True self.out_data['clicked_cancel'] = False old_obj = self.out_data[self.active_key] old_obj.line_width = self.line_width_edit.value() old_obj.point_size = self.point_size_edit.value() old_obj.bar_scale = self.bar_scale_edit.value() old_obj.opacity = self.opacity_edit.value() #old_obj.color = self.color_edit old_obj.is_visible = self.checkbox_show.isChecked() return True #name_value, flag0 = self.check_name(self.name_edit) #ox_value, flag1 = self.check_float(self.transparency_edit) #if flag0 and flag1: #self.out_data['clicked_ok'] = True #return True #return False @property def is_gui(self): return hasattr(self.win_parent, 'on_update_geometry_properties') def on_apply(self, force=False): passed = self.on_validate() #print("passed=%s force=%s allow=%s" % (passed, force, self.allow_update)) if (passed or force) and self.allow_update and self.is_gui: #print('obj = %s' % self.out_data[self.active_key]) self.win_parent.on_update_geometry_properties(self.out_data, name=self.active_key) return passed def on_cancel(self): passed = self.on_apply(force=True) if passed: self.close()
class ItemPropertyDialog(QDialog): def __init__(self, jsonitem: JsonItem, parent=None): super().__init__(parent) assert jsonitem is not None self.item = jsonitem # name self.nameLabel = QLabel(self.tr("name:")) self.nameLineEdit = QLineEdit(self.item.name or "") self.nameLabel.setBuddy(self.nameLineEdit) # unit self.unitLabel = QLabel(self.tr("unit:")) self.unitLineEdit = QLineEdit(self.item.unit or "") self.unitLabel.setBuddy(self.unitLineEdit) # type self.typeLabel = QLabel(self.tr("type:")) self.typeComboBox = QComboBox() self.typeComboBox.addItems([k for k, t in VALUETYPES]) self.typeComboBox.setCurrentIndex( self.typeComboBox.findText(self.item.type)) self.typeComboBox.currentIndexChanged.connect(self.data_changed) self.typeLabel.setBuddy(self.typeComboBox) # decimals self.decimalsLabel = QLabel(self.tr("decimals:")) self.decimalsSpinBox = QSpinBox() self.decimalsSpinBox.setRange(0, 10) self.decimalsSpinBox.setValue(self.item.decimals or 0) self.decimalsLabel.setBuddy(self.decimalsSpinBox) self.decimalsSpinBox.valueChanged.connect(self.data_changed) self.last_decimals = self.decimalsSpinBox.value() # min self.minLabel = QLabel(self.tr("minimum:")) self.minSpinBox =QDoubleSpinBox() self.minSpinBox.setRange(-sys.maxsize, sys.maxsize) self.minLabel.setBuddy(self.minSpinBox) self.minSpinBox.setValue(self.item.min or 0.0) # max self.maxLabel = QLabel(self.tr("maximum:")) self.maxSpinBox = QDoubleSpinBox() self.maxSpinBox.setRange(-sys.maxsize, sys.maxsize) self.maxSpinBox.setValue(self.item.max or 100.0) # numerator self.scalefactorLabel = QLabel(self.tr("scalefactor:")) self.scalefactorSpinBox = NoZerosDoubleSpinBox() self.scalefactorSpinBox.setRange(-sys.maxsize, sys.maxsize) self.scalefactorSpinBox.setButtonSymbols(QSpinBox.NoButtons) self.scalefactorSpinBox.setDecimals(10) self.scalefactorSpinBox.setValue(self.item.scalefactor or 1) self.scalefactorLabel.setBuddy(self.scalefactorSpinBox) # readonly self.readonlyCheckBox = QCheckBox(self.tr("readonly")) self.readonlyCheckBox.setChecked(Qt.Checked if self.item.readonly else Qt.Unchecked) self.readonlyCheckBox.stateChanged.connect(self.data_changed) # buttons self.buttons = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal ) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) # layout layout = QGridLayout() layout.addWidget(self.nameLabel, 0, 0) layout.addWidget(self.nameLineEdit, 0, 1) layout.addWidget(self.unitLabel, 1, 0) layout.addWidget(self.unitLineEdit, 1, 1) layout.addWidget(self.typeLabel, 2, 0) layout.addWidget(self.typeComboBox, 2, 1) layout.addWidget(self.decimalsLabel, 3, 0) layout.addWidget(self.decimalsSpinBox, 3, 1) layout.addWidget(self.minLabel, 4, 0) layout.addWidget(self.minSpinBox, 4, 1) layout.addWidget(self.maxLabel, 5, 0) layout.addWidget(self.maxSpinBox, 5, 1) layout.addWidget(self.scalefactorLabel, 6, 0) layout.addWidget(self.scalefactorSpinBox, 6, 1) layout.addWidget(self.readonlyCheckBox, 7, 0, 1, 2) layout.addWidget(self.buttons, 8, 0, 1, 2) self.setLayout(layout) # misc self.setWindowTitle("Edit JsonItem '%s'" % self.item.key) self.data_changed() def accept(self): self.item.name = self.nameLineEdit.text() self.item.unit = self.unitLineEdit.text() self.item.decimals = self.decimalsSpinBox.value() self.item.min = self.minSpinBox.value() self.item.max = self.maxSpinBox.value() self.item.scalefactor = self.scalefactorSpinBox.value() self.item.readonly = self.readonlyCheckBox.checkState() == Qt.Checked self.item.type = self.typeComboBox.currentText() return super().accept() def data_changed(self): type_numeric = self.typeComboBox.currentText() not in ('bool', 'str') type_int = self.typeComboBox.currentText() == 'int' readonly = self.readonlyCheckBox.checkState() == Qt.Checked # not used properties invisible self.decimalsSpinBox.setVisible(type_numeric) self.decimalsLabel.setVisible(type_numeric) self.scalefactorSpinBox.setVisible(type_numeric) self.scalefactorLabel.setVisible(type_numeric) self.minSpinBox.setVisible(type_numeric and not readonly) self.minLabel.setVisible(type_numeric and not readonly) self.maxSpinBox.setVisible(type_numeric and not readonly) self.maxLabel.setVisible(type_numeric and not readonly) self.unitLineEdit.setVisible(type_numeric) self.unitLabel.setVisible(type_numeric) # no decimals for int self.minSpinBox.setDecimals(self.decimalsSpinBox.value()) self.maxSpinBox.setDecimals(self.decimalsSpinBox.value()) if type_int: delta = self.decimalsSpinBox.value() - self.last_decimals self.scalefactorSpinBox.setValue( self.scalefactorSpinBox.value() / 10**delta ) self.last_decimals = self.decimalsSpinBox.value()
class DimensionMDE(Dimension): binningChanged = Signal() """ MDEventWorkspace has additional properties for either number_of_bins or thickness from mantidqt.widgets.sliceviewer.dimensionwidget import DimensionMDE from qtpy.QtWidgets import QApplication app = QApplication([]) window = DimensionMDE({'minimum':-1.1, 'number_of_bins':11, 'width':0.2, 'name':'Dim0', 'units':'A'}) window.show() app.exec_() """ def __init__(self, dim_info, number=0, state=State.NONE, parent=None): # hack in a number_of_bins for MDEventWorkspace dim_info['number_of_bins'] = 1000 dim_info['width'] = (dim_info['maximum'] - dim_info['minimum']) / 1000 self.spinBins = QSpinBox() self.spinBins.setRange(2, 9999) self.spinBins.setValue(100) self.spinBins.hide() self.spinBins.setMinimumWidth(110) self.spinThick = QDoubleSpinBox() self.spinThick.setRange(0.001, 999) self.spinThick.setValue(0.1) self.spinThick.setSingleStep(0.1) self.spinThick.setDecimals(3) self.spinThick.setMinimumWidth(110) self.rebinLabel = QLabel("thick") self.rebinLabel.setMinimumWidth(44) super().__init__(dim_info, number, state, parent) self.spinBins.valueChanged.connect(self.binningChanged) self.spinThick.valueChanged.connect(self.valueChanged) self.layout.addWidget(self.spinBins) self.layout.addWidget(self.spinThick) self.layout.addWidget(self.rebinLabel) def get_bins(self): return int(self.spinBins.value()) def get_thickness(self): return float(self.spinThick.value()) def set_state(self, state): super().set_state(state) if self.state == State.X: self.spinBins.show() self.spinThick.hide() self.rebinLabel.setText('bins') elif self.state == State.Y: self.spinBins.show() self.spinThick.hide() self.rebinLabel.setText('bins') elif self.state == State.NONE: self.spinBins.hide() self.spinThick.show() self.rebinLabel.setText('thick') else: self.spinBins.hide() self.spinThick.hide() self.rebinLabel.hide()
class MainWindow(QMainWindow): def selectFileToOpen(self): def getPreProcessingChoice(self, filename, filestructure): items = ("Choose the longest", "Merge all") item, okPressed = QInputDialog.getItem( self, "Multiple tracks/segments", "File '" + filename + "' contains more than one track/segment\n\n" + infos + "\nWhat to do?", items, 0, False) if okPressed and item: return items.index(item) else: return 0 # Try to recover the last used directory old_directory = self.settings.value("lastdirectory", str) # Check if the setting exists if old_directory is not None: # Check if it's not empty if old_directory: old_directory = old_directory else: old_directory = bombo.TRACKS_FOLDER else: old_directory = bombo.TRACKS_FOLDER # Open the dialog box fullfilename_list = QFileDialog.getOpenFileNames( self, 'Open .gpx', old_directory, "GPX files (*.gpx)") if os.environ['QT_API'] == 'pyqt': pass elif os.environ['QT_API'] == 'pyqt5': fullfilename_list = fullfilename_list[0] # Process every selected file for i, fullfilename in enumerate(fullfilename_list): # Process filename directory, filename = os.path.split(str(fullfilename)) filename, fileextension = os.path.splitext(filename) # Save the new directory in the application settings (it only # needs to be done once) if i == 0: # print "New directory to be saved: {}\n".format(directory) if os.environ['QT_API'] == 'pyqt': self.settings.setValue("lastdirectory", str(directory)) elif os.environ['QT_API'] == 'pyqt5': self.settings.setValue("lastdirectory", QtCore.QVariant(str(directory))) # Open file and inspect what's inside gpxraw, longest_traseg, Ntracks, Nsegments, infos = bombo.LoadGPX( fullfilename) # If there's more than one track or segment, ask how to proceed if (Ntracks > 1) or (Nsegments > 1): preprocessingchoice = getPreProcessingChoice( self, filename, infos) if preprocessingchoice == 0: preprocessedgpx = bombo.SelectOneTrackAndSegmentFromGPX( gpxraw, longest_traseg[0], longest_traseg[1]) listname = filename + " (longest)" elif preprocessingchoice == 1: preprocessedgpx = bombo.MergeAllTracksAndSegmentsFromGPX( gpxraw) listname = filename + " (merged)" else: preprocessedgpx = gpxraw listname = filename # Append the list of open GPX files using the next available color (that's the size of the list -1) self.gpxlist.append(preprocessedgpx) self.gpxnamelist.append(listname) newitem = QListWidgetItem(listname) newitem.setBackground( QtGui.QColor(self.palette[len(self.gpxlist) - 1])) self.tracklist.addItem(newitem) return def Go(self): if len(self.gpxselectedlist) > 0: # Temporarily change cursor QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) # Clear up global variables self.proc_coords = [] self.proc_measurements = [] self.proc_state_means = [] self.proc_state_vars = [] self.proc_new_coords = [] self.proc_new_gpx = [] self.proc_coords_to_plot = [] self.proc_coords_to_plot2 = [] self.proc_balloondata = [] # For every GPX file that is selected self.textWarningConsole.clear() for i, currentgpx in enumerate(self.gpxselectedlist): # Parse the GPX file gpx, coords, dinfos_before, warnings = bombo.ParseGPX( currentgpx, track_nr=0, segment_nr=0, use_srtm_elevation=bool(self.checkUseSRTM.isChecked())) self.textWarningConsole.append(warnings) # Kalman processing coords, measurements, state_means, state_vars, dinfos_during = bombo.ApplyKalmanFilter( coords, gpx, method=self.comboBoxProcessingMethod.currentIndex(), use_acceleration=self.checkUseAcceleration.isChecked(), extra_smooth=self.checkExtraSmooth.isChecked(), debug_plot=False) # Save data in GPX structure to compute speed and elevations new_coords, new_gpx, dinfos_after = bombo.SaveDataToCoordsAndGPX( coords, state_means) # Update GUI with the computed stats parent = QtGui.QStandardItem(self.gpxselectednamelist[i]) parent_beforeprocessing = QtGui.QStandardItem("Raw GPX stats") parent_beforeprocessing.appendRow([ QtGui.QStandardItem("Total distance"), QtGui.QStandardItem(dinfos_before['total_distance']) ]) parent_beforeprocessing_moving = QtGui.QStandardItem("Moving") parent_beforeprocessing_moving.appendRow([ QtGui.QStandardItem("Time"), QtGui.QStandardItem(dinfos_before['moving_time']) ]) parent_beforeprocessing_moving.appendRow([ QtGui.QStandardItem("Distance"), QtGui.QStandardItem(dinfos_before['moving_distance']) ]) parent_beforeprocessing.appendRow( parent_beforeprocessing_moving) parent_beforeprocessing_idle = QtGui.QStandardItem("Idle") parent_beforeprocessing_idle.appendRow([ QtGui.QStandardItem("Time"), QtGui.QStandardItem(dinfos_before['idle_time']) ]) parent_beforeprocessing_idle.appendRow([ QtGui.QStandardItem("Distance"), QtGui.QStandardItem(dinfos_before['idle_distance']) ]) parent_beforeprocessing.appendRow(parent_beforeprocessing_idle) parent_beforeprocessing.appendRow([ QtGui.QStandardItem("Elevation"), QtGui.QStandardItem(dinfos_before['elevation']) ]) parent_beforeprocessing.appendRow([ QtGui.QStandardItem("Climb"), QtGui.QStandardItem(dinfos_before['climb']) ]) parent.appendRow(parent_beforeprocessing) parent.appendRow([ QtGui.QStandardItem("Samples"), QtGui.QStandardItem(dinfos_during['nsamples']) ]) parent.appendRow([ QtGui.QStandardItem("Total distance"), QtGui.QStandardItem(dinfos_after['total_distance']) ]) parent_moving = QtGui.QStandardItem("Moving") parent_moving.appendRow([ QtGui.QStandardItem("Time"), QtGui.QStandardItem(dinfos_after['moving_time']) ]) parent_moving.appendRow([ QtGui.QStandardItem("Distance"), QtGui.QStandardItem(dinfos_after['moving_distance']) ]) parent.appendRow(parent_moving) parent_idle = QtGui.QStandardItem("Idle") parent_idle.appendRow([ QtGui.QStandardItem("Time"), QtGui.QStandardItem(dinfos_after['idle_time']) ]) parent_idle.appendRow([ QtGui.QStandardItem("Distance"), QtGui.QStandardItem(dinfos_after['idle_distance']) ]) parent.appendRow(parent_idle) parent.appendRow([ QtGui.QStandardItem("Elevation"), QtGui.QStandardItem(dinfos_after['elevation']) ]) parent.appendRow([ QtGui.QStandardItem("Climb"), QtGui.QStandardItem(dinfos_after['climb']) ]) self.treemodel.appendRow(parent) # Create balloondata for the html plot balloondata = { 'distance': np.cumsum( bombo.HaversineDistance(np.asarray(new_coords['lat']), np.asarray( new_coords['lon']))), 'elevation': np.asarray(new_coords['ele']), 'speed': None } # Create extra data for the html plot (fully implemented in bombo, not here) """ data = np.ones((len(lat_cleaned),2)) data[:,0] = h_filtered / np.max(h_filtered) * 0.0004 data[:,1] = np.hstack((np.asarray([0]), speed_h)) / np.max(np.hstack((np.asarray([0]), speed_h))) * 0.0004 tangentdata = {'data': data, 'sides': (0, 1), 'palette': ('blue','red')} """ # Save relevant output in global variables self.proc_coords.append(coords) self.proc_measurements.append(measurements) self.proc_state_means.append(state_means) self.proc_state_vars.append(state_vars) self.proc_new_coords.append(new_coords) self.proc_new_gpx.append(new_gpx) self.proc_coords_to_plot.append( np.vstack((new_coords['lat'], new_coords['lon'])).T) self.proc_coords_to_plot2.append( np.vstack((coords['lat'], coords['lon'])).T) self.proc_balloondata.append(balloondata) # Restore original cursor QApplication.restoreOverrideCursor() # Generate embedded plots if len(self.gpxselectedlist) == 1: self.plotEmbeddedElevationAndSpeed.update_figure( measurements, state_means, new_gpx.tracks[0].segments[0]) self.plotEmbeddedDetails.update_figure( measurements, state_means, state_vars, new_gpx.tracks[0].segments[0]) else: # Commentato per adesso # self.plotEmbeddedElevationAndSpeed.update_figure_multiple_tracks(self.proc_measurements, self.proc_state_means, self.proc_new_gpx) self.plotEmbeddedElevationAndSpeed.clear_figure() self.plotEmbeddedDetails.clear_figure() # Generate html plot, if only one track is selected, proceed with the complete output, otherwise just plot the traces if len(self.gpxselectedlist) is 1: bombo.PlotOnMap( coords_array_list=self.proc_coords_to_plot, coords_array2_list=self.proc_coords_to_plot2, coords_palette=self.selectedpalette, tangentdata=None, balloondata_list=self.proc_balloondata, rdp_reduction=self.checkUseRDP.isChecked(), showmap=bool(self.check2DMapInExternalBrowser.isChecked())) else: bombo.PlotOnMap( coords_array_list=self.proc_coords_to_plot, coords_array2_list=None, coords_palette=self.selectedpalette, tangentdata=None, balloondata_list=self.proc_balloondata, rdp_reduction=self.checkUseRDP.isChecked(), showmap=bool(self.check2DMapInExternalBrowser.isChecked())) self.map2d.load(QtCore.QUrl(bombo.MAP_2D_FILENAME)) self.map2d.show() # Generate 3D plot, only with one track for the moment if len(self.gpxselectedlist) == 1: if self.check3DMapSelection.isChecked(): tile_selection = 'auto' else: tile_selection = self.text3DMapName.text() terrain, track, warnings = bombo.Generate3DMap( new_coords['lat'], new_coords['lon'], tile_selection=tile_selection, margin=self.spinbox3DMargin.value(), elevation_scale=self.spinbox3DElevationScale.value(), mapping='coords', use_osm_texture=True, texture_type='osm', texture_zoom=self.spinbox3DOSMZoom.value(), texture_invert=self.check3DOSMInvert.isChecked(), use_proxy=self.use_proxy, proxy_data=self.proxy_config, verbose=False) self.textWarningConsole.append(warnings) if terrain is not None: self.map3d.update_plot(terrain, track) else: self.textWarningConsole.setText( "You need to open a .gpx file before!") return def PlotSpecificAreaDialog(self): def PlotSpecificArea(): # Save coordinates for the next time if os.environ['QT_API'] == 'pyqt': self.settings.setValue("last_point_coord_lat", self.spinboxLatDec.value()) self.settings.setValue("last_point_coord_lon", self.spinboxLonDec.value()) elif os.environ['QT_API'] == 'pyqt5': self.settings.setValue( "last_point_coord_lat", QtCore.QVariant(self.spinboxLatDec.value())) self.settings.setValue( "last_point_coord_lon", QtCore.QVariant(self.spinboxLonDec.value())) # Select the 3D Map tab self.tab.setCurrentIndex(2) # Plot if self.check3DMapSelection.isChecked(): tile_selection = 'auto' else: tile_selection = self.text3DMapName.text() terrain, track, warnings = bombo.Generate3DMap( [self.spinboxLatDec.value()], [self.spinboxLonDec.value()], tile_selection=tile_selection, margin=self.spinbox3DMargin.value(), elevation_scale=self.spinbox3DElevationScale.value(), mapping='coords', use_osm_texture=True, texture_type='osm', texture_zoom=self.spinbox3DOSMZoom.value(), texture_invert=self.check3DOSMInvert.isChecked(), use_proxy=self.use_proxy, proxy_data=self.proxy_config, verbose=False) self.textWarningConsole.append(warnings) if terrain is not None: self.map3d.update_plot(terrain, track) d.done(0) def Convert(): try: dd = bombo.parse_dms(self.textLatLonGMS.text()) self.spinboxLatDec.setValue(dd[0]) self.spinboxLonDec.setValue(dd[1]) except: pass d = QDialog() grid = QGridLayout() hBox_coordsGMS = QHBoxLayout() hBox_coordsGMS.setSpacing(5) label = QLabel('Coordinates (gms)') grid.addWidget(label, 0, 0) self.textLatLonGMS = QLineEdit() self.textLatLonGMS.setText("") grid.addWidget(self.textLatLonGMS, 0, 1, 1, 2) button1 = QPushButton("Convert to decimal") button1.clicked.connect(Convert) grid.addWidget(button1, 0, 3) label = QLabel('Coordinates (decimal)') grid.addWidget(label, 1, 0) self.spinboxLatDec = QDoubleSpinBox() self.spinboxLatDec.setRange(-90, +90) self.spinboxLatDec.setSingleStep(0.0000001) self.spinboxLatDec.setDecimals(7) grid.addWidget(self.spinboxLatDec, 1, 1) self.spinboxLonDec = QDoubleSpinBox() self.spinboxLonDec.setRange(-180, +180) self.spinboxLonDec.setSingleStep(0.0000001) self.spinboxLonDec.setDecimals(7) grid.addWidget(self.spinboxLonDec, 1, 2) # Try to recover the last used points try: old_lat = self.settings.value("last_point_coord_lat", type=float) old_lon = self.settings.value("last_point_coord_lon", type=float) self.spinboxLatDec.setValue(old_lat) self.spinboxLonDec.setValue(old_lon) except: # Coordinates of Mt. Rinjani in Indonesia self.spinboxLatDec.setValue(-8.4166000) self.spinboxLonDec.setValue(116.4666000) button2 = QPushButton("Show 3D map") button2.clicked.connect(PlotSpecificArea) grid.addWidget(button2, 1, 3) d.setWindowTitle("Show point on 3D map") d.setLayout(grid) d.setWindowModality(QtCore.Qt.ApplicationModal) d.exec_() def ProxyDialog(self): def SetProxy(): self.use_proxy = bool(self.checkUseProxy.isChecked()) self.proxy_config = self.textProxyConfig.text() if os.environ['QT_API'] == 'pyqt': self.settings.setValue("use_proxy", self.use_proxy) self.settings.setValue("proxy_config", str(self.proxy_config)) elif os.environ['QT_API'] == 'pyqt5': self.settings.setValue("use_proxy", QtCore.QVariant(self.use_proxy)) self.settings.setValue("proxy_config", QtCore.QVariant(str(self.proxy_config))) d.done(0) d = QDialog() box = QVBoxLayout() hBox_proxy = QHBoxLayout() hBox_proxy.setSpacing(5) label = QLabel('Proxy') hBox_proxy.addWidget(label) self.textProxyConfig = QLineEdit() try: self.textProxyConfig.setText( self.settings.value('proxy_config', str)) except: self.textProxyConfig.setText(bombo.PROXY_DATA) self.textProxyConfig.setMinimumWidth(200) hBox_proxy.addWidget(self.textProxyConfig) box.addLayout(hBox_proxy) self.checkUseProxy = QCheckBox("Use proxy") try: self.checkUseProxy.setChecked( self.settings.value('use_proxy', bool)) except: self.checkUseProxy.setChecked(bool(bombo.USE_PROXY)) box.addWidget(self.checkUseProxy) button = QPushButton("Save configuration") button.clicked.connect(SetProxy) box.addWidget(button) d.setWindowTitle("Proxy configuration") d.setLayout(box) d.setWindowModality(QtCore.Qt.ApplicationModal) d.exec_() def __init__(self, parent=None): super(MainWindow, self).__init__() self.initVariables() self.initUI() def initVariables(self): self.gpxlist = list() self.gpxnamelist = list() self.gpxselectedlist = list() self.gpxselectednamelist = list() self.palette = bombo.GeneratePalette(N=10) * 5 # replicated 5 times #self.palette = ["#0000FF", "#00FF00", "#00FFFF", "#FF0000", "#FF00FF", "#FFFF00", "#FFFFFF"] # test palette self.selectedpalette = list() self.proc_coords = list() self.proc_measurements = list() self.proc_state_means = list() self.proc_state_vars = list() self.proc_new_coords = list() self.proc_new_gpx = list() self.proc_coords_to_plot = list() self.proc_coords_to_plot2 = list() self.proc_balloondata = list() def initUI(self): def selection_changed(): # Retrieve selected items # selecteditems = self.tracklist.selectedItems() selectedindexes = self.tracklist.selectedIndexes() # Adding the selected items to the processing list self.gpxselectedlist[:] = [] self.gpxselectednamelist[:] = [] self.selectedpalette[:] = [] for i in selectedindexes: # print str(i.text()) self.gpxselectedlist.append(self.gpxlist[i.row()]) self.gpxselectednamelist.append(self.gpxnamelist[i.row()]) self.selectedpalette.append(self.palette[i.row()]) def ClearStats(): """ # Some other code that could be used in the future index = self.treemodel.indexFromItem(parent1) self.tree.expand(index) selmod = self.tree.selectionModel() index2 = self.treemodel.indexFromItem(child2) selmod.select(index2, QtCore.QItemSelectionModel.Select|QtCore.QItemSelectionModel.Rows) root = self.treemodel.invisibleRootItem() (item.parent() or root).removeChild(item) """ # Returns a list of indexes. In our case, for each row there are 2 indexes, cos there are 2 columns. for index in self.tree.selectedIndexes(): # Consider only the first columns if index.column() == 0: # Need to check if it's a top item (i.e. track), otherwise if a subitem (i.e. distance or time) is selected, the result might be buggy parent = index.parent() parent_item = self.treemodel.itemFromIndex(parent) if parent_item is None: self.treemodel.removeRow(index.row()) # Application Settings QtCore.QCoreApplication.setOrganizationName("Ste") QtCore.QCoreApplication.setOrganizationDomain( "https://github.com/stesalati/sport/") QtCore.QCoreApplication.setApplicationName("TrackAnalyser") # Config settings self.settings = QtCore.QSettings(self) # Proxy settings try: self.use_proxy = self.settings.value('use_proxy', bool) self.proxy_config = self.settings.value('proxy_config', str) except: self.use_proxy = bombo.USE_PROXY self.proxy_config = bombo.PROXY_DATA # Actions openfile = QAction(QtGui.QIcon("icons/openfile.png"), "Open .gpx", self) openfile.setShortcut("Ctrl+O") openfile.setStatusTip("Open file") openfile.triggered.connect(self.selectFileToOpen) go = QAction(QtGui.QIcon("icons/go.png"), "Go!", self) go.setShortcut("Ctrl+R") go.setStatusTip("Run analysis") go.triggered.connect(self.Go) clearstats = QAction(QtGui.QIcon("icons/clear.png"), "Clear stats", self) clearstats.setShortcut("Ctrl+C") clearstats.setStatusTip("Clear stats") clearstats.triggered.connect(ClearStats) sep1 = QAction(self) sep1.setSeparator(True) showpoint = QAction(QtGui.QIcon("icons/point.png"), "Show point", self) showpoint.setShortcut("Ctrl+P") showpoint.setStatusTip("Show point") showpoint.triggered.connect(self.PlotSpecificAreaDialog) sep2 = QAction(self) sep2.setSeparator(True) quitapp = QAction(QtGui.QIcon("icons/quit.png"), "Quit", self) quitapp.setShortcut("Ctrl+Q") quitapp.setStatusTip("Quit application") quitapp.triggered.connect(qApp.quit) configs = QAction(QtGui.QIcon("icons/configs.png"), "Configs", self) configs.setStatusTip("Configs") configs.triggered.connect(self.ProxyDialog) # Menubar mainMenu = self.menuBar() configMenu = mainMenu.addMenu('&Config') configMenu.addAction(configs) # Toolbar toolbar = self.addToolBar('My tools') toolbar.addAction(openfile) toolbar.addAction(go) toolbar.addAction(clearstats) toolbar.addAction(sep1) toolbar.addAction(showpoint) toolbar.addAction(sep2) toolbar.addAction(quitapp) toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) toolbar.setIconSize(QtCore.QSize(30, 30)) # Status bar self.statusBar().show() # Main widget (everything that's not toolbar, statusbar or menubar must be in this widget) self.scatola = QWidget() # Main horizontal impagination hBox = QHBoxLayout() hBox.setSpacing(5) # Vertical left column vBox_left = QVBoxLayout() vBox_left.setSpacing(5) # 1st vertical box, a list self.tracklist = QListWidget() vBox_left.addWidget(self.tracklist) self.tracklist.setSelectionMode(QAbstractItemView.ExtendedSelection) self.tracklist.itemSelectionChanged.connect(selection_changed) self.tracklist.setMaximumHeight(120) # 2nd vertical box, containing several horizontal boxes, one for each setting vBox2 = QVBoxLayout() vBox2.setSpacing(5) # Just the group label labelSettings = QLabel('Settings') vBox2.addWidget(labelSettings) # Use/don't use corrected altitude self.checkUseSRTM = QCheckBox( "Use SRTM corrected elevation (needs Internet)") self.checkUseSRTM.setChecked(False) vBox2.addWidget(self.checkUseSRTM) # Choose processing method + use/don't use acceleration hBoxProcessingMethod = QHBoxLayout() labelProcessingMethod = QLabel('Processing method') hBoxProcessingMethod.addWidget(labelProcessingMethod) self.comboBoxProcessingMethod = QComboBox() self.comboBoxProcessingMethod.addItem("Just use available data") self.comboBoxProcessingMethod.addItem( "Fill all gaps at T=1s (resample)") self.comboBoxProcessingMethod.addItem("Fill only smaller gaps at T=1s") hBoxProcessingMethod.addWidget(self.comboBoxProcessingMethod) self.checkUseAcceleration = QCheckBox("Use acceleration") self.checkUseAcceleration.setChecked(False) hBoxProcessingMethod.addWidget(self.checkUseAcceleration) vBox2.addLayout(hBoxProcessingMethod) # Use/don't use variance smooth self.checkExtraSmooth = QCheckBox("Extra smooth") self.checkExtraSmooth.setChecked(False) vBox2.addWidget(self.checkExtraSmooth) # 2D interactive map settings hBox2DMap = QHBoxLayout() self.checkUseRDP = QCheckBox("Use RDP to reduce points") self.checkUseRDP.setChecked(False) hBox2DMap.addWidget(self.checkUseRDP) self.check2DMapInExternalBrowser = QCheckBox( "Show in external browser") self.check2DMapInExternalBrowser.setChecked(False) hBox2DMap.addWidget(self.check2DMapInExternalBrowser) vBox2.addLayout(hBox2DMap) # Settings for the 3D map line3DViewSettings = QFrame() #line3DViewSettings.setGeometry(QtCore.QRect(320, 150, 118, 3)) line3DViewSettings.setFrameShape(QFrame.HLine) line3DViewSettings.setFrameShadow(QFrame.Sunken) vBox2.addWidget(line3DViewSettings) label3DViewSettings = QLabel('3D view settings') vBox2.addWidget(label3DViewSettings) hBox3DMapSelection = QHBoxLayout() self.check3DMapSelection = QCheckBox( "Select elevation tiles automatically, otherwise") self.check3DMapSelection.setChecked(True) hBox3DMapSelection.addWidget(self.check3DMapSelection) self.text3DMapName = QLineEdit() self.text3DMapName.setText("Iceland.tif") hBox3DMapSelection.addWidget(self.text3DMapName) vBox2.addLayout(hBox3DMapSelection) hBox3D = QHBoxLayout() label3DMargin = QLabel('Margin') hBox3D.addWidget(label3DMargin) self.spinbox3DMargin = QSpinBox() self.spinbox3DMargin.setRange(50, 1000) self.spinbox3DMargin.setValue(100) self.spinbox3DMargin.setSingleStep(10) hBox3D.addWidget(self.spinbox3DMargin) labelSpace = QLabel(' ') hBox3D.addWidget(labelSpace) label3DElevationScale = QLabel('Elev. scale') hBox3D.addWidget(label3DElevationScale) self.spinbox3DElevationScale = QDoubleSpinBox() self.spinbox3DElevationScale.setRange(1, 50) self.spinbox3DElevationScale.setSingleStep(0.1) hBox3D.addWidget(self.spinbox3DElevationScale) hBox3D.addWidget(labelSpace) label3DOSMZoom = QLabel('Zoom') hBox3D.addWidget(label3DOSMZoom) self.spinbox3DOSMZoom = QSpinBox() self.spinbox3DOSMZoom.setRange(8, 15) self.spinbox3DOSMZoom.setValue(13) self.spinbox3DOSMZoom.setSingleStep(1) hBox3D.addWidget(self.spinbox3DOSMZoom) hBox3D.addWidget(labelSpace) self.check3DOSMInvert = QCheckBox("Invert") self.check3DOSMInvert.setChecked(False) hBox3D.addWidget(self.check3DOSMInvert) vBox2.addLayout(hBox3D) vBox_left.addLayout(vBox2) # 3rd stats tree lineTree = QFrame() lineTree.setFrameShape(QFrame.HLine) lineTree.setFrameShadow(QFrame.Sunken) vBox2.addWidget(lineTree) labelTree = QLabel('Track stats') vBox2.addWidget(labelTree) self.tree = QTreeView() self.tree.setSelectionBehavior(QAbstractItemView.SelectRows) self.treemodel = QtGui.QStandardItemModel() self.treemodel.setHorizontalHeaderLabels(['Name', 'Value']) self.tree.setModel(self.treemodel) self.tree.setUniformRowHeights(True) self.tree.setColumnWidth(0, 200) vBox_left.addWidget(self.tree) # 4th text, containing text messages/errors self.textWarningConsole = QTextEdit() self.textWarningConsole.setReadOnly(True) self.textWarningConsole.setFont(QtGui.QFont("Courier New", FONTSIZE)) self.textWarningConsole.clear() self.textWarningConsole.setMaximumHeight(50) vBox_left.addWidget(self.textWarningConsole) # I put "vBox_left" inside a widget and then the widget inside "hBox" # instead of just doing "hBox.addLayout(vBox_left) so I can set its # maximum width. vBox_left_widget = QWidget() vBox_left_widget.setLayout(vBox_left) vBox_left_widget.setMinimumWidth(400) vBox_left_widget.setMaximumWidth(500) hBox.addWidget(vBox_left_widget) # Vertical right column self.tab = QTabWidget() # Tab 1: Summary: elevation and speed tab1 = QWidget() # The tab layout vBox_tab = QVBoxLayout() vBox_tab.setSpacing(5) # Plot area self.plotEmbeddedElevationAndSpeed = EmbeddedPlot_ElevationSpeed( width=5, height=4, dpi=100) self.plotEmbeddedElevationAndSpeed.setMinimumWidth(800) # Add toolbar to the plot self.mpl_toolbar1 = NavigationToolbar( self.plotEmbeddedElevationAndSpeed, self.scatola) # Add widgets to the layout vBox_tab.addWidget(self.plotEmbeddedElevationAndSpeed) vBox_tab.addWidget(self.mpl_toolbar1) # Associate the layout to the tab tab1.setLayout(vBox_tab) # Tab 2: html 2D map tab2 = QWidget() # The tab layout vBox_tab = QVBoxLayout() vBox_tab.setSpacing(5) # Area self.map2d = QtWebEngineWidgets.QWebEngineView() # Add widgets to the layout vBox_tab.addWidget(self.map2d) # Associate the layout to the tab tab2.setLayout(vBox_tab) # Tab 3: 3D plot tab3 = QWidget() # The tab layout vBox_tab = QVBoxLayout() vBox_tab.setSpacing(5) # Area self.map3d = MayaviQWidget() # Add widgets to the layout vBox_tab.addWidget(self.map3d) # Associate the layout to the tab tab3.setLayout(vBox_tab) # Tab 4: Details tab4 = QWidget() # The tab layout vBox_tab = QVBoxLayout() vBox_tab.setSpacing(5) # Plot area self.plotEmbeddedDetails = EmbeddedPlot_Details(width=5, height=4, dpi=100) self.plotEmbeddedDetails.setMinimumWidth(800) # Add toolbar to the plot self.mpl_toolbar2 = NavigationToolbar(self.plotEmbeddedDetails, self.scatola) # Add widgets to the layout vBox_tab.addWidget(self.plotEmbeddedDetails) vBox_tab.addWidget(self.mpl_toolbar2) # Associate the layout to the tab tab4.setLayout(vBox_tab) # Associate tabs self.tab.addTab(tab1, "Summary") self.tab.addTab(tab2, "2D Map") self.tab.addTab(tab3, "3D Map") self.tab.addTab(tab4, "Details") hBox.addWidget(self.tab) # Setting hBox as main box self.scatola.setLayout(hBox) self.setCentralWidget(self.scatola) # Application settings self.setWindowTitle('TrackAnalyser') self.setWindowIcon((QtGui.QIcon('icons/app.png'))) self.setGeometry(100, 100, 1200, 700) self.show()
class SliderSpinBox(QWidget): valueChanged = Signal(float) def __init__(self, parent=None, value_range=(0, 100), slider_steps=100, spinbox_steps=1000, decimals=None): QWidget.__init__(self, parent) layout = QHBoxLayout(self) self.setLayout(layout) self.horizontalSlider = QSlider(Qt.Horizontal, self) self.doubleSpinBox = QDoubleSpinBox(self) self.decimals = decimals layout.setMargin(0) layout.addWidget(self.doubleSpinBox) layout.addWidget(self.horizontalSlider) self.doubleSpinBox.valueChanged.connect(self.spinbox_changed) self.horizontalSlider.valueChanged.connect(self.slider_changed) self.wt = [] self.changer = None self.slider_steps = slider_steps self.horizontalSlider.setMaximum(slider_steps) self.spinbox_steps = spinbox_steps self.set_range(value_range) def set_value(self, value): self.doubleSpinBox.setValue(value) value = property(lambda self: self.doubleSpinBox.value(), set_value) def set_range(self, value_range): self.changer = "set_range" spinbox_step_decimal = np.ceil(np.log10(1. / (float(value_range[1] - value_range[0]) / self.spinbox_steps))) self.slider_decimals = int(np.ceil(np.log10(self.slider_steps) - np.log10(value_range[1] - value_range[0]))) if self.decimals is None: self.doubleSpinBox.setDecimals(spinbox_step_decimal + 1) else: self.doubleSpinBox.setDecimals(self.decimals) spinbox_step_decimal = min(self.decimals, spinbox_step_decimal) self.slider_decimals = min(self.decimals, self.slider_decimals) self.doubleSpinBox.setSingleStep(10 ** -spinbox_step_decimal) self.value_range = value_range self.doubleSpinBox.setMinimum(value_range[0]) self.doubleSpinBox.setMaximum(value_range[1]) self.horizontalSlider.setValue(np.floor(value_range[0])) self.changer = None self.doubleSpinBox.setValue(value_range[0]) def range(self): return self.doubleSpinBox.minimum(), self.doubleSpinBox.maximum() def slider_changed(self, value): if self.changer is None: self.changer = 'slider' value = np.round(value * (self.value_range[1] - self.value_range[0]) / self.slider_steps + self.value_range[0], self.slider_decimals) self.doubleSpinBox.setValue(value) self.changer = None self.value_changed(value) def spinbox_changed(self, value): if self.changer is None: self.changer = 'spinbox' slider_value = .5 + (value - self.value_range[0]) * self.slider_steps / (self.value_range[1] - self.value_range[0]) self.horizontalSlider.setValue(slider_value) self.changer = None self.value_changed(value) @postpone_until_last_call_finishes def value_changed(self, value): self.valueChanged.emit(value)
class DimensionMDE(Dimension): binningChanged = Signal() """ MDEventWorkspace has additional properties for either number_of_bins or thickness from mantidqt.widgets.sliceviewer.dimensionwidget import DimensionMDE from qtpy.QtWidgets import QApplication app = QApplication([]) window = DimensionMDE({'minimum':-1.1, 'number_of_bins':11, 'width':0.2, 'name':'Dim0', 'units':'A'}) window.show() app.exec_() """ def __init__(self, dim_info, number=0, state=State.NONE, parent=None): # hack in a number_of_bins for MDEventWorkspace dim_info['number_of_bins'] = 1000 dim_info['width'] = (dim_info['maximum']-dim_info['minimum'])/1000 self.spinBins = QSpinBox() self.spinBins.setRange(2,9999) self.spinBins.setValue(100) self.spinBins.hide() self.spinBins.setMinimumWidth(110) self.spinThick = QDoubleSpinBox() self.spinThick.setRange(0.001,999) self.spinThick.setValue(0.1) self.spinThick.setSingleStep(0.1) self.spinThick.setDecimals(3) self.spinThick.setMinimumWidth(110) self.rebinLabel = QLabel("thick") self.rebinLabel.setMinimumWidth(44) super(DimensionMDE, self).__init__(dim_info, number, state, parent) self.spinBins.valueChanged.connect(self.binningChanged) self.spinThick.valueChanged.connect(self.valueChanged) self.layout.addWidget(self.spinBins) self.layout.addWidget(self.spinThick) self.layout.addWidget(self.rebinLabel) def get_bins(self): return int(self.spinBins.value()) def get_thickness(self): return float(self.spinThick.value()) def set_state(self, state): super(DimensionMDE, self).set_state(state) if self.state == State.X: self.spinBins.show() self.spinThick.hide() self.rebinLabel.setText('bins') elif self.state == State.Y: self.spinBins.show() self.spinThick.hide() self.rebinLabel.setText('bins') elif self.state == State.NONE: self.spinBins.hide() self.spinThick.show() self.rebinLabel.setText('thick') else: self.spinBins.hide() self.spinThick.hide() self.rebinLabel.hide()
class EpochDialog(QDialog): def __init__(self, parent, events): super().__init__(parent) self.setWindowTitle("Create Epochs") grid = QGridLayout(self) label = QLabel("Events:") label.setAlignment(Qt.AlignTop) grid.addWidget(label, 0, 0, 1, 1) self.events = QListWidget() self.events.insertItems(0, unique(events[:, 2]).astype(str)) self.events.setSelectionMode(QListWidget.ExtendedSelection) grid.addWidget(self.events, 0, 1, 1, 2) grid.addWidget(QLabel("Interval around events:"), 1, 0, 1, 1) self.tmin = QDoubleSpinBox() self.tmin.setMinimum(-10000) self.tmin.setValue(-0.2) self.tmin.setSingleStep(0.1) self.tmin.setAlignment(Qt.AlignRight) self.tmax = QDoubleSpinBox() self.tmax.setMinimum(-10000) self.tmax.setValue(0.5) self.tmax.setSingleStep(0.1) self.tmax.setAlignment(Qt.AlignRight) grid.addWidget(self.tmin, 1, 1, 1, 1) grid.addWidget(self.tmax, 1, 2, 1, 1) self.baseline = QCheckBox("Baseline Correction:") self.baseline.setChecked(True) self.baseline.stateChanged.connect(self.toggle_baseline) grid.addWidget(self.baseline, 2, 0, 1, 1) self.a = QDoubleSpinBox() self.a.setMinimum(-10000) self.a.setValue(-0.2) self.a.setSingleStep(0.1) self.a.setAlignment(Qt.AlignRight) self.b = QDoubleSpinBox() self.b.setMinimum(-10000) self.b.setValue(0) self.b.setSingleStep(0.1) self.b.setAlignment(Qt.AlignRight) grid.addWidget(self.a, 2, 1, 1, 1) grid.addWidget(self.b, 2, 2, 1, 1) self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonbox.accepted.connect(self.accept) self.buttonbox.rejected.connect(self.reject) grid.addWidget(self.buttonbox, 3, 0, 1, -1) self.events.itemSelectionChanged.connect(self.toggle_ok) self.toggle_ok() grid.setSizeConstraint(QGridLayout.SetFixedSize) @Slot() def toggle_ok(self): if self.events.selectedItems(): self.buttonbox.button(QDialogButtonBox.Ok).setEnabled(True) else: self.buttonbox.button(QDialogButtonBox.Ok).setEnabled(False) @Slot() def toggle_baseline(self): if self.baseline.isChecked(): self.a.setEnabled(True) self.b.setEnabled(True) else: self.a.setEnabled(False) self.b.setEnabled(False)
class _LinkLengthDialog(QDialog): """Link length dialog.""" vlinks: Dict[str, FrozenSet[int]] def __init__(self, parent: MainWindowBase): super(_LinkLengthDialog, self).__init__(parent) self.setWindowTitle("Set Link Length") self.main_layout = QVBoxLayout(self) layout = QHBoxLayout() self.leader = QComboBox(self) self.follower = QComboBox(self) self.length = QDoubleSpinBox(self) layout.addWidget(self.leader) layout.addWidget(self.follower) layout.addWidget(self.length) self.main_layout.addLayout(layout) self.vpoints = parent.vpoint_list self.vlinks = { vlink.name: frozenset(vlink.points) for vlink in parent.vlink_list } self.leader.currentTextChanged.connect(self.__set_follower) self.follower.currentTextChanged.connect(self.__set_length) self.leader.addItems([f"P{i}" for i in range(len(self.vpoints))]) self.leader.setCurrentIndex(0) self.length.setMaximum(100000) button_box = QDialogButtonBox(self) button_box.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) button_box.button(QDialogButtonBox.Ok).setEnabled( bool(parent.vpoint_list)) self.main_layout.addWidget(button_box) @Slot(str) def __set_follower(self, leader: str) -> None: """Set follower options.""" self.follower.clear() n = int(leader.replace('P', '')) options: Set[int] = set() for name, points in self.vlinks.items(): if name == VLink.FRAME: continue if n in points: options.update(points) options.discard(n) self.follower.addItems([f"P{i}" for i in options]) @Slot(str) def __set_length(self, follower: str) -> None: """Set the current length of two points.""" if not follower: return n1 = self.get_leader() n2 = int(follower.replace('P', '')) self.length.setValue(self.vpoints[n1].distance(self.vpoints[n2])) def get_leader(self) -> int: """Get current leader.""" return int(self.leader.currentText().replace('P', '')) def get_follower(self) -> int: """Get current follower.""" return int(self.follower.currentText().replace('P', '')) def get_length(self) -> float: """Get current length.""" return self.length.value()