Ejemplo n.º 1
0
 def setData(self, index, qvalue):
     taurus_role = index.model().role(index.column())
     str_value = Qt.from_qvariant(qvalue, str)
     if taurus_role in (ChannelView.Channel, ChannelView.Conditioning,
                        ChannelView.NXPath, ChannelView.DataType) :
         data = str_value
     elif taurus_role in (ChannelView.Enabled, ChannelView.Output) :
         data = Qt.from_qvariant(qvalue, bool)
     elif taurus_role == ChannelView.PlotType:
         data = PlotType[str_value]
     elif taurus_role == ChannelView.Normalization:
         data = Normalization[str_value]
     elif taurus_role == ChannelView.PlotAxes:
         data = [a for a in str_value.split(':')]
     elif taurus_role == ChannelView.Shape:
         s = str_value
         try:
             data = eval(s, {}, {})
             if not isinstance(data, (tuple, list)):
                 raise ValueError
         except:
             from taurus.core.util.log import Logger
             Logger(self.__class__.__name__).error('Invalid shape %s', s)
             data = ()
     else:
         raise NotImplementedError('Unknown role')
     ch_name, ch_data = self.itemData()
     key = self.itemdata_keys_map[taurus_role]
     ch_data[key] = data
Ejemplo n.º 2
0
 def _onEditDisplay(self):
     selected = self.selectionModel().selectedIndexes()
     if len(selected) == 1:
         idx = selected[0]
     else:
         return
     value = Qt.from_qvariant(self._model.data(
         idx, role=Qt.Qt.DisplayRole), str)
     src = Qt.from_qvariant(self._model.data(idx, role=SRC_ROLE), str)
     value, ok = Qt.QInputDialog.getText(
         self, "Display Value", "Display value for %s?" % src, Qt.QLineEdit.Normal, value)
     if not ok:
         return
     self._model.setData(idx, Qt.QVariant(value), role=Qt.Qt.DisplayRole)
Ejemplo n.º 3
0
    def setData(self, index, value, role=Qt.Qt.DisplayRole):
        '''see :meth:`Qt.QAbstractTableModel.setData`'''

        idx_data_str = Qt.from_qvariant(index.data(), str)
        value_str = Qt.from_qvariant(value, str)
        if idx_data_str == value_str:
            return False
        #self.itemFromIndex(index).setData(value, role)
        try:
            self.valueChanged(value_str, index)
        except:
            self.showError.emit('Wrong value!',
                      'The value you entered is wrong. The old value will be restored.')
            return Qt.QStandardItemModel.setData(self, index, index.data(), role)
        return Qt.QStandardItemModel.setData(self, index, value, role)
Ejemplo n.º 4
0
 def setEditorData(self, editor, index):
     if index.column() == 1:
         text = Qt.from_qvariant(index.model().data(index, Qt.Qt.DisplayRole), str)
         if text in ["None", "", None]:
             Qt.QItemDelegate.setEditorData(self, editor, index)
         else:
             node = index.model().mapToSource(index).internalPointer()
             paramType = node.type()
             if paramType in globals.EDITOR_COMBOBOX_PARAMS :
                 i = editor.findText(text)
                 if i == -1:
                     i = 0
                 else:
                     editor.previous = text
                 editor.setCurrentIndex(i)
             elif paramType in globals.EDITOR_SPINBOX_PARAMS:
                 editor.setValue(int(text))
             elif paramType in globals.EDITOR_DOUBLESPINBOX_PARAMS:
                 editor.setValue(float(text))
             elif paramType in globals.EDITOR_LINEEDIT_PARAMS:
                 editor.setText(text)
             elif paramType in globals.EDITOR_FILEDIALOG_PARAMS:
                 editor.filePath.setText(text)
     else:
         Qt.QItemDelegate.setEditorData(self, editor, index)
Ejemplo n.º 5
0
    def setData(self, index, qvalue, role=Qt.Qt.EditRole):
        #For those things which are at the unit level, we handle them here
        taurus_role = self.role(index.column())
        if taurus_role in (ChannelView.Timer, ChannelView.Monitor, ChannelView.Trigger):
            ch_name, ch_data = index.internalPointer().itemData()
            ch_info = self.getAvailableChannels()[ch_name]
            unit_data = self.getPyData(ctrlname=ch_data['_controller_name'], unitid=ch_data['_unit_id'])
            key = self.data_keys_map[taurus_role]
            data = Qt.from_qvariant(qvalue, str)

            self._dirty = True
            self.beginResetModel()
            is_settable = ch_info['type'] in ('CTExpChannel', 'OneDExpChannel', 'TwoDExpChannel')
            if taurus_role == ChannelView.Trigger:
                data = AcqTriggerType[data]
                if is_settable:
                    unit_data[key] = data
            else:
                if is_settable:
                    if unit_data[key] == self._mgconfig[key]:
                        self._mgconfig[key] = data
                    unit_data[key] = data
                else:
                    self._mgconfig[key] = data
            self.endResetModel()
            return True
        #for the rest, we use the regular TaurusBaseModel item-oriented approach
        #ret = self._setData(index, qvalue, role) #@todo we do not use _setData because it is not Qt4.4-compatible
        item = index.internalPointer()
        item.setData(index, qvalue)
        self._dirty = True
        self.emit(Qt.SIGNAL("dataChanged(const QModelIndex &, const QModelIndex &)"),
                  index, index)
        return True
Ejemplo n.º 6
0
    def getModifiedWriteData(self):
        '''
        returns an array for the write data that includes the user modifications

        :return: (numpy.array) The write values including user modifications.
        '''
        table = self._wtabledata
        kind = table.dtype.kind
        if kind in 'SU':
            table = table.tolist()  # we want to allow the strings to be larger than the original ones
            for (r, c), v in self._modifiedDict.items():
                table[r][c] = Qt.from_qvariant(v, str)
            table = numpy.array(table, dtype=str)
        else:
            for k, v in self._modifiedDict.items():
                if kind in ['f', 'i', 'u']:
                    units = self._parent.getCurrentUnits()
                    q = _value2Quantity(v, units)
                    table[k] = q
                elif kind == 'b':
                    # TODO: This does not work Qt.from_qvariant(v, bool)
                    if str(v) == "true":
                        table[k] = True
                    else:
                        table[k] = False
                else:
                    raise TypeError('Unknown data type "%s"' % kind)
        # reshape if needed
        if self._attr.data_format == DataFormat._1D:
            table = table.flatten()
        return table
Ejemplo n.º 7
0
    def _create_multi_selection_panel(self, input_data):
        panel = self._create_group_panel(input_data)
        layout = panel.layout()
        items = input_data['data_type']
        default_value = input_data.get('default_value')
        if default_value is None:
            default_value = ()
        dft_is_seq = not isinstance(default_value, (str, unicode)) and \
            isinstance(default_value, collections.Sequence)
        if not dft_is_seq:
            default_value = default_value,

        self._ui.inputWidget = listwidget = Qt.QListWidget()
        listwidget.setSelectionMode(Qt.QAbstractItemView.MultiSelection)

        for item in items:
            is_seq = not isinstance(item, (str, unicode)) and \
                isinstance(item, collections.Sequence)
            if is_seq:
                text, userData = item
            else:
                text, userData = str(item), item
            item_widget = Qt.QListWidgetItem(text, listwidget)
            item_widget.setData(Qt.Qt.UserRole, Qt.to_qvariant(userData))
            if userData in default_value:
                item_widget.setSelected(True)
        layout.addWidget(listwidget)
        return panel, self._get_multi_selection_value
Ejemplo n.º 8
0
    def getValue(self):
        """
        Get the value that the widget is displaying now, not the value
        of the attribute.
        """
        model = self.getModelObj()
        if model is None:
            return None
        dtype = model.type
        new_value = self.itemData(self.currentIndex())
        if new_value is None:
            return None

        if dtype == DataType.Integer:
            func = int
        elif dtype == DataType.Float:
            func = float
        elif dtype == DataType.String:
            func = str
        elif dtype == DataType.Boolean:
            func = bool
        else:
            return None
        new_value = Qt.from_qvariant(new_value, func)
        return new_value
Ejemplo n.º 9
0
    def valueChanged(self, value, index):
        '''
        Modifies value in the temporary settings file and the model internal
        dictionary. Invoked by :meth:`Qt.QAbstractTableModel.setData`, when user
        make changes to the value in the settings tree.

        :param value: (str) the new value (a string that will be python-evaluated)
        :param index: (QModelIndex) index of the model
        '''
        changedItem = self.itemFromIndex(index)
        path = Qt.from_qvariant(changedItem.data(Qt.Qt.UserRole), str)
        self._configurationDictionaries = self.changeTreeValue(
            self._configurationDictionaries, path, value)
        try:
            group = eval(str(path).split(';', 1)[0])
        except:
            group = str(path).split(';', 1)[0]
        itemToMark = self.itemFromIndex(index.sibling(index.row(), 0))
        self.markedItems.append(itemToMark.index())

        self.itemFromIndex(index.sibling(index.row(), 1)
                           ).setText(str(type(eval(value))))
        changedItem.setData(Qt.QVariant(
            'Value has been changed. Old value: ' + str(changedItem.text())),
            Qt.Qt.ToolTipRole)
        itemToMark.setData(Qt.QVariant(Qt.QIcon.fromTheme('emblem-important')),
                           Qt.Qt.DecorationRole)
        while(itemToMark is not None):
            itemToMark.setData(Qt.QVariant(
                Qt.QFont("Arial", 10, Qt.QFont.Bold)), Qt.Qt.FontRole)
            itemToMark = self.itemFromIndex(itemToMark.index().parent())
        self.saveSettings(group)
Ejemplo n.º 10
0
    def deleteBranch(self):
        '''
        Deletes selected branch from the settings tree. Also updates the
        temporary configuration file.
        '''
        tmpindex = self._toDeleteIndex
        item = self.itemFromIndex(tmpindex)
        path = Qt.from_qvariant(item.data(Qt.Qt.UserRole), str)
        self._delete = False
        self._configurationDictionaries = self.removeBranch(
            self._configurationDictionaries, path)

        try:
            group = eval(str(path).split(';', 1)[0])
        except:
            group = str(path).split(';', 1)[0]
        itemToMark = self.itemFromIndex(tmpindex.parent())
        while(itemToMark is not None):
            itemToMark.setData(Qt.QVariant(
                Qt.QFont("Arial", 10, Qt.QFont.Bold)), Qt.Qt.FontRole)
            itemToMark = self.itemFromIndex(itemToMark.index().parent())

        self.markedItems.append(self._toDeleteIndex.parent())
        self.removeRow(tmpindex.row(), tmpindex.parent())
        self.saveSettings(group)
Ejemplo n.º 11
0
def set_property_methods(obj, name, type_="QString", default=None, getter=None, setter=None, reset=None, get_callback=None, set_callback=None, reset_callback=None, qt=False, config=False):
    """
    This method allows to add QProperties dynamically with calls like:
    <pre>
        set_property_methods(self,'Filters','QString',default='',
            set_callback=lambda s=self:s.loadTree(s.getFilters(),clear=True),
            reset_callback=lambda s=self:s.loadTree('',clear=True)
            )
    </pre>

    @TODO: This method should be refactored using python descriptors/properties and types.MethodType
    """
    klass = obj.__class__
    mname = '%s%s' % (name[0].upper(), name[1:])
    lname = '%s%s' % (name[0].lower(), name[1:])
    getter = getter or (lambda o=obj, n=name, c=get_callback: get_property(
        o, n, c))  # partial(get_property,name=name,callback=get_callback)
    setter = setter or (lambda x, y=None, o=obj, d=default, n=name, c=set_callback: set_property(
        o, n, x if x is not obj else y, c))  # partial(set_property),name=name,callback=set_callback)
    reset = reset or (lambda o=obj, n=name, d=default, c=reset_callback: reset_property(
        o, n, d, c))  # partial(reset_property,name=name,default=default,callback=reset_callback)
    setattr(obj, 'set%s' % mname, setter)
    setattr(obj, 'get%s' % mname, getter)
    setattr(obj, 'reset%s' % mname, reset)
    if qt:
        setattr(klass, lname, Qt.pyqtProperty(
            "QString", getter, setter, reset))
    if config:
        obj.registerConfigProperty(getter, setter, name)
    reset()
Ejemplo n.º 12
0
 def mimeData(self, indexes):
     mimedata = Qt.QAbstractTableModel.mimeData(self, indexes)
     if len(indexes) == 1:
         #            txt = Qt.from_qvariant(self.data(indexes[0], str)
         #            mimedata.setData(TAURUS_ATTR_MIME_TYPE, txt)
         txt = Qt.from_qvariant(self.data(indexes[0], role=SRC_ROLE), str)
         mimedata.setText(txt)
     return mimedata
Ejemplo n.º 13
0
 def _setData(self, index, qvalue, role=QtQt.EditRole):
     item = index.internalPointer()
     pyobj = Qt.from_qvariant(qvalue)
     if pyobj is NotImplemented:
         self.warning(
             "Failed attempt to convert a QValue. Maybe it is due to Qt<4.6")
     item.setData(index, pyobj)
     return True
Ejemplo n.º 14
0
 def onItemChanged(self, item):
     """slot used when an item data has changed"""
     name = Qt.from_qvariant(item.data(self.NAME_ROLE), str)
     previousTitle = self.curvePropDict[name].title
     currentTitle = item.text()
     if previousTitle != currentTitle:
         self.curvePropDict[name].title = currentTitle
         self.CurveTitleEdited.emit(name, currentTitle)
Ejemplo n.º 15
0
    def setData (self, index, value, role=Qt.Qt.EditRole):
        node = self.nodeFromIndex(index)
#        if index.isValid() and 0 <= index.row() < len(node.parent()):
        if index.column() == 1:
            node.setValue(Qt.from_qvariant(value, str))
            self.emit(Qt.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index)
            return True
        return False
Ejemplo n.º 16
0
 def mimeData(self, indexes):
     '''reimplemented from :class:`Qt.QAbstractListModel`'''
     mimedata = Qt.QAbstractListModel.mimeData(self, indexes)
     if len(indexes) == 1:
         # mimedata.setData(TAURUS_ATTR_MIME_TYPE,
         # Qt.from_qvariant(self.data(indexes[0]), str)))
         txt = Qt.from_qvariant(self.data(indexes[0], role=SRC_ROLE), str)
         mimedata.setText(txt)
     return mimedata
Ejemplo n.º 17
0
    def setEditorData(self, editor, index):
        '''
        see :meth:`Qt.QStyledItemDelegate.setEditorData`
        '''
        if index.model().editedIndex == (index.row(), index.column()):
            return
        index.model().editedIndex = (index.row(), index.column())
        self._initialText = None
        if index.model().getType() == bool:
            editor.addItems(['true', 'false'])
            a = str(Qt.from_qvariant(index.data(), bool)).lower()
            self._initialText = a

            editor.setCurrentIndex(editor.findText(a))
        else:
            data = index.model().data(index, Qt.Qt.EditRole)
            self._initialText = Qt.from_qvariant(data, str)
            editor.setText(str(self._initialText))
Ejemplo n.º 18
0
 def setEditorData(self, editor, index):
     model = index.model()
     dataSource = model.dataSource()
     taurus_role = model.role(index.column())
     if taurus_role == ChannelView.PlotType:
         editor.addItems(PlotType.keys())
         current = Qt.from_qvariant(model.data(index), str)
         editor.setCurrentIndex(editor.findText(current))
     elif taurus_role == ChannelView.Normalization:
         editor.addItems(Normalization.keys())
         current = Qt.from_qvariant(model.data(index), str)
         editor.setCurrentIndex(editor.findText(current))
     elif taurus_role in (ChannelView.Timer, ChannelView.Monitor):
         key = taurus_role == ChannelView.Timer and 'timer' or 'monitor'
         ch_name, ch_data = index.internalPointer().itemData()
         ctrl_filterlist = [ch_data['_controller_name']]
         ctrl_dict = getChannelConfigs(dataSource, ctrls=ctrl_filterlist)
         all_channels = model.getAvailableChannels()
         # if it is a timer capable type of element
         if all_channels[ch_name]['type'] in ('CTExpChannel', 'OneDExpChannel', 'TwoDExpChannel'):
             for full_name, channel_data in ctrl_dict:
                 editor.addItem(channel_data['name'], Qt.QVariant(full_name))
             current = Qt.from_qvariant(model.data(index), str)
             editor.setCurrentIndex(editor.findText(current))
         else:
             for ctrl_data in dataSource['controllers'].values():
                 for unit_data in ctrl_data['units'].values():
                     if key in unit_data:
                         channel = all_channels[unit_data[key]]
                         editor.addItem(channel['name'], Qt.QVariant(channel['full_name']))
             current = dataSource.get(key)  # current global timer/monitor
             editor.setCurrentIndex(editor.findData(Qt.QVariant(current)))
     elif taurus_role == ChannelView.Trigger:
         editor.addItems(AcqTriggerType.keys())
         current = Qt.from_qvariant(model.data(index), str)
         editor.setCurrentIndex(editor.findText(current))
     elif taurus_role == ChannelView.PlotAxes:
         selectables = ['<idx>', '<mov>'] + [n for n, d in getChannelConfigs(dataSource)]
         editor.setChoices(selectables)
         current = Qt.from_qvariant(model.data(index), str)
         editor.setCurrentChoices(current)
     else:
         Qt.QStyledItemDelegate.setEditorData(self, editor, index)
Ejemplo n.º 19
0
    def getSelectedCurveNames(self):
        """Returns the curve names for the curves selected at the curves list.

        *Note*: The names may differ from the displayed text, which
        corresponds to the curve titles (this method is what you likely need if
        you want to get keys to use in curves or curveProp dicts).

        :return: (string_list) the names of the selected curves
        """
        return [Qt.from_qvariant(item.data(self.NAME_ROLE), str) for item in self.curvesLW.selectedItems()]
Ejemplo n.º 20
0
Archivo: senv.py Proyecto: cmft/sardana
 def setData(self, index, value=None, role=Qt.Qt.EditRole):
     if index.isValid() and (0 <= index.row() < self.rowCount()):
         row = index.row()
         column = index.column()
         value = Qt.from_qvariant(value, str)
         if column == 0: self.__columns[row]['label'] = value
         elif column == 1: self.__columns[row]['model'] = value
         elif column == 2: self.__columns[row]['instrument'] = value
         self.emit(Qt.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index)
         return True
     return False
Ejemplo n.º 21
0
 def setData (self, index, value, role=Qt.Qt.EditRole):
     node = self.nodeFromIndex(index)
     if index.column() == 1:
         if isinstance(node, macro.SingleParamNode):
             node.setValue(Qt.from_qvariant(value, str))
             self.emit(Qt.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index)
             while True:
                 index = index.parent()
                 node = self.nodeFromIndex(index)
                 if isinstance(node, macro.MacroNode):
                     self.emit(Qt.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index.sibling(index.row(), self.columnCount(index) - 1))
                     break
     elif index.column() == 2:
         progress = Qt.from_qvariant(value, float)
         node.setProgress(progress)
         self.emit(Qt.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index)
     elif index.column() == 3:
         node.setPause(Qt.from_qvariant(value, bool))
         self.emit(Qt.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index)
     return True
Ejemplo n.º 22
0
 def setData(self, index, value=None, role=Qt.Qt.EditRole):
     '''reimplemented from :class:`Qt.QAbstractListModel`'''
     if index.isValid() and (0 <= index.row() < self.rowCount()):
         row = index.row()
         item = self.items[row]
         value = Qt.from_qvariant(value, unicode)
         if role == Qt.Qt.EditRole:
             item.src = value
         elif role == Qt.Qt.DisplayRole:
             item.display = value
         self.dataChanged.emit(index, index)
         return True
     return False
Ejemplo n.º 23
0
    def contextMenuEvent(self, event):
        '''Reimplemented from :meth:`QWidget.contextMenuEvent`'''

        self.tree._toDeleteIndex = self.treeview.selectedIndexes()[0]
        text = Qt.from_qvariant(self.tree._toDeleteIndex.data(), str)
        if self.tree._toDeleteIndex.column() in [1, 2] or text in ['LAST', '[custom]'] or text in self.tree.perspectives:
            return
        menu = Qt.QMenu()
        menu.addAction(Qt.QIcon.fromTheme('process-stop'),
                       "Delete branch: " + text, self.tree.deleteBranch)
        menu.addSeparator()
        menu.addAction(Qt.QIcon.fromTheme('help-browser'), "Help")
        menu.exec_(event.globalPos())
        event.accept()
Ejemplo n.º 24
0
 def _onReportTriggered(self, index):
     report_handlers = get_report_handlers()
     combo = self.reportComboBox()
     name = Qt.from_qvariant(combo.itemData(index), str)
     report_handler = report_handlers[name]
     report = report_handler(self)
     app = Qt.QApplication.instance()
     txt = _REPORT.format(
         appName=app.applicationName(),
         appVersion=app.applicationVersion(),
         time=datetime.datetime.now().ctime(),
         text=self.getText(),
         detail=self.getDetailedText(),
         origin=self.getOriginText(),
     )
     report.report(txt)
Ejemplo n.º 25
0
    def getTaurusConfigFromSettings(self, key='TaurusConfig'):
        '''
        Loads and returns the configuration dictionary from the settings file
        using pickle module.

        :param key: (str)

        :returns (dict)
        '''
        result = None
        qstate = Qt.from_qvariant(self._settings.value(key), 'toByteArray')
        if qstate is not None and not qstate.isNull():
            try:
                result = pickle.loads(qstate.data())
            except Exception, e:
                msg = 'problems loading TaurusConfig: \n%s' % repr(e)
                Qt.QMessageBox.critical(None, 'Error loading settings', msg)
Ejemplo n.º 26
0
 def setData(self, index, value=None, role=Qt.Qt.EditRole):
     if index.isValid() and (0 <= index.row() < self.rowCount()):
         row = index.row()
         curve = self.curves[row]
         column = index.column()
         value = Qt.from_qvariant(value, str)
         if column == X:
             curve.taurusparam.xModel = value
             curve.x.processSrc(value)
         elif column == Y:
             curve.taurusparam.yModel = value
             curve.y.processSrc(value)
         elif column == TITLE:
             curve.curveparam.label = value
         self.dataChanged.emit(index, index)
         return True
     return False
Ejemplo n.º 27
0
    def sizeHint(self, option, index):
        if index.column() == 0:
            fm = option.fontMetrics
            text = Qt.from_qvariant(index.model().data(index, Qt.Qt.DisplayRole), str)
            document = Qt.QTextDocument()
            document.setDefaultFont(option.font)
            document.setHtml(text)
            size = Qt.QSize(document.idealWidth() + 5, fm.height())
        elif index.column() == 1:
            editor = self.createEditor(self.parent(), option, index)
            if editor is None:
                size = Qt.QItemDelegate.sizeHint(self, option, index)
            else:
                size = editor.sizeHint()
                editor.hide()
                editor.setParent(None)
#                editor.destroy()
        else:
            size = Qt.QItemDelegate.sizeHint(self, option, index)
        return size
Ejemplo n.º 28
0
    def setEditorData(self, editor, index):
        if index.column() == 1:
            text = Qt.from_qvariant(index.model().data(index, Qt.Qt.DisplayRole), str)
            if text == "None" or text == "" or text is None:
                Qt.QStyledItemDelegate.setEditorData(self, editor, index)
            else:
                editor.setValue(text)
#                node = index.model().nodeFromIndex(index)
#                paramType = node.type()
#                if paramType in globals.EDITOR_COMBOBOX_PARAMS :
#                    editor.setValue(text)
#                elif paramType in globals.EDITOR_SPINBOX_PARAMS:
#                    editor.setValue(int(text))
#                elif paramType in globals.EDITOR_DOUBLESPINBOX_PARAMS:
#                    editor.setValue(float(text))
#                elif paramType in globals.EDITOR_LINEEDIT_PARAMS:
#                    editor.setText(text)
#                elif paramType in globals.EDITOR_FILEDIALOG_PARAMS:
#                    editor.filePath.setText(text)
        else:
            Qt.QStyledItemDelegate.setEditorData(self, editor, index)
Ejemplo n.º 29
0
    def calculate(self):
        db = self.getModelObj()
        if db is None:
            return

        g_layout = self.layout()

        filters = []
        for i in xrange(1, g_layout.count() - 1):
            field_layout = g_layout.itemAt(i).widget().layout()
            comboBox = field_layout.itemAt(1).widget()
            edit = field_layout.itemAt(2).widget()

            type = Qt.from_qvariant(comboBox.itemData(comboBox.currentIndex()))
            expr = str(edit.text())
            f = getFilter(type, expr)
            filters.append(f)

        finalType = self.getHeaderType()
        filters.append(getFilter(finalType))
        return filters
Ejemplo n.º 30
0
 def setData(self, index, value=None, role=Qt.Qt.EditRole):
     if index.isValid() and (0 <= index.row() < self.rowCount()):
         row = index.row()
         curve = self.curves[row]
         if role == PROPS_ROLE:
             self.curves[row].properties = value
             self.dataChanged.emit(self.index(
                 row, 0), self.index(row, self.ncolumns - 1))
         else:
             column = index.column()
             value = Qt.from_qvariant(value, unicode)
             if column == X:
                 curve.x.setSrc(value)
             elif column == Y:
                 curve.y.setSrc(value)
             elif column == TITLE:
                 curve.title = value
             elif column == VIS:
                 curve.vis = value
             self.dataChanged.emit(index, index)
         return True
     return False
