예제 #1
0
class MultiWidget(QWidget):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    def __init__(self,
                 parent,
                 types,
                 curvalue,
                 client,
                 allow_enter=False,
                 valinfo=None):
        QWidget.__init__(self, parent)
        layout = self._layout = QGridLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self._widgets = []
        if valinfo is not None:
            for i, info in enumerate(valinfo):
                layout.addWidget(QLabel(info.name), 0, i)
        for i, (typ, val) in enumerate(zip(types, curvalue)):
            widget = create(self,
                            typ,
                            val,
                            client=client,
                            allow_enter=allow_enter)
            self._widgets.append(widget)
            widget.valueModified.connect(self.valueModified)
            if allow_enter:
                widget.valueChosen.connect(
                    lambda val: self.valueChosen.emit(self.getValue()))
            layout.addWidget(widget, 1, i)
        self.setLayout(layout)

    def getValue(self):
        return tuple(w.getValue() for w in self._widgets)
예제 #2
0
class SetOfWidget(QWidget):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    def __init__(self, parent, values, curvalue, client):
        QWidget.__init__(self, parent)
        layout = self._layout = QVBoxLayout()
        self.checkboxes = []
        self.values = []
        curvalue = curvalue or set()
        for value in values:
            checkbox = QCheckBox(str(value), self)
            if value in curvalue:
                checkbox.setCheckState(Qt.Checked)
            checkbox.stateChanged.connect(self.on_checkbox_stateChanged)
            layout.addWidget(checkbox)
            self.checkboxes.append(checkbox)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

    def on_checkbox_stateChanged(self, state):
        self.valueModified.emit()

    def getValue(self):
        result = set()
        for value, checkbox in zip(self.values, self.checkboxes):
            if checkbox.isChecked():
                result.add(value)
        return result
예제 #3
0
class DictWithWidget(QWidget):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    def __init__(self,
                 parent,
                 keys,
                 types,
                 curvalue,
                 client,
                 allow_enter=False):
        QWidget.__init__(self, parent)
        layout = self._layout = QFormLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.keys = keys
        self._widgets = []
        for (key, typ, val) in zip(keys, types, curvalue.values()):
            widget = create(self,
                            typ,
                            val,
                            client=client,
                            allow_enter=allow_enter)
            self._widgets.append(widget)
            widget.valueModified.connect(self.valueModified)
            if allow_enter:
                widget.valueChosen.connect(
                    lambda val: self.valueChosen.emit(self.getValue()))
            layout.addRow(key, widget)
        self.setLayout(layout)

    def getValue(self):
        return {k: w.getValue() for k, w in zip(self.keys, self._widgets)}
예제 #4
0
class PositionTable(QTableWidget):
    """Display all selected measurement positions.

    Each value is modifiable and removable.
    """

    pointRemove = pyqtSignal(int)
    valueChanged = pyqtSignal(int, int, float)

    def __init__(self, parent=None):
        QTableWidget.__init__(self, parent)

    def mousePressEvent(self, event):
        if event.button() == Qt.RightButton:
            item = self.itemAt(event.pos())
            if item:
                if QMessageBox.question(self, 'Remove data point', 'Do you '
                                        'really want to remove this data '
                                        'point?') == QMessageBox.Yes:
                    event.accept()
                    r = item.row()
                    self.removeRow(r)
                    self.pointRemove.emit(r)
        QTableWidget.mousePressEvent(self, event)

    def clearTable(self):
        while self.rowCount():
            self.removeRow(0)
            self.pointRemove.emit(0)

    def getValues(self, row):
        return [float(self.item(row, i).text()) for i in range(3)]
예제 #5
0
class CheckWidget(QWidget):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    def __init__(self, parent, inner, curvalue, client):
        QWidget.__init__(self, parent)
        layout = self._layout = QHBoxLayout()
        self.checkbox = QCheckBox(self)
        if curvalue is not None:
            self.checkbox.setCheckState(Qt.Checked)
        if curvalue is None:
            curvalue = inner()  # generate a dummy value
        self.inner_widget = create(self, inner, curvalue, client=client)
        self.inner_widget.setEnabled(self.checkbox.isChecked())
        self.inner_widget.valueModified.connect(self.valueModified)
        layout.addWidget(self.checkbox)
        layout.addWidget(self.inner_widget)
        layout.setContentsMargins(0, 0, 0, 0)
        self.checkbox.stateChanged.connect(self.on_checkbox_stateChanged)
        self.setLayout(layout)

    def on_checkbox_stateChanged(self, state):
        self.inner_widget.setEnabled(state == Qt.Checked)
        self.valueModified.emit()

    def getValue(self):
        if self.checkbox.isChecked():
            return self.inner_widget.getValue()
        return None
