コード例 #1
0
ファイル: gui_util.py プロジェクト: flueke/mesycontrol
    def setReadOnly(self, ro):
        pal = QtGui.QPalette()
        if ro:
            pal.setColor(QtGui.QPalette.Base, QtGui.QColor('lightgrey'))
        self.setPalette(pal)

        super(NotesTextEdit, self).setReadOnly(ro)
コード例 #2
0
    def paint(self, painter, option, index):
        node = index.internalPointer()

        option = QtWidgets.QStyleOptionViewItem(option)
        self.initStyleOption(option, index)

        if (option.state & QtWidgets.QStyle.State_Selected
                and isinstance(node, (ctm.DeviceNode, htm.DeviceNode))
                and self.director.linked_mode):

            device = node.ref
            color = None

            if device.idc_conflict or device.address_conflict:
                color = QtGui.QColor('darkRed')

            elif device.has_hw and device.has_cfg:
                if device.hw.is_connected():
                    if device.config_applied is True:
                        color = QtGui.QColor('darkGreen')
                    elif device.config_applied is False:
                        color = QtGui.QColor('darkOrange')
                    # else config_applied should be None meaning "unknown"

            if color is not None:
                option.palette.setColor(QtGui.QPalette.Highlight, color)

        super(MCTreeItemDelegate, self).paint(painter, option, index)
コード例 #3
0
ファイル: dialogs.py プロジェクト: flueke/mesycontrol
    def __init__(self,
                 serial_ports_usb,
                 serial_ports_serial,
                 urls_in_use=list(),
                 url=None,
                 do_connect_default=True,
                 autoconnect_default=True,
                 title="Add MRC",
                 parent=None):
        super(AddMRCDialog, self).__init__(parent)
        self.urls_in_use = urls_in_use
        self.ui = util.loadUi(":/ui/connect_dialog.ui")
        layout = QtWidgets.QHBoxLayout(self)
        layout.addWidget(self.ui)

        self.setWindowTitle(title)
        self.ui.buttonBox.button(
            QtWidgets.QDialogButtonBox.Ok).setEnabled(False)

        self.ui.accepted.connect(self.accept)
        self.ui.rejected.connect(self.reject)

        for combo in (self.ui.combo_serial_port_usb,
                      self.ui.combo_serial_port_serial):
            combo.setValidator(
                QtGui.QRegExpValidator(QtCore.QRegExp('.+'), None))

        self.ui.le_tcp_host.setValidator(
            QtGui.QRegExpValidator(QtCore.QRegExp('.+'), None))
        self.ui.le_mesycontrol_host.setValidator(
            QtGui.QRegExpValidator(QtCore.QRegExp('.+'), None))
        self.ui.le_tcp_host.setText('localhost')
        self.ui.le_mesycontrol_host.setText('localhost')
        self.ui.cb_connect.setChecked(do_connect_default)
        self.ui.cb_autoconnect.setChecked(autoconnect_default)

        for port in serial_ports_usb:
            self.ui.combo_serial_port_usb.addItem(port)

        for port in serial_ports_serial:
            self.ui.combo_serial_port_serial.addItem(port)

        for le in self.ui.findChildren(QtWidgets.QLineEdit):
            le.textChanged.connect(self._validate_inputs)

        for combo in self.ui.findChildren(QtWidgets.QComboBox):
            combo.currentIndexChanged.connect(self._validate_inputs)
            combo.editTextChanged.connect(self._validate_inputs)

        for spin in self.ui.findChildren(QtWidgets.QSpinBox):
            spin.valueChanged.connect(self._validate_inputs)

        self.ui.stacked_widget.currentChanged.connect(self._validate_inputs)
        self._validate_inputs()

        self._result = None

        if url is not None:
            self._set_url(url)