Ejemplo n.º 31
0
 def data(self, index, role=Qt.Qt.DisplayRole):
     if not index.isValid() or not (0 <= index.row() < self.rowCount()):
         return Qt.QVariant()
     row = index.row()
     column = index.column()
     # Display Role
     if role == Qt.Qt.DisplayRole:
         if column == X:
             return Qt.QVariant(str(self.curves[row].x.display))
         elif column == Y:
             return Qt.QVariant(str(self.curves[row].y.display))
         elif column == TITLE:
             return Qt.QVariant(str(self.curves[row].curveparam.label))
         else:
             return Qt.QVariant()
     elif role == Qt.Qt.DecorationRole:
         if column == X:
             return Qt.QVariant(self.curves[row].x.icon)
         elif column == Y:
             return Qt.QVariant(self.curves[row].y.icon)
         else:
             return Qt.QVariant()
     elif role == Qt.Qt.TextColorRole:
         if column == X:
             Qt.QVariant(
                 Qt.QColor(self.curves[row].x.ok and 'green' or 'red'))
         elif column == Y:
             Qt.QVariant(
                 Qt.QColor(self.curves[row].y.ok and 'green' or 'red'))
         else:
             return Qt.QVariant()
     elif role == SRC_ROLE:
         if column == X:
             return Qt.QVariant(str(self.curves[row].taurusparam.xModel))
         elif column == Y:
             return Qt.QVariant(str(self.curves[row].taurusparam.yModel))
         else:
             return Qt.QVariant()
     elif role == Qt.Qt.ToolTipRole:
         if column == X:
             return Qt.QVariant(str(self.curves[row].taurusparam.xModel))
         elif column == Y:
             return Qt.QVariant(str(self.curves[row].taurusparam.yModel))
         else:
             return Qt.QVariant()
     if role == Qt.Qt.EditRole:
         if column == X:
             return Qt.QVariant(str(self.curves[row].taurusparam.xModel))
         elif column == Y:
             return Qt.QVariant(str(self.curves[row].taurusparam.yModel))
         elif column == TITLE:
             return Qt.QVariant(str(self.curves[row].curveparam.label))
         else:
             return Qt.QVariant()
     return Qt.QVariant()
Ejemplo n.º 32
0
        Qt.QWidget.__init__(self, parent)
        self.loadUi()
        self.ui.comboBox_begin.addItem(str2localtime("-1d"))
        self.ui.comboBox_end.addItem(str2localtime(time.time()))

    def getTimes(self):
        t0 = str2localtime(self.ui.comboBox_begin.currentText())
        t1s = self.ui.comboBox_end.currentText()
        # if not absolute time
        if self._ts_re.match(t1s) is None:
            t1s = t1s.replace('now', '{}'.format(time.time() - str2time(t0)))
            t1s = str2time(t0) + str2time(t1s)
        t1 = str2localtime(t1s)
        return t0, t1


if __name__ == '__main__':

    from taurus.qt.qtgui.application import TaurusApplication
    import sys
    app = TaurusApplication()
    button = Qt.QPushButton("Press me")
    w = TangoArchivingTimeSelector()
    def p_getTimes():
        print(w.getTimes())
    button.pressed.connect(p_getTimes)
    w.ui.horizontalLayout.addWidget(button)
    w.show()
    
    sys.exit(app.exec_())
Ejemplo n.º 33
0
class TaurusGrid(QtGui.QFrame, TaurusBaseWidget):
    """ TaurusGrid is a Taurus widget designed to represent a set of attributes distributed in columns and rows.
    The Model will be a list with attributes or device names (for devices the State attribute will be shown).
    Each setModel(*) execution will be able to modify the attribute list.
    An example of execution:<pre>
    /usr/bin/python taurusgrid.py "model=lt.*/VC.*/.*/((C*)|(P*)|(I*))" cols=IP,CCG,PNV rows=LT01,LT02
    </pre>
    @author originally developed by gcuni, extended by srubio and sblanch
    @todo Future releases should allow a list of filters as argument
    @todo names/widgets should be accessible as a caselessdict dictionary (e.g. for adding custom context menus)
    @todo refactoring to have methods that add/remove new widgets one by one, not only the whole dictionary
    @todo _TAGS property should allow to change row/columns meaning and also add new Custom tags based on regexp
    """

    # -------------------------------------------------------------------------
    # Write your own code here to define the signals generated by this widget
    #

    itemSelected = Qt.pyqtSignal('QString')
    itemClicked = Qt.pyqtSignal('QString')

    _TAGS = ['DOMAIN', 'FAMILY', 'HOST',
             'LEVEL', 'CLASS', 'ATTRIBUTE', 'DEVICE']

    class _TaurusGridCell(Qt.QFrame):

        itemClicked = Qt.pyqtSignal('QString')

        # Done in this way as TaurusValue.mousePressEvent is never called
        def mousePressEvent(self, event):
            # print 'In cell clicked'
            targets = set(str(child.getModelName())
                          for child in self.children()
                          if hasattr(child, 'underMouse')
                          and child.underMouse()
                          and hasattr(child, 'getModelName')
                          )
            for t in targets:
                self.itemClicked.emit(t)

    def __init__(self, parent=None, designMode=False):
        name = self.__class__.__name__

        self.call__init__wo_kw(QtGui.QFrame, parent)
        # self.call__init__(TaurusBaseWidget, name, parent,
        #                   designMode=designMode)
        # It was needed to avoid exceptions in TaurusDesigner!
        if isinstance(parent, TaurusBaseWidget):
            self.call__init__(TaurusBaseWidget, name,
                              parent, designMode=designMode)
        else:
            self.call__init__(TaurusBaseWidget, name, designMode=designMode)

        self.title = ''
        self.showLabels = True
        self.filter = ''
        self._modelNames = []
        self.row_labels = []
        self.column_labels = []
        self._widgets_list = []
        self._last_selected = None
        self._show_frames = True
        self._show_row_frame = True
        self._show_column_frame = True
        self._show_others = False
        self._show_attr_labels = True
        self._show_attr_units = True
        self.hideLabels = False

        self.defineStyle()
        self.modelsQueue = Queue()
        self.__modelsThread = None
        if not designMode:
            self.modelsThread

    @property
    def modelsThread(self):
        modelsThread = self.__modelsThread
        if modelsThread is None:
            modelsThread = SingletonWorker(parent=self, name='TaurusGrid',
                                           queue=self.modelsQueue,
                                           method=modelSetter, cursor=True)
            self.__modelsThread = modelsThread
        return modelsThread

    def save(self, filename):
        import pickle
        d = {
            'model': self.filter,
            'row_labels': self.row_labels, 'column_labels': self.column_labels,
            'frames': self._show_row_frame or self._show_column_frame,
            'labels': self._show_attr_labels,
            'units': self._show_attr_units, 'others': self._show_others
        }
        f = open(filename, 'w')
        pickle.dump(d, f)
        f.close()

    def load(self, filename, delayed=False):
        self.trace('In TauGrid.load(%s,%s)' % (filename, delayed))
        if not isinstance(filename, dict):
            manual = False
            import pickle
            f = open(filename)
            d = pickle.load(f)
            f.close()
        else:
            manual = True
            d = filename
        self.setRowLabels(d['row_labels'])
        self.setColumnLabels(d['column_labels'])
        self.showAttributeLabels(d.get('labels', True))
        self.showAttributeUnits(d.get('units', True))
        self.showOthers(d.get('others', True))
        self.showRowFrame(d.get('frames', True))
        if manual:
            self.showColumnFrame(d.get('frames', True))
        self.setModel(d['model'], delayed=d.get('delayed', delayed))
        return self._modelNames

    def defineStyle(self):
        """ Defines the initial style for the widget """
        # ----------------------------------------------------------------------
        # Write your own code here to set the initial style of your widget
        #
        self.setLayout(QtGui.QGridLayout())
        # self.layout().setContentsMargins(0,0,0,0)
        self.updateStyle()

    def sizeHint(self):
        return QtGui.QFrame.sizeHint(self)

    def minimumSizeHint(self):
        return QtGui.QFrame.minimumSizeHint(self)

    # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
    # TaurusBaseWidget over writing
    # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-

    def getModelClass(self):
        # ----------------------------------------------------------------------
        # [MANDATORY]
        # Replace your own code here
        # ex.: return taurus.core.taurusattribute.Attribute
        raise RuntimeError("Forgot to overwrite %s.getModelClass" % str(self))
        return list

    def attach(self):
        """Attaches the widget to the model"""

        if self.isAttached():
            return True

        # ----------------------------------------------------------------------
        # Write your own code here before attaching widget to attribute connect
        # the proper signal so that the first event is correctly received by the
        # widget

        ret = TaurusBaseWidget.attach(self)

        # by default enable/disable widget according to attach state
        self.setEnabled(ret)
        return ret

    def detach(self):
        """Detaches the widget from the model"""

        TaurusBaseWidget.detach(self)

        # ----------------------------------------------------------------------
        # Write your own code here after detaching the widget from the model

        # by default disable widget when dettached
        self.setEnabled(False)

    # -------------------------------------------------------------------------
    # [MANDATORY]
    # Uncomment the following method if your superclass does not provide with a
    # isReadOnly() method or if you need to change its behavior

    # def isReadOnly(self):
    #    return True

    def updateStyle(self):
        # ----------------------------------------------------------------------
        # Write your own code here to update your widget style
        self.trace('@' * 80)
        self.trace(
            'In TaurusGrid.updateStyle() ....... It seems never called!!!!')
        self.trace('@' * 80)

        # It was showing an annoying "True" in the widget
        # value = self.getShowText() or ''
        # if self._setText: self._setText(value) ##It must be included

        # update tooltip
        self.setToolTip(self.getFormatedToolTip())  # It must be included

        # send a repaint in the end
        if hasattr(self, 'title_widget'):
            if self.title:
                self.title_widget.show()
            else:
                self.title_widget.hide()

        self.update()

    # -------------------------------------------------------------------------
    # Write your own code here for your own widget properties

    def setModel(self, model, devsInRows=False, delayed=False, append=False,
                 load=True):
        '''The model can be initialized as a list of devices or hosts or dictionary or ...'''
        # self.setModelCheck(model) ##It must be included
        # differenciate if the model is a RegExp
        if isinstance(model, dict):
            self.load(model)
        else:
            model = isinstance(model, string_types) and [model] or list(model)
            self.trace('#' * 80)
            self.trace('In TaurusGrid.setModel(%s)' % str(model)[:100])

            self.delayed = delayed
            self.filter = model
            if any('*' in m for m in model):
                model = get_all_models(model)
                self.debug(
                    'model was a RegExp, done the query and converted to an attr list')

            if not self._modelNames == []:  # clean to start from scratch
                for widget in self._widgets_list:
                    del widget

            # here we always have the reals model list, even if it comes from a
            # regexp
            if append:
                self._modelNames = self._modelNames + model
            else:
                self._modelNames = model

            self.debug(('In TaurusGrid.setModel(...): modelNames are %s' %
                        (self._modelNames))[:100] + '...')

            if load:
                self.trace(
                    'In TaurusGrid.setModel(%s,load=True): modelNames are %d' % (
                        str(model)[:100] + '...',
                        len(self._modelNames)))  # ,self._modelNames))
                if devsInRows:
                    self.setRowLabels(
                        ','.join(
                            set(d.rsplit('/', 1)[0] for d in self._modelNames)))
                self.create_widgets_table(self._modelNames)
                self.modelsQueue.put(
                    (MethodModel(self.showRowFrame), self._show_row_frame))
                self.modelsQueue.put(
                    (
                    MethodModel(self.showColumnFrame), self._show_column_frame))
                self.modelsQueue.put(
                    (MethodModel(self.showOthers), self._show_others))
                self.modelsQueue.put(
                    (MethodModel(self.showAttributeLabels),
                     self._show_attr_labels))
                self.modelsQueue.put(
                    (MethodModel(self.showAttributeUnits),
                     self._show_attr_units))
                self.updateStyle()

                if not self.delayed:
                    self.trace('In setModel(): not delayed loading of models')
                    if not self.modelsThread.isRunning():
                        # print 'In setModel(): Starting Thread! (%d objs in
                        # queue)'%(self.modelsThread.queue.qsize())
                        self.trace('<' * 80)
                        # self.modelsThread.IdlePriority)
                        self.modelsThread.start()
                    else:
                        # print 'In setModel(): Thread already started! (%d
                        # objs in queue)'%(self.modelsThread.queue.qsize())
                        self.modelsThread.next()
                else:
                    self.trace('In setModel(): models loading delayed!')
                    pass

            self.trace('Out of TaurusGrid.setModel(%s)' % str(model)[:100])
            self.updateStyle()
        return

    def getModel(self):
        return self._modelNames

    def resetModel(self):
        self._modelNames = []
        self.updateFromList(self._modelNames)
        return

    def setTitle(self, title):
        self.title = str(title)
        if hasattr(self, 'title_widget'):
            if title:
                self.title_widget.setText(self.title)
                self.title_widget.show()
            else:
                self.title_widget.hide()

    def parse_labels(self, text):
        if any(text.startswith(c[0]) and text.endswith(c[1]) for c in
               [('{', '}'), ('(', ')'), ('[', ']')]):
            try:
                labels = eval(text)
                return labels
            except Exception as e:
                self.warning(
                    'ERROR! Unable to parse labels property: %s' % str(e))
                return []
        else:
            exprs = [t.strip() for t in text.split(',')]
            labels = [(':' in e and (e.split(':', 1)[0].strip(), e.split(
                ':', 1)[-1].strip()) or (e, e)) for e in exprs]
            return labels

    def setRowLabels(self, rows):
        '''The model can be initialized as a list of devices or hosts or ...'''
        # self.setModelCheck(model) ##It must be included
        self.row_labels = self.parse_labels(str(rows))
        try:
            self.rows = [r[0] for r in self.row_labels]
            for i in range(len(self.rows)):
                section = self.rows[i]
                self.table.setVerticalHeaderItem(
                    i, QtGui.QTableWidgetItem(section))
        except Exception as e:
            self.debug("setRowLabels(): Exception! %s" % e)
            # self.create_widgets_table(self._columnsNames)

    def getRowLabels(self):
        return ','.join(':'.join(c) for c in self.row_labels)

    def resetRowLabels(self):
        self.row_labels = []
        return

    def setColumnLabels(self, columns):
        '''The model can be initialized as a list of devices or hosts or ...'''
        # self.setModelCheck(model) ##It must be included
        self.column_labels = self.parse_labels(str(columns))
        try:
            self.columns = [c[0] for c in self.column_labels]
            for i in range(len(self.columns)):
                equipment = self.columns[i]
                self.table.setHorizontalHeaderItem(
                    i, QtGui.QTableWidgetItem(equipment))
        except Exception as e:
            self.debug("setColumnLabels(): Exception! %s" % e)
            # self.create_widgets_table(self._columnsNames)

    def getColumnLabels(self):
        return ','.join(':'.join(c) for c in self.column_labels)

    def resetColumnLabels(self):
        self.column_labels = []
        return

    # FIXME: when they are called before setModel they fails because
    # frames are not yet created, and it doesn't has memoty about this.
    def showRowFrame(self, boolean):
        self._show_row_frame = boolean
        if hasattr(self, 'rows_frame'):
            if boolean:
                self.rows_frame.show()
            else:
                self.rows_frame.hide()

    def showColumnFrame(self, boolean):
        self._show_column_frame = boolean
        if hasattr(self, 'columns_frame'):
            if boolean:
                self.columns_frame.show()
            else:
                self.columns_frame.hide()

    def showAttributeLabels(self, boolean):
        self.trace('In showAttributeLabels(%s)' % boolean)
        self._show_attr_labels = boolean
        for tv in self._widgets_list:
            try:
                if tv and tv.labelWidget:
                    if boolean:
                        tv.labelWidget().show()
                    else:
                        tv.labelWidget().hide()
            except:
                pass
        return self._show_attr_labels

    def showAttributeUnits(self, boolean):
        self.trace('In showAttributeUnits(%s)' % boolean)
        self._show_attr_units = boolean
        for tv in self._widgets_list:
            try:
                if tv and tv.unitsWidget:
                    if boolean:
                        tv.unitsWidget().show()
                    else:
                        tv.unitsWidget().hide()
            except:
                pass
        return self._show_attr_units

    # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
    # QT properties
    # -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-

    model = QtCore.pyqtProperty("QStringList", getModel,
                                setModel,
                                resetModel)

    rowlabels = QtCore.pyqtProperty("QString", getRowLabels,
                                    setRowLabels,
                                    resetRowLabels)

    columnlabels = QtCore.pyqtProperty("QString", getColumnLabels,
                                       setColumnLabels,
                                       resetColumnLabels)

    useParentModel = QtCore.pyqtProperty("bool",
                                         TaurusBaseWidget.getUseParentModel,
                                         TaurusBaseWidget.setUseParentModel,
                                         TaurusBaseWidget.resetUseParentModel)

    # -------------------------------------------------------------------------
    # Write your own code here for your own widget properties

    def create_widgets_dict(self, models):
        from collections import defaultdict
        # recursive dictionary with 2 levels
        values = defaultdict(lambda: defaultdict(list))
        # domains = list(set(m.split('/')[0].upper()))
        # families = list(set(m.split('/')[1].upper()))

        if not self.row_labels:  # Domains used by default
            self.row_labels = sorted(
                list(set(m.split('/')[0].upper() for m in models if
                         m.count('/') >= 2)))
            self.row_labels = list(zip(self.row_labels, self.row_labels))
        if not self.column_labels:  # Families used by default
            self.column_labels = sorted(
                list(set(m.split('/')[1].upper() for m in models if
                         m.count('/') >= 2)))
            self.column_labels = list(zip(self.column_labels, self.column_labels))

            # for m in models:
            # if m.count('/')<2:
            # self.warning('Wrong model cannot be added: %s'%m)
            # else:
            # domain,family = m.upper().split('/')[:2]
            # values[domain][family].append(m)

        row_not_found, col_not_found = False, False

        for m in models:
            row, column = 'Others', 'Others'
            for label, rexp in self.row_labels:
                if '*' in rexp and '.*' not in rexp:
                    rexp = rexp.replace('*', '.*')
                if re_search_low(rexp, m):
                    row = label
                    break
            for label, rexp in self.column_labels:
                if '*' in rexp and '.*' not in rexp:
                    rexp = rexp.replace('*', '.*')
                if re_search_low(rexp, m):
                    column = label
                    break
            if 'Others' == row:
                row_not_found = True
            if 'Others' == column:
                col_not_found = True
            self.debug('Model %s added to row %s , column %s' %
                       (m, row, column))
            values[row][column].append(m)
        if row_not_found:
            self.row_labels.append(('Others', '.*'))
        if col_not_found:
            self.column_labels.append(('Others', '.*'))

        return values

    def create_frame_with_gridlayout(self):
        """ Just a 'macro' to create the layouts that seem to fit better. """
        frame = TaurusGrid._TaurusGridCell()
        frame.setLayout(QtGui.QGridLayout())
        frame.layout().setContentsMargins(2, 2, 2, 2)
        frame.layout().setSpacing(0)
        frame.layout().setSpacing(0)
        return frame

    def create_widgets_table(self, models):

        # Added a title to the panel
        self.title_widget = QtGui.QLabel()
        self.layout().addWidget(self.title_widget, 0, 0)
        self.setTitle(self.title)

        dct = self.create_widgets_dict(models)
        # Assignments modified to keep the order of labels as inserted in
        # properties
        self.rows = [r[0] for r in self.row_labels]  # dct.keys()
        # list(set(reduce(operator.add,v.keys()) for v in dct.values()))
        self.columns = [c[0] for c in self.column_labels]

        values = []
        for row in self.rows:
            line = []
            for col in self.columns:
                # line.append(dct[row][col] if col in dct[row] else [])
                if col in dct[row]:
                    line.append(dct[row][col])
                else:
                    line.append([])
            values.append(line)

        # Here is where the table is created!
        self.table = self.build_table(values)

        # SET COLUMN HEADERS (self.columns)
        for i in range(len(self.columns)):
            equipment = self.columns[i]
            self.table.setHorizontalHeaderItem(
                i, QtGui.QTableWidgetItem(equipment))
            # SOMEDAY THIS WILL BE ICONS

        # SET ROW HEADERS (self.rows)
        for i in range(len(self.rows)):
            section = self.rows[i]
            self.table.setVerticalHeaderItem(
                i, QtGui.QTableWidgetItem(section))

        #        table.setAutoScroll(True)
        #        resize_mode = QtGui.QHeaderView.Stretch
        #        table.horizontalHeader().setSectionResizeMode(resize_mode)
        # table.verticalHeader().setSectionResizeMode(resize_mode)

        #        for row in range(len(self.rows)):
        #            table.setRowHeight(row,5+25*sum(len(dct[self.rows[row]][col]) for col in self.columns))
        # for col in range(len(self.columns)):
        #    table.setColumnWidth(col,300)

        use_scroll = False  # It didn't work ... it doesn't allow the table widget to resize
        if use_scroll:
            scrollable = QtGui.QScrollArea(self)
            scrollable.setWidget(self.table)
            self.layout().addWidget(scrollable, 1, 0)
        else:
            self.layout().addWidget(self.table, 1, 0)

        # ----------------------------------------------------------------------
        # SECTION CHECKBOXES
        self.checkboxes_frame = self.create_frame_with_gridlayout()

        self.rows_frame = self.create_frame_with_gridlayout()
        self.rows_frame.setFrameStyle(QtGui.QFrame.Box)
        if not self._show_row_frame:
            self.rows_frame.hide()
        self.checkboxes_frame.layout().addWidget(self.rows_frame, 0, 0)

        self.columns_frame = self.create_frame_with_gridlayout()
        self.columns_frame.setFrameStyle(QtGui.QFrame.Box)
        if not self._show_column_frame:
            self.columns_frame.hide()
        self.checkboxes_frame.layout().addWidget(self.columns_frame, 0, 1)

        layout_row = 0
        layout_col = 0
        # For all rows, create rows of three checkboxes in order to
        # show or hide the corresponding rows in the table
        for i in range(len(self.rows)):
            section = self.rows[i]
            checkbox = QtGui.QCheckBox(section)

            # -------------------------------------------------------
            # Work around for https://bugs.kde.org/show_bug.cgi?id=345023
            # TODO: make better solution for this
            checkbox._id = section  # <-- ugly monkey-patch!
            # -------------------------------------------------------

            if section == 'Others':
                checkbox.setChecked(False)
                if not self._show_others:
                    checkbox.hide()
            else:
                checkbox.setChecked(True)
            self.rows_frame.layout().addWidget(checkbox, layout_row, layout_col)
            layout_col += 1
            if layout_col == 3:
                layout_col = 0
                layout_row += 1
            checkbox.toggled.connect(self.show_hide_rows)
        self.show_hide_rows()

        layout_row = 0
        layout_col = 0
        # For all self.columns, create rows of three checkboxes in order to
        # show or hide the corresponding columns in the table
        for i in range(len(self.columns)):
            column = self.columns[i]
            checkbox = QtGui.QCheckBox(column)

            # -------------------------------------------------------
            # Work around for https://bugs.kde.org/show_bug.cgi?id=345023
            # TODO: make better solution for this
            checkbox._id = column  # <-- ugly monkey-patch!
            # -------------------------------------------------------

            if column == 'Others':
                checkbox.setChecked(False)
                if not self._show_others:
                    checkbox.hide()
            else:
                checkbox.setChecked(True)
            self.columns_frame.layout().addWidget(checkbox, layout_row,
                                                  layout_col)
            layout_col += 1
            if layout_col == 3:
                layout_col = 0
                layout_row += 1
            checkbox.toggled.connect(self.show_hide_columns)
        self.show_hide_columns()

        self.layout().addWidget(self.checkboxes_frame, 2, 0)
        # self.resize(800,600)

    def show_hide_rows(self):
        """
        This needs refactoring to be together with the show_hide_columns method
        """
        for checkbox in self.rows_frame.children():
            if isinstance(checkbox, QtGui.QCheckBox):
                # -------------------------------------------------------
                # Work around for https://bugs.kde.org/show_bug.cgi?id=345023
                # TODO: make better solution for this
                # checkbox.text()  <-- fails due to added "&
                table_row = self.rows.index(checkbox._id)
                # -------------------------------------------------------
                if checkbox.isChecked():
                    self.table.showRow(table_row)
                else:
                    self.table.hideRow(table_row)

    def show_hide_columns(self):
        """
        This needs refactoring to be together with the show_hide_rows method
        """
        for checkbox in self.columns_frame.children():
            if isinstance(checkbox, QtGui.QCheckBox):
                # -------------------------------------------------------
                # Work around for https://bugs.kde.org/show_bug.cgi?id=345023
                # TODO: make better solution for this
                # checkbox.text()  <-- fails due to added "&
                table_col = self.columns.index(checkbox._id)
                # -------------------------------------------------------
                if checkbox.isChecked():
                    self.table.showColumn(table_col)
                else:
                    self.table.hideColumn(table_col)

    def showOthers(self, boolean):
        self._show_others = boolean
        if hasattr(self, 'rows_frame'):
            for checkbox in self.rows_frame.children():
                if (isinstance(checkbox, QtGui.QCheckBox)
                # -------------------------------------------------------
                # Work around for https://bugs.kde.org/show_bug.cgi?id=345023
                # TODO: make better solution for this
                # checkbox.text()  <-- fails due to added "&
                        and checkbox._id == 'Others'):
                # -------------------------------------------------------
                    if self._show_others:
                        checkbox.show()
                    else:
                        checkbox.hide()
        if hasattr(self, 'columns_frame'):
            for checkbox in self.columns_frame.children():
                if (isinstance(checkbox, QtGui.QCheckBox)
                # -------------------------------------------------------
                # Work around for https://bugs.kde.org/show_bug.cgi?id=345023
                # TODO: make better solution for this
                # checkbox.text()  <-- fails due to added "&
                        and checkbox._id == 'Others'):
                # -------------------------------------------------------
                    if self._show_others:
                        checkbox.show()
                    else:
                        checkbox.hide()

    def build_table(self, values):
        """
        This is a builder. For all the elements in widgets matrix,
        just set the corresponding cells of the QTableWidget.
        """
        self.trace('In TaurusGrid.build_table(%s)' % values)
        widgets_matrix = self.build_widgets(values, self.showLabels)
        rows = len(widgets_matrix)
        cols = rows and len(widgets_matrix[0]) or 0

        table = QtGui.QTableWidget()
        table.setItemDelegate(Delegate(table))
        # This example replaces the blue background of selected cells in tables
        palette = Qt.QPalette()
        palette.setBrush(palette.Active, palette.Highlight,
                         Qt.QBrush(Qt.Qt.white))
        table.setPalette(palette)

        table.setRowCount(rows)
        table.setColumnCount(cols)
        for row in range(len(widgets_matrix)):
            for col in range(len(widgets_matrix[row])):
                table.setCellWidget(row, col, widgets_matrix[row][col])

        # table.resizeColumnsToContents()
        # table.resizeRowsToContents()
        hh = table.horizontalHeader()
        if hh.length() > 0:
            try:
                hh.setSectionResizeMode(hh.Stretch)
            except AttributeError:  # PyQt4
                hh.setResizeMode(hh.Stretch)
        # table.verticalHeader().setSectionResizeMode(QtGui.QHeaderView.Stretch)
        # table.horizontalHeader().setSectionResizeMode(QtGui.QHeaderView.ResizeToContents)
        vh = table.verticalHeader()
        if vh.length() > 0:
            try:
                vh.setSectionResizeMode(vh.ResizeToContents)
            except AttributeError:  # PyQt4
                hh.setResizeMode(vh.ResizeToContents)

        return table

    def build_widgets(self, values, show_labels=False, width=240, height=20,
                      value_width=120):
        widgets_matrix = []
        for row in values:
            widgets_row = []
            for cell in row:
                cell_frame = self.create_frame_with_gridlayout()
                cell_frame.itemClicked.connect(self.onItemClicked)
                count = 0
                for synoptic in sorted(cell):
                    self.debug("processing synoptic %s" % synoptic)
                    name = model = synoptic

                    self.debug('Creating TaurusValue with model =  %s' % model)
                    synoptic_value = TaurusValue(cell_frame)
                    self.modelsQueue.put((synoptic_value, model))

                    if self.hideLabels:
                        synoptic_value.setLabelWidgetClass(None)
                    else:
                        # DO NOT DELETE THIS LINE!!!
                        synoptic_value.setLabelConfig('label')
                    cell_frame.layout().addWidget(synoptic_value, count, 0)
                    self._widgets_list.append(synoptic_value)
                    count += 1

                widgets_row.append(cell_frame)
            widgets_matrix.append(widgets_row)
        return widgets_matrix

    def onItemClicked(self, item_name):
        self.trace('In TaurusGrid.itemClicked(%s)' % item_name)
        self.setItemSelected(item_name)
        self.itemClicked.emit(str(item_name))

    def setItemSelected(self, item_name='', selected=True):
        """ it adds a blue frame around a clicked item. """
        if isinstance(item_name, TaurusValue):
            self.trace('In TaurusGrid.setItemSelected(%s,%s)' %
                       (str(item_name.getModel()), selected))
            item = item_name
        else:
            self.trace('In TaurusGrid.setItemSelected(%s,%s)' %
                       (str(item_name), selected))
            if item_name:
                item = self.getItemByModel(item_name)
            else:
                item = self._last_selected
        if item:
            if selected:
                item._labelWidget.setStyleSheet(
                    'border-style: solid ; border-width: 1px; border-color: blue; color: blue; border-radius:4px;')
                if self._last_selected and self._last_selected != item:
                    self.setItemSelected(self._last_selected, False)
                self._last_selected = item
            else:
                item._labelWidget.setStyleSheet(
                    'border-style: solid; border-width: 1px; border-color: transparent; color: black;  border-radius:4px;')
                self._last_selected = None
        else:
            return None

    def getItemByModel(self, model, index=0):
        # a particular model can be many times, index means which one of them
        model = str(model).lower()
        for widget in self._widgets_list:
            if str(widget.getModel()).lower() == model:
                if index <= 0:
                    return widget
                else:
                    index -= 1

    @classmethod
    def getQtDesignerPluginInfo(cls):
        ret = TaurusBaseWidget.getQtDesignerPluginInfo()
        ret['module'] = 'taurus.qt.qtgui.table'
        ret['group'] = 'Taurus Views'
        ret['icon'] = "designer:grid.png"
        return ret