예제 #6
0
class DeviceComboWidget(QComboBox):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    def __init__(self,
                 parent,
                 curvalue,
                 client,
                 needs_class='nicos.core.device.Device',
                 allow_enter=False):
        QComboBox.__init__(self, parent, editable=True)
        self.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        if client:
            devs = client.getDeviceList(needs_class)
            self.addItems(devs)
            try:
                index = devs.index(curvalue)
                self.setCurrentIndex(index)
            except ValueError:
                self.setEditText(curvalue)
        else:
            self.setEditText(curvalue)
        self.editTextChanged.connect(lambda _: self.valueModified.emit())
        if allow_enter:
            self.lineEdit().returnPressed.connect(
                lambda: self.valueChosen.emit(self.currentText()))

    def getValue(self):
        return self.currentText()
예제 #7
0
class OneofdictOrWidget(QWidget):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    def __init__(self, parent, inner, selector, buttons):
        QWidget.__init__(self, parent)
        self._inner = inner
        self._selector = selector

        layout = self._layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        inner.valueModified.connect(self.valueModified)
        inner.valueChosen.connect(self.valueChosen)
        if not buttons:
            selector.valueModified.connect(self.on_selector_valueModified)
            inner.setVisible(selector.getValue() is Ellipsis)
        else:
            selector.valueChosen.connect(self.valueChosen)
        layout.addWidget(selector)
        layout.addWidget(inner)
        self.setLayout(layout)

    def on_selector_valueModified(self):
        val = self._selector.getValue()
        self._inner.setVisible(val is Ellipsis)
        self.valueModified.emit()

    def getValue(self):
        val = self._selector.getValue()
        if val is Ellipsis:
            return self._inner.getValue()
        return val
예제 #8
0
class TableWidget(QTableWidget):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    def __init__(self,
                 parent,
                 validator,
                 curvalue,
                 fmtstr,
                 client,
                 allow_enter=False):
        self._rows, self._cols = curvalue.shape
        self.validator = validator
        QTableWidget.__init__(self, self._rows, self._cols, parent)
        for i in range(self._rows):
            for j in range(self._cols):
                self.setItem(i, j, QTableWidgetItem(fmtstr % curvalue[i, j]))
        self.cellChanged.connect(lambda i, j: self.valueModified.emit())

    def getValue(self):
        value = np.zeros((self._rows, self._cols))
        for i in range(self._rows):
            for j in range(self._cols):
                value[i, j] = self.validator(self.item(i, j).text())
        return value
예제 #9
0
class CacheSignals(QObject):
    """This must be a separate object since the metaclasses of BaseCacheClient
    and CacheSignals are not compatible.
    """

    connected = pyqtSignal()
    disconnected = pyqtSignal()
    keyUpdated = pyqtSignal(str, object)
예제 #10
0
class MissingWidget(QLabel):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    def __init__(self, parent, curvalue, text='editing impossible'):
        QLabel.__init__(self, parent)
        self.setText('(%s)' % text)
        self._value = curvalue

    def getValue(self):
        return self._value
예제 #11
0
class ExprWidget(QLineEdit):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    def __init__(self, parent, curvalue, allow_enter=False):
        QLineEdit.__init__(self, parent)
        self.setText(cache_dump(curvalue))
        self.textChanged.connect(lambda txt: self.valueModified.emit())
        if allow_enter:
            self.returnPressed.connect(
                lambda: self.valueChosen.emit(cache_load(self.text())))

    def getValue(self):
        return cache_load(self.text())
