class ColorMapWidget(QWidget): """Interface for changing ColorMap information. It shows the current color map selection, a selector for other colormaps, and the option to cycle the color map by any number of ordinal values. This widget was designed for use with the tab dialog. It can be used by itself or it can be used as part of a bigger color tab. Changes to this widget are emitted via a changeSignal as a ColorMap object and this widget's tag. """ changeSignal = Signal(ColorMap, str) def __init__(self, parent, initial_map, tag): """Creates a ColorMap widget. parent The Qt parent of this widget. initial_map The colormap set on creation. tag A name for this widget, will be emitted on change. """ super(ColorMapWidget, self).__init__(parent) self.color_map = initial_map.color_map self.color_map_name = initial_map.color_map_name self.color_step = initial_map.color_step self.step_size = initial_map.step_size self.tag = tag self.color_map_label = "Color Map" self.color_step_label = "Cycle Color Map" self.number_steps_label = "Colors" self.color_step_tooltip = "Use the given number of evenly spaced " \ + " colors from the map and assign to discrete values in cycled " \ + " sequence." layout = QVBoxLayout() layout.addWidget(self.buildColorBarControl()) layout.addItem(QSpacerItem(5,5)) layout.addWidget(self.buildColorStepsControl()) self.setLayout(layout) def buildColorBarControl(self): """Builds the portion of this widget for color map selection.""" widget = QWidget() layout = QHBoxLayout() label = QLabel(self.color_map_label) self.colorbar = QLabel(self) self.colorbar.setPixmap(QPixmap.fromImage(ColorBarImage( self.color_map, 180, 15))) self.mapCombo = QComboBox(self) self.mapCombo.addItems(map_names) self.mapCombo.setCurrentIndex(map_names.index(self.color_map_name)) self.mapCombo.currentIndexChanged.connect(self.colorbarChange) layout.addWidget(label) layout.addItem(QSpacerItem(5,5)) layout.addWidget(self.mapCombo) layout.addItem(QSpacerItem(5,5)) layout.addWidget(self.colorbar) widget.setLayout(layout) return widget @Slot(int) def colorbarChange(self, ind): """Handles a selection of a different colormap.""" indx = self.mapCombo.currentIndex() self.color_map_name = map_names[indx] self.color_map = getMap(self.color_map_name) self.colorbar.setPixmap(QPixmap.fromImage(ColorBarImage( self.color_map, 180, 12))) self.changeSignal.emit(ColorMap(self.color_map_name, self.color_step, self.step_size), self.tag) def buildColorStepsControl(self): """Builds the portion of this widget for color cycling options.""" widget = QWidget() layout = QHBoxLayout() self.stepBox = QCheckBox(self.color_step_label) self.stepBox.stateChanged.connect(self.colorstepsChange) self.stepEdit = QLineEdit("8", self) # Setting max to sys.maxint in the validator causes an overflow! D: self.stepEdit.setValidator(QIntValidator(1, 65536, self.stepEdit)) self.stepEdit.setEnabled(False) self.stepEdit.editingFinished.connect(self.colorstepsChange) if self.color_step > 0: self.stepBox.setCheckState(Qt.Checked) self.stepEdit.setEnabled(True) layout.addWidget(self.stepBox) layout.addItem(QSpacerItem(5,5)) layout.addWidget(QLabel("with")) layout.addItem(QSpacerItem(5,5)) layout.addWidget(self.stepEdit) layout.addItem(QSpacerItem(5,5)) layout.addWidget(QLabel(self.number_steps_label)) widget.setLayout(layout) return widget def colorstepsChange(self): """Handles a change in the state of the color cycling for this colormap. """ if self.stepBox.checkState() == Qt.Checked: self.stepEdit.setEnabled(True) self.color_step = int(self.stepEdit.text()) self.changeSignal.emit(ColorMap(self.color_map_name, self.color_step, self.step_size), self.tag) else: self.stepEdit.setEnabled(False) self.color_step = 0 self.changeSignal.emit(ColorMap(self.color_map_name, self.color_step, self.step_size), self.tag)
class RenderSlicerParamWidget(QWidget): """ RenderSlicerParamWidget shows parameters with which slicers can be manipulated. """ def __init__(self, renderController, parent=None): super(RenderSlicerParamWidget, self).__init__(parent=parent) self.renderController = renderController self.renderController.slicesChanged.connect(self.setSlices) self.renderController.clippingBoxChanged.connect(self.showsClippingBox) self.renderController.clippingPlanesChanged.connect( self.showsClippingPlanes) self.sliceLabelTexts = ["Axial:", "Coronal:", "Sagittal:"] self.sliceLabels = [QLabel(text) for text in self.sliceLabelTexts] self.sliceCheckBoxes = [QCheckBox() for i in range(3)] for index in range(3): self.sliceCheckBoxes[index].clicked.connect(self.checkBoxChanged) self.sliceLabels[index].setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.sliceCheckBoxes[index].setEnabled(True) slicesLayout = QGridLayout() slicesLayout.setAlignment(Qt.AlignTop) for index in range(3): slicesLayout.addWidget(self.sliceLabels[index], index + 1, 0) slicesLayout.addWidget(self.sliceCheckBoxes[index], index + 1, 1) self.slicesGroupBox = QGroupBox() self.slicesGroupBox.setTitle("Visible slices") self.slicesGroupBox.setLayout(slicesLayout) # Create option to show clipping box self.clippingCheckBox = QCheckBox() self.clippingCheckBox.setChecked(self.renderController.clippingBox) self.clippingCheckBox.clicked.connect(self.clippingCheckBoxChanged) self.clippingPlanesCheckBox = QCheckBox() self.clippingPlanesCheckBox.setChecked( self.renderController.clippingPlanes) self.clippingPlanesCheckBox.clicked.connect( self.clippingPlanesCheckBoxChanged) self.resetButton = QPushButton("Reset") self.resetButton.clicked.connect(self.resetClippingBox) clippingLabel = QLabel("Clipping box:") clippingLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) clippingPlanesLabel = QLabel("Clipping planes:") clippingPlanesLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) clipLayout = QGridLayout() clipLayout.addWidget(clippingLabel, 0, 0) clipLayout.addWidget(self.clippingCheckBox, 0, 1) clipLayout.addWidget(clippingPlanesLabel, 1, 0) clipLayout.addWidget(self.clippingPlanesCheckBox, 1, 1) clipLayout.addWidget(self.resetButton, 2, 0) self.clippingGroupBox = QGroupBox() self.clippingGroupBox.setTitle("Clipping box") self.clippingGroupBox.setLayout(clipLayout) # Create a nice layout for the labels layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.addWidget(self.slicesGroupBox, 0, 0) layout.addWidget(self.clippingGroupBox, 0, 1) self.setLayout(layout) @Slot() def checkBoxChanged(self): """ Callback function for the check boxes. """ for index in range(3): showCheckBox = self.sliceCheckBoxes[index].checkState( ) == Qt.Checked self.renderController.setSliceVisibility(index, showCheckBox) @Slot(object) def setSlices(self, slices): for index in range(len(slices)): checkBox = self.sliceCheckBoxes[index] checkBox.setChecked(slices[index]) @Slot() def clippingCheckBoxChanged(self): """ Callback function for the clipping check box. """ self.renderController.showClippingBox( self.clippingCheckBox.checkState() == Qt.Checked) @Slot() def clippingPlanesCheckBoxChanged(self): """ Callback function for the clipping check box. """ self.renderController.showClippingPlanes( self.clippingPlanesCheckBox.checkState() == Qt.Checked) @Slot() def resetClippingBox(self): self.renderController.resetClippingBox() @Slot(bool) def showsClippingBox(self, show): self.clippingCheckBox.setChecked(show) @Slot(bool) def showsClippingPlanes(self, show): self.clippingPlanesCheckBox.setChecked(show)
class RenderSlicerParamWidget(QWidget): """ RenderSlicerParamWidget shows parameters with which slicers can be manipulated. """ def __init__(self, renderController, parent=None): super(RenderSlicerParamWidget, self).__init__(parent=parent) self.renderController = renderController self.renderController.slicesChanged.connect(self.setSlices) self.renderController.clippingBoxChanged.connect(self.showsClippingBox) self.renderController.clippingPlanesChanged.connect(self.showsClippingPlanes) self.sliceLabelTexts = ["Axial:", "Coronal:", "Sagittal:"] self.sliceLabels = [QLabel(text) for text in self.sliceLabelTexts] self.sliceCheckBoxes = [QCheckBox() for i in range(3)] for index in range(3): self.sliceCheckBoxes[index].clicked.connect(self.checkBoxChanged) self.sliceLabels[index].setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.sliceCheckBoxes[index].setEnabled(True) slicesLayout = QGridLayout() slicesLayout.setAlignment(Qt.AlignTop) for index in range(3): slicesLayout.addWidget(self.sliceLabels[index], index+1, 0) slicesLayout.addWidget(self.sliceCheckBoxes[index], index+1, 1) self.slicesGroupBox = QGroupBox() self.slicesGroupBox.setTitle("Visible slices") self.slicesGroupBox.setLayout(slicesLayout) # Create option to show clipping box self.clippingCheckBox = QCheckBox() self.clippingCheckBox.setChecked(self.renderController.clippingBox) self.clippingCheckBox.clicked.connect(self.clippingCheckBoxChanged) self.clippingPlanesCheckBox = QCheckBox() self.clippingPlanesCheckBox.setChecked(self.renderController.clippingPlanes) self.clippingPlanesCheckBox.clicked.connect(self.clippingPlanesCheckBoxChanged) self.resetButton = QPushButton("Reset") self.resetButton.clicked.connect(self.resetClippingBox) clippingLabel = QLabel("Clipping box:") clippingLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) clippingPlanesLabel = QLabel("Clipping planes:") clippingPlanesLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) clipLayout = QGridLayout() clipLayout.addWidget(clippingLabel, 0, 0) clipLayout.addWidget(self.clippingCheckBox, 0, 1) clipLayout.addWidget(clippingPlanesLabel, 1, 0) clipLayout.addWidget(self.clippingPlanesCheckBox, 1, 1) clipLayout.addWidget(self.resetButton, 2, 0) self.clippingGroupBox = QGroupBox() self.clippingGroupBox.setTitle("Clipping box") self.clippingGroupBox.setLayout(clipLayout) # Create a nice layout for the labels layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.addWidget(self.slicesGroupBox, 0, 0) layout.addWidget(self.clippingGroupBox, 0, 1) self.setLayout(layout) @Slot() def checkBoxChanged(self): """ Callback function for the check boxes. """ for index in range(3): showCheckBox = self.sliceCheckBoxes[index].checkState() == Qt.Checked self.renderController.setSliceVisibility(index, showCheckBox) @Slot(object) def setSlices(self, slices): for index in range(len(slices)): checkBox = self.sliceCheckBoxes[index] checkBox.setChecked(slices[index]) @Slot() def clippingCheckBoxChanged(self): """ Callback function for the clipping check box. """ self.renderController.showClippingBox(self.clippingCheckBox.checkState() == Qt.Checked) @Slot() def clippingPlanesCheckBoxChanged(self): """ Callback function for the clipping check box. """ self.renderController.showClippingPlanes(self.clippingPlanesCheckBox.checkState() == Qt.Checked) @Slot() def resetClippingBox(self): self.renderController.resetClippingBox() @Slot(bool) def showsClippingBox(self, show): self.clippingCheckBox.setChecked(show) @Slot(bool) def showsClippingPlanes(self, show): self.clippingPlanesCheckBox.setChecked(show)
class PersistentFilter(QWidget): CONFIG_SECTION = "Filters" apply_filter = Signal(str) """ Will be emitted when the user signals he wants to apply the current filter (the filter is passed as a unicode string to the signal). The filter is read from the filter_edit_widget passed in the constructor. """ @Slot() def _emit_apply_filter(self): self.apply_filter.emit(self.super_filter_entry.text()) def current_filter(self): return self.super_filter_entry.text() def remember_current_selection(self, config): f = self.get_filters_combo().current_filter() config.set(self.CONFIG_SECTION, f.family, f.filter_query_id) config.save() def load_last_filter(self, config): """ Loads last save filter (save inf configuration). If no filter found in configuration then we shall take a default one (arbitrarily) """ if config.is_set(self.CONFIG_SECTION, self._filter_family): filter_query_id = int( config.get(self.CONFIG_SECTION, self._filter_family)) mainlog.debug( "load_last_filter : there is a saved filter id={}".format( filter_query_id)) self.get_filters_combo().preselect(filter_query_id) else: mainlog.debug( "load_last_filter : no saved filter, defaulting to one") self.filter_name.preselect(None) @Slot() def _filters_selected_from_combo_box(self, fq): self._show_filter(fq) self._emit_apply_filter() def get_filters_combo(self): if not self.filter_name: self.filter_name = FiltersCombo(self, self._filter_family) self.filter_name.filter_query_selected.connect( self._filters_selected_from_combo_box) return self.filter_name def select_default_filter(self): self.filter_name.preselect(None, emit_selection_signal=True) def __init__(self, filter_family: str, suggestion_finder=None, parent=None): super(PersistentFilter, self).__init__(parent) self.filter_name = None self._filter_family = filter_family self.apply_filter_action = QAction(_("Filter"), self) self.apply_filter_action.triggered.connect(self._emit_apply_filter) self.save_filter_action = QAction(_("Save filter"), self) self.save_filter_action.triggered.connect(self.save_filter_action_slot) self.save_filter_as_action = QAction(_("Save filter as"), self) self.save_filter_as_action.triggered.connect( self.save_filter_as_action_slot) self.delete_filter_action = QAction(_("Delete filter"), self) self.delete_filter_action.triggered.connect( self.delete_filter_action_slot) def action_to_button(action): b = QPushButton(action.text()) b.clicked.connect(action.trigger) return b hlayout_god_mode = QHBoxLayout() hlayout_god_mode.addWidget(QLabel(_("Filter :"))) self.query_label = QLabel() hlayout_god_mode.addWidget(self.query_label) hlayout_god_mode.addWidget(QLabel(_("Query :"))) if suggestion_finder: self.super_filter_entry = QueryLineEdit(suggestion_finder) else: self.super_filter_entry = QLineEdit() hlayout_god_mode.addWidget(self.super_filter_entry) # self.completion.setParent(self.super_filter_entry) # self.super_filter_entry.cursorPositionChanged.connect(self.cursorPositionChanged_slot) self.super_filter_entry.editingFinished.connect( self.completEditFinished_slot) self.super_filter_entry.returnPressed.connect(self._emit_apply_filter) self.share_filter = QCheckBox(_("Shared")) hlayout_god_mode.addWidget(self.share_filter) self.super_filter_button = action_to_button(self.apply_filter_action) hlayout_god_mode.addWidget(self.super_filter_button) self.save_filter_button = action_to_button(self.save_filter_action) hlayout_god_mode.addWidget(self.save_filter_button) hlayout_god_mode.addWidget(action_to_button( self.save_filter_as_action)) self.delete_filter_button = action_to_button(self.delete_filter_action) hlayout_god_mode.addWidget(self.delete_filter_button) self.setLayout(hlayout_god_mode) # self._load_available_queries() def _populate_dto(self, dto): fq_query = self.super_filter_entry.text() if not fq_query or not fq_query.strip(): showWarningBox(_("The filter's query can't be empty"), None, parent=self, object_name="empty_filter_query") return False dto.owner_id = user_session.user_id dto.shared = self.share_filter.checkState() == Qt.Checked dto.query = fq_query dto.family = self._filter_family return True @Slot() def _show_filter(self, fq): if fq: mainlog.debug("_show_filter : {}".format(fq.query)) if fq.owner_id == user_session.user_id: self.query_label.setText("<b>{}</b>".format(fq.name)) else: self.query_label.setText("<b>{}</b> ({})".format( fq.name, fq.owner.fullname)) self.super_filter_entry.setText(fq.query) self.save_filter_button.setEnabled( fq.owner_id == user_session.user_id) self.delete_filter_button.setEnabled( fq.owner_id == user_session.user_id) if fq.shared: self.share_filter.setCheckState(Qt.Checked) else: self.share_filter.setCheckState(Qt.Unchecked) else: mainlog.debug("_show_filter : {}".format(None)) self.super_filter_entry.setText("") self.share_filter.setCheckState(Qt.Unchecked) self.save_filter_button.setEnabled(True) self.delete_filter_button.setEnabled(True) # @Slot() # def filter_activated_slot(self,ndx): # # fq_id = self.filter_name.itemData(self.filter_name.currentIndex()) # # if fq_id: # try: # fq = dao.filters_dao.find_by_id(fq_id) # self._show_filter(fq) # self._apply_filter() # except Exception as e: # showErrorBox(_("There was a problem while loading the filter. It may have been deleted by its owner"),None,e,object_name="missing_filter") # # MAke sure the filter doesn't appear anymore # self.filter_name.reload() # self.filter_name.preselect(None) # return # else: # self._show_filter(None) @Slot() def delete_filter_action_slot(self): try: fq_id = None if self.filter_name.currentIndex() >= 0: fq_id = self.filter_name.itemData( self.filter_name.currentIndex()) if not fq_id: showWarningBox( _("The filter you want to delete was never saved"), None, parent=self, object_name="no_need_to_delete_filter") return fq = dao.filters_dao.find_by_id(fq_id) if fq.owner_id != user_session.user_id: showWarningBox(_( "You can't delete the filter because it doesn't belong to you." ), None, parent=self, object_name="not_my_filter") return dao.filters_dao.delete_by_id(fq_id, user_session.user_id) self.filter_name.reload() self.filter_name.preselect(None) except Exception as e: mainlog.error("Can't delete fq_id = {}".format(fq_id)) showErrorBox(_("There was a problem while deleting the filter."), None, e, object_name="delete_filter_fatal") self.filter_name.reload() self.filter_name.preselect(None) @Slot() def save_filter_as_action_slot(self): d = GiveNewNameDialog(self) d.exec_() if d.result() == QDialog.Accepted: new_name = d.line_edit.text() if not dao.filters_dao.is_name_used(new_name, user_session.user_id, self._filter_family): fq = dao.filters_dao.get_dto(None) if self._populate_dto(fq): fq.name = new_name fq_id = dao.filters_dao.save(fq) self.filter_name.reload() self._show_filter(fq) self.filter_name.preselect(fq_id, emit_selection_signal=False) else: showErrorBox(_( "There is already a filter with that name. You must delete it first if you want to use that name." ), None, None, object_name="filter_with_same_name") @Slot() def save_filter_action_slot(self): ndx = self.filter_name.currentIndex() fq_id = None if ndx >= 0: fq_id = self.filter_name.itemData(ndx) fq_dto = dao.filters_dao.get_dto(fq_id) if fq_dto.owner_id == user_session.user_id: if self._populate_dto(fq_dto): fq_dto.name = self.filter_name.itemText(ndx) fq_id = dao.filters_dao.save(fq_dto) else: if yesNoBox(_("This is not your filter !"), _("OK to save it under another name ?") ) == QMessageBox.Yes: self.save_filter_as_action_slot() else: mainlog.debug("save_filter_action_slot ndx={}".format(ndx)) self.save_filter_as_action_slot() @Slot() def completEditFinished_slot(self): # self.super_filter_entry.completion.hide() self.nofocuslost = False
class LoginDialog(QDialog): def __init__(self, parent, user_session): super(LoginDialog, self).__init__(parent) self.user = None self.user_session = user_session title = _("{} Login").format(configuration.get("Globals", "name")) self.setWindowTitle(title) self.title_widget = TitleWidget(title, self) self.userid = QLineEdit() self.password = QLineEdit() self.password.setEchoMode(QLineEdit.Password) self.remember_me = QCheckBox() form_layout = QFormLayout() form_layout.addRow(_("User ID"), self.userid) form_layout.addRow(_("Password"), self.password) form_layout.addRow(_("Remember me"), self.remember_me) self.buttons = QDialogButtonBox() self.buttons.addButton(QDialogButtonBox.Ok) top_layout = QVBoxLayout() top_layout.addWidget(self.title_widget) top_layout.addWidget(QLabel(_("Please identify yourself"))) top_layout.addLayout(form_layout) top_layout.addWidget(self.buttons) self.setLayout(top_layout) # QWidget takes ownership of the layout self.buttons.accepted.connect(self.try_login) self.buttons.rejected.connect(self.cancel) self.userid.textEdited.connect(self.login_changed) if configuration.get("AutoLogin", "user"): self.remember_me.setCheckState(Qt.Checked) self.userid.setText(configuration.get("AutoLogin", "user")) self.password.setText(configuration.get("AutoLogin", "password")) mainlog.debug("__init__ login dialog") def showEvent(self, event): # Center the dialog on the screen super(LoginDialog, self).showEvent(event) scr = QApplication.desktop().screenGeometry() self.move(scr.center() - self.rect().center()) @Slot() def login_changed(self, text): self.remember_me.setCheckState(Qt.Unchecked) @Slot() def try_login(self): # self.user = services.employees.authenticate(self.userid.text(),pw) self.user = dao.employee_dao.authenticate( self.userid.text(), Employee.hash_password(self.password.text())) if self.user: super(LoginDialog, self).accept() self.initialize_session() self.setResult(QDialog.Accepted) return d = makeErrorBox(_("You can't log"), _("The user or password is not valid.")) d.exec_() d.deleteLater() return def authenticated_user(self): return self.user @Slot() def cancel(self): return super(LoginDialog, self).reject() def initialize_session(self): # if not user_session.is_active(): # the configuration may have forced a user self.user_session.open(self.user) if self.remember_me.checkState() == Qt.Checked: configuration.set("AutoLogin", "user", self.user_session.login) configuration.set("AutoLogin", "password", self.password.text()) configuration.save() elif configuration.get("AutoLogin", "user") or configuration.get( "AutoLogin", "password"): configuration.set("AutoLogin", "user", "") configuration.set("AutoLogin", "password", "") configuration.save()
class RenderSlicerParamWidget(QWidget): """ RenderSlicerParamWidget shows parameters with which slicers can be manipulated. """ def __init__(self, renderController, parent=None): super(RenderSlicerParamWidget, self).__init__(parent=parent) self.renderController = renderController self.renderController.slicesChanged.connect(self.setSlices) self.renderController.clippingBoxChanged.connect(self.showsClippingBox) self.slicesLabel = QLabel("Show slices for directions:") self.sliceLabelTexts = ["x:", "y:", "z:"] self.sliceLabels = [QLabel(text) for text in self.sliceLabelTexts] self.sliceCheckBoxes = [QCheckBox() for i in range(3)] for index in range(3): self.sliceCheckBoxes[index].clicked.connect(self.checkBoxChanged) self.sliceLabels[index].setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.sliceCheckBoxes[index].setEnabled(True) # Create a nice layout for the labels layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.setColumnStretch(0, 1) layout.setColumnStretch(1, 3) layout.addWidget(self.slicesLabel, 0, 0, 1, -1) for index in range(3): layout.addWidget(self.sliceLabels[index], index + 1, 0) layout.addWidget(self.sliceCheckBoxes[index], index + 1, 1) # Create option to show clipping box self.clippingCheckBox = QCheckBox() self.clippingCheckBox.clicked.connect(self.clippingCheckBoxChanged) self.clippingLabel = QLabel("Clipping box:") self.clippingLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) layout.addWidget(self.clippingLabel, 5, 0) layout.addWidget(self.clippingCheckBox, 5, 1) self.setLayout(layout) @Slot() def checkBoxChanged(self): """ Callback function for the check boxes. """ for index in range(3): showCheckBox = self.sliceCheckBoxes[index].checkState( ) == Qt.Checked self.renderController.setSliceVisibility(index, showCheckBox) @Slot(object) def setSlices(self, slices): for index in range(len(slices)): checkBox = self.sliceCheckBoxes[index] checkBox.setChecked(slices[index]) @Slot() def clippingCheckBoxChanged(self): """ Callback function for the clipping check box. """ self.renderController.showClippingBox( self.clippingCheckBox.checkState() == Qt.Checked) @Slot(bool) def showsClippingBox(self, show): self.clippingCheckBox.setChecked(show)
class RenderSlicerParamWidget(QWidget): """ RenderSlicerParamWidget shows parameters with which slicers can be manipulated. """ def __init__(self, renderController, parent=None): super(RenderSlicerParamWidget, self).__init__(parent=parent) self.renderController = renderController self.renderController.slicesChanged.connect(self.setSlices) self.renderController.clippingBoxChanged.connect(self.showsClippingBox) self.slicesLabel = QLabel("Show slices for directions:") self.sliceLabelTexts = ["x:", "y:", "z:"] self.sliceLabels = [QLabel(text) for text in self.sliceLabelTexts] self.sliceCheckBoxes = [QCheckBox() for i in range(3)] for index in range(3): self.sliceCheckBoxes[index].clicked.connect(self.checkBoxChanged) self.sliceLabels[index].setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.sliceCheckBoxes[index].setEnabled(True) # Create a nice layout for the labels layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.setColumnStretch(0, 1) layout.setColumnStretch(1, 3) layout.addWidget(self.slicesLabel, 0, 0, 1, -1) for index in range(3): layout.addWidget(self.sliceLabels[index], index+1, 0) layout.addWidget(self.sliceCheckBoxes[index], index+1, 1) # Create option to show clipping box self.clippingCheckBox = QCheckBox() self.clippingCheckBox.clicked.connect(self.clippingCheckBoxChanged) self.clippingLabel = QLabel("Clipping box:") self.clippingLabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) layout.addWidget(self.clippingLabel, 5, 0) layout.addWidget(self.clippingCheckBox, 5, 1) self.setLayout(layout) @Slot() def checkBoxChanged(self): """ Callback function for the check boxes. """ for index in range(3): showCheckBox = self.sliceCheckBoxes[index].checkState() == Qt.Checked self.renderController.setSliceVisibility(index, showCheckBox) @Slot(object) def setSlices(self, slices): for index in range(len(slices)): checkBox = self.sliceCheckBoxes[index] checkBox.setChecked(slices[index]) @Slot() def clippingCheckBoxChanged(self): """ Callback function for the clipping check box. """ self.renderController.showClippingBox(self.clippingCheckBox.checkState() == Qt.Checked) @Slot(bool) def showsClippingBox(self, show): self.clippingCheckBox.setChecked(show)
class ColorMapWidget(QWidget): """Interface for changing ColorMap information. It shows the current color map selection, a selector for other colormaps, and the option to cycle the color map by any number of ordinal values. This widget was designed for use with the tab dialog. It can be used by itself or it can be used as part of a bigger color tab. Changes to this widget are emitted via a changeSignal as a ColorMap object and this widget's tag. """ changeSignal = Signal(ColorMap, str) def __init__(self, parent, initial_map, tag): """Creates a ColorMap widget. parent The Qt parent of this widget. initial_map The colormap set on creation. tag A name for this widget, will be emitted on change. """ super(ColorMapWidget, self).__init__(parent) self.color_map = initial_map.color_map self.color_map_name = initial_map.color_map_name self.color_step = initial_map.color_step self.step_size = initial_map.step_size self.tag = tag self.color_map_label = "Color Map" self.color_step_label = "Cycle Color Map" self.number_steps_label = "Colors" self.color_step_tooltip = "Use the given number of evenly spaced " \ + " colors from the map and assign to discrete values in cycled " \ + " sequence." layout = QVBoxLayout() layout.addWidget(self.buildColorBarControl()) layout.addItem(QSpacerItem(5, 5)) layout.addWidget(self.buildColorStepsControl()) self.setLayout(layout) def buildColorBarControl(self): """Builds the portion of this widget for color map selection.""" widget = QWidget() layout = QHBoxLayout() label = QLabel(self.color_map_label) self.colorbar = QLabel(self) self.colorbar.setPixmap( QPixmap.fromImage(ColorBarImage(self.color_map, 180, 15))) self.mapCombo = QComboBox(self) self.mapCombo.addItems(map_names) self.mapCombo.setCurrentIndex(map_names.index(self.color_map_name)) self.mapCombo.currentIndexChanged.connect(self.colorbarChange) layout.addWidget(label) layout.addItem(QSpacerItem(5, 5)) layout.addWidget(self.mapCombo) layout.addItem(QSpacerItem(5, 5)) layout.addWidget(self.colorbar) widget.setLayout(layout) return widget @Slot(int) def colorbarChange(self, ind): """Handles a selection of a different colormap.""" indx = self.mapCombo.currentIndex() self.color_map_name = map_names[indx] self.color_map = getMap(self.color_map_name) self.colorbar.setPixmap( QPixmap.fromImage(ColorBarImage(self.color_map, 180, 12))) self.changeSignal.emit( ColorMap(self.color_map_name, self.color_step, self.step_size), self.tag) def buildColorStepsControl(self): """Builds the portion of this widget for color cycling options.""" widget = QWidget() layout = QHBoxLayout() self.stepBox = QCheckBox(self.color_step_label) self.stepBox.stateChanged.connect(self.colorstepsChange) self.stepEdit = QLineEdit("8", self) # Setting max to sys.maxint in the validator causes an overflow! D: self.stepEdit.setValidator(QIntValidator(1, 65536, self.stepEdit)) self.stepEdit.setEnabled(False) self.stepEdit.editingFinished.connect(self.colorstepsChange) if self.color_step > 0: self.stepBox.setCheckState(Qt.Checked) self.stepEdit.setEnabled(True) layout.addWidget(self.stepBox) layout.addItem(QSpacerItem(5, 5)) layout.addWidget(QLabel("with")) layout.addItem(QSpacerItem(5, 5)) layout.addWidget(self.stepEdit) layout.addItem(QSpacerItem(5, 5)) layout.addWidget(QLabel(self.number_steps_label)) widget.setLayout(layout) return widget def colorstepsChange(self): """Handles a change in the state of the color cycling for this colormap. """ if self.stepBox.checkState() == Qt.Checked: self.stepEdit.setEnabled(True) self.color_step = int(self.stepEdit.text()) self.changeSignal.emit( ColorMap(self.color_map_name, self.color_step, self.step_size), self.tag) else: self.stepEdit.setEnabled(False) self.color_step = 0 self.changeSignal.emit( ColorMap(self.color_map_name, self.color_step, self.step_size), self.tag)
class EditDeliverySlipDialog(QDialog): # def _make_units_qaulifications_gui(self): # hlayout = QHBoxLayout() # for qualif in [_("Good"), _("Bad"), _("Test")]: # hlayout.addWidget( QLabel(qualif)) # hlayout.addWidget( QLineEdit()) # # f = QGroupBox(_("Qualification of units")) # f.setLayout(hlayout) # return f def __init__(self,parent): global dao super(EditDeliverySlipDialog,self).__init__(parent) title = _("Create delivery slip") self.setWindowTitle(title) top_layout = QVBoxLayout() self.title_widget = TitleWidget(title,self) top_layout.addWidget(self.title_widget) self.info_label = QLabel() self.info_label.setWordWrap(True) top_layout.addWidget(self.info_label) self.buttons = QDialogButtonBox() self.buttons.addButton( QDialogButtonBox.StandardButton.Cancel) self.buttons.addButton( QDialogButtonBox.Ok) order_part_prototype = [] order_part_prototype.append( TextLinePrototype('human_identifier',_('Part n.'),editable=False)) order_part_prototype.append( TextLinePrototype('description',_('Description'),editable=False)) order_part_prototype.append( IntegerNumberPrototype('qty',_('Qty plan.'),editable=False)) order_part_prototype.append( IntegerNumberPrototype('tex2',_('Qty so far'),editable=False)) order_part_prototype.append( IntegerNumberPrototype(None,_('Qty out now'),nullable=True)) self.qty_out_column = len(order_part_prototype) - 1 # order_part_prototype.append( IntegerNumberPrototype(None,_('Reglages'),nullable=True)) # order_part_prototype.append( IntegerNumberPrototype(None,_('Derogation'),nullable=True)) # order_part_prototype.append( IntegerNumberPrototype(None,_('Rebus'),nullable=True)) self.controller_part = PrototypeController(self, order_part_prototype,None,freeze_row_count=True) self.controller_part.view.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents) self.controller_part.view.horizontalHeader().setResizeMode(1,QHeaderView.Stretch) self.controller_part.setModel(TrackingProxyModel(self,order_part_prototype)) self.close_order_checkbox = QCheckBox(_("Close the order")) top_layout.addWidget(self.controller_part.view) # self.time_tracks_view) # top_layout.addWidget(self._make_units_qaulifications_gui()) top_layout.addWidget(self.close_order_checkbox) top_layout.addWidget(self.buttons) self.setLayout(top_layout) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) sg = QDesktopWidget().screenGeometry() self.setMinimumWidth(0.5*sg.width()) self.setMinimumHeight(0.3*sg.height()) self.slip_id = None def set_data(self,order_id): self.slip_id = None self.order_id = order_id order = dao.order_dao.find_by_id(order_id) parts = list(filter(lambda part:part.qty > 0 and part.tex2 < part.qty, order.parts)) self.controller_part.model._buildModelFromObjects(parts) cn = "" if order.customer_order_name: cn = u" " + _("(customer number <b>{}</b>)").format(order.customer_order_name) self.info_label.setText(_("Creating a new delivery slip for order <b>{}</b>{} of customer <b>{}</b>").format(order.accounting_label,cn,order.customer.fullname)) for p in parts: x = p.order_part_id # Force attribute load session().expunge(p) session().commit() # FIXME let the locks go def _start_edit(self): # Out to allow testing ndx = self.controller_part.model.index(0,self.qty_out_column) self.controller_part.view.setCurrentIndex( ndx) self.controller_part.view.edit( ndx) def exec_(self): # Start editing the table when showing the dialog self._start_edit() super(EditDeliverySlipDialog,self).exec_() def save(self): return True @Slot() def accept(self): # I do this to make sure that if the user was editing some data # in the table, those data will actually be commited once he # pushed the button ndx = self.controller_part.view.currentIndex() self.controller_part.view.setCurrentIndex(self.controller_part.model.index(0,0)) self.controller_part.view.setCurrentIndex(ndx) if self.make_delivery_slip() == True: super(EditDeliverySlipDialog,self).accept() @Slot() def reject(self): super(EditDeliverySlipDialog,self).reject() def _check_unpriced_part(self): t = self.controller_part.model parts = dict() for p in dao.order_part_dao.find_by_order_id(self.order_id): parts[p.order_part_id] = p for i in range(t.rowCount()): if t.objects[i]: qty = t.data( t.index(i,self.qty_out_column), Qt.UserRole) or 0 order_part_id = t.objects[i].order_part_id if qty > 0 and parts[order_part_id].sell_price == 0: return True def _check_for_quantities_too_big(self): t = self.controller_part.model too_big = False order = dao.order_dao.find_by_id(self.order_id) for i in range(t.rowCount()): if t.objects[i]: qty = t.data( t.index(i,self.qty_out_column), Qt.UserRole) or 0 order_part_id = t.objects[i].order_part_id for part in order.parts: if part.order_part_id == order_part_id: if part.tex2 + qty > part.qty: too_big = True break session().commit() return too_big def make_delivery_slip(self): global dao t = self.controller_part.model # mainlog.debug(u"make_delivery_slip() {}".format(t.objects)) # Extract the quantities to get out from the order part table parts_ids_quantities = dict() info = u"" for i in range(t.rowCount()): qty = t.data( t.index(i,self.qty_out_column), Qt.UserRole) or 0 order_part = t.objects[i] mainlog.debug("Line {} qty = {}, order part={} ".format(i,qty, order_part is not None)) if order_part and qty > 0: if order_part.order_part_id not in parts_ids_quantities: parts_ids_quantities[order_part.order_part_id] = 0 parts_ids_quantities[order_part.order_part_id] += qty info = info + ("<li>" + _("For {} {}, quantity {}")\ + "</li>").format(t.data( t.index(i,0), Qt.UserRole), t.data( t.index(i,1), Qt.UserRole), qty) info = u"<ul>{}</ul>".format(info) mainlog.debug("edit_dialog : checking for missing quantities") if len(parts_ids_quantities) == 0: showWarningBox(_("You requested to create a new delivery slip. However, you didn't encode any quantities"),None,None,"quantity_missing") return False mainlog.debug("edit_dialog : checking for quantities") if self._check_for_quantities_too_big(): showErrorBox(_("One quantity is too big"), _("Pay attention ! On some parts, you gave a quantity out that will make the total quantity out bigger than what was ordered. You must either change the quantity out or change the planned quantity."),None,"quantityTooBig") return False if self._check_unpriced_part(): showWarningBox(_("Some of the parts you want to make a delivery slip for have a null sell price. This is not an error but you may want to double check that situation."),None,None,"unpriced_part") mainlog.debug("edit_dialog : confirmationBox to be opened order_id is {}".format(self.order_id)) if confirmationBox(u"<font color='red'><b>{}</b></font>".format(_("<b>You're about to make a new delivery slip. This can't be reversed, please confirm.\n Here are the quantities you're going to record")),info,"confirmDSCreation"): mainlog.debug("confirmationBox was OK") try: self.slip_id = dao.delivery_slip_part_dao.make_delivery_slip_for_order( self.order_id, parts_ids_quantities, datetime.now(), self.close_order_checkbox.checkState() == Qt.Checked) mainlog.debug("A delivery slip was created {}".format(self.slip_id)) return True except Exception as ex: showErrorBox(_("Error while creating the delivery slip"), _("The delivery slip was not created due to an unexpected error."),ex) return False