Ejemplo n.º 34
0
    def validateAllExpresion(self, secValidation=False):
        # This method is responsible for full validation of the macro. It is executed whenever the text is changed (when user edits values).
        # Validation starts with checking if the macro (name) is valid.
        # Next steps:
        # 1. Validates every SingleParamNode and counts how many there are in the macro.
        # 2. If there are more SingleParamNodes than entered values it will check if there is RepeatParamNode.
        #   If there is RepeatParamNode it will check if its RepeatNodes can be deleted.
        # 3. If there are more values entered than SingleParamNodes in macro it will check if there is RepeatParamNode.
        #   If there is it will try to add new RepeatNode.

        if self.model() is None:
            raise RuntimeError(
                'Door must be set in order to use the macroexecutor.')

        self.currentIndex = Qt.QModelIndex()
        mlist = str(self.text()).split()
        problems = []
        try:
            if str(mlist[0]) != str(self.model().root().name()):
                try:
                    self.getModelObj().validateMacroName(str(mlist[0]))
                    self.validateMacro(mlist[0])
                    self.updateMacroEditor(mlist[0])
                    if not secValidation:
                        self.validateAllExpresion(True)

                except Exception as e:
                    if self.disableEditMode:
                        self.updateMacroEditor(mlist[0])
                        raise Exception(e)
                    message = e.args[0]
                    #raise Exception(e)
                    problems.append(message)

        except IndexError:
            problems.append("<b>Macro<\b> is missing!")
            self.setStyleSheet("")
            self.setToolTip('<br>'.join(problems))
            return
        self.currentIndex = Qt.QModelIndex()
        ix = self.getIndex()
        self.currentIndex = ix
        counter = 1

        while not ix == Qt.QModelIndex():
            try:
                propValue = mlist[counter]
                try:
                    self.validateOneValue(propValue)
                    self.model().setData(self.currentIndex, propValue)
                except Exception as e:
                    self.model().setData(self.currentIndex, 'None')
                    txt = str(ix.sibling(ix.row(), 0).data())
                    message = "<b>" + txt + "</b> " + e.args[0]
                    problems.append(message)
            except IndexError:
                txt = str(ix.sibling(ix.row(), 0).data())
                problems.append("<b>" + txt + "</b> is missing!")

                data = str(ix.data())
                if data != 'None':
                    self.model().setData(self.currentIndex, 'None')
                else:
                    self.model().setData(self.currentIndex, None)
            counter += 1
            ix = self.getIndex()
            self.currentIndex = ix

        if len(mlist) > counter:  # if there are more values than parameters
            repeatNode = None
            for i in self.model().root().params():
                repeatNode = i
                if isinstance(repeatNode, macro.RepeatParamNode):
                    index = self.findParamRepeat(i)
                    self.currentIndex = self.model()._insertRow(index)
                    nn = self.model().nodeFromIndex(self.currentIndex)
                    self.expandTree.emit()
                    ix = self.getIndex()
                    if not secValidation:
                        self.validateAllExpresion(True)
                        return

                repeatNode = None
            if repeatNode is None:
                problems.append("Too many values.")

        elif counter - len(mlist) >= 1:
            repeatNode = None
            node = None
            for i in self.model().root().params():
                repeatNode = i
                if isinstance(repeatNode, macro.RepeatParamNode):
                    index = self.findParamRepeat(i)
                    node = self.model().nodeFromIndex(index)
                    sub = len(node.child(0))
                    break
                repeatNode = None

            if repeatNode is not None:
                while counter - len(mlist) > sub - 1:
                    if len(node.children()) == 1 and node.isReachedMin():
                        break
                    self.model()._removeRow(index.child(len(node.children()) - 1, 0))
                    counter -= sub

                if not secValidation:
                    self.validateAllExpresion(True)
                    return

        if len(problems) == 0:
            self.setStyleSheet('SpockCommandWidget {background-color: %s; color: %s; border: %s; border-radius: %s}' % (
                'yellow', 'black', '3px solid green', '5px'))
            self.setToolTip("")
        else:
            self.setStyleSheet("")
            self.setToolTip('<br>'.join(problems))
        return
 def _colorIcon(self, color, w=10, h=10):
     # to do: create a border
     pixmap = Qt.QPixmap(w, h)
     pixmap.fill(Qt.QColor(color))
     return Qt.QIcon(pixmap)
Ejemplo n.º 36
0
class TaurusSequencerWidget(TaurusWidget):

    doorChanged = Qt.pyqtSignal('QString')
    macroStarted = Qt.pyqtSignal('QString')
    plotablesFilterChanged = Qt.pyqtSignal(compat.PY_OBJECT)
    currentMacroChanged = Qt.pyqtSignal(compat.PY_OBJECT)
    macroNameChanged = Qt.pyqtSignal('QString')
    shortMessageEmitted = Qt.pyqtSignal('QString')
    sequenceEmpty = Qt.pyqtSignal()

    comment_characters = ('#',)

    def __init__(self, parent=None, designMode=False):
        TaurusWidget.__init__(self, parent, designMode)
        # list representing all macros ids (all from sequence) currently
        # executed
        self._macroIds = []
        self._sequencesPath = str(Qt.QDir.homePath())
        self._sequenceModel = MacroSequenceTreeModel()

        self.registerConfigProperty(
            "sequencesPath", "setSequencesPath", "sequencesPath")

        self.setLayout(Qt.QVBoxLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)
        splitter = Qt.QSplitter()
        self.layout().addWidget(splitter)
        splitter.setOrientation(Qt.Qt.Vertical)

        self.sequenceEditor = TaurusWidget()
        splitter.addWidget(self.sequenceEditor)
        self.sequenceEditor.setLayout(Qt.QVBoxLayout())
        self.sequenceEditor.layout().setContentsMargins(0, 0, 0, 0)

        self.tree = MacroSequenceTree(self.sequenceEditor)
        self.sequenceProxyModel = MacroSequenceProxyModel()
        self.sequenceProxyModel.setSourceModel(self._sequenceModel)
        self.tree.setModel(self.sequenceProxyModel)
        self.tree.setItemDelegate(SequenceEditorDelegate(self.tree))

        actionsLayout = Qt.QHBoxLayout()
        actionsLayout.setContentsMargins(0, 0, 0, 0)
        self.newSequenceAction = Qt.QAction(
            Qt.QIcon.fromTheme("document-new"), "New", self)
        self.newSequenceAction.triggered.connect(self.onNewSequence)
        self.newSequenceAction.setToolTip("New sequence")
        self.newSequenceAction.setEnabled(False)
        newSequenceButton = Qt.QToolButton()
        newSequenceButton.setDefaultAction(self.newSequenceAction)
        actionsLayout.addWidget(newSequenceButton)

        self.openSequenceAction = Qt.QAction(
            Qt.QIcon.fromTheme("document-open"), "Open...", self)
        self.openSequenceAction.triggered.connect(self.onOpenSequence)
        self.openSequenceAction.setToolTip("Open sequence...")
        openSequenceButton = Qt.QToolButton()
        openSequenceButton.setDefaultAction(self.openSequenceAction)
        actionsLayout.addWidget(openSequenceButton)

        self.saveSequenceAction = Qt.QAction(
            Qt.QIcon.fromTheme("document-save"), "Save...", self)
        self.saveSequenceAction.triggered.connect(self.onSaveSequence)
        self.saveSequenceAction.setToolTip("Save sequence...")
        self.saveSequenceAction.setEnabled(False)
        saveSequenceButton = Qt.QToolButton()
        saveSequenceButton.setDefaultAction(self.saveSequenceAction)
        actionsLayout.addWidget(saveSequenceButton)

        self.stopSequenceAction = Qt.QAction(
            Qt.QIcon("actions:media_playback_stop.svg"), "Stop", self)
        self.stopSequenceAction.triggered.connect(self.onStopSequence)
        self.stopSequenceAction.setToolTip("Stop sequence")
        stopSequenceButton = Qt.QToolButton()
        stopSequenceButton.setDefaultAction(self.stopSequenceAction)
        actionsLayout.addWidget(stopSequenceButton)

        self.pauseSequenceAction = Qt.QAction(
            Qt.QIcon("actions:media_playback_pause.svg"), "Pause", self)
        self.pauseSequenceAction.triggered.connect(self.onPauseSequence)
        self.pauseSequenceAction.setToolTip("Pause sequence")
        pauseSequenceButton = Qt.QToolButton()
        pauseSequenceButton.setDefaultAction(self.pauseSequenceAction)
        actionsLayout.addWidget(pauseSequenceButton)

        self.playSequenceAction = Qt.QAction(
            Qt.QIcon("actions:media_playback_start.svg"), "Play", self)
        self.playSequenceAction.triggered.connect(self.onPlaySequence)
        self.playSequenceAction.setToolTip("Play sequence")
        playSequenceButton = Qt.QToolButton()
        playSequenceButton.setDefaultAction(self.playSequenceAction)
        actionsLayout.addWidget(playSequenceButton)

        self.doorStateLed = TaurusLed(self)
        actionsLayout.addWidget(self.doorStateLed)

        #@todo this feature will be replaced by checkboxes in the
        # sequence tree view indicating clearing of the plot after execution
        self.fullSequencePlotCheckBox = Qt.QCheckBox(
            "Full sequence plot", self)
        self.fullSequencePlotCheckBox.toggled.connect(self.setFullSequencePlot)
        self.fullSequencePlotCheckBox.setChecked(True)
        actionsLayout.addWidget(self.fullSequencePlotCheckBox)

        spacerItem = Qt.QSpacerItem(
            0, 0, Qt.QSizePolicy.Expanding, Qt.QSizePolicy.Fixed)
        actionsLayout.addItem(spacerItem)

        self.sequenceEditor.layout().addLayout(actionsLayout)

        macroLayout = Qt.QHBoxLayout()
        macroLayout.setContentsMargins(0, 0, 0, 0)
        macroLabel = Qt.QLabel("Macro:")
        macroLayout.addWidget(macroLabel)
        self.macroComboBox = MacroComboBox(self)
        self.macroComboBox.setModelColumn(0)
        self.macroComboBox.setSizePolicy(
            Qt.QSizePolicy.Expanding, Qt.QSizePolicy.Minimum)
        macroLayout.addWidget(self.macroComboBox)

        self.addMacroAction = Qt.QAction(
            Qt.QIcon.fromTheme("list-add"), "Add macro...", self)
        self.addMacroAction.triggered.connect(self.onAdd)
        self.addMacroAction.setToolTip(
            "Clicking this button will add selected macro")
        self.addMacroAction.setEnabled(False)
        addButton = Qt.QToolButton()
        addButton.setDefaultAction(self.addMacroAction)
        macroLayout.addWidget(addButton)

        self.sequenceEditor.layout().addLayout(macroLayout)

        sequenceLayout = Qt.QHBoxLayout()
        sequenceLayout.addWidget(self.tree)

        layout = Qt.QVBoxLayout()
        delButton = Qt.QToolButton()
        delButton.setDefaultAction(self.tree.deleteAction)
        delButton.setEnabled(False)
        layout.addWidget(delButton)
        upButton = Qt.QToolButton()
        upButton.setDefaultAction(self.tree.moveUpAction)
        upButton.setEnabled(False)
        layout.addWidget(upButton)
        downButton = Qt.QToolButton()
        downButton.setDefaultAction(self.tree.moveDownAction)
        downButton.setEnabled(False)
        layout.addWidget(downButton)
        leftButton = Qt.QToolButton()
        leftButton.setDefaultAction(self.tree.moveLeftAction)
        leftButton.setEnabled(False)
        layout.addWidget(leftButton)
        rightButton = Qt.QToolButton()
        rightButton.setDefaultAction(self.tree.moveRightAction)
        rightButton.setEnabled(False)
        layout.addWidget(rightButton)
        spacerItem = Qt.QSpacerItem(
            0, 40, Qt.QSizePolicy.Fixed, Qt.QSizePolicy.Expanding)
        layout.addItem(spacerItem)
        sequenceLayout.addLayout(layout)
        self.sequenceEditor.layout().addLayout(sequenceLayout)

        self.parametersProxyModel = MacroParametersProxyModel()
        self.parametersProxyModel.setSourceModel(self._sequenceModel)

        self.stackedWidget = Qt.QStackedWidget()
        splitter.addWidget(self.stackedWidget)
        self.standardMacroParametersEditor = StandardMacroParametersEditor(
            self.stackedWidget)
        self.standardMacroParametersEditor.setModel(self.parametersProxyModel)
        self.standardMacroParametersEditor.tree.setItemDelegate(
            ParamEditorDelegate(self.standardMacroParametersEditor.tree))
        self.stackedWidget.addWidget(self.standardMacroParametersEditor)
        self.customMacroParametersEditor = None

        self.macroComboBox.currentIndexChanged.connect(
            self.onMacroComboBoxChanged)
        self.tree.macroChanged.connect(self.setMacroParametersRootIndex)

    def contextMenuEvent(self, event):
        menu = Qt.QMenu()
        menu.addAction(Qt.QIcon.fromTheme("view-refresh"), "Check door state",
                       self.checkDoorState)
        menu.exec_(event.globalPos())

    def checkDoorState(self):
        """Method used by "Check door state" action (available in the context
        menu). It is a workaround for situations when the event notification
        about the macro status does not reach the sequencer widget."""

        door = Device(self.doorName())
        doorState = door.getState()
        if doorState == PyTango.DevState.RUNNING:
            self.playSequenceAction.setEnabled(False)
            self.pauseSequenceAction.setEnabled(True)
            self.stopSequenceAction.setEnabled(True)
        elif doorState in (PyTango.DevState.ON, PyTango.DevState.ALARM):
            self.playSequenceAction.setEnabled(True)
            self.pauseSequenceAction.setEnabled(False)
            self.stopSequenceAction.setEnabled(False)
        elif doorState == PyTango.DevState.STANDBY:
            self.playSequenceAction.setEnabled(True)
            self.pauseSequenceAction.setEnabled(False)
            self.stopSequenceAction.setEnabled(True)

    def doorName(self):
        return self._doorName

    def setDoorName(self, doorName):
        self._doorName = doorName

    def firstMacroId(self):
        return self._firstMacroId

    def setFirstMacroId(self, firstMacroId):
        self._firstMacroId = firstMacroId

    def lastMacroId(self):
        return self._lastMacroId

    def setLastMacroId(self, lastMacroId):
        self._lastMacroId = lastMacroId

    def macroIds(self):
        return self._macroIds

    def setMacroIds(self, macroIds):
        self._macroIds = macroIds

    def emitExecutionStarted(self):
        return self._emitExecutionStarted

    def setEmitExecutionStarted(self, yesNo):
        self._emitExecutionStarted = yesNo

    def sequencesPath(self):
        return self._sequencesPath

    def setSequencesPath(self, sequencesPath):
        self._sequencesPath = sequencesPath

    def isFullSequencePlot(self):
        return self._fullSequencePlot

    def setFullSequencePlot(self, fullSequencePlot):
        self._fullSequencePlot = fullSequencePlot

    def onNewSequence(self):
        if Qt.QMessageBox.question(self,
                                   "New sequence",
                                   "Do you want to save existing sequence?",
                                   Qt.QMessageBox.Yes,
                                   Qt.QMessageBox.No) == Qt.QMessageBox.Yes:
            self.onSaveSequence()
        self.tree.clearTree()
        self.newSequenceAction.setEnabled(False)
        self.saveSequenceAction.setEnabled(False)
        self.currentMacroChanged.emit(None)

    def loadFile(self, fileName):
        if fileName == "":
            return
        #@todo: reset macroComboBox to index 0
        try:
            file = open(fileName, 'r')
            string = file.read()
            if fileName.endswith('.xml'):
                root = self.fromXmlString(string)
            else:
                root = self.fromPlainText(string)
            self._sequenceModel.setRoot(root)
            self.sequenceProxyModel.invalidateFilter()
            self.tree.expandAll()
            self.tree.expanded()
            self.parametersProxyModel.setMacroIndex(None)
            self.parametersProxyModel.invalidateFilter()

            if not self._sequenceModel.isEmpty():
                self.newSequenceAction.setEnabled(True)
                self.saveSequenceAction.setEnabled(True)
                self.playSequenceAction.setEnabled(True)
        except IOError:
            Qt.QMessageBox.warning(
                self,
                "Error while loading macros sequence",
                "There was a problem while reading from file: %s" % fileName)
            file = None
            self.tree.clearTree()
            self.newSequenceAction.setEnabled(False)
            self.saveSequenceAction.setEnabled(False)
        except:
            self.tree.clearTree()
            self.playSequenceAction.setEnabled(False)
            self.newSequenceAction.setEnabled(False)
            self.saveSequenceAction.setEnabled(False)
            raise
        finally:
            if not file is None:
                file.close()
            self.setSequencesPath(str.join("/", fileName.rsplit("/")[:-1]))

        self.currentMacroChanged.emit(None)

    def onOpenSequence(self):
        if not self._sequenceModel.isEmpty():
            if Qt.QMessageBox.question(
                    self,
                    "Open sequence",
                    "Do you want to save existing sequence?",
                    Qt.QMessageBox.Yes,
                    Qt.QMessageBox.No) == Qt.QMessageBox.Yes:
                self.onSaveSequence()
                self.tree.clearTree()

        sequencesPath = self.sequencesPath()
        fileName, _ = compat.getOpenFileName(
            self,
            "Choose a sequence to open...",
            sequencesPath,
            "*")
        self.loadFile(fileName)


    def onSaveSequence(self):
        sequencesPath = self.sequencesPath()
        if sequencesPath == "":
            sequencesPath = str(Qt.QDir.homePath())

        sequencesPath = os.path.join(sequencesPath, "Untitled.xml")
        fileName, _ = compat.getSaveFileName(
            self,
            "Choose a sequence file name...",
            sequencesPath,
            "*.xml")
        if fileName == "":
            return
        try:
            file = open(fileName, "w")
            file.write(self.tree.toXmlString(pretty=True, withId=False))
            self.setSequencesPath(str.join("/", fileName.rsplit("/")[:-1]))
        except Exception as e:
            Qt.QMessageBox.warning(
                self,
                "Error while saving macros sequence",
                "There was a problem while writing to the file: %s" %
                fileName)
            print(e)
        finally:
            if not file is None:
                file.close()

    def onPlaySequence(self):
        door = Device(self.doorName())
        doorState = door.getState()
        if (doorState == PyTango.DevState.ON or
                doorState == PyTango.DevState.ALARM):
            first, last, ids = self.tree.prepareMacroIds()
            self.setFirstMacroId(first)
            self.setLastMacroId(last)
            self.setMacroIds(ids)
            self.tree.prepareMacroProgresses()
            self.setEmitExecutionStarted(True)
            door.runMacro(self.tree.toXmlString())
        elif doorState == PyTango.DevState.STANDBY:
            door.command_inout("ResumeMacro")
        else:
            Qt.QMessageBox.warning(
                self,
                "Error while starting/resuming sequence",
                "It was not possible to start/resume sequence, "
                "because state of the door was different than ON/STANDBY")

    def onStopSequence(self):
        door = Device(self.doorName())
        doorState = door.getState()
        if doorState in (PyTango.DevState.RUNNING, PyTango.DevState.STANDBY):
            door.command_inout("StopMacro")
        else:
            Qt.QMessageBox.warning(
                self,
                "Error while stopping sequence",
                "It was not possible to stop sequence, "
                "because state of the door was different than "
                "RUNNING or STANDBY")

    def onPauseSequence(self):
        door = Device(self.doorName())
        doorState = door.getState()
        if doorState == PyTango.DevState.RUNNING:
            door.command_inout("PauseMacro")
        else:
            Qt.QMessageBox.warning(
                self,
                "Error while pausing sequence",
                "It was not possible to pause sequence, "
                "because state of the door was different than RUNNING")

    def onMacroStatusUpdated(self, data):
        macro = data[0]
        if macro is None:
            return
        data = data[1][0]
        state, range, step, id = str(data["state"]), data[
            "range"], data["step"], data["id"]
        if id is None:
            return
        id = int(id)
        if not id in self.macroIds():
            return
        macroName = macro.name
        shortMessage = ""
        if state == "start":
            #@todo: Check this signal because it doesn't work,
            # emitExecutionStarted is not set!!!
            if self.emitExecutionStarted():
                self.macroStarted.emit("DoorOutput")
            self.tree.setRangeForMacro(id, range)
            self.playSequenceAction.setEnabled(False)
            self.pauseSequenceAction.setEnabled(True)
            self.stopSequenceAction.setEnabled(True)
            if id == self.firstMacroId():
                self.plotablesFilterChanged.emit(None)
                self.plotablesFilterChanged.emit(standardPlotablesFilter)
                shortMessage = "Sequence started."
            elif not self.isFullSequencePlot():
                self.plotablesFilterChanged.emit(None)
            shortMessage += " Macro %s started." % macroName
        elif state == "pause":
            self.playSequenceAction.setText("Resume sequence")
            self.playSequenceAction.setToolTip("Resume sequence")
            self.playSequenceAction.setEnabled(True)
            self.pauseSequenceAction.setEnabled(False)
            shortMessage = "Macro %s paused." % macroName
        elif state == "resume":
            self.playSequenceAction.setText("Start sequence")
            self.playSequenceAction.setToolTip("Start sequence")
            self.playSequenceAction.setEnabled(False)
            self.pauseSequenceAction.setEnabled(True)
            shortMessage = "Macro %s resumed." % macroName
        elif state == "stop" or state == "finish":
            shortMessage = "Macro %s finished." % macroName
            if id == self.lastMacroId():
                self.playSequenceAction.setEnabled(True)
                self.pauseSequenceAction.setEnabled(False)
                self.stopSequenceAction.setEnabled(False)
                shortMessage += " Sequence finished."
        elif state == 'exception':
            self.playSequenceAction.setEnabled(True)
            self.pauseSequenceAction.setEnabled(False)
            self.stopSequenceAction.setEnabled(False)
            shortMessage = "Macro %s error." % macroName
            exc_value, exc_stack = data['exc_value'], data['exc_stack']
            exceptionDialog = TaurusMessageBox(
                MacroRunException, exc_value, exc_stack)
            exceptionDialog.exec_()
        elif state == 'abort':
            self.playSequenceAction.setText("Start sequence")
            self.playSequenceAction.setToolTip("Start sequence")
            self.playSequenceAction.setEnabled(True)
            self.pauseSequenceAction.setEnabled(False)
            self.stopSequenceAction.setEnabled(False)
            shortMessage = "Macro %s stopped." % macroName
        elif state == "step":
            shortMessage = "Macro %s at %d %% of progress." % (macroName,
                                                               step)
        self.shortMessageEmitted.emit(shortMessage)
        self.tree.setProgressForMacro(id, step)

    def onDoorChanged(self, doorName):
        self.setDoorName(doorName)
        if self.doorName() == "":
            self.doorStateLed.setModel(None)
            return
        self.doorStateLed.setModel(self.doorName() + "/State")
        door = Device(doorName)
        doorState = door.stateObj.rvalue
        if doorState == PyTango.DevState.ON:
            self.playSequenceAction.setText("Start sequence")
            self.playSequenceAction.setToolTip("Start sequence")
            self.playSequenceAction.setEnabled(False)
            self.pauseSequenceAction.setEnabled(False)
            self.stopSequenceAction.setEnabled(False)
        elif doorState == PyTango.DevState.STANDBY:
            self.playSequenceAction.setText("Resume sequence")
            self.playSequenceAction.setToolTip("Resume sequence")
            self.playSequenceAction.setEnabled(True)
            self.pauseSequenceAction.setEnabled(False)
            self.stopSequenceAction.setEnabled(True)

    def setMacroParametersRootIndex(self, sourceIndex):
        parametersModel = self.standardMacroParametersEditor.tree.model()
        parametersModel.setMacroIndex(sourceIndex)
        parametersModel.invalidateFilter()
        proxyIndex = parametersModel.mapFromSource(sourceIndex)

        macroNode = sourceIndex.internalPointer()
        macroName = macroNode.name()

        if self.stackedWidget.count() == 2:
            self.stackedWidget.removeWidget(self.customMacroParametersEditor)
            self.customMacroParametersEditor.setParent(None)
        self.customMacroParametersEditor = \
            ParamEditorManager().getMacroEditor(macroName)
        if self.customMacroParametersEditor:
            self.customMacroParametersEditor.setModel(parametersModel)
            self.customMacroParametersEditor.setRootIndex(proxyIndex)
            self.stackedWidget.addWidget(self.customMacroParametersEditor)
            self.stackedWidget.setCurrentWidget(
                self.customMacroParametersEditor)
        else:
            self.standardMacroParametersEditor.tree.setRootIndex(proxyIndex)
            self.standardMacroParametersEditor.tree.expandAll()

    def onMacroComboBoxChanged(self):
        macroName = str(self.macroComboBox.currentText())
        if macroName == "":
            self.addMacroAction.setEnabled(False)
        else:
            self.addMacroAction.setEnabled(True)
        self.macroNameChanged.emit(macroName)

    def onAdd(self):
        macroName = str(self.macroComboBox.currentText())
        macroNode = self.getModelObj().getMacroNodeObj(macroName)
        self.tree.addMacro(macroNode)
        self.saveSequenceAction.setEnabled(True)
        self.playSequenceAction.setEnabled(True)

    def isEmptySequence(self):
        return len(self.tree.root()) == 0

    def isMacroSelected(self):
        return len(self.tree.selectedIndexes()) == 2

    def emptySequence(self):
        self.tree.clearTree()
        self.disableButtons()
        self.currentMacroChanged.emit(None)
        self.sequenceEmpty.emit()

    def fromXmlString(self, xmlString):
        newRoot = self.tree.fromXmlString(xmlString)
        macroServerObj = self.getModelObj()
        for macroNode in newRoot.allMacros():
            macroServerObj.fillMacroNodeAdditionalInfos(macroNode)
        return newRoot

    def fromPlainText(self, plainText):
        plainTextMacros = []
        macroInfos = []
        macroServerObj = self.getModelObj()
        unknownMacros = []
        for plainTextMacro in plainText.split('\n'):
            # stripping the whitespace characters
            plainTextMacro = plainTextMacro.strip()
            # ignoring the empty lines
            if len(plainTextMacro) == 0:
                continue
            # ignoring the commented lines
            if plainTextMacro[0] in self.comment_characters:
                continue
            macroName = plainTextMacro.split()[0]
            macroInfo = macroServerObj.getMacroInfoObj(macroName)
            if macroInfo is None:
                unknownMacros.append(macroName)
            plainTextMacros.append(plainTextMacro)
            macroInfos.append(macroInfo)
        if len(unknownMacros) > 0:
            msg = ("{0} macro(s) are not loaded in the "
                   "MacroServer".format(", ".join(unknownMacros)))
            Qt.QMessageBox.warning(self, "Error while parsing the sequence",
                                   msg)
            raise ValueError(msg)
        newRoot = self.tree.fromPlainText(plainTextMacros, macroInfos)
        return newRoot

    def setModel(self, model):
        oldModelObj = self.getModelObj()
        if oldModelObj is not None:
            oldModelObj.macrosUpdated.disconnect(
                self.macroComboBox.onMacrosUpdated)
        TaurusWidget.setModel(self, model)
        newModelObj = self.getModelObj()
        newModelObj.macrosUpdated.connect(self.macroComboBox.onMacrosUpdated)
        self.sequenceEditor.setModel(model)
        self.macroComboBox.setModel(model)

    @classmethod
    def getQtDesignerPluginInfo(cls):
        return {'container': False,
                'group': 'Taurus Sardana',
                'module': 'taurus.qt.qtgui.extra_macroexecutor',
                'icon': ':/designer/frame.png'}