예제 #12
0
class PnPSetupQuestion(QMessageBox):
    """Special QMessageBox for asking what to do a new setup was detected."""

    closed = pyqtSignal('QMessageBox')

    def __init__(self, parent, client, data):
        self.client = client
        client.setup.connect(self.on_client_setup)
        self.data = data
        add_mode = data[0] == 'added'
        if add_mode:
            message = (
                '<b>New sample environment detected</b><br/>'
                'A new sample environment <b>%s</b> has been detected:<br/>%s'
                % (data[1], data[2] or ''))
        else:
            message = (
                '<b>Sample environment removed</b><br/>'
                'The sample environment <b>%s</b> has been removed:<br/>%s' %
                (data[1], data[2] or ''))
        QMessageBox.__init__(self, QMessageBox.Information,
                             'NICOS Plug & Play', message,
                             QMessageBox.NoButton, parent)
        self.setWindowModality(Qt.NonModal)
        self.b0 = self.addButton('Ignore', QMessageBox.RejectRole)
        self.b0.setIcon(self.style().standardIcon(
            QStyle.SP_DialogCancelButton))
        if add_mode:
            self.b1 = self.addButton('Load setup', QMessageBox.YesRole)
        else:
            self.b1 = self.addButton('Remove setup', QMessageBox.YesRole)
        self.b1.setIcon(self.style().standardIcon(QStyle.SP_DialogOkButton))
        self.b0.clicked.connect(self.on_ignore_clicked)
        self.b1.clicked.connect(self.on_execute_clicked)
        self.b0.setFocus()

    def on_ignore_clicked(self):
        self.closed.emit(self)
        self.reject()

    def on_execute_clicked(self):
        if self.data[0] == 'added':
            self.client.run('AddSetup(%r)' % self.data[1])
        else:
            self.client.run('RemoveSetup(%r)' % self.data[1])
        self.closed.emit(self)
        self.accept()

    def closeEvent(self, event):
        self.closed.emit(self)
        return QMessageBox.closeEvent(self, event)

    def on_client_setup(self, data):
        setupnames = data[0]
        if self.data[0] == 'added' and self.data[1] in setupnames:
            # somebody loaded the setup!
            self.on_ignore_clicked()
        elif self.data[0] == 'removed' and self.data[1] not in setupnames:
            # somebody unloaded the setup!
            self.on_ignore_clicked()
예제 #13
0
class CustomCombo(QComboBox):

    valueChanged = pyqtSignal(int)

    def __init__(self, container=None, box_data=None, init_state=None):
        QComboBox.__init__(self, parent=container)
        self.current = init_state
        for item in box_data:
            self.addItem('%s' % item)
        self.setCurrentIndex(self.current)
        self.currentIndexChanged[int].connect(self.index_changed)

    @pyqtSlot(int)
    def index_changed(self, index):
        # self.setDisabled(True)
        self.valueChanged[int].emit(index)

    def mousePressEvent(self, e):
        if e.button() == Qt.RightButton:
            if self.parent():
                self.parent().mousePressEvent(e)
        else:
            QComboBox.mousePressEvent(self, e)

    def setValue(self, val):
        self.current = val
        self.setCurrentIndex(self.findText('%s' % val))
        self.setEnabled(True)

    def value(self):
        return self.currentText()
예제 #14
0
class SetupDepPanelMixin(QObject):
    """Mixin to handle setup-dependent visibility.

    Note: You must explicity add the following class attribute in all
    classes using this mixin (A PyQt resctriction, see
    https://riverbankcomputing.com/pipermail/pyqt/2013-September/033199.html):

    `setWidgetVisible = SetupDepPanelMixin.setWidgetVisible`
    """
    setupSpec = ()
    setWidgetVisible = pyqtSignal(QWidget, bool, name='setWidgetVisible')

    def __init__(self, client, options):  # pylint: disable=super-init-not-called
        setups = options.get('setups', '')
        self.setSetups(setups)
        client.register(self, 'session/mastersetup')

    def setSetups(self, setupSpec):
        self.setupSpec = setupSpec
        self.log.debug('setups are: %r', self.setupSpec)
        checkSetupSpec(self.setupSpec, '', log=self.log)

    def on_keyChange(self, key, value, time, expired):
        if key == 'session/mastersetup' and self.setupSpec:
            if hasattr(self, 'setWidgetVisible'):
                enabled = checkSetupSpec(self.setupSpec, value, log=self.log)
                self.setWidgetVisible.emit(self, enabled)
예제 #15
0
class CondCell(CellItem):
    standard_value = 'TrueTime'
    conds = ('LiveTime', 'TrueTime', 'ClockTime', 'counts')

    condChanged = pyqtSignal(str)

    def __init__(self, controller, parent=None, state=None):
        CellItem.__init__(self, controller, parent, state)
        index = int(self.conds.index(self.state))
        self.cc = CustomCombo(container=self,
                              box_data=self.conds,
                              init_state=index)
        self.cc.valueChanged[int].connect(self.on_cb_changed)
        self.widgets.append(self.cc)
        self.set_layout()
        self.setMaximumWidth(100)

    def setValue(self, new_data):
        if new_data in CondCell.conds:
            self.cc.setValue(new_data)
            self.state = new_data
            self.condChanged.emit(new_data)

    def value(self):
        return self.cc.currentText()

    @pyqtSlot(int)
    def on_cb_changed(self, index):
        self.cellChanged.emit(self)
        self.condChanged.emit(self.value())
