예제 #1
0
파일: logdisplay.py 프로젝트: klauer/pydm
 def __init__(self, parent=None, logname=None, level=logging.NOTSET):
     QWidget.__init__(self, parent=parent)
     # Create Widgets
     self.label = QLabel('Minimum displayed log level: ', parent=self)
     self.combo = QComboBox(parent=self)
     self.text = QPlainTextEdit(parent=self)
     self.text.setReadOnly(True)
     self.clear_btn = QPushButton("Clear", parent=self)
     # Create layout
     layout = QVBoxLayout()
     level_control = QHBoxLayout()
     level_control.addWidget(self.label)
     level_control.addWidget(self.combo)
     layout.addLayout(level_control)
     layout.addWidget(self.text)
     layout.addWidget(self.clear_btn)
     self.setLayout(layout)
     # Allow QCombobox to control log level
     for log_level, value in LogLevels.as_dict().items():
         self.combo.addItem(log_level, value)
     self.combo.currentIndexChanged[str].connect(self.setLevel)
     # Allow QPushButton to clear log text
     self.clear_btn.clicked.connect(self.clear)
     # Create a handler with the default format
     self.handler = GuiHandler(level=level, parent=self)
     self.logFormat = self.default_format
     self.handler.message.connect(self.write)
     # Create logger. Either as a root or given logname
     self.log = None
     self.level = None
     self.logName = logname or ''
     self.logLevel = level
예제 #2
0
파일: code_only.py 프로젝트: tacaswell/pydm
 def setup_ui(self):
     main = QHBoxLayout()
     sub = QVBoxLayout()
     for i in range(10):
         sub.addWidget(QLabel(str(i)))
     main.addLayout(sub)
     self.setLayout(main)
예제 #3
0
 def __init__(self, device, parent=None):
     super().__init__(device, parent=parent)
     # Create button widget
     self.buttons = QWidget(parent=parent)
     self.button_layout = QHBoxLayout()
     self.buttons.setLayout(self.button_layout)
     # Create Insert PushButton
     if hasattr(device, 'insert'):
         self.insert_button = QPushButton('Insert', parent=parent)
         self.insert_button.setFont(self.font)
         self.button_layout.addWidget(self.insert_button)
         self.button_layout.addItem(QSpacerItem(10, 20))
     # Create Remove PushButton
     if hasattr(device, 'remove'):
         self.remove_button = QPushButton('Remove', parent=parent)
         self.remove_button.setFont(self.font)
         self.button_layout.addWidget(self.remove_button)
     # Subscribe device to state changes
     try:
         # Wait for later to update widget
         self.device.subscribe(self.update_state,
                               event_type=self.device.SUB_STATE,
                               run=False)
     except Exception:
         logger.error("Widget is unable to subscribe to device %s",
                      device.name)
예제 #4
0
 def _add_row(self, read, name, write=None, is_enum=False):
     # Create label
     label = QLabel(self)
     label.setText(name)
     # Create signal display
     val_display = QHBoxLayout()
     # Add readback
     ro = TyphonLabel(init_channel=read, parent=self)
     val_display.addWidget(ro)
     # Add our write_pv if available
     if write:
         # Check whether our device is an enum or not
         if is_enum:
             edit = TyphonComboBox(init_channel=write, parent=self)
         else:
             logger.debug("Adding LineEdit for %s", name)
             edit = TyphonLineEdit(init_channel=write, parent=self)
         # Add our control widget to layout
         val_display.addWidget(edit)
         # Make sure they share space evenly
         val_display.setStretch(0, 1)
         val_display.setStretch(1, 1)
     # Add displays to panel
     loc = len(self.signals)
     self.layout().addWidget(label, loc, 0)
     self.layout().addLayout(val_display, loc, 1)
     # Store signal
     self.signals[name] = (read, write)
     return loc
예제 #5
0
    def __init__(self, name, default, required=True, enum=None):
        self.name = name
        self.data_type = type(default)
        self.config = self.NO_CONFIG

        if not required or isinstance(default, bool):
            self.config += self.CHECK
        if not isinstance(default, bool):
            if enum is None:
                self.config += self.LINE
            else:
                self.config += self.COMBO

        self.layout = QHBoxLayout()
        if self.config & self.CHECK:
            self.check = QCheckBox()
            self.layout.addWidget(self.check)
        else:
            self.check = None
        if self.config == self.CHECK:
            self.check.setText('Enabled')
        if self.config & self.LINE:
            self.data = QLineEdit()
            self.data.setText(str(default))
            if self.data_type == int:
                self.data.setValidator(QIntValidator())
            elif self.data_type == float:
                self.data.setValidator(QDoubleValidator())
            self.layout.addWidget(self.data)
        elif self.config & self.COMBO:
            self.data = QComboBox()
            for value in enum:
                self.data.addItem(str(value))
            if default is not None:
                pass  # TODO: pick correct default combo box item
            self.layout.addWidget(self.data)
        else:
            self.data = None

        if self.check is not None and self.data is not None:
            self.check.toggled.connect(self.data.setEnabled)
        if self.check is not None:
            if default in (None, False):
                self.check.setChecked(False)
            else:
                self.check.setChecked(True)