Ejemplo n.º 37
0
 def expanded(self):
     for column in range(self.model().columnCount(Qt.QModelIndex())):
         self.resizeColumnToContents(column)
Ejemplo n.º 38
0
    def onContextChanged(self, idx=None):
        try:
            cid = self.getCurrentContext(idx)
            print "onContextChanged(%s,(%s,%s,%s))" % (
                cid, self.filterComboBox.currentText(),
                self.filterComboBox2.currentText(),
                self.contextComboBox.currentText())
            try:
                self.context = self.snapapi.get_context(cid)
            except:
                msg = QExceptionMessage('\n'.join(("Tango Archiving Problem",
                                        "Could not retrieve context with following ID: %s.<br>" % cid + \
                                        "Please check if SnapManagerDS is running.<br>" + \
                                        "Also check if this context exists.")))
                return
            self.infoLabel1_2.setText("<b>%s</b>" % self.context.author)
            self.infoLabel2_2.setText("<b>%s</b>" % self.context.reason)
            if len(self.context.description) > 80:
                self.infoLabel3_2.setText(
                    "<b>%s</b>" % (self.context.description[:75] + ' ...'))
            else:
                #self.infoLabel3_2.setWordWrap(True)
                self.infoLabel3_2.setText("<b>%s</b>" %
                                          (self.context.description))
            self.infoLabel3_2.setToolTip(
                fandango.str2lines(self.context.description))

            if self.defaultContextID():
                self.defaultContextLabel.setText(
                    "<b>%s</b> [%d]" % (self.context.name, self.context.ID))

            self.listWidget.clear()
            print "onContextChanged(%s): get_snapshots()" % (cid)
            self.snapshots = self.context.get_snapshots()
            print '[%d]' % len(self.snapshots)
            for id, snapshot in self.snapshots.items():
                item = Qt.QListWidgetItem()
                item.setText("%s - %s [ID: %d]" %
                             (snapshot[0], snapshot[1].split('\n')[0], id))
                item.setData(Qt.Qt.UserRole, Qt.QVariant(id))
                item.setToolTip(snapshot[1])
                self.listWidget.addItem(item)
            self.listWidget.model().sort(0, Qt.Qt.DescendingOrder)
            self.buttonTake.show()
            self.buttonImport.show()
            self.infoLabel1_1.show()
            self.infoLabel1_2.show()
            self.infoLabel2_1.show()
            self.infoLabel2_2.show()
            self.infoLabel3_1.show()
            self.infoLabel3_2.show()
            self.infoLabel4_1.show()
            self.tableWidget.clear()
            self.tableWidget.setColumnCount(0)
            self.tableWidget.setRowCount(0)
            self.tableWidget.setHorizontalHeaderLabels([""])
            self.comp._wi.tableWidget.clear()
            self.comp._wi.tableWidget.setColumnCount(0)
            self.comp._wi.tableWidget.setRowCount(0)
            self.comp._wi.tableWidget.setHorizontalHeaderLabels([""])
            self.attributes = []
            self.comp._wi.diffComboBox.clear()
            self.tableView()
        except:
            msg = QExceptionMessage("Error")
Ejemplo n.º 39
0
class FavouritesMacrosList(Qt.QListView, BaseConfigurableClass):

    favouriteSelected = Qt.pyqtSignal(object)

    def __init__(self, parent=None):
        Qt.QListView.__init__(self, parent)

        self.setSelectionMode(Qt.QListView.ExtendedSelection)

        self.removeAction = Qt.QAction(getIcon(":/actions/list-remove.svg"),
                                       "Remove from favourites", self)
        self.removeAction.triggered.connect(self.removeMacros)
        self.removeAction.setToolTip(
            "Clicking this button will remove selected macros "
            "from favourites.")

        self.removeAllAction = Qt.QAction(getIcon(":/places/user-trash.svg"),
                                          "Remove all from favourites", self)
        self.removeAllAction.triggered.connect(self.removeAllMacros)
        self.removeAllAction.setToolTip(
            "Clicking this button will remove all macros from favourites.")

        self.moveUpAction = Qt.QAction(getIcon(":/actions/go-up.svg"),
                                       "Move up", self)
        self.moveUpAction.triggered.connect(self.upMacro)
        self.moveUpAction.setToolTip(
            "Clicking this button will move the macro up "
            "in the favourites hierarchy.")

        self.moveDownAction = Qt.QAction(getIcon(":/actions/go-down.svg"),
                                         "Move down", self)
        self.moveDownAction.triggered.connect(self.downMacro)
        self.moveDownAction.setToolTip(
            "Clicking this button will move the macro down "
            "in the favourites hierarchy.")

        self.disableActions()

    def currentChanged(self, current, previous):
        macro = copy.deepcopy(self.currentIndex().internalPointer())
        self.favouriteSelected.emit(macro)
        Qt.QListView.currentChanged(self, current, previous)

    def selectionChanged(self, old, new):
        macro = None
        if self.currentIndex().isValid():
            self.removeAllAction.setEnabled(True)
            self.isIndexSelected()
        else:
            self.disableActions()
        Qt.QListView.selectionChanged(self, old, new)
        if len(self.selectedIndexes()) > 1:
            self.moveUpAction.setEnabled(False)
            self.moveDownAction.setEnabled(False)

    def isIndexSelected(self):
        if len(self.selectedIndexes()) > 0:
            self.removeAction.setEnabled(True)
            self.moveUpAction.setEnabled(self.model().isUpRowAllowed(
                self.currentIndex()))
            self.moveDownAction.setEnabled(self.model().isDownRowAllowed(
                self.currentIndex()))
        else:
            self.removeAction.setEnabled(False)
            self.moveUpAction.setEnabled(False)
            self.moveDownAction.setEnabled(False)

    def mousePressEvent(self, e):
        clickedIndex = self.indexAt(e.pos())
        if clickedIndex.isValid():
            macro = copy.deepcopy(self.currentIndex().internalPointer())
            self.favouriteSelected.emit(macro)
        Qt.QListView.mousePressEvent(self, e)

    def disableActions(self):
        self.removeAction.setEnabled(False)
        self.removeAllAction.setEnabled(False)
        self.moveUpAction.setEnabled(False)
        self.moveDownAction.setEnabled(False)

    def insertMacro(self, macroNode):
        idx = self.model().insertRow(macroNode)
        self.setCurrentIndex(idx)

    def removeMacros(self):
        slist = sorted(self.selectedIndexes(),
                       key=lambda index: index.row(),
                       reverse=True)
        for index in slist:
            row = index.row()
            idx = self.model().removeRow(row)
        self.setCurrentIndex(idx)

    def removeAllMacros(self):
        self.selectAll()
        slist = sorted(self.selectedIndexes(),
                       key=lambda index: index.row(),
                       reverse=True)
        for index in slist:
            self.model().removeRow(index.row())

    def upMacro(self):
        row = self.currentIndex().row()
        idx = self.model().upRow(row)
        self.setCurrentIndex(idx)

    def downMacro(self):
        row = self.currentIndex().row()
        idx = self.model().downRow(row)
        self.setCurrentIndex(idx)

    def toXmlString(self):
        return self.model().toXmlString()

    def fromXmlString(self, xmlString):
        self.model().fromXmlString(xmlString)
Ejemplo n.º 40
0
class TaurusMacroExecutorWidget(TaurusWidget):

    doorChanged = Qt.pyqtSignal('QString')
    macroNameChanged = Qt.pyqtSignal('QString')
    macroStarted = Qt.pyqtSignal('QString')
    plotablesFilterChanged = Qt.pyqtSignal(compat.PY_OBJECT)
    shortMessageEmitted = Qt.pyqtSignal('QString')

    def __init__(self, parent=None, designMode=False):
        TaurusWidget.__init__(self, parent, designMode)
        self.setObjectName(self.__class__.__name__)

        self._doorName = ""
        self._macroId = None
        self.setLayout(Qt.QVBoxLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)

        self.addToFavouritesAction = Qt.QAction(
            Qt.QIcon("status:software-update-available.svg"),
            "Add to favourites", self)
        self.addToFavouritesAction.triggered.connect(self.onAddToFavourites)
        self.addToFavouritesAction.setToolTip("Add to favourites")
        self.stopMacroAction = Qt.QAction(
            Qt.QIcon("actions:media_playback_stop.svg"), "Stop macro", self)
        self.stopMacroAction.triggered.connect(self.onStopMacro)
        self.stopMacroAction.setToolTip("Stop macro")
        self.pauseMacroAction = Qt.QAction(
            Qt.QIcon("actions:media_playback_pause.svg"), "Pause macro", self)
        self.pauseMacroAction.triggered.connect(self.onPauseMacro)
        self.pauseMacroAction.setToolTip("Pause macro")
        self.playMacroAction = Qt.QAction(
            Qt.QIcon("actions:media_playback_start.svg"), "Start macro", self)
        self.playMacroAction.triggered.connect(self.onPlayMacro)
        self.playMacroAction.setToolTip("Start macro")
        actionsLayout = Qt.QHBoxLayout()
        actionsLayout.setContentsMargins(0, 0, 0, 0)
        addToFavouritsButton = Qt.QToolButton()
        addToFavouritsButton.setDefaultAction(self.addToFavouritesAction)
        self.addToFavouritesAction.setEnabled(False)
        actionsLayout.addWidget(addToFavouritsButton)

        self.macroComboBox = MacroComboBox(self)
        self.macroComboBox.setModelColumn(0)
        actionsLayout.addWidget(self.macroComboBox)
        stopMacroButton = Qt.QToolButton()
        stopMacroButton.setDefaultAction(self.stopMacroAction)
        actionsLayout.addWidget(stopMacroButton)
        pauseMacroButton = Qt.QToolButton()
        pauseMacroButton.setDefaultAction(self.pauseMacroAction)
        actionsLayout.addWidget(pauseMacroButton)
        self.playMacroButton = Qt.QToolButton()
        self.playMacroButton.setDefaultAction(self.playMacroAction)
        actionsLayout.addWidget(self.playMacroButton)
        self.disableControlActions()
        self.doorStateLed = TaurusLed(self)
        actionsLayout.addWidget(self.doorStateLed)
        self.layout().addLayout(actionsLayout)

        splitter = Qt.QSplitter(self)
        self.layout().addWidget(splitter)
        splitter.setOrientation(Qt.Qt.Vertical)

        self._paramEditorModel = ParamEditorModel()
        self.stackedWidget = Qt.QStackedWidget()
        self.standardMacroParametersEditor = StandardMacroParametersEditor(
            self.stackedWidget)
        self.stackedWidget.addWidget(self.standardMacroParametersEditor)
        self.customMacroParametersEditor = None
        splitter.addWidget(self.stackedWidget)

        self._favouritesBuffer = None
        self.favouritesMacrosEditor = FavouritesMacrosEditor(self)
        self.registerConfigDelegate(self.favouritesMacrosEditor)
        self.favouritesMacrosEditor.setFocusPolicy(Qt.Qt.NoFocus)

        self._historyBuffer = None
        self.historyMacrosViewer = HistoryMacrosViewer(self)
        self.registerConfigDelegate(self.historyMacrosViewer)
        self.historyMacrosViewer.setFocusPolicy(Qt.Qt.NoFocus)

        self.tabMacroListsWidget = Qt.QTabWidget(self)
        self.tabMacroListsWidget.addTab(
            self.favouritesMacrosEditor, "Favourite list")
        self.tabMacroListsWidget.addTab(
            self.historyMacrosViewer, "History Viewer")
        splitter.addWidget(self.tabMacroListsWidget)
        # Due to a limitation in the useParentModel architecture of Taurus,
        # the parent of historyMacrosViewer and favouritesMacrosEditor
        # must be recalculated. See more details in the taurus snippet code [1]
        # [1] https://raw.githubusercontent.com/taurus-org/taurus/develop/doc/source/devel/examples/parentmodel_issue_demo.py
        self.historyMacrosViewer.recheckTaurusParent()
        self.favouritesMacrosEditor.recheckTaurusParent()

        self._isHistoryMacro = False
        self.macroProgressBar = MacroProgressBar(self)
        self.layout().addWidget(self.macroProgressBar)

        #spockCommandLabel = Qt.QLabel("Spock command:", self)
        # spockCommandLabel.setFont(Qt.QFont("Courier",9))
        self.spockCommand = SpockCommandWidget("Spock", self)
        self.spockCommand.setSizePolicy(
            Qt.QSizePolicy.Expanding, Qt.QSizePolicy.Minimum)
        spockCommandLayout = Qt.QHBoxLayout()
        spockCommandLayout.setContentsMargins(0, 0, 0, 0)
        # spockCommandLayout.addWidget(spockCommandLabel)
        spockCommandLayout.addWidget(self.spockCommand)
        self.layout().addLayout(spockCommandLayout)

        self.macroComboBox.currentIndexChanged['QString'].connect(
            self.onMacroComboBoxChanged)
        self.favouritesMacrosEditor.list.favouriteSelected.connect(
            self.onFavouriteSelected)
        self.historyMacrosViewer.list.historySelected.connect(
            self.onHistorySelected)

        self.spockCommand.pressedReturn.connect(self.onPlayMacro)
        self.spockCommand.spockComboBox.connect(self.setComboBoxItem)
        self.spockCommand.elementUp.connect(self.setHistoryUp)
        self.spockCommand.elementDown.connect(self.setHistoryDown)
        self.spockCommand.expandTree.connect(
            self.standardMacroParametersEditor.tree.expandAll)

    def macroId(self):
        return self._macroId

    def contextMenuEvent(self, event):
        menu = Qt.QMenu()
        menu.addAction(Qt.QIcon.fromTheme("view-refresh"), "Check door state",
                       self.checkDoorState)
        menu.exec_(event.globalPos())

    def checkDoorState(self):
        door = Device(self.doorName())
        doorState = door.getState()
        if doorState == PyTango.DevState.RUNNING:
            self.playMacroAction.setEnabled(False)
            self.pauseMacroAction.setEnabled(True)
            self.stopMacroAction.setEnabled(True)
        elif doorState == PyTango.DevState.ON or doorState == PyTango.DevState.ALARM:
            self.playMacroAction.setEnabled(True)
            self.pauseMacroAction.setEnabled(False)
            self.stopMacroAction.setEnabled(False)
        elif doorState == PyTango.DevState.STANDBY:
            self.playMacroAction.setEnabled(True)
            self.pauseMacroAction.setEnabled(False)
            self.stopMacroAction.setEnabled(True)

    def setMacroId(self, macroId):
        self._macroId = macroId

    def doorName(self):
        return self._doorName

    def setDoorName(self, doorName):
        self._doorName = doorName

    def setFavouritesBuffer(self, favouritesMacro):
        self._favouritesBuffer = favouritesMacro

    # History Widget
    def setHistoryUp(self):
        self.setHistoryFocus()
        self.historyMacrosViewer.listElementUp()

    def setHistoryDown(self):
        self.setHistoryFocus()
        self.historyMacrosViewer.listElementDown()

    def setHistoryFocus(self):
        self.tabMacroListsWidget.setCurrentWidget(self.historyMacrosViewer)
        # self.historyMacrosViewer.setFocus()

    def historyBuffer(self):
        return self._historyBuffer

    def setHistoryBuffer(self, favouritesMacro):
        self._historyBuffer = favouritesMacro

    def favouritesBuffer(self):
        return self._favouritesBuffer

    def paramEditorModel(self):
        return self._paramEditorModel

    def setParamEditorModel(self, paramEditorModel):
        self._paramEditorModel = paramEditorModel

    def setComboBoxItem(self, macroName):
        self.macroComboBox.selectMacro(macroName)

    @Qt.pyqtSlot('QString')
    def onMacroComboBoxChanged(self, macroName):
        macroName = str(macroName)
        if macroName == "":
            macroName, macroNode = None, None
#            macroNode = macro.MacroNode(name="")
            self.playMacroAction.setEnabled(False)
            self.addToFavouritesAction.setEnabled(False)
        else:
            if self._isHistoryMacro:
                macroNode = self.historyBuffer()
                self.setHistoryBuffer(None)
                self.favouritesMacrosEditor.list.clearSelection()
            else:
                macroNode = self.favouritesBuffer()
                self.setFavouritesBuffer(None)
                self.historyMacrosViewer.list.clearSelection()
            self._isHistoryMacro = False

            if macroNode is None:
                macroNode = self.getModelObj().getMacroNodeObj(macroName)

            self.playMacroAction.setEnabled(True)
            self.addToFavouritesAction.setEnabled(True)

        self.paramEditorModel().setRoot(macroNode)
        self.spockCommand.setModel(self.paramEditorModel())
        if self.stackedWidget.count() == 2:
            self.stackedWidget.removeWidget(self.customMacroParametersEditor)
            self.customMacroParametersEditor.setParent(None)
        self.customMacroParametersEditor = ParamEditorManager(
        ).getMacroEditor(macroName, self.stackedWidget)
        if self.customMacroParametersEditor:
            self.customMacroParametersEditor.setModel(self.paramEditorModel())
            self.stackedWidget.addWidget(self.customMacroParametersEditor)
            self.stackedWidget.setCurrentWidget(
                self.customMacroParametersEditor)
        else:
            self.standardMacroParametersEditor.setModel(
                self.paramEditorModel())

        self.macroNameChanged.emit(macroName)

    def onFavouriteSelected(self, macroNode):
        self.setFavouritesBuffer(macroNode)
        name = ""
        if not macroNode is None:
            name = macroNode.name()
        self._isHistoryMacro = False
        self.macroComboBox.selectMacro(name)

    def onHistorySelected(self, macroNode):
        self.setHistoryBuffer(macroNode)
        name = ""
        if not macroNode is None:
            name = macroNode.name()
        self._isHistoryMacro = True
        self.macroComboBox.selectMacro(name)

    def onAddToFavourites(self):
        self.favouritesMacrosEditor.addMacro(
            deepcopy(self.paramEditorModel().root()))

    def addToHistory(self):
        self.historyMacrosViewer.addMacro(
            deepcopy(self.paramEditorModel().root()))

    def onDoorChanged(self, doorName):
        self.setDoorName(doorName)
        if self.doorName() == "":
            self.doorStateLed.setModel(None)
            return
        self.doorStateLed.setModel(self.doorName() + "/State")
        door = Device(doorName)
        doorState = door.stateObj.rvalue
        if doorState == PyTango.DevState.ON:
            self.playMacroAction.setText("Start macro")
            self.playMacroAction.setToolTip("Start macro")
        elif doorState == PyTango.DevState.STANDBY:
            self.playMacroAction.setText("Resume macro")
            self.playMacroAction.setToolTip("Resume macro")

    def onPlayMacro(self):
        door = Device(self.doorName())
        doorState = door.getState()
        if doorState == PyTango.DevState.ON or doorState == PyTango.DevState.ALARM:
            self.setFocus()
            paramEditorModel = self.paramEditorModel()
            macroNode = paramEditorModel.root()
            id = macroNode.assignId()
            self.setMacroId(id)
            params, alerts = macroNode.toRun()
            xmlString = paramEditorModel.toXmlString()
            if len(alerts) > 0:
                Qt.QMessageBox.warning(
                    self, "Macro parameters warning", alerts)
                return
            door.runMacro(xmlString)
            self.addToHistory()
