コード例 #1
0
class SpinBoxEvent(qt_import.QObject):

    returnPressedSignal = qt_import.pyqtSignal()
    contextMenuSignal = qt_import.pyqtSignal()

    def eventFilter(self, obj, event):
        if event.type() == qt_import.QEvent.KeyPress:
            if event.key() in [qt_import.Qt.Key_Enter, qt_import.Qt.Key_Return]:
                self.returnPressedSignal.emit()

        elif event.type() == qt_import.QEvent.MouseButtonRelease:
            self.returnPressedSignal.emit()
        elif event.type() == qt_import.QEvent.ContextMenu:
            self.contextMenuSignal.emit()
        return False
コード例 #2
0
    def disconnect_hwobj(self, sender, signal, slot):
        signal = str(signal)
        if signal[0].isdigit():
            pysignal = signal[0] == "9"
            signal = signal[1:]
        else:
            pysignal = True

        if isinstance(sender, HardwareObject):
            sender.disconnect(sender, signal, slot)
            return

        # workaround for PyQt lapse
        if hasattr(sender, "disconnectNotify"):
            sender.disconnect_notify(signal)

        if not isinstance(sender, qt_import.QObject):
            sender = emitter(sender)

            try:
                uid = (
                    sender,
                    pysignal and qt_import.pyqtSignal(signal)
                    or qt_import.pyqtSignal(signal),
                    hash(slot),
                )
                signal_slot_filter = self._signal_slot_filters[uid]
            except KeyError:
                getattr(sender, signal).disconnect(slot)
                # qt_import.QObject.disconnect(sender,
                #                            pysignal and
                #                            qt_import.QtCore.SIGNAL(signal) or
                #                            qt_import.QtCore.SIGNAL(signal),
                #                            slot)
            else:
                getattr(sender, signal).disconnect(signal_slot_filter)
                # qt_import.QObject.disconnect(sender,
                #                            pysignal and
                #                            qt_import.SIGNAL(signal) or
                #                            qt_import.SIGNAL(signal),
                #                            signal_slot_filter)
                del self._signal_slot_filters[uid]
        else:
            getattr(sender, signal).disconnect(signal_slot_filter)
コード例 #3
0
    def connect_hwobj(self,
                      sender,
                      signal,
                      slot,
                      instance_filter=False,
                      should_cache=True):

        if sys.version_info > (3, 0):
            signal = str(
                signal.decode("utf8") if isinstance(signal, bytes) else signal)
        else:
            signal = str(signal)

        if signal[0].isdigit():
            pysignal = signal[0] == "9"
            signal = signal[1:]
        else:
            pysignal = True

        if not isinstance(sender, qt_import.QObject):
            if isinstance(sender, HardwareObject):
                sender.connect(signal, slot)
                return
            else:
                _sender = emitter(sender)
        else:
            _sender = sender

        if instance_filter:
            self.connect_signal_slot_filter(
                _sender,
                pysignal and qt_import.pyqtSignal(signal)
                or qt_import.pyqtSignal(signal),
                slot,
                should_cache,
            )
        else:
            # Porting to Qt5
            getattr(_sender, signal).connect(slot)
コード例 #4
0
class DuoStateButton(qt_import.QToolButton):

    commandExecuteSignal = qt_import.pyqtSignal(bool)

    def __init__(self, parent, caption):
        qt_import.QToolButton.__init__(self, parent)

        self.setToolButtonStyle(qt_import.Qt.ToolButtonTextUnderIcon)
        self.executing = False
        self.run_icon = None
        self.stop_icon = None
        self.standard_color = self.palette().color(qt_import.QPalette.Window)
        self.setText(caption)
        self.setSizePolicy(qt_import.QSizePolicy.Expanding,
                           qt_import.QSizePolicy.Fixed)
        self.clicked.connect(self.button_clicked)

    def set_icons(self, icon_run, icon_stop):
        self.run_icon = icons.load_icon(icon_run)
        self.stop_icon = icons.load_icon(icon_stop)
        if self.executing:
            self.setIcon(self.stop_icon)
        else:
            self.setIcon(self.run_icon)

    def button_clicked(self):
        self.commandExecuteSignal.emit(not self.executing)
        # if not self.executing:
        #    self.setEnabled(False)

    def command_started(self):
        colors.set_widget_color(self, colors.LIGHT_YELLOW,
                                qt_import.QPalette.Button)
        if self.stop_icon is not None:
            self.setIcon(self.stop_icon)
        self.executing = True
        self.setEnabled(True)

    def is_executing(self):
        return self.executing

    def command_done(self):
        self.executing = False
        colors.set_widget_color(self, self.standard_color,
                                qt_import.QPalette.Button)
        if self.run_icon is not None:
            self.setIcon(self.run_icon)
        self.setEnabled(True)

    def command_failed(self):
        self.command_done()
コード例 #5
0
ファイル: log_view_brick.py プロジェクト: rhfogh/mxcube
class LogViewBrick(BaseWidget):
    """Views the log messages, either in a list or in separated tabs.
       In tab mode it is possible to send a feedback mail.
       The debug messages might me switched off (in either modes).
    """

    TOOLTIPS = {
        "info": "Displays the progress of the requested operations",
        "feedback": "Submits a feedback email about this software",
        "details": "Detailed messages, including warnings and errors",
        "debug": "Debug messages; please disregard them",
    }

    incUnreadMessagesSignal = qt_import.pyqtSignal(int, bool)
    resetUnreadMessagesSignal = qt_import.pyqtSignal(bool)

    def __init__(self, *args):
        BaseWidget.__init__(self, *args)

        # Hardware objects ----------------------------------------------------

        # Internal values -----------------------------------------------------

        # Properties ----------------------------------------------------------
        self.add_property("level", "combo",
                          ("NOT SET", "INFO", "WARNING", "ERROR"), "NOT SET")
        self.add_property("showDebug", "boolean", True)
        self.add_property("appearance", "combo", ("list", "tabs"), "tabs")
        self.add_property("enableFeedback", "boolean", True)
        self.add_property("emailAddresses", "string", "")
        self.add_property("fromEmailAddress", "string", "")
        self.add_property("maxLogLines", "integer", -1)
        self.add_property("autoSwitchTabs", "boolean", False)
        self.add_property("myTabLabel", "string", "")

        # Signals -------------------------------------------------------------
        self.define_signal("incUnreadMessagesSignal", ())
        self.define_signal("resetUnreadMessagesSignal", ())

        # Slots ---------------------------------------------------------------
        self.define_slot("clearLog", ())
        self.define_slot("tabSelected", ())

        # Graphic elements ----------------------------------------------------
        self.tab_widget = qt_import.QTabWidget(self)

        self.details_log = CustomTreeWidget(self.tab_widget,
                                            "Errors and warnings")
        self.info_log = CustomTreeWidget(self.tab_widget, "Information")
        self.debug_log = CustomTreeWidget(self.tab_widget, "Debug")
        self.feedback_log = Submitfeedback(self.tab_widget,
                                           self["emailAddresses"],
                                           "Submit feedback")

        self.tab_widget.addTab(self.details_log, icons.load_icon("Caution"),
                               "Errors and warnings")
        self.tab_widget.addTab(self.info_log, icons.load_icon("Inform"),
                               "Information")
        self.tab_widget.addTab(self.debug_log, icons.load_icon("Hammer"),
                               "Debug")
        self.tab_widget.addTab(self.feedback_log, icons.load_icon("Envelope"),
                               "Submit feedback")

        # Layout --------------------------------------------------------------
        _main_vlayout = qt_import.QVBoxLayout(self)
        _main_vlayout.addWidget(self.tab_widget)
        _main_vlayout.setSpacing(0)
        _main_vlayout.setContentsMargins(2, 2, 2, 2)

        # SizePolicies --------------------------------------------------------
        self.setSizePolicy(qt_import.QSizePolicy.Minimum,
                           qt_import.QSizePolicy.Expanding)

        # Qt signal/slot connections ------------------------------------------

        # Other ---------------------------------------------------------------
        self.tab_levels = {
            logging.NOTSET: self.info_log,
            logging.DEBUG: self.info_log,
            logging.INFO: self.info_log,
            logging.WARNING: self.info_log,
            logging.ERROR: self.info_log,
            logging.CRITICAL: self.info_log,
        }

        self.filter_level = logging.NOTSET
        # Register to GUI log handler
        gui_log_handler.GUILogHandler().register(self)

    def run(self):
        # Register to GUI log handler
        self.tab_widget.currentChanged.connect(self.resetUnreadMessages)

    def clearLog(self):
        self.details_log.clear()
        self.info_log.clear()
        self.debug_log.clear()

        self.details_log.unread_messages = 0
        self.info_log.unread_messages = 0
        self.debug_log.unread_messages = 0

    def tabSelected(self, tab_name):
        if self["appearance"] == "list":
            if tab_name == self["myTabLabel"]:
                self.resetUnreadMessagesSignal.emit(True)

    def append_log_record(self, record):
        rec_level = record.getLevel()

        if rec_level == logging.DEBUG and not self["showDebug"]:
            return
        else:
            if rec_level < self.filter_level:
                return

        tab = self.tab_levels[rec_level]
        tab.add_log_line(record)

        if self["appearance"] == "tabs":
            if self.tab_widget.currentWidget() != tab:
                if self["autoSwitchTabs"]:
                    self.tab_widget.setCurrentWidget(tab)
                else:
                    tab.unread_messages += 1
                    tab_label = "%s (%d)" % (tab.tab_label,
                                             tab.unread_messages)
                    self.tab_widget.setTabText(self.tab_widget.indexOf(tab),
                                               tab_label)
        elif self["appearance"] == "list":
            self.incUnreadMessagesSignal.emit(1, True)

    def resetUnreadMessages(self, tab_index):
        selected_tab = self.tab_widget.widget(tab_index)
        selected_tab.unread_messages = 0
        self.tab_widget.setTabText(tab_index, selected_tab.tab_label)

    def customEvent(self, event):
        if self.is_running():
            self.append_log_record(event.record)

    def blockSignals(self, block):
        pass

    def property_changed(self, property_name, old_value, new_value):
        if property_name == "level":
            self.filter_level = logging.NOTSET

            if new_value == "INFO":
                self.filter_level = logging.INFO
            elif new_value == "WARNING":
                self.filter_level = logging.WARNING
            elif new_value == "ERROR":
                self.filter_level = logging.ERROR

        elif property_name == "showDebug":
            if self["appearance"] == "tabs":
                if not new_value:
                    self.tab_widget.removeTab(
                        self.tab_widget.indexOf(self.debug_log))

        elif property_name == "emailAddresses":
            self.feedback_log.email_addresses = new_value
        elif property_name == "fromEmailAddress":
            self.feedback_log.from_email_address = new_value

        elif property_name == "enableFeedback":
            if self["appearance"] == "tabs":
                if not new_value:
                    self.tab_widget.removeTab(
                        self.tab_widget.indexOf(self.feedback_log))

        elif property_name == "appearance":
            if new_value == "list":
                self.tab_levels = {
                    logging.NOTSET: self.info_log,
                    logging.DEBUG: self.info_log,
                    logging.INFO: self.info_log,
                    logging.WARNING: self.info_log,
                    logging.ERROR: self.info_log,
                    logging.CRITICAL: self.info_log,
                }

                self.tab_widget.removeTab(
                    self.tab_widget.indexOf(self.details_log))
                self.tab_widget.removeTab(
                    self.tab_widget.indexOf(self.debug_log))

            elif new_value == "tabs":
                self.tab_levels = {
                    logging.NOTSET: self.details_log,
                    logging.DEBUG: self.debug_log,
                    logging.INFO: self.info_log,
                    logging.WARNING: self.details_log,
                    logging.ERROR: self.details_log,
                    logging.CRITICAL: self.details_log,
                }

        elif property_name == "maxLogLines":
            self.details_log.set_max_log_lines(new_value)
            self.info_log.set_max_log_lines(new_value)
            self.debug_log.set_max_log_lines(new_value)
        else:
            BaseWidget.property_changed(self, property_name, old_value,
                                        new_value)
コード例 #6
0
class ProposalBrick(BaseWidget):

    sessionSelected = qt_import.pyqtSignal(int, str, str, int, str, str, bool)
    setWindowTitle = qt_import.pyqtSignal(str)
    loggedIn = qt_import.pyqtSignal(bool)
    userGroupSaved = qt_import.pyqtSignal(str)

    NOBODY_STR = "<nobr><b>Login is required for collecting data!</b>"

    def __init__(self, *args):
        """
        Proposal brick is used to authentificate current user.
        Brick can be used in two modes defined by ispyb hwobj
         - loginAsUser = True, Brick displays combobox with all
           proposals from ISPyB that are associated to the current user
         - loginAsUser = False. Brick displays combobox to choose proposal
           type and linedits to enter proposal number and password.
           In this case user is authentificated with
           LDAP and proposal from ISPyB is retrieved.
        """
        BaseWidget.__init__(self, *args)

        # Hardware objects ----------------------------------------------------
        self.local_login_hwobj = None

        # Internal values -----------------------------------------------------
        self.login_as_user = None

        self.proposal = None
        self.person = None
        self.laboratory = None
        # self.sessionId=None
        self.inhouseProposal = None
        self.instance_server_hwobj = None
        self.secondary_proposals = []

        # Properties ----------------------------------------------------------
        self.add_property("titlePrefix", "string", "")
        self.add_property("autoSessionUsers", "string", "")
        self.add_property("codes", "string", "fx ifx ih im ix ls mx opid")
        self.add_property("secondaryProposals", "string", "")
        self.add_property("icons", "string", "")
        self.add_property("serverStartDelay", "integer", 500)

        # Signals ------------------------------------------------------------
        self.define_signal("sessionSelected", ())
        self.define_signal("setWindowTitle", ())
        self.define_signal("loggedIn", ())
        self.define_signal("userGroupSaved", ())

        # Slots ---------------------------------------------------------------
        self.define_slot("setButtonEnabled", ())
        self.define_slot("impersonateProposal", ())

        # Graphic elements ----------------------------------------------------
        self.main_gbox = qt_import.QGroupBox("ISPyB proposal", self)

        self.login_as_proposal_widget = qt_import.QWidget(self.main_gbox)
        code_label = qt_import.QLabel("  Code: ", self.login_as_proposal_widget)
        self.proposal_type_combox = qt_import.QComboBox(self.login_as_proposal_widget)
        self.proposal_type_combox.setEditable(True)
        self.proposal_type_combox.setFixedWidth(60)
        dash_label = qt_import.QLabel(" - ", self.login_as_proposal_widget)
        self.proposal_number_ledit = qt_import.QLineEdit(self.login_as_proposal_widget)
        self.proposal_number_ledit.setFixedWidth(60)
        password_label = qt_import.QLabel("   Password: "******"Login", self.login_as_proposal_widget)
        self.login_button.setFixedWidth(70)
        self.logout_button = qt_import.QPushButton("Logout", self.main_gbox)
        self.logout_button.hide()
        self.logout_button.setFixedWidth(70)
        self.login_as_proposal_widget.hide()

        self.login_as_user_widget = qt_import.QWidget(self.main_gbox)
        self.proposal_combo = qt_import.QComboBox(self.login_as_user_widget)

        self.user_group_widget = qt_import.QWidget(self.main_gbox)
        # self.title_label = QtGui.QLabel(self.user_group_widget)
        # self.title_label.setAlignment(QtCore.Qt.AlignCenter)
        self.user_group_label = qt_import.QLabel("  Group: ", self.user_group_widget)
        self.user_group_ledit = qt_import.QLineEdit(self.user_group_widget)
        self.user_group_ledit.setFixedSize(100, 27)
        self.user_group_save_button = qt_import.QToolButton(self.user_group_widget)
        self.user_group_save_button.setText("Set")
        self.user_group_save_button.setFixedHeight(27)
        self.saved_group = True

        # Layout --------------------------------------------------------------
        _user_group_widget_hlayout = qt_import.QHBoxLayout(self.user_group_widget)
        _user_group_widget_hlayout.setSpacing(2)
        # _user_group_widget_hlayout.addWidget(self.title_label)
        _user_group_widget_hlayout.addWidget(self.user_group_label)
        _user_group_widget_hlayout.addWidget(self.user_group_ledit)
        _user_group_widget_hlayout.addWidget(self.user_group_save_button)
        _user_group_widget_hlayout.setContentsMargins(0, 0, 0, 0)
        self.user_group_widget.hide()

        _login_as_proposal_widget_layout = qt_import.QHBoxLayout(
            self.login_as_proposal_widget
        )
        _login_as_proposal_widget_layout.addWidget(code_label)
        _login_as_proposal_widget_layout.addWidget(self.proposal_type_combox)
        _login_as_proposal_widget_layout.addWidget(dash_label)
        _login_as_proposal_widget_layout.addWidget(self.proposal_number_ledit)
        _login_as_proposal_widget_layout.addWidget(password_label)
        _login_as_proposal_widget_layout.addWidget(self.proposal_password_ledit)
        _login_as_proposal_widget_layout.addWidget(self.login_button)
        _login_as_proposal_widget_layout.setSpacing(2)
        _login_as_proposal_widget_layout.setContentsMargins(0, 0, 0, 0)

        _login_as_user_widget_layout = qt_import.QHBoxLayout(self.login_as_user_widget)
        _login_as_user_widget_layout.addWidget(self.proposal_combo)
        _login_as_user_widget_layout.setSpacing(2)
        _login_as_user_widget_layout.setContentsMargins(0, 0, 0, 0)

        _main_gboxlayout = qt_import.QHBoxLayout(self.main_gbox)
        _main_gboxlayout.addWidget(self.login_as_proposal_widget)
        _main_gboxlayout.addWidget(self.logout_button)
        _main_gboxlayout.addWidget(self.login_as_user_widget)
        _main_gboxlayout.addStretch()
        _main_gboxlayout.addWidget(self.user_group_widget)
        _main_gboxlayout.setSpacing(2)
        _main_gboxlayout.setContentsMargins(0, 0, 0, 0)

        _main_vlayout = qt_import.QVBoxLayout(self)
        _main_vlayout.addWidget(self.main_gbox)
        _main_vlayout.setSpacing(2)
        _main_vlayout.setContentsMargins(2, 2, 2, 2)

        # SizePolicies --------------------------------------------------------
        #  self.user_group_ledit

        # Qt signal/slot connections ------------------------------------------
        self.proposal_password_ledit.returnPressed.connect(self.login)
        self.login_button.clicked.connect(self.login)
        self.logout_button.clicked.connect(self.logout_clicked)
        self.proposal_combo.activated.connect(self.proposal_combo_activated)
        self.user_group_save_button.clicked.connect(self.save_group)
        self.user_group_ledit.returnPressed.connect(self.save_group)
        self.user_group_ledit.textChanged.connect(self.user_group_changed)

        # Other ---------------------------------------------------------------
        colors.set_widget_color(
            self.proposal_number_ledit, colors.LIGHT_RED, qt_import.QPalette.Base
        )
        colors.set_widget_color(
            self.proposal_password_ledit, colors.LIGHT_RED, qt_import.QPalette.Base
        )

    def save_group(self):
        user_group = str(self.user_group_ledit.text())

        pattern = r"^[a-zA-Z0-9_-]*$"
        valid = re.match(pattern, user_group, flags=0).group() == user_group

        if valid:
            self.saved_group = True
            colors.set_widget_color(
                self.user_group_ledit, colors.LIGHT_GREEN, qt_import.QPalette.Base
            )
            msg = "User group set to: %s" % str(self.user_group_ledit.text())
            logging.getLogger("GUI").info(msg)
            self.userGroupSaved.emit(self.user_group_ledit.text())
        else:
            msg = "User group not valid, please enter a valid user group"
            logging.getLogger("GUI").info(msg)
            colors.set_widget_color(
                self.user_group_ledit, colors.LIGHT_RED, qt_import.QPalette.Base
            )

    def user_group_changed(self, value):
        if self.saved_group:
            msg = "User group changed, press set to apply change"
            logging.getLogger("GUI").warning(msg)
            colors.set_widget_color(
                self.user_group_ledit, colors.LINE_EDIT_CHANGED, qt_import.QPalette.Base
            )
        self.saved_group = False

    def customEvent(self, event):
        if self.is_running():
            if event.type() == PROPOSAL_GUI_EVENT:
                try:
                    method = event.method
                    arguments = event.arguments
                except (Exception, diag):
                    logging.getLogger().exception(
                        "ProposalBrick2: problem in event! (%s)" % str(diag)
                    )
                except BaseException:
                    logging.getLogger().exception("ProposalBrick2: problem in event!")
                else:
                    # logging.getLogger().debug("ProposalBrick2: custom event method is %s" % method)
                    if callable(method):
                        try:
                            method(*arguments)
                        except Exception as diag:
                            logging.getLogger().exception(
                                "ProposalBrick2: uncaught exception! (%s)" % str(diag)
                            )
                        except BaseException:
                            logging.getLogger().exception(
                                "ProposalBrick2: uncaught exception!"
                            )
                        else:
                            # logging.getLogger().debug("ProposalBrick2: custom event finished")
                            pass
                    else:
                        logging.getLogger().warning(
                            "ProposalBrick2: uncallable custom event!"
                        )

    # Enabled/disabled the login/logout button
    def setButtonEnabled(self, state):
        self.login_button.setEnabled(state)
        self.logout_button.setEnabled(state)

    def impersonateProposal(self, proposal_code, proposal_number):
        if BaseWidget.is_instance_user_id_inhouse():
            self._do_login_as_proposal(
                proposal_code,
                proposal_number,
                None,
                HWR.beamline.lims.beamline_name,
                impersonate=True,
            )
        else:
            logging.getLogger().debug(
                "ProposalBrick2: cannot impersonate unless logged as the inhouse user!"
            )

    # Opens the logout dialog (modal); if the answer is OK then logout the user
    def logout_clicked(self):
        if (
            qt_import.QMessageBox.question(
                self,
                "Confirm logout",
                "Press OK to logout.",
                qt_import.QMessageBox.Ok,
                qt_import.QMessageBox.Cancel,
            )
            == qt_import.QMessageBox.Ok
        ):
            self.log_out()

    # Logout the user; reset the brick; changes from logout mode to login mode
    def log_out(self):
        # Reset brick info
        self.proposal_number_ledit.setText("")
        self.proposal = None
        # self.sessionId=None
        self.person = None
        self.laboratory = None
        # Change mode from logout to login
        if not self.login_as_user:
            self.login_as_proposal_widget.setEnabled(True)
            self.login_button.show()
            self.logout_button.hide()
        # self.title_label.hide()
        self.user_group_widget.hide()

        # resets active proposal
        self.reset_proposal()

        # self.proposalLabel.setText(ProposalBrick2.NOBODY_STR)
        # QToolTip.add(self.proposalLabel,"")

        # Emit signals clearing the proposal and session
        self.setWindowTitle.emit(self["titlePrefix"])
        # self.sessionSelected.emit(None, None, None, None, None, None, None)
        self.loggedIn.emit(False)

    def reset_proposal(self):
        HWR.beamline.session.proposal_code = None
        HWR.beamline.session.session_id = None
        HWR.beamline.session.proposal_id = None
        HWR.beamline.session.proposal_number = None

    # Sets the current session; changes from login mode to logout mode
    def set_proposal(self, proposal, session):
        HWR.beamline.lims.enable()
        HWR.beamline.session.proposal_code = proposal["code"]
        HWR.beamline.session.session_id = session["sessionId"]
        HWR.beamline.session.proposal_id = proposal["proposalId"]
        HWR.beamline.session.proposal_number = proposal["number"]

        # Change mode
        if not self.login_as_user:
            self.login_button.hide()
            self.login_as_proposal_widget.setDisabled(True)
            self.logout_button.show()

        # Store info in the brick
        self.proposal = proposal

        code = proposal["code"].lower()

        if code == "":
            logging.getLogger().warning(
                "Using local login: the data collected won't be stored in the database"
            )
            HWR.beamline.lims.disable()
            self.loggedIn.emit(False)
        else:
            msg = "Results in ISPyB will be stored under proposal %s%s - '%s'" % (
                proposal["code"],
                str(proposal["number"]),
                proposal["title"],
            )
            logging.getLogger("GUI").debug(msg)
            self.loggedIn.emit(True)

    def set_codes(self, codes):
        codes_list = codes.split()
        self.proposal_type_combox.clear()
        for cd in codes_list:
            self.proposal_type_combox.addItem(cd)

    def run(self):
        self.setEnabled(HWR.beamline.session is not None)

        self.login_as_user = HWR.beamline.lims.get_login_type() == "user"
        if self.login_as_user:
            self.login_as_user_widget.show()
            self.login_as_proposal_widget.hide()
        else:
            self.login_as_user_widget.hide()
            self.login_as_proposal_widget.show()

        # find if we are using dbconnection, etc. or not
        if not HWR.beamline.lims:
            self.login_as_proposal_widget.hide()
            self.login_button.hide()
            # self.title_label.setText("<nobr><b>%s</b></nobr>" % os.environ["USER"])
            # self.title_label.show()
            self.user_group_widget.show()
            HWR.beamline.session.proposal_code = ""
            HWR.beamline.session.session_id = 1
            HWR.beamline.session.proposal_id = ""
            HWR.beamline.session.proposal_number = ""

            self.setWindowTitle.emit(self["titlePrefix"])
            # self.loggedIn.emit(False)
            # self.sessionSelected.emit(None, None, None, None, None, None, None)
            self.loggedIn.emit(True)
            self.sessionSelected.emit(
                HWR.beamline.session.session_id,
                str(os.environ["USER"]),
                0,
                "",
                "",
                HWR.beamline.session.session_id,
                False,
            )
        else:
            self.setWindowTitle.emit(self["titlePrefix"])
            # self.sessionSelected.emit(None, None, None, None, None, None, None)
            self.loggedIn.emit(False)

            if self.login_as_user:
                if os.getenv("SUDO_USER"):
                    user_name = os.getenv("SUDO_USER")
                else:
                    user_name = os.getenv("USER")
                self._do_login_as_user(user_name)

        start_server_event = ProposalGUIEvent(self.start_servers, ())
        qt_import.QApplication.postEvent(self, start_server_event)

    def start_servers(self):
        if self.instance_server_hwobj is not None:
            self.instance_server_hwobj.initialize_instance()

    def refuse_login(self, stat, message=None):
        if message is not None:
            if stat is False:
                icon = qt_import.QMessageBox.Critical
            elif stat is None:
                icon = qt_import.QMessageBox.Warning
            elif stat is True:
                icon = qt_import.QMessageBox.Information
            msg_dialog = qt_import.QMessageBox(
                "Register user",
                message,
                icon,
                qt_import.QMessageBox.Ok,
                qt_import.QMessageBox.NoButton,
                qt_import.QMessageBox.NoButton,
                self,
            )
            s = self.font().pointSize()
            f = msg_dialog.font()
            f.setPointSize(s)
            msg_dialog.setFont(f)
            msg_dialog.updateGeometry()
            msg_dialog.show()

        self.setEnabled(True)

    def accept_login(self, proposal_dict, session_dict):
        self.set_proposal(proposal_dict, session_dict)
        self.setEnabled(True)

    def set_ispyb_down(self):
        msg_dialog = qt_import.QMessageBox(
            "Register user",
            "Couldn't contact "
            + "the ISPyB database server: you've been logged as the local user.\n"
            + "Your experiments' information will not be stored in ISPyB!",
            qt_import.QMessageBox.Warning,
            qt_import.QMessageBox.Ok,
            qt_import.QMessageBox.NoButton,
            qt_import.QMessageBox.NoButton,
            self,
        )
        s = self.font().pointSize()
        f = msg_dialog.font()
        f.setPointSize(s)
        msg_dialog.setFont(f)
        msg_dialog.updateGeometry()
        msg_dialog.show()

        now = time.strftime("%Y-%m-%d %H:%M:S")
        prop_dict = {"code": "", "number": "", "title": "", "proposalId": ""}
        ses_dict = {"sessionId": "", "startDate": now, "endDate": now, "comments": ""}
        self.accept_login(prop_dict, ses_dict)

    # Handler for the Login button (check the password in LDAP)
    def login(self):
        self.saved_group = False
        colors.set_widget_color(self.user_group_ledit, colors.WHITE)
        self.user_group_ledit.setText("")
        self.setEnabled(False)

        if not self.login_as_user:
            prop_type = str(self.proposal_type_combox.currentText())
            prop_number = str(self.proposal_number_ledit.text())
            prop_password = str(self.proposal_password_ledit.text())
            self.proposal_password_ledit.setText("")

            if prop_type == "" and prop_number == "":
                if self.local_login_hwobj is None:
                    return self.refuse_login(False, "Local login not configured.")
                try:
                    locallogin_password = self.local_login_hwobj.password
                except AttributeError:
                    return self.refuse_login(False, "Local login not configured.")

                if prop_password != locallogin_password:
                    return self.refuse_login(None, "Invalid local login password.")

                now = time.strftime("%Y-%m-%d %H:%M:S")
                prop_dict = {"code": "", "number": "", "title": "", "proposalId": ""}
                ses_dict = {
                    "sessionId": "",
                    "startDate": now,
                    "endDate": now,
                    "comments": "",
                }
                return self.accept_login(prop_dict, ses_dict)

            if HWR.beamline.lims is None:
                return self.refuse_login(
                    False,
                    "Not connected to the ISPyB database, unable to get proposal.",
                )

            self._do_login_as_proposal(
                prop_type,
                prop_number,
                prop_password,
                HWR.beamline.lims.beamline_name
            )

    def pass_control(self, has_control_id):
        pass

    def have_control(self, have_control):
        pass

    def property_changed(self, property_name, old_value, new_value):
        if property_name == "codes":
            self.set_codes(new_value)
        elif property_name == "localLogin":
            self.local_login_hwobj = self.get_hardware_object(new_value, optional=True)
        elif property_name == "instanceServer":
            if self.instance_server_hwobj is not None:
                self.disconnect(
                    self.instance_server_hwobj, "passControl", self.pass_control
                )
                self.disconnect(
                    self.instance_server_hwobj, "haveControl", self.have_control
                )
            self.instance_server_hwobj = self.get_hardware_object(
                new_value, optional=True
            )
            if self.instance_server_hwobj is not None:
                self.connect(
                    self.instance_server_hwobj, "passControl", self.pass_control
                )
                self.connect(
                    self.instance_server_hwobj, "haveControl", self.have_control
                )
        elif property_name == "icons":
            icons_list = new_value.split()
            try:
                self.login_button.setIcon(icons.load_icon(icons_list[0]))
            except IndexError:
                pass
            try:
                self.logout_button.setIcon(icons.load_icon(icons_list[1]))
            except IndexError:
                pass
        elif property_name == "secondaryProposals":
            self.secondary_proposals = new_value.split()
        else:
            BaseWidget.property_changed(self, property_name, old_value, new_value)

    def _do_login_as_proposal(
        self,
        proposal_code,
        proposal_number,
        proposal_password,
        beamline_name,
        impersonate=False,
    ):
        # Get proposal and sessions
        logging.getLogger().debug("ProposalBrick: querying ISPyB database...")
        prop = HWR.beamline.lims.getProposal(proposal_code, proposal_number)

        # Check if everything went ok
        prop_ok = True
        try:
            prop_ok = prop["status"]["code"] == "ok"
        except KeyError:
            prop_ok = False
        if not prop_ok:
            self.set_ispyb_down()
            BaseWidget.set_status_info("ispyb", "error")
        else:
            self.select_proposal(prop)
            BaseWidget.set_status_info(
                "user", "%s%s@%s" % (proposal_code, str(proposal_number), beamline_name)
            )
            BaseWidget.set_status_info("ispyb", "ready")

    def proposal_combo_activated(self, item_index):
        self.select_proposal(self.proposals[item_index])

    def select_proposal(self, selected_proposal):
        beamline_name = HWR.beamline.lims.beamline_name
        proposal = selected_proposal["Proposal"]
        # person = selected_proposal['Person']
        # laboratory = selected_proposal['Laboratory']
        sessions = selected_proposal["Session"]
        # Check if there are sessions in the proposal
        todays_session = None
        if sessions is None or len(sessions) == 0:
            pass
        else:
            # Check for today's session
            for session in sessions:
                beamline = session["beamlineName"]
                start_date = "%s 00:00:00" % session["startDate"].split()[0]
                end_date = "%s 23:59:59" % session["endDate"].split()[0]
                try:
                    start_struct = time.strptime(start_date, "%Y-%m-%d %H:%M:%S")
                except ValueError:
                    pass
                else:
                    try:
                        end_struct = time.strptime(end_date, "%Y-%m-%d %H:%M:%S")
                    except ValueError:
                        pass
                    else:
                        start_time = time.mktime(start_struct)
                        end_time = time.mktime(end_struct)
                        current_time = time.time()

                        # Check beamline name
                        if beamline == beamline_name:
                            # Check date
                            if current_time >= start_time and current_time <= end_time:
                                todays_session = session
                                break

        if todays_session is None:
            is_inhouse = HWR.beamline.session.is_inhouse(
                proposal["code"], proposal["number"]
            )
            if not is_inhouse:
                if BaseWidget.is_instance_role_client():
                    self.refuse_login(
                        None, "You don't have a session scheduled for today!"
                    )
                    return

            current_time = time.localtime()
            start_time = time.strftime("%Y-%m-%d 00:00:00", current_time)
            end_time = time.mktime(current_time) + 60 * 60 * 24
            tomorrow = time.localtime(end_time)
            end_time = time.strftime("%Y-%m-%d 07:59:59", tomorrow)

            # Create a session
            new_session_dict = {}
            new_session_dict["proposalId"] = selected_proposal["Proposal"]["proposalId"]
            new_session_dict["startDate"] = start_time
            new_session_dict["endDate"] = end_time
            new_session_dict["beamlineName"] = beamline_name
            new_session_dict["scheduled"] = 0
            new_session_dict["nbShifts"] = 3
            new_session_dict["comments"] = "Session created by MXCuBE"
            session_id = HWR.beamline.lims.create_session(new_session_dict)
            new_session_dict["sessionId"] = session_id

            todays_session = new_session_dict
            localcontact = None
        else:
            session_id = todays_session["sessionId"]
            logging.getLogger().debug(
                "ProposalBrick: getting local contact for %s" % session_id
            )
            localcontact = HWR.beamline.lims.get_session_local_contact(session_id)

        self.accept_login(selected_proposal["Proposal"], todays_session)

    def _do_login_as_user(self, user_name):
        logging.getLogger().debug("ProposalBrick: querying ISPyB database...")

        self.proposals = HWR.beamline.lims.get_proposals_by_user(user_name)

        if len(self.proposals) == 0:
            logging.getLogger("GUI").error(
                "No proposals for user %s found in ISPyB" % user_name
            )
            self.set_ispyb_down()
            BaseWidget.set_status_info("ispyb", "error")
        else:
            self.proposal_combo.clear()
            proposal_tooltip = "Available proposals:"
            for proposal in self.proposals:
                proposal_info = "%s%s - %s" % (
                    proposal["Proposal"]["code"],
                    proposal["Proposal"]["number"],
                    proposal["Proposal"]["title"],
                )
                self.proposal_combo.addItem(proposal_info)
                proposal_tooltip += "\n   %s" % proposal_info

            if len(self.proposals) > 1:
                proposal_index = self.select_todays_proposal(self.proposals)
                self.proposal_combo.setEnabled(True)
            else:
                proposal_tooltip = ""
                proposal_index = 0
                self.proposal_combo.setEnabled(False)

            self.select_proposal(self.proposals[proposal_index])
            self.proposal_combo.setCurrentIndex(proposal_index)
            proposal_info = "%s%s - %s" % (
                self.proposals[proposal_index]["Proposal"]["code"],
                self.proposals[proposal_index]["Proposal"]["number"],
                self.proposals[proposal_index]["Proposal"]["title"],
            )
            proposal_tooltip += "\nSelected proposal:\n   %s" % proposal_info
            self.proposal_combo.setToolTip(proposal_tooltip)
            logging.getLogger("GUI").info("ISPyB proposal: %s" % proposal_info)

            BaseWidget.set_status_info(
                "user", "%s@%s" % (user_name, HWR.beamline.lims.beamline_name)
            )
            BaseWidget.set_status_info("ispyb", "ready")

    def select_todays_proposal(self, proposal_list):
        """Selects a proposal that is assigned for current day
           If no session found then returns first proposal
        """
        for prop_index, proposal in enumerate(proposal_list):
            sessions = proposal["Session"]
            proposal_code_number = (
                proposal["Proposal"]["code"] + proposal["Proposal"]["number"]
            )
            if (
                len(sessions) > 0
                and not proposal_code_number in self.secondary_proposals
            ):
                # Check for today's session
                for session in sessions:
                    beamline = session["beamlineName"]
                    start_date = "%s 00:00:00" % session["startDate"].split()[0]
                    end_date = "%s 23:59:59" % session["endDate"].split()[0]
                    try:
                        start_struct = time.strptime(start_date, "%Y-%m-%d %H:%M:%S")
                    except ValueError:
                        pass
                    else:
                        try:
                            end_struct = time.strptime(end_date, "%Y-%m-%d %H:%M:%S")
                        except ValueError:
                            pass
                        else:
                            start_time = time.mktime(start_struct)
                            end_time = time.mktime(end_struct)
                            current_time = time.time()
                            # Check beamline name
                            if beamline == HWR.beamline.lims.beamline_name:
                                # Check date
                                if (
                                    current_time >= start_time
                                    and current_time <= end_time
                                ):
                                    return prop_index

        # If no proposal with valid session found then the last
        # proposal from the list is selected
        return len(proposal_list) - 1