コード例 #4
0
    def data(self, column, role):
        mrc = self.ref

        if not mrc:
            return None

        if column == 0 and role == Qt.DisplayRole:
            ret = mrc.get_display_url()
            if mrc.hw is not None and mrc.hw.is_silenced():
                ret += " (silenced)"
            if mrc.hw is not None and not mrc.hw.has_write_access():
                ret += " (read-only)"
            return ret

        if column == 0:
            if mrc.hw is not None and not mrc.hw.is_connected() and mrc.hw.last_connection_error is not None:
                if role == Qt.DecorationRole:
                    return QtGui.QPixmap(":/warning.png")

                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    return "%s: %s" % (mrc.get_display_url(), mrc.hw.last_connection_error)

            elif mrc.hw is not None and mrc.hw.is_connecting():
                if role == Qt.DecorationRole:
                    return QtGui.QPixmap(":/connecting.png")

                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    return "Connecting to %s" % (mrc.get_display_url(),)

            elif mrc.hw is None or mrc.hw.is_disconnected():
                if role == Qt.DecorationRole:
                    return QtGui.QPixmap(":/disconnected.png")

                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    return "Disconnected from %s" % (mrc.get_display_url(),)

            elif mrc.hw is not None and mrc.hw.is_connected() and any(d.address_conflict for d in mrc.hw):
                if role == Qt.DecorationRole:
                    return QtGui.QPixmap(":/warning.png")

                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    return "Address conflict detected"

            elif mrc.hw is not None and mrc.hw.is_connected():
                if role == Qt.DecorationRole:
                    return QtGui.QPixmap(":/connected.png")

                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    return "Connected to %s" % mrc.get_display_url()
コード例 #5
0
    def _get_palette_old(self, rf):
        pal = QtGui.QPalette(self._original_palette)

        try:
            result = rf.result()
            if isinstance(result, bm.SetResult) and not result:
                raise RuntimeError()
        except Exception:
            pal.setColor(QtGui.QPalette.Base, QtGui.QColor('red'))
            log.debug("_get_palette: Exception from result future; setting red background color")
            return pal

        if (self.write_mode == util.COMBINED
                and self.device.has_hw
                and self.device.has_cfg
                and self.profile is not None
                and self.get_write_profile().should_be_stored()):
            try:
                log.debug("_get_palette: comparing hardware and config")
                f_cfg = self.device.cfg.get_parameter(self.write_address)
                f_hw  = self.device.hw.get_parameter(self.read_address)

                if not f_cfg.done():
                    log.debug("_get_palette: adding update callback to config future")
                    f_cfg.add_done_callback(self._update_wrapper)

                if not f_hw.done():
                    log.debug("_get_palette: adding update callback to hardware future")
                    f_hw.add_done_callback(self._update_wrapper)

                if f_cfg.done() and f_hw.done():
                    cfg_value = int(f_cfg)
                    hw_value  = int(f_hw)
                    log.debug("_get_palette: both cfg and hw futures are done; ra=%d, wa=%d, cfg_value=%d, hw_value=%d",
                            self.read_address, self.write_address, cfg_value, hw_value)

                    if cfg_value != hw_value:
                        log.debug("_get_palette: ra=%d, wa=%d, cfg and hw differ; returning orange",
                                self.read_address, self.write_address)
                        pal.setColor(QtGui.QPalette.Base, QtGui.QColor('orange'))

            except (future.IncompleteFuture, KeyError,
                    util.SocketError, util.Disconnected):
                log.exception("_get_palette")

        else:
            log.debug("_get_palette: hw vs cfg condition failed; returning original palette")

        return pal
コード例 #6
0
    def __init__(self, gui_app, parent=None):
        super(TutorialWidget, self).__init__(parent)
        self.gui_app = gui_app

        #self.setStyleSheet('background: lightyellow;')

        self.text_doc = QtGui.QTextDocument(self)

        f = QtCore.QFile(":/quickstart.html")
        if f.open(QtCore.QIODevice.ReadOnly):
            s = QtCore.QTextStream(f)
            html = s.readAll()
        else:
            html = "quickstart.html not found!"

        self.text_doc.setHtml(html)

        self.text_browser = TutorialTextBrowser(openLinks=False)
        self.text_browser.setDocument(self.text_doc)
        self.text_browser.href_hover.connect(self._on_href_hover)

        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.text_browser)

        self.flasher = UIFlasher(widget=self)
コード例 #7
0
ファイル: util.py プロジェクト: flueke/mesycontrol
def make_title_label(title):
    title_font = QtGui.QFont()
    title_font.setBold(True)
    label = QtWidgets.QLabel(title)
    label.setFont(title_font)
    label.setAlignment(Qt.AlignCenter)
    return label