예제 #6
0
 def __init__(self, parameter, default=inspect._empty, parent=None):
     super().__init__(parent=parent)
     # Store parameter information
     self.parameter = parameter
     self.default = default
     self.setLayout(QHBoxLayout())
     # Create our label
     self.param_label = QLabel(parent=self)
     self.param_label.setText(clean_attr(parameter))
     self.layout().addWidget(self.param_label)
     # Indicate required parameters in bold font
     if default == inspect._empty:
         logger.debug("Inferring that %s has no default", parameter)
         bold = QFont()
         bold.setBold(True)
         self.param_label.setFont(bold)
예제 #7
0
 def __init__(self, methods=None, parent=None):
     # Initialize parent
     super().__init__("Functions", parent=parent)
     self.contents = QWidget()
     self.layout().addWidget(self.contents)
     # Create Layout
     self.contents.setLayout(QHBoxLayout())
     # Add two spacers to center our functions without
     # expanding them
     self.contents.layout().addItem(QSpacerItem(10, 20))
     self.contents.layout().addItem(QSpacerItem(10, 20))
     # Add methods
     methods = methods or list()
     self.methods = dict()
     for method in methods:
         self.add_method(method)
예제 #8
0
    def add_pv(self, read_pv, name, write_pv=None):
        """
        Add PVs to the SignalPanel

        Parameters
        ---------
        read_pv : pyepics.PV

        name : str
            Name of signal to display

        write_pv : pyepics.PV, optional

        Returns
        -------
        loc : int
            Row number that the signal information was added to in the
            `SignalPanel.layout()``
        """
        logger.debug("Adding PV %s", name)
        # Create label
        label = QLabel(self)
        label.setText(name)
        label_font = QFont()
        label.setFont(label_font)
        # Create signal display
        val_display = QHBoxLayout()
        # Add readback
        ro = TyphonLabel(init_channel=channel_name(read_pv.pvname),
                         parent=self)
        val_display.addWidget(ro)
        # Add our write_pv if available
        if write_pv:
            ch = channel_name(write_pv.pvname)
            # Check whether our device is an enum or not
            if write_pv.enum_strs:
                edit = TyphonComboBox(init_channel=ch, parent=self)
            else:
                logger.debug("Adding LineEdit for %s", name)
                edit = PyDMLineEdit(init_channel=ch, parent=self)
            # Add our control widget to layout
            val_display.addWidget(edit)
        # Add displays to panel
        loc = len(self.pvs)
        self.layout().addWidget(label, loc, 0)
        self.layout().addLayout(val_display, loc, 1)
        # Store signal
        self.pvs[name] = (read_pv, write_pv)
        return loc
예제 #9
0
 def _add_row(self, read, name, write=None):
     # Create label
     label = QLabel(self)
     label.setText(name)
     # Create signal display
     val_display = QHBoxLayout()
     # Add readback
     val_display.addWidget(read)
     # Add our write_pv if available
     if write is not None:
         # Add our control widget to layout
         val_display.addWidget(write)
         # Make sure they share space evenly
         val_display.setStretch(0, 1)
         val_display.setStretch(1, 1)
     # Add displays to panel
     loc = len(self.signals)
     self.layout().addWidget(label, loc, 0)
     self.layout().addLayout(val_display, loc, 1)
     # Store signal
     self.signals[name] = (read, write)
     return loc