예제 #16
0
class CustomLED(ClickableOutputLed):
    """Just views to what state the Attenuator should/will be set."""

    valueChanged = pyqtSignal(int)

    def __init__(self,
                 container,
                 state_names=('in', 'out'),
                 state_colors=('blue', 'yellow'),
                 initState=None):
        ClickableOutputLed.__init__(self, parent=container)
        self.stateActive = state_names[0]
        self.stateInactive = state_names[1]
        self._colorActive = state_colors[0]
        self._colorInactive = state_colors[1]
        self.current = initState
        self.set_ledcolor()

    def set_ledcolor(self):
        self.ledColor = self._colorActive \
            if self.current == self._stateActive else self._colorInactive

    def setValue(self, val):
        self.current = val
        self.set_ledcolor()

    def value(self):
        return self.current

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.setValue(self._stateInactive if self.current ==
                          self._stateActive else self._stateActive)
            self.valueChanged[int].emit(self.current)
            event.accept()
예제 #17
0
class MultiEntry(QWidget):
    addOrRemove = pyqtSignal()

    def __init__(self, parent, client, uifile):
        QWidget.__init__(self, parent)
        new_layout = QHBoxLayout()
        self.subwidget = QWidget(self)
        if uifile:
            uic.loadUi(uifile, self.subwidget)
        self.button = QToolButton(self)
        self.setButton('+')
        self.button.clicked.connect(self.on_button_click)
        new_layout.addWidget(self.subwidget)
        new_layout.addSpacerItem(QSpacerItem(15, 1, QSizePolicy.Fixed))
        new_layout.addWidget(self.button)
        new_layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(new_layout)
        for ch in self.subwidget.findChildren(NicosWidget):
            ch.setClient(client)

    def setButton(self, plusminus):
        self.button.setText(plusminus)
        if plusminus == '+':
            self.button.setToolTip('Add another')
        else:
            self.button.setToolTip('Remove this')

    def on_button_click(self):
        self.addOrRemove.emit()
예제 #18
0
class CellItem(QWidget):
    standard_value = ''

    cellChanged = pyqtSignal('QWidget')

    def __init__(self, controller, parent=None, state=None):
        QWidget.__init__(self, parent)

        # update Request for parameter gets sent to controller
        self.controller = controller

        # contains widgets that are currently displayed
        self.widgets = []
        self.state = state if state is not None else self.standard_value
        self.doubleclick = None

        # setting up layout:
        layout = QHBoxLayout()
        layout.setContentsMargins(0.1, 0.1, 0.1, 0.1)
        layout.setSpacing(1)
        self.setLayout(layout)

    def set_enabled(self, enabled):
        for widget in self.widgets:
            widget.setEnabled(enabled)
        # some
        self.reloadstate()

    def reloadstate(self):
        pass

    def is_enabled(self):
        return max(w.isEnabled() for w in self.widgets)

    def set_layout(self):
        for w in self.widgets:
            self.layout().addWidget(w)

    def setValue(self, val):
        self.label.setText('%s' % val)

    def value(self):
        return self.label.text()

    def disable(self):
        for w in self.widgets:
            w.setDisabled(True)

    def mouseDoubleClickEvent(self, e):
        for w in self.widgets:
            w.setEnabled(True)
        if self.doubleclick is not None:
            self.doubleclick = True
        e.ignore()
예제 #19
0
class AnnotatedWidget(QWidget):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    def __init__(self, parent, inner, annotation):
        QWidget.__init__(self, parent)
        layout = self._layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self._inner = inner
        self._inner.valueModified.connect(self.valueModified)
        self._inner.valueChosen.connect(self.valueChosen)
        layout.addWidget(inner)
        layout.addWidget(QLabel(annotation, parent))
        self.setLayout(layout)

    def getValue(self):
        return self._inner.getValue()

    def setFocus(self):
        self._inner.setFocus()
예제 #20
0
class SpinBoxWidget(QSpinBox):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    def __init__(self,
                 parent,
                 curvalue,
                 minmax,
                 fmtstr='%.4g',
                 allow_enter=False):
        QSpinBox.__init__(self, parent)
        self.setRange(minmax[0], minmax[1])
        self.setValue(curvalue)
        self.valueChanged['int'].connect(lambda val: self.valueModified.emit())
        if allow_enter:
            self.lineEdit().returnPressed.connect(
                lambda: self.valueChosen.emit(self.value()))

    def getValue(self):
        return self.value()