#            door.runMacro(str(macroNode.name()), params)
        elif doorState == PyTango.DevState.STANDBY:
            door.command_inout("ResumeMacro")
        else:
            Qt.QMessageBox.warning(self, "Error while starting/resuming macro",
                                   "It was not possible to start/resume macro, because state of the door was different than ON/STANDBY")

    def onStopMacro(self):
        door = Device(self.doorName())
        doorState = door.getState()

        if doorState in (PyTango.DevState.RUNNING, PyTango.DevState.STANDBY):
            door.command_inout("StopMacro")
        else:
            Qt.QMessageBox.warning(self, "Error while stopping macro",
                                   "It was not possible to stop macro, because state of the door was different than RUNNING or STANDBY")

    def onPauseMacro(self):
        door = Device(self.doorName())
        doorState = door.getState()

        if doorState == PyTango.DevState.RUNNING:
            door.command_inout("PauseMacro")
        else:
            Qt.QMessageBox.warning(self, "Error while pausing macro",
                                   "It was not possible to pause macro, because state of the door was different than RUNNING")

    def onMacroStatusUpdated(self, data):
        macro = data[0]
        if macro is None:
            return
        data = data[1][0]
        state, range, step, id = data["state"], data[
            "range"], data["step"], data["id"]
        if id is None:
            return
        if id != self.macroId():
            return
        macroName = macro.name
        shortMessage = ""
        if state == "start":
            self.macroStarted.emit("DoorOutput")
            self.macroProgressBar.setRange(range[0], range[1])
            self.playMacroAction.setEnabled(False)
            self.pauseMacroAction.setEnabled(True)
            self.stopMacroAction.setEnabled(True)
            self.plotablesFilterChanged.emit(None)
            self.plotablesFilterChanged.emit(standardPlotablesFilter)
            shortMessage = "Macro %s started." % macroName
        elif state == "pause":
            self.playMacroAction.setText("Resume macro")
            self.playMacroAction.setToolTip("Resume macro")
            self.playMacroAction.setEnabled(True)
            self.pauseMacroAction.setEnabled(False)
            shortMessage = "Macro %s paused." % macroName
        elif state == "resume":
            self.playMacroAction.setText("Start macro")
            self.playMacroAction.setToolTip("Start macro")
            self.playMacroAction.setEnabled(False)
            self.pauseMacroAction.setEnabled(True)
            shortMessage = "Macro %s resumed." % macroName
        elif state == "stop" or state == "finish":
            self.playMacroAction.setEnabled(True)
            self.pauseMacroAction.setEnabled(False)
            self.stopMacroAction.setEnabled(False)
            shortMessage = "Macro %s finished." % macroName
        elif state == "exception":
            self.playMacroAction.setEnabled(True)
            self.pauseMacroAction.setEnabled(False)
            self.stopMacroAction.setEnabled(False)
            shortMessage = "Macro %s error." % macroName
            exc_value, exc_stack = data['exc_value'], data['exc_stack']
            exceptionDialog = TaurusMessageBox(
                MacroRunException, exc_value, exc_stack)
            exceptionDialog.exec_()
        elif state == "abort":
            self.playMacroAction.setText("Start macro")
            self.playMacroAction.setToolTip("Start macro")
            self.playMacroAction.setEnabled(True)
            self.pauseMacroAction.setEnabled(False)
            self.stopMacroAction.setEnabled(False)
            shortMessage = "Macro %s stopped." % macroName
        elif state == "step":
            shortMessage = "Macro %s at %d %% of progress." % (macroName, step)
        self.shortMessageEmitted.emit(shortMessage)
        self.macroProgressBar.setValue(step)

    def disableControlActions(self):
        self.pauseMacroAction.setEnabled(False)
        self.stopMacroAction.setEnabled(False)
        self.playMacroAction.setEnabled(False)

    def setModel(self, model):
        oldModelObj = self.getModelObj()
        if oldModelObj is not None:
            # TODO: check if macrosUpdated signal exists
            oldModelObj.macrosUpdated.disconnect(
                self.macroComboBox.onMacrosUpdated)
        TaurusWidget.setModel(self, model)
        newModelObj = self.getModelObj()
        newModelObj.macrosUpdated.connect(
            self.macroComboBox.onMacrosUpdated)
        self.macroComboBox.setModel(model)
        self.favouritesMacrosEditor.setModel(model)
        self.historyMacrosViewer.setModel(model)
        self.spockCommand.setModel(model)

    @classmethod
    def getQtDesignerPluginInfo(cls):
        return {'container': False,
                'group': 'Taurus Sardana',
                'module': 'taurus.qt.qtgui.extra_macroexecutor',
                'icon': ':/designer/frame.png'}
Ejemplo n.º 41
0
 def onApply(self):
     self.emit(Qt.SIGNAL('applied'))
    def showProperties(self, prop=None):
        """Updates the dialog to show the given properties.

        :param prop: (CurveAppearanceProperties) the properties object
                     containing what should be shown. If a given property is
                     set to CONFLICT, the corresponding plot_item will show a
                     "neutral" display
        """

        if prop is None:
            prop = self._shownProp
        # set the Style comboboxes
        self.sStyleCB.setCurrentIndex(
            self.sStyleCB.findText(NamedSymbolStyles[prop.sStyle]))
        self.lStyleCB.setCurrentIndex(
            self.lStyleCB.findText(NamedLineStyles[prop.lStyle]))
        self.cStyleCB.setCurrentIndex(
            self.cStyleCB.findText(NamedCurveStyles[prop.cStyle]))

        if prop.y2 is CONFLICT:
            self.assignToY1BT.setChecked(False)
            self.assignToY2BT.setChecked(False)
        elif prop.y2:
            self.assignToY2BT.setChecked(True)
        else:
            self.assignToY1BT.setChecked(True)

        # set sSize and lWidth spinboxes. if prop.sSize is None, it puts -1
        # (which is the special value for these switchhboxes)
        if prop.sSize is CONFLICT or prop.sStyle is None:
            self.sSizeSB.setValue(-1)
        else:
            self.sSizeSB.setValue(max(prop.sSize, -1))
        if prop.lWidth is CONFLICT:
            self.lWidthSB.setValue(-1)
        else:
            self.lWidthSB.setValue(max(prop.lWidth, -1))

        # Set the Color combo boxes. The item at index 0 is the empty one in
        # the comboboxes Manage unknown colors by including them
        if prop.sColor in (None, CONFLICT) or prop.sStyle is None:
            index = 0
        else:
            index = self.sColorCB.findData(Qt.QColor(prop.sColor))
        if index == -1:  # if the color is not supported, add it to combobox
            index = self.sColorCB.count()
            self.sColorCB.addItem(self._colorIcon(
                Qt.QColor(prop.sColor)), "", Qt.QColor(prop.sColor))
        self.sColorCB.setCurrentIndex(index)
        if prop.lColor is None or prop.lColor is CONFLICT:
            index = 0
        else:
            index = self.lColorCB.findData(Qt.QColor(prop.lColor))
        if index == -1:  # if the color is not supported, add it to combobox
            index = self.lColorCB.count()
            self.lColorCB.addItem(self._colorIcon(
                Qt.QColor(prop.lColor)), "", Qt.QColor(prop.lColor))
        self.lColorCB.setCurrentIndex(index)
        # set the Fill Checkbox. The prop.sFill value can be in 3 states: True,
        # False and None
        if prop.sFill is None or prop.sFill is CONFLICT:
            checkState = Qt.Qt.PartiallyChecked
        elif prop.sFill:
            checkState = Qt.Qt.Checked
        else:
            checkState = Qt.Qt.Unchecked
        self.sFillCB.setCheckState(checkState)
        # set the Area Fill Checkbox. The prop.cFill value can be in 3 states:
        # True, False and None
        if prop.cFill is CONFLICT:
            checkState = Qt.Qt.PartiallyChecked
            self.cAreaDSB.setValue(0.0)
        elif prop.cFill is None:
            checkState = Qt.Qt.Unchecked
            self.cAreaDSB.setValue(0.0)
        else:
            checkState = Qt.Qt.Checked
            self.cAreaDSB.setValue(prop.cFill)
        self.cFillCB.setCheckState(checkState)
    def getShownProperties(self):
        """Returns a copy of the currently shown properties and updates
        self._shownProp

        :return: (CurveAppearanceProperties)
        """
        prop = CurveAppearanceProperties()

        for name in self.getSelectedCurveNames():
            prop.title = self.curvePropDict[name].title

        # get the values from the Style comboboxes. Note that the empty string
        # ("") translates into CONFLICT
        prop.sStyle = ReverseNamedSymbolStyles[
            str(self.sStyleCB.currentText())]
        prop.lStyle = ReverseNamedLineStyles[str(self.lStyleCB.currentText())]
        prop.cStyle = ReverseNamedCurveStyles[str(self.cStyleCB.currentText())]
        # get sSize and lWidth from the spinboxes (-1 means conflict)
        v = self.sSizeSB.value()
        if v == -1:
            prop.sSize = CONFLICT
        else:
            prop.sSize = v
        v = self.lWidthSB.value()
        if v == -1:
            prop.lWidth = CONFLICT
        else:
            prop.lWidth = v
        # Get the Color combo boxes. The item at index 0 is the empty one in
        # the comboboxes
        index = self.sColorCB.currentIndex()
        if index == 0:
            prop.sColor = CONFLICT
        else:
            prop.sColor = Qt.QColor(self.sColorCB.itemData(index))
        index = self.lColorCB.currentIndex()
        if index == 0:
            prop.lColor = CONFLICT
        else:
            prop.lColor = Qt.QColor(self.lColorCB.itemData(index))
        # get the sFill from the Checkbox.
        checkState = self.sFillCB.checkState()
        if checkState == Qt.Qt.PartiallyChecked:
            prop.sFill = CONFLICT
        else:
            prop.sFill = bool(checkState)
        # get the cFill from the Checkbox.
        checkState = self.cFillCB.checkState()
        if checkState == Qt.Qt.PartiallyChecked:
            prop.cFill = CONFLICT
        elif checkState == Qt.Qt.Checked:
            prop.cFill = self.cAreaDSB.value()
        else:
            prop.cFill = None

        # get the y2 state from the buttons
        y1 = self.assignToY1BT.isChecked()
        y2 = self.assignToY2BT.isChecked()
        if not y1 and not y2:
            prop.y2 = CONFLICT
        elif y1:
            prop.y2 = False
        elif y2:
            prop.y2 = True
        else:
            # both buttons should never be checked simultaneously
            raise RuntimeError('Inconsistent state of Y-axis buttons')

        # store the props
        self._shownProp = copy.deepcopy(prop)
        return copy.deepcopy(prop)
Ejemplo n.º 44
0
    def __init__(self, parent=None, designMode=False):
        TaurusWidget.__init__(self, parent, designMode)
        # list representing all macros ids (all from sequence) currently
        # executed
        self._macroIds = []
        self._sequencesPath = str(Qt.QDir.homePath())
        self._sequenceModel = MacroSequenceTreeModel()

        self.registerConfigProperty(
            "sequencesPath", "setSequencesPath", "sequencesPath")

        self.setLayout(Qt.QVBoxLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)
        splitter = Qt.QSplitter()
        self.layout().addWidget(splitter)
        splitter.setOrientation(Qt.Qt.Vertical)

        self.sequenceEditor = TaurusWidget()
        splitter.addWidget(self.sequenceEditor)
        self.sequenceEditor.setLayout(Qt.QVBoxLayout())
        self.sequenceEditor.layout().setContentsMargins(0, 0, 0, 0)

        self.tree = MacroSequenceTree(self.sequenceEditor)
        self.sequenceProxyModel = MacroSequenceProxyModel()
        self.sequenceProxyModel.setSourceModel(self._sequenceModel)
        self.tree.setModel(self.sequenceProxyModel)
        self.tree.setItemDelegate(SequenceEditorDelegate(self.tree))

        actionsLayout = Qt.QHBoxLayout()
        actionsLayout.setContentsMargins(0, 0, 0, 0)
        self.newSequenceAction = Qt.QAction(
            Qt.QIcon.fromTheme("document-new"), "New", self)
        self.newSequenceAction.triggered.connect(self.onNewSequence)
        self.newSequenceAction.setToolTip("New sequence")
        self.newSequenceAction.setEnabled(False)
        newSequenceButton = Qt.QToolButton()
        newSequenceButton.setDefaultAction(self.newSequenceAction)
        actionsLayout.addWidget(newSequenceButton)

        self.openSequenceAction = Qt.QAction(
            Qt.QIcon.fromTheme("document-open"), "Open...", self)
        self.openSequenceAction.triggered.connect(self.onOpenSequence)
        self.openSequenceAction.setToolTip("Open sequence...")
        openSequenceButton = Qt.QToolButton()
        openSequenceButton.setDefaultAction(self.openSequenceAction)
        actionsLayout.addWidget(openSequenceButton)

        self.saveSequenceAction = Qt.QAction(
            Qt.QIcon.fromTheme("document-save"), "Save...", self)
        self.saveSequenceAction.triggered.connect(self.onSaveSequence)
        self.saveSequenceAction.setToolTip("Save sequence...")
        self.saveSequenceAction.setEnabled(False)
        saveSequenceButton = Qt.QToolButton()
        saveSequenceButton.setDefaultAction(self.saveSequenceAction)
        actionsLayout.addWidget(saveSequenceButton)

        self.stopSequenceAction = Qt.QAction(
            Qt.QIcon("actions:media_playback_stop.svg"), "Stop", self)
        self.stopSequenceAction.triggered.connect(self.onStopSequence)
        self.stopSequenceAction.setToolTip("Stop sequence")
        stopSequenceButton = Qt.QToolButton()
        stopSequenceButton.setDefaultAction(self.stopSequenceAction)
        actionsLayout.addWidget(stopSequenceButton)

        self.pauseSequenceAction = Qt.QAction(
            Qt.QIcon("actions:media_playback_pause.svg"), "Pause", self)
        self.pauseSequenceAction.triggered.connect(self.onPauseSequence)
        self.pauseSequenceAction.setToolTip("Pause sequence")
        pauseSequenceButton = Qt.QToolButton()
        pauseSequenceButton.setDefaultAction(self.pauseSequenceAction)
        actionsLayout.addWidget(pauseSequenceButton)

        self.playSequenceAction = Qt.QAction(
            Qt.QIcon("actions:media_playback_start.svg"), "Play", self)
        self.playSequenceAction.triggered.connect(self.onPlaySequence)
        self.playSequenceAction.setToolTip("Play sequence")
        playSequenceButton = Qt.QToolButton()
        playSequenceButton.setDefaultAction(self.playSequenceAction)
        actionsLayout.addWidget(playSequenceButton)

        self.doorStateLed = TaurusLed(self)
        actionsLayout.addWidget(self.doorStateLed)

        #@todo this feature will be replaced by checkboxes in the
        # sequence tree view indicating clearing of the plot after execution
        self.fullSequencePlotCheckBox = Qt.QCheckBox(
            "Full sequence plot", self)
        self.fullSequencePlotCheckBox.toggled.connect(self.setFullSequencePlot)
        self.fullSequencePlotCheckBox.setChecked(True)
        actionsLayout.addWidget(self.fullSequencePlotCheckBox)

        spacerItem = Qt.QSpacerItem(
            0, 0, Qt.QSizePolicy.Expanding, Qt.QSizePolicy.Fixed)
        actionsLayout.addItem(spacerItem)

        self.sequenceEditor.layout().addLayout(actionsLayout)

        macroLayout = Qt.QHBoxLayout()
        macroLayout.setContentsMargins(0, 0, 0, 0)
        macroLabel = Qt.QLabel("Macro:")
        macroLayout.addWidget(macroLabel)
        self.macroComboBox = MacroComboBox(self)
        self.macroComboBox.setModelColumn(0)
        self.macroComboBox.setSizePolicy(
            Qt.QSizePolicy.Expanding, Qt.QSizePolicy.Minimum)
        macroLayout.addWidget(self.macroComboBox)

        self.addMacroAction = Qt.QAction(
            Qt.QIcon.fromTheme("list-add"), "Add macro...", self)
        self.addMacroAction.triggered.connect(self.onAdd)
        self.addMacroAction.setToolTip(
            "Clicking this button will add selected macro")
        self.addMacroAction.setEnabled(False)
        addButton = Qt.QToolButton()
        addButton.setDefaultAction(self.addMacroAction)
        macroLayout.addWidget(addButton)

        self.sequenceEditor.layout().addLayout(macroLayout)

        sequenceLayout = Qt.QHBoxLayout()
        sequenceLayout.addWidget(self.tree)

        layout = Qt.QVBoxLayout()
        delButton = Qt.QToolButton()
        delButton.setDefaultAction(self.tree.deleteAction)
        delButton.setEnabled(False)
        layout.addWidget(delButton)
        upButton = Qt.QToolButton()
        upButton.setDefaultAction(self.tree.moveUpAction)
        upButton.setEnabled(False)
        layout.addWidget(upButton)
        downButton = Qt.QToolButton()
        downButton.setDefaultAction(self.tree.moveDownAction)
        downButton.setEnabled(False)
        layout.addWidget(downButton)
        leftButton = Qt.QToolButton()
        leftButton.setDefaultAction(self.tree.moveLeftAction)
        leftButton.setEnabled(False)
        layout.addWidget(leftButton)
        rightButton = Qt.QToolButton()
        rightButton.setDefaultAction(self.tree.moveRightAction)
        rightButton.setEnabled(False)
        layout.addWidget(rightButton)
        spacerItem = Qt.QSpacerItem(
            0, 40, Qt.QSizePolicy.Fixed, Qt.QSizePolicy.Expanding)
        layout.addItem(spacerItem)
        sequenceLayout.addLayout(layout)
        self.sequenceEditor.layout().addLayout(sequenceLayout)

        self.parametersProxyModel = MacroParametersProxyModel()
        self.parametersProxyModel.setSourceModel(self._sequenceModel)

        self.stackedWidget = Qt.QStackedWidget()
        splitter.addWidget(self.stackedWidget)
        self.standardMacroParametersEditor = StandardMacroParametersEditor(
            self.stackedWidget)
        self.standardMacroParametersEditor.setModel(self.parametersProxyModel)
        self.standardMacroParametersEditor.tree.setItemDelegate(
            ParamEditorDelegate(self.standardMacroParametersEditor.tree))
        self.stackedWidget.addWidget(self.standardMacroParametersEditor)
        self.customMacroParametersEditor = None

        self.macroComboBox.currentIndexChanged.connect(
            self.onMacroComboBoxChanged)
        self.tree.macroChanged.connect(self.setMacroParametersRootIndex)
Ejemplo n.º 45
0
##
# Taurus is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
##
# Taurus is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
##
# You should have received a copy of the GNU Lesser General Public License
# along with Taurus.  If not, see <http://www.gnu.org/licenses/>.
##
###########################################################################
'''An example of usage of TaurusGui in which no configuration file is used
(everything is done programmatically)
This can be launched directly as a stand-alone python script'''

if __name__ == '__main__':
    from taurus.qt.qtgui.application import TaurusApplication
    from taurus.qt.qtgui.taurusgui import TaurusGui
    from taurus.external.qt import Qt
    # if app_name name not given, it uses the file name
    app = TaurusApplication(app_name='MyGui', cmd_line_parser=None)
    gui = TaurusGui()
    panel = Qt.QWidget()
    gui.createPanel(panel, 'Foo')
    gui.show()
    app.exec_()
Ejemplo n.º 46
0
 def contextMenuEvent(self, event):
     menu = Qt.QMenu()
     menu.addAction(Qt.QIcon.fromTheme("view-refresh"), "Check door state",
                    self.checkDoorState)
     menu.exec_(event.globalPos())