예제 #10
0
class Setting:
    """
    Abstraction of a Single user input setting. Handles what the ui should look
    like for just this setting and keeps the input value and display values in
    sync.

    Widgets are held in the "layout" attribute.

    Supports several different kinds of configurations and associated values:
        -Just a checkbox:
            Can be True (checked) or False (unchecked)
            Chosen if default is a boolean
        -Just a line edit:
            Can be any value the same type as default
            Chosen if required=True and no enum provided
        -Just a combo box
            Can be any value in the enum argument
            Chosen if required=True and enum list provided
        -A checkbox and a line edit or combo box
            Chosen if required=False and default is non-boolean
            If the checkbox is unchecked, the value is None
    """
    NO_CONFIG = 0
    CHECK = 1
    LINE = 2
    COMBO = 4

    def __init__(self, name, default, required=True, enum=None):
        self.name = name
        self.data_type = type(default)
        self.config = self.NO_CONFIG

        if not required or isinstance(default, bool):
            self.config += self.CHECK
        if not isinstance(default, bool):
            if enum is None:
                self.config += self.LINE
            else:
                self.config += self.COMBO

        self.layout = QHBoxLayout()
        if self.config & self.CHECK:
            self.check = QCheckBox()
            self.layout.addWidget(self.check)
        else:
            self.check = None
        if self.config == self.CHECK:
            self.check.setText('Enabled')
        if self.config & self.LINE:
            self.data = QLineEdit()
            self.data.setText(str(default))
            if self.data_type == int:
                self.data.setValidator(QIntValidator())
            elif self.data_type == float:
                self.data.setValidator(QDoubleValidator())
            self.layout.addWidget(self.data)
        elif self.config & self.COMBO:
            self.data = QComboBox()
            for value in enum:
                self.data.addItem(str(value))
            if default is not None:
                pass  # TODO: pick correct default combo box item
            self.layout.addWidget(self.data)
        else:
            self.data = None

        if self.check is not None and self.data is not None:
            self.check.toggled.connect(self.data.setEnabled)
        if self.check is not None:
            if default in (None, False):
                self.check.setChecked(False)
            else:
                self.check.setChecked(True)

    @property
    def value(self):
        if self.config == self.CHECK:
            return self.check.isChecked()
        elif self.config & self.CHECK:
            if not self.check.isChecked():
                return None
        if self.config & self.LINE:
            raw = self.data.text()
        elif self.config & self.COMBO:
            raw = self.data.currentText()
        else:
            raw = None
        try:
            return self.data_type(raw)
        except Exception:
            return raw

    @value.setter
    def value(self, val):
        if self.config == self.CHECK:
            self.check.setChecked(bool(val))
            return
        elif self.config & self.CHECK and val is None:
            self.check.setChecked(False)
            return
        else:
            try:
                val = self.data_type(val)
            except Exception:
                logger.exception('Invalid data type')
                return
            finally:
                txt = str(val)
            if self.config & self.LINE:
                self.data.setText(txt)
            elif self.config & self.COMBO:
                index = self.enum.index(txt)
                self.data.setCurrentIndex(index)
예제 #11
0
    def __init__(self, parent=None, collumns=None, **settings):
        """
        Parameters
        ----------
        collumns: list, optional
            List of lists of headers included in each collumn
            The list at index 0 will be the first collumn, etc.

        settings: kwargs
            Mapping of header to list of Setting objects
        """
        self.settings = {}
        self.window = QDialog(parent=parent)
        self.window.setWindowTitle('Skywalker Settings')
        main_layout = QVBoxLayout()
        self.window.setLayout(main_layout)
        self.window.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        all_cols_layout = QHBoxLayout()
        main_layout.addLayout(all_cols_layout)
        if collumns is None:
            collumns = [list(settings.keys())]
        for col in collumns:
            col_layout = QVBoxLayout()
            all_cols_layout.addLayout(col_layout)
            for header in col:
                title = QLabel()
                title.setText(header.capitalize())
                title.setAlignment(Qt.AlignCenter)
                col_layout.addWidget(title)
                form = QFormLayout()
                col_layout.addLayout(form)
                for setting in settings[header]:
                    self.settings[setting.name] = setting
                    label = QLabel()
                    label.setText(setting.name.capitalize())
                    label.setSizePolicy(QSizePolicy.Minimum,
                                        QSizePolicy.Minimum)
                    form.addRow(label, setting.layout)
            vertical_spacer = QSpacerItem(20, 10, QSizePolicy.Minimum,
                                          QSizePolicy.Expanding)
            col_layout.addItem(vertical_spacer)
        confirm_layout = QHBoxLayout()
        main_layout.addLayout(confirm_layout)
        horizontal_spacer = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                        QSizePolicy.Minimum)
        cancel_button = QPushButton('Cancel')
        cancel_button.pressed.connect(self.window.reject)
        apply_button = QPushButton('Apply')
        apply_button.pressed.connect(self.window.accept)
        confirm_layout.addItem(horizontal_spacer)
        confirm_layout.addWidget(cancel_button)
        confirm_layout.addWidget(apply_button)