コード例 #7
0
class StepEditor(qt_import.QFrame):
    """ Brick to handle the step a motor position changes.

    Combines the +/- Step button and the widget to change the step value.

    Long description for Step Editor.
    """

    (LEFT_LAYOUT, RIGHT_LAYOUT) = (0, 1)
    value_changed_signal = qt_import.pyqtSignal('double')
    clicked_signal = qt_import.pyqtSignal('double')

    def __init__(self,
                 layout,
                 initial_value,
                 parent=None,
                 title="",
                 prefix=""):
        """"
        Constructor of StepEditor

        :param layout: select step value edit widget position
        :param initial_value: set motor initial position
        :param parent: parent widget
        :param title: step value edit widget's title
        :param prefix: + / - symbol fordward/backward step buttons
        """
        super(StepEditor, self).__init__(parent)

        self.prefix = prefix
        self.value = initial_value

        # Graphic elements-----------------------------------------------------

        self.title_label = qt_import.QLabel(title)
        self.selection_box = qt_import.QFrame()
        self.edition_box = qt_import.QFrame()

        self.txt_new_value = qt_import.QLineEdit()
        self.cmd_ok = qt_import.QPushButton()
        self.cmd_ok.setIcon(icons.load_icon("button_ok_small"))
        self.cmd_ok.setFixedWidth(20)

        self.cmd_cancel = qt_import.QPushButton()
        self.cmd_cancel.setIcon(icons.load_icon("button_cancel_small"))
        self.cmd_cancel.setFixedWidth(20)

        self.edition_box.hide()
        self.title_label.hide()
        self.edition_box.setSizePolicy(qt_import.QSizePolicy.Fixed,
                                       qt_import.QSizePolicy.Fixed)

        self.double_validator = qt_import.QDoubleValidator(self.txt_new_value)
        self.double_validator.setNotation(
            qt_import.QDoubleValidator.StandardNotation)
        self.txt_new_value.setValidator(self.double_validator)

        # Layout --------------------------------------------------------------

        self.main_vertical_layout = qt_import.QVBoxLayout()
        self.selection_box_layout = qt_import.QHBoxLayout()
        self.edition_box_layout = qt_import.QHBoxLayout()

        # widget's addition order defines their position

        self.edition_box_layout.addWidget(self.txt_new_value)
        self.edition_box_layout.addWidget(self.cmd_ok)
        self.edition_box_layout.addWidget(self.cmd_cancel)
        self.edition_box.setLayout(self.edition_box_layout)

        self.selection_box_layout.addWidget(self.edition_box)

        if layout == StepEditor.RIGHT_LAYOUT:
            self.cmd_select_value = qt_import.QPushButton(prefix +
                                                          str(initial_value))
            self.cmd_edit_value = qt_import.QPushButton("...")
            self.selection_box_layout.addWidget(self.cmd_select_value)
            self.selection_box_layout.addWidget(self.cmd_edit_value)

        else:
            self.cmd_edit_value = qt_import.QPushButton("...")
            self.cmd_select_value = qt_import.QPushButton(prefix +
                                                          str(initial_value))
            self.selection_box_layout.addWidget(self.cmd_edit_value)
            self.selection_box_layout.addWidget(self.cmd_select_value)

        self.selection_box.setLayout(self.selection_box_layout)

        self.main_vertical_layout.addWidget(self.title_label)
        self.main_vertical_layout.addWidget(self.selection_box)

        self.setLayout(self.main_vertical_layout)

        self.cmd_select_value.setAutoDefault(False)

        # Qt signal/slot connections -----------------------------------------
        self.cmd_select_value.clicked.connect(self.cmd_select_value_clicked)
        self.cmd_edit_value.clicked.connect(self.cmd_edit_values_clicked)
        self.txt_new_value.returnPressed.connect(self.validate_new_value)
        self.cmd_ok.clicked.connect(self.validate_new_value)
        self.cmd_cancel.clicked.connect(self.end_edit)

    def set_title(self, title):
        """Set step value edit widget's title."""
        self.title_label.setText(title)

    def set_prefix(self, prefix):
        """Set prefix to step forward/backward buttons."""
        self.prefix = prefix
        self.cmd_select_value.setText(self.prefix + str(self.value))

    def set_value(self, value):
        """Set value step forward/backward buttons."""
        self.value = value
        self.cmd_select_value.setText(self.prefix + str(value))

    def allow_change_value(self, allow):
        """Show/hide step value edit widget."""
        if allow:
            self.cmd_edit_value.show()
        else:
            self.cmd_edit_value.hide()

    def cmd_select_value_clicked(self):
        """Emit step value edited signal."""
        self.clicked_signal.emit(self.value)

    def cmd_edit_values_clicked(self):
        """Open step value edit widget."""
        self.cmd_edit_value.hide()
        self.cmd_select_value.hide()
        self.edition_box.show()
        self.title_label.show()
        self.txt_new_value.setText(str(self.value))
        self.txt_new_value.selectAll()
        self.txt_new_value.setFocus()

    def end_edit(self):
        """Close step value edit widget."""
        self.cmd_edit_value.show()
        self.cmd_select_value.show()
        self.title_label.hide()
        self.edition_box.hide()
        self.value_changed_signal.emit(self.value)

    def validate_new_value(self):
        """Validate entered new value."""
        try:
            self.value = float(str(self.txt_new_value.text()))
        except BaseException:
            logging.getLogger().error("%s is not a valid float value",
                                      self.txtNewValue.text())
        else:
            self.cmd_select_value.setText(self.prefix + str(self.value))
            self.end_edit()
コード例 #8
0
class PlotWidget(qt_import.QWidget):

    mouseMovedSignal = qt_import.pyqtSignal(float, float)
    mouseClickedSignal = qt_import.pyqtSignal(float, float)
    mouseDoubleClickedSignal = qt_import.pyqtSignal(float, float)
    mouseLeftSignal = qt_import.pyqtSignal()

    def __init__(self, parent=None):

        qt_import.QWidget.__init__(self, parent)

        self.im = None
        self.mpl_canvas = MplCanvas(self)
        self.colorbar = None
        # self.ntb = NavigationToolbar(self.mpl_canvas, self)
        self.selection_xrange = None
        self.selection_span = None
        self.mouse_clicked = None

        _main_vlayout = qt_import.QVBoxLayout(self)
        _main_vlayout.addWidget(self.mpl_canvas)
        # _main_vlayout.addWidget(self.ntb)
        _main_vlayout.setSpacing(2)
        _main_vlayout.setContentsMargins(0, 0, 0, 0)

        self.setSizePolicy(qt_import.QSizePolicy.Expanding,
                           qt_import.QSizePolicy.Expanding)

        # self.mpl_canvas.axes.grid(True)
        self.mpl_canvas.axes.grid(color="r")
        self.mpl_canvas.fig.canvas.mpl_connect("button_press_event",
                                               self.button_pressed)
        self.mpl_canvas.fig.canvas.mpl_connect("button_release_event",
                                               self.mouse_released)
        self.mpl_canvas.fig.canvas.mpl_connect("motion_notify_event",
                                               self.motion_notify_event)
        # self.setFixedSize(1000, 700)

    def button_pressed(self, mouse_event):
        dbl_click = False
        if hasattr(mouse_event, "dblclick"):
            dbl_click = mouse_event.dblclick
        #if mouse_event.xdata and mouse_event.ydata:
        if True:
            if dbl_click:
                self.mouseDoubleClickedSignal.emit(mouse_event.xdata,
                                                   mouse_event.ydata)
            else:
                self.mouse_clicked = True
                self.mouseClickedSignal.emit(mouse_event.xdata,
                                             mouse_event.ydata)

    def mouse_released(self, mouse_event):
        self.mouse_clicked = False

    def motion_notify_event(self, mouse_event):
        if mouse_event.xdata and mouse_event.ydata:
            self.mouseMovedSignal.emit(mouse_event.xdata, mouse_event.ydata)
        else:
            self.mouseLeftSignal.emit()

        if self.selection_xrange and mouse_event.xdata:
            do_update = False
            (x_start, x_end) = self.mpl_canvas.axes.get_xlim()
            delta = abs((x_end - x_start) / 50.0)
            if abs(self.selection_xrange[0] - mouse_event.xdata) < delta:
                qt_import.QApplication.setOverrideCursor(
                    qt_import.QCursor(qt_import.Qt.SizeHorCursor))
                if self.mouse_clicked:
                    self.selection_xrange[0] = mouse_event.xdata
                    do_update = True
            elif abs(self.selection_xrange[1] - mouse_event.xdata) < delta:
                qt_import.QApplication.setOverrideCursor(
                    qt_import.QCursor(qt_import.Qt.SizeHorCursor))
                if self.mouse_clicked:
                    self.selection_xrange[1] = mouse_event.xdata
                    do_update = True

            if do_update:
                self.selection_span.set_xy([
                    [self.selection_xrange[0], 0],
                    [self.selection_xrange[0], 1],
                    [self.selection_xrange[1], 1],
                    [self.selection_xrange[1], 0],
                    [self.selection_xrange[0], 0],
                ])
                self.mpl_canvas.fig.canvas.draw()
                self.mpl_canvas.fig.canvas.flush_events()

    def plot_result(self, result, aspect=None):
        if not aspect:
            aspect = "auto"

        if self.im is None:
            self.im = self.mpl_canvas.axes.imshow(
                result,
                interpolation="none",
                aspect="auto",
                extent=[0, result.shape[1], 0, result.shape[0]],
            )
            self.im.set_cmap("hot")
        else:
            self.im.set_data(result)

        self.im.autoscale()
        self.mpl_canvas.fig.canvas.draw()
        self.mpl_canvas.fig.canvas.flush_events()

        if result.max() > 0 and self.colorbar is None:
            self.add_colorbar()

    def get_current_coord(self):
        return self.mpl_canvas.get_mouse_coord()

    def set_x_axis_limits(self, limits):
        self.mpl_canvas.axes.set_xlim(limits)

    def set_y_axis_limits(self, limits):
        self.mpl_canvas.axes.set_ylim(limits)

    def set_ytick_labels(self, labels):
        self.mpl_canvas.axes.set_yticklabels(labels)
        self.mpl_canvas.fig.canvas.draw()
        self.mpl_canvas.fig.canvas.flush_events()

    def set_yticks(self, ticks):
        self.mpl_canvas.axes.set_yticks(ticks)
        self.mpl_canvas.fig.canvas.draw()
        self.mpl_canvas.fig.canvas.flush_events()

    def add_colorbar(self):
        if self.colorbar:
            self.colorbar.remove()
        divider = make_axes_locatable(self.mpl_canvas.axes)
        cax = divider.append_axes("right", size=0.3, pad=0.05)
        cax.tick_params(axis="x", labelsize=8)
        cax.tick_params(axis="y", labelsize=8)
        self.colorbar = plt.colorbar(self.im, cax=cax)

    def clear(self):
        self.im = None
        self.selection_xrange = None
        self.selection_span = None
        self.mpl_canvas.clear()
        if self.colorbar:
            self.colorbar.remove()
            self.colorbar = None

    def hide_all_curves(self):
        self.mpl_canvas.hide_curves()

    def show_curve(self, name):
        self.mpl_canvas.show_curve(name)
        self.mpl_canvas.refresh()

    def adjust_axes(self, name):
        self.mpl_canvas.adjust_axes(name)
        self.mpl_canvas.refresh()

    def add_curve(
        self,
        name,
        y_axis_array,
        x_axis_array=None,
        label=None,
        linestyle="-",
        color="blue",
        marker=None,
        ytick_labels=None,
    ):
        self.mpl_canvas.plot_curve(
            name,
            y_axis_array,
            x_axis_array=None,
            label=None,
            linestyle=linestyle,
            color=color,
            marker=marker,
        )
        if x_axis_array:
            self.set_x_axis_limits((x_axis_array.min(), x_axis_array.max()))
        if ytick_labels:
            self.set_ytick_labels(ytick_labels)

    def update_curves(self, data):
        self.mpl_canvas.update_curves(data)

    def enable_selection_range(self):
        (x_start, x_end) = self.mpl_canvas.axes.get_xlim()
        offset = abs((x_end - x_start) / 10.0)
        self.selection_xrange = [x_start + offset, x_end - offset]

        self.selection_span = self.mpl_canvas.axes.axvspan(
            self.selection_xrange[0],
            self.selection_xrange[1],
            facecolor="g",
            alpha=0.3)
        self.mpl_canvas.refresh()

    def enable_legend(self):
        self.mpl_canvas.axes.legend()
        self.mpl_canvas.refresh()
コード例 #9
0
class PeriodicTableWidget(qt_import.QWidget):

    elementEdgeSelectedSignal = qt_import.pyqtSignal(str, str)

    def __init__(self, parent=None, name=None, fl=0):

        qt_import.QWidget.__init__(self, parent, qt_import.Qt.WindowFlags(fl))
        if name is not None:
            self.setObjectName(name)
        self.selected_element = None
        self.selected_edge = "L3"

        # Signals ------------------------------------------------------------

        # Slots ---------------------------------------------------------------

        # Graphic elements ----------------------------------------------------
        if PYMCA_IMPORTED:
            self.periodic_table = CustomPeriodicTable(self)
        else:
            self.periodic_elements_combo = qt_import.QComboBox(self)
            self.periodic_elements_combo.setFixedWidth(100)

        self.edge_widget = qt_import.QWidget(self)
        edge_label = qt_import.QLabel("Edge:", self.edge_widget)
        self.edge_combo = qt_import.QComboBox(self.edge_widget)

        # Layout --------------------------------------------------------------
        _edge_hlayout = qt_import.QHBoxLayout(self.edge_widget)
        if not PYMCA_IMPORTED:
            _edge_hlayout.addWidget(self.periodic_elements_combo)
        _edge_hlayout.addWidget(edge_label)
        _edge_hlayout.addWidget(self.edge_combo)
        _edge_hlayout.addStretch(0)
        _edge_hlayout.setSpacing(2)
        _edge_hlayout.setContentsMargins(0, 0, 0, 0)

        _main_vlayout = qt_import.QVBoxLayout(self)
        if PYMCA_IMPORTED:
            _main_vlayout.addWidget(self.periodic_table, qt_import.Qt.AlignHCenter)
        _main_vlayout.addWidget(self.edge_widget)
        _main_vlayout.addStretch(0)
        _main_vlayout.setSpacing(2)
        _main_vlayout.setContentsMargins(2, 2, 2, 2)

        # SizePolicies --------------------------------------------------------

        # Qt signal/slot connections ------------------------------------------
        if PYMCA_IMPORTED:
            self.periodic_table.edgeSelectedSignal.connect(self.edge_selected)
        else:
            self.periodic_elements_combo.activated.connect(self.element_combo_activated)
        self.edge_combo.addItem("K")
        self.edge_combo.activated.connect(self.edge_combo_activated)
        self.edge_combo.setEnabled(False)

        # Other ---------------------------------------------------------------

    def element_combo_activated(self, element):
        self.selected_element = str(self.periodic_elements_combo.currentText())
        self.selected_edge = str(self.edge_combo.currentText())
        self.elementEdgeSelectedSignal.emit(self.selected_element, self.selected_edge)

    def edge_selected(self, element, edge):
        self.selected_element = str(element)
        self.selected_edge = str(edge)
        self.edge_widget.setEnabled(self.selected_edge != "K")

        self.edge_combo.clear()
        if edge == "K":
            edge_list = "K"
        else:
            edge_list = ("L1", "L2", "L3")
        for item in edge_list:
            self.edge_combo.addItem(item)
        self.edge_combo.setCurrentIndex(edge_list.index(item))
        self.edge_combo.setEnabled(self.edge_combo.count() > 1)
        self.elementEdgeSelectedSignal.emit(self.selected_element, self.selected_edge)

    def set_current_element_edge(self, element, edge):
        if PYMCA_IMPORTED:
            self.periodic_table.table_element_clicked(element, edge)

    def get_selected_element_edge(self):
        return self.selected_element, self.selected_edge

    def edge_combo_activated(self, item_index):
        self.selected_edge = str(self.edge_combo.currentText())
        self.elementEdgeSelectedSignal.emit(self.selected_element, self.selected_edge)

    def set_elements(self, elements):
        if PYMCA_IMPORTED:
            self.periodic_table.setElements(elements)
        else:
            for element in elements:
                self.periodic_elements_combo.addItem(element["symbol"])
コード例 #10
0
ファイル: gphl_data_dialog.py プロジェクト: rhfogh/mxcube
class GphlDataDialog(qt_import.QDialog):

    continueClickedSignal = qt_import.pyqtSignal()

    def __init__(self, parent=None, name=None, fl=0):
        qt_import.QDialog.__init__(self, parent, qt_import.Qt.WindowFlags(fl))

        if name is not None:
            self.setObjectName(name)

        # Internal variables --------------------------------------------------
        # AsyncResult to return values
        self._async_result = None

        # Layout
        qt_import.QVBoxLayout(self)
        main_layout = self.layout()
        main_layout.setSpacing(10)
        main_layout.setMargin(6)
        self.setSizePolicy(qt_import.QSizePolicy.Expanding,
                           qt_import.QSizePolicy.Expanding)

        self.setWindowTitle("GPhL Workflow parameters")

        # Info box
        self.info_gbox = qt_import.QGroupBox("Info", self)
        qt_import.QVBoxLayout(self.info_gbox)
        main_layout.addWidget(self.info_gbox)
        self.info_text = qt_import.QTextEdit(self.info_gbox)
        self.info_text.setFont(qt_import.QFont("Courier"))
        self.info_text.setReadOnly(True)
        self.info_gbox.layout().addWidget(self.info_text)

        # Special parameter box
        self.cplx_gbox = qt_import.QGroupBox("Indexing solution", self)
        qt_import.QVBoxLayout(self.cplx_gbox)
        main_layout.addWidget(self.cplx_gbox)
        self.cplx_gbox.setSizePolicy(qt_import.QSizePolicy.Expanding,
                                     qt_import.QSizePolicy.Expanding)
        self.cplx_widget = None

        # Parameter box
        self.parameter_gbox = qt_import.QGroupBox("Parameters", self)
        main_layout.addWidget(self.parameter_gbox)
        self.parameter_gbox.setSizePolicy(qt_import.QSizePolicy.Expanding,
                                          qt_import.QSizePolicy.Expanding)
        self.params_widget = None

        # Button bar
        button_layout = qt_import.QHBoxLayout(None)
        hspacer = qt_import.QSpacerItem(1, 20, qt_import.QSizePolicy.Expanding,
                                        qt_import.QSizePolicy.Minimum)
        button_layout.addItem(hspacer)
        self.continue_button = qt_import.QPushButton("Continue", self)
        button_layout.addWidget(self.continue_button)
        self.cancel_button = qt_import.QPushButton("Abort", self)
        button_layout.addWidget(self.cancel_button)
        main_layout.addLayout(button_layout)

        self.continue_button.clicked.connect(self.continue_button_click)
        self.cancel_button.clicked.connect(self.cancel_button_click)

        self.resize(
            qt_import.QSize(1018, 472).expandedTo(self.minimumSizeHint()))
        # self.clearWState(qt_import.WState_Polished)

    def continue_button_click(self):
        result = {}
        if self.parameter_gbox.isVisible():
            result.update(self.params_widget.get_parameters_map())
        if self.cplx_gbox.isVisible():
            result["_cplx"] = self.cplx_widget.get_value()
        self.accept()
        self._async_result.set(result)
        self._async_result = None

    def cancel_button_click(self):
        self.reject()
        HWR.beamline.gphl_workflow.abort("Manual abort")

    def open_dialog(self, field_list, async_result):

        self._async_result = async_result

        # get special parameters
        parameters = []
        info = None
        cplx = None
        for dd0 in field_list:
            if info is None and dd0.get("variableName") == "_info":
                # Info text - goes to info_gbox
                info = dd0
            elif cplx is None and dd0.get("variableName") == "_cplx":
                # Complex parameter - goes to cplx_gbox
                cplx = dd0
            else:
                parameters.append(dd0)

        # Info box
        if info is None:
            self.info_text.setText("")
            self.info_gbox.setTitle("Info")
            self.info_gbox.hide()
        else:
            self.info_text.setText(info.get("defaultValue"))
            self.info_gbox.setTitle(info.get("uiLabel"))
            self.info_gbox.show()

        # Complex box
        if self.cplx_widget:
            self.cplx_widget.close()
        if cplx is None:
            self.cplx_gbox.hide()
        else:
            if cplx.get("type") == "selection_table":
                self.cplx_widget = SelectionTable(self.cplx_gbox,
                                                  "cplx_widget",
                                                  cplx["header"])
                self.cplx_gbox.layout().addWidget(self.cplx_widget)
                self.cplx_gbox.setTitle(cplx.get("uiLabel"))
                for ii, values in enumerate(cplx["defaultValue"]):
                    self.cplx_widget.populateColumn(
                        ii, values, colours=cplx.get("colours"))
                self.cplx_gbox.show()

            else:
                raise NotImplementedError(
                    "GPhL complex widget type %s not recognised for parameter _cplx"
                    % repr(cplx.get("type")))

        # parameters widget
        if self.params_widget is not None:
            self.params_widget.close()
            self.params_widget = None
        if parameters:
            self.params_widget = FieldsWidget(fields=parameters,
                                              parent=self.parameter_gbox)

            values = {}
            for dd0 in field_list:
                name = dd0["variableName"]
                value = dd0.get("defaultValue")
                if value is not None:
                    dd0[name] = value
            self.params_widget.set_values(values)
            self.parameter_gbox.show()
        else:
            self.parameter_gbox.hide()

        self.show()
        self.setEnabled(True)
コード例 #11
0
class _Bar(qt_import.QWidget):

    clickedValue = qt_import.pyqtSignal(int)

    def __init__(self, steps, *args, **kwargs):
        super(_Bar, self).__init__(*args, **kwargs)

        self.setSizePolicy(qt_import.QSizePolicy.MinimumExpanding,
                           qt_import.QSizePolicy.MinimumExpanding)

        if isinstance(steps, list):
            # list of colours.
            self.n_steps = len(steps)
            self.steps = steps

        elif isinstance(steps, int):
            # int number of bars, defaults to red.
            self.n_steps = steps
            self.steps = ['red'] * steps

        else:
            raise TypeError('steps must be a list or int')

        self._bar_solid_percent = 0.8
        self._background_color = qt_import.QColor('black')
        self._padding = 4.0  # n-pixel gap around edge.

    def paintEvent(self, e):
        painter = qt_import.QPainter(self)

        brush = qt_import.QBrush()
        brush.setColor(self._background_color)
        brush.setStyle(qt_import.Qt.SolidPattern)
        rect = qt_import.QRect(0, 0,
                               painter.device().width(),
                               painter.device().height())
        painter.fillRect(rect, brush)

        # Get current state.
        parent = self.parent()
        vmin, vmax = parent.minimum(), parent.maximum()
        value = parent.value()

        # Define our canvas.
        d_height = painter.device().height() - (self._padding * 2)
        d_width = painter.device().width() - (self._padding * 2)

        # Draw the bars.
        step_size = d_height / self.n_steps
        bar_height = step_size * self._bar_solid_percent
        bar_spacer = step_size * (1 - self._bar_solid_percent) / 2

        # Calculate the y-stop position, from the value in range.
        pc = (value - vmin) / (vmax - vmin)
        n_steps_to_draw = int(pc * self.n_steps)

        for n in range(n_steps_to_draw):
            brush.setColor(qt_import.QColor(self.steps[n]))
            rect = qt_import.QRect(
                self._padding,
                self._padding + d_height - ((1 + n) * step_size) + bar_spacer,
                d_width, bar_height)
            painter.fillRect(rect, brush)

        painter.end()

    def sizeHint(self):
        return qt_import.QSize(40, 120)

    def _trigger_refresh(self):
        self.update()

    def _calculate_clicked_value(self, e):
        parent = self.parent()
        vmin, vmax = parent.minimum(), parent.maximum()
        d_height = self.size().height() + (self._padding * 2)
        step_size = d_height / self.n_steps
        click_y = e.y() - self._padding - step_size / 2

        pc = (d_height - click_y) / d_height
        value = vmin + pc * (vmax - vmin)
        self.clickedValue.emit(value)

    def mouseMoveEvent(self, e):
        self._calculate_clicked_value(e)

    def mousePressEvent(self, e):
        self._calculate_clicked_value(e)