コード例 #8
0
    def _get_palette(self, rf):
        pal = QtGui.QPalette(self._original_palette)

        try:
            result = rf.result()
            if isinstance(result, bm.SetResult) and not result:
                raise RuntimeError()
        except Exception:
            pal.setColor(QtGui.QPalette.Base, QtGui.QColor('red'))
            log.debug("_get_palette: Exception from result future; setting red background color")
            return future.Future().set_result(pal)

        ret = future.Future()

        if (self.write_mode == util.COMBINED
                and self.device.has_hw
                and self.device.has_cfg
                and self.profile is not None
                and self.get_write_profile().should_be_stored()):
            try:
                f_cfg    = self.device.cfg.get_parameter(self.write_address)
                f_hw     = self.device.hw.get_parameter(self.read_address)
                f_params = self.device.get_config_parameters()

                def all_done(_):
                    has_param = any(pp.address in (self.write_address, self.read_address) for pp in f_params.result())
                    if has_param:
                        cfg_value = int(f_cfg)
                        hw_value  = int(f_hw)

                        if cfg_value != hw_value:
                            log.debug("_get_palette: ra=%d, wa=%d, cfg and hw differ; returning orange",
                                    self.read_address, self.write_address)
                            pal.setColor(QtGui.QPalette.Base, QtGui.QColor('orange'))

                    ret.set_result(pal)

                future.all_done(f_cfg, f_hw, f_params).add_done_callback(all_done)
                return ret

            except (future.IncompleteFuture, KeyError,
                    util.SocketError, util.Disconnected):
                pass

        return ret.set_result(pal)
コード例 #9
0
 def handle_exception(self, exc_type, exc_value, exc_trace):
     with QtCore.QMutexLocker(self._mutex):
         try:
             self.setTextColor(QtGui.QColor("#ff0000"))
             lines = exc_value.traceback_lines
             self.append("".join(lines).strip())
         except AttributeError:
             self.append("".join(traceback.format_exception(exc_type, exc_value, exc_trace)).strip())
         finally:
             self.setTextColor(self._original_text_color)
コード例 #10
0
 def handle_log_record(self, log_record):
     with QtCore.QMutexLocker(self._mutex):
         try:
             if log_record.levelno >= logging.ERROR:
                 self.setTextColor(QtGui.QColor("#ff0000"))
                 self.append(self.err_fmt.format(log_record), prepend_time=False)
             else:
                 self.append(self.fmt.format(log_record), prepend_time=False)
         finally:
             self.setTextColor(self._original_text_color)
コード例 #11
0
    def __init__(self, **kwargs):
        super(DefaultParameterBinding, self).__init__(**kwargs)

        log.info("DefaultParameterBinding: target=%s", self.target)

        if isinstance(self.target, QtWidgets.QWidget):
            self._original_palette = QtGui.QPalette(self.target.palette())
        else:
            self._original_palette = None
            log.info("DefaultParameterBinding: non QWidget target %s", self.target)
コード例 #12
0
    def data(self, column, role):
        if column == 0 and role == Qt.DisplayRole:
            return str(self.bus_number)

        if column == 0 and role in (Qt.ToolTipRole, Qt.StatusTipRole):
            return "Bus %d" % self.bus_number

        if column == 0 and role == Qt.DecorationRole:
            mrc = self.parent.ref.hw
            if mrc is not None and any(d.address_conflict for d in mrc.get_devices(self.bus_number)):
                return QtGui.QPixmap(":/warning.png")
コード例 #13
0
                def all_done(_):
                    has_param = any(pp.address in (self.write_address, self.read_address) for pp in f_params.result())
                    if has_param:
                        cfg_value = int(f_cfg)
                        hw_value  = int(f_hw)

                        if cfg_value != hw_value:
                            log.debug("_get_palette: ra=%d, wa=%d, cfg and hw differ; returning orange",
                                    self.read_address, self.write_address)
                            pal.setColor(QtGui.QPalette.Base, QtGui.QColor('orange'))

                    ret.set_result(pal)