예제 #12
0
class LightRow(InactiveRow):
    """
    Basic Widget to display LightDevice information

    The widget shows the device information and state, updating looking at the
    devices :attr:`.inserted` and :attr:`.removed` attributes. The
    :attr:`.remove_button` also allows the user to remove devices by calling
    the :meth:`.remove` method of the given device. The identical button is
    setup if the device is determined to have an `insert` method. Finally,
    PyDMRectangle is used to show the current path of the beam through the
    table

    Parameters
    ----------
    device : obj

    path : BeamPath

    parent : QObject, optional
    """
    def __init__(self, device, parent=None):
        super().__init__(device, parent=parent)
        # Create button widget
        self.buttons = QWidget(parent=parent)
        self.button_layout = QHBoxLayout()
        self.buttons.setLayout(self.button_layout)
        # Create Insert PushButton
        if hasattr(device, 'insert'):
            self.insert_button = QPushButton('Insert', parent=parent)
            self.insert_button.setFont(self.font)
            self.button_layout.addWidget(self.insert_button)
            self.button_layout.addItem(QSpacerItem(10, 20))
        # Create Remove PushButton
        if hasattr(device, 'remove'):
            self.remove_button = QPushButton('Remove', parent=parent)
            self.remove_button.setFont(self.font)
            self.button_layout.addWidget(self.remove_button)
        # Subscribe device to state changes
        try:
            # Wait for later to update widget
            self.device.subscribe(self.update_state,
                                  event_type=self.device.SUB_STATE,
                                  run=False)
        except Exception:
            logger.error("Widget is unable to subscribe to device %s",
                         device.name)

    def update_state(self, *args, **kwargs):
        """
        Update the state label

        The displayed state can be one of ``Unknown`` , ``Inserted``,
        ``Removed`` or ``Error``, with ``Unknown`` being if the device is not
        inserted or removed, and error being if the device is reporting as both
        inserted and removed. The color of the label is also adjusted to either
        green or red to quickly
        """
        states = Enum('states', ('Unknown', 'Inserted', 'Removed', 'Error'))
        # Interpret state
        try:
            state = 1 + int(
                self.device.inserted) + 2 * int(self.device.removed)
        except Exception as exc:
            logger.error(exc)
            state = states.Error.value
        # Set label to state description
        self.state_label.setText(states(state).name)
        # Set the color of the label
        if state == states.Removed.value:
            self.state_label.setStyleSheet("QLabel {color : rgb(124,252,0)}")
        elif state == states.Unknown.value:
            self.state_label.setStyleSheet("QLabel {color : rgb(255, 215, 0)}")
        else:
            self.state_label.setStyleSheet("QLabel {color : red}")
        # Disable buttons if necessary
        if hasattr(self, 'insert_button'):
            self.insert_button.setEnabled(state != states.Inserted.value)
        if hasattr(self, 'remove_button'):
            self.remove_button.setEnabled(state != states.Removed.value)

    @property
    def widgets(self):
        """
        Ordered list of widgets to add to designer
        """
        return [
            self.indicator, self.name_label, self.prefix_label, self.spacer,
            self.state_label, self.buttons
        ]

    def clear_sub(self):
        """
        Clear the subscription event
        """
        self.device.clear_sub(self.update_state)
예제 #13
0
    def setup_ui(self):
        # Create the main layout
        main_layout = QVBoxLayout()
        self.setLayout(main_layout)

        # Create a Label to be the title
        lbl_title = QLabel("Motors Diagnostic")
        # Add some StyleSheet to it
        lbl_title.setStyleSheet("\
            QLabel {\
                qproperty-alignment: AlignCenter;\
                border: 1px solid #FF17365D;\
                border-top-left-radius: 15px;\
                border-top-right-radius: 15px;\
                background-color: #FF17365D;\
                padding: 5px 0px;\
                color: rgb(255, 255, 255);\
                max-height: 25px;\
                font-size: 14px;\
            }")

        # Add the title label to the main layout
        main_layout.addWidget(lbl_title)
        
        # Create the Search Panel layout
        search_layout = QHBoxLayout()
        
        # Create a GroupBox with "Filtering" as Title
        gb_search = QGroupBox(parent=self)
        gb_search.setTitle("Filtering")        
        gb_search.setLayout(search_layout)
        
        # Create a label, line edit and button for filtering
        lbl_search = QLabel(text="Filter: ")
        self.txt_filter = QLineEdit()
        self.txt_filter.returnPressed.connect(self.do_search)
        btn_search = QPushButton()
        btn_search.setText("Search")
        btn_search.clicked.connect(self.do_search)
        
        # Add the created widgets to the layout
        search_layout.addWidget(lbl_search)
        search_layout.addWidget(self.txt_filter)
        search_layout.addWidget(btn_search)

        # Add the Groupbox to the main layout
        main_layout.addWidget(gb_search)

        # Create the Results Layout
        self.results_layout = QVBoxLayout()
        self.results_layout.setContentsMargins(0, 0, 0, 0)

        # Create a Frame to host the results of search
        self.frm_result = QFrame(parent=self)       
        self.frm_result.setLayout(self.results_layout)

        # Create a ScrollArea so we can properly handle
        # many entries
        scroll_area = QScrollArea(parent=self)
        scroll_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        scroll_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        scroll_area.setWidgetResizable(True)

        # Add the Frame to the scroll area
        scroll_area.setWidget(self.frm_result)

        # Add the scroll area to the main layout
        main_layout.addWidget(scroll_area)