コード例 #12
0
class DataPathWidget(qt_import.QWidget):

    pathTemplateChangedSignal = qt_import.pyqtSignal()

    def __init__(self, parent=None, name="", fl=0, data_model=None, layout=None):

        qt_import.QWidget.__init__(self, parent, qt_import.Qt.WindowFlags(fl))

        if name is not None:
            self.setObjectName(name)
        self.parent = parent

        # Hardware objects ----------------------------------------------------

        # Internal variables --------------------------------------------------
        self._base_image_dir = ""
        self._base_process_dir = ""
        self.path_conflict_state = False
        self.enable_macros = False

        if data_model is None:
            self._data_model = queue_model_objects.PathTemplate()
        else:
            self._data_model = data_model

        self._data_model_pm = DataModelInputBinder(self._data_model)

        # Graphic elements ----------------------------------------------------
        if layout == "vertical":
            self.data_path_layout = qt_import.load_ui_file(
                "data_path_widget_vertical_layout.ui"
            )
        else:
            self.data_path_layout = qt_import.load_ui_file(
                "data_path_widget_horizontal_layout.ui"
            )

        # Layout --------------------------------------------------------------
        _main_vlayout = qt_import.QVBoxLayout(self)
        _main_vlayout.addWidget(self.data_path_layout)
        _main_vlayout.setSpacing(0)
        _main_vlayout.setContentsMargins(0, 0, 0, 0)

        # Qt signal/slot connections ------------------------------------------
        self.data_path_layout.prefix_ledit.textChanged.connect(
            self._prefix_ledit_change
        )
        self.data_path_layout.run_number_ledit.textChanged.connect(
            self._run_number_ledit_change
        )
        self.data_path_layout.browse_button.clicked.connect(self._browse_clicked)
        self.data_path_layout.folder_ledit.textChanged.connect(
            self._folder_ledit_change
        )
        self.data_path_layout.compression_cbox.clicked.connect(
            self._compression_toggled
        )

        # Other ---------------------------------------------------------------
        self._data_model_pm.bind_value_update(
            "base_prefix", self.data_path_layout.prefix_ledit, str, None
        )

        self._data_model_pm.bind_value_update(
            "run_number",
            self.data_path_layout.run_number_ledit,
            int,
            qt_import.QIntValidator(0, 1000, self),
        )

        self._data_model_pm.bind_value_update(
            "compression", self.data_path_layout.compression_cbox, bool, None
        )

    def set_base_image_directory(self, base_image_dir):
        self._base_image_dir = base_image_dir

    def set_base_process_directory(self, base_process_dir):
        self._base_process_dir = base_process_dir

    def _browse_clicked(self):
        file_dialog = qt_import.QFileDialog(self)
        file_dialog.setNameFilter("%s*" % self._base_image_dir)

        selected_dir = str(
            file_dialog.getExistingDirectory(
                self, "Select a directory", str(self._base_image_dir), qt_import.QFileDialog.ShowDirsOnly
            )
        )
        if selected_dir is not None and len(selected_dir) > 0 and selected_dir.startswith(self._base_image_dir):
            self.set_directory(selected_dir)
        else:
            msg = "Selected directory do not start " +\
                  "with the base directory %s" % self._base_image_dir
            logging.getLogger("GUI").error(msg)

    def _prefix_ledit_change(self, new_value):
        cursor_pos = self.data_path_layout.prefix_ledit.cursorPosition()

        if len(new_value) > 0:
            available_chars = (
                string.ascii_lowercase + string.ascii_uppercase + string.digits + "-_"
            )
            if self.enable_macros:
                available_chars += "%"
            new_value = "".join(i for i in str(new_value) if i in available_chars)
            new_value = new_value.replace("\\", "")

        if len(new_value) > 50:
            logging.getLogger("GUI").error(
                "Current prefix is to long (max 50 characters are allowed)"
            )
            new_value = new_value[:-1]

        self.data_path_layout.prefix_ledit.setText(new_value)
        self.data_path_layout.prefix_ledit.setCursorPosition(cursor_pos)

        self._data_model.base_prefix = str(new_value)
        self.update_file_name()
        self.pathTemplateChangedSignal.emit()

    def _run_number_ledit_change(self, new_value):
        if str(new_value).isdigit():
            self._data_model.run_number = int(new_value)
            self.data_path_layout.run_number_ledit.setText(str(new_value))

            self.update_file_name()
            self.pathTemplateChangedSignal.emit()
        else:
            # self.data_path_layout.run_number_ledit.setText(str(self._data_model.run_number))
            colors.set_widget_color(
                self.data_path_layout.folder_ledit, colors.LIGHT_YELLOW
            )

    def _folder_ledit_change(self, new_value):
        base_image_dir = self._base_image_dir
        base_proc_dir = self._base_process_dir
        new_sub_dir = str(new_value).strip(" ")

        cursor_pos = self.data_path_layout.folder_ledit.cursorPosition()
        if len(new_value) > 0:
            available_chars = (
                string.ascii_lowercase + string.ascii_uppercase + string.digits + "-_/"
            )
            if self.enable_macros:
                available_chars += "%"
            new_value = "".join(i for i in str(new_value) if i in available_chars)
            # new_value = new_value.replace("\\", "")

        new_sub_dir = str(new_value).strip(" ")
        self.data_path_layout.folder_ledit.setText(new_value)
        self.data_path_layout.folder_ledit.setCursorPosition(cursor_pos)

        if len(new_sub_dir) > 0:
            if new_sub_dir[0] == os.path.sep:
                new_sub_dir = new_sub_dir[1:]
            new_image_directory = os.path.join(base_image_dir, str(new_sub_dir))
            new_proc_dir = os.path.join(base_proc_dir, str(new_sub_dir))
        else:
            new_image_directory = base_image_dir
            new_proc_dir = base_proc_dir

        self._data_model.directory = new_image_directory
        self._data_model.process_directory = new_proc_dir
        colors.set_widget_color(self.data_path_layout.folder_ledit, colors.WHITE)

        self.pathTemplateChangedSignal.emit()

    def _compression_toggled(self, state):
        if hasattr(self.parent, "_tree_brick"):
            if self.parent._tree_brick:
                self.parent._tree_brick.compression_state = state

        queue_model_objects.Characterisation.set_char_compression(state)
        self._data_model.compression = state
        self.update_file_name()
        self.pathTemplateChangedSignal.emit()

    def update_file_name(self):
        """
        updates filename if prefix or run number changed
        at start values are initalized before precision is set.
        so a check for isdigit is done to be on the safe side
        """
        if str(self._data_model.precision).isdigit():
            file_name = self._data_model.get_image_file_name()
            file_name = file_name.replace(
                "%" + str(self._data_model.precision) + "d",
                int(self._data_model.precision) * "#",
            )
            file_name = file_name.strip(" ")
            self.data_path_layout.file_name_value_label.setText(file_name)

    def set_data_path(self, path):
        (dir_name, file_name) = os.path.split(path)
        if self._data_model.precision:
            precision = self._data_model.precision
        else:
            precision = "5"

        self.set_directory(dir_name)
        file_name = file_name.replace(
            "%" + str(self._data_model.precision) + "d",
            int(precision) * "#",
        )
        self.data_path_layout.file_name_value_label.setText(file_name)

    def set_directory(self, directory):
        self._data_model.directory = str(directory)

        if len(directory.split("/")) != len(self._base_image_dir.split("/")):
            dir_parts = directory.split("/")
            sub_dir = os.path.join(*dir_parts[len(self._base_image_dir.split("/")) :])
            self.data_path_layout.folder_ledit.setText(sub_dir)
        else:
            self.data_path_layout.folder_ledit.setText("")
            self._data_model.directory = self._base_image_dir

        self.data_path_layout.base_path_ledit.setText(self._base_image_dir)

    # def set_run_number(self, run_number):
    #    """
    #    Descript. :
    #    """
    #    self._data_model.run_number = int(run_number)
    #    self.data_path_layout.run_number_ledit.setText(str(run_number))

    def set_prefix(self, base_prefix):
        self._data_model.base_prefix = str(base_prefix)
        self.data_path_layout.prefix_ledit.setText(str(base_prefix))
        file_name = self._data_model.get_image_file_name()
        file_name = file_name.replace(
            "%" + str(self._data_model.precision) + "d",
            int(self._data_model.precision) * "#",
        )
        self.data_path_layout.file_name_value_label.setText(file_name)

    def update_data_model(self, data_model):
        self._data_model = data_model
        self.set_data_path(data_model.get_image_path())
        self._data_model_pm.set_model(data_model)
        self.data_path_layout.browse_button.setEnabled(os.path.exists(self._base_image_dir))

    def indicate_path_conflict(self, conflict):
        if conflict:
            colors.set_widget_color(
                self.data_path_layout.prefix_ledit,
                colors.LIGHT_RED,
                qt_import.QPalette.Base,
            )
            colors.set_widget_color(
                self.data_path_layout.run_number_ledit,
                colors.LIGHT_RED,
                qt_import.QPalette.Base,
            )
            colors.set_widget_color(
                self.data_path_layout.folder_ledit,
                colors.LIGHT_RED,
                qt_import.QPalette.Base,
            )

            logging.getLogger("GUI").error(
                "The current path settings will overwrite data "
                + "from another task. Correct the problem before "
                + "adding to queue"
            )
        else:
            # We had a conflict previous, but its corrected now !
            if self.path_conflict_state:
                logging.getLogger("GUI").info("Path valid")

                colors.set_widget_color(
                    self.data_path_layout.prefix_ledit,
                    colors.WHITE,
                    qt_import.QPalette.Base,
                )
                colors.set_widget_color(
                    self.data_path_layout.run_number_ledit,
                    colors.WHITE,
                    qt_import.QPalette.Base,
                )
                colors.set_widget_color(
                    self.data_path_layout.folder_ledit,
                    colors.WHITE,
                    qt_import.QPalette.Base,
                )
        self.path_conflict_state = conflict
コード例 #13
0
class BaseWidget(connectable.Connectable, qt_import.QFrame):
    """Base class for MXCuBE bricks"""

    (
        INSTANCE_ROLE_UNKNOWN,
        INSTANCE_ROLE_SERVER,
        INSTANCE_ROLE_SERVERSTARTING,
        INSTANCE_ROLE_CLIENT,
        INSTANCE_ROLE_CLIENTCONNECTING,
    ) = (0, 1, 2, 3, 4)
    (INSTANCE_MODE_UNKNOWN, INSTANCE_MODE_MASTER, INSTANCE_MODE_SLAVE) = (0, 1,
                                                                          2)
    (
        INSTANCE_LOCATION_UNKNOWN,
        INSTANCE_LOCATION_LOCAL,
        INSTANCE_LOCATION_INHOUSE,
        INSTANCE_LOCATION_INSITE,
        INSTANCE_LOCATION_EXTERNAL,
    ) = (0, 1, 2, 3, 4)
    (
        INSTANCE_USERID_UNKNOWN,
        INSTANCE_USERID_LOGGED,
        INSTANCE_USERID_INHOUSE,
        INSTANCE_USERID_IMPERSONATE,
    ) = (0, 1, 2, 3)
    (INSTANCE_MIRROR_UNKNOWN, INSTANCE_MIRROR_ALLOW,
     INSTANCE_MIRROR_PREVENT) = (
         0,
         1,
         2,
     )

    _run_mode = False
    _instance_role = INSTANCE_ROLE_UNKNOWN
    _instance_mode = INSTANCE_MODE_UNKNOWN
    _instance_location = INSTANCE_LOCATION_UNKNOWN
    _instance_user_id = INSTANCE_USERID_UNKNOWN
    _instance_mirror = INSTANCE_MIRROR_UNKNOWN
    _filter_installed = False
    _events_cache = {}
    _menu_background_color = None
    _menubar = None
    _toolbar = None
    _statusbar = None
    _warning_box = None
    _progressbar = None
    _progress_dialog = None

    _application_event_filter = InstanceEventFilter(None)

    widgetSynchronizeSignal = qt_import.pyqtSignal([])

    @staticmethod
    def set_run_mode(mode):
        if mode:
            BaseWidget._run_mode = True
            for widget in qt_import.QApplication.allWidgets():
                if isinstance(widget, BaseWidget):
                    widget.__run()
                    try:
                        widget.set_expert_mode(False)
                    except BaseException:
                        logging.getLogger().exception(
                            "Could not set %s to user mode", widget.name())

        else:
            BaseWidget._run_mode = False
            for widget in qt_import.QApplication.allWidgets():
                if isinstance(widget, BaseWidget):
                    widget.__stop()
                    try:
                        widget.set_expert_mode(True)
                    except Exception as ex:
                        logging.getLogger().exception(
                            "Could not set %s to expert mode: %s" %
                            (str(widget), str(ex)))

    @staticmethod
    def is_running():
        return BaseWidget._run_mode

    @staticmethod
    def update_menu_bar_color(enable_checkbox=None):
        """Not a direct way how to change menubar color
           It is now done by changing stylesheet
        """
        color = None
        if BaseWidget._menubar is not None:
            BaseWidget._menubar.parent.update_instance_caption("")
            if BaseWidget._instance_mode == BaseWidget.INSTANCE_MODE_MASTER:
                if (BaseWidget._instance_user_id ==
                        BaseWidget.INSTANCE_USERID_IMPERSONATE):
                    color = "lightBlue"
                else:
                    color = "rgb(204,255,204)"
            elif BaseWidget._instance_mode == BaseWidget.INSTANCE_MODE_SLAVE:
                BaseWidget._menubar.parent.update_instance_caption(
                    " : slave instance (all controls are disabled)")
                if (BaseWidget._instance_role ==
                        BaseWidget.INSTANCE_ROLE_CLIENTCONNECTING):
                    color = "rgb(255,204,204)"
                elif BaseWidget._instance_user_id == BaseWidget.INSTANCE_USERID_UNKNOWN:
                    color = "rgb(255, 165, 0)"
                else:
                    color = "yellow"

        if color is not None:
            BaseWidget._menubar.set_color(color)

    @staticmethod
    def set_instance_mode(mode):
        BaseWidget._instance_mode = mode
        for widget in qt_import.QApplication.allWidgets():
            if isinstance(widget, BaseWidget):
                widget._instance_mode_changed(mode)
                if widget["instanceAllowAlways"]:
                    widget.setEnabled(True)
                else:
                    widget.setEnabled(mode == BaseWidget.INSTANCE_MODE_MASTER)
        if BaseWidget._instance_mode == BaseWidget.INSTANCE_MODE_MASTER:
            if BaseWidget._filter_installed:
                qt_import.QApplication.instance().removeEventFilter(
                    BaseWidget._application_event_filter)
                BaseWidget._filter_installed = False
                BaseWidget.synchronize_with_cache()  # why?
        else:
            if not BaseWidget._filter_installed:
                qt_import.QApplication.instance().installEventFilter(
                    BaseWidget._application_event_filter)
                BaseWidget._filter_installed = True

        BaseWidget.update_menu_bar_color(
            BaseWidget._instance_mode == BaseWidget.INSTANCE_MODE_MASTER)

    @staticmethod
    def set_status_info(info_type, info_message, info_status=""):
        """Updates status bar"""
        if BaseWidget._statusbar:
            BaseWidget._statusbar.parent().update_status_info(
                info_type, info_message, info_status)

    @staticmethod
    def set_warning_box(warning_msg):
        """Updates status bar"""
        if BaseWidget._warning_box:
            BaseWidget._warning_box.parent().show_warning_box(warning_msg)

    @staticmethod
    def init_progress_bar(progress_type, number_of_steps):
        """Updates status bar"""
        if BaseWidget._statusbar:
            BaseWidget._statusbar.parent().init_progress_bar(
                progress_type, number_of_steps)

    @staticmethod
    def set_progress_bar_step(step):
        """Updates status bar"""
        if BaseWidget._statusbar:
            BaseWidget._statusbar.parent().set_progress_bar_step(step)

    @staticmethod
    def stop_progress_bar():
        """Updates status bar"""
        if BaseWidget._statusbar:
            BaseWidget._statusbar.parent().stop_progress_bar()

    @staticmethod
    def open_progress_dialog(msg, max_steps):
        if BaseWidget._progress_dialog:
            BaseWidget._progress_dialog.parent().open_progress_dialog(
                msg, max_steps)

    @staticmethod
    def set_progress_dialog_step(step, msg):
        if BaseWidget._progress_dialog:
            BaseWidget._progress_dialog.parent().set_progress_dialog_step(
                step, msg)

    @staticmethod
    def close_progress_dialog():
        if BaseWidget._progress_dialog:
            BaseWidget._progress_dialog.parent().close_progress_dialog()

    @staticmethod
    def set_user_file_directory(user_file_directory):
        BaseWidget.user_file_directory = user_file_directory

    def should_filter_event(self):
        if BaseWidget._instance_mode == BaseWidget.INSTANCE_MODE_MASTER:
            return False
        try:
            allow_always = self["instanceAllowAlways"]
        except KeyError:
            return False
        if not allow_always:
            try:
                allow_connected = self["instanceAllowConnected"]
            except KeyError:
                return False

            connected = BaseWidget._instance_role in (
                BaseWidget.INSTANCE_ROLE_SERVER,
                BaseWidget.INSTANCE_ROLE_CLIENT,
            )
            if allow_connected and connected:
                return False
            return True

        return False

    def connect_group_box(self, widget, widget_name, master_sync):
        brick_name = self.objectName()
        widget.toggled.connect(lambda s: BaseWidget.widget_groupbox_toggled(
            brick_name, widget_name, master_sync, s))

    def connect_combobox(self, widget, widget_name, master_sync):
        brick_name = self.objectName()
        widget.activated.connect(
            lambda i: BaseWidget.widget_combobox_activated(
                brick_name, widget_name, widget, master_sync, i))

    def connect_line_edit(self, widget, widget_name, master_sync):
        brick_name = self.objectName()
        widget.textChanged.connect(
            lambda t: BaseWidget.widget_line_edit_text_changed(
                brick_name, widget_name, master_sync, t))

    def connect_spinbox(self, widget, widget_name, master_sync):
        brick_name = self.objectName()
        widget.valueChanged.connect(
            lambda t: BaseWidget.widget_spinbox_value_changed(
                brick_name, widget_name, master_sync, t))

    def connect_double_spinbox(self, widget, widget_name, master_sync):
        brick_name = self.objectName()
        widget.valueChanged.connect(
            lambda t: BaseWidget.widget_double_spinbox_value_changed(
                brick_name, widget_name, master_sync, t))

    def connect_generic_widget(self, widget, widget_name, master_sync):
        brick_name = self.objectName()
        widget.widgetSynchronize.connect(
            lambda state: BaseWidget.widget_generic_changed(
                brick_name, widget_name, master_sync, state))

    def _instance_mode_changed(self, mode):
        for widget, widget_name, master_sync in self._widget_events:
            if isinstance(widget, qt_import.QGroupBox):
                self.connect_group_box(widget, widget_name, master_sync)
            elif isinstance(widget, qt_import.QComboBox):
                self.connect_combobox(widget, widget_name, master_sync)
            elif isinstance(widget, qt_import.QLineEdit):
                self.connect_line_edit(widget, widget_name, master_sync)
            elif isinstance(widget, qt_import.QSpinBox):
                self.connect_spinbox(widget, widget_name, master_sync)
            elif isinstance(widget, qt_import.QDoubleSpinBox):
                self.connect_double_spinbox(widget, widget_name, master_sync)
            else:
                # verify if widget has the widgetSynchronize method!!!
                self.connect_generic_widget(widget, widget_name, master_sync)
        self._widget_events = []

        if self.should_filter_event():
            self.setCursor(qt_import.QCursor(qt_import.Qt.ForbiddenCursor))
        else:
            self.setCursor(qt_import.QCursor(qt_import.Qt.ArrowCursor))

    @staticmethod
    def is_instance_mode_master():
        return BaseWidget._instance_mode == BaseWidget.INSTANCE_MODE_MASTER

    @staticmethod
    def is_instance_mode_slave():
        return BaseWidget._instance_mode == BaseWidget.INSTANCE_MODE_SLAVE

    @staticmethod
    def is_istance_role_unknown():
        return BaseWidget._instance_role == BaseWidget.INSTANCE_ROLE_UNKNOWN

    @staticmethod
    def is_instance_role_client():
        return BaseWidget._instance_role == BaseWidget.INSTANCE_ROLE_CLIENT

    @staticmethod
    def is_instance_role_server():
        return BaseWidget._instance_role == BaseWidget.INSTANCE_ROLE_SERVER

    @staticmethod
    def is_instance_user_id_unknown():
        return BaseWidget._instance_user_id == BaseWidget.INSTANCE_USERID_UNKNOWN

    @staticmethod
    def is_instance_user_id_logged():
        return BaseWidget._instance_user_id == BaseWidget.INSTANCE_USERID_LOGGED

    @staticmethod
    def is_instance_user_id_inhouse():
        return BaseWidget._instance_user_id == BaseWidget.INSTANCE_USERID_INHOUSE

    @staticmethod
    def set_instance_role(role):
        if role == BaseWidget._instance_role:
            return
        BaseWidget._instance_role = role
        for widget in qt_import.QApplication.allWidgets():
            if isinstance(widget, BaseWidget):
                # try:
                widget.instance_role_changed(role)
                # except:
                #    pass

    @staticmethod
    def set_instance_location(location):
        if location == BaseWidget._instance_location:
            return
        BaseWidget._instance_location = location
        for widget in qt_import.QApplication.allWidgets():
            if isinstance(widget, BaseWidget):
                # try:
                widget.instance_location_changed(location)
                # except:
                #    pass

    @staticmethod
    def set_instance_user_id(user_id):
        if user_id == BaseWidget._instance_user_id:
            return
        BaseWidget._instance_user_id = user_id

        for widget in qt_import.QApplication.allWidgets():
            if isinstance(widget, BaseWidget):
                # try:
                widget.instance_user_id_changed(user_id)
                # except:
                #    pass
        BaseWidget.update_menu_bar_color()

    @staticmethod
    def set_instance_mirror(mirror):
        if mirror == BaseWidget._instance_mirror:
            return
        BaseWidget._instance_mirror = mirror

        if mirror == BaseWidget.INSTANCE_MIRROR_ALLOW:
            BaseWidget.synchronize_with_cache()

        for widget in qt_import.QApplication.allWidgets():
            if isinstance(widget, BaseWidget):
                widget.instance_mirror_changed(mirror)

    def instance_mirror_changed(self, mirror):
        pass

    def instance_location_changed(self, location):
        pass

    @staticmethod
    def is_instance_location_unknown():
        return BaseWidget._instance_location == BaseWidget.INSTANCE_LOCATION_UNKNOWN

    @staticmethod
    def is_instance_location_local():
        return BaseWidget._instance_location == BaseWidget.INSTANCE_LOCATION_LOCAL

    @staticmethod
    def is_instance_mirror_allow():
        return BaseWidget._instance_mirror == BaseWidget.INSTANCE_MIRROR_ALLOW

    def instance_user_id_changed(self, user_id):
        pass

    def instance_role_changed(self, role):
        pass

    @staticmethod
    def update_whats_this():
        for widget in qt_import.QApplication.allWidgets():
            if isinstance(widget, BaseWidget):
                msg = "%s (%s)\n%s" % (
                    widget.objectName(),
                    widget.__class__.__name__,
                    widget.get_hardware_objects_info(),
                )
                widget.setWhatsThis(msg)
        qt_import.QWhatsThis.enterWhatsThisMode()

    @staticmethod
    def update_widget(brick_name, widget_name, method_name, method_args,
                      master_sync):
        for widget in qt_import.QApplication.allWidgets():
            try:
                if hasattr(widget, "configuration"):
                    top_level_widget = widget
                    break
            except NameError:
                continue

        if (not master_sync or BaseWidget._instance_mode
                == BaseWidget.INSTANCE_MODE_MASTER):
            top_level_widget.brickChangedSignal.emit(brick_name, widget_name,
                                                     method_name, method_args,
                                                     master_sync)

    @staticmethod
    def update_tab_widget(tab_name, tab_index):
        if BaseWidget._instance_mode == BaseWidget.INSTANCE_MODE_MASTER:
            for widget in qt_import.QApplication.allWidgets():
                if hasattr(widget, "configuration"):
                    widget.tabChangedSignal.emit(tab_name, tab_index)

    @staticmethod
    def widget_groupbox_toggled(brick_name, widget_name, master_sync, state):
        BaseWidget.update_widget(brick_name, widget_name, "setChecked",
                                 (state, ), master_sync)

    @staticmethod
    def widget_combobox_activated(brick_name, widget_name, widget, master_sync,
                                  item_index):
        lines = []
        if widget.isEditable():
            for index in range(widget.count()):
                lines.append(str(widget.itemText(index)))
        BaseWidget.update_widget(brick_name, widget_name, "setCurrentIndex",
                                 (item_index, ), master_sync)

    @staticmethod
    def widget_line_edit_text_changed(brick_name, widget_name, master_sync,
                                      text):
        BaseWidget.update_widget(brick_name, widget_name, "setText", (text, ),
                                 master_sync)

    @staticmethod
    def widget_spinbox_value_changed(brick_name, widget_name, master_sync,
                                     text):
        BaseWidget.update_widget(brick_name, widget_name, "setValue",
                                 (int(text), ), master_sync)

    @staticmethod
    def widget_double_spinbox_value_changed(brick_name, widget_name,
                                            master_sync, text):
        BaseWidget.update_widget(brick_name, widget_name, "setValue",
                                 (float(text), ), master_sync)

    @staticmethod
    def widget_generic_changed(brick_name, widget_name, master_sync, state):
        BaseWidget.update_widget(brick_name, widget_name, "widget_synchronize",
                                 (state, ), master_sync)

    def instance_forward_events(self, widget_name, master_sync):
        if widget_name == "":
            widget = self
        else:
            widget = getattr(self, widget_name)
        self._widget_events.append((widget, widget_name, master_sync))

    def instance_synchronize(self, *args, **kwargs):
        for widget_name in args:
            self.instance_forward_events(widget_name,
                                         kwargs.get("master_sync", True))

    @staticmethod
    def should_run_event():
        return BaseWidget._instance_mirror == BaseWidget.INSTANCE_MIRROR_ALLOW

    @staticmethod
    def add_event_to_cache(timestamp, method, *args):
        try:
            method_to_add = WeakMethod(method)
        except TypeError:
            method_to_add = method
        BaseWidget._events_cache[method_to_add] = (timestamp, method_to_add,
                                                   args)

    @staticmethod
    def synchronize_with_cache():
        events = list(BaseWidget._events_cache.values())
        ordered_events = sorted(events, key=operator.itemgetter(0))
        for event_timestamp, event_method, event_args in ordered_events:
            try:
                method = event_method()
                if method is not None:
                    method(*event_args)
            except BaseException:
                pass
        BaseWidget._events_cache = {}

    @staticmethod
    def set_gui_enabled(enabled):
        for widget in qt_import.QApplication.allWidgets():
            if isinstance(widget, BaseWidget):
                widget.setEnabled(enabled)

    def __init__(self, parent=None, widget_name=""):

        connectable.Connectable.__init__(self)
        qt_import.QFrame.__init__(self, parent)
        self.setObjectName(widget_name)
        self.property_bag = property_bag.PropertyBag()

        self.__enabled_state = True
        self.__loaded_hardware_objects = []
        self.__failed_to_load_hwobj = False
        self.__use_progress_dialog = False
        self._signal_slot_filters = {}
        self._widget_events = []

        self.setWhatsThis("%s (%s)\n" % (widget_name, self.__class__.__name__))

        self.add_property("fontSize", "string", str(self.font().pointSize()))
        self.add_property("frame",
                          "boolean",
                          False,
                          comment="Draw a frame around the widget")
        self.add_property(
            "instanceAllowAlways",
            "boolean",
            False,
            comment="Allow to control brick in all modes",
        )
        self.add_property(
            "instanceAllowConnected",
            "boolean",
            False,
            comment="Allow to control brick in slave mode",
        )
        self.add_property("fixedWidth",
                          "integer",
                          "-1",
                          comment="Set fixed width in pixels")
        self.add_property("fixedHeight",
                          "integer",
                          "-1",
                          comment="Set fixed height in pixels")
        self.add_property("hide", "boolean", False, comment="Hide widget")

        dispatcher.connect(
            self.__hardware_object_discarded,
            "hardwareObjectDiscarded",
            HWR.get_hardware_repository(),
        )
        self.define_slot("enable_widget", ())
        self.define_slot("disable_widget", ())

        # If PySide used then connect method was not overriden
        # This solution of redirecting methods works...

        self.connect = self.connect_hwobj
        self.disconnect = self.disconnect_hwobj
        # self.run_mode = QPushButton("Run mode", self)

    def __run(self):
        self.setAcceptDrops(False)
        self.blockSignals(False)
        self.setEnabled(self.__enabled_state)
        # self.run_mode_pushbutton = QPushButton("Simulation", self)

        try:
            self.run()
        except BaseException:
            logging.getLogger().exception("Could not set %s to run mode",
                                          self.objectName())

    def __stop(self):
        self.blockSignals(True)

        try:
            self.stop()
        except BaseException:
            logging.getLogger().exception("Could not stop %s",
                                          self.objectName())

        # self.setAcceptDrops(True)
        self.__enabled_state = self.isEnabled()
        qt_import.QWidget.setEnabled(self, True)

    def __repr__(self):
        return repr("<%s: %s>" % (self.__class__, self.objectName()))

    def connect_signal_slot_filter(self, sender, signal, slot, should_cache):
        uid = (sender, signal, hash(slot))
        signal_slot_filter = SignalSlotFilter(signal, slot, should_cache)
        self._signal_slot_filters[uid] = signal_slot_filter

        signal.connect(signal_slot_filter)
        # qt_import.QObject.connect(sender, signal, signal_slot_filter)

    def connect_hwobj(self,
                      sender,
                      signal,
                      slot,
                      instance_filter=False,
                      should_cache=True):

        if sys.version_info > (3, 0):
            signal = str(
                signal.decode("utf8") if isinstance(signal, bytes) else signal)
        else:
            signal = str(signal)

        if signal[0].isdigit():
            pysignal = signal[0] == "9"
            signal = signal[1:]
        else:
            pysignal = True

        if not isinstance(sender, qt_import.QObject):
            if isinstance(sender, HardwareObject):
                sender.connect(signal, slot)
                return
            else:
                _sender = emitter(sender)
        else:
            _sender = sender

        if instance_filter:
            self.connect_signal_slot_filter(
                _sender,
                pysignal and qt_import.pyqtSignal(signal)
                or qt_import.pyqtSignal(signal),
                slot,
                should_cache,
            )
        else:
            # Porting to Qt5
            getattr(_sender, signal).connect(slot)

            # QtCore.QObject.connect(_sender,
            #                       pysignal and \
            #                       QtCore.SIGNAL(signal) or \
            #                       QtCore.SIGNAL(signal),
            #                       slot)

        # workaround for PyQt lapse
        # if hasattr(sender, "connectNotify"):
        #    sender.connect_notify(QtCore.pyqtSignal(signal))

    def disconnect_hwobj(self, sender, signal, slot):
        signal = str(signal)
        if signal[0].isdigit():
            pysignal = signal[0] == "9"
            signal = signal[1:]
        else:
            pysignal = True

        if isinstance(sender, HardwareObject):
            sender.disconnect(sender, signal, slot)
            return

        # workaround for PyQt lapse
        if hasattr(sender, "disconnectNotify"):
            sender.disconnect_notify(signal)

        if not isinstance(sender, qt_import.QObject):
            sender = emitter(sender)

            try:
                uid = (
                    sender,
                    pysignal and qt_import.pyqtSignal(signal)
                    or qt_import.pyqtSignal(signal),
                    hash(slot),
                )
                signal_slot_filter = self._signal_slot_filters[uid]
            except KeyError:
                getattr(sender, signal).disconnect(slot)
                # qt_import.QObject.disconnect(sender,
                #                            pysignal and
                #                            qt_import.QtCore.SIGNAL(signal) or
                #                            qt_import.QtCore.SIGNAL(signal),
                #                            slot)
            else:
                getattr(sender, signal).disconnect(signal_slot_filter)
                # qt_import.QObject.disconnect(sender,
                #                            pysignal and
                #                            qt_import.SIGNAL(signal) or
                #                            qt_import.SIGNAL(signal),
                #                            signal_slot_filter)
                del self._signal_slot_filters[uid]
        else:
            getattr(sender, signal).disconnect(signal_slot_filter)
            # qt_import.QObject.disconnect(sender,
            #                            pysignal and
            #                            qt_import.SIGNAL(signal) or
            #                            qt_import.SIGNAL(signal),
            #                            signal_slot_filter)

    def reparent(self, widget_to):
        saved_enabled_state = self.isEnabled()
        if self.parent() is not None:
            self.parent().layout().removeWidget(self)
        if widget_to is not None:
            widget_to.layout().addWidget(self)
            self.setEnabled(saved_enabled_state)

    def blockSignals(self, block):
        for child in self.children():
            child.blockSignals(block)

    def run(self):
        pass

    def stop(self):
        pass

    def restart(self):
        self.stop()
        self.run()

    def set_persistent_property_bag(self, persistent_property_bag):
        if id(persistent_property_bag) != id(self.property_bag):
            for prop in persistent_property_bag:
                if hasattr(prop, "get_name"):
                    if prop.get_name() in self.property_bag.properties:
                        self.property_bag.get_property(
                            prop.get_name()).set_value(prop.get_user_value())
                    elif prop.hidden:
                        self.property_bag[prop.get_name()] = prop
                else:
                    if prop["name"] in self.property_bag.properties:
                        self.property_bag.get_property(prop["name"]).set_value(
                            prop["value"])
                    elif prop["hidden"]:
                        self.property_bag[prop["name"]] = prop

        self.read_properties()

    def read_properties(self):
        for prop in self.property_bag:
            self._property_changed(prop.get_name(), None,
                                   prop.get_user_value())

    def add_property(self, *args, **kwargs):
        self.property_bag.add_property(*args, **kwargs)

    def get_property(self, property_name):
        return self.property_bag.get_property(property_name)

    def show_property(self, property_name):
        return self.property_bag.show_property(property_name)

    def hide_property(self, property_name):
        return self.property_bag.hide_property(property_name)

    def del_property(self, property_name):
        return self.property_bag.del_property(property_name)

    def get_hardware_object(self, hardware_object_name, optional=False):
        splash_screen = mxcubeqt.get_splash()
        if splash_screen:
            splash_screen.set_message(
                "Loading hardware object defined in %s.xml" %
                hardware_object_name)

        if not hardware_object_name in self.__loaded_hardware_objects:
            if splash_screen:
                splash_screen.inc_progress_value()
            self.__loaded_hardware_objects.append(hardware_object_name)

        hwobj = HWR.get_hardware_repository().get_hardware_object(
            hardware_object_name)

        if hwobj is not None:
            self.connect(hwobj, "progressInit", self.progress_init)
            self.connect(hwobj, "progressStep", self.progress_step)
            self.connect(hwobj, "progressStop", self.progress_stop)
            self.connect(hwobj, "statusMessage", self.status_message_changed)
            self.connect(hwobj, "showWarning", self.show_warning)

        if hwobj is None and not optional:
            logging.getLogger("GUI").error(
                "%s: Unable to initialize hardware object defined in %s.xml" %
                (self.objectName(), hardware_object_name[1:]))
            self.set_background_color(colors.LIGHT_RED)
            self.__failed_to_load_hwobj = True
            self.setDisabled(True)

        return hwobj

    def progress_init(self, progress_type, number_of_steps, use_dialog=False):
        self.__use_progress_dialog = use_dialog
        if self.__use_progress_dialog:
            BaseWidget.open_progress_dialog(progress_type, number_of_steps)

    def progress_step(self, step, msg=None):
        if self.__use_progress_dialog:
            BaseWidget.set_progress_dialog_step(step, msg)

    def progress_stop(self):
        if self.__use_progress_dialog:
            BaseWidget.close_progress_dialog()

    def status_message_changed(self, info_type, message, state):
        BaseWidget.set_status_info(info_type, message, state)

    def show_warning(self, warning_msg):
        BaseWidget.set_warning_box(warning_msg)

    def __hardware_object_discarded(self, hardware_object_name):
        if hardware_object_name in self.__loaded_hardware_objects:
            # there is a high probability we need to reload this hardware object...
            self.readProperties()  # force to read properties

    def get_hardware_objects_info(self):
        info_dict = {}
        for ho_name in self.__loaded_hardware_objects:
            info = HWR.get_hardware_repository().get_info(ho_name)

            if len(info) > 0:
                info_dict[ho_name] = info

        if len(info_dict):
            return "Hardware Objects:\n\n%s" % pprint.pformat(info_dict)
        else:
            return ""

    def __getitem__(self, property_name):
        return self.property_bag[property_name]

    def __setitem__(self, property_name, value):
        property_bag = self.property_bag.get_property(property_name)
        old_value = property_bag.get_value()
        property_bag.set_value(value)

        self._property_changed(property_name, old_value,
                               property_bag.get_user_value())

    def _property_changed(self, property_name, old_value, new_value):
        if property_name == "fontSize":
            try:
                font_size = int(new_value)
            except BaseException:
                self.get_property("fontSize").set_value(
                    self.font().pointSize())
            else:
                font = self.font()
                font.setPointSize(font_size)
                self.setFont(font)

                for brick in self.children():
                    if isinstance(brick, BaseWidget):
                        brick["fontSize"] = font_size
                self.update()
        elif property_name == "frame":
            try:
                if new_value:
                    self.setFrameStyle(qt_import.QFrame.StyledPanel)
                else:
                    self.setFrameStyle(qt_import.QFrame.NoFrame)
            except BaseException:
                pass
            self.update()
        elif property_name == "fixedWidth":
            if new_value > -1:
                self.setFixedWidth(new_value)
        elif property_name == "fixedHeight":
            if new_value > -1:
                self.setFixedHeight(new_value)
        elif property_name == "hide":
            if new_value:
                self.setHidden(True)
            #else:
            #    self.setVisible(True)
        else:
            try:
                self.property_changed(property_name, old_value, new_value)
            except BaseException:
                logging.getLogger().exception(
                    "Error while setting property %s " % property_name +
                    "for %s (details in log file)." % str(self.objectName()))

    def property_changed(self, property_name, old_value, new_value):
        pass

    def set_expert_mode(self, expert):
        pass

    def enable_widget(self, state):
        if self.__failed_to_load_hwobj:
            state = False

        if state:
            self.setEnabled(True)
        else:
            self.setDisabled(True)

    def disable_widget(self, state):
        if self.__failed_to_load_hwobj:
            state = True

        if state:
            self.setDisabled(True)
        else:
            self.setEnabled(True)

    def get_window_display_widget(self):
        for widget in qt_import.QApplication.allWidgets():
            if hasattr(widget, "configuration"):
                return widget

    def set_background_color(self, color):
        colors.set_widget_color(self, color, qt_import.QPalette.Background)