コード例 #14
0
ファイル: util.py プロジェクト: flueke/mesycontrol
def make_apply_common_button_layout(input_spinbox, tooltip, on_clicked):

    # Wrapper to invoke the clicked handler without the boolean arg that's
    # passed from QPushButton.clicked().
    def _on_clicked():
        on_clicked()

    button = QtWidgets.QPushButton(clicked=_on_clicked)
    button.setIcon(QtGui.QIcon(":/arrow-bottom.png"))
    button.setMaximumHeight(input_spinbox.sizeHint().height())
    button.setMaximumWidth(16)
    button.setToolTip(tooltip)

    layout = QtWidgets.QHBoxLayout()
    layout.addWidget(input_spinbox)
    layout.addWidget(button)
    layout.setContentsMargins(0, 0, 0, 0)
    layout.setSpacing(1)

    return (layout, button)
コード例 #15
0
ファイル: dialogs.py プロジェクト: flueke/mesycontrol
    def __init__(self,
                 bus=None,
                 available_addresses=bm.ALL_DEVICE_ADDRESSES,
                 known_idcs=list(),
                 allow_custom_idcs=True,
                 title="Add Device",
                 selected_bus=None,
                 selected_address=None,
                 selected_idc=None,
                 assigned_name=None,
                 parent=None):
        """
        Dialog constructor.

        If `bus' is given the dialog will use it as the selected bus and won't
        allow the user to change the bus.

        `available_addresses` should be a list of (bus, address) pairs. These
        address pairs will be available for the user to choose from.

        `known_idcs` should be a list of (idc, name) pairs.

        If `allow_custom_idcs` is True the user may enter a custom IDC,
        otherwise only IDCs from `known_idcs` are selectable.

        If `known_idcs' is empty and `allow_custom_idcs' is False this method
        will raise an exception.

        If `selected_bus` and `selected_address` is not None the corresponding
        item will be preselected in the GUI.

        If `selected_idc` is not None the device type will be set using the given IDC
        and will not be modifyable.
        """

        if len(known_idcs) == 0 and not allow_custom_idcs:
            raise RuntimeError("No devices to choose from")

        if len(available_addresses) == 0 or (
                bus is not None and util.ilen_destructive(
                    filter(lambda x: x[0] == bus, available_addresses)) == 0):
            raise RuntimeError("No addresses available")

        super(AddDeviceDialog, self).__init__(parent)

        self.log = util.make_logging_source_adapter(__name__, self)

        self.setWindowTitle(title)
        self._result = None
        self.allow_custom_idcs = allow_custom_idcs

        self.bus_combo = QtWidgets.QComboBox()
        self.bus_combo.addItems([str(i) for i in bm.BUS_RANGE])

        self.address_combos = [QtWidgets.QComboBox() for i in bm.BUS_RANGE]

        for b, a in sorted(available_addresses):
            self.address_combos[b].addItem("%X" % a, a)

        self.address_combo_stack = QtWidgets.QStackedWidget()

        for combo in self.address_combos:
            self.address_combo_stack.addWidget(combo)

        self.bus_combo.activated.connect(
            self.address_combo_stack.setCurrentIndex)

        self.idc_combo = EatReturnCombo()
        for idc, name in sorted(known_idcs, key=lambda x: x[1]):
            self.idc_combo.addItem("%s (%d)" % (name, idc), idc)

        if self.idc_combo.findData(idc) < 0:
            self.idc_combo.addItem(str(idc), idc)

        if selected_idc is not None:
            self.log.debug("selected_idc=%d, idx=%d", selected_idc,
                           self.idc_combo.findData(selected_idc))

            self.idc_combo.setCurrentIndex(
                self.idc_combo.findData(selected_idc))
            self.idc_combo.setEnabled(False)

        if bus is not None:
            self.bus_combo.setCurrentIndex(bus)
            self.address_combo_stack.setCurrentIndex(bus)

        self.name_input = QtWidgets.QLineEdit()

        if assigned_name is not None:
            self.name_input.setText(assigned_name)

        self.button_box = QtWidgets.QDialogButtonBox(
            QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)

        if allow_custom_idcs:
            self.idc_combo.setEditable(True)
            self.idc_combo.setValidator(QtGui.QIntValidator(1, 99))

            ok_button = self.button_box.button(QtWidgets.QDialogButtonBox.Ok)
            ok_button.setEnabled(len(known_idcs))

            def combo_index_changed():
                ok_button.setEnabled(True)

            def combo_le_text_edited():
                ok_button.setEnabled(
                    self.idc_combo.lineEdit().hasAcceptableInput())

            self.idc_combo.currentIndexChanged.connect(combo_index_changed)
            self.idc_combo.lineEdit().textEdited.connect(combo_le_text_edited)

        if selected_bus is not None:
            assert selected_bus in bm.BUS_RANGE
            self.bus_combo.setCurrentIndex(selected_bus)
            self.address_combo_stack.setCurrentIndex(selected_bus)

            if selected_address is not None:
                assert selected_address in bm.DEV_RANGE
                combo = self.address_combo_stack.currentWidget()
                combo.setCurrentIndex(combo.findText("%X" % selected_address))

        def accept():
            bus = self.bus_combo.currentIndex()
            address = int(self.address_combos[bus].itemData(
                self.address_combos[bus].currentIndex()))

            if self.allow_custom_idcs and self.idc_combo.lineEdit(
            ).hasAcceptableInput():
                idc = int(self.idc_combo.lineEdit().text())
            else:
                idx = self.idc_combo.currentIndex()
                idc = int(self.idc_combo.itemData(idx))

            name = self.name_input.text()

            self._result = AddDeviceDialog.Result(bus, address, idc, name)

            super(AddDeviceDialog, self).accept()

        self.button_box.accepted.connect(accept)
        self.button_box.rejected.connect(self.reject)

        layout = QtWidgets.QFormLayout(self)
        layout.addRow("Bus", self.bus_combo)
        layout.addRow("Address", self.address_combo_stack)
        layout.addRow("IDC", self.idc_combo)
        layout.addRow("Name", self.name_input)
        layout.addRow(self.button_box)