Ejemplo n.º 47
0
class SpockCommandWidget(Qt.QLineEdit, TaurusBaseContainer):

    pressedReturn = Qt.pyqtSignal()
    spockComboBox = Qt.pyqtSignal('QString')
    elementUp = Qt.pyqtSignal()
    elementDown = Qt.pyqtSignal()
    setHistoryFocus = Qt.pyqtSignal()
    expandTree = Qt.pyqtSignal()

    def __init__(self, name='', parent=None, designMode=False):
        # self.newValue - is used as a flag to indicate whether a controlUp controlDown actions are used to iterate existing element or put new one
        # self.disableEditMode - flag, used to disable edition, when user enters name of the macro which is not valid (not allowed to edit in the yellow line)
        #                   switches off validation
        # disableSpockCommandUpdate - flag, it disables updates of the model
        # when macro is edited by macroEditor

        Qt.QLineEdit.__init__(self, parent)
        TaurusBaseContainer.__init__(self, name, parent, designMode)

        self._model = None
        self.setFont(Qt.QFont("Courier", 9))
        palette = Qt.QPalette()
        palette.setColor(Qt.QPalette.Base, Qt.QColor('yellow'))
        self.setPalette(palette)
        self.currentIndex = Qt.QModelIndex()
        self.newValue = False
        self.disableSpockCommandUpdate = False
        self.disableEditMode = True
        self.setEnabled(False)

        self.setActions()
        self.textChanged.connect(self.onTextChanged)
        self.returnPressed.connect(self.onReturnPressed)

    def setActions(self):
        self._downAction = Qt.QAction("downAction", self)
        self._upAction = Qt.QAction("upAction", self)
        self._ctrlDownAction = Qt.QAction("controlDownAction", self)
        self._ctrlUpAction = Qt.QAction("controlUpAction", self)

        self._ctrlDownAction.setShortcut(
            Qt.QKeySequence(Qt.Qt.CTRL + Qt.Qt.Key_Down))
        self._ctrlUpAction.setShortcut(
            Qt.QKeySequence(Qt.Qt.CTRL + Qt.Qt.Key_Up))
        self._downAction.setShortcuts([Qt.Qt.Key_Down])
        self._upAction.setShortcuts([Qt.Qt.Key_Up])

        self._ctrlDownAction.setShortcutContext(Qt.Qt.WidgetShortcut)
        self._ctrlUpAction.setShortcutContext(Qt.Qt.WidgetShortcut)
        self._downAction.setShortcutContext(Qt.Qt.WidgetShortcut)
        self._upAction.setShortcutContext(Qt.Qt.WidgetShortcut)

        self.addAction(self._ctrlDownAction)
        self.addAction(self._ctrlUpAction)
        self.addAction(self._downAction)
        self.addAction(self._upAction)
        self._downAction.triggered.connect(self.downAction)
        self._upAction.triggered.connect(self.upAction)
        self._ctrlDownAction.triggered.connect(self.controlDownAction)
        self._ctrlUpAction.triggered.connect(self.controlUpAction)

    def setCommand(self):
        command = self._model.toSpockCommand().strip()
        if not self.disableSpockCommandUpdate:
            self.setText(command)

    def onDataChanged(self, idx):
        """
        If data is changed to nothing set it to the default value.
        Otherwise update the spock command and check the validation.
        This is a workaround for bug-451 that clear all input parameters when an
        empty string parameter is deselected.
        """
        if idx.data() == "":
            defaultvalue = self._model.nodeFromIndex(idx).defValue()
            if defaultvalue != "":
                self._model.setData(idx, defaultvalue)
        else:
            self.setCommand()

    def setModel(self, model):
        if isinstance(model, Qt.QAbstractItemModel):
            enable = bool(model)
            self.disableEditMode = not enable
            self.setEnabled(enable)
            self._model = model
            self._model.dataChanged.connect(self.onDataChanged)
            self._model.modelReset.connect(self.setCommand)
        else:
            TaurusBaseContainer.setModel(self, model)


    def model(self):
        return self._model

    def getIndex(self, elementNumber=-1):
        # Returns QModelIndex of the required element (number of single
        # parameter). If the elementNumber == -1 next single parameter index is
        # returned.
        if elementNumber == -1:
            ix = self.currentIndex
            elementNumber = 1
        elif elementNumber == 0:
            return Qt.QModelIndex()
        else:
            ix = Qt.QModelIndex()

        (col, row, parentIdx) = (ix.column(), ix.row(), ix.parent())
        # to start from second column
        if col == -1 and row == -1:
            ix = self.forwardIdx(0, 1, ix)
        for i in range(0, elementNumber):
            # This condition in case we start tabbing with cursor on first
            # column
            if col == 0:
                currentNode = self.model().nodeFromIndex(ix)
                if isinstance(currentNode, macro.SingleParamNode):
                    nextIdx = self.forwardIdx(row, 1, parentIdx)
                else:
                    nextIdx = self.forwardIdx(0, 1, ix)
            else:
                nextIdx = self.forwardIdx(row + 1, 1, parentIdx)
            # this condition in case there is no next index and we want to pass focus
            # to next widget in parent obj
            if nextIdx == "term":
                return Qt.QModelIndex()
            ix = nextIdx
            (col, row, parentIdx) = (ix.column(), ix.row(), ix.parent())
        return ix

    def forwardIdx(self, row, col, parentIdx):
        # This method is moving down the tree to get next SingleParamNode
        # index.
        try:
            proposalIdx = self.model().index(row, col, parentIdx)
        except AssertionError:

            if parentIdx.row() == -1:
                return Qt.QModelIndex()
            grandParentIdx = parentIdx.parent()
            return self.forwardIdx(parentIdx.row() + 1, col, grandParentIdx)

        proposalNode = self.model().nodeFromIndex(proposalIdx)

        if isinstance(proposalNode, macro.SingleParamNode):
            return proposalIdx
        elif isinstance(proposalNode, macro.RepeatNode):
            return self.forwardIdx(0, 1, proposalIdx)
        elif isinstance(proposalNode, macro.RepeatParamNode):
            if len(proposalNode) > 0:
                return self.forwardIdx(0, 1, proposalIdx)
            else:
                return self.forwardIdx(row + 1, col, proposalIdx)

        elif not proposalIdx.isValid():
            proposalIdx = parentIdx.sibling(parentIdx.row() + 1, 0)

            if proposalIdx.isValid():
                proposalIdx = proposalIdx.child(0, 1)
            else:
                while not proposalIdx.isValid():
                    parentIdx = parentIdx.parent()
                    if not parentIdx.isValid():

                        return Qt.QModelIndex()
                    proposalIdx = parentIdx.sibling(parentIdx.row() + 1, 1)

            return proposalIdx

    def validateAllExpresion(self, secValidation=False):
        # This method is responsible for full validation of the macro. It is executed whenever the text is changed (when user edits values).
        # Validation starts with checking if the macro (name) is valid.
        # Next steps:
        # 1. Validates every SingleParamNode and counts how many there are in the macro.
        # 2. If there are more SingleParamNodes than entered values it will check if there is RepeatParamNode.
        #   If there is RepeatParamNode it will check if its RepeatNodes can be deleted.
        # 3. If there are more values entered than SingleParamNodes in macro it will check if there is RepeatParamNode.
        #   If there is it will try to add new RepeatNode.

        if self.model() is None:
            raise RuntimeError(
                'Door must be set in order to use the macroexecutor.')

        self.currentIndex = Qt.QModelIndex()
        mlist = str(self.text()).split()
        problems = []
        try:
            if str(mlist[0]) != str(self.model().root().name()):
                try:
                    self.getModelObj().validateMacroName(str(mlist[0]))
                    self.validateMacro(mlist[0])
                    self.updateMacroEditor(mlist[0])
                    if not secValidation:
                        self.validateAllExpresion(True)

                except Exception as e:
                    if self.disableEditMode:
                        self.updateMacroEditor(mlist[0])
                        raise Exception(e)
                    message = e.args[0]
                    #raise Exception(e)
                    problems.append(message)

        except IndexError:
            problems.append("<b>Macro<\b> is missing!")
            self.setStyleSheet("")
            self.setToolTip('<br>'.join(problems))
            return
        self.currentIndex = Qt.QModelIndex()
        ix = self.getIndex()
        self.currentIndex = ix
        counter = 1

        while not ix == Qt.QModelIndex():
            try:
                propValue = mlist[counter]
                try:
                    self.validateOneValue(propValue)
                    self.model().setData(self.currentIndex, propValue)
                except Exception as e:
                    self.model().setData(self.currentIndex, 'None')
                    txt = str(ix.sibling(ix.row(), 0).data())
                    message = "<b>" + txt + "</b> " + e.args[0]
                    problems.append(message)
            except IndexError:
                txt = str(ix.sibling(ix.row(), 0).data())
                problems.append("<b>" + txt + "</b> is missing!")

                data = str(ix.data())
                if data != 'None':
                    self.model().setData(self.currentIndex, 'None')
                else:
                    self.model().setData(self.currentIndex, None)
            counter += 1
            ix = self.getIndex()
            self.currentIndex = ix

        if len(mlist) > counter:  # if there are more values than parameters
            repeatNode = None
            for i in self.model().root().params():
                repeatNode = i
                if isinstance(repeatNode, macro.RepeatParamNode):
                    index = self.findParamRepeat(i)
                    self.currentIndex = self.model()._insertRow(index)
                    nn = self.model().nodeFromIndex(self.currentIndex)
                    self.expandTree.emit()
                    ix = self.getIndex()
                    if not secValidation:
                        self.validateAllExpresion(True)
                        return

                repeatNode = None
            if repeatNode is None:
                problems.append("Too many values.")

        elif counter - len(mlist) >= 1:
            repeatNode = None
            node = None
            for i in self.model().root().params():
                repeatNode = i
                if isinstance(repeatNode, macro.RepeatParamNode):
                    index = self.findParamRepeat(i)
                    node = self.model().nodeFromIndex(index)
                    sub = len(node.child(0))
                    break
                repeatNode = None

            if repeatNode is not None:
                while counter - len(mlist) > sub - 1:
                    if len(node.children()) == 1 and node.isReachedMin():
                        break
                    self.model()._removeRow(index.child(len(node.children()) - 1, 0))
                    counter -= sub

                if not secValidation:
                    self.validateAllExpresion(True)
                    return

        if len(problems) == 0:
            self.setStyleSheet('SpockCommandWidget {background-color: %s; color: %s; border: %s; border-radius: %s}' % (
                'yellow', 'black', '3px solid green', '5px'))
            self.setToolTip("")
        else:
            self.setStyleSheet("")
            self.setToolTip('<br>'.join(problems))
        return

    def findParamRepeat(self, repeatNode):
        # Method which finds index of given ParamRepeatNode in the macro.
        children = self.model().root().children()
        occ = children.count(repeatNode)
        idx = 0
        for i in range(0, occ):
            idx = children.index(repeatNode, idx)
        index = self.model().index(idx, 0, Qt.QModelIndex())
        return index

    def validateOneValue(self, value):
        # Validates value of a SingleParamNode of a currentIndex
        paramNode = deepcopy(self.model().nodeFromIndex(self.currentIndex))
        paramNode.setValue(value)
        return self.getModelObj().validateSingleParam(paramNode)

    def onReturnPressed(self):
        # SLOT called when return is pressed
        if self.toolTip() == "":
            self.pressedReturn.emit()
        else:
            raise Exception(
                "Cannot start macro. Please correct following mistakes: <br>" + self.toolTip())

    def onTextChanged(self, strs):
        # SLOT called when QLineEdit text is changed
        if strs == "":
            self.updateMacroEditor("")

        if not self.disableEditMode and self.disableSpockCommandUpdate:
            self.validateAllExpresion()
        else:
            txt_parts = str(self.text()).split()
            if len(txt_parts) == 0:
                return
            try:
                if self.validateMacro(txt_parts[0]):
                    self.validateAllExpresion()
            except:
                self.setToolTip("Read Mode")

    def validateMacro(self, value):
        # Method which ivestigates if the macro can be edited using yellow line.
        # It cannot be executed when: 1. there are more than 1 ParamRepeatNodes,
        # 2. There is a ParamRepeatNode inside ParamRepeatNodem
        # 3. After ParamRepeatNode there are other nodes

        macroNode = self.getModelObj().getMacroNodeObj(str(value))
        if macroNode is None:
            return False
        t = [child for child in macroNode.children() if isinstance(child,
                                                                   macro.RepeatParamNode)]
        if len(t) > 1:
            self.disableEditMode = True
            raise Exception(
                'Macro <b> %s </b> cannot be edited using yellow line.<br>It contains more than 1 paramRepeat node. <br>Please use Macro Editor Widget to edit and execute this macro.' % str(value))
        elif len(t) == 1:
            if len([child for child in t[0].children() if isinstance(child, macro.RepeatParamNode)]) > 0:
                self.disableEditMode = True
                raise Exception(
                    'Macro <b> %s </b> cannot be edited using yellow line.<br>It contains paramRepeat node inside paramRepeat node. <br>Please use Macro Editor Widget to edit and execute this macro.' % str(value))
            else:
                if macroNode.children().index(t[0]) != len(macroNode.children()) - 1:
                    self.disableEditMode = True
                    raise Exception(
                        'Macro <b> %s </b> cannot be edited using yellow line.<br>It contains paramRepeat node but not as a last parameter. <br>Please use Macro Editor Widget to edit and execute this macro.' % str(value))
        self.disableEditMode = False
        return True

    def downAction(self):
        # Goes down in the history list of executed macros.
        # self.disableSpockCommandUpdate flag is used to allow updating yellow
        # line when model is changed. (when new row in history is chosen)

        self.disableSpockCommandUpdate = False
        self.elementDown.emit()
        text = str(self.text()).split()
        if len(text) > 0:
            self.validateMacro(text[0])
        self.disableSpockCommandUpdate = True

    def upAction(self):
        self.disableSpockCommandUpdate = False
        self.elementUp.emit()
        text = str(self.text()).split()
        if len(text) > 0:
            self.validateMacro(text[0])
        self.disableSpockCommandUpdate = True

    def controlDownAction(self):
        c = self.cursorPosition()
        newValue = False
        try:
            if self.text()[c] == " " and self.text()[c - 1] == " ":
                newValue = True
        except IndexError:
            if c == 0:
                newValue = True
            elif len(self.text()) == self.cursorPosition() and self.text()[c - 1] == " ":
                newValue = True
        try:
            txt = str(self.text())
            txt = txt[:txt.find(" ", c)]
        except IndexError:
            txt = str(self.text())[:c]
        elementsNum = txt.split()

        if newValue:
            self.insert("0")
            self.currentIndex = self.getIndex(len(elementsNum))
            if not self.currentIndex.isValid():
                if len(elementsNum) > 0:
                    self.backspace()
                    return
            value = self.prevValue("")
            self.backspace()
            self.insert(value)
            self.model().setData(self.currentIndex, value)
        else:
            self.currentIndex = self.getIndex(len(elementsNum) - 1)
            if not self.currentIndex.isValid():
                if len(elementsNum) > 1:
                    return
            value = self.prevValue(elementsNum[len(elementsNum) - 1])
            sel = self.measureSelection(self.cursorPosition())
            self.setSelection(sel[0], sel[1])
            c = c - (sel[1] - len(str(value)))
            self.insert(value)
            self.setCursorPosition(c)
            self.model().setData(self.currentIndex, value)

    def controlUpAction(self):
        c = self.cursorPosition()
        newValue = False
        try:
            if self.text()[c] == " " and self.text()[c - 1] == " ":
                newValue = True
        except IndexError:
            if c == 0:
                newValue = True
            elif len(self.text()) == self.cursorPosition() and self.text()[c - 1] == " ":
                newValue = True
        try:
            txt = str(self.text())
            txt = txt[:txt.find(" ", c)]
        except IndexError:
            txt = str(self.text())[:c]
        elementsNum = txt.split()

        if newValue:
            self.insert("0")
            self.currentIndex = self.getIndex(len(elementsNum))
            if not self.currentIndex.isValid():
                if len(elementsNum) > 0:
                    self.backspace()
                    return
            value = self.nextValue("")
            self.backspace()
            self.insert(value)
            self.model().setData(self.currentIndex, value)
        else:
            self.currentIndex = self.getIndex(len(elementsNum) - 1)
            if not self.currentIndex.isValid():
                if len(elementsNum) > 1:
                    return
            value = self.nextValue(elementsNum[len(elementsNum) - 1])
            sel = self.measureSelection(self.cursorPosition())
            self.setSelection(sel[0], sel[1])
            c = c - (sel[1] - len(str(value)))
            self.insert(value)
            self.setCursorPosition(c)
            self.model().setData(self.currentIndex, value)

    def getParamItems(self, index):
        # Returns list of items that can be chosen for the node corresponding
        # to the given index. Used by {next,prev}Value methods

        node = self.model().nodeFromIndex(index)
        if isinstance(node, macro.MacroNode):
            return None
        type = node.type()
        ms = self.getParentModelObj()
        items = list(ms.getElementsWithInterface(type).keys())
        return items, type

    def nextValue(self, current):
        current = str(current)
        if self.currentIndex.isValid():
            items, type = self.getParamItems(self.currentIndex)
            items = sorted(items)
        else:
            items = self.getParentModelObj().getMacroStrList()
            items = sorted(items)
            type = "Macro"

        if type == "Float":
            value = float(current) + 0.1
        elif type == "Integer":
            value = int(current) + 1
        elif type == "Boolean":
            value = True
        else:
            try:
                textindex = items.index(current)
                value = items[textindex - 1]
            except:
                tmpitems = [s for s in items if s.startswith(current)]
                if len(tmpitems) > 0:
                    value = tmpitems[0]
                else:
                    value = items[0]
        return str(value)

    def prevValue(self, current):
        current = str(current)
        if self.currentIndex.isValid():
            items, type = self.getParamItems(self.currentIndex)
            items = sorted(items)
        else:
            items = self.getParentModelObj().getMacroStrList()
            items = sorted(items)
            type = "Macro"

        if type == "Float":
            value = float(current) - 0.1
        elif type == "Integer":
            value = int(current) - 1
        elif type == "Boolean":
            value = True
        else:
            try:
                textindex = items.index(current)
                value = items[textindex + 1]
            except:
                tmpitems = [s for s in items if s.startswith(current)]
                if len(tmpitems) > 0:
                    value = tmpitems[0]
                else:
                    value = items[0]
        return str(value)

    def updateMacroEditor(self, macroName):
        # I had to make the macroname lowered as macros in comboBox (with macros), has names with all letter low.
        # Because of that sometimes it was not loading macros in MacroEditor
        # TO FIX
        self.spockComboBox.emit(str(macroName).lower())

    def measureSelection(self, position):
        s = str(self.text()) + " "
        try:
            if s[position] == " ":
                position -= 1
        except IndexError:
            position -= 1
        end = s.find(' ', position)
        beg = s.rfind(' ', 0, position + 1)
        if end == -1:
            end = s.length() - 1
        return beg + 1, end - beg - 1  # returns the start and length of the value

    def focusInEvent(self, event):
        self.disableSpockCommandUpdate = True
        Qt.QLineEdit.focusInEvent(self, event)

    def focusOutEvent(self, event):
        self.disableSpockCommandUpdate = False
        Qt.QLineEdit.focusOutEvent(self, event)
Ejemplo n.º 48
0
 def rowCount(self, index=Qt.QModelIndex()):
     return len(self.curves)
Ejemplo n.º 49
0
 def setModel(self, model):
     self._model = model
     if isinstance(model, ParamEditorModel):
         self.setRootIndex(Qt.QModelIndex())
Ejemplo n.º 50
0
 def showCalendar(self, target):
     return
     self.qcalendar = Qt.QCalendarWidget()
     self.qcalendar.show()
Ejemplo n.º 51
0
    def setTable(self, model, filters=[]):
        ''' 
        This method  overrides TaurusPropTable.setTable(), which connects with TaurusClassTable
        This method fill the table with the names of properties and values for the device selected
        '''
        try:
            model = model and fandango.tango.parse_tango_model(str(model))
            if model is None:
                self.warning(
                    'VaccaPropTable.setTable(%s(%s)): MODEL NOT PARSABLE!' %
                    (type(model), model))
                return
            else:
                try:
                    model = model['device']
                except:
                    model = str(model)
                self.debug('VaccaPropTable.setTable(%s(%s))' %
                           (type(model), model))

            #TaurusPropTable.setTable(self,model)
            Qt.QObject.disconnect(self, Qt.SIGNAL("cellChanged(int,int)"),
                                  self.valueChanged)
            self.db = fandango.get_database()
            dev_name = str(model)
            self.list_prop = list(
                self.db.get_device_property_list(dev_name, '*'))
            neg = ['polled_attr'
                   ] + [f[1:] for f in filters if f.startswith('!')]
            pos = [f for f in filters if not f.startswith('!')]
            self.list_prop = [
                p for p in self.list_prop
                if (not pos or fandango.matchAny(pos, p))
                and not fandango.matchAny(neg, p)
            ]

            self.setRowCount(len(self.list_prop))
            for i in range(0, len(self.list_prop)):
                elem = self.list_prop[i]
                self.setText(elem, i, 0)
                self.dictionary = self.db.get_device_property(
                    dev_name, self.list_prop)
                self.debug('Getting %s properties: %s -> %s' %
                           (dev_name, self.list_prop, self.dictionary))
                value = self.dictionary[elem]
                self.debug('VaccaPropTable: property %s is type %s' %
                           (elem, type(value)))
                USE_TABLES = False
                if USE_TABLES: self.setPropertyValue(value, i, 1)
                else:
                    if not isinstance(value,
                                      str):  #not something like an string
                        #if isinstance(value,list):#type(value) is list:
                        heigh1 = len(value)
                        value = '\n'.join(
                            str(v) for v in value
                        )  # adding new lines in between elements in the list
                    self.setText(str(value), i, 1)

            self.updateStyle()
            self.dev_name = dev_name
            #self.dev_obj = taurus.Device(dev_name)
            self.setWindowTitle('%s Properties' % dev_name)
            self.resizeColumnsToContents()
            self.resizeRowsToContents()

        except:
            traceback.print_exc()
class CurvesAppearanceChooser(Qt.QWidget):
    """
    A plot_item for choosing plot appearance for one or more curves.
    The current curves properties are passed using the setCurves() method using
    a dictionary with the following structure::

        curvePropDict={name1:prop1, name2:prop2,...}

    where propX is an instance of :class:`CurveAppearanceProperties`
    When applying, a signal is emitted and the chosen properties are made
    available in a similar dictionary. """

    NAME_ROLE = Qt.Qt.UserRole

    controlChanged = Qt.pyqtSignal()
    curveAppearanceChanged = Qt.pyqtSignal(object, list)
    CurveTitleEdited = Qt.pyqtSignal('QString', 'QString')

    def __init__(self, parent=None, curvePropDict={}, showButtons=False,
                 autoApply=False, Y2Axis=None, curvePropAdapter=None):
        # try:
        super(CurvesAppearanceChooser, self).__init__(parent)
        self.loadUi()
        self.autoApply = autoApply
        self.sStyleCB.insertItems(0, sorted(NamedSymbolStyles.values()))
        self.lStyleCB.insertItems(0, list(NamedLineStyles.values()))
        self.cStyleCB.insertItems(0, list(NamedCurveStyles.values()))
        self.sColorCB.addItem("")
        self.lColorCB.addItem("")
        if not showButtons:
            self.applyBT.hide()
            self.resetBT.hide()
        for color in NamedColors:
            icon = self._colorIcon(color)
            self.sColorCB.addItem(icon, "", Qt.QColor(color))
            self.lColorCB.addItem(icon, "", Qt.QColor(color))
        self.__itemsDict = CaselessDict()
        self.setCurves(curvePropDict)
        # set the icon for the background button (stupid designer limitations
        # forces to do it programatically)
        self.bckgndBT.setIcon(Qt.QIcon(":color-fill.svg"))

        # connections.
        self.curvesLW.itemSelectionChanged.connect(self._onSelectedCurveChanged)
        self.curvesLW.itemChanged.connect(self._onItemChanged)
        self.applyBT.clicked.connect(self.onApply)
        self.resetBT.clicked.connect(self.onReset)
        self.sStyleCB.currentIndexChanged.connect(self._onSymbolStyleChanged)

        self.sStyleCB.currentIndexChanged.connect(self._onControlChanged)
        self.lStyleCB.currentIndexChanged.connect(self._onControlChanged)
        self.sColorCB.currentIndexChanged.connect(self._onControlChanged)
        self.lColorCB.currentIndexChanged.connect(self._onControlChanged)
        self.cStyleCB.currentIndexChanged.connect(self._onControlChanged)
        self.sSizeSB.valueChanged.connect(self._onControlChanged)
        self.lWidthSB.valueChanged.connect(self._onControlChanged)
        self.cAreaDSB.valueChanged.connect(self._onControlChanged)
        self.sFillCB.stateChanged.connect(self._onControlChanged)
        self.cFillCB.stateChanged.connect(self._onControlChanged)

        self.assignToY1BT.toggled[bool].connect(self.__onY1Toggled)
        self.assignToY2BT.toggled[bool].connect(self.__onY2Toggled)

        # self.bckgndBT.clicked.connect(self.changeBackgroundColor)

        # Disabled buttons until future implementations
        # (set background color and set curve labels)
        self.changeTitlesBT.setEnabled(False)
        self.bckgndBT.setEnabled(False)

        # disable the group box with the options for swap curves between Y axes
        if Y2Axis is None:
            self.groupBox.setEnabled(False)

        # set properties from curves for first launch of config dialog and
        # keeps a curvePropAdapter object
        self._onSelectedCurveChanged()
        self.curvePropAdapter = curvePropAdapter
        self.axis = None

    def __onY1Toggled(self, checked):
        if checked:
            self.assignToY2BT.setChecked(False)

    def __onY2Toggled(self, checked):
        if checked:
            self.assignToY1BT.setChecked(False)

    def changeBackgroundColor(self):
        """Launches a dialog for choosing the parent's canvas background color
        """
        color = Qt.QColorDialog.getColor(
            self.curvePropAdapter.getBackgroundColor(), self)
        if Qt.QColor.isValid(color):
            self.curvePropAdapter.setBackgroundColor(color)

    def setCurves(self, curvePropDict):
        """Populates the list of curves from the properties dictionary. It uses
        the curve title for display, and stores the curve name as the item data
        (with role=CurvesAppearanceChooser.NAME_ROLE)

        :param curvePropDict:  (dict) a dictionary whith keys=curvenames and
                               values= :class:`CurveAppearanceProperties`
                               object
        """
        self.curvePropDict = curvePropDict
        self._curvePropDictOrig = copy.deepcopy(curvePropDict)
        self.curvesLW.clear()
        self.__itemsDict = CaselessDict()
        for name, prop in self.curvePropDict.items():
            # create and insert the item
            item = Qt.QListWidgetItem(prop.title, self.curvesLW)
            self.__itemsDict[name] = item
            item.setData(self.NAME_ROLE, name)
            item.setToolTip("<b>Curve Name:</b> %s" % name)
            item.setFlags(Qt.Qt.ItemIsEnabled | Qt.Qt.ItemIsSelectable |
                          Qt.Qt.ItemIsUserCheckable | Qt.Qt.ItemIsDragEnabled |
                          Qt.Qt.ItemIsEditable)
        self.curvesLW.setCurrentRow(0)

    def _onItemChanged(self, item):
        """slot used when an item data has changed"""
        name = item.data(self.NAME_ROLE)
        previousTitle = self.curvePropDict[name].title
        currentTitle = item.text()
        if previousTitle != currentTitle:
            self.curvePropDict[name].title = currentTitle
            self.CurveTitleEdited.emit(name, currentTitle)

    def updateTitles(self, newTitlesDict=None):
        """
        Updates the titles of the curves that are displayed in the curves list.

        :param newTitlesDict: (dict<str,str>) dictionary with key=curve_name
                                and value=title
        """
        if newTitlesDict is None:
            return
        for name, title in newTitlesDict.items():
            self.curvePropDict[name].title = title
            self.__itemsDict[name].setText(title)

    def getSelectedCurveNames(self):
        """Returns the curve names for the curves selected at the curves list.

        *Note*: The names may differ from the displayed text, which
        corresponds to the curve titles (this method is what you likely need if
        you want to get keys to use in curves or curveProp dicts).

        :return: (string_list) the names of the selected curves
        """
        return [item.data(self.NAME_ROLE)
                for item in self.curvesLW.selectedItems()]

    def showProperties(self, prop=None):
        """Updates the dialog to show the given properties.

        :param prop: (CurveAppearanceProperties) the properties object
                     containing what should be shown. If a given property is
                     set to CONFLICT, the corresponding plot_item will show a
                     "neutral" display
        """

        if prop is None:
            prop = self._shownProp
        # set the Style comboboxes
        self.sStyleCB.setCurrentIndex(
            self.sStyleCB.findText(NamedSymbolStyles[prop.sStyle]))
        self.lStyleCB.setCurrentIndex(
            self.lStyleCB.findText(NamedLineStyles[prop.lStyle]))
        self.cStyleCB.setCurrentIndex(
            self.cStyleCB.findText(NamedCurveStyles[prop.cStyle]))

        if prop.y2 is CONFLICT:
            self.assignToY1BT.setChecked(False)
            self.assignToY2BT.setChecked(False)
        elif prop.y2:
            self.assignToY2BT.setChecked(True)
        else:
            self.assignToY1BT.setChecked(True)

        # set sSize and lWidth spinboxes. if prop.sSize is None, it puts -1
        # (which is the special value for these switchhboxes)
        if prop.sSize is CONFLICT or prop.sStyle is None:
            self.sSizeSB.setValue(-1)
        else:
            self.sSizeSB.setValue(max(prop.sSize, -1))
        if prop.lWidth is CONFLICT:
            self.lWidthSB.setValue(-1)
        else:
            self.lWidthSB.setValue(max(prop.lWidth, -1))

        # Set the Color combo boxes. The item at index 0 is the empty one in
        # the comboboxes Manage unknown colors by including them
        if prop.sColor in (None, CONFLICT) or prop.sStyle is None:
            index = 0
        else:
            index = self.sColorCB.findData(Qt.QColor(prop.sColor))
        if index == -1:  # if the color is not supported, add it to combobox
            index = self.sColorCB.count()
            self.sColorCB.addItem(self._colorIcon(
                Qt.QColor(prop.sColor)), "", Qt.QColor(prop.sColor))
        self.sColorCB.setCurrentIndex(index)
        if prop.lColor is None or prop.lColor is CONFLICT:
            index = 0
        else:
            index = self.lColorCB.findData(Qt.QColor(prop.lColor))
        if index == -1:  # if the color is not supported, add it to combobox
            index = self.lColorCB.count()
            self.lColorCB.addItem(self._colorIcon(
                Qt.QColor(prop.lColor)), "", Qt.QColor(prop.lColor))
        self.lColorCB.setCurrentIndex(index)
        # set the Fill Checkbox. The prop.sFill value can be in 3 states: True,
        # False and None
        if prop.sFill is None or prop.sFill is CONFLICT:
            checkState = Qt.Qt.PartiallyChecked
        elif prop.sFill:
            checkState = Qt.Qt.Checked
        else:
            checkState = Qt.Qt.Unchecked
        self.sFillCB.setCheckState(checkState)
        # set the Area Fill Checkbox. The prop.cFill value can be in 3 states:
        # True, False and None
        if prop.cFill is CONFLICT:
            checkState = Qt.Qt.PartiallyChecked
            self.cAreaDSB.setValue(0.0)
        elif prop.cFill is None:
            checkState = Qt.Qt.Unchecked
            self.cAreaDSB.setValue(0.0)
        else:
            checkState = Qt.Qt.Checked
            self.cAreaDSB.setValue(prop.cFill)
        self.cFillCB.setCheckState(checkState)

    def _onControlChanged(self, *args):
        """
        Slot to be called whenever a control plot_item is changed. It emits a
        `controlChanged` signal and applies the change if in autoapply mode.
        It ignores any arguments passed
        """

        self.controlChanged.emit()
        if self.autoApply:
            self.onApply()

    def _onSelectedCurveChanged(self):
        """Updates the shown properties when the curve selection changes"""
        plist = [self.curvePropDict[name]
                 for name in self.getSelectedCurveNames()]
        if len(plist) == 0:
            plist = [CurveAppearanceProperties()]
            self.lineGB.setEnabled(False)
            self.symbolGB.setEnabled(False)
            self.otherGB.setEnabled(False)
        else:
            self.lineGB.setEnabled(True)
            self.symbolGB.setEnabled(True)
            self.otherGB.setEnabled(True)

        self._shownProp = CurveAppearanceProperties.merge(plist)
        self.showProperties(self._shownProp)

    def _onSymbolStyleChanged(self, text):
        """Slot called when the Symbol style is changed, to ensure that symbols
        are visible if you choose them

        :param text: (str) the new symbol style label
        """
        text = str(text)
        if self.sSizeSB.value() < 2 and not text in ["", "No symbol"]:
            # a symbol size of 0 is invisible and 1 means you should use
            # cStyle=dots
            self.sSizeSB.setValue(3)

    def getShownProperties(self):
        """Returns a copy of the currently shown properties and updates
        self._shownProp

        :return: (CurveAppearanceProperties)
        """
        prop = CurveAppearanceProperties()

        for name in self.getSelectedCurveNames():
            prop.title = self.curvePropDict[name].title

        # get the values from the Style comboboxes. Note that the empty string
        # ("") translates into CONFLICT
        prop.sStyle = ReverseNamedSymbolStyles[
            str(self.sStyleCB.currentText())]
        prop.lStyle = ReverseNamedLineStyles[str(self.lStyleCB.currentText())]
        prop.cStyle = ReverseNamedCurveStyles[str(self.cStyleCB.currentText())]
        # get sSize and lWidth from the spinboxes (-1 means conflict)
        v = self.sSizeSB.value()
        if v == -1:
            prop.sSize = CONFLICT
        else:
            prop.sSize = v
        v = self.lWidthSB.value()
        if v == -1:
            prop.lWidth = CONFLICT
        else:
            prop.lWidth = v
        # Get the Color combo boxes. The item at index 0 is the empty one in
        # the comboboxes
        index = self.sColorCB.currentIndex()
        if index == 0:
            prop.sColor = CONFLICT
        else:
            prop.sColor = Qt.QColor(self.sColorCB.itemData(index))
        index = self.lColorCB.currentIndex()
        if index == 0:
            prop.lColor = CONFLICT
        else:
            prop.lColor = Qt.QColor(self.lColorCB.itemData(index))
        # get the sFill from the Checkbox.
        checkState = self.sFillCB.checkState()
        if checkState == Qt.Qt.PartiallyChecked:
            prop.sFill = CONFLICT
        else:
            prop.sFill = bool(checkState)
        # get the cFill from the Checkbox.
        checkState = self.cFillCB.checkState()
        if checkState == Qt.Qt.PartiallyChecked:
            prop.cFill = CONFLICT
        elif checkState == Qt.Qt.Checked:
            prop.cFill = self.cAreaDSB.value()
        else:
            prop.cFill = None

        # get the y2 state from the buttons
        y1 = self.assignToY1BT.isChecked()
        y2 = self.assignToY2BT.isChecked()
        if not y1 and not y2:
            prop.y2 = CONFLICT
        elif y1:
            prop.y2 = False
        elif y2:
            prop.y2 = True
        else:
            # both buttons should never be checked simultaneously
            raise RuntimeError('Inconsistent state of Y-axis buttons')

        # store the props
        self._shownProp = copy.deepcopy(prop)
        return copy.deepcopy(prop)

    def onApply(self):
        """Apply does 2 things:

            - It updates `self.curvePropDict` using the current values
              chosen in the dialog
            - It emits a curveAppearanceChanged signal that indicates the names
              of the curves that changed and the new properties.  (TODO)

        :return: (tuple<CurveAppearanceProperties,list>) a tuple containing the
                 curve properties and a list of the selected curve names (as a
                 list<str>)
        """
        names = self.getSelectedCurveNames()
        prop = self.getShownProperties()
        # Update self.curvePropDict for selected properties
        for n in names:
            self.curvePropDict[n] = CurveAppearanceProperties.merge(
                [self.curvePropDict[n], prop],
                conflict=CurveAppearanceProperties.inConflict_update_a)
        # emit a (PyQt) signal telling what properties (first argument) need to
        # be applied to which curves (second argument)
        # self.curveAppearanceChanged.emit(prop, names)
        # return both values

        self.curvePropAdapter.setCurveProperties(self.curvePropDict, names)
        return prop, names

    def onReset(self):
        """slot to be called when the reset action is triggered. It reverts to
        the original situation"""
        self.setCurves(self._curvePropDictOrig)
        self.curvesLW.clearSelection()

    def _colorIcon(self, color, w=10, h=10):
        # to do: create a border
        pixmap = Qt.QPixmap(w, h)
        pixmap.fill(Qt.QColor(color))
        return Qt.QIcon(pixmap)