コード例 #14
0
class EsrfConfigurationBrick(BaseWidget):

    operation_modes_edited = qt_import.pyqtSignal(list)
    operation_modes_saved = qt_import.pyqtSignal(list)
    data_policy_changed = qt_import.pyqtSignal(dict)

    def __init__(self, *args):

        BaseWidget.__init__(self, *args)

        # variables -----------------------------------------------------------

        self.list_of_operational_modes = []
        self.default_session = None

        self.multipos_file_xml_path = None
        self.bliss_session_list = None

        # Hardware objects ----------------------------------------------------
        self.multipos_hwobj = None

        # Internal values -----------------------------------------------------
        self.table_created = False

        # Properties ----------------------------------------------------------
        self.add_property("mnemonic", "string", "/multiple-positions")

        # Signals ------------------------------------------------------------

        self.define_signal("operation_modes_edited", ())
        self.define_signal("operation_modes_saved", ())
        self.define_signal("data_policy_changed", ())

        # Slots ---------------------------------------------------------------

        # Graphic elements ----------------------------------------------------
        self.main_groupbox = qt_import.QGroupBox("Beam Configuration", self)
        self.ui_widgets_manager = qt_import.load_ui_file(
            "esrf_id13_configuration_widget.ui")

        # Size policy --------------------------------
        self.ui_widgets_manager.configuration_table.setSizePolicy(
            qt_import.QSizePolicy.Minimum,
            qt_import.QSizePolicy.Minimum,
        )

        # Layout --------------------------------------------------------------
        _groupbox_vlayout = qt_import.QVBoxLayout(self)
        _groupbox_vlayout.addWidget(self.ui_widgets_manager)
        _groupbox_vlayout.setSpacing(0)
        _groupbox_vlayout.setContentsMargins(0, 0, 0, 0)
        self.main_groupbox.setLayout(_groupbox_vlayout)

        _main_vlayout = qt_import.QVBoxLayout(self)
        _main_vlayout.addWidget(self.main_groupbox)
        _main_vlayout.setSpacing(0)
        _main_vlayout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(_main_vlayout)

        # Qt signal/slot connections ------------------------------------------

        self.ui_widgets_manager.save_table_changes.clicked.connect(
            self.save_table_changes)

        self.ui_widgets_manager.cancel_table_changes.clicked.connect(
            self.cancel_table_changes)

        self.ui_widgets_manager.bliss_session_combo_box.currentIndexChanged.connect(
            self.display_data_policy)

        self.ui_widgets_manager.configuration_table.itemChanged.connect(
            self.configuration_table_item_changed)

        self.ui_widgets_manager.add_label_button.clicked.connect(
            self.add_op_mode_to_list)

        self.ui_widgets_manager.delete_label_button.clicked.connect(
            self.delete_op_mode_from_list)

        self.ui_widgets_manager.save_labels_button.clicked.connect(
            self.save_op_mode_list)

        self.ui_widgets_manager.label_list.itemSelectionChanged.connect(
            self.label_list_selection_changed)

        self.ui_widgets_manager.reload_data_policy_button.clicked.connect(
            self.reload_data_policy)

    def configuration_table_item_changed(self, item):

        validated_value = self.validate_cell_value(item.text())
        item.setText(str(validated_value))
        item.setBackground(qt_import.QColor(qt_import.Qt.yellow))

        # create new dict from new data
        table = self.ui_widgets_manager.configuration_table
        item_row = item.row()
        item_col = item.column()

        if item_col in (1, 2):
            who_changed = 0
        elif item_col in (3, 4):
            who_changed = 1
        else:
            who_changed = 2

        edited_key = table.item(item_row, 0).text()

        dict_elem = {}

        dict_elem["zoom_tag"] = edited_key
        dict_elem["beam_pos_x"] = int(
            self.validate_cell_value(table.item(item_row, 1).text()))
        dict_elem["beam_pos_y"] = int(
            self.validate_cell_value(table.item(item_row, 2).text()))

        resox = self.validate_cell_value(table.item(item_row, 3).text())
        dict_elem["cal_x"] = float(resox)

        resoy = self.validate_cell_value(table.item(item_row, 4).text())
        dict_elem["cal_y"] = float(resoy)

        dict_elem["light"] = int(
            self.validate_cell_value(table.item(item_row, 5).text()))
        dict_elem["zoom"] = int(
            self.validate_cell_value(table.item(item_row, 6).text()))

        self.multipos_hwobj.edit_data(dict_elem, edited_key, who_changed)

    def load_default_session(self):
        """
        Parse xml file and search for 'default_session' tag
        """
        xml_file_tree = cElementTree.parse(self.multipos_file_xml_path)
        xml_tree = xml_file_tree.getroot()
        if xml_tree.find("default_session") is not None:
            self.default_session = xml_tree.find("default_session").text

    def load_list_of_operational_modes(self):
        """
        Parse xml file and load list of operational modes :

        'tag0', 'tag1', ...
        """
        xml_file_tree = cElementTree.parse(self.multipos_file_xml_path)

        xml_tree = xml_file_tree.getroot()
        mode_list = []
        if xml_tree.find("operational_modes") is not None:
            mode_list = xml_tree.find("operational_modes").text
            self.list_of_operational_modes = eval(mode_list)
        else:
            #if no operational_mode, hide all related controls
            self.ui_widgets_manager.add_label_button.hide()
            self.ui_widgets_manager.delete_label_button.hide()
            self.ui_widgets_manager.label_list.hide()
            self.ui_widgets_manager.label_3.hide()
            self.ui_widgets_manager.new_label_edit.hide()
            self.ui_widgets_manager.save_labels_button.hide()

    def property_changed(self, property_name, old_value, new_value):

        if property_name == "mnemonic":
            if self.multipos_hwobj is not None:
                # disconnect signal/slots
                self.disconnect(self.multipos_hwobj,
                                "beam_pos_cal_data_changed",
                                self.beam_pos_cal_data_changed)
                self.disconnect(self.multipos_hwobj, "beam_pos_cal_data_saved",
                                self.beam_cal_pos_data_saved)
                self.disconnect(self.multipos_hwobj,
                                "beam_pos_cal_data_cancelled",
                                self.beam_cal_pos_data_cancelled)
                pass

            if new_value is not None:
                self.multipos_hwobj = self.get_hardware_object(new_value)

            #search xml file so it handles the 'tags'
            # TODO : create a separate xml file for tags!!

            if new_value.startswith("/"):
                new_value = new_value[1:]

            self.multipos_file_xml_path = os.path.join(
                HWR.getHardwareRepositoryConfigPath(), new_value + ".xml")

            if self.multipos_hwobj is not None:
                self.connect(self.multipos_hwobj, "beam_pos_cal_data_changed",
                             self.beam_pos_cal_data_changed)
                self.connect(self.multipos_hwobj, "beam_pos_cal_data_saved",
                             self.beam_cal_pos_data_saved)
                self.connect(self.multipos_hwobj,
                             "beam_pos_cal_data_cancelled",
                             self.beam_cal_pos_data_cancelled)
            # self.load_zoom_positions_dict()
            self.load_list_of_operational_modes()
            self.load_default_session()

            self.init_interface()

        else:
            BaseWidget.property_changed(self, property_name, old_value,
                                        new_value)

    def beam_pos_cal_data_changed(self, who_changed, new_data_dict):
        self.fill_config_table()

        if new_data_dict:
            current_pos_name = new_data_dict["zoom_tag"]
        else:
            current_pos_name = self.multipos_hwobj.get_value()

        table = self.ui_widgets_manager.configuration_table

        self.ui_widgets_manager.configuration_table.itemChanged.disconnect(
            self.configuration_table_item_changed)

        for row_index in range(table.rowCount()):
            if table.item(row_index, 0).text() == current_pos_name:
                if who_changed == 0:
                    table.item(row_index, 1).setBackground(
                        qt_import.QColor(qt_import.Qt.yellow))
                    table.item(row_index, 2).setBackground(
                        qt_import.QColor(qt_import.Qt.yellow))
                elif who_changed == 1:
                    table.item(row_index, 3).setBackground(
                        qt_import.QColor(qt_import.Qt.yellow))
                    table.item(row_index, 4).setBackground(
                        qt_import.QColor(qt_import.Qt.yellow))

        self.ui_widgets_manager.configuration_table.itemChanged.connect(
            self.configuration_table_item_changed)

    def fill_op_modes_list(self):
        if self.list_of_operational_modes is not None:
            self.ui_widgets_manager.label_list.clear()

            for tag_text in self.list_of_operational_modes:
                self.ui_widgets_manager.label_list.addItem(tag_text)

    def fill_config_table(self):
        tmp_dict = self.multipos_hwobj.get_positions()
        if tmp_dict is not None:

            self.ui_widgets_manager.configuration_table.itemChanged.disconnect(
                self.configuration_table_item_changed)

            if not self.table_created:
                # create table items for first and only time

                self.ui_widgets_manager.configuration_table.setRowCount(
                    len(tmp_dict))

                for row in range(len(tmp_dict)):
                    for col in range(7):
                        tmp_item = qt_import.QTableWidgetItem()
                        if col == 0:
                            #zoom position name not editable
                            tmp_item.setFlags(tmp_item.flags()
                                              ^ qt_import.Qt.ItemIsEditable)
                        self.ui_widgets_manager.configuration_table.setItem(
                            row, col, tmp_item)
                self.table_created = True

            table = self.ui_widgets_manager.configuration_table
            for i, (position,
                    position_dict_elem) in enumerate(tmp_dict.items()):

                table.item(i, 0).setText(str(position))

                table.item(i, 1).setText(str(position_dict_elem["beam_pos_x"]))
                table.item(i, 2).setText(str(position_dict_elem["beam_pos_y"]))

                if position_dict_elem["cal_x"] == 1:
                    y_calib = "Not defined"
                else:
                    y_calib = str(abs(int(position_dict_elem["cal_x"])))
                if position_dict_elem["cal_y"] == 1:
                    z_calib = "Not defined"
                else:
                    z_calib = str(abs(int(position_dict_elem["cal_y"])))

                table.item(i, 3).setText(y_calib)
                table.item(i, 4).setText(z_calib)

                table.item(i, 5).setText(str(position_dict_elem['light']))
                table.item(i, 6).setText(str(position_dict_elem['zoom']))

            self.ui_widgets_manager.configuration_table.itemChanged.connect(
                self.configuration_table_item_changed)

            self.ui_widgets_manager.configuration_table.horizontalHeader(
            ).setSectionResizeMode(qt_import.QHeaderView.ResizeToContents)

    def beam_cal_pos_data_saved(self):
        """
        data saved: clean cell background
        """
        self.clean_cells_background()

    def beam_cal_pos_data_cancelled(self):
        """
        data cancelled:
        clean cell background
        reload data from hardware object
        """
        self.fill_config_table()
        self.clean_cells_background()

    def init_interface(self):
        """
        Fill table and combobox and make them functional
        """
        if self.multipos_hwobj is not None:
            self.fill_config_table()
            self.fill_op_modes_list()
            self.load_sessions()
            self.reload_data_policy()

    def load_sessions(self):
        """
        Load list of sessions and populate combobox
        """
        self.bliss_session_list = get_sessions_list()
        self.ui_widgets_manager.bliss_session_combo_box.clear()

        self.ui_widgets_manager.bliss_session_combo_box.currentIndexChanged.disconnect(
            self.display_data_policy)

        for session in self.bliss_session_list:
            self.ui_widgets_manager.bliss_session_combo_box.addItem(session)

        if self.default_session in self.bliss_session_list:
            index = self.ui_widgets_manager.bliss_session_combo_box.findText(
                self.default_session)
            if index != -1:
                self.ui_widgets_manager.bliss_session_combo_box.setCurrentIndex(
                    index)
        else:
            self.ui_widgets_manager.bliss_session_combo_box.setCurrentIndex(-1)

        self.ui_widgets_manager.bliss_session_combo_box.currentIndexChanged.connect(
            self.display_data_policy)

    def reload_data_policy(self):

        self.display_data_policy(
            self.ui_widgets_manager.bliss_session_combo_box.currentIndex())

    def display_data_policy(self, index):
        """
        Display data policy of selected session in combobox
        """

        if index > -1:
            new_session = self.bliss_session_list[index]

            scan_savings = ESRFScanSaving(new_session)

            session_info_string = ''
            session_info_dict = {}
            session_info_dict['session'] = new_session
            session_info_dict['base_path'] = scan_savings.base_path
            session_info_dict['data_filename'] = scan_savings.data_filename
            session_info_dict['data_path'] = scan_savings.data_path
            session_info_dict['dataset'] = scan_savings.dataset
            session_info_dict['date'] = scan_savings.date
            session_info_dict['sample'] = scan_savings.sample
            session_info_dict['proposal'] = scan_savings.proposal
            session_info_dict['template'] = scan_savings.template
            session_info_dict['beamline'] = scan_savings.beamline

            # waiting to https://gitlab.esrf.fr/bliss/bliss/-/merge_requests/2948
            # be part of current BLISS version
            #session_info_dict['filename'] = scan_savings.filename
            #session_info_dict['data_fullpath'] = scan_savings.data_fullpath
            for key, val in session_info_dict.items():

                info_str = ' ' + key + ' : ' + val
                session_info_string += info_str + ' \n'

            self.data_policy_changed.emit(session_info_dict)
            self.ui_widgets_manager.data_policy_label.setText(
                session_info_string)

    def save_op_mode_list(self):
        """
        Save data to xml file
        Clean cell background
        """
        xml_file_tree = cElementTree.parse(self.multipos_file_xml_path)
        xml_tree = xml_file_tree.getroot()

        xml_tree.find("operational_modes").text = str(
            self.list_of_operational_modes)

        xml_file_tree.write(self.multipos_file_xml_path)

        self.operation_modes_saved.emit(self.list_of_operational_modes)

    def add_op_mode_to_list(self):
        """
        add lable list to list
        and to self.list_of_operational_modes
        Data not saved yet
        """
        new_label_list_full = self.ui_widgets_manager.new_label_edit.text(
        ).strip()
        new_label_list = new_label_list_full.split()

        if not new_label_list:
            return
        # check if label already exist
        for new_label in new_label_list:
            if new_label not in self.list_of_operational_modes:
                self.list_of_operational_modes.append(new_label)
                self.ui_widgets_manager.label_list.addItem(new_label)
                #select newly added item
                self.ui_widgets_manager.label_list.setCurrentRow(
                    self.ui_widgets_manager.label_list.count() - 1)

        self.operation_modes_edited.emit(self.list_of_operational_modes)

    def delete_op_mode_from_list(self):
        """
        delete lable from list
        detele from self.list_of_operational_modes
        changes not saved yet
        """
        label_to_delete_list_full = self.ui_widgets_manager.new_label_edit.text(
        ).strip()
        label_to_delete_list = label_to_delete_list_full.split()

        if not label_to_delete_list:
            return
        for label_to_delete in label_to_delete_list:
            if label_to_delete not in self.list_of_operational_modes:
                continue
            index = self.list_of_operational_modes.index(label_to_delete)
            self.ui_widgets_manager.label_list.takeItem(index)
            self.list_of_operational_modes.remove(label_to_delete)
            #select first item
        if self.list_of_operational_modes:
            self.ui_widgets_manager.label_list.setCurrentRow(0)
        self.operation_modes_edited.emit(self.list_of_operational_modes)

    def label_list_selection_changed(self):
        selected_label_list = self.ui_widgets_manager.label_list.selectedItems(
        )

        label_text_list = []
        for label in selected_label_list:
            label_text_list.append(label.text())
        self.ui_widgets_manager.new_label_edit.setText(
            ' '.join(label_text_list))

    def clean_cells_background(self):
        """
        clean cells background color
        """
        table = self.ui_widgets_manager.configuration_table

        table.itemChanged.disconnect(self.configuration_table_item_changed)

        for row in range(table.rowCount()):
            for col in range(table.columnCount()):
                table.item(row, col).setData(qt_import.Qt.BackgroundRole, None)

        table.itemChanged.connect(self.configuration_table_item_changed)

    def save_table_changes(self):
        """
        send signal to self.multipos_hwobj to save data to file
        clean cells background color
        """
        if self.multipos_hwobj is not None:
            self.multipos_hwobj.save_data_to_file(self.multipos_file_xml_path)

    def validate_cell_value(self, input_val):
        """
        return value adapted according to input
        """
        try:
            output = int(input_val)
        except ValueError:
            output = 1

        return output

    def cancel_table_changes(self):
        """
        cancel any change in config table.
        reload data from last saved version of xml file:
            recover data from multipos_hwobj and display it
        """
        self.multipos_hwobj.cancel_edited_data()

        self.fill_config_table()
        self.clean_cells_background()

    def clear_table(self):
        """
        clean table of contents. keep headers
        """
        self.ui_widgets_manager.configuration_table.clearContents()

    def from_text_to_int(self, input_str, factor=1):
        if input_str is None:
            return 0
        return abs(int(float(input_str) * factor))

    def from_text_to_float(self, input_str, factor=1):
        if input_str is None:
            return 0
        return abs((float(input_str) * factor))