コード例 #16
0
    def data(self, column, role):
        device = self.ref  # app_model.Device
        hw = device.hw  # hardware_model.Device
        cfg = device.cfg  # config_model.Device

        if column == 0 and role == Qt.DisplayRole:

            if cfg is None:
                return "%X <not present in setup>" % device.address

            try:
                type_name = self.model.device_registry.get_device_name(cfg.idc)
            except KeyError:
                type_name = "idc=%d" % cfg.idc

            if len(cfg.name):
                data = "%s (%s)" % (cfg.name, type_name)
            else:
                data = type_name

            if cfg.modified:
                data += "*"

            return "%X %s" % (device.address, data)

        if column == 0 and role == Qt.EditRole:
            return self.ref.cfg.name

        if column == 0:
            if hw is not None and cfg is not None and self.model.linked_mode and hw.address_conflict:
                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    return "Address conflict"

            if hw is not None and self.model.linked_mode and device.idc_conflict:
                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    return "IDC conflict"

            if self.model.linked_mode and device.has_hw and device.has_cfg and device.hw.is_connected(
            ):
                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    if device.config_applied is True:
                        return "Hardware matches config"
                    elif device.config_applied is False:
                        return "Hardware and config differ"

            if cfg is not None and role in (Qt.ToolTipRole, Qt.StatusTipRole):
                data = str()
                if len(cfg.name):
                    data += cfg.name + " "

                type_name = self.model.device_registry.get_device_name(cfg.idc)
                data += "%s (idc=%d)" % (type_name, cfg.idc)

                if cfg.modified:
                    data += " (modified)"

                return data

        if role == Qt.BackgroundRole and self.model.linked_mode:
            if device.idc_conflict or device.address_conflict:
                return QtGui.QColor('red')

            if device.has_hw and device.has_cfg:
                if device.hw.is_connected():
                    if device.config_applied is True:
                        return QtGui.QColor('green')
                    if device.config_applied is False:
                        return QtGui.QColor('orange')