예제 #21
0
class ButtonWidget(QWidget):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    def __init__(self, parent, values):
        QWidget.__init__(self, parent)
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self._values = {}
        for value in values:
            btn = QPushButton(str(value), self)
            self._values[btn] = value
            btn.clicked.connect(self.on_button_pressed)
            layout.addWidget(btn)
        self.setLayout(layout)

    def on_button_pressed(self):
        self.valueChosen.emit(self._values[self.sender()])

    def getValue(self):
        return Ellipsis
예제 #22
0
class EditWidget(QLineEdit):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    def __init__(self,
                 parent,
                 typ,
                 curvalue,
                 fmtstr='%.4g',
                 minmax=None,
                 allow_enter=False):
        QLineEdit.__init__(self, parent)
        self._typ = typ
        if typ is float:
            val = DoubleValidator(self)
            if minmax:
                # setRange doesn't work correctly in some Qt versions...
                val.setBottom(minmax[0])
                if minmax[1] is not None:
                    val.setTop(minmax[1])
            self.setValidator(val)
            self.setText(fmtstr % curvalue)
        elif typ is int:
            val = QIntValidator(self)
            if minmax:
                val.setRange(minmax[0], minmax[1])
            self.setValidator(val)
            self.setText(str(curvalue))
        else:
            self.setText(str(curvalue))
        self.textChanged.connect(lambda txt: self.valueModified.emit())
        if allow_enter:
            self.returnPressed.connect(
                lambda: self.valueChosen.emit(self._typ(self.text())))

    def getValue(self):
        return self._typ(self.text())
예제 #23
0
파일: live.py 프로젝트: ess-dmsc/nicos
class LiveWidget(DefaultLiveWidget):
    """
    Add a 'name' attribute to LiveWidget and emit 'clicked' signal when clicked
    """

    clicked = pyqtSignal(str)

    def __init__(self, name, parent=None):
        DefaultLiveWidget.__init__(self, parent)
        self.setMinimumSize(150, 150)
        self.name = name

    def mousePressEvent(self, event):
        self.clicked.emit(self.name)
예제 #24
0
class DeviceParam(QWidget):
    editedParam = pyqtSignal()
    clickedRemoveButton = pyqtSignal(str)

    def __init__(self, param, valueWidget, isUnknownValue=False, parent=None):
        QWidget.__init__(self, parent)
        uic.loadUi(
            path.abspath(
                path.join(path.dirname(__file__), 'ui', 'deviceparam.ui')),
            self)
        self.placeholder.setVisible(False)
        self.param = param
        self.valueWidget = valueWidget
        self.isUnknownValue = isUnknownValue
        self.pushButtonRemove.clicked.connect(
            lambda: self.clickedRemoveButton.emit(self.param))
        self.labelParam.setText(self.param + ':')
        self.horizontalLayout.addWidget(self.valueWidget)
        self.valueWidget.valueModified.connect(self.editedParam)
        self.valueWidget.valueChosen.connect(lambda _: self.editedParam.emit())

    def getValue(self):
        return self.valueWidget.getValue()
예제 #25
0
class ComboWidget(QComboBox):

    valueModified = pyqtSignal()
    valueChosen = pyqtSignal(object)

    def __init__(self, parent, values, curvalue, add_other=False):
        QComboBox.__init__(self, parent)
        self._values = sorted(values, key=str)
        self._textvals = list(map(str, self._values))
        self._add_other = add_other
        if add_other:
            self._values.append(Ellipsis)
            self._textvals.append('<other value>')
        self.addItems(self._textvals)
        if curvalue in self._values:
            self.setCurrentIndex(self._values.index(curvalue))
        elif add_other:
            self.setCurrentIndex(len(self._values) - 1)
        self.currentIndexChanged['int'].connect(
            lambda idx: self.valueModified.emit())

    def getValue(self):
        return self._values[self._textvals.index(self.currentText())]
예제 #26
0
class MeasElement(QObject):
    """Represents one setting for a measurement that can be manipulated."""

    LABEL = ''
    ORDER = 1

    changed = pyqtSignal(object)

    def __init__(self, eltype, client, value=None, extra=None):
        """Initialize widget contents, if necessary."""
        QObject.__init__(self)
        self.eltype = eltype
        self.value = value
        self.extra = extra
        self._widget = None
        self.clientUpdate(client)

    def getLabel(self):
        """Return label for the element."""
        if self.LABEL:
            return self.LABEL
        return self.eltype.capitalize()

    def clientUpdate(self, client):
        """Update internal info from daemon."""

    def createWidget(self, parent, client):
        """Create and return a Qt widget for editing this element."""

    def destroyWidget(self):
        """Destroy the currently created widget."""
        if self._widget:
            self._widget.deleteLater()
            self._widget = None

    def getValue(self):
        """Return currently selected value."""
        return self.value

    def getDispValue(self):
        """Return a form of the value to be displayed."""
        return str(self.getValue())

    def otherChanged(self, eltype, value):
        """Hook to be called when a sibling element changed."""