コード例 #15
0
ファイル: acquisition_widget.py プロジェクト: rhfogh/mxcube
class AcquisitionWidget(qt_import.QWidget):

    acqParametersChangedSignal = qt_import.pyqtSignal(list)
    madEnergySelectedSignal = qt_import.pyqtSignal(str, float, bool)

    def __init__(
        self,
        parent=None,
        name=None,
        fl=0,
        acq_params=None,
        path_template=None,
        layout="horizontal",
    ):

        qt_import.QWidget.__init__(self, parent, qt_import.Qt.WindowFlags(fl))

        if name is not None:
            self.setObjectName(name)

        # Hardware objects ----------------------------------------------------

        # Internal variables --------------------------------------------------
        self.previous_energy = 0

        # If the acq. widget is used with grids then total osc range is not
        # equal to num_images * osc_range, but num_images_per_line * osc_range
        # For grids the osc total range is updated when a grid is selected

        self.grid_mode = False

        # Properties ----------------------------------------------------------

        # Signals -------------------------------------------------------------

        # Slots ---------------------------------------------------------------

        # Graphic elements ----------------------------------------------------
        if acq_params is None:
            self._acquisition_parameters = queue_model_objects.AcquisitionParameters()
        else:
            self._acquisition_parameters = acq_params

        if path_template is None:
            self._path_template = queue_model_objects.PathTemplate()
        else:
            self._path_template = path_template

        self._acquisition_mib = DataModelInputBinder(self._acquisition_parameters)

        if layout == "horizontal":
            self.acq_widget_layout = qt_import.load_ui_file(
                "acquisition_widget_horizontal_layout.ui"
            )
            self.use_osc_start(False)
        else:
            self.acq_widget_layout = qt_import.load_ui_file(
                "acquisition_widget_vertical_layout.ui"
            )

        # Layout --------------------------------------------------------------
        __main_vlayout = qt_import.QVBoxLayout(self)
        __main_vlayout.addWidget(self.acq_widget_layout)
        __main_vlayout.setSpacing(0)
        __main_vlayout.setContentsMargins(0, 0, 0, 0)

        # SizePolicies --------------------------------------------------------

        # Qt signal/slot connections ------------------------------------------
        self.acq_widget_layout.osc_start_cbox.stateChanged.connect(self.fix_osc_start)
        self.acq_widget_layout.exp_time_ledit.textChanged.connect(
            self.exposure_time_ledit_changed
        )
        self.acq_widget_layout.exp_time_total_ledit.textEdited.connect(
            self.exp_time_total_ledit_changed
        )
        self.acq_widget_layout.first_image_ledit.textChanged.connect(
            self.first_image_ledit_change
        )
        self.acq_widget_layout.num_images_ledit.textChanged.connect(
            self.num_images_ledit_change
        )
        self.acq_widget_layout.detector_roi_mode_combo.activated.connect(
            self.detector_roi_mode_changed
        )
        self.acq_widget_layout.energies_combo.activated.connect(self.energy_selected)
        self.acq_widget_layout.mad_cbox.toggled.connect(self.use_mad)
        self.acq_widget_layout.osc_start_ledit.textEdited.connect(
            self.osc_start_ledit_changed
        )
        self.acq_widget_layout.osc_range_ledit.textEdited.connect(
            self.osc_range_per_frame_ledit_changed
        )
        self.acq_widget_layout.osc_total_range_ledit.textEdited.connect(
            self.osc_total_range_ledit_changed
        )
        self.acq_widget_layout.energy_ledit.textEdited.connect(
            self.energy_ledit_changed
        )
        self.acq_widget_layout.transmission_ledit.textEdited.connect(
            self.transmission_ledit_changed
        )
        self.acq_widget_layout.resolution_ledit.textEdited.connect(
            self.resolution_ledit_changed
        )
        self.acq_widget_layout.kappa_ledit.textEdited.connect(self.kappa_ledit_changed)
        self.acq_widget_layout.kappa_phi_ledit.textEdited.connect(
            self.kappa_phi_ledit_changed
        )

        if self.acq_widget_layout.findChild(qt_import.QLineEdit, "overlap_ledit"):
            self.acq_widget_layout.overlap_ledit.textChanged.connect(
                self.overlap_changed
            )
        if self.acq_widget_layout.findChild(qt_import.QCheckBox, "max_osc_range_cbx"):
            self.acq_widget_layout.max_osc_range_cbx.toggled.connect(
                self.max_osc_range_toggled
            )

        # Other ---------------------------------------------------------------
        self.value_changed_list = []

        self.acq_widget_layout.energies_combo.setDisabled(True)
        self.acq_widget_layout.energies_combo.addItems(
            ["ip: -", "pk: -", "rm1: -", "rm2: -"]
        )

        self.osc_start_validator = qt_import.QDoubleValidator(
            -10000, 10000, 4, self.acq_widget_layout.osc_start_ledit
        )
        self.osc_range_per_frame_validator = qt_import.QDoubleValidator(
            0, 10000, 4, self.acq_widget_layout.osc_range_ledit
        )
        self.osc_total_range_validator = qt_import.QDoubleValidator(
            0, 10000, 4, self.acq_widget_layout.osc_total_range_ledit
        )
        self.kappa_validator = qt_import.QDoubleValidator(
            -0.01, 360, 4, self.acq_widget_layout.kappa_ledit
        )
        self.kappa_phi_validator = qt_import.QDoubleValidator(
            -360, 360, 4, self.acq_widget_layout.kappa_phi_ledit
        )
        self.energy_validator = qt_import.QDoubleValidator(
            4, 25, 5, self.acq_widget_layout.energy_ledit
        )
        self.resolution_validator = qt_import.QDoubleValidator(
            0, 15, 3, self.acq_widget_layout.resolution_ledit
        )
        self.transmission_validator = qt_import.QDoubleValidator(
            0, 100, 3, self.acq_widget_layout.transmission_ledit
        )
        self.exp_time_validator = qt_import.QDoubleValidator(
            0.0001, 10000, 7, self.acq_widget_layout.exp_time_ledit
        )
        self.first_img_validator = qt_import.QIntValidator(
            0, 99999, self.acq_widget_layout.first_image_ledit
        )
        self.num_img_validator = qt_import.QIntValidator(
            1, 9999999, self.acq_widget_layout.num_images_ledit
        )
        self.acq_widget_layout.detector_roi_mode_label.setEnabled(False)
        self.acq_widget_layout.detector_roi_mode_combo.setEnabled(False)

        self.init_limits()

    def use_max_osc_range(self, state):
        self.acq_widget_layout.max_osc_range_cbx.setEnabled(state)

    def fix_osc_start(self, state):
        """
        Fix osc start, so the lineEdit do not change when osc is changed
        """
        self.acq_widget_layout.osc_start_ledit.setEnabled(state)

    def update_osc_start(self, new_value):
        """
        Updates osc line edit
        """
        if (
            "osc_start" not in self.value_changed_list
            and not self.acq_widget_layout.osc_start_ledit.hasFocus()
            and not self.acq_widget_layout.osc_start_cbox.isChecked()
        ):
            osc_start_value = 0
            try:
                osc_start_value = round(float(new_value), 2)
            except TypeError:
                pass

            self.acq_widget_layout.osc_start_ledit.setText(str(osc_start_value))
            self._acquisition_parameters.osc_start = osc_start_value

            # self.update_osc_total_range_limits()
            # self.update_num_images_limits()

    def osc_start_ledit_changed(self, osc_start):
        """Fixes osc start edit"""
        if "osc_start" not in self.value_changed_list:
            self.value_changed_list.append("osc_start")
        self.update_osc_total_range_limits()
        self.update_num_images_limits()
        self.emit_acq_parameters_changed()

    def update_osc_start_limits(self):
        """In the plate mode sets osc start limits"""
        self.update_osc_total_range_limits()
        self.update_num_images_limits()

    def osc_range_per_frame_ledit_changed(self, new_value):
        self.update_osc_total_range()
        self.update_num_images_limits()
        self.update_exp_time_limits()
        self.emit_acq_parameters_changed()

    def update_osc_range_per_frame_limits(self):
        try:
            max_osc_speed = HWR.beamline.diffractometer.get_osc_max_speed()
            top_limit = max_osc_speed * float(
                self.acq_widget_layout.exp_time_ledit.text()
            )
            self.osc_range_per_frame_validator.setTop(top_limit)
            tool_tip = (
                "Oscillation range per frame limits 0 : "
                + "%0.4f\n4 digits precision." % top_limit
            )

            self.acq_widget_layout.osc_range_ledit.setToolTip(tool_tip)
            self._acquisition_mib.validate_all()
        except BaseException:
            pass

    def update_osc_total_range(self):
        self.acq_widget_layout.osc_total_range_ledit.blockSignals(True)

        if not self.grid_mode:
            try:
                self.acq_widget_layout.osc_total_range_ledit.setText(
                    "%0.2f" %
                    (
                        float(self.acq_widget_layout.osc_range_ledit.text())
                        * int(self.acq_widget_layout.num_images_ledit.text())
                    )
                )
            except BaseException:
                pass
        self.acq_widget_layout.osc_total_range_ledit.blockSignals(False)

    def update_total_exp_time(self):
        try:
            self.acq_widget_layout.exp_time_total_ledit.setText(
                "%.2f"
                % (
                    float(self.acq_widget_layout.exp_time_ledit.text())
                    * float(self.acq_widget_layout.num_images_ledit.text())
                )
            )
        except BaseException:
            pass

    def osc_total_range_ledit_changed(self, new_value):
        if not self.grid_mode:
            try:
                num_images = int(
                    float(new_value)
                    / float(self.acq_widget_layout.osc_range_ledit.text())
                )
                self.acq_widget_layout.num_images_ledit.blockSignals(True)
                self.acq_widget_layout.num_images_ledit.setText("%d" % num_images)
                self._acquisition_parameters.num_images = num_images
                self.acq_widget_layout.num_images_ledit.blockSignals(False)
            except BaseException:
                pass
            self.emit_acq_parameters_changed()

    def exp_time_total_ledit_changed(self, new_value):
        try:
            exp_time = float(new_value)  / float(self.acq_widget_layout.num_images_ledit.text())
            self.acq_widget_layout.exp_time_ledit.blockSignals(True)
            self.acq_widget_layout.exp_time_ledit.setText("%.4f" % exp_time)
            self._acquisition_parameters.exp_time = exp_time
            self.acq_widget_layout.exp_time_ledit.blockSignals(False)
        except BaseException:
            pass
        self.emit_acq_parameters_changed()

    def update_osc_total_range_limits(self, num_images=None):
        """Updates osc totol range. Limits are changed if a plate is used.
           - For simple oscillation osc_range is defined by osc_start and
             osc_start top limit.
           - For mesh osc_range is defined by number of images per line
             and osc in the middle of mesh
        """
        if HWR.beamline.diffractometer.in_plate_mode():
            if hasattr(self.parent(), "set_osc_total_range"):
                self.parent().set_osc_total_range(num_images)
                self._acquisition_mib.validate_all()

    def update_exp_time_limits(self):
        try:
            exp_time_limits = (
                HWR.beamline.detector.get_exposure_time_limits()
            )
            max_osc_speed = HWR.beamline.diffractometer.get_osc_max_speed()
            top_limit = (
                float(self.acq_widget_layout.osc_range_ledit.text()) / max_osc_speed
            )
            limits = (max(exp_time_limits[0], top_limit), exp_time_limits[1])

            self.update_detector_exp_time_limits(limits)
        except BaseException:
            pass

    def update_kappa(self, new_value):
        if not self.acq_widget_layout.kappa_ledit.hasFocus() and new_value is not None:
            self.acq_widget_layout.kappa_ledit.setText(str(new_value))
            self.emit_acq_parameters_changed()

    def update_kappa_phi(self, new_value):
        if not self.acq_widget_layout.kappa_phi_ledit.hasFocus() and new_value:
            self.acq_widget_layout.kappa_phi_ledit.setText(str(new_value))
            self.emit_acq_parameters_changed()

    def use_osc_start(self, state):
        self.acq_widget_layout.osc_start_cbox.setVisible(state)
        self.acq_widget_layout.osc_start_label.setVisible(not state)
        self.acq_widget_layout.osc_start_ledit.setEnabled(not state)

    def use_kappa(self, state):
        if HWR.beamline.diffractometer is not None:
            if HWR.beamline.diffractometer.in_plate_mode():
                state = False
        self.acq_widget_layout.kappa_label.setEnabled(state)
        self.acq_widget_layout.kappa_ledit.setEnabled(state)
        self.acq_widget_layout.kappa_phi_label.setEnabled(state)
        self.acq_widget_layout.kappa_phi_ledit.setEnabled(state)

    def init_limits(self):
        limits_dict = HWR.beamline.acquisition_limit_values

        tpl = limits_dict.get("osc_range")
        if tpl:
            self.osc_start_validator.setRange(tpl[0], tpl[1], 4)
            self.osc_range_per_frame_validator.setRange(tpl[0], tpl[1], 4)
            self.osc_total_range_validator.setRange(tpl[0], tpl[1], 4)

        self._acquisition_mib.bind_value_update(
            "osc_start",
            self.acq_widget_layout.osc_start_ledit,
            float,
            self.osc_start_validator,
        )

        self._acquisition_mib.bind_value_update(
            "osc_range",
            self.acq_widget_layout.osc_range_ledit,
            float,
            self.osc_range_per_frame_validator,
        )

        self._acquisition_mib.bind_value_update(
            "osc_total_range",
            self.acq_widget_layout.osc_total_range_ledit,
            float,
            self.osc_total_range_validator,
        )

        tpl = limits_dict.get("kappa")
        if tpl:
            self.kappa_validator.setRange(tpl[0], tpl[1], 4)
        self._acquisition_mib.bind_value_update(
            "kappa", self.acq_widget_layout.kappa_ledit, float, self.kappa_validator
        )

        tpl = limits_dict.get("kappa_phi")
        if tpl:
            self.kappa_phi_validator.setRange(tpl[0], tpl[1], 4)
        self._acquisition_mib.bind_value_update(
            "kappa_phi",
            self.acq_widget_layout.kappa_phi_ledit,
            float,
            self.kappa_phi_validator,
        )

        tpl = limits_dict.get("exposure_time")
        if tpl:
            self.exp_time_validator.setRange(tpl[0], tpl[1], 6)

        self._acquisition_mib.bind_value_update(
            "exp_time",
            self.acq_widget_layout.exp_time_ledit,
            float,
            self.exp_time_validator,
        )

        tpl = limits_dict.get("number_of_images")
        if tpl:
            self.num_img_validator.setRange(tpl[0], tpl[1])
            self.first_img_validator.setRange(tpl[0], tpl[1])

        self._acquisition_mib.bind_value_update(
            "first_image",
            self.acq_widget_layout.first_image_ledit,
            int,
            self.first_img_validator,
        )

        self._acquisition_mib.bind_value_update(
            "num_images",
            self.acq_widget_layout.num_images_ledit,
            int,
            self.num_img_validator,
        )

        num_passes = self.acq_widget_layout.findChild(
            qt_import.QLineEdit, "num_passes_ledit"
        )

        if num_passes:
            self._acquisition_mib.bind_value_update(
                "num_passes", num_passes, int, qt_import.QIntValidator(1, 1000, self)
            )

        overlap_ledit = self.acq_widget_layout.findChild(
            qt_import.QLineEdit, "overlap_ledit"
        )

        if overlap_ledit:
            self._acquisition_mib.bind_value_update(
                "overlap",
                overlap_ledit,
                float,
                qt_import.QDoubleValidator(-1000, 1000, 2, self),
            )

        self._acquisition_mib.bind_value_update(
            "energy", self.acq_widget_layout.energy_ledit, float, self.energy_validator
        )
        self.update_energy_limits(
            (self.energy_validator.bottom(), self.energy_validator.top())
        )

        self._acquisition_mib.bind_value_update(
            "transmission",
            self.acq_widget_layout.transmission_ledit,
            float,
            self.transmission_validator,
        )
        self.update_transmission_limits(
            (self.transmission_validator.bottom(), self.transmission_validator.top())
        )

        self._acquisition_mib.bind_value_update(
            "resolution",
            self.acq_widget_layout.resolution_ledit,
            float,
            self.resolution_validator,
        )
        # self.update_resolution_limits((self.resolution_validator.bottom(),
        #                               self.resolution_validator.top()))

        self._acquisition_mib.bind_value_update(
            "shutterless", self.acq_widget_layout.shutterless_cbx, bool, None
        )

        self.set_tunable_energy(HWR.beamline.tunable_wavelength)

        has_shutter_less = HWR.beamline.detector.has_shutterless()
        self.acq_widget_layout.shutterless_cbx.setEnabled(has_shutter_less)
        self.acq_widget_layout.shutterless_cbx.setChecked(has_shutter_less)

        if HWR.beamline.disable_num_passes:
            num_passes = self.acq_widget_layout.findChild(
                qt_import.QLineEdit, "num_passes_ledit"
            )
            if num_passes:
                num_passes.setDisabled(True)

        self.init_detector_roi_modes()

    def first_image_ledit_change(self, new_value):
        self.emit_acq_parameters_changed()

    def exposure_time_ledit_changed(self, new_value):
        """If the exposure time changes we have to check the osc speed
           and if necessary update osc range per frame
        """
        self.update_osc_range_per_frame_limits()
        self.update_osc_total_range_limits()
        self.update_total_exp_time()
        self.emit_acq_parameters_changed()

    def num_images_ledit_change(self, new_value):
        if str(new_value).isdigit():
            # self._path_template.num_files = int(new_value)
            self.update_osc_range_per_frame_limits()
            self.update_osc_total_range_limits()
            self.update_osc_total_range()
            self.update_total_exp_time()
        self.emit_acq_parameters_changed()

    def overlap_changed(self, new_value):

        if HWR.beamline.detector.has_shutterless():
            try:
                new_value = float(new_value)
            except ValueError:
                pass

            if new_value != 0:
                self.acq_widget_layout.shutterless_cbx.setEnabled(False)
                self.acq_widget_layout.shutterless_cbx.setChecked(False)
                self._acquisition_parameters.shutterless = False
            else:
                self.acq_widget_layout.shutterless_cbx.setEnabled(True)
                self.acq_widget_layout.shutterless_cbx.setChecked(True)
                self._acquisition_parameters.shutterless = True

    def use_mad(self, state):
        self.acq_widget_layout.energies_combo.setEnabled(state)
        if state:
            (name, energy) = self.get_mad_energy()

            if energy != 0:
                self.update_energy(energy)
            self.madEnergySelectedSignal.emit(name, energy, state)
        else:
            self.update_energy(self.previous_energy)
            # energy = HWR.beamline.energy.get_current_energy()
            self.madEnergySelectedSignal.emit("", self.previous_energy, state)

    def max_osc_range_toggled(self, state):
        self.update_osc_total_range_limits()

    def get_mad_energy(self):
        energy_str = str(self.acq_widget_layout.energies_combo.currentText())
        (name, value) = energy_str.split(":")

        name = name.strip()
        value = value.strip()
        value = 0 if (value == "-") else float(value)

        return (name, value)

    def set_energies(self, energy_scan_result):
        self.acq_widget_layout.energies_combo.clear()

        inflection = (
            ("ip: %.4f" % energy_scan_result.inflection)
            if energy_scan_result.inflection
            else "ip: -"
        )

        peak = (
            ("pk: %.4f" % energy_scan_result.peak)
            if energy_scan_result.peak
            else "pk: -"
        )

        first_remote = (
            ("rm1: %.4f" % energy_scan_result.first_remote)
            if energy_scan_result.first_remote
            else "rm1: -"
        )

        second_remote = (
            ("rm2: %.4f" % energy_scan_result.second_remote)
            if energy_scan_result.second_remote
            else "rm2: -"
        )

        self.acq_widget_layout.energies_combo.addItems(
            [inflection, peak, first_remote, second_remote]
        )

    def energy_selected(self, index):
        if self.acq_widget_layout.mad_cbox.isChecked():
            (name, energy) = self.get_mad_energy()
            if energy != 0:
                self.update_energy(energy)

            self.madEnergySelectedSignal.emit(name, energy, True)

    def energy_ledit_changed(self, new_value):
        if "energy" not in self.value_changed_list:
            self.value_changed_list.append("energy")
        self.emit_acq_parameters_changed()

    def update_energy(self, energy):
        if (
            "energy" not in self.value_changed_list
            and not self.acq_widget_layout.energy_ledit.hasFocus()
        ):
            self.acq_widget_layout.energy_ledit.setText(str(energy))
        self.emit_acq_parameters_changed()

    def transmission_ledit_changed(self, transmission):
        if "transmission" not in self.value_changed_list:
            self.value_changed_list.append("transmission")
        self.emit_acq_parameters_changed()

    def update_transmission(self, transmission):
        if "transmission" not in self.value_changed_list:
            self.acq_widget_layout.transmission_ledit.setText(str(transmission))
        self.emit_acq_parameters_changed()

    def resolution_ledit_changed(self, resolution):
        if "resolution" not in self.value_changed_list:
            self.value_changed_list.append("resolution")
        self.emit_acq_parameters_changed()

    def update_resolution(self, resolution):
        if (
            "resolution" not in self.value_changed_list
            and not self.acq_widget_layout.resolution_ledit.hasFocus()
        ):
            self.acq_widget_layout.resolution_ledit.setText(str(resolution))
        self.emit_acq_parameters_changed()

    def update_energy_limits(self, limits):
        if limits:
            self.energy_validator.setBottom(limits[0])
            self.energy_validator.setTop(limits[1])
            self.acq_widget_layout.energy_ledit.setToolTip(
                "Energy limits %0.4f : %0.4f keV\n" % (limits[0], limits[1])
                + "4 digits precision."
            )
            self._acquisition_mib.validate_all()

    def update_transmission_limits(self, limits):
        if limits:
            self.transmission_validator.setBottom(limits[0])
            self.transmission_validator.setTop(limits[1])
            self.acq_widget_layout.transmission_ledit.setToolTip(
                "Transmission limits %0.2f : %0.2f %%\n" % (limits[0], limits[1])
                + "2 digits precision."
            )
            self._acquisition_mib.validate_all()

    def update_resolution_limits(self, limits):
        if limits:
            self.resolution_validator.setBottom(limits[0])
            self.resolution_validator.setTop(limits[1])
            self.acq_widget_layout.resolution_ledit.setToolTip(
                "Resolution limits %0.4f : %0.4f %s\n"
                % (limits[0], limits[1], chr(197))
                + "4 digits precision."
            )
            self._acquisition_mib.validate_all()

    def update_detector_exp_time_limits(self, limits):
        if limits:
            self.exp_time_validator.setRange(limits[0], limits[1], 6)
            self.acq_widget_layout.exp_time_ledit.setToolTip(
                "Exposure time limits %0.6f s : %0.1f s\n" % (limits[0], limits[1])
                + "6 digits precision."
            )
            self._acquisition_mib.validate_all()

    def update_num_images_limits(self, num_images_limits=None):
        """Updates number of images limit. Method used if plate mode.
        """

        self._acquisition_mib.validate_all()

        return
        if HWR.beamline.diffractometer.in_plate_mode():
            if num_images_limits is None:
                try:
                    osc_start = float(self.acq_widget_layout.osc_start_ledit.text())
                    osc_range = float(self.acq_widget_layout.osc_range_ledit.text())
                except ValueError:
                    return

                if osc_range == 0:
                    return

                num_images_limits = int(
                    (self.osc_start_validator.top() - osc_start) / osc_range
                )

            self.num_img_validator.setTop(num_images_limits)
            self.acq_widget_layout.num_images_ledit.setToolTip(
                "Number of images limits : %d" % num_images_limits
            )
            self._acquisition_mib.validate_all()

    def init_detector_roi_modes(self):
        roi_modes = HWR.beamline.detector.get_roi_modes()
        if (
            len(roi_modes) > 0
            and self.acq_widget_layout.detector_roi_mode_combo.count() == 0
        ):
            for roi_mode in roi_modes:
                self.acq_widget_layout.detector_roi_mode_combo.addItem(roi_mode)
            self.acq_widget_layout.detector_roi_mode_label.setEnabled(True)
            self.acq_widget_layout.detector_roi_mode_combo.setEnabled(True)

    def update_detector_roi_mode(self, roi_mode_index):
        if (
            roi_mode_index is not None
            and self.acq_widget_layout.detector_roi_mode_combo.count() > 0
        ):
            self.acq_widget_layout.detector_roi_mode_combo.setCurrentIndex(
                roi_mode_index
            )

    def detector_roi_mode_changed(self, roi_mode_index):
        HWR.beamline.detector.set_roi_mode(roi_mode_index)

    def kappa_ledit_changed(self, new_value):
        if "kappa" not in self.value_changed_list:
            self.value_changed_list.append("kappa")
        self.emit_acq_parameters_changed()

    def kappa_phi_ledit_changed(self, new_value):
        if "kappa_phi" not in self.value_changed_list:
            self.value_changed_list.append("kappa_phi")
        self.emit_acq_parameters_changed()

    def update_data_model(self, acquisition_parameters, path_template):
        self._acquisition_parameters = acquisition_parameters
        self._path_template = path_template
        self._acquisition_mib.set_model(acquisition_parameters)

        # Update mad widgets
        mad = True if self._path_template.mad_prefix != "" else False
        if mad:
            mad_prefix = str(self._path_template.mad_prefix)
            index = MAD_ENERGY_COMBO_NAMES[str(mad_prefix)]
            self.acq_widget_layout.energies_combo.setCurrentIndex(index)
            self.acq_widget_layout.mad_cbox.setChecked(True)
            self.acq_widget_layout.energies_combo.setEnabled(True)
        else:
            self.acq_widget_layout.mad_cbox.setChecked(False)
            self.acq_widget_layout.energies_combo.setEnabled(False)
            self.acq_widget_layout.energies_combo.setCurrentIndex(0)

        self.update_osc_total_range()
        self.update_total_exp_time()

        self.emit_acq_parameters_changed()

    def set_tunable_energy(self, state):
        self.acq_widget_layout.energy_ledit.setEnabled(state)
        self.acq_widget_layout.mad_cbox.setEnabled(state)
        self.acq_widget_layout.energies_combo.setEnabled(state)

    def check_parameter_conflict(self):
        return self._acquisition_mib.validate_all()

    def emit_acq_parameters_changed(self):
        self.acqParametersChangedSignal.emit(self._acquisition_mib.validate_all())
コード例 #16
0
class ConfirmDialog(qt_import.QDialog):

    continueClickedSignal = qt_import.pyqtSignal(list, list)

    def __init__(self, parent=None, name=None, flags=0):

        qt_import.QDialog.__init__(
            self,
            parent,
            qt_import.Qt.WindowFlags(flags
                                     | qt_import.Qt.WindowStaysOnTopHint),
        )

        if name is not None:
            self.setObjectName(name)

        # Internal variables --------------------------------------------------
        self.checked_items = []
        self.sample_items = []

        # Graphic elements ----------------------------------------------------
        self.conf_dialog_layout = qt_import.load_ui_file(
            "confirmation_dialog_layout.ui")

        continue_shortcut = qt_import.QShortcut(
            qt_import.QKeySequence("C"),
            self.conf_dialog_layout.continue_button)
        continue_shortcut.activated.connect(self.continue_shortcut_pressed)

        # Layout --------------------------------------------------------------
        _main_vlayout = qt_import.QVBoxLayout(self)
        _main_vlayout.addWidget(self.conf_dialog_layout)
        _main_vlayout.setContentsMargins(0, 0, 0, 0)
        _main_vlayout.setSpacing(0)

        # Qt signal/slot connections ------------------------------------------
        self.conf_dialog_layout.continue_button.clicked.connect(
            self.continue_button_click)
        self.conf_dialog_layout.cancel_button.clicked.connect(
            self.cancel_button_click)

        # SizePolicies --------------------------------------------------------
        self.setMinimumWidth(1200)

        # Other ---------------------------------------------------------------
        self.setWindowTitle("Confirm collection")

    def set_plate_mode(self, plate_mode):
        """Sets plate mode"""
        if plate_mode:
            snapshot_count = [0, 1]
            self.conf_dialog_layout.take_video_cbx.setEnabled(False)
            self.conf_dialog_layout.take_video_cbx.setChecked(False)
        else:
            snapshot_count = [0, 1, 2, 4]
        self.conf_dialog_layout.take_snapshots_combo.clear()
        for item in snapshot_count:
            self.conf_dialog_layout.take_snapshots_combo.addItem(str(item))
        self.conf_dialog_layout.take_snapshots_combo.setCurrentIndex(1)

    def disable_dark_current_cbx(self):
        self.conf_dialog_layout.force_dark_cbx.setEnabled(False)
        self.conf_dialog_layout.force_dark_cbx.setChecked(False)

    def enable_dark_current_cbx(self):
        self.conf_dialog_layout.force_dark_cbx.setEnabled(True)
        self.conf_dialog_layout.force_dark_cbx.setChecked(True)

    def set_items(self, checked_items):
        """Populates information about items to be collected"""
        self.sample_items = []
        self.checked_items = checked_items

        collection_items = []
        current_sample_item = None
        sample_treewidget_item = None
        collection_group_treewidget_item = None
        num_images = 0
        file_exists = False
        interleave_items = 0

        self.conf_dialog_layout.summary_treewidget.clear()
        self.conf_dialog_layout.file_treewidget.clear()
        self.conf_dialog_layout.interleave_cbx.setChecked(False)
        self.conf_dialog_layout.interleave_images_num_ledit.setText("")
        self.conf_dialog_layout.inverse_cbx.setChecked(False)
        self.conf_dialog_layout.inverse_beam_num_images_ledit.setText("")

        for item in checked_items:
            # item_type_name = ""
            info_str_list = []
            acq_parameters = None
            path_template = None
            item_model = item.get_model()
            item_type_name = item_model.get_display_name()

            if isinstance(item, queue_item.SampleQueueItem):
                self.sample_items.append(item)
                current_sample_item = item
                info_str_list.append(item_model.get_name())
                if item.mounted_style:
                    info_str_list.append("Already mounted")
                else:
                    info_str_list.append("Sample mounting")
                sample_treewidget_item = qt_import.QTreeWidgetItem(
                    self.conf_dialog_layout.summary_treewidget, info_str_list)
                for col in range(13):
                    sample_treewidget_item.setBackground(
                        col, qt_import.QBrush(colors.TREE_ITEM_SAMPLE))
                sample_treewidget_item.setExpanded(True)
            elif isinstance(item, queue_item.DataCollectionGroupQueueItem):
                info_str_list.append(item_type_name)
                collection_group_treewidget_item = qt_import.QTreeWidgetItem(
                    sample_treewidget_item, info_str_list)
                collection_group_treewidget_item.setExpanded(True)
            elif isinstance(item, queue_item.SampleCentringQueueItem):
                info_str_list.append(item_type_name)
                qt_import.QTreeWidgetItem(collection_group_treewidget_item,
                                          info_str_list)
            elif isinstance(item, queue_item.DataCollectionQueueItem):
                acq_parameters = item_model.acquisitions[
                    0].acquisition_parameters
                if not item_model.is_helical() and not item_model.is_mesh():
                    interleave_items += 1
            elif isinstance(item, queue_item.CharacterisationQueueItem):
                acq_parameters = item_model.reference_image_collection.acquisitions[
                    0].acquisition_parameters
                self.conf_dialog_layout.take_snapshots_combo.setCurrentIndex(
                    self.conf_dialog_layout.take_snapshots_combo.count() - 1)
            elif isinstance(item, queue_item.XrayCenteringQueueItem):
                acq_parameters = item_model.mesh_dc.acquisitions[
                    0].acquisition_parameters
            elif isinstance(item, queue_item.XrayImagingQueueItem):
                acq_parameters = item_model.acquisitions[
                    0].acquisition_parameters

            path_template = item_model.get_path_template()

            if acq_parameters and path_template:
                info_str_list.append(item_type_name)
                info_str_list.append("")
                info_str_list.append(path_template.directory)
                # This part is also in data_path_widget. Mote to PathTemplate
                file_name = path_template.get_image_file_name()
                file_name = file_name.replace(
                    "%" + path_template.precision + "d",
                    int(path_template.precision) * "#",
                )
                file_name = file_name.strip(" ")
                info_str_list.append(file_name)
                info_str_list.append("%.3f keV" % acq_parameters.energy)
                info_str_list.append("%.2f A" % acq_parameters.resolution)
                info_str_list.append("%.2f %%" % acq_parameters.transmission)
                info_str_list.append("%.1f" % acq_parameters.osc_start)
                info_str_list.append(str(acq_parameters.osc_range))
                info_str_list.append(str(acq_parameters.num_images))
                info_str_list.append("%s s" % str(acq_parameters.exp_time))
                info_str_list.append(
                    str(acq_parameters.num_images * acq_parameters.osc_range))
                info_str_list.append(
                    "%s s" %
                    str(acq_parameters.num_images * acq_parameters.exp_time))

                collection_treewidget_item = qt_import.QTreeWidgetItem(
                    collection_group_treewidget_item, info_str_list)
                for col in range(13):
                    collection_treewidget_item.setBackground(
                        col, qt_import.QBrush(colors.TREE_ITEM_COLLECTION))

                collection_items.append(item)
                file_paths = path_template.get_files_to_be_written()
                num_images += acq_parameters.num_images

                if len(file_paths) > 20:
                    file_paths = file_paths[:20]

                for file_path in file_paths:
                    if os.path.exists(file_path):
                        (dir_name, file_name) = os.path.split(file_path)
                        sample_name = current_sample_item.get_model(
                        ).get_display_name()
                        if sample_name is "":
                            sample_name = current_sample_item.get_model(
                            ).loc_str
                        file_str_list = []
                        file_str_list.append(sample_name)
                        file_str_list.append(dir_name)
                        file_str_list.append(file_name)

                        file_treewidgee_item = qt_import.QTreeWidgetItem(
                            self.conf_dialog_layout.file_treewidget,
                            file_str_list)
                        if hasattr(file_treewidgee_item, "setTextcolor"):
                            file_treewidgee_item.setTextcolor(
                                1, qt_import.Qt.red)
                            file_treewidgee_item.setTextcolor(
                                2, qt_import.Qt.red)
                        else:
                            file_treewidgee_item.setForeground(
                                1, qt_import.QBrush(qt_import.Qt.red))
                            file_treewidgee_item.setForeground(
                                2, qt_import.QBrush(qt_import.Qt.red))
                        file_exists = True

        self.conf_dialog_layout.file_gbox.setEnabled(file_exists)
        self.conf_dialog_layout.interleave_cbx.setEnabled(interleave_items > 1)
        self.conf_dialog_layout.inverse_cbx.setEnabled(interleave_items == 1)

        num_samples = len(self.sample_items)
        num_collections = len(collection_items)

        for col_index in range(
                self.conf_dialog_layout.summary_treewidget.columnCount()):
            if col_index != 2:
                self.conf_dialog_layout.summary_treewidget.resizeColumnToContents(
                    col_index)
        self.conf_dialog_layout.summary_label.setText(
            "Collecting " + str(num_collections) + " collection(s) on " +
            str(num_samples) + " sample(s) resulting in " + str(num_images) +
            " image(s).")

    def continue_shortcut_pressed(self):
        self.continue_button_click()

    def continue_button_click(self):
        for item in self.checked_items:
            item_model = item.get_model()
            acq_parameters = None

            if isinstance(item_model, queue_model_objects.DataCollection):
                acq_parameters = item_model.acquisitions[
                    0].acquisition_parameters
            elif isinstance(item_model, queue_model_objects.Characterisation):
                acq_parameters = item_model.reference_image_collection.acquisitions[
                    0].acquisition_parameters
            elif isinstance(item_model, queue_model_objects.XrayCentering):
                acq_parameters = item_model.mesh_dc.acquisitions[
                    0].acquisition_parameters
            elif isinstance(item_model, queue_model_objects.TaskGroup):
                try:
                    item_model.interleave_num_images = int(
                        self.conf_dialog_layout.interleave_images_num_ledit.
                        text())
                except BaseException:
                    pass
                try:
                    item_model.inverse_beam_num_images = int(
                        self.conf_dialog_layout.inverse_beam_num_images_ledit.
                        text())
                except BaseException:
                    pass
            if acq_parameters:
                acq_parameters.take_snapshots = int(
                    self.conf_dialog_layout.take_snapshots_combo.currentText())
                acq_parameters.take_video = (
                    self.conf_dialog_layout.take_video_cbx.isChecked())
                acq_parameters.take_dark_current = (
                    self.conf_dialog_layout.force_dark_cbx.isChecked())
                acq_parameters.skip_existing_images = (
                    self.conf_dialog_layout.skip_existing_images_cbx.isChecked(
                    ))

        self.continueClickedSignal.emit(self.sample_items, self.checked_items)
        self.accept()

    def cancel_button_click(self):
        self.reject()