コード例 #17
0
    def data(self, column, role):
        device  = self.ref   # app_model.Device
        hw      = device.hw  # hardware_model.Device
        mrc     = device.mrc # app_model.MRC

        if column == 0 and role == Qt.DisplayRole:
            if mrc.hw is None or not mrc.hw.is_connected():
                return "%X <no mrc connection>" % device.address
            elif hw is None:
                return "%X <device not connected>" % device.address

            try:
                name = self.model.device_registry.get_device_name(hw.idc)
                data = "%s" % name
            except KeyError:
                name = None
                data = "idc=%d" % hw.idc

            return "%X %s" % (device.address, data)

        if column == COL_RC and hw is not None and mrc.hw.is_connected():
            if role == Qt.DisplayRole:
                return "RC on" if hw.rc else "RC off"
            if role == Qt.EditRole:
                return hw.rc

        if column == 0:
            if hw is not None and hw.address_conflict:
                if role == Qt.DecorationRole:
                    return QtGui.QPixmap(":/warning.png")

                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    return "Address conflict"

            if hw is not None and self.model.linked_mode and  device.idc_conflict:
                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    return "IDC conflict"

            if self.model.linked_mode and device.has_hw and device.has_cfg and device.hw.is_connected():
                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    if device.config_applied is True:
                        return "Hardware matches config"
                    elif device.config_applied is False:
                        return "Hardware and config differ"

            if mrc.hw is None or mrc.hw.is_disconnected():
                if role == Qt.DecorationRole:
                    return QtGui.QPixmap(":/disconnected.png")

                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    return "Disconnected from %s" % (mrc.get_display_url(),)

            if mrc.hw is not None and mrc.hw.is_connecting():
                if role == Qt.DecorationRole:
                    return QtGui.QPixmap(":/connecting.png")

                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    return "Connecting to %s" % (mrc.get_display_url(),)

            if mrc.hw is not None and mrc.hw.is_connected() and not hw:
                if role == Qt.DecorationRole:
                    return QtGui.QPixmap(":/disconnected.png")

            if mrc.hw is not None and not mrc.hw.is_connected() and mrc.hw.last_connection_error is not None:
                if role == Qt.DecorationRole:
                    return QtGui.QPixmap(":/warning.png")

                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    return "%s: %s" % (mrc.get_display_url(), mrc.hw.last_connection_error)

            if mrc.hw is not None and mrc.hw.is_connected() and hw is not None:
                if role == Qt.DecorationRole:
                    return QtGui.QPixmap(":/connected.png")

                if role in (Qt.ToolTipRole, Qt.StatusTipRole):
                    return "%s (idc=%d)" % (device.hw_profile.name, hw.idc)

        if role == Qt.BackgroundRole and self.model.linked_mode:
            if hw is not None and hw.address_conflict:
                return QtGui.QColor('red')

            if device.idc_conflict and self.model.linked_mode:
                return QtGui.QColor('red')

            if device.has_hw and device.has_cfg:
                if device.hw.is_connected():
                    if device.config_applied is True:
                        return QtGui.QColor('green')
                    if device.config_applied is False:
                        return QtGui.QColor('orange')
コード例 #18
0
ファイル: gui_mainwindow.py プロジェクト: flueke/mesycontrol
    def on_actionAbout_triggered(self):
        try:
            from . import mc_version
            version = mc_version.version
        except ImportError:
            version = "devel version"

        d = QtWidgets.QDialog(self)
        d.setWindowTitle("About mesycontrol")

        license = QtWidgets.QTextBrowser(parent=d)
        license.setWindowFlags(Qt.Window)
        license.setWindowTitle("mesycontrol license")
        license.setText("")

        try:
            f = QtCore.QFile(":/gpl-notice.txt")
            if not f.open(QtCore.QIODevice.ReadOnly | QtCore.QIODevice.Text):
                return
            license.setPlainText(str(f.readAll(), 'utf-8'))
        finally:
            f.close()

        l = QtWidgets.QVBoxLayout(d)

        logo = QtWidgets.QLabel()
        logo.setPixmap(
            QtGui.QPixmap(":/mesytec-logo.png").scaledToWidth(
                300, Qt.SmoothTransformation))
        l.addWidget(logo)

        t = "mesycontrol - %s" % version
        label = QtWidgets.QLabel(t)
        font = label.font()
        font.setPointSize(15)
        font.setBold(True)
        label.setFont(font)
        l.addWidget(label)

        l.addWidget(QtWidgets.QLabel("Remote control for mesytec devices."))
        l.addWidget(QtWidgets.QLabel("© 2014-2022 mesytec GmbH & Co. KG"))

        t = '<a href="mailto:[email protected]">[email protected]</a> - <a href="http://www.mesytec.com">www.mesytec.com</a>'
        label = QtWidgets.QLabel(t)
        label.setOpenExternalLinks(True)
        l.addWidget(label)

        t = 'Running on Python %s using PySide2 %s with Qt %s.' % (
            platform.python_version(), PySide2.__version__,
            PySide2.QtCore.__version__)
        l.addWidget(QtWidgets.QLabel(t))

        l.addSpacing(20)

        bl = QtWidgets.QHBoxLayout()

        def license_button_clicked():
            sz = license.size()
            sz = sz.expandedTo(QtCore.QSize(500, 300))
            license.resize(sz)
            license.show()
            license.raise_()

        b = QtWidgets.QPushButton("&License", clicked=license_button_clicked)
        bl.addWidget(b)

        b = QtWidgets.QPushButton("&Close", clicked=d.close)
        b.setAutoDefault(True)
        b.setDefault(True)
        bl.addWidget(b)

        l.addLayout(bl)

        for item in (l.itemAt(i) for i in range(l.count())):
            item.setAlignment(Qt.AlignHCenter)

            w = item.widget()

            if isinstance(w, QtWidgets.QLabel):
                w.setTextInteractionFlags(Qt.TextBrowserInteraction)

        d.exec_()