예제 #27
0
파일: tabwidget.py 프로젝트: ess-dmsc/nicos
class DetachedWindow(QMainWindow):

    closed = pyqtSignal(object)

    def __init__(self, title, parent):
        self.tabIdx = -1
        QMainWindow.__init__(self, parent)
        self.setWindowTitle(title)
        self.setWindowModality(Qt.NonModal)
        self.sgroup = SettingGroup(title)
        with self.sgroup as settings:
            loadBasicWindowSettings(self, settings)

    @pyqtSlot(QWidget, bool)
    def setWidgetVisibleSlot(self, widget, visible):
        self.setVisible(visible)

    def setWidget(self, widget):
        self.setCentralWidget(widget)
        widget.show()

    def closeEvent(self, event):
        with self.sgroup as settings:
            settings.setValue('detached', False)
        self.closed.emit(self)
        self.deleteLater()

    def moveEvent(self, event):
        QMainWindow.moveEvent(self, event)
        self.saveSettings()

    def resizeEvent(self, event):
        QMainWindow.resizeEvent(self, event)
        self.saveSettings()

    def saveSettings(self, detached=True):
        with self.sgroup as settings:
            settings.setValue('detached', detached)
            settings.setValue('geometry', self.saveGeometry())
            settings.setValue('windowstate', self.saveState())
예제 #28
0
class StandaloneHistoryWindow(DlgUtils, BaseHistoryWindow, QMainWindow):

    newValue = pyqtSignal(object)

    def __init__(self, app):
        QMainWindow.__init__(self, None)
        self.app = app
        self.client = app  # used by the NewViewDialog

        # this is done in Panel.__init__ for the panel version
        self.settings = CompatSettings()
        self.loadSettings(self.settings)

        BaseHistoryWindow.__init__(self)
        self.splitter.setSizes([20, 80])

        DlgUtils.__init__(self, 'History viewer')

        self.actionAttachElog.setVisible(False)

        self.splitter.restoreState(self.splitterstate)

        self.setCentralWidget(self.splitter)
        self.newValue.connect(self.newvalue_callback)

        for toolbar in self.getToolbars():
            self.addToolBar(toolbar)
        for menu in self.getMenus():
            self.menuBar().addMenu(menu)
        self.actionFitLinear.trigger()
        self.statusBar = QStatusBar(self)
        self.setStatusBar(self.statusBar)

    def gethistory_callback(self, key, fromtime, totime):
        return self.app.history(None, key, fromtime, totime)

    def closeEvent(self, event):
        self.saveSettings(self.settings)
        return QMainWindow.closeEvent(self, event)