コード例 #17
0
class WrapperHO(qt_import.QObject):
    DEVICE_MAP = {
        "Device": "Procedure",
        "SOLEILGuillotine": "Shutter",
        "SoleilSafetyShutter": "Shutter",
        "TangoShutter": "Shutter",
        "ShutterEpics": "Shutter",
        "MD2v4_FastShutter": "Shutter",
        "TempShutter": "Shutter",
        "EMBLSafetyShutter": "Shutter",
        "MDFastShutter": "Shutter",
        "WagoPneu": "WagoPneu",
        "Shutter": "WagoPneu",
        "SpecMotorWSpecPositions": "WagoPneu",
        "Procedure": "WagoPneu",
    }

    WAGO_STATE = {"in": "in", "out": "out", "unknown": "unknown"}

    SHUTTER_STATE = {
        "fault": "error",
        "opened": "in",
        "noperm": "noperm",
        "closed": "out",
        "unknown": "unknown",
        "moving": "moving",
        "automatic": "automatic",
        "disabled": "disabled",
        "error": "error",
    }
    DOOR_INTERLOCK_STATE = {
        "locked": "out",
        "unlocked": "disabled",
        "locked_active": "out",
        "locked_inactive": "disabled",
        "error": "error",
    }

    MOTOR_WPOS = ("out", "in")
    MOTOR_WSTATE = ("disabled", "error", None, "moving", "moving", "moving")

    STATES = (
        "unknown",
        "disabled",
        "closed",
        "error",
        "out",
        "moving",
        "in",
        "automatic",
        "noperm",
    )

    duoStateChangedSignal = qt_import.pyqtSignal(str, str)

    def __init__(self, hardware_obj):
        qt_import.QObject.__init__(self)

        # self.setIn = new.instancemethod(lambda self: None, self)
        self.setIn = lambda self: None
        self.setOut = self.setIn
        # self.get-State = new.instancemethod(lambda self: "unknown", self)
        self.get_state = lambda self: "unknown"
        self.dev = hardware_obj
        try:
            sClass = str(self.dev.__class__)
            i, j = re.search("'.*'", sClass).span()
        except BaseException:
            dev_class = sClass
        else:
            dev_class = sClass[i + 1 : j - 1]
        self.devClass = dev_class.split(".")[-1]

        self.devClass = WrapperHO.DEVICE_MAP.get(self.devClass, "Shutter")

        initFunc = getattr(self, "init%s" % self.devClass)
        initFunc()
        self.setIn = getattr(self, "setIn%s" % self.devClass)
        self.setOut = getattr(self, "setOut%s" % self.devClass)
        self.get_state = getattr(self, "getState%s" % self.devClass)

    def __getstate__(self):
        dict = self.__dict__.copy()
        del dict["setIn"]
        del dict["setOut"]
        del dict["getState"]
        return dict

    def __setstate__(self, dict):
        self.__dict__ = dict.copy()
        try:
            # Python2
            import new

            self.setIn = new.instancemethod(lambda self: None, self)
            self.setOut = self.setIn
            self.get_state = new.instancemethod(lambda self: "unknown", self)
        except ImportError:
            import types

            self.setIn = types.MethodType(lambda self: None, self)
            self.setOut = self.setIn
            self.get_state = types.MethodType(lambda self: "unknown", self)

    def userName(self):
        return self.dev.username

    # WagoPneu HO methods
    def initWagoPneu(self):
        self.dev.connect(self.dev, "wagoStateChanged", self.stateChangedWagoPneu)

    def setInWagoPneu(self):
        self.duoStateChangedSignal.emit("moving")
        self.dev.wagoIn()

    def setOutWagoPneu(self):
        self.duoStateChangedSignal.emit("moving")
        self.dev.wagoOut()

    def stateChangedWagoPneu(self, state):
        try:
            state = WrapperHO.WAGO_STATE[state]
        except KeyError:
            state = "error"
        self.duoStateChangedSignal.emit(state)

    def getStateWagoPneu(self):
        state = self.dev.getWagoState()
        try:
            state = WrapperHO.WAGO_STATE[state]
        except KeyError:
            state = "error"
        return state

    # Shutter HO methods
    def initShutter(self):
        self.dev.connect(self.dev, "shutterStateChanged", self.stateChangedShutter)

    def setInShutter(self):
        self.dev.openShutter()

    def setOutShutter(self):
        self.dev.closeShutter()

    def stateChangedShutter(self, state, state_label=None):
        state = WrapperHO.SHUTTER_STATE.get(state, "unknown")
        if not state_label:
            state_label = ""
        self.duoStateChangedSignal.emit(state, state_label)

    def getStateShutter(self):
        state = self.dev.getShutterState()
        try:
            state = WrapperHO.SHUTTER_STATE[state]
        except KeyError:
            state = "error"
        return state

    # SpecMotorWSpecPositions HO methods
    def initSpecMotorWSpecPositions(self):
        self.positions = None
        self.dev.connect(
            self.dev,
            "predefinedPositionChanged",
            self.position_changed_spec_motor_wspec_positions,
        )
        self.dev.connect(
            self.dev, "stateChanged", self.stateChangedSpecMotorWSpecPositions
        )
        self.dev.connect(
            self.dev,
            "newPredefinedPositions",
            self.new_predefined_spec_motor_wspec_positions,
        )

    def setInSpecMotorWSpecPositions(self):
        if self.positions is not None:
            self.dev.moveToPosition(self.positions[1])

    def setOutSpecMotorWSpecPositions(self):
        if self.positions is not None:
            self.dev.moveToPosition(self.positions[0])

    def stateChangedSpecMotorWSpecPositions(self, state):
        # logging.info("stateChangedSpecMotorWSpecPositions %s" % state)
        try:
            state = WrapperHO.MOTOR_WSTATE[state]
        except IndexError:
            state = "error"
        if state is not None:
            self.duoStateChangedSignal.emit(state)

    def position_changed_spec_motor_wspec_positions(self, pos_name, pos):
        if self.dev.get_state() != self.dev.READY:
            return
        state = "error"
        if self.positions is not None:
            for i in range(len(self.positions)):
                if pos_name == self.positions[i]:
                    state = WrapperHO.MOTOR_WPOS[i]
        self.duoStateChangedSignal.emit(state)

    def get_state_spec_motor_wspec_positions(self):
        if self.positions is None:
            return "error"
        curr_pos = self.dev.get_current_position_name()
        if curr_pos is None:
            state = self.dev.get_state()
            try:
                state = WrapperHO.MOTOR_WSTATE[state]
            except IndexError:
                state = "error"
            return state
        else:
            for i in range(len(self.positions)):
                if curr_pos == self.positions[i]:
                    return WrapperHO.MOTOR_WPOS[i]
        return "error"

    def new_predefined_spec_motor_wspec_positions(self):
        self.positions = self.dev.get_predefined_positions_list()
        self.position_changed_spec_motor_wspec_positions(
            self.dev.get_current_position_name(), self.dev.get_value()
        )

    # Procedure HO methods
    def init_procedure(self):
        cmds = self.dev.get_commands()

        self.set_in_cmd = None
        self.set_out_cmd = None

        try:
            channel = self.dev.get_channel_object("dev_state")
        except KeyError:
            channel = None
        self.stateChannel = channel
        if self.stateChannel is not None:
            self.state_dict = {
                "OPEN": "in",
                "CLOSED": "out",
                "ERROR": "error",
                "1": "in",
                "0": "out",
            }
            self.stateChannel.connect_signal("update", self.channel_update)
        else:
            self.state_dict = {}

        for cmd in cmds:
            if cmd.name() == "set in":
                self.set_in_cmd = cmd
                if self.stateChannel is not None:
                    self.set_in_cmd.connect_signal(
                        "commandReplyArrived", self.procedureSetInEnded
                    )
                    self.set_in_cmd.connect_signal(
                        "commandBeginWaitReply", self.procedure_started
                    )
                    self.set_in_cmd.connect_signal(
                        "commandFailed", self.procedure_aborted
                    )
                    self.set_in_cmd.connect_signal(
                        "commandAborted", self.procedure_aborted
                    )
            elif cmd.name() == "set out":
                self.set_out_cmd = cmd
                if self.stateChannel is not None:
                    self.set_out_cmd.connect_signal(
                        "commandReplyArrived", self.procedure_set_out_ended
                    )
                    self.set_out_cmd.connect_signal(
                        "commandBeginWaitReply", self.procedure_started
                    )
                    self.set_out_cmd.connect_signal(
                        "commandFailed", self.procedure_aborted
                    )
                    self.set_out_cmd.connect_signal(
                        "commandAborted", self.procedure_aborted
                    )

    def channel_update(self, value):
        try:
            key = self.dev.statekey
        except AttributeError:
            pass
        else:
            try:
                state = value[key]
            except TypeError:
                state = "error"
        try:
            state = self.state_dict[state]
        except KeyError:
            pass
        self.duoStateChangedSignal.emit(state)

    def set_in_procedure(self):
        if self.set_in_cmd is not None:
            self.set_in_cmd()

    def set_out_procedure(self):
        if self.set_out_cmd is not None:
            self.set_out_cmd()

    """
    def stateChangedProcedure(self,state):
        pass
    """

    def get_state_procedure(self):
        if self.stateChannel is not None:
            try:
                state = self.stateChannel.get_value()
            except BaseException:
                state = "error"
            else:
                try:
                    key = self.dev.statekey
                except AttributeError:
                    pass
                else:
                    try:
                        state = state[key]
                    except TypeError:
                        state = "error"
            try:
                state = self.state_dict[state]
            except KeyError:
                pass
            return state
        return "unknown"

    def procedureSetInEnded(self, *args):
        self.duoStateChangedSignal.emit("in")

    def procedure_set_out_ended(self, *args):
        self.duoStateChangedSignal.emit("out")

    def procedure_started(self, *args):
        self.duoStateChangedSignal.emit("moving")

    def procedure_aborted(self, *args):
        self.duoStateChangedSignal.emit("error")
コード例 #18
0
class AcquisitionWidgetSimple(qt_import.QWidget):

    acqParametersChangedSignal = qt_import.pyqtSignal(list)
    madEnergySelectedSignal = qt_import.pyqtSignal(str, float, bool)

    def __init__(
        self,
        parent=None,
        name=None,
        fl=0,
        acq_params=None,
        path_template=None,
        layout=None,
    ):

        qt_import.QWidget.__init__(self, parent, qt_import.Qt.WindowFlags(fl))
        if name is not None:
            self.setObjectName(name)

        # Internal variables --------------------------------------------------
        self.value_changed_list = []

        # Properties ----------------------------------------------------------

        # Signals -------------------------------------------------------------

        # Slots ---------------------------------------------------------------

        # Graphic elements ----------------------------------------------------
        if acq_params is None:
            self._acquisition_parameters = queue_model_objects.AcquisitionParameters(
            )
        else:
            self._acquisition_parameters = acq_params
        if path_template is None:
            self._path_template = queue_model_objects.PathTemplate()
        else:
            self._path_template = path_template

        self._acquisition_mib = DataModelInputBinder(
            self._acquisition_parameters)
        self.acq_widget_layout = qt_import.load_ui_file(
            "acquisition_widget_vertical_simple_layout.ui")

        # Layout --------------------------------------------------------------
        main_layout = qt_import.QVBoxLayout(self)
        main_layout.addWidget(self.acq_widget_layout)
        main_layout.setSpacing(0)
        main_layout.setContentsMargins(0, 0, 0, 0)

        # SizePolicies --------------------------------------------------------

        # Qt signal/slot connections ------------------------------------------
        self.acq_widget_layout.osc_start_cbox.stateChanged.connect(
            self.use_osc_start)
        self.acq_widget_layout.num_images_cbox.activated.connect(
            self.update_num_images)
        self.acq_widget_layout.detector_roi_mode_combo.activated.connect(
            self.detector_roi_mode_changed)

        # Other ---------------------------------------------------------------
        self.osc_start_validator = qt_import.QDoubleValidator(
            -10000, 10000, 4, self.acq_widget_layout.osc_start_ledit)
        self.osc_range_validator = qt_import.QDoubleValidator(
            -10000, 10000, 4, self.acq_widget_layout.osc_range_ledit)
        self.kappa_validator = qt_import.QDoubleValidator(
            0, 360, 4, self.acq_widget_layout.kappa_ledit)
        self.kappa_phi_validator = qt_import.QDoubleValidator(
            0, 360, 4, self.acq_widget_layout.kappa_phi_ledit)
        self.energy_validator = qt_import.QDoubleValidator(
            0, 25, 5, self.acq_widget_layout.energy_ledit)
        self.resolution_validator = qt_import.QDoubleValidator(
            0, 15, 3, self.acq_widget_layout.resolution_ledit)
        self.transmission_validator = qt_import.QDoubleValidator(
            0, 100, 3, self.acq_widget_layout.transmission_ledit)
        self.exp_time_validator = qt_import.QDoubleValidator(
            0, 10000, 6, self.acq_widget_layout.exp_time_ledit)
        self.acq_widget_layout.num_images_cbox.setCurrentIndex(1)

        self.acq_widget_layout.detector_roi_mode_label.setEnabled(False)
        self.acq_widget_layout.detector_roi_mode_combo.setEnabled(False)

        self.set_tunable_energy(HWR.beamline.tunable_wavelength)

        if HWR.beamline.diffractometer.in_plate_mode():
            self.acq_widget_layout.num_images_cbox.clear()
            self.acq_widget_layout.num_images_cbox.addItem("1")
            self.acq_widget_layout.num_images_cbox.setCurrentIndex(0)

        self.init_detector_roi_modes()
        self.init_limits()

    def update_osc_total_range(self):
        pass

    def set_osc_start_limits(self, limits):
        if not None in limits:
            self.osc_start_validator.setRange(limits[0], limits[1], 4)

    def update_osc_start(self, new_value):
        if not self.acq_widget_layout.osc_start_cbox.hasFocus():
            self.acq_widget_layout.osc_start_ledit.setText(str(new_value))

    def update_kappa(self, new_value):
        if not self.acq_widget_layout.kappa_ledit.hasFocus():
            self.acq_widget_layout.kappa_ledit.setText(str(new_value))

    def update_kappa_phi(self, new_value):
        if not self.acq_widget_layout.kappa_phi_ledit.hasFocus():
            self.acq_widget_layout.kappa_phi_ledit.setText(str(new_value))

    def use_kappa(self, state):
        if HWR.beamline.diffractometer.in_plate_mode():
            state = False
        self.acq_widget_layout.kappa_label.setEnabled(state)
        self.acq_widget_layout.kappa_ledit.setEnabled(state)
        self.acq_widget_layout.kappa_phi_label.setEnabled(state)
        self.acq_widget_layout.kappa_phi_ledit.setEnabled(state)

    def use_max_osc_range(self, state):
        pass

    def update_num_images(self, index=None, num_images=None):
        if index is not None:
            if index is 0:
                self._acquisition_parameters.num_images = 1
                self._path_template.num_files = 1
            elif index is 1:
                self._acquisition_parameters.num_images = 2
                self._path_template.num_files = 2
            elif index is 2:
                self._acquisition_parameters.num_images = 4
                self._path_template.num_files = 4

        if num_images:
            if self.acq_widget_layout.num_images_cbox.count() > 3:
                self.acq_widget_layout.num_images_cbox.removeItem(4)

            if num_images is 1:
                self.acq_widget_layout.num_images_cbox.setCurrentIndex(0)
            elif num_images is 2:
                self.acq_widget_layout.num_images_cbox.setCurrentIndex(1)
            elif num_images is 4:
                self.acq_widget_layout.num_images_cbox.setCurrentIndex(2)
            else:
                self.acq_widget_layout.num_images_cbox.addItem(str(num_images))
                self.acq_widget_layout.num_images_cbox.setCurrenIndex(3)

            self._path_template.num_files = num_images

    def use_mad(self, state):
        pass

    def get_mad_energy(self):
        pass

    def set_energies(self, energy_scan_result):
        pass

    def energy_selected(self, index):
        pass

    def init_limits(self):
        limits_dict = HWR.beamline.acquisition_limit_values

        tpl = limits_dict.get("osc_range")
        if tpl:
            self.osc_start_validator.setRange(tpl[0], tpl[1], 4)
            self.osc_range_validator.setRange(tpl[0], tpl[1], 4)

        self._acquisition_mib.bind_value_update(
            "osc_start",
            self.acq_widget_layout.osc_start_ledit,
            float,
            self.osc_start_validator,
        )

        self._acquisition_mib.bind_value_update(
            "osc_range",
            self.acq_widget_layout.osc_range_ledit,
            float,
            self.osc_range_validator,
        )

        tpl = limits_dict.get("kappa")
        if tpl:
            self.kappa_validator.setRange(tpl[0], tpl[1], 4)
        self._acquisition_mib.bind_value_update(
            "kappa", self.acq_widget_layout.kappa_ledit, float,
            self.kappa_validator)

        tpl = limits_dict.get("kappa_phi")
        if tpl:
            self.kappa_phi_validator.setRange(tpl[0], tpl[1], 4)
        self._acquisition_mib.bind_value_update(
            "kappa_phi",
            self.acq_widget_layout.kappa_phi_ledit,
            float,
            self.kappa_phi_validator,
        )

        tpl = limits_dict.get("exposure_time")
        if tpl:
            self.exp_time_validator.setRange(tpl[0], tpl[1], 6)
        self._acquisition_mib.bind_value_update(
            "exp_time",
            self.acq_widget_layout.exp_time_ledit,
            float,
            self.exp_time_validator,
        )

        self._acquisition_mib.bind_value_update(
            "energy", self.acq_widget_layout.energy_ledit, float,
            self.energy_validator)
        self.acq_widget_layout.energy_ledit.setToolTip(
            "Energy limits %0.3f : %0.3f" %
            (self.energy_validator.bottom(), self.energy_validator.top()))

        self._acquisition_mib.bind_value_update(
            "transmission",
            self.acq_widget_layout.transmission_ledit,
            float,
            self.transmission_validator,
        )

        self._acquisition_mib.bind_value_update(
            "resolution",
            self.acq_widget_layout.resolution_ledit,
            float,
            self.resolution_validator,
        )

        if HWR.beamline.diffractometer.in_plate_mode():
            self.acq_widget_layout.num_images_cbox.clear()
            self.acq_widget_layout.num_images_cbox.addItem("1")
            self.acq_widget_layout.num_images_cbox.setCurrentIndex(0)

    def set_energy(self, energy, wav):
        if not self.acq_widget_layout.energy_ledit.hasFocus():
            self.acq_widget_layout.energy_ledit.setText(str(energy))

    def update_transmission(self, transmission):
        if self.acq_widget_layout.transmission_ledit.hasFocus():
            self.acq_widget_layout.transmission_ledit.setText(
                str(transmission))

    def update_resolution(self, resolution):
        if not self.acq_widget_layout.resolution_ledit.hasFocus():
            self.acq_widget_layout.resolution_ledit.setText(str(resolution))

    def update_energy_limits(self, limits):
        if limits:
            self.energy_validator.setBottom(limits[0])
            self.energy_validator.setTop(limits[1])
            self.acq_widget_layout.energy_ledit.setToolTip(
                "Energy limits %0.3f : %0.3f" % (limits[0], limits[1]))
            self._acquisition_mib.validate_all()

    def update_transmission_limits(self, limits):
        if limits:
            self.transmission_validator.setBottom(limits[0])
            self.transmission_validator.setTop(limits[1])
            self.acq_widget_layout.transmission_ledit.setToolTip(
                "Transmission limits %0.3f : %0.3f" % (limits[0], limits[1]))
            self._acquisition_mib.validate_all()

    def update_resolution_limits(self, limits):
        if limits:
            self.resolution_validator.setBottom(limits[0])
            self.resolution_validator.setTop(limits[1])
            self.acq_widget_layout.resolution_ledit.setToolTip(
                "Resolution limits %0.3f : %0.3f" % (limits[0], limits[1]))
            self._acquisition_mib.validate_all()

    def update_detector_exp_time_limits(self, limits):
        if limits:
            self.exp_time_validator.setBottom(limits[0])
            self.exp_time_validator.setTop(limits[1])
            self.acq_widget_layout.exp_time_ledit.setToolTip(
                "Exposure time limits %0.3f : %0.3f" % (limits[0], limits[1]))
            self._acquisition_mib.validate_all()

    def update_energy(self, energy):
        if ("energy" not in self.value_changed_list
                and not self.acq_widget_layout.energy_ledit.hasFocus()):
            self.acq_widget_layout.energy_ledit.setText("%.4f" % float(energy))

    def init_detector_roi_modes(self):
        roi_modes = HWR.beamline.detector.get_roi_modes()
        if (len(roi_modes) > 0 and
                self.acq_widget_layout.detector_roi_mode_combo.count() == 0):
            for roi_mode in roi_modes:
                self.acq_widget_layout.detector_roi_mode_combo.addItem(
                    roi_mode)
            self.acq_widget_layout.detector_roi_mode_label.setEnabled(True)
            self.acq_widget_layout.detector_roi_mode_combo.setEnabled(True)

    def update_exp_time_limits(self):
        try:
            exp_time_limits = (
                HWR.beamline.detector.get_exposure_time_limits())
            max_osc_speed = HWR.beamline.diffractometer.get_osc_max_speed()
            top_limit = (float(self.acq_widget_layout.osc_range_ledit.text()) /
                         max_osc_speed)
            limits = (max(exp_time_limits[0], top_limit), exp_time_limits[1])
            self.update_detector_exp_time_limits(limits)
        except BaseException:
            pass

    def update_detector_roi_mode(self, roi_mode_index):
        if (roi_mode_index is not None and
                self.acq_widget_layout.detector_roi_mode_combo.count() > 0):
            self.acq_widget_layout.detector_roi_mode_combo.setCurrentIndex(
                roi_mode_index)

    def update_osc_range_limits(self, limits=None):
        pass

    def detector_roi_mode_changed(self, roi_mode_index):
        HWR.beamline.detector.set_roi_mode(roi_mode_index)

    def update_data_model(self, acquisition_parameters, path_template):
        self._acquisition_parameters = acquisition_parameters
        self._acquisition_mib.set_model(acquisition_parameters)
        self._path_template = path_template
        self.update_num_images(None, acquisition_parameters.num_images)

    def set_tunable_energy(self, state):
        self.acq_widget_layout.energy_ledit.setEnabled(state)

    def use_osc_start(self, state):
        self.acq_widget_layout.osc_start_ledit.setEnabled(state)

    def check_parameter_conflict(self):
        return self._acquisition_mib.validate_all()
コード例 #19
0
class PowerBar(qt_import.QWidget):
    """
    Custom Qt Widget to show a power bar and dial.
    Demonstrating compound and custom-drawn widget.

    Left-clicking the button shows the color-chooser, while
    right-clicking resets the color to None (no-color).
    """

    value_changed = qt_import.pyqtSignal(int)

    def __init__(self, steps=5, *args, **kwargs):
        super(PowerBar, self).__init__(*args, **kwargs)

        layout = qt_import.QVBoxLayout()
        self._bar = _Bar(steps)
        layout.addWidget(self._bar)

        # Create the QDial widget and set up defaults.
        # - we provide accessors on this class to override.
        self._dial = qt_import.QDial()
        self._dial.setNotchesVisible(True)
        self._dial.setWrapping(False)
        self._dial.valueChanged.connect(self._bar._trigger_refresh)
        self._dial.valueChanged.connect(self.slot_value_changed)

        # Take feedback from click events on the meter.
        self._bar.clickedValue.connect(self._dial.setValue)

        layout.addWidget(self._dial)
        self.setLayout(layout)
        # now, _dial and _bar have a parent() a PowerBar object

    def __getattr__(self, name):
        if name in self.__dict__:
            return self[name]

        return getattr(self._dial, name)

    def setValue(self, new_value):
        self._dial.setValue(new_value)

    def setColor(self, color):
        self._bar.steps = [color] * self._bar.n_steps
        self._bar.update()

    def setColors(self, colors):
        self._bar.n_steps = len(colors)
        self._bar.steps = colors
        self._bar.update()

    def setBarPadding(self, i):
        self._bar._padding = int(i)
        self._bar.update()

    def setBarSolidPercent(self, f):
        self._bar._bar_solid_percent = float(f)
        self._bar.update()

    def setBackgroundColor(self, color):
        self._bar._background_color = qt_import.QColor(color)
        self._bar.update()

    def slot_value_changed(self, new_value):
        self.value_changed.emit(new_value)

    def setDialVisible(self, visible):
        self._dial.setVisible(visible)

    def setBarVisible(self, visible):
        self._bar.setVisible(visible)

    def dialAndBarInvible(self):
        return (not self._bar.isVisible() and not self._dial.isVisible())
コード例 #20
0
class TaskToolboxBrick(BaseWidget):

    request_tree_brick = qt_import.pyqtSignal()

    def __init__(self, *args):
        BaseWidget.__init__(self, *args)

        # Internal values -----------------------------------------------------
        self.ispyb_logged_in = False
        self.tree_brick = None

        # Properties ----------------------------------------------------------
        self.add_property("useOscStartCbox", "boolean", False)
        self.add_property("useCompression", "boolean", False)
        #self.add_property("availableTasks", "string", "discrete char helical")
        self.add_property("showDiscreetTask", "boolean", True)
        self.add_property("showHelicalTask", "boolean", True)
        self.add_property("showCharTask", "boolean", True)
        self.add_property("showAdvancedTask", "boolean", True)
        self.add_property("showSsxTask", "boolean", False)
        self.add_property("showCollectNowButton", "boolean", False)

        # Signals -------------------------------------------------------------
        self.define_signal("request_tree_brick", ())

        # Slots ---------------------------------------------------------------
        self.define_slot("logged_in", ())
        self.define_slot("set_session", ())
        self.define_slot("selection_changed", ())
        self.define_slot("user_group_saved", ())
        self.define_slot("set_tree_brick", ())

        # Graphic elements ----------------------------------------------------
        self.task_tool_box_widget = TaskToolBoxWidget(self)

        # Layout --------------------------------------------------------------
        self.main_layout = qt_import.QVBoxLayout(self)
        self.main_layout.addWidget(self.task_tool_box_widget)
        self.main_layout.setSpacing(0)
        self.main_layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.main_layout)

        # SizePolicies --------------------------------------------------------
        # self.setSizePolicy(qt_import.QSizePolicy.MinimumExpanding,
        #                   qt_import.QSizePolicy.MinimumExpanding)

        # Other ---------------------------------------------------------------
        HWR.beamline.sample_view.connect("pointSelected", self.point_selected)

    def set_expert_mode(self, expert):
        self.task_tool_box_widget.set_expert_mode(expert)

    def run(self):
        if HWR.beamline.session.session_id:
            self.setEnabled(True)

        #self.task_tool_box_widget.set_available_tasks(self["availableTasks"])
        self.request_tree_brick.emit()
        self.task_tool_box_widget.adjust_width(self.width())

    def user_group_saved(self, new_user_group):
        HWR.beamline.session.set_user_group(str(new_user_group))
        self.task_tool_box_widget.update_data_path_model()
        path = (HWR.beamline.session.get_base_image_directory() + "/" +
                str(new_user_group))
        msg = "Image path is: %s" % path
        logging.getLogger("GUI").info(msg)

    @qt_import.pyqtSlot(BaseWidget)
    def set_tree_brick(self, brick):
        self.tree_brick = brick
        self.tree_brick.compression_state = self["useCompression"] == 1
        self.task_tool_box_widget.set_tree_brick(brick)

    @qt_import.pyqtSlot(int, str, str, int, str, str, bool)
    def set_session(
        self,
        session_id,
        t_prop_code=None,
        prop_number=None,
        prop_id=None,
        start_date=None,
        prop_code=None,
        is_inhouse=None,
    ):
        """
        Connected to the slot set_session and is called after a
        request to get the current session from LIMS (ISPyB) is
        made. The signal is normally emitted by the brick that
        handles LIMS login, ie ProposalBrick.
        The session_id is '' if no session could be retrieved.
        """
        if session_id is "":
            self.logged_in(True)

    @qt_import.pyqtSlot(bool)
    def logged_in(self, logged_in):
        """
        Handels the signal logged_in from the brick the handles
        LIMS (ISPyB) login, ie ProposalBrick. The signal is
        emitted when a user was succesfully logged in.
        """
        logged_in = True

        self.ispyb_logged_in = logged_in

        if HWR.beamline.session is not None:
            HWR.beamline.session.set_user_group("")

        self.setEnabled(logged_in)
        self.task_tool_box_widget.ispyb_logged_in(logged_in)

    def property_changed(self, property_name, old_value, new_value):
        if property_name == "useOscStartCbox":
            self.task_tool_box_widget.use_osc_start_cbox(new_value)
        elif property_name == "useCompression":
            self.task_tool_box_widget.enable_compression(new_value)
        elif property_name == "showCollectNowButton":
            self.task_tool_box_widget.collect_now_button.setVisible(new_value)
        elif property_name == "showDiscreetTask":
            if not new_value:
                self.task_tool_box_widget.hide_task(
                    self.task_tool_box_widget.discrete_page)
        elif property_name == "showHelicalTask":
            if not new_value:
                self.task_tool_box_widget.hide_task(
                    self.task_tool_box_widget.helical_page)
        elif property_name == "showCharTask":
            if not new_value:
                self.task_tool_box_widget.hide_task(
                    self.task_tool_box_widget.char_page)
        elif property_name == "showAdvancedTask":
            if not new_value:
                self.task_tool_box_widget.hide_task(
                    self.task_tool_box_widget.advanced_page)
        elif property_name == "showSsxTask":
            if not new_value:
                self.task_tool_box_widget.hide_task(
                    self.task_tool_box_widget.ssx_page)

    def selection_changed(self, items):
        """
        Connected to the signal "selection_changed" of the TreeBrick.
        Called when the selection in the tree changes.
        """
        self.task_tool_box_widget.selection_changed(items)

    def point_selected(self, selected_position):
        self.task_tool_box_widget.helical_page.centred_position_selection(
            selected_position)
        self.task_tool_box_widget.discrete_page.centred_position_selection(
            selected_position)
        self.task_tool_box_widget.char_page.centred_position_selection(
            selected_position)
        self.task_tool_box_widget.energy_scan_page.centred_position_selection(
            selected_position)
        self.task_tool_box_widget.xrf_spectrum_page.centred_position_selection(
            selected_position)

        self.task_tool_box_widget.discrete_page.refresh_current_item()
        self.task_tool_box_widget.helical_page.refresh_current_item()
        self.task_tool_box_widget.char_page.refresh_current_item()
        self.task_tool_box_widget.energy_scan_page.refresh_current_item()
        self.task_tool_box_widget.xrf_spectrum_page.refresh_current_item()