Ejemplo n.º 53
0
    def __init__(self, parent=None, flags=Qt.Qt.WindowFlags()):
        self.parent = parent
        # if parent==None or not isinstance(parent, TaurusPlotConfigCapable):
        #    raise NotImplementedError, "Parent object doesn't implement TaurusPlotConfigCapable class"
        # call qt designer generated functions to initialize GUI
        Qt.QDialog.__init__(self, parent, flags)
        self.loadUi()

        # insert the CurvesAppearanceWidget
        #(@TODO:must be changed to be done directly in the ui, but I couldn't make the widget available to TaurusDesigner)
        from curvesAppearanceChooserDlg import CurvesAppearanceChooser
        layout = Qt.QVBoxLayout()
        self.curvesAppearanceChooser = CurvesAppearanceChooser(None)
        layout.addWidget(self.curvesAppearanceChooser)
        self.ui.curveAppearanceGB.setLayout(layout)

        # set the values for the CurvesAppearanceChooser
        self.curvesAppearanceChooser.setCurves(
            self.parent.getCurveAppearancePropertiesDict())

        # insert valid values into mode combobox (linear or logarihtmic) and
        # set selected one in combobox
        self.ui.xModeComboBox.insertItem(0, "Linear")
        self.ui.xModeComboBox.insertItem(1, "Logarithmic")
        self.ui.y1ModeComboBox.insertItem(0, "Linear")
        self.ui.y1ModeComboBox.insertItem(1, "Logarithmic")
        self.ui.y2ModeComboBox.insertItem(0, "Linear")
        self.ui.y2ModeComboBox.insertItem(1, "Logarithmic")

        # insert valid values into peaks combobox (max, min or both) and set
        # selected one in combobox
        self.ui.peaksComboBox.insertItem(0, "Both")
        self.ui.peaksComboBox.insertItem(1, "Max")
        self.ui.peaksComboBox.insertItem(2, "Min")
        self.ui.peaksComboBox.insertItem(3, "None")

        # Init X axis group
        self.ui.xRangeCB.setVisible(False)
        self.ui.xLabelRange.setVisible(False)
        if self.parent.getXIsTime():
            # adapt the X axis group for time-based measurements
            self.ui.xRangeCB.addItems(
                ["", "1 m", "1 h", "1 d", "1 w", "30 d", "1 y"])
            self.ui.xGroupBox.setTitle("Time")
            self.ui.xLabelMin.setText("Start")
            self.ui.xLabelMax.setText("End")
            timetooltip = """It accepts both absolute data-times (e.g. "25/10/1917 21:45:01") \n"""\
                """or relative ones with format <+|-><number><s|m|h|d|w|y> (e.g. "-12h").\n"""\
                """The keyword "now" is also accepted."""
            self.ui.xEditMin.setToolTip(timetooltip)
            self.ui.xEditMax.setToolTip(timetooltip)
        else:
            # The default settings are ok for non-time plots
            self.ui.xEditMin.setValidator(Qt.QDoubleValidator(self))
            self.ui.xEditMax.setValidator(Qt.QDoubleValidator(self))
            self.ui.xRangeCB.setValidator(Qt.QDoubleValidator(self))
            self.ui.xRangeCB.addItems(
                ["", "10", "100", "1000", "10000", "100000", "1000000"])

        self.ui.xDynScaleCheckBox.setChecked(self.parent.getXDynScale())
        auto = self.parent.axisAutoScale(Qwt5.QwtPlot.xBottom)
        self.ui.xAutoGroupBox.setChecked(not auto)

        # this call already initialises the edit boxes of the X axis
        self.setXDynScale(self.parent.getXDynScale())
        self.ui.xDynScaleCheckBox.setVisible(
            self.parent.isXDynScaleSupported())

        # Init Y axes groups
        self._populateYAxisScales()
        self.ui.y1AutoGroupBox.setChecked(
            not self.parent.axisAutoScale(Qwt5.QwtPlot.yLeft))
        self.ui.y2AutoGroupBox.setChecked(
            not self.parent.axisAutoScale(Qwt5.QwtPlot.yRight))

        # set validators for Y min/max edits
        self.ui.y1EditMin.setValidator(Qt.QDoubleValidator(self))
        self.ui.y1EditMax.setValidator(Qt.QDoubleValidator(self))
        self.ui.y2EditMin.setValidator(Qt.QDoubleValidator(self))
        self.ui.y2EditMax.setValidator(Qt.QDoubleValidator(self))

        # populate initial axis mode (linear or logarithmic) values from plot. Warning!: we're using
        # qwt QwtPlot.axis enum type to relate our GUI combo name and qwt axis
        # name (enum type).
        axes = [
            self.ui.y1ModeComboBox, self.ui.y2ModeComboBox,
            self.ui.xModeComboBox
        ]
        for axis in range(len(axes)):
            scaleType = self.parent.getAxisTransformationType(axis)
            if scaleType == Qwt5.QwtScaleTransformation.Linear:
                axes[axis].setCurrentIndex(0)
            elif scaleType == Qwt5.QwtScaleTransformation.Log10:
                axes[axis].setCurrentIndex(1)
            else:
                raise TypeError, "TaurusPlotConfigDialog::__init__(): unexpected axis scale type (linear or logarihtmic expected)"
        self.ui.xModeComboBox.setEnabled(not self.parent.getXIsTime())

        # determine which axes are visible
        if not self.parent.axisEnabled(Qwt5.QwtPlot.xBottom):
            self.ui.xGroupBox.setVisible(False)

        # populate initial peaks from parent
        if self.parent._showMaxPeaks and self.parent._showMinPeaks:
            self.ui.peaksComboBox.setCurrentIndex(0)
        elif self.parent._showMaxPeaks:
            self.ui.peaksComboBox.setCurrentIndex(1)
        elif self.parent._showMinPeaks:
            self.ui.peaksComboBox.setCurrentIndex(2)
        else:
            self.ui.peaksComboBox.setCurrentIndex(3)

        # connect signals
        self.ui.buttonBox.button(Qt.QDialogButtonBox.Close).clicked.connect(
            self.hide)
        self.ui.buttonBox.button(Qt.QDialogButtonBox.Apply).clicked.connect(
            self.apply)
        self.ui.xAutoGroupBox.toggled.connect(self.toggledAutoScale)
        self.ui.y1AutoGroupBox.toggled.connect(self.toggledAutoScale)
        self.ui.y2AutoGroupBox.toggled.connect(self.toggledAutoScale)
        #        self.connect(self.ui.xEditMin,  Qt.SIGNAL("returnPressed()"),self.apply)
        #        self.connect(self.ui.xEditMax,  Qt.SIGNAL("returnPressed()"),self.apply)
        #        self.connect(self.ui.y1EditMin, Qt.SIGNAL("returnPressed()"),self.apply)
        #        self.connect(self.ui.y1EditMax, Qt.SIGNAL("returnPressed()"),self.apply)
        #        self.connect(self.ui.y2EditMin, Qt.SIGNAL("returnPressed()"),self.apply)
        #        self.connect(self.ui.y2EditMax, Qt.SIGNAL("returnPressed()"),self.apply)
        self.ui.xModeComboBox.currentIndexChanged.connect(
            self.modeComboChanged)
        self.ui.xDynScaleCheckBox.toggled.connect(self.setXDynScale)
        #self.connect(self.ui.xRangeCB, Qt.SIGNAL("currentIndexChanged(const QString&)"),self.apply)
        self.ui.y1ModeComboBox.currentIndexChanged.connect(
            self.modeComboChanged)
        self.ui.y2ModeComboBox.currentIndexChanged.connect(
            self.modeComboChanged)
        self.ui.peaksComboBox.currentIndexChanged.connect(
            self.peaksComboChanged)
        # self.connect(self.curvesAppearanceChooser,
        # Qt.SIGNAL("controlChanged"),self.apply) #"autoapply" mode for *all*
        # the curve appearance controls
        self.curvesAppearanceChooser.assignToY1BT.clicked[()].connect(
            self.setCurvesYAxis)
        self.curvesAppearanceChooser.assignToY2BT.clicked[()].connect(
            self.setCurvesYAxis)
        self.curvesAppearanceChooser.bckgndBT.clicked.connect(
            self.changeBackgroundColor)
        self.curvesAppearanceChooser.changeTitlesBT.clicked.connect(
            self.onChangeTitles)
        self.curvesAppearanceChooser.CurveTitleEdited.connect(
            self.onCurveTitleEdited)

        # finally adjust size
        self.adjustSize()
    def __init__(self, parent=None, curvePropDict={}, showButtons=False,
                 autoApply=False, Y2Axis=None, curvePropAdapter=None):
        # try:
        super(CurvesAppearanceChooser, self).__init__(parent)
        self.loadUi()
        self.autoApply = autoApply
        self.sStyleCB.insertItems(0, sorted(NamedSymbolStyles.values()))
        self.lStyleCB.insertItems(0, list(NamedLineStyles.values()))
        self.cStyleCB.insertItems(0, list(NamedCurveStyles.values()))
        self.sColorCB.addItem("")
        self.lColorCB.addItem("")
        if not showButtons:
            self.applyBT.hide()
            self.resetBT.hide()
        for color in NamedColors:
            icon = self._colorIcon(color)
            self.sColorCB.addItem(icon, "", Qt.QColor(color))
            self.lColorCB.addItem(icon, "", Qt.QColor(color))
        self.__itemsDict = CaselessDict()
        self.setCurves(curvePropDict)
        # set the icon for the background button (stupid designer limitations
        # forces to do it programatically)
        self.bckgndBT.setIcon(Qt.QIcon(":color-fill.svg"))

        # connections.
        self.curvesLW.itemSelectionChanged.connect(self._onSelectedCurveChanged)
        self.curvesLW.itemChanged.connect(self._onItemChanged)
        self.applyBT.clicked.connect(self.onApply)
        self.resetBT.clicked.connect(self.onReset)
        self.sStyleCB.currentIndexChanged.connect(self._onSymbolStyleChanged)

        self.sStyleCB.currentIndexChanged.connect(self._onControlChanged)
        self.lStyleCB.currentIndexChanged.connect(self._onControlChanged)
        self.sColorCB.currentIndexChanged.connect(self._onControlChanged)
        self.lColorCB.currentIndexChanged.connect(self._onControlChanged)
        self.cStyleCB.currentIndexChanged.connect(self._onControlChanged)
        self.sSizeSB.valueChanged.connect(self._onControlChanged)
        self.lWidthSB.valueChanged.connect(self._onControlChanged)
        self.cAreaDSB.valueChanged.connect(self._onControlChanged)
        self.sFillCB.stateChanged.connect(self._onControlChanged)
        self.cFillCB.stateChanged.connect(self._onControlChanged)

        self.assignToY1BT.toggled[bool].connect(self.__onY1Toggled)
        self.assignToY2BT.toggled[bool].connect(self.__onY2Toggled)

        # self.bckgndBT.clicked.connect(self.changeBackgroundColor)

        # Disabled buttons until future implementations
        # (set background color and set curve labels)
        self.changeTitlesBT.setEnabled(False)
        self.bckgndBT.setEnabled(False)

        # disable the group box with the options for swap curves between Y axes
        if Y2Axis is None:
            self.groupBox.setEnabled(False)

        # set properties from curves for first launch of config dialog and
        # keeps a curvePropAdapter object
        self._onSelectedCurveChanged()
        self.curvePropAdapter = curvePropAdapter
        self.axis = None
Ejemplo n.º 55
0
class MacroSequenceTree(Qt.QTreeView, BaseConfigurableClass):

    macroNameChanged = Qt.pyqtSignal('QString')
    macroChanged = Qt.pyqtSignal(compat.PY_OBJECT)

    def __init__(self, parent=None):
        Qt.QTreeView.__init__(self, parent)
        BaseConfigurableClass.__init__(self)
        self._idIndexDict = {}

        self.setSelectionBehavior(Qt.QTreeView.SelectRows)
        self.setSelectionMode(Qt.QTreeView.SingleSelection)
        self.setRootIsDecorated(False)
#        self.setItemsExpandable(False)
        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.setTabKeyNavigation(True)
        self.setEditTriggers(Qt.QAbstractItemView.EditKeyPressed |
                             Qt.QAbstractItemView.CurrentChanged)
        self.setDropIndicatorShown(True)

        self.deleteAction = Qt.QAction(
            Qt.QIcon.fromTheme("list-remove"), "Remove macro", self)
        self.deleteAction.triggered.connect(self.deleteMacro)
        self.deleteAction.setToolTip(
            "Clicking this button will remove current macro.")

        self.moveUpAction = Qt.QAction(Qt.QIcon.fromTheme("go-up"), "Move up",
                                       self)
        self.moveUpAction.triggered.connect(self.upMacro)
        self.moveUpAction.setToolTip(
            "Clicking this button will move current macro up.")

        self.moveDownAction = Qt.QAction(
            Qt.QIcon.fromTheme("go-down"), "Move down", self)
        self.moveDownAction.triggered.connect(self.downMacro)
        self.moveDownAction.setToolTip(
            "Clicking this button will move current macro down.")

        self.moveLeftAction = Qt.QAction(
            Qt.QIcon.fromTheme("go-previous"), "Move left", self)
        self.moveLeftAction.triggered.connect(self.leftMacro)
        self.moveLeftAction.setToolTip(
            "Clicking this button will move current macro to the left.")

        self.moveRightAction = Qt.QAction(
            Qt.QIcon.fromTheme("go-next"), "Move right", self)
        self.moveRightAction.triggered.connect(self.rightMacro)
        self.moveRightAction.setToolTip(
            "Clicking this button will move current macro to the right.")

    def disableActions(self):
        self.deleteAction.setEnabled(False)
        self.moveUpAction.setEnabled(False)
        self.moveDownAction.setEnabled(False)
        self.moveLeftAction.setEnabled(False)
        self.moveRightAction.setEnabled(False)

    def contextMenuEvent(self, event):
        contextMenu = Qt.QMenu()
        proxyIndex = self.indexAt(event.pos())
        node = self.model().nodeFromIndex(proxyIndex)
        # this is in case if we right click on an empty field of tree
        if not isinstance(node, MacroNode):
            return
        parentNode = node.parent()
        # this is in case if we right click on a top level macro
        if not isinstance(parentNode, MacroNode):
            return
        allowedHooks = parentNode.allowedHookPlaces()
        if allowedHooks:
            hookPlacesSubmenu = contextMenu.addMenu("Hook places")
            for allowedHook in allowedHooks:
                action = HookAction(allowedHook, self, node)
                hookPlacesSubmenu.addAction(action)
        contextMenu.exec_(event.globalPos())

#    def setHint(self, add):
#        action = self.sender()
#        hookText = action.text()
#        macroNode = action.macroNode()
#        if add:
#            macroNode.addHook(hookText)
#        else:
#            macroNode.removeHook(hookText)
#        pass

    def selectionChanged(self, selected, deselected):
        self.disableActions()
        macroName = None
        node, proxyIndex = self.selectedNodeAndIndex()
        if node is not None:
            macroName = node.name()
            self.deleteAction.setEnabled(True)
            self.moveUpAction.setEnabled(node.isAllowedMoveUp())
            self.moveDownAction.setEnabled(node.isAllowedMoveDown())
            self.moveLeftAction.setEnabled(node.isAllowedMoveLeft())
            self.moveRightAction.setEnabled(node.isAllowedMoveRight())
            sourceIndex = self.model().mapToSource(proxyIndex)
            self.macroChanged.emit(sourceIndex)
        self.macroNameChanged.emit(macroName)

    def expanded(self):
        for column in range(self.model().columnCount(Qt.QModelIndex())):
            self.resizeColumnToContents(column)

    def clearTree(self):
        self.model().clearSequence()

    def toXmlString(self, pretty=False, withId=True):
        return self.model().toXmlString(pretty=pretty, withId=withId)

    def fromXmlString(self, xmlString):
        newRoot = self.model().fromXmlString(xmlString)
        self.expandAll()
        self.expanded()
        return newRoot

    def fromPlainText(self, plainTextMacros, macroInfos):
        newRoot = self.model().fromPlainText(plainTextMacros, macroInfos)
        self.expandAll()
        self.expanded()
        return newRoot

    def root(self):
        return self.model().root()

    def setRoot(self, root):
        self.model().beginResetModel()
        self.model().setRoot(root)
        self.model().endResetModel()

    def addMacro(self, macroNode):
        node, proxyIndex = self.selectedNodeAndIndex()
        if node is None or not node.isAllowedHooks():
            proxyIndex = self.rootIndex()
        sourceIndex = self.model().mapToSource(proxyIndex)
        newSourceIndex = self.model()._insertRow(sourceIndex, macroNode)
        newProxyIndex = self.model().mapFromSource(newSourceIndex)
#        persistentProxyIndex = Qt.QPersistentModelIndex(newProxyIndex)
#        self._idIndexDict[macroNode.id()] = persistentProxyIndex
        self.setCurrentIndex(newProxyIndex)
        self.expandAll()
        self.expanded()

    def deleteMacro(self):
        node, proxyIndex = self.selectedNodeAndIndex()
        sourceIndex = self.model().mapToSource(proxyIndex)
        self.model()._removeRow(sourceIndex)
#        self._idIndexDict.pop(node.id())
        self.expandAll()
        self.expanded()

    def upMacro(self):
        node, proxyIndex = self.selectedNodeAndIndex()
        sourceIndex = self.model().mapToSource(proxyIndex)
        newSourceIndex = self.model()._upRow(sourceIndex)
        newProxyIndex = self.model().mapFromSource(newSourceIndex)
#        persistentProxyIndex = Qt.QPersistentModelIndex(newProxyIndex)
#        self._idIndexDict[node.id()] = persistentProxyIndex
        self.setCurrentIndex(newProxyIndex)
        self.expandAll()
#        self.expanded()

    def downMacro(self):
        node, proxyIndex = self.selectedNodeAndIndex()
        sourceIndex = self.model().mapToSource(proxyIndex)
        newSourceIndex = self.model()._downRow(sourceIndex)
        newProxyIndex = self.model().mapFromSource(newSourceIndex)
#        persistentProxyIndex = Qt.QPersistentModelIndex(newProxyIndex)
#        self._idIndexDict[node.id()] = persistentProxyIndex
        self.setCurrentIndex(newProxyIndex)
        self.expandAll()
#        self.expanded()

    def leftMacro(self):
        node, proxyIndex = self.selectedNodeAndIndex()
        sourceIndex = self.model().mapToSource(proxyIndex)
        newSourceIndex = self.model()._leftRow(sourceIndex)
        newProxyIndex = self.model().mapFromSource(newSourceIndex)