예제 #29
0
class TimelineWidget(QGraphicsView):
    """General widget to display timeline with a list of ordered timepoints.
    A timepoint is selectable via click and the timepointSelected signal
    can be used to react to it."""
    timepointSelected = pyqtSignal(object)  # datetime.datetime object

    # general layout and design parameters
    TIMEPOINT_DIAMETER = 30
    SELECTION_DIAMETER = 40
    TIMEPOINT_SPACING = 50
    TIMELINE_WIDTH = 5
    LABEL_SPACING = 20
    MARGIN_HORIZONTAL = 5
    STRFTIME_FMT = '%H:%M:%S\n%Y-%m-%d'

    def __init__(self, parent=None):
        QGraphicsView.__init__(self, QGraphicsScene(), parent)
        self.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.setRenderHints(QPainter.Antialiasing
                            | QPainter.SmoothPixmapTransform)

        # margins set to 0 to simplify calculations
        self.setContentsMargins(0, 0, 0, 0)
        self.setViewportMargins(0, 0, 0, 0)

        # full viewport updates required to avoid optical double selections
        # caused by scrolling
        self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)

        self._time_points = []
        self._time_point_items = {}
        self._selection_item = None

        # start with at least one time point (current time) to be able
        # to reuse size calculation methods for the inital size
        self.setTimePoints([datetime.now()])

    @property
    def time_points(self):
        """Sorted list of all timepoints (sorted new to old)"""
        return self._time_points

    @property
    def selected_time_point(self):
        """Get the selected timeout as datetime object. None if there is no
        selection."""
        if self._selection_item is None:
            return None

        return self._time_point_items[self._selection_item]

    @property
    def previous_time_point(self):
        """Get the timepoint before (older than) the currently selected one as
        datetime object. None if there is no selection"""
        try:
            index = self._time_points.index(self.selected_time_point)
            return self._time_points[index + 1]
        except (ValueError, IndexError):
            return None

    def resizeEvent(self, event):
        """Clear and readd all items on resize. Avoids complex scaling."""
        self.scene().clear()
        self.setTimePoints(self._time_points)

    def setTimePoints(self, time_points):
        """Sets and list of datetime objects as timepoints, sets up all
        necessary graphics items and adjusts sizes."""

        self.scene().clear()
        self._selection_item = None

        # store the timepoints sorted from new to old
        self._time_points = list(reversed(sorted(time_points)))
        self._time_point_items = {}

        # draw the timeline
        self._timeline = self._add_timeline()

        # draw the time points
        self._add_time_points()

        # update the scene size and a slightly larger widget size to avoid
        # superfluous scrolling (and displaying of scroll bars)
        size = self.scene().itemsBoundingRect().size()
        self.setSceneRect(0, 0, size.width(), size.height() - 5)

        if time_points:
            self.setMinimumWidth(size.width() * 1.2)
            self.setMaximumWidth(size.width() * 1.2)

    def mousePressEvent(self, event):
        """Handle mouse press events to support item selection."""
        item = self.itemAt(event.pos())
        if item in self._time_point_items:
            self._select_item(item)

        return QGraphicsView.mousePressEvent(self, event)

    def _select_item(self, item):
        """Select the given item by drawing a colored circle beneath the
        selected item (so it looks like a ring around it.
        Also emits the timepointSelected signal."""

        # The selection_item used to signal the selection of a timepoint
        # is always the same and is only moved.
        if self._selection_item is None:
            self._selection_item = QGraphicsEllipseItem(
                0, 0, self.SELECTION_DIAMETER, self.SELECTION_DIAMETER)

            # The used color is a cubical to the time point color
            self._selection_item.setBrush(QBrush(QColor(0x70, 0xbb, 0x00)))
            self._selection_item.setPen(QPen(0))
            self.scene().addItem(self._selection_item)

        # center position of the timepoint circle
        center_x = item.pos().x() + self.TIMEPOINT_DIAMETER / 2
        center_y = item.pos().y() + self.TIMEPOINT_DIAMETER / 2

        # move selection item
        self._selection_item.setPos(center_x - self.SELECTION_DIAMETER / 2,
                                    center_y - self.SELECTION_DIAMETER / 2)

        # store the selection_item like a timepoint item (using the timepoint
        # of the selected item)
        self._time_point_items[self._selection_item] = \
            self._time_point_items[item]

        # emit signal at the end to ensure a valid internal state before
        # anything can react to it
        self.timepointSelected.emit(self._time_point_items[item])

    def _add_timeline(self):
        """Draw the timeline."""

        # height is either the necessary space to display all items or the
        # maximal available display size, so it's looks nicely in larger
        # windows and enables scrolling in smaller ones.
        height = self.TIMEPOINT_DIAMETER * len(self._time_points)
        height += self.TIMEPOINT_SPACING * len(self._time_points)
        height = max(height, self.viewport().height())

        # draw the timeline left aligned with enough space to draw the items
        # and the selection ring.
        x = self.MARGIN_HORIZONTAL + (self.SELECTION_DIAMETER / 2)

        # position the line on the left side of the item
        item = QGraphicsLineItem(0, 0, 0, height)

        # The used color for the timeline is the lightest one of the FRM II
        # colors
        item.setPen(QPen(QBrush(QColor(0xa3, 0xc1, 0xe7)),
                         self.TIMELINE_WIDTH))

        self.scene().addItem(item)

        # move the whole item to the desired timeline position
        item.setPos(x, 0)
        return item

    def _add_time_points(self):
        """Add all time point items."""
        if not self._time_points:
            return

        timeline_pos = self._timeline.pos()
        timeline_size = self._timeline.boundingRect().size()
        height = timeline_size.height()

        # time points are always equally distributed on the timeline
        spacing = height / float(len(self._time_points))

        center_x = timeline_pos.x()

        # add half of the items spacing on the top and bottom of the timeline
        start = timeline_pos.y() - spacing / 2

        for i, entry in enumerate(self._time_points):
            self._add_time_point(center_x, start + spacing * (i + 1), entry)

    def _add_time_point(self, center_x, center_y, time_point):
        """Add a single time point item."""
        x = center_x - (self.TIMEPOINT_DIAMETER / 2)
        y = center_y - (self.TIMEPOINT_DIAMETER / 2)

        # Create the acutal time point item
        time_point_item = QGraphicsEllipseItem(0, 0, self.TIMEPOINT_DIAMETER,
                                               self.TIMEPOINT_DIAMETER)

        # The used color is the strongest one of the FRM II colors.
        time_point_item.setBrush(QBrush(QColor(0x00, 0x71, 0xbb)))
        time_point_item.setPen(QPen(0))

        self.scene().addItem(time_point_item)
        time_point_item.setPos(x, y)

        # place the time point item above the timeline and the selection item
        time_point_item.setZValue(2)

        # Create the label of the time point showing the time in the
        # defined strftime format on the right side of the time point item.
        label = QGraphicsTextItem(time_point.strftime(self.STRFTIME_FMT))
        label.setFont(QFont('Monospace'))
        label_height = label.boundingRect().height()

        # minor height adjustment
        label_y = y - label_height / 6

        self.scene().addItem(label)
        label.setPos(x + self.SELECTION_DIAMETER + self.LABEL_SPACING, label_y)

        # store references to the item and the timepoint in the same dict
        # to be able to use it for forward and reverse lookup
        self._time_point_items[time_point] = time_point_item
        self._time_point_items[time_point_item] = time_point