コード例 #21
0
    class CustomPeriodicTable(QPeriodicTable.QPeriodicTable):

        edgeSelectedSignal = qt_import.pyqtSignal(str, str)

        def __init__(self, *args):
            QPeriodicTable.QPeriodicTable.__init__(self, *args)

            self.elements_dict = {}
            if PYMCA_IMPORTED == 5:
                self.sigElementClicked.connect(self.table_element_clicked)
            else:
                qt_import.QObject.connect(
                    self, qt_import.SIGNAL("elementClicked"), self.table_element_clicked
                )
            for b in self.eltButton:
                self.eltButton[b].colors[0] = qt_import.QColor(qt_import.Qt.green)
                self.eltButton[b].colors[1] = qt_import.QColor(qt_import.Qt.darkGreen)
                self.eltButton[b].setEnabled(False)
            for el in QPeriodicTable.Elements:
                symbol = el[0]
                self.elements_dict[symbol] = el

        def elementEnter(self, symbol, z=None, name=None):
            if isinstance(symbol, tuple) and len(symbol) > 0:
                symbol = symbol[0]

            b = self.eltButton[symbol]
            if b.isEnabled():
                b.setCurrent(True)

        def elementLeave(self, symbol):
            if isinstance(symbol, tuple) and len(symbol) > 0:
                symbol = symbol[0]

            b = self.eltButton[symbol]
            if b.isEnabled():
                b.setCurrent(False)

        def table_element_clicked(self, symbol, energy=None):
            if isinstance(symbol, tuple) and len(symbol) > 0:
                symbol = symbol[0]

            if energy is None:
                energy = self.energies_dict[symbol]
            self.setSelection((symbol,))
            if energy is None:
                energy = self.energies_dict[symbol]
            else:
                index = self.elements_dict[symbol][1]
                name = self.elements_dict[symbol][4]
                txt = "%s - %s (%s,%s)" % (symbol, energy, index, name)
                self.eltLabel.setText(txt)
                self.edgeSelectedSignal.emit(symbol, energy)
                # self.widgetSynchronizeSignal([symbol, energy])

        def setElements(self, elements):
            self.energies_dict = {}
            for b in self.eltButton:
                self.eltButton[b].setEnabled(False)
            first_element = None
            for element in elements:
                symbol = element["symbol"]
                if first_element is None:
                    first_element = symbol
                energy = element["energy"]
                self.energies_dict[symbol] = energy
                b = self.eltButton[symbol]
                b.setEnabled(True)

        def widgetSynchronize(self, state):
            symbol = state[0]
            self.tableElementChanged(symbol)
コード例 #22
0
ファイル: processing_widget.py プロジェクト: rhfogh/mxcube
class ProcessingWidget(qt_import.QWidget):

    enableProcessingSignal = qt_import.pyqtSignal(bool, bool)

    def __init__(self, parent=None, name=None, fl=0, data_model=None):

        qt_import.QWidget.__init__(self, parent, qt_import.Qt.WindowFlags(fl))
        if name is not None:
            self.setObjectName(name)

        if data_model is None:
            self._model = queue_model_objects.ProcessingParameters()
        else:
            self._model = data_model

        self._model_mib = DataModelInputBinder(self._model)

        self.processing_widget = qt_import.load_ui_file(
            "processing_widget_vertical_layout.ui")

        self.main_layout = qt_import.QVBoxLayout(self)
        self.main_layout.addWidget(self.processing_widget)
        self.main_layout.setSpacing(0)
        self.main_layout.setContentsMargins(0, 0, 0, 0)

        self.processing_widget.space_group_combo.addItems(
            queue_model_enumerables.XTAL_SPACEGROUPS)

        self._model_mib.bind_value_update("cell_a",
                                          self.processing_widget.a_ledit,
                                          float, None)

        self._model_mib.bind_value_update("cell_alpha",
                                          self.processing_widget.alpha_ledit,
                                          float, None)

        self._model_mib.bind_value_update("cell_b",
                                          self.processing_widget.b_ledit,
                                          float, None)

        self._model_mib.bind_value_update("cell_beta",
                                          self.processing_widget.beta_ledit,
                                          float, None)

        self._model_mib.bind_value_update("cell_c",
                                          self.processing_widget.c_ledit,
                                          float, None)

        self._model_mib.bind_value_update("cell_gamma",
                                          self.processing_widget.gamma_ledit,
                                          float, None)

        self._model_mib.bind_value_update(
            "num_residues", self.processing_widget.num_residues_ledit, float,
            None)

        self._model_mib.bind_value_update(
            "resolution_cutoff",
            self.processing_widget.resolution_cutoff_ledit, float, None)

        self._model_mib.bind_value_update(
            "pdb_file", self.processing_widget.pdb_file_ledit, str, None)

        self.processing_widget.space_group_combo.activated.connect(
            self._space_group_change)
        self.processing_widget.run_offline_processing_cbox.stateChanged.connect(
            self._run_offline_processing_toggled)
        self.processing_widget.run_online_processing_cbox.stateChanged.connect(
            self._run_online_processing_toggled)
        self.processing_widget.pdb_file_browse_button.clicked.connect(
            self._browse_clicked)

        self.processing_widget.resolution_cutoff_label.setHidden(True)
        self.processing_widget.resolution_cutoff_ledit.setHidden(True)
        self.processing_widget.pdb_file_label.setHidden(True)
        self.processing_widget.pdb_file_ledit.setHidden(True)
        self.processing_widget.pdb_file_browse_button.setHidden(True)

        if HWR.beamline.offline_processing_methods:
            cbox_text = "Run offline processing ("
            for method in HWR.beamline.offline_processing_methods:
                cbox_text += "%s, " % method
            cbox_text = cbox_text[:-2] + ")"
            self.processing_widget.run_offline_processing_cbox.setText(
                cbox_text)
            self.processing_widget.run_offline_processing_cbox.setChecked(
                HWR.beamline.run_offline_processing)
        else:
            self.processing_widget.run_offline_processing_cbox.setChecked(
                False)
            self.processing_widget.run_offline_processing_cbox.setEnabled(
                False)

        if HWR.beamline.online_processing_methods:
            cbox_text = "Run online processing ("
            for method in HWR.beamline.online_processing_methods:
                cbox_text += "%s, " % method
            cbox_text = cbox_text[:-2] + ")"
            self.processing_widget.run_online_processing_cbox.setText(
                cbox_text)
            self.processing_widget.run_online_processing_cbox.setChecked(
                HWR.beamline.run_online_processing)
        else:
            self.processing_widget.run_online_processing_cbox.setChecked(False)
            self.processing_widget.run_online_processing_cbox.setEnabled(False)

    def _space_group_change(self, index):
        self._model.space_group = queue_model_enumerables.XTAL_SPACEGROUPS[
            index]

    def _set_space_group(self, space_group):
        index = 0

        if space_group in queue_model_enumerables.XTAL_SPACEGROUPS:
            index = queue_model_enumerables.XTAL_SPACEGROUPS.index(space_group)

        self._space_group_change(index)
        self.processing_widget.space_group_combo.setCurrentIndex(index)

    def update_data_model(self, model):
        self._model = model
        self._model_mib.set_model(model)
        self._set_space_group(model.space_group)

    def _run_offline_processing_toggled(self, state):
        self.enableProcessingSignal.emit(
            self.processing_widget.run_offline_processing_cbox.isChecked(),
            self.processing_widget.run_online_processing_cbox.isChecked(),
        )

    def _run_online_processing_toggled(self, state):
        self.enableProcessingSignal.emit(
            self.processing_widget.run_offline_processing_cbox.isChecked(),
            self.processing_widget.run_online_processing_cbox.isChecked(),
        )

    def _browse_clicked(self):
        file_dialog = qt_import.QFileDialog(self)

        pdb_filename = str(
            file_dialog.getOpenFileName(self, "Select a PDB file",
                                        expanduser("~")))
        self._model.pdb_file = pdb_filename
        self.processing_widget.pdb_file_ledit.setText(pdb_filename)

    def get_processing_state(self):
        return self.processing_widget.run_offline_processing_cbox.isChecked(), \
               self.processing_widget.run_online_processing_cbox.isChecked()
コード例 #23
0
ファイル: chat_brick.py プロジェクト: rhfogh/mxcube
class ChatBrick(BaseWidget):

    PRIORITY_COLORS = ("darkblue", "black", "red")
    MY_COLOR = "darkgrey"

    incoming_unread_messages = qt_import.pyqtSignal(int, bool)
    reset_unread_messages = qt_import.pyqtSignal(bool)

    def __init__(self, *args):

        BaseWidget.__init__(self, *args)

        # Properties ----------------------------------------------------------
        self.add_property("mnemonic", "string", "")
        self.add_property("icons", "string", "")
        self.add_property("myTabLabel", "string", "")

        # Signals ------------------------------------------------------------
        self.define_signal("incoming_unread_messages", ())
        self.define_signal("reset_unread_message", ())

        # Slots ---------------------------------------------------------------
        self.define_slot("tabSelected", ())
        self.define_slot("sessionSelected", ())

        # Hardware objects ----------------------------------------------------
        self.instance_server_hwobj = None

        # Internal values -----------------------------------------------------
        self.session_id = None
        self.nickname = ""
        self.role = BaseWidget.INSTANCE_ROLE_UNKNOWN

        # Graphic elements ----------------------------------------------------
        self.conversation_textedit = qt_import.QTextEdit(self)
        self.conversation_textedit.setReadOnly(True)
        _controls_widget = qt_import.QWidget(self)
        _say_label = qt_import.QLabel("Say:", _controls_widget)
        self.message_ledit = qt_import.QLineEdit(_controls_widget)
        self.send_button = qt_import.QPushButton("Send", _controls_widget)
        self.send_button.setEnabled(False)

        # Layout --------------------------------------------------------------
        _controls_widget_hlayout = qt_import.QHBoxLayout(_controls_widget)
        _controls_widget_hlayout.addWidget(_say_label)
        _controls_widget_hlayout.addWidget(self.message_ledit)
        _controls_widget_hlayout.addWidget(self.send_button)
        _controls_widget_hlayout.setSpacing(2)
        _controls_widget_hlayout.setContentsMargins(0, 0, 0, 0)

        _main_vlayout = qt_import.QVBoxLayout(self)
        _main_vlayout.addWidget(self.conversation_textedit)
        _main_vlayout.addWidget(_controls_widget)
        _main_vlayout.setSpacing(2)
        _main_vlayout.setContentsMargins(2, 2, 2, 2)

        # Qt signal/slot connections ------------------------------------------
        self.send_button.clicked.connect(self.send_current_message)
        self.message_ledit.returnPressed.connect(self.send_current_message)
        self.message_ledit.textChanged.connect(self.message_changed)

        # self.setFixedHeight(120)
        # self.setFixedWidth(790)

    def run(self):
        self.set_role(self.role)

    def session_selected(self, *args):
        session_id = args[0]
        is_inhouse = args[-1]
        self.conversation_textedit.clear()
        if is_inhouse:
            self.session_id = None
        else:
            self.session_id = session_id
            self.load_chat_history()

    def load_chat_history(self):
        if self.instance_server_hwobj is not None:
            chat_history_filename = "/tmp/mxCuBE_chat_%s.%s" % (
                self.session_id,
                self.instance_server_hwobj.isClient() and "client" or "server",
            )
        else:
            return
        try:
            chat_history = open(chat_history_filename, "r")
        except BaseException:
            return

        if self.isEnabled():
            for msg in chat_history.readlines():
                self.conversation_textedit.append(msg)

    def instance_role_changed(self, role):
        self.set_role(role)

    def set_role(self, role):
        self.role = role
        if role != BaseWidget.INSTANCE_ROLE_UNKNOWN and not self.isEnabled():
            self.setEnabled(True)
            self.load_chat_history()

    def message_changed(self, text):
        self.send_button.setEnabled(len(str(text)) > 0)

    def message_arrived(self, priority, user_id, message):
        color = ChatBrick.PRIORITY_COLORS[priority]
        msg_prefix = ""
        msg_suffix = ""
        if priority == QtInstanceServer.ChatInstanceMessage.PRIORITY_NORMAL:
            if user_id is None:
                header = ""
            else:
                header = " %s:" % self.instance_server_hwobj.idPrettyPrint(
                    user_id)
                if user_id[0] == self.nickname:
                    color = ChatBrick.MY_COLOR
        else:
            header = ""
            msg_prefix = "<i>"
            msg_suffix = "</i>"

        now = time.strftime("%T")
        new_line = "<font color=%s><b>(%s)%s</b> %s%s%s</font>" % (
            color,
            now,
            header,
            msg_prefix,
            message,
            msg_suffix,
        )
        self.conversation_textedit.append(new_line)

        if self.session_id is not None and self.instance_server_hwobj is not None:
            chat_history_filename = "/tmp/mxCuBE_chat_%s.%s" % (
                self.session_id,
                self.instance_server_hwobj.isClient() and "client" or "server",
            )
            try:
                if time.time() - os.stat(
                        chat_history_filename).st_mtime > 24 * 3600:
                    os.unlink(chat_history_filename)
            except OSError:
                pass
            chat_history_file = open(chat_history_filename, "a")
            chat_history_file.write(new_line)
            chat_history_file.write("\n")
            chat_history_file.close()

        # self.emit(QtCore.SIGNAL("incUnreadMessages"),1, True)
        self.incoming_unread_messages.emit(1, True)

    def new_client(self, client_id):
        msg = ("%s has joined the conversation." %
               self.instance_server_hwobj.idPrettyPrint(client_id))
        self.message_arrived(QtInstanceServer.ChatInstanceMessage.PRIORITY_LOW,
                             None, msg)

    def wants_control(self, client_id):
        msg = "%s wants to have control!" % self.instance_server_hwobj.idPrettyPrint(
            client_id)
        self.message_arrived(
            QtInstanceServer.ChatInstanceMessage.PRIORITY_HIGH, None, msg)

    def server_initialized(self, started, server_id=None):
        if started:
            # sg="I'm moderating the chat as %s." % server_id[0]
            # self.message_arrived(InstanceServer.ChatInstanceMessage.PRIORITY_LOW,None,msg)
            self.nickname = server_id[0]

    def client_closed(self, client_id):
        msg = ("%s has left the conversation..." %
               self.instance_server_hwobj.idPrettyPrint(client_id))
        self.message_arrived(QtInstanceServer.ChatInstanceMessage.PRIORITY_LOW,
                             None, msg)

    def client_initialized(self,
                           connected,
                           server_id=None,
                           my_nickname=None,
                           quiet=False):
        if connected:
            server_print = self.instance_server_hwobj.idPrettyPrint(server_id)
            msg = "I've joined the conversation as %s (moderator is %s)." % (
                my_nickname,
                server_print,
            )
            self.message_arrived(
                QtInstanceServer.ChatInstanceMessage.PRIORITY_LOW, None, msg)
            self.nickname = my_nickname

    def client_changed(self, old_client_id, new_client_id):
        # print "CHAT CLIENT CHANGED",old_client_id,new_client_id
        if old_client_id[0] == self.nickname:
            self.nickname = new_client_id[0]
        else:
            old_client_print = self.instance_server_hwobj.idPrettyPrint(
                old_client_id)
            new_client_print = self.instance_server_hwobj.idPrettyPrint(
                new_client_id)
            msg = "%s has changed to %s." % (old_client_print,
                                             new_client_print)
            self.message_arrived(
                QtInstanceServer.ChatInstanceMessage.PRIORITY_LOW, None, msg)

    def send_current_message(self):
        txt = str(self.message_ledit.text())
        if len(txt):
            self.instance_server_hwobj.sendChatMessage(
                QtInstanceServer.ChatInstanceMessage.PRIORITY_NORMAL, txt)
            self.message_ledit.setText("")

    def property_changed(self, property_name, old_value, new_value):
        if property_name == "mnemonic":
            if self.instance_server_hwobj is not None:
                self.disconnect(
                    self.instance_server_hwobj,
                    "chatMessageReceived",
                    self.message_arrived,
                )
                self.disconnect(self.instance_server_hwobj, "newClient",
                                self.new_client)
                self.disconnect(
                    self.instance_server_hwobj,
                    "serverInitialized",
                    self.server_initialized,
                )
                self.disconnect(
                    self.instance_server_hwobj,
                    "clientInitialized",
                    self.client_initialized,
                )
                self.disconnect(self.instance_server_hwobj, "serverClosed",
                                self.client_closed)
                self.disconnect(self.instance_server_hwobj, "wantsControl",
                                self.wants_control)
                self.disconnect(self.instance_server_hwobj, "haveControl",
                                self.have_control)
                self.disconnect(self.instance_server_hwobj, "passControl",
                                self.pass_control)
                self.disconnect(self.instance_server_hwobj, "clientClosed",
                                self.client_closed)
                self.disconnect(self.instance_server_hwobj, "clientChanged",
                                self.client_changed)

            self.instance_server_hwobj = self.get_hardware_object(new_value)

            if self.instance_server_hwobj is not None:
                self.connect(
                    self.instance_server_hwobj,
                    "chatMessageReceived",
                    self.message_arrived,
                )
                self.connect(self.instance_server_hwobj, "newClient",
                             self.new_client)
                self.connect(
                    self.instance_server_hwobj,
                    "serverInitialized",
                    self.server_initialized,
                )
                self.connect(
                    self.instance_server_hwobj,
                    "clientInitialized",
                    self.client_initialized,
                )
                self.connect(self.instance_server_hwobj, "serverClosed",
                             self.client_closed)
                self.connect(self.instance_server_hwobj, "wantsControl",
                             self.wants_control)
                self.connect(self.instance_server_hwobj, "haveControl",
                             self.have_control)
                self.connect(self.instance_server_hwobj, "passControl",
                             self.pass_control)
                self.connect(self.instance_server_hwobj, "clientClosed",
                             self.client_closed)
                self.connect(self.instance_server_hwobj, "clientChanged",
                             self.client_changed)

        elif property_name == "icons":
            icons_list = new_value.split()
            try:
                self.send_button.setIcon(icons.load_icon(icons_list[0]))
            except IndexError:
                pass
        else:
            BaseWidget.property_changed(self, property_name, old_value,
                                        new_value)

    def have_control(self, have_control, gui_only=False):
        if not gui_only:
            if have_control:
                p = QtInstanceServer.ChatInstanceMessage.PRIORITY_HIGH
                msg = "I've gained control!"
            else:
                p = QtInstanceServer.ChatInstanceMessage.PRIORITY_HIGH
                msg = "I've lost control..."
            self.message_arrived(p, None, msg)

    def pass_control(self, has_control_id):
        has_control_print = self.instance_server_hwobj.idPrettyPrint(
            has_control_id)
        msg = "%s has control." % has_control_print
        self.message_arrived(QtInstanceServer.ChatInstanceMessage.PRIORITY_LOW,
                             None, msg)

    def tabSelected(self, tab_name):
        if tab_name == self["myTabLabel"]:
            # self.emit(QtCore.SIGNAL("resetUnreadMessages"), True)
            self.reset_unread_messages.emit(True)
コード例 #24
0
ファイル: gui_supervisor.py プロジェクト: rhfogh/mxcube
class GUISupervisor(qt_import.QWidget):
    """GUI supervisor"""

    brickChangedSignal = qt_import.pyqtSignal(str, str, str, tuple, bool)
    tabChangedSignal = qt_import.pyqtSignal(str, int)

    def __init__(self,
                 design_mode=False,
                 show_maximized=False,
                 no_border=False):
        """Main mxcube gui widget"""

        qt_import.QWidget.__init__(self)

        self.framework = None
        self.gui_config_file = None
        self.user_file_dir = None
        self.configuration = None
        self.user_settings = None

        self.launch_in_design_mode = design_mode
        self.hardware_repository = HWR.get_hardware_repository()
        self.show_maximized = show_maximized
        self.no_border = no_border
        self.windows = []

        self.splash_screen = SplashScreen(icons.load_pixmap("splash"))

        set_splash_screen(self.splash_screen)
        self.splash_screen.show()

        self.time_stamp = 0

    def set_user_file_directory(self, user_file_directory):
        """Sets user file directory"""
        self.user_file_dir = user_file_directory
        BaseWidget.set_user_file_directory(user_file_directory)

    def load_gui(self, gui_config_file):
        """Loads gui"""
        self.configuration = configuration.Configuration()
        self.gui_config_file = gui_config_file

        if self.gui_config_file:
            load_from_dict = gui_config_file.endswith(
                ".json") or gui_config_file.endswith(".yml")
            if hasattr(self, "splash_screen"):
                self.splash_screen.set_gui_name(
                    os.path.splitext(os.path.basename(gui_config_file))[0])

            if os.path.exists(gui_config_file):
                filestat = os.stat(gui_config_file)
                self.time_stamp = filestat[stat.ST_MTIME]

                if filestat[stat.ST_SIZE] == 0:
                    return self.new_gui()

                try:
                    gui_file = open(gui_config_file)
                except BaseException:
                    logging.getLogger().exception("Cannot open file %s",
                                                  gui_config_file)
                    qt_import.QMessageBox.warning(
                        self,
                        "Error",
                        "Could not open file %s !" % gui_config_file,
                        qt_import.QMessageBox.Ok,
                    )
                else:
                    # find mnemonics to speed up loading
                    # (using the 'require' feature from Hardware Repository)

                    def __get_mnemonics(items_list):
                        """Gets mnemonics"""

                        mne_list = []

                        for item in items_list:
                            if "brick" in item:
                                try:
                                    if load_from_dict:
                                        props = item["properties"]
                                    else:
                                        props = pickle.loads(
                                            item["properties"])
                                except BaseException:
                                    logging.getLogger().exception(
                                        "Could not load properties for %s" %
                                        item["name"])
                                else:
                                    item["properties"] = props
                                    try:
                                        for prop in props:
                                            if load_from_dict:
                                                prop_value = prop["value"]
                                            else:
                                                prop_value = prop.get_value()
                                            if isinstance(
                                                    prop_value, type("")
                                            ) and prop_value.startswith("/"):
                                                mne_list.append(prop_value)
                                    except BaseException:
                                        logging.exception(
                                            "Could not " +
                                            "build list of required " +
                                            "hardware objects")

                                continue

                            mne_list += __get_mnemonics(item["children"])

                        return mne_list

                    failed_msg = ("Cannot read configuration from file %s. " %
                                  gui_config_file)
                    failed_msg += "Starting in designer mode with clean GUI."

                    raw_config = None
                    try:
                        if gui_config_file.endswith(".json"):
                            raw_config = json.load(gui_file)
                        elif gui_config_file.endswith(".yml"):
                            raw_config = yaml.safe_load(gui_file)
                        else:
                            raw_config = eval(gui_file.read())
                    except BaseException:
                        logging.getLogger().exception(failed_msg)

                    self.splash_screen.set_message("Gathering H/O info...")
                    self.splash_screen.set_progress_value(10)
                    mnemonics = __get_mnemonics(raw_config)
                    self.hardware_repository.require(mnemonics)
                    gui_file.close()

                    try:
                        self.splash_screen.set_message(
                            "Building GUI configuration...")
                        self.splash_screen.set_progress_value(20)
                        config = configuration.Configuration(raw_config)
                    except BaseException:
                        logging.getLogger("GUI").exception(failed_msg)
                        qt_import.QMessageBox.warning(self, "Error",
                                                      failed_msg,
                                                      qt_import.QMessageBox.Ok)
                    else:
                        self.configuration = config

                    try:
                        user_settings_filename = os.path.join(
                            self.user_file_dir, "settings.dat")
                        user_settings_file = open(user_settings_filename)
                        self.user_settings = eval(user_settings_file.read())
                    except BaseException:
                        self.user_settings = []
                        logging.getLogger().error(
                            "Unable to read user settings file: %s" %
                            user_settings_filename)
                    else:
                        user_settings_file.close()

                    if len(self.configuration.windows) == 0:
                        return self.new_gui()

                    #self.hardware_repository.print_report()

                    if self.launch_in_design_mode:
                        self.framework = gui_builder.GUIBuilder()

                        qt_import.QApplication.setActiveWindow(self.framework)

                        self.framework.filename = gui_config_file
                        self.framework.configuration = config
                        self.framework.setWindowTitle("GUI Builder - %s" %
                                                      gui_config_file)
                        self.framework.gui_editor_window.set_configuration(
                            config)
                        self.framework.gui_editor_window.draw_window_preview()
                        self.framework.show()

                        return self.framework
                    else:
                        main_window = self.execute(self.configuration)
                        return main_window

        return self.new_gui()

    def new_gui(self):
        """Starts new gui"""

        self.time_stamp = 0
        self.launch_in_design_mode = True

        self.framework = gui_builder.GUIBuilder()

        qt_import.QApplication.setActiveWindow(self.framework)
        self.framework.show()
        self.framework.new_clicked(self.gui_config_file)

        return self.framework

    def display(self):
        """Shows all defined windows"""
        self.windows = []
        for window in self.configuration.windows_list:
            display = gui_display.WindowDisplayWidget(None,
                                                      window["name"],
                                                      execution_mode=True,
                                                      no_border=self.no_border)
            self.windows.append(display)
            display.set_caption(window["properties"]["caption"])
            display.draw_preview(window, id(display))
            display.close_on_exit = window["properties"]["closeOnExit"]
            display.set_keep_open(window["properties"]["keepOpen"])
            display.set_font_size(window["properties"]["fontSize"])

            if window["properties"]["show"]:
                display._show = True
            else:
                display._show = False
            display.hide()

            for item in self.user_settings:
                if item["name"] == window["name"]:
                    display.move(item["posx"], item["posy"])
                    display.resize(item["width"], item["height"])

        for window in self.windows:
            window.append_windows_links(self.windows)

    def execute(self, config):
        """Start in execution mode"""
        self.splash_screen.set_message("Executing configuration...")
        self.splash_screen.set_progress_value(90)
        self.display()

        main_window = None

        if len(self.windows) > 0:
            main_window = self.windows[0]
            main_window.configuration = config
            qt_import.QApplication.setActiveWindow(main_window)
            if self.no_border:
                main_window.move(0, 0)
                width = qt_import.QApplication.desktop().width()
                height = qt_import.QApplication.desktop().height()
                main_window.resize(qt_import.QSize(width, height))

            # make connections
            widgets_dict = dict([(
                isinstance(w.objectName, collections.Callable)
                and str(w.objectName()) or None,
                w,
            ) for w in qt_import.QApplication.allWidgets()])

            def make_connections(items_list):
                """Creates connections"""

                for item in items_list:
                    try:
                        sender = widgets_dict[item["name"]]
                    except KeyError:
                        logging.getLogger().error(
                            "Could not find receiver widget %s" % item["name"])
                    else:
                        for connection in item["connections"]:
                            _receiver = (connection["receiver"]
                                         or connection["receiverWindow"])
                            try:
                                receiver = widgets_dict[_receiver]
                            except KeyError:
                                logging.getLogger().error(
                                    "Could not find " + "receiver widget %s",
                                    _receiver)
                            else:
                                try:
                                    slot = getattr(receiver,
                                                   connection["slot"])
                                    # etattr(sender, connection["signal"]).connect(slot)
                                except AttributeError:
                                    logging.getLogger().error(
                                        "No slot '%s' " % connection["slot"] +
                                        "in receiver %s" % _receiver)
                                else:
                                    if not isinstance(sender, NullBrick):
                                        getattr(
                                            sender,
                                            connection["signal"]).connect(slot)
                                    # sender.connect(sender,
                                    #    QtCore.SIGNAL(connection["signal"]),
                                    #    slot)
                    make_connections(item["children"])

            self.splash_screen.set_progress_value(95)
            self.splash_screen.set_message("Connecting bricks...")
            make_connections(config.windows_list)

            # set run mode for every brick
            self.splash_screen.set_progress_value(100)
            self.splash_screen.set_message("Setting run mode...")
            BaseWidget.set_run_mode(True)

            if self.show_maximized:
                main_window.showMaximized()
            else:
                main_window.show()

            for window in self.windows:
                if window._show:
                    window.show()

        if BaseWidget._menubar:
            BaseWidget._menubar.set_exp_mode(False)

        HWR.beamline.force_emit_signals()

        return main_window

    def finalize(self):
        """Finalize gui load"""

        BaseWidget.set_run_mode(False)  # call .stop() for each brick

        self.hardware_repository.close()

        qt_import.QApplication.sendPostedEvents()
        qt_import.QApplication.processEvents()

        self.save_size()

    def save_size(self):
        """Saves window size and coordinates in the gui file"""
        display_config_list = []

        if not self.launch_in_design_mode:
            for window in self.windows:
                window_cfg = self.configuration.windows[str(
                    window.objectName())]
                display_config_list.append({
                    "name": window_cfg.name,
                    "posx": window.x(),
                    "posy": window.y(),
                    "width": window.width(),
                    "height": window.height(),
                })
            try:
                user_settings_filename = os.path.join(self.user_file_dir,
                                                      "settings.dat")
                user_settings_file = open(user_settings_filename, "w")
                user_settings_file.write(repr(display_config_list))
                os.chmod(user_settings_filename, 0o660)
            except BaseException:
                logging.getLogger().exception(
                    "Unable to save window position and size in " +
                    "configuration file: %s" % user_settings_filename)
            else:
                user_settings_file.close()

    def finish_init(self, gui_config_file):
        """Finalize gui init"""

        while True:
            try:
                self.hardware_repository.connect()
            except BaseException:
                logging.getLogger().exception(
                    "Timeout while trying to " +
                    "connect to Hardware Repository server.")
                message = (
                    "Timeout while connecting to Hardware " +
                    "Repository server.\nMake sure the Hardware " +
                    "Repository Server is running on host:\n%s." %
                    str(self.hardware_repository.server_address).split(":")[0])
                if (qt_import.QMessageBox.warning(
                        self,
                        "Cannot connect to Hardware Repository",
                        message,
                        qt_import.QMessageBox.Retry
                        | qt_import.QMessageBox.Cancel
                        | qt_import.QMessageBox.NoButton,
                ) == qt_import.QMessageBox.Cancel):
                    logging.getLogger().warning(
                        "Gave up trying to " +
                        "connect to Hardware Repository server.")
                    break
            else:
                logging.getLogger().info(
                    "Connected to Hardware " + "Repository server %s" %
                    self.hardware_repository.server_address)
                break

        try:
            main_widget = None
            main_widget = self.load_gui(gui_config_file)
            if main_widget:
                set_splash_screen(None)
                self.splash_screen.finish(main_widget)
            del self.splash_screen
        except BaseException:
            logging.getLogger().exception("exception while loading GUI file")
            qt_import.QApplication.exit()

    def customEvent(self, event):
        """Custom event"""

        self.finish_init(event.data)
