#!/usr/bin/env python
#############################################################################
##
## This file is part of Taurus
##
## http://taurus-scada.org
##
## Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
##
## 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/>.
##
#############################################################################
"""
AttributeChooser.py: widget for choosing (a list of) attributes from a tango DB
"""
import sys
from taurus.external.qt import Qt
import taurus.core
from taurus.qt.qtgui.container import TaurusWidget
from taurus.qt.qtgui.tree import TaurusDbTreeWidget
from taurus.core.util.containers import CaselessList
from taurusmodellist import TaurusModelList
import taurus.qt.qtgui.resource
[docs]class TaurusModelSelectorTree(TaurusWidget):
def __init__(self, parent = None, selectables=None, buttonsPos=None, designMode = None):
TaurusWidget.__init__(self, parent)
if selectables is None: selectables = [taurus.core.taurusbasetypes.TaurusElementType.Attribute, taurus.core.taurusbasetypes.TaurusElementType.Member,
taurus.core.taurusbasetypes.TaurusElementType.Device]
self._selectables = selectables
#tree
self._deviceTree = TaurusDbTreeWidget(perspective=taurus.core.taurusbasetypes.TaurusElementType.Device)
self._deviceTree.getQModel().setSelectables(self._selectables)
self._deviceTree.setUseParentModel(True)
#toolbar
self._toolbar = Qt.QToolBar("TangoSelector toolbar")
self._toolbar.setIconSize(Qt.QSize(16,16))
self._toolbar.setFloatable(False)
self._addSelectedAction = self._toolbar.addAction(taurus.qt.qtgui.resource.getThemeIcon("list-add"), "Add selected", self.onAddSelected)
#defines the layout
self.setButtonsPos(buttonsPos)
self._deviceTree.recheckTaurusParent() ##NOT WORKING????
self.connect(self, Qt.SIGNAL(self.ModelChangedSignal), self._deviceTree.setModel) ##@todo: This is Workaround because UseSetParentModel is giving trouble again!
[docs] def getSelectedModels(self):
selected = []
for item in self._deviceTree.selectedItems():
nfo = item.itemData()
if isinstance(nfo, taurus.core.taurusdatabase.TaurusDevInfo):
selected.append(nfo.fullName())
elif isinstance(nfo, taurus.core.taurusdatabase.TaurusAttrInfo):
selected.append( "%s/%s"%(nfo.device().fullName(),nfo.name()) )
else:
self.info("Unknown item '%s' in selection"%repr(nfo))
return selected
[docs] def onAddSelected(self):
self.emit(Qt.SIGNAL("addModels"), self.getSelectedModels())
[docs] def treeView(self):
return self._deviceTree.treeView()
@classmethod
[docs] def getQtDesignerPluginInfo(cls):
ret = TaurusWidget.getQtDesignerPluginInfo()
ret['module'] = 'taurus.qt.qtgui.panel'
ret['icon'] = ":/designer/listview.png"
ret['container'] = False
ret['group'] = 'Taurus Views'
return ret
[docs]class TaurusModelChooser(TaurusWidget):
'''A widget that allows the user to select a list of models from a tree representing
devices and attributes from a Tango server.
The user selects models and adds them to a list. Then the user should click on the
update button to notify that the selection is ready.
signals::
- "updateModels" emitted when the user clicks on the update button. It
passes a list<str> of models that have been selected.
'''
def __init__(self, parent = None, selectables=None, host=None, designMode=None, singleModel=False):
'''Creator of TaurusModelChooser
:param parent: (QObject) parent for the dialog
:param selectables: (list<TaurusElementType>) if passed, only elements of the tree whose
type is in the list will be selectable.
:param host: (QObject) Tango host to be explored by the chooser
:param designMode: (bool) needed for taurusdesigner but ignored here
:param singleModel: (bool) If True, the selection will be of just one
model. Otherwise (default) a list of models can be selected
'''
TaurusWidget.__init__(self, parent)
if host is None: host = taurus.Database().getNormalName()
self._allowDuplicates = False
self.setLayout(Qt.QVBoxLayout())
self.tree = TaurusModelSelectorTree(selectables = selectables, buttonsPos = Qt.Qt.BottomToolBarArea)
self.tree.setModel(host)
self.list = TaurusModelList()
self.list.setSelectionMode(Qt.QAbstractItemView.ExtendedSelection)
applyBT = Qt.QToolButton()
applyBT.setToolButtonStyle(Qt.Qt.ToolButtonTextBesideIcon)
applyBT.setText('Apply')
applyBT.setIcon(taurus.qt.qtgui.resource.getIcon(":/status/available.svg"))
self.setSingleModelMode(singleModel)
#toolbar
self._toolbar = self.tree._toolbar
self._toolbar.addAction(self.list.removeSelectedAction)
self._toolbar.addAction(self.list.removeAllAction)
self._toolbar.addAction(self.list.moveUpAction)
self._toolbar.addAction(self.list.moveDownAction)
self._toolbar.addSeparator()
self._toolbar.addWidget(applyBT)
self.layout().addWidget(self.tree)
self.layout().addWidget(self.list)
#self.tree.setUseParentModel(True) #It does not work!!!!
self.connect(self, Qt.SIGNAL(self.ModelChangedSignal), self.tree.setModel) ##@todo: This is Workaround because UseSetParentModel is giving trouble again!
#connections:
self.connect(self.tree, Qt.SIGNAL("addModels"), self.addModels)
self.connect(applyBT, Qt.SIGNAL("clicked()"), self._onUpdateModels)
# self.connect(self.tree._deviceTree, Qt.SIGNAL("itemDoubleClicked"), self.onTreeDoubleClick)
# def onTreeDoubleClick(self, item, colum): #@todo: Implement this function properly
# if item.Role in self.tree._selectables:
# self.addModels([str(item.text())])
[docs] def getListedModels(self, asMimeData=False):
'''returns the list of models that have been added
:param asMimeData: (bool) If False (default), the return value will be a
list of models. If True, the return value is a
`QMimeData` containing at least `TAURUS_MODEL_LIST_MIME_TYPE`
and `text/plain` MIME types. If only one model was selected,
the mime data also contains a TAURUS_MODEL_MIME_TYPE.
:return: (list<str> or QMimeData) the type of return depends on the value of `asMimeData`'''
models = self.list.getModelList()
if self.isSingleModelMode():
models=models[:1]
if asMimeData:
md = Qt.QMimeData()
md.setData(taurus.qt.qtcore.mimetypes.TAURUS_MODEL_LIST_MIME_TYPE, str("\r\n".join(models)))
md.setText(", ".join(models))
if len(models) == 1:
md.setData(taurus.qt.qtcore.mimetypes.TAURUS_MODEL_MIME_TYPE, str(models[0]))
return md
return models
[docs] def setListedModels(self, models):
'''adds the given list of models to the widget list
'''
self.list.model().clearAll()
self.list.addModels(models)
[docs] def resetListedModels(self):
'''equivalent to setListedModels([])'''
self.list.model().clearAll()
[docs] def updateList(self, attrList ):
'''for backwards compatibility with AttributeChooser only. Use :meth:`setListedModels` instead'''
self.info('ModelChooser.updateList() is provided for backwards compatibility only. Use setListedModels() instead')
self.setListedModels(attrList)
[docs] def addModels(self, models):
''' Add given models to the selected models list'''
if len(models) == 0:
models= ['']
if self.isSingleModelMode():
self.resetListedModels()
if self._allowDuplicates:
self.list.addModels(models)
else:
listedmodels = CaselessList(self.getListedModels())
for m in models:
if m not in listedmodels:
listedmodels.append(m)
self.list.addModels([m])
[docs] def onRemoveSelected(self):
'''
Remove the list-selected models from the list
'''
self.list.removeSelected()
def _onUpdateModels(self):
models = self.getListedModels()
self.emit(Qt.SIGNAL("updateModels"), models)
if taurus.core.taurusbasetypes.TaurusElementType.Attribute in self.tree._selectables:
self.emit(Qt.SIGNAL("UpdateAttrs"), models) #for backwards compatibility with the old AttributeChooser
[docs] def setSingleModelMode(self, single):
'''sets whether the selection should be limited to just one model
(single=True) or not (single=False)'''
if single:
self.tree.treeView().setSelectionMode(Qt.QAbstractItemView.SingleSelection)
else:
self.tree.treeView().setSelectionMode(Qt.QAbstractItemView.ExtendedSelection)
self._singleModelMode = single
[docs] def isSingleModelMode(self):
'''returns True if the selection is limited to just one model. Returns False otherwise.
:return: (bool)'''
return self._singleModelMode
[docs] def resetSingleModelMode(self):
'''equivalent to setSingleModelMode(False)'''
self.setSingleModelMode(self, False)
@staticmethod
[docs] def modelChooserDlg(parent = None, selectables=None, host=None, asMimeData=False, singleModel=False, windowTitle='Model Chooser'):
'''Static method that launches a modal dialog containing a TaurusModelChooser
:param parent: (QObject) parent for the dialog
:param selectables: (list<TaurusElementType>) if passed, only elements of the tree whose
type is in the list will be selectable.
:param host: (QObject) Tango host to be explored by the chooser
:param asMimeData: (bool) If False (default), a list of models will be.
returned. If True, a `QMimeData` object will be
returned instead. See :meth:`getListedModels` for a
detailed description of this QMimeData object.
:param singleModel: (bool) If True, the selection will be of just one
model. Otherwise (default) a list of models can be selected
:param windowTitle: (str) Title of the dialog (default="Model Chooser")
:return: (list,bool or QMimeData,bool) Returns a models,ok tuple. models can be
either a list of models or a QMimeData object, depending on
`asMimeData`. ok is True if the dialog was accepted (by
clicking on the "update" button) and False otherwise
'''
dlg = Qt.QDialog(parent)
dlg.setWindowTitle(windowTitle)
dlg.setWindowIcon(taurus.qt.qtgui.resource.getIcon(":/taurus.png"))
layout = Qt.QVBoxLayout()
w = TaurusModelChooser(parent = parent, selectables=selectables, host=host, singleModel=singleModel)
layout.addWidget(w)
dlg.setLayout(layout)
dlg.connect(w,Qt.SIGNAL('updateModels'), dlg.accept)
dlg.exec_()
return w.getListedModels(asMimeData=asMimeData), (dlg.result() == dlg.Accepted)
@classmethod
[docs] def getQtDesignerPluginInfo(cls):
ret = TaurusWidget.getQtDesignerPluginInfo()
ret['module'] = 'taurus.qt.qtgui.panel'
ret['icon'] = ":/designer/listview.png"
ret['container'] = False
ret['group'] = 'Taurus Views'
return ret
singleModelMode = Qt.pyqtProperty("bool", isSingleModelMode, setSingleModelMode, resetSingleModelMode)
[docs]def main(args):
if len(sys.argv)>1:
host=sys.argv[1]
else:
host = None
app = Qt.QApplication(args)
print TaurusModelChooser.modelChooserDlg(host=host)
sys.exit()
if __name__=="__main__":
main(sys.argv)