コード例 #19
0
def test_app_model_using_local_setup():
    from mesycontrol import application_registry
    from mesycontrol import app_model
    from mesycontrol import config
    from mesycontrol import hw_model
    from mesycontrol import mrc_connection
    from mesycontrol import mrc_controller

    logging.basicConfig(level=logging.INFO,
            format='[%(asctime)-15s] [%(name)s.%(levelname)s] %(message)s')

    signal.signum_to_name = dict((getattr(signal, n), n)
            for n in dir(signal) if n.startswith('SIG') and '_' not in n)
    signal.signal(signal.SIGINT, signal_handler)

    application_registry.instance = application_registry.ApplicationRegistry(
            sys.executable if getattr(sys, 'frozen', False) else __file__)

    app = QtGui.QApplication(sys.argv)

    timer = QtCore.QTimer()
    timer.timeout.connect(lambda: None)
    timer.start(500)

    con                             = mrc_connection.factory(serial_port='/dev/ttyUSB0', baud_rate=0)
    mrc_model                       = hw_model.MRCModel()
    mrc_model.controller            = mrc_controller.MRCController(con, mrc_model)
    mrc_config                      = config.MRCConfig()
    mrc_config.connection_config    = config.make_connection_config(con)
    mrc                             = app_model.AppMrc(mrc_model=mrc_model, mrc_config=mrc_config)
    setup                           = config.Setup()
    setup.add_mrc_config(mrc_config)

    def on_mrc_connecting():
        print("connecting...")

    def on_mrc_connected():
        print("connected!")

    def on_mrc_disconnected(info=None):
        print("disconnected!", info)

    def on_mrc_ready():
        print("MRC is ready!")
        for device in mrc.get_devices():
            print(device, device.model, device.config)

        print("Saving setup...")

    def on_device_added(device):
        print("Device added: %s" % device)

    mrc.connecting.connect(on_mrc_connecting)
    mrc.connected.connect(on_mrc_connected)
    mrc.disconnected.connect(on_mrc_disconnected)
    mrc.ready.connect(on_mrc_ready)
    mrc.device_added.connect(on_device_added)

    mrc.connect()

    return app.exec_()