#        persistentProxyIndex = Qt.QPersistentModelIndex(newProxyIndex)
#        self._idIndexDict[node.id()] = persistentProxyIndex
        self.setCurrentIndex(newProxyIndex)
        self.expandAll()
        self.expanded()

    def rightMacro(self):
        node, proxyIndex = self.selectedNodeAndIndex()
        sourceIndex = self.model().mapToSource(proxyIndex)
        newSourceIndex = self.model()._rightRow(sourceIndex)
        newProxyIndex = self.model().mapFromSource(newSourceIndex)
#        persistentProxyIndex = Qt.QPersistentModelIndex(newProxyIndex)
#        self._idIndexDict[node.id()] = persistentProxyIndex
        self.setCurrentIndex(newProxyIndex)
        self.expandAll()
        self.expanded()

    def prepareMacroIds(self):
        model = self.model()
        ids = model.assignIds()
        firstId = model.firstMacroId()
        lastId = model.lastMacroId()
        return firstId, lastId, ids

    def prepareMacroProgresses(self):
        self._idIndexDict = self.model().createIdIndexDictionary()
        for macroId in self._idIndexDict.keys():
            self.setProgressForMacro(macroId, 0)

    def setProgressForMacro(self, macroId, progress):
        persistentIndex = self._idIndexDict.get(macroId, None)
        if persistentIndex is None:
            return
        progressIndex = persistentIndex.sibling(persistentIndex.row(), 2)
        index = Qt.QModelIndex(progressIndex)
        self.model().setData(index, progress)

    def setRangeForMacro(self, macroId, range):
        persistentIndex = self._idIndexDict.get(macroId, None)
        if persistentIndex is None:
            return
        index = Qt.QModelIndex(persistentIndex)
        node = self.model().nodeFromIndex(index)
        node.setRange(range)

    def selectedNodeAndIndex(self):
        """Returns a tuple with selected internal model node object and
        QModelIndex from current model."""
        for idx in self.selectedIndexes():
            if idx.column() == 0:
                node = self.model().nodeFromIndex(idx)
                break
        else:
            node, idx = None, None
        return node, idx

    def dropEvent(self, event):
        Qt.QTreeView.dropEvent(self, event)
        self.expandAll()
Ejemplo n.º 56
0
 def columnCount(self, index=Qt.QModelIndex()):
     return self.ncolumns
Ejemplo n.º 57
0
class TaurusJDrawSynopticsView(Qt.QGraphicsView, TaurusBaseWidget):
    '''
    Taurus Class that visualizes Synoptics drawn with the JDraw tool (by ESRF). It is equivalent to ATK Synoptic Player (Java).

    After initialization call setModel('/your/file.jdw') to parse the synoptic file and connect to controlled objects.

    Arguments to TaurusJDrawSynopticsView() creator are:

        - designMode; used by Qt Designer
        - updateMode; controls Qt Viewport refresh (disabled by default)
        - alias; a dictionary of name replacements to be applied on graphical objects
        - resizable: whether to allow resizing or not
        - panelClass: class object, class name or shell command to be shown when an object is clicked (None will show default panel, '' or 'noPanel' will disable it)

    TaurusJDrawSynopticsView and TaurusGraphicsScene signals/slots

    External events::

     Slot selectGraphicItem(const QString &) displays a selection
     mark around the TaurusGraphicsItem that matches the argument passed.

    Mouse Left-button events::

     Signal graphicItemSelected(QString) is triggered, passing the
     selected TaurusGraphicsItem.name() as argument.

    Mouse Right-button events::

     TaurusGraphicsItem.setContextMenu([(ActionName,ActionMethod(device_name))]
     allows to configure custom context menus for graphic items using a list
     of tuples. Empty tuples will insert separators in the menu.
    '''
    itemsChanged = Qt.pyqtSignal(str, dict)
    modelsChanged = Qt.pyqtSignal(list)
    graphicItemSelected = Qt.pyqtSignal('QString')
    graphicSceneClicked = Qt.pyqtSignal('QPoint')

    def __init__(self, parent=None, designMode=False, updateMode=None, alias=None, resizable=True, panelClass=None):
        name = self.__class__.__name__
        self.call__init__wo_kw(Qt.QGraphicsView, parent)
        self.call__init__(TaurusBaseWidget, name, designMode=designMode)
        self._currF = self.modelName
        self.path = ''
        self.w_scene = None
        self.h_scene = None
        self._fileName = "Root"
        self._mousePos = (0, 0)
        self._selectionStyle = SynopticSelectionStyle.OUTLINE
        self.setResizable(resizable)
        self.setInteractive(True)
        self.setAlias(alias)
        self.setDragEnabled(True)
        self.setPanelClass(panelClass)

        # By default the items will update the view when necessary.
        # This default value is much more efficient then the QQraphicsView default
        # value, so if you decide to change then expect a lot of processor to be
        # used by your application.
        if updateMode is None:
            self.setViewportUpdateMode(Qt.QGraphicsView.NoViewportUpdate)
        else:
            self.setViewportUpdateMode(updateMode)

    def defineStyle(self):
        self.updateStyle()

    #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
    # TaurusBaseWidget over writing
    #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-

    def isReadOnly(self):
        return True

    def update(self):
        # self.emit_signal()
        self.emitColors()

    def openJDraw(self):
        ifile = unicode(Qt.QFileDialog.getOpenFileName(
            self, 'Load JDraw File', '', 'JDraw File (*.jdw)'))
        if not ifile:
            return
        fileName = ifile.split("/")
        self._fileName = fileName[-1]
        self.setModel(ifile)
        return fileName[-1]

    def setAlias(self, alias):
        """ Assigning a dictionary like {'Tag':'Value'} with tags to be replaced in object names while parsing. """
        if (isinstance(alias, dict) or hasattr(alias, 'items')) and alias:
            self.alias = alias
        else:
            self.alias = None
        return

    def get_item_list(self):
        return [item._name for item in self.scene().items() if hasattr(item, '_name') and item._name]

    def get_device_list(self):
        items = [(item, parseTangoUri(item)) for item in self.get_item_list()]
        return list(set(v['_devslashname'] for k, v in items if v))

    def get_item_colors(self, emit=False):
        item_colors = {}
        try:
            for item in self.scene().items():
                if not getattr(item, '_name', '') or not getattr(item, '_currBgBrush', None):
                    continue
                item_colors[item._name] = item._currBgBrush.color().name()
            if emit:
                self.itemsChanged.emit(self.modelName.split(
                    '/')[-1].split('.')[0], item_colors)
        except:
            self.warning('Unable to emitColors: %s' % traceback.format_exc())
        return item_colors

    @Qt.pyqtSlot('QString')
    def selectGraphicItem(self, item_name):
        self.scene().selectGraphicItem(item_name)
        return False

    def _graphicItemSelected(self, item_name):
        self.debug(' => graphicItemSelected(QString)(%s)' % item_name)
        self.graphicItemSelected.emit(item_name)

    def _graphicSceneClicked(self, point):
        self.debug('In TaurusJDrawSynopticsView.graphicSceneClicked(%s,%s)' % (
            point.x(), point.y()))
        self.graphicSceneClicked.emit(point)

    def __modelsChanged(self):
        items = self.get_item_list()
        self.debug('modelsChanged(%s)' % len(items))
        self.modelsChanged.emit(items)

    def emitColors(self):
        '''emit signal which is used to refresh the tree and colors of icons depend of the current status in jdrawSynoptic'''
        self.get_item_colors(True)

    def get_sizes(self):
        srect = self.scene().sceneRect()
        sizes = [x for s in (self.size(), self.sizeHint(), srect.size())
                 for x in (s.width(), s.height())]
        try:
            s = self.parent().size()
            sizes.extend([s.width(), s.height()])
        except:
            sizes.extend([0, 0])
        return tuple(sizes)

    def fitting(self, ADJUST_FRAME=False):
        """
        Parent size is the size of the bigger panel (desn't keep ratio)
        Rect size never changes (fixed by the graphics objects)
        Size and SizeHint move one around the other

        the method works well until an object is clicked,
        then the whole reference changes and doesn't work again.
        """

        srect = self.scene().sceneRect()
        w, h = (srect.width(), srect.height())
        offset = self.mapToGlobal(Qt.QPoint(srect.x(), srect.y()))
        x0, y0 = (offset.x(), offset.y())

        self.debug('\n\nIn TauJDrawSynopticsView.fitting()')
        self.debug(self.get_sizes())
        self.debug(
            '\tAdjusting SizeHint: size(%s,%s),hint(%s,%s),srect(%s,%s),parent(%s,%s)' % self.get_sizes())
        self.debug('\toffset = %s,%s ; size = %s,%s' % (x0, y0, w, h))
        self.fitInView(x0, y0, w, h, Qt.Qt.KeepAspectRatio)

        # -------------------------------------------------------------------
        # This block seems to be a poorly executed workaround to some
        # issue, but it is itself causing bugs (see
        # https://github.com/taurus-org/taurus/issues/484 ).
        # We are not removing it yet to preserve bck-compat
        # TODO: Deprecate the ADJUST_FRAME kwarg?
        if ADJUST_FRAME:  # This additional resizing adjust the "white" frame around the synoptic
            self.debug(
                '\tResizing: size(%s,%s),hint(%s,%s),srect(%s,%s),parent(%s,%s)' % self.get_sizes())
            self.resize(self.sizeHint() + Qt.QSize(5, 5))
        # -------------------------------------------------------------------

        # THIS LINE MUST BE ALWAYS EXECUTED, It prevents the UP/DOWN resize BUG!!!
        # apparently Qt needs this 2 fitInView calls to be aware of it, maybe
        # first offset was not good
        self.debug(
            '\tFitting:: size(%s,%s),hint(%s,%s),srect(%s,%s),parent(%s,%s)' % self.get_sizes())
        self.fitInView(x0, y0, w, h, Qt.Qt.KeepAspectRatio)

        self.debug(
            'Done: size(%s,%s),hint(%s,%s),srect(%s,%s),parent(%s,%s)\n\n' % self.get_sizes())

    def resizeEvent(self, event):
        """ It has been needed to reimplent size policies """
        if not self.resizable() or not self.scene() or isinstance(self.parent(), Qt.QScrollArea) or not self.isVisible():
            self.debug('In TaurusJDrawSynopticsView(' +
                       self._fileName + ').resizeEvent(): Disabled')
            return
        try:
            self.debug('In TaurusJDrawSynopticsView(' +
                       self._fileName + ').resizeEvent()')
            if self.size() == self.sizeHint():
                self.debug('\tSize already fits: %s' % self.size())
                return
            self.setVerticalScrollBarPolicy(Qt.Qt.ScrollBarAlwaysOff)
            self.setHorizontalScrollBarPolicy(Qt.Qt.ScrollBarAlwaysOff)
            self.fitting()
            self.emitColors()
        except Exception:
            self.warning('Exception in JDrawView(' + self._fileName +
                         ').resizeEvent: %s' % traceback.format_exc())
            pass

    def refreshModel(self):
        self.setModel(self.getModelName())

    def updateStyle(self):
        self.repaint()

    def repaint(self):
        Qt.QGraphicsView.repaint(self)
        # self.fitting()

    def getGraphicsFactory(self, delayed=False):
        import jdraw
        # self.parent())
        return jdraw.TaurusJDrawGraphicsFactory(self, alias=(self.alias or None), delayed=delayed)

    ###########################################################################

    def getFramed(self):
        try:
            parent = self.parent()
        except:
            parent = None
        frame = Qt.QFrame(parent)
        self.setFrameStyle(self.StyledPanel | self.Raised)
        self.setLineWidth(2)
        self.setParent(frame)
        return frame

    def setResizable(self, resizable):
        self._resizable = resizable

    def resizable(self):
        return self._resizable

    def mousePressEvent(self, event):
        """ Records last event position to use it for DragEvents """
        try:
            self.mousePos = event.scenePos().x(), event.scenePos().y()
        except:
            self.mousePos = event.x(), event.y()
            self.debug('MouseEvent received is not a GraphicsScene event, using raw position %s' % str(
                self.mousePos))
        TaurusBaseWidget.mousePressEvent(self, event)

    def getModelMimeData(self):
        """ Used for drag events """
        model, mimeData = '', None
        try:
            #model = getattr(self.scene().itemAt(*self.mousePos),'_name','')
            selected = self.scene()._selectedItems
            if not selected:
                self.debug(
                    'jdrawView.getModelMimeData(%s): nothing to drag' % model)
                return
            model = getattr(([s for s in selected if s.isUnderMouse() and getattr(
                s, '_name', '')] or [selected])[0], '_name', '')
            self.debug('getModelMimeData(%s)' % model)
            mimeData = Qt.QMimeData()
            if model:
                taurusType = taurushelper.getValidTypesForName(model, False)
                if TaurusElementType.Device in taurusType:
                    self.debug('getMimeData(): DeviceModel at %s: %s',
                               self.mousePos, model)
                    mimeData.setData(TAURUS_DEV_MIME_TYPE, model)
                if TaurusElementType.Attribute in taurusType:
                    self.debug('getMimeData(): AttributeModel at %s: %s',
                               self.mousePos, model)
                    mimeData.setData(TAURUS_ATTR_MIME_TYPE, model)
                else:
                    self.debug('getMimeData(): UnknownModel at %s: %s',
                               self.mousePos, model)
                    mimeData.setData(TAURUS_MODEL_MIME_TYPE, model)
        except:
            self.debug(
                'jdrawView.getModelMimeData(%s): unable to get MimeData' % model)
            self.debug(traceback.format_exc())
        return mimeData

    #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
    # QT properties
    #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-

    @classmethod
    def setDefaultPanelClass(klass, other):
        """
        This method returns the Class used to open new object panels on double-click (TaurusDevicePanel by default)
        """
        klass._defaultClass = other

    @classmethod
    def defaultPanelClass(klass):
        """
        This method assigns the Class used to open new object panels on double-click (TaurusDevicePanel by default)
        If an string is used it can be either a Taurus class or an OS launcher
        """
        if not hasattr(klass, '_defaultClass'):
            from taurus.qt.qtgui.panel import TaurusDevicePanel
            # 'taurusdevicepanel' #You can use an executable or a class
            klass._defaultClass = TaurusDevicePanel
        obj = klass._defaultClass
        return obj

    def setPanelClass(self, widget):
        self._panelClass = widget

    def panelClass(self):
        if self._panelClass is None:
            return self.defaultPanelClass()
        else:
            return self._panelClass

    @Qt.pyqtSlot('QString')
    def setModel(self, model, alias=None, delayed=False, trace=False):
        self.modelName = str(model)
        self._currF = str(model)
        if alias is not None:
            self.setAlias(alias)
        ll = taurus.getLogLevel()
        if trace:
            taurus.setLogLevel(taurus.Debug)
        # self.debug('setModel("%s")'%model)
        if self._currF:
            #filename = str(self._currFile.absoluteFilePath())
            filename = self._currF
            filename = os.path.realpath(filename)
            if os.path.isfile(filename):
                self.debug("Starting to parse %s" % filename)
                self.path = os.path.dirname(filename)
                factory = self.getGraphicsFactory(delayed=delayed)
                scene = jdraw_parser.parse(filename, factory)
                scene.setSelectionStyle(self._selectionStyle)
                self.debug("Obtained %s(%s)", type(scene).__name__, filename)
                if not scene:
                    self.warning("TaurusJDrawSynopticsView.setModel(%s): Unable to parse %s!!!" % (
                        model, filename))
                elif self.w_scene is None and scene.sceneRect():
                    self.w_scene = scene.sceneRect().width()
                    self.h_scene = scene.sceneRect().height()
                else:
                    self.debug('JDrawView.sceneRect() is NONE!!!')
                self.setScene(scene)
                self.scene().graphicItemSelected.connect(self._graphicItemSelected)
                self.scene().graphicSceneClicked.connect(self._graphicSceneClicked)
                # Qt.QApplication.instance().lastWindowClosed.connect(self.close) #It caused a
                # segfault!
                self.__modelsChanged()
                self.setWindowTitle(self.modelName)
                # The emitted signal contains the filename and a dictionary
                # with the name of items and its color
                self.emitColors()  # get_item_colors(emit=True)
                self.fitting()
            else:
                self.setScene(None)
        #self.debug('out of setModel()')
        taurus.setLogLevel(ll)

    def closeEvent(self, event=None):
        if self.scene():
            self.scene().closeAllPanels()
        Qt.QGraphicsView.closeEvent(self, event)

    def setModels(self):
        """ This method triggers item.setModel(item._name) in all internal items. """
        for item in self.scene().items():
            if item._name and isinstance(item, TaurusGraphicsItem):
                self.debug(
                    'TaurusJDrawGraphicsFactory.setModels(): calling item.setModel(%s)' % (item._name))
                item.setModel(item._name)

    def getModel(self):
        return self._currF

    @classmethod
    def getQtDesignerPluginInfo(cls):
        ret = TaurusBaseWidget.getQtDesignerPluginInfo()
        ret['group'] = 'Taurus Display'
        ret['module'] = 'taurus.qt.qtgui.graphic'
        ret['icon'] = "designer:graphicsview.png"
        return ret

    model = Qt.pyqtProperty("QString", getModel, setModel)

    def setSelectionStyle(self, selectionStyle):
        if isinstance(selectionStyle, (Qt.QString, basestring)):
            selectionStyle = str(selectionStyle).upper()
            try:
                selectionStyle = SynopticSelectionStyle[selectionStyle]
            except:
                self.debug('invalid selectionStyle "%s"', selectionStyle)
                return
        if self.scene() is not None:
            self.scene().setSelectionStyle(selectionStyle)
        self._selectionStyle = selectionStyle

    def getSelectionStyle(self):
        return self._selectionStyle

    def getSelectionStyleName(self):
        return SynopticSelectionStyle.whatis(self.getSelectionStyle())

    def resetSelectionStyle(self):
        self.setSelectionStyle(SynopticSelectionStyle.OUTLINE)

    selectionStyle = Qt.pyqtProperty("QString", getSelectionStyleName,
                                     setSelectionStyle,
                                     resetSelectionStyle)
Ejemplo n.º 58
0
    def resetEnableWheelEvent(self):
        self.setEnableWheelEvent(False)

    @classmethod
    def getQtDesignerPluginInfo(cls):
        ret = TaurusBaseWritableWidget.getQtDesignerPluginInfo()
        ret['module'] = 'taurus.qt.qtgui.input'
        ret['icon'] = "designer:lineedit.png"
        return ret

    #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
    # QT properties
    #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-

    model = Qt.pyqtProperty("QString", TaurusBaseWritableWidget.getModel,
                            TaurusBaseWritableWidget.setModel,
                            TaurusBaseWritableWidget.resetModel)

    useParentModel = Qt.pyqtProperty(
        "bool", TaurusBaseWritableWidget.getUseParentModel,
        TaurusBaseWritableWidget.setUseParentModel,
        TaurusBaseWritableWidget.resetUseParentModel)

    autoApply = Qt.pyqtProperty("bool", TaurusBaseWritableWidget.getAutoApply,
                                TaurusBaseWritableWidget.setAutoApply,
                                TaurusBaseWritableWidget.resetAutoApply)

    forcedApply = Qt.pyqtProperty("bool",
                                  TaurusBaseWritableWidget.getForcedApply,
                                  TaurusBaseWritableWidget.setForcedApply,
                                  TaurusBaseWritableWidget.resetForcedApply)
Ejemplo n.º 59
0
 def __init__(self, src):
     self.display = ''
     self.icon = Qt.QIcon()
     self.ok = True
     self.processSrc(src)
Ejemplo n.º 60
0
    def __init__(self, parent=None, designMode=False):
        TaurusWidget.__init__(self, parent, designMode)
        self.setObjectName(self.__class__.__name__)

        self._doorName = ""
        self._macroId = None
        self.setLayout(Qt.QVBoxLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)

        self.addToFavouritesAction = Qt.QAction(
            Qt.QIcon("status:software-update-available.svg"),
            "Add to favourites", self)
        self.addToFavouritesAction.triggered.connect(self.onAddToFavourites)
        self.addToFavouritesAction.setToolTip("Add to favourites")
        self.stopMacroAction = Qt.QAction(
            Qt.QIcon("actions:media_playback_stop.svg"), "Stop macro", self)
        self.stopMacroAction.triggered.connect(self.onStopMacro)
        self.stopMacroAction.setToolTip("Stop macro")
        self.pauseMacroAction = Qt.QAction(
            Qt.QIcon("actions:media_playback_pause.svg"), "Pause macro", self)
        self.pauseMacroAction.triggered.connect(self.onPauseMacro)
        self.pauseMacroAction.setToolTip("Pause macro")
        self.playMacroAction = Qt.QAction(
            Qt.QIcon("actions:media_playback_start.svg"), "Start macro", self)
        self.playMacroAction.triggered.connect(self.onPlayMacro)
        self.playMacroAction.setToolTip("Start macro")
        actionsLayout = Qt.QHBoxLayout()
        actionsLayout.setContentsMargins(0, 0, 0, 0)
        addToFavouritsButton = Qt.QToolButton()
        addToFavouritsButton.setDefaultAction(self.addToFavouritesAction)
        self.addToFavouritesAction.setEnabled(False)
        actionsLayout.addWidget(addToFavouritsButton)

        self.macroComboBox = MacroComboBox(self)
        self.macroComboBox.setModelColumn(0)
        actionsLayout.addWidget(self.macroComboBox)
        stopMacroButton = Qt.QToolButton()
        stopMacroButton.setDefaultAction(self.stopMacroAction)
        actionsLayout.addWidget(stopMacroButton)
        pauseMacroButton = Qt.QToolButton()
        pauseMacroButton.setDefaultAction(self.pauseMacroAction)
        actionsLayout.addWidget(pauseMacroButton)
        self.playMacroButton = Qt.QToolButton()
        self.playMacroButton.setDefaultAction(self.playMacroAction)
        actionsLayout.addWidget(self.playMacroButton)
        self.disableControlActions()
        self.doorStateLed = TaurusLed(self)
        actionsLayout.addWidget(self.doorStateLed)
        self.layout().addLayout(actionsLayout)

        splitter = Qt.QSplitter(self)
        self.layout().addWidget(splitter)
        splitter.setOrientation(Qt.Qt.Vertical)

        self._paramEditorModel = ParamEditorModel()
        self.stackedWidget = Qt.QStackedWidget()
        self.standardMacroParametersEditor = StandardMacroParametersEditor(
            self.stackedWidget)
        self.stackedWidget.addWidget(self.standardMacroParametersEditor)
        self.customMacroParametersEditor = None
        splitter.addWidget(self.stackedWidget)

        self._favouritesBuffer = None
        self.favouritesMacrosEditor = FavouritesMacrosEditor(self)
        self.registerConfigDelegate(self.favouritesMacrosEditor)
        self.favouritesMacrosEditor.setFocusPolicy(Qt.Qt.NoFocus)

        self._historyBuffer = None
        self.historyMacrosViewer = HistoryMacrosViewer(self)
        self.registerConfigDelegate(self.historyMacrosViewer)
        self.historyMacrosViewer.setFocusPolicy(Qt.Qt.NoFocus)

        self.tabMacroListsWidget = Qt.QTabWidget(self)
        self.tabMacroListsWidget.addTab(
            self.favouritesMacrosEditor, "Favourite list")
        self.tabMacroListsWidget.addTab(
            self.historyMacrosViewer, "History Viewer")
        splitter.addWidget(self.tabMacroListsWidget)
        # Due to a limitation in the useParentModel architecture of Taurus,
        # the parent of historyMacrosViewer and favouritesMacrosEditor
        # must be recalculated. See more details in the taurus snippet code [1]
        # [1] https://raw.githubusercontent.com/taurus-org/taurus/develop/doc/source/devel/examples/parentmodel_issue_demo.py
        self.historyMacrosViewer.recheckTaurusParent()
        self.favouritesMacrosEditor.recheckTaurusParent()

        self._isHistoryMacro = False
        self.macroProgressBar = MacroProgressBar(self)
        self.layout().addWidget(self.macroProgressBar)

        #spockCommandLabel = Qt.QLabel("Spock command:", self)
        # spockCommandLabel.setFont(Qt.QFont("Courier",9))
        self.spockCommand = SpockCommandWidget("Spock", self)
        self.spockCommand.setSizePolicy(
            Qt.QSizePolicy.Expanding, Qt.QSizePolicy.Minimum)
        spockCommandLayout = Qt.QHBoxLayout()
        spockCommandLayout.setContentsMargins(0, 0, 0, 0)
        # spockCommandLayout.addWidget(spockCommandLabel)
        spockCommandLayout.addWidget(self.spockCommand)
        self.layout().addLayout(spockCommandLayout)

        self.macroComboBox.currentIndexChanged['QString'].connect(
            self.onMacroComboBoxChanged)
        self.favouritesMacrosEditor.list.favouriteSelected.connect(
            self.onFavouriteSelected)
        self.historyMacrosViewer.list.historySelected.connect(
            self.onHistorySelected)

        self.spockCommand.pressedReturn.connect(self.onPlayMacro)
        self.spockCommand.spockComboBox.connect(self.setComboBoxItem)
        self.spockCommand.elementUp.connect(self.setHistoryUp)
        self.spockCommand.elementDown.connect(self.setHistoryDown)
        self.spockCommand.expandTree.connect(
            self.standardMacroParametersEditor.tree.expandAll)