예제 #30
0
class Cmdlet(QWidget):

    name = ''
    category = ''

    cmdletUp = pyqtSignal()
    cmdletDown = pyqtSignal()
    cmdletRemove = pyqtSignal()
    valueModified = pyqtSignal()

    def __init__(self, parent, client, uifile):
        self.client = client
        QWidget.__init__(self, parent)
        loadUi(self, uifile)
        loadUi(self.buttons, 'cmdlets/buttons.ui')
        self.buttons.upBtn.clicked.connect(self.cmdletUp)
        self.buttons.downBtn.clicked.connect(self.cmdletDown)
        self.buttons.delBtn.clicked.connect(self.cmdletRemove)

    def removeSelf(self):
        self.parent().layout().removeWidget(self)
        self.hide()

    def changed(self, *args):
        """Should be called whenever any value in the cmdlet changes."""
        self.valueModified.emit()

    def getValues(self):
        """Return a dict with the values of the cmdlet.

        Values should have a name that is the same for the same logical
        value in multiple cmdlets, e.g. "dev" for the device in a command.
        """
        return {}

    def _getDeviceList(self, special_clause=''):
        """Helper for getting a list of devices for manipulation."""
        exp = getattr(self.parent(), 'expertmode', False)
        if exp:
            clause = special_clause
        else:
            clause = ('(dn in session.explicit_devices or '
                      '("nicos.core.mixins.AutoDevice" in d.classes and '
                      'dn.split(".")[0] in session.explicit_devices))')
            if special_clause:
                clause += ' and ' + special_clause
        # special construction to get AutoDevices like slit.centerx which is
        # useful to make scans over
        return self.client.getDeviceList('nicos.core.device.Moveable',
                                         only_explicit=False,
                                         special_clause=clause)

    def _getDeviceRepr(self, devname):
        """Return bare ``dev`` if the device is in the NICOS user namespace,
        else ``'dev'`` in quotes.
        """
        if self.client.eval(devname, None) is None:
            return srepr(devname)
        return devname

    def _setDevice(self, values):
        """Helper for setValues for setting a device combo box."""
        if 'dev' in values:
            idx = self.device.findText(values['dev'])
            if idx > -1:
                self.device.setCurrentIndex(idx)

    def setValues(self, values):
        """Set values of the cmdlet with values from the argument.

        Unknown values must be ignored.
        """

    def markValid(self, ctl, condition):
        """Return boolean condition, and also mark the offending widget.

        For use in isValid().
        """
        if condition:
            setBackgroundColor(ctl, Qt.white)
        else:
            setBackgroundColor(ctl, invalid)
        if isinstance(ctl, QAbstractSpinBox):
            # also mark the inner line-edit
            return self.markValid(ctl.lineEdit(), condition)
        return condition

    def isValid(self):
        """Check if all entered data is valid.

        This method can change widget styles to indicate invalid data with
        the markValid() method if wanted.
        """
        return True

    def generate(self, mode):
        """Generate code for the commandlet.

        *mode* is 'python' or 'simple'.

        Should generate a string of lines, complete with newlines.
        """
        return ''