コード例 #20
0
    def data(self, idx, role=Qt.DisplayRole):
        if not idx.isValid() or self.device is None:
            return None

        row = idx.row()
        col = idx.column()
        hw = self.device.hw
        cfg = self.device.cfg
        profile = self.profile

        try:
            pp = profile[row]  # parameter profile
        except (IndexError, AttributeError):
            pp = None

        if role == Qt.DisplayRole:
            if col == COL_ADDRESS:
                return row

            elif col == COL_NAME and pp is not None and pp.is_named():
                return pp.name

            elif col == COL_HW_VALUE:
                if hw is None:
                    return "<device not present>"

                if hw.is_disconnected():
                    return "<not connected>"

                if hw.is_connecting():
                    return "<connecting>"

                if hw.address_conflict:
                    return "<address conflict>"

                try:
                    value = int(hw.get_parameter(row))
                    if self.display_hex_values:
                        return "0x{:04x}".format(value)
                    return value
                except future.IncompleteFuture:
                    return "<reading>"

            elif col == COL_CFG_VALUE:
                if pp is None or not pp.should_be_stored():
                    return None

                if cfg is None:
                    return "<config not present>"

                try:
                    value = int(cfg.get_parameter(row))
                    if self.display_hex_values:
                        return "0x{:04x}".format(value)
                    return value
                except future.IncompleteFuture:
                    return "<reading>"
                except KeyError:
                    return "<not set>"

            elif col in (COL_HW_UNIT_VALUE, COL_CFG_UNIT_VALUE):
                try:
                    unit = pp.units[1]  # skip the 'raw' unit at index 0
                except (IndexError, AttributeError):
                    return None

                if (col == COL_HW_UNIT_VALUE and hw is not None
                        and hw.is_connected() and not hw.address_conflict):
                    try:
                        raw = int(hw.get_parameter(row))
                    except future.IncompleteFuture:
                        return "<reading>"

                elif col == COL_CFG_UNIT_VALUE and cfg is not None:
                    if pp is None or not pp.should_be_stored() or cfg is None:
                        return None
                    try:
                        raw = int(cfg.get_parameter(row))
                    except future.IncompleteFuture:
                        return "<reading>"
                    except KeyError:
                        return None
                else:
                    return None

                value = unit.unit_value(raw)

                return "%f %s" % (value, unit.label)

        if role == Qt.EditRole:
            if col == COL_HW_VALUE:
                # should succeed as otherwise the editable flag would not be set
                return int(hw.get_parameter(row))

            if col == COL_CFG_VALUE:
                try:
                    # fails if no config exists or the parameter is not set
                    return int(cfg.get_parameter(row))
                except (IndexError, AttributeError, KeyError):
                    if pp is not None:
                        return pp.default
                    return 0

        if role == Qt.BackgroundRole:
            if (self.display_mode == util.COMBINED and hw is not None
                    and cfg is not None and pp is not None
                    and pp.should_be_stored()):
                try:
                    cfg_raw = int(cfg.get_parameter(row))
                    hw_raw = int(hw.get_parameter(row))
                    if cfg_raw != hw_raw:
                        return QtGui.QColor('orange')
                except (future.IncompleteFuture, KeyError, util.SocketError,
                        util.Disconnected):
                    pass

            if col == COL_HW_VALUE and pp is not None and pp.read_only:
                return QtGui.QColor("lightgray")

            if col == COL_CFG_VALUE and pp is not None and not pp.should_be_stored(
            ):
                return QtGui.QColor("lightgray")

        if role in (Qt.ToolTipRole, Qt.StatusTipRole):
            if pp is not None and pp.read_only:
                if col == COL_HW_VALUE:
                    return "%s=%s (read_only)" % (
                        pp.name if pp.is_named() else str(row),
                        self.data(idx, Qt.DisplayRole))

                if col == COL_CFG_VALUE:
                    return "%s (read_only)" % (pp.name
                                               if pp.is_named() else str(row))

            if col == COL_CFG_VALUE and pp is not None and not pp.should_be_stored(
            ):
                return "%s (not stored in config)" % (pp.name if pp.is_named()
                                                      else str(row))

        return None
コード例 #21
0
ファイル: util.py プロジェクト: flueke/mesycontrol
def make_icon(source):
    return QtGui.QIcon(QtGui.QPixmap(source))
コード例 #22
0
                self.append("".join(lines).strip())
            except AttributeError:
                self.append("".join(traceback.format_exception(exc_type, exc_value, exc_trace)).strip())
            finally:
                self.setTextColor(self._original_text_color)

    def contextMenuEvent(self, event):
        pos  = event.globalPos()
        menu = self.createStandardContextMenu(pos)
        menu.addAction("Clear").triggered.connect(self.clear)
        menu.exec_(pos)

if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG,
            format='[%(asctime)-15s] [%(name)s.%(levelname)s] %(message)s')
    qapp = QtGui.QApplication(sys.argv)

    log_view = LogView()
    log_view.resize(400, 400)
    log_view.show()

    qt_logger = util.QtLogEmitter()
    qt_logger.log_record.connect(log_view.handle_log_record)
    logging.getLogger().addHandler(qt_logger.get_handler())

    logger = logging.getLogger(__name__)
    def on_button_clicked():
        logging.getLogger("testlogger").debug("Hello World!")

    button = QtWidgets.QPushButton("Log!", clicked=on_button_clicked)
    button.show()