コード例 #25
0
class MoveBox(qt_import.QWidget):
    """Widget to set position and launch motor mouvement

    Widget composed of:
    A text box to enter new position
    Button to launch new position
    Button to recover last positions
    Button to stop motor
    """

    # define signals
    move_motor_signal = qt_import.pyqtSignal(float)
    clicked_signal = qt_import.pyqtSignal(float)
    stop_motor_signal = qt_import.pyqtSignal()

    def __init__(self, parent=None):
        """"
        Constructor of MoveBox

        :param parent: MoveBox parent widget
        """
        super(MoveBox, self).__init__(parent)

        self.old_positions = []  # history of motor positions

        self.label_move = qt_import.QLabel("go to ", self)
        self.text_move = qt_import.QLineEdit("", self)
        self.cmd_move = qt_import.QPushButton("", self)
        self.cmd_move.setCheckable(True)
        self.cmd_go_back = qt_import.QPushButton("", self)
        self.cmd_stop = qt_import.QPushButton("", self)

        self.text_move.setFixedWidth(
            self.text_move.fontMetrics().width("8888.8888"))
        self.cmd_move.setCheckable(True)
        self.cmd_stop.setIcon(icons.load_icon("stop_small"))
        self.cmd_stop.setEnabled(False)
        self.cmd_go_back.setIcon(icons.load_icon("goback_small"))
        self.cmd_move.setIcon(icons.load_icon("move_small"))
        self.cmd_go_back.setEnabled(False)

        # connections

        self.text_move.textChanged.connect(self.text_move_text_changed)
        self.cmd_move.clicked.connect(self.move_clicked)
        self.cmd_stop.clicked.connect(self.stop_motor_signal)
        self.text_move.returnPressed.connect(self.text_move_return_pressed)
        self.cmd_go_back.clicked.connect(self.go_back_clicked)

        # layout

        hboxlayout = qt_import.QHBoxLayout(self)

        hboxlayout.insertSpacerItem(
            0,
            qt_import.QSpacerItem(0, 0, qt_import.QSizePolicy.Expanding,
                                  qt_import.QSizePolicy.Fixed))

        hboxlayout.addWidget(self.label_move)
        hboxlayout.addWidget(self.text_move)
        hboxlayout.addWidget(self.cmd_move)
        hboxlayout.addWidget(self.cmd_go_back)
        hboxlayout.addWidget(self.cmd_stop)
        hboxlayout.insertSpacerItem(
            0,
            qt_import.QSpacerItem(0, 0, qt_import.QSizePolicy.Expanding,
                                  qt_import.QSizePolicy.Fixed))

        self.setLayout(hboxlayout)

    def move_clicked(self):
        """Act when move clicked."""
        self.text_move_return_pressed()

    def set_old_position(self, position):
        """Recover one of motor's old position."""
        position = str(position)

        if len(self.old_positions) == 20:
            del self.old_positions[-1]

        if position in self.old_positions:
            return

        self.old_positions.insert(0, position)

    def text_move_return_pressed(self):
        """Selected one of motor's old position."""
        try:
            move_position = float(str(self.text_move.text()))
        except BaseException:
            self.cmd_move.setChecked(False)
        else:
            self.move_motor_signal.emit(move_position)

    def text_move_text_changed(self, text):
        """Act when text value change."""
        if text and not self.cmd_move.isChecked():
            self.cmd_move.setEnabled(True)
        else:
            self.cmd_move.setEnabled(False)

    def go_back_clicked(self):
        """Act when 'go to old position' button clicked."""
        old_positions_menu = qt_import.QMenu(self)
        old_positions_menu.addSection(
            str("<nobr><b>Last positions :</b></nobr>"))

        old_positions_menu.addSeparator()

        for i in range(len(self.old_positions)):
            receiver = lambda i: self.go_to_old_position(i)
            position_action = old_positions_menu.addAction(
                self.old_positions[i])
            position_action.triggered.connect(receiver)

        old_positions_menu.exec_(qt_import.QCursor.pos())

    def go_to_old_position(self, old_pos_id):
        """Move motor to selected old position."""
        pos = self.old_positions[old_pos_id]
        self.text_move.setText(pos)
        self.text_move_return_pressed()

    def set_is_moving(self, moving):
        """Update display according to motor moving or not."""
        if moving:
            self.text_move.setText("")
            self.cmd_move.setChecked(True)
            self.cmd_move.setEnabled(False)
            self.cmd_go_back.setEnabled(False)
            self.cmd_stop.setEnabled(True)
        else:
            self.cmd_move.setChecked(False)
            if len(self.text_move.text()) > 0:
                self.cmd_move.setEnabled(True)
            else:
                self.cmd_move.setEnabled(False)
            if len(self.old_positions) > 0:
                self.cmd_go_back.setEnabled(True)
            self.cmd_stop.setEnabled(False)
コード例 #26
0
class AcquisitionSsxWidget(qt_import.QWidget):

    acqParametersChangedSignal = qt_import.pyqtSignal(list)

    def __init__(
        self,
        parent=None,
        name=None,
        fl=0,
        acq_params=None,
        path_template=None,
        layout="vertical",
    ):
        """
        Loads ui file that defines the gui layout.
        Initiates QLineEdits by adding limits, precision
        Connects to qt signals to update acquisition parameters
        :param parent:
        :param name:
        :param fl:
        :param acq_params:
        :param path_template:
        :param layout:
        """

        qt_import.QWidget.__init__(self, parent, qt_import.Qt.WindowFlags(fl))

        if name is not None:
            self.setObjectName(name)

        # Internal variables --------------------------------------------------
        self.value_changed_list = []

        # Properties ----------------------------------------------------------

        # Signals -------------------------------------------------------------

        # Slots ---------------------------------------------------------------

        # Graphic elements ----------------------------------------------------
        if acq_params is None:
            self._acquisition_parameters = queue_model_objects.AcquisitionParameters(
            )
        else:
            self._acquisition_parameters = acq_params

        if path_template is None:
            self._path_template = queue_model_objects.PathTemplate()
        else:
            self._path_template = path_template

        self._acquisition_mib = DataModelInputBinder(
            self._acquisition_parameters)

        self.acq_widget_layout = qt_import.load_ui_file(
            "acquisition_widget_vertical_ssx_layout.ui")
        # Layout --------------------------------------------------------------
        __main_vlayout = qt_import.QVBoxLayout(self)
        __main_vlayout.addWidget(self.acq_widget_layout)
        __main_vlayout.setSpacing(0)
        __main_vlayout.setContentsMargins(0, 0, 0, 0)

        # SizePolicies --------------------------------------------------------

        # Qt signal/slot connections ------------------------------------------
        self.acq_widget_layout.num_triggers_ledit.textChanged.connect(
            self.num_triggers_ledit_changed)
        self.acq_widget_layout.num_images_per_trigger_ledit.textChanged.connect(
            self.num_images_per_trigger_ledit_changed)

        self.acq_widget_layout.exp_time_ledit.textChanged.connect(
            self.exposure_time_ledit_changed)
        self.acq_widget_layout.detector_roi_mode_combo.activated.connect(
            self.detector_roi_mode_changed)
        self.acq_widget_layout.energy_ledit.textEdited.connect(
            self.energy_ledit_changed)
        self.acq_widget_layout.transmission_ledit.textEdited.connect(
            self.transmission_ledit_changed)
        self.acq_widget_layout.resolution_ledit.textEdited.connect(
            self.resolution_ledit_changed)

        # Other ---------------------------------------------------------------
        self.energy_validator = qt_import.QDoubleValidator(
            4, 25, 4, self.acq_widget_layout.energy_ledit)
        self.resolution_validator = qt_import.QDoubleValidator(
            0, 15, 3, self.acq_widget_layout.resolution_ledit)
        self.transmission_validator = qt_import.QDoubleValidator(
            0, 100, 3, self.acq_widget_layout.transmission_ledit)
        self.exp_time_validator = qt_import.QDoubleValidator(
            0.0001, 10000, 7, self.acq_widget_layout.exp_time_ledit)
        self.num_triggers_validator = qt_import.QIntValidator(
            1, 9999999, self.acq_widget_layout.num_triggers_ledit)
        self.num_images_per_trigger_validator = qt_import.QIntValidator(
            1, 9999999, self.acq_widget_layout.num_images_per_trigger_ledit)
        self.num_img_validator = qt_import.QIntValidator(
            1, 9999999, self.acq_widget_layout.num_images_ledit)
        self.hare_num_validator = qt_import.QIntValidator(
            1, 9999999, self.acq_widget_layout.hare_num_ledit)

        limits_dict = HWR.beamline.acquisition_limit_values

        tpl = limits_dict.get("exposure_time")
        if tpl:
            self.exp_time_validator.setRange(tpl[0], tpl[1], 6)

        self._acquisition_mib.bind_value_update(
            "exp_time",
            self.acq_widget_layout.exp_time_ledit,
            float,
            self.exp_time_validator,
        )

        self._acquisition_mib.bind_value_update(
            "num_triggers",
            self.acq_widget_layout.num_triggers_ledit,
            int,
            self.num_triggers_validator,
        )

        self._acquisition_mib.bind_value_update(
            "num_images_per_trigger",
            self.acq_widget_layout.num_images_per_trigger_ledit,
            int,
            self.num_images_per_trigger_validator,
        )

        self._acquisition_mib.bind_value_update(
            "hare_num",
            self.acq_widget_layout.hare_num_ledit,
            int,
            self.hare_num_validator,
        )

        tpl = limits_dict.get("number_of_images")
        if tpl:
            self.num_img_validator.setRange(tpl[0], tpl[1])

        self._acquisition_mib.bind_value_update(
            "num_images",
            self.acq_widget_layout.num_images_ledit,
            int,
            self.num_img_validator,
        )

        self._acquisition_mib.bind_value_update(
            "energy", self.acq_widget_layout.energy_ledit, float,
            self.energy_validator)
        self.update_energy_limits(
            (self.energy_validator.bottom(), self.energy_validator.top()))

        self._acquisition_mib.bind_value_update(
            "transmission",
            self.acq_widget_layout.transmission_ledit,
            float,
            self.transmission_validator,
        )
        self.update_transmission_limits((self.transmission_validator.bottom(),
                                         self.transmission_validator.top()))

        self._acquisition_mib.bind_value_update(
            "resolution",
            self.acq_widget_layout.resolution_ledit,
            float,
            self.resolution_validator,
        )

        self.init_detector_roi_modes()
        self.acq_widget_layout.detector_roi_mode_label.setEnabled(False)
        self.acq_widget_layout.detector_roi_mode_combo.setEnabled(False)
        self.update_exp_time_limits()

    def update_osc_total_range(self):
        """
        :return: None
        """
        return

    def use_osc_start(self, status):
        """
        :param status: boolean
        :return: None
        """
        return

    def use_max_osc_range(self, status):
        """
        :param status: boolean
        :return: None
        """
        return

    def use_kappa(self, status):
        """
        :param status: boolean
        :return: None
        """
        return

    def exposure_time_ledit_changed(self, value):
        """
        Updates exposure time QLineEdit
        :param value: str
        :return: None
        """
        self.update_total_exp_time()
        self.emit_acq_parameters_changed()

    def energy_ledit_changed(self, value):
        """
        Fixes energy value. Energy change will not rewrite the typed energy value
        :param value: str
        :return: None
        """
        if "energy" not in self.value_changed_list:
            self.value_changed_list.append("energy")
        self.emit_acq_parameters_changed()

    def update_energy(self, energy):
        """
        Updates energy QLineEdit
        :param energy: energy in keV (float)
        :param wav: wavelength in A (float)
        :return: None
        """
        if ("energy" not in self.value_changed_list
                and not self.acq_widget_layout.energy_ledit.hasFocus()):
            self.acq_widget_layout.energy_ledit.setText(str(energy))
        self.emit_acq_parameters_changed()

    def transmission_ledit_changed(self, transmission):
        """
        Event when a value in the transmission QLineEdit is changed
        :param transmission: in perc. (str)
        :return: None
        """
        if "transmission" not in self.value_changed_list:
            self.value_changed_list.append("transmission")
        self.emit_acq_parameters_changed()

    def update_transmission(self, transmission):
        """
        Updates transmission QLineEdit
        :param transmission: in perc. (float)
        :return: None
        """
        if "transmission" not in self.value_changed_list:
            self.acq_widget_layout.transmission_ledit.setText(
                str(transmission))
        self.emit_acq_parameters_changed()

    def resolution_ledit_changed(self, resolution):
        """
        Method called when user changes resolution
        :param resolution: in A (float)
        :return: None
        """
        if "resolution" not in self.value_changed_list:
            self.value_changed_list.append("resolution")
        self.emit_acq_parameters_changed()

    def update_resolution(self, resolution):
        """
        Updates resolution QLineEdit
        :param resolution: A (float)
        :return: None
        """
        if ("resolution" not in self.value_changed_list
                and not self.acq_widget_layout.resolution_ledit.hasFocus()):
            self.acq_widget_layout.resolution_ledit.setText(str(resolution))
        self.emit_acq_parameters_changed()

    def update_energy_limits(self, limits):
        """
        Updates energy limits
        :param limits: list of two floats
        :return: None
        """
        if limits:
            self.energy_validator.setBottom(limits[0])
            self.energy_validator.setTop(limits[1])
            self.acq_widget_layout.energy_ledit.setToolTip(
                "Energy limits %0.4f : %0.4f keV\n" % (limits[0], limits[1]) +
                "4 digits precision.")
            self._acquisition_mib.validate_all()

    def update_transmission_limits(self, limits):
        """
        Updates transmission limits
        :param limits: list of two floats
        :return: None
        """
        if limits:
            self.transmission_validator.setBottom(limits[0])
            self.transmission_validator.setTop(limits[1])
            self.acq_widget_layout.transmission_ledit.setToolTip(
                "Transmission limits %0.2f : %0.2f %%\n" %
                (limits[0], limits[1]) + "2 digits precision.")
            self._acquisition_mib.validate_all()

    def update_resolution_limits(self, limits):
        """
        Updates resolution limits
        :param limits: list of two floats
        :return: None
        """
        if limits:
            self.resolution_validator.setBottom(limits[0])
            self.resolution_validator.setTop(limits[1])
            self.acq_widget_layout.resolution_ledit.setToolTip(
                "Resolution limits %0.4f : %0.4f %s\n" %
                (limits[0], limits[1], chr(197)) + "4 digits precision.")
            self._acquisition_mib.validate_all()

    def update_detector_exp_time_limits(self, limits):
        """
        Updates exposure time limits
        :param limits: list of two floats
        :return: None
        """
        if limits:
            self.exp_time_validator.setRange(limits[0], limits[1], 6)
            self.acq_widget_layout.exp_time_ledit.setToolTip(
                "Exposure time limits %0.6f s : %0.1f s\n" %
                (limits[0], limits[1]) + "6 digits precision.")
            self._acquisition_mib.validate_all()

    def init_detector_roi_modes(self):
        """
        Initiates detetor ROI modes. Available modes are added to the combobox
        :return: None
        """
        roi_modes = HWR.beamline.detector.get_roi_modes()
        if (len(roi_modes) > 0 and
                self.acq_widget_layout.detector_roi_mode_combo.count() == 0):
            for roi_mode in roi_modes:
                self.acq_widget_layout.detector_roi_mode_combo.addItem(
                    roi_mode)
        self.acq_widget_layout.detector_roi_mode_label.setEnabled(
            len(roi_modes) > 1)
        self.acq_widget_layout.detector_roi_mode_combo.setEnabled(
            len(roi_modes) > 1)

    def update_detector_roi_mode(self, roi_mode_index):
        """
        Method called when roi mode has been chaned
        :param roi_mode_index: int
        :return: None
        """
        if (roi_mode_index is not None and
                self.acq_widget_layout.detector_roi_mode_combo.count() > 0):
            self.acq_widget_layout.detector_roi_mode_combo.setCurrentIndex(
                roi_mode_index)

    def detector_roi_mode_changed(self, roi_mode_index):
        """
        Method called when user selects a detector roi mode
        :param roi_mode_index: int
        :return:
        """
        HWR.beamline.detector.set_roi_mode(roi_mode_index)

    def update_osc_range_per_frame_limits(self):
        """
        Updates osc range per frame limits
        :return: None
        """
        return

    def update_exp_time_limits(self):
        self.update_detector_exp_time_limits(
            HWR.beamline.detector.get_exposure_time_limits())

    def update_osc_start(self, value):
        """
        Updates osc start
        :param value: float
        :return: None
        """
        return

    def update_kappa(self, value):
        """
        Updates kappa value
        :param value: float
        :return:
        """
        return

    def update_kappa_phi(self, value):
        """
        Updates kappa phi value
        :param value: float
        :return: None
        """
        return

    def update_data_model(self, acquisition_parameters, path_template):
        """
        Updates data model
        :param acquisition_parameters: AcquisitionParameters
        :param path_template: PathTemplate
        :return: None
        """
        self._acquisition_parameters = acquisition_parameters
        self._path_template = path_template
        self._acquisition_mib.set_model(acquisition_parameters)
        self.emit_acq_parameters_changed()

    def check_parameter_conflict(self):
        """
        Checks for parameter conflicts
        :return: list of conflicts
        """
        return self._acquisition_mib.validate_all()

    def emit_acq_parameters_changed(self):
        """
        Emits acqParametersChangedSignal
        :return: None
        """
        self.acqParametersChangedSignal.emit(
            self._acquisition_mib.validate_all())

    def set_energies(self, energies):
        """
        Sets energies
        :param energies:
        :return: None
        """
        return

    def num_triggers_ledit_changed(self, value):
        """
        Updates num images and total exp time
        :param value: QString
        :return: None
        """
        if "num_triggers" not in self.value_changed_list:
            self.value_changed_list.append("num_triggers")
        self.update_num_images()
        self.update_total_exp_time()
        self.emit_acq_parameters_changed()

    def num_images_per_trigger_ledit_changed(self, value):
        """
                Updates num images and total exp time
                :param value: QString
                :return: None
                """
        if "num_images_per_trigger" not in self.value_changed_list:
            self.value_changed_list.append("num_images_per_trigger")
        self.update_num_images()
        self.update_total_exp_time()
        self.emit_acq_parameters_changed()

    def update_num_images(self):
        """
        Updates num images
        :return: None
        """
        self.acq_widget_layout.num_images_ledit.setText(
            str(self._acquisition_parameters.num_triggers *
                self._acquisition_parameters.num_images_per_trigger))

    def update_total_exp_time(self):
        """Updates total exposure time
        :return: None
        """
        try:
            self.acq_widget_layout.exp_time_total_ledit.setText(
                "%.2f" %
                (float(self.acq_widget_layout.exp_time_ledit.text()) *
                 float(self.acq_widget_layout.num_images_ledit.text())))
        except BaseException:
            pass
コード例 #27
0
class PlotWidget(qt_import.QWidget):

    mouseMovedSignal = qt_import.pyqtSignal(float, float)
    mouseClickedSignal = qt_import.pyqtSignal(float, float)
    mouseDoubleClickedSignal = qt_import.pyqtSignal(float, float)
    mouseLeftSignal = qt_import.pyqtSignal()

    def __init__(self, parent=None):
        qt_import.QWidget.__init__(self, parent)

        self.curves_dict = {}
        self.visible_curve = None

        self.view_box = CustomViewBox()
        self.one_dim_plot = pg.PlotWidget(viewBox=self.view_box)
        self.two_dim_plot = pg.ImageView()

        self.one_dim_plot.showGrid(x=True, y=True)
        self.two_dim_plot.ui.histogram.hide()
        self.two_dim_plot.ui.roiBtn.hide()
        self.two_dim_plot.ui.menuBtn.hide()
        self.two_dim_plot.setFixedWidth(400)

        hlayout = qt_import.QHBoxLayout(self)
        hlayout.addWidget(self.one_dim_plot)
        hlayout.addWidget(self.two_dim_plot)

        colors = [(0, 0, 0),
                  (255, 0, 0),
                  (255, 255, 0),
                  (255, 255, 255)]
        cmap = pg.ColorMap(pos=np.linspace(0.0, 1.0, 4), color=colors)
        self.two_dim_plot.setColorMap(cmap)

        self.one_dim_plot.scene().sigMouseMoved.connect(self.one_dim_plot_mouse_moved)
        self.two_dim_plot.scene.sigMouseMoved.connect(self.two_dim_plot_mouse_moved)

    def set_plot_type(self, plot_type):
        self.one_dim_plot.setVisible(plot_type == "1D")
        self.two_dim_plot.setVisible(plot_type == "2D")

    def add_curve(self, key, y_array, x_array, color):
        self.curves_dict[key] = self.one_dim_plot.plot(
            y=y_array,
            x=x_array,
            symbolPen='w',
            symbolBrush=color,
            symbolSize=3
        )
        self.visible_curve = key

    def add_energy_scan_plot(self, scan_info):
        self.one_dim_plot.setTitle(scan_info["title"])
        pen = pg.mkPen('w', width=2)
        plot = self.one_dim_plot.plot(pen=pen)
        plot.setDownsampling(method="peak")
        plot.setClipToView(True)
        self.curves_dict["energyscan"] = plot
    
    def add_energy_scan_plot_point(self, x, y):
        if self.curves_dict["energyscan"].xData is None:
            x_data = [x]
            y_data = [y]
        else:
            x_data = np.append(self.curves_dict["energyscan"].xData, x)
            y_data = np.append(self.curves_dict["energyscan"].yData, y)
        self.curves_dict["energyscan"].setData(y=y_data, x=x_data)

    def plot_energy_scan_results(self, data, title):
        pen = pg.mkPen('w', width=2)
        #x_data = [item[0] for item in data]
        #y_data = [item[1] for item in data]
        self.one_dim_plot.plot(data, pen=pen)

    def plot_chooch_results(
        self,
        pk,
        fppPeak,
        fpPeak,
        ip,
        fppInfl,
        fpInfl,
        rm,
        chooch_graph_x,
        chooch_graph_y1,
        chooch_graph_y2,
        title,
    ):
        pen = pg.mkPen('r', width=3)
        self.one_dim_plot.plot(y=chooch_graph_y1, x=chooch_graph_x, pen=pen)
        pen = pg.mkPen('b', width=3)
        self.one_dim_plot.plot(y=chooch_graph_y2, x=chooch_graph_x, pen=pen)

    def update_curves(self, result):
        for key in result.keys():
            if key in self.curves_dict:
                self.curves_dict[key].setData(y=result[key]) #, x=result['x_array'])

    def plot_result(self, result, aspect=None):
        self.two_dim_plot.setImage(result)

    def autoscale_axes(self):
        #self.one_dim_plot.enableAutoRange(self.view_box.XYAxes, True)
        self.view_box.autoRange(padding=0.02)
        
        self.view_box.setYRange(min=0, max=max(self.curves_dict[self.visible_curve].yData))

    def clear(self):
        self.one_dim_plot.clear()
        self.two_dim_plot.clear()
        self.curves_dict = {}

    def hide_all_curves(self):
        for key in self.curves_dict.keys():
            self.curves_dict[key].hide()
        self.visible_curve = None

    def show_curve(self, curve_key):
        for key in self.curves_dict.keys():
            if key == curve_key:
                self.curves_dict[key].show()
                self.visible_curve = key
                return

    def one_dim_plot_mouse_moved(self, mouse_event):
        mouse_point = self.one_dim_plot.plotItem.vb.mapSceneToView(mouse_event)
        self.mouseMovedSignal.emit(mouse_point.x(), mouse_point.y())

    def two_dim_plot_mouse_moved(self, mouse_event):
        mouse_point = self.two_dim_plot.imageItem.getViewBox().mapSceneToView(mouse_event)
        self.mouseMovedSignal.emit(mouse_point.x(), mouse_point.y())

    def mouse_double_clicked(self, press_event, double):
        pass

    def set_yticks(self, ticks):
        y_axis = self.one_dim_plot.getAxis("left")
        y_axis.setTicks([ticks])

    def set_x_axis_limits(self, limits):
        self.one_dim_plot.setRange(xRange=limits)

    def set_y_axis_limits(self, limits):
        self.one_dim_plot.setRange(yRange=limits)
コード例 #28
0
ファイル: property_editor.py プロジェクト: rhfogh/mxcube
class ConfigurationTable(qt_import.QTableWidget):

    propertyChangedSignal = qt_import.pyqtSignal(str, object, object)

    def __init__(self, parent):

        qt_import.QTableWidget.__init__(self, parent)

        self.display_hwobj = False
        self.property_bag = None

        self.setObjectName("configurationTable")
        self.setFrameShape(qt_import.QFrame.StyledPanel)
        self.setFrameShadow(qt_import.QFrame.Sunken)
        self.setContentsMargins(0, 3, 0, 3)
        self.setColumnCount(4)
        self.setSelectionMode(qt_import.QTableWidget.NoSelection)

        # self.setHorizontalHeaderLabels([self.trUtf8('Property'),
        #                                self.trUtf8('Value'),
        #                                self.trUtf8(''),
        #                                self.trUtf8('Comment')])
        self.setHorizontalHeaderLabels(["Property", "Value", "", "Comment"])

        self.setSizePolicy(
            qt_import.QSizePolicy.MinimumExpanding, qt_import.QSizePolicy.Fixed
        )
        self.setHorizontalScrollBarPolicy(qt_import.Qt.ScrollBarAlwaysOff)

        self.cellChanged.connect(self.on_cell_changed)

    def clear(self):
        for i in range(self.rowCount()):
            self.removeRow(i)
        self.setRowCount(0)
        self.property_bag = None

    def set_property_bag(self, property_bag, show_hidden=False, display_hwobj=False):
        self.display_hwobj = display_hwobj
        self.clear()

        if self.property_bag is not None:
            for prop in self.property_bag:
                prop._editor = None

        self.property_bag = property_bag

        if self.property_bag is not None:
            i = 0
            for prop in self.property_bag:
                prop._editor = weakref.ref(self)
                prop_name = prop.get_name()

                if not show_hidden and prop.hidden:
                    continue

                if display_hwobj:
                    if not prop_name.startswith("hwobj_"):
                        continue
                    else:
                        prop_name = prop_name.replace("hwobj_", "")
                else:
                    if prop_name.startswith("hwobj_"):
                        continue

                self.setRowCount(i + 1)
                temp_table_item = qt_import.QTableWidgetItem(prop_name)
                temp_table_item.setFlags(qt_import.Qt.ItemIsEnabled)
                self.blockSignals(True)
                self.setItem(i, 0, temp_table_item)
                self.set_widget_from_property(i, prop)

                temp_table_item = qt_import.QTableWidgetItem(prop.comment)
                temp_table_item.setFlags(qt_import.Qt.ItemIsEnabled)
                self.setItem(i, 3, temp_table_item)

                self.blockSignals(False)

                validation_panel = ValidationTableItem(self)
                self.setCellWidget(i, 2, validation_panel)
                validation_panel.ok_button.clicked.connect(self.on_validate_click)
                validation_panel.cancel_button.clicked.connect(self.on_invalidate_click)
                validation_panel.reset_button.clicked.connect(self.on_reset_click)
                i += 1
            self.setEnabled(i > 0)
        self.resizeColumnsToContents()
        self.setFixedHeight((self.rowCount() + 1) * (self.rowHeight(0) + 2))
        # self.adjustSize()
        self.parent().adjustSize()
        # self.parent().resize(self.parent().sizeHint())

    def set_widget_from_property(self, row, prop):
        """Adds new property to the propery table

        :param row: selected row
        :type row: int
        :param prop: property
        :type prop: dict
        """
        if prop.get_type() == "boolean":
            new_property_item = qt_import.QTableWidgetItem("")
            self.setItem(row, 1, new_property_item)
            if prop.get_user_value():
                self.item(row, 1).setCheckState(qt_import.Qt.Checked)
            else:
                self.item(row, 1).setCheckState(qt_import.Qt.Unchecked)
        elif prop.get_type() == "combo":
            choices_list = []
            choices = prop.get_choices()
            for choice in choices:
                choices_list.append(choice)
            new_property_item = ComboBoxTableItem(self, row, 1, choices_list)
            new_property_item.setCurrentIndex(
                new_property_item.findText(prop.get_user_value())
            )
            self.setCellWidget(row, 1, new_property_item)
        elif prop.get_type() == "file":
            new_property_item = FileTableItem(
                self, row, 1, prop.get_user_value(), prop.getFilter()
            )
            self.setCellWidget(row, 1, new_property_item)
        elif prop.get_type() == "color":
            new_property_item = ColorTableItem(self, row, 1, prop.get_user_value())
            self.setCellWidget(row, 1, new_property_item)
        else:
            if prop.get_user_value() is None:
                temp_table_item = qt_import.QTableWidgetItem("")
            else:
                temp_table_item = qt_import.QTableWidgetItem(str(prop.get_user_value()))
            self.setItem(row, 1, temp_table_item)
        self.resizeColumnsToContents()
        # self.parent().adjustSize()

    def on_cell_changed(self, row, col):
        """Assignes new value to the property, clicked on the the
           property table
        """
        col += 1
        prop_name = str(self.item(row, 0).text())
        if self.display_hwobj:
            prop_name = "hwobj_" + prop_name

        item_property = self.property_bag.get_property(prop_name)
        old_value = item_property.get_user_value()

        if item_property.get_type() == "boolean":
            item_property.set_value(self.item(row, 1).checkState())
        elif item_property.get_type() == "combo":
            item_property.set_value(self.cellWidget(row, 1).currentText())
        elif item_property.get_type() == "file":
            item_property.set_value(self.cellWidget(row, 1).get_filename())
        elif item_property.get_type() == "color":
            item_property.set_value(self.cellWidget(row, 1).color)
        else:
            try:
                item_property.set_value(str(self.item(row, 1).text()))
            except BaseException:
                logging.getLogger().error(
                    "Cannot assign value %s to property %s"
                    % (str(self.item(row, 1).text()), prop_name)
                )

            if item_property.get_user_value() is None:
                self.item(row, 1).setText("")
            else:
                self.item(row, 1).setText(str(item_property.get_user_value()))

        if not old_value == item_property.get_user_value():
            self.propertyChangedSignal.emit(
                prop_name, old_value, item_property.get_user_value()
            )

    def on_validate_click(self):
        # current row, col 1, accept = 1, replace = 0
        self.endEdit(self.currentRow(), 1, 1, 0)
        self.activateNextCell()

    def on_invalidate_click(self):
        # current row, col 1, accept = 0, replace = 0
        self.endEdit(self.currentRow(), 1, 0, 0)

    def on_reset_click(self):
        self.endEdit(self.currentRow(), 1, 0, 0)
        prop_name = str(self.item(self.currentRow(), 0).text())
        if self.display_hwobj:
            prop_name = "hwobj_" + prop_name

        prop = self.property_bag.get_property(prop_name)

        default_value = prop.getDefaultValue()
        if not default_value is None:
            prop.set_value(default_value)

        self.set_widget_from_property(self.currentRow(), prop)

    def beginEdit(self, row, col, replace):
        if col == 1 and row >= 0:
            self.item(row, 2).setEnabled(1)

        return qt_import.QTableWidget.beginEdit(self, row, col, replace)

    def endEdit(self, row, col, accept, replace):
        if col == 1 and row >= 0:
            self.item(row, 2).setEnabled(0)

            if accept:
                prop_name = str(self.item(row, 0).text())
                if self.display_hwobj:
                    prop_name = "hwobj_" + prop_name
                prop = self.property_bag.get_property(prop_name)

                old_value = prop.get_user_value()

                if prop.get_type() == "boolean":
                    prop.set_value(self.item(row, 1).isChecked())
                elif prop.get_type() == "combo":
                    prop.set_value(self.item(row, 1).currentText())
                else:
                    try:
                        prop.set_value(str(self.text(row, 1)))
                    except BaseException:
                        logging.getLogger().error(
                            "Cannot assign value to property %s" % prop_name
                        )

                    if prop.get_user_value() is None:
                        self.setText(row, 1, "")
                    else:
                        self.setText(row, 1, str(prop.get_user_value()))

                if not old_value == prop.get_user_value():
                    self.propertyChangedSignal.emit(
                        prop_name, old_value, prop.get_user_value()
                    )
                    # self.emit(QtCore.SIGNAL('propertyChanged'),
                    # (prop_name, old_value, prop.get_user_value(), ))

        return qt_import.QTableWidget.endEdit(self, row, col, accept, replace)