Source code for taurus.qt.qtgui.tree.qtree
#!/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/>.
#
# ###########################################################################
"""This module provides base tree widget
"""
__docformat__ = "restructuredtext"
from taurus.external.qt import Qt
from taurus.qt.qtgui.model import QBaseModelWidget, BaseToolBar
from taurus.qt.qtgui.util import ActionFactory
class _NavigationWidget(Qt.QFrame):
"""Internal widget that provides a navigation path to be placed in a
toolbar"""
def __init__(self, treeWidget, toolBarWidget, parent=None):
super(_NavigationWidget, self).__init__(parent)
self._tree = treeWidget
self._toolbar = toolBarWidget
self._label = Qt.QLabel()
lyt = Qt.QHBoxLayout()
lyt.setContentsMargins(4, 0, 4, 0)
self.setLayout(lyt)
lyt.addWidget(self._label)
def treeWidget(self):
return self._tree
def viewWidget(self):
return self.treeWidget().viewWidget()
def toolBarWidget(self):
return self._toolbar
def updateSelection(self, index):
treeWidget = self.treeWidget()
src_model = treeWidget.getBaseQModel()
_ = self.toolBarWidget() # TODO: is this needed?
txt = ""
while index.isValid():
src_index = treeWidget._mapToSource(index)
name = src_model.pyData(src_index, Qt.Qt.DisplayRole)
txt = " \u00bb " + name + txt
index = index.parent()
txt = "Root" + txt
self._label.setText(txt)
def onGotoNode(self, *args):
label = self.sender()
persistent_index = label.parent().index()
index = Qt.QModelIndex(persistent_index)
tree = self.viewWidget()
tree.setRootIndex(index)
tree.setCurrentIndex(index.child(0, 0))
class NavigationToolBar(BaseToolBar):
goIntoTriggered = Qt.pyqtSignal()
goUpTriggered = Qt.pyqtSignal()
goTopTriggered = Qt.pyqtSignal()
def __init__(self, view=None, parent=None, designMode=False):
BaseToolBar.__init__(
self,
name="Taurus selection toolbar",
view=view,
parent=parent,
designMode=designMode,
)
af = ActionFactory()
self._goIntoAction = af.createAction(
self,
"Go Into",
icon=Qt.QIcon.fromTheme("go-down"),
tip="Go into the selected item",
triggered=self.goInto,
)
self._goUpAction = af.createAction(
self,
"Go Up",
icon=Qt.QIcon.fromTheme("go-up"),
tip="Go up one level",
triggered=self.goUp,
)
self._goTopAction = af.createAction(
self,
"Go Top",
icon=Qt.QIcon.fromTheme("go-top"),
tip="Go to top level",
triggered=self.goTop,
)
self.addAction(self._goIntoAction)
self.addAction(self._goUpAction)
self.addAction(self._goTopAction)
self._navigationWidget = _NavigationWidget(view, self, parent=self)
self._navigationAction = self.addWidget(self._navigationWidget)
def goIntoAction(self):
return self._goIntoAction
def goTopAction(self):
return self._goTopAction
def goUpAction(self):
return self._goUpAction
def goInto(self):
self.goIntoTriggered.emit()
def goUp(self):
self.goUpTriggered.emit()
def goTop(self):
self.goTopTriggered.emit()
class ExpansionBar(BaseToolBar):
expandTriggered = Qt.pyqtSignal()
collapseTriggered = Qt.pyqtSignal()
expandSelectionTriggered = Qt.pyqtSignal()
collapseSelectionTriggered = Qt.pyqtSignal()
def __init__(self, view=None, parent=None, designMode=False):
BaseToolBar.__init__(
self,
name="Taurus selection toolbar",
view=view,
parent=parent,
designMode=designMode,
)
af = ActionFactory()
self._expandAllAction = af.createAction(
self,
"Expand All",
icon=Qt.QIcon("actions:expand.png"),
tip="Expand all items",
triggered=self.onExpandAll,
)
self._collapseAllAction = af.createAction(
self,
"Collapse All",
icon=Qt.QIcon("actions:collapse.png"),
tip="Collapse all items",
triggered=self.onCollapseAll,
)
self._expandSelectionAction = af.createAction(
self,
"Expand selection",
icon=Qt.QIcon("actions:expand-selection.png"),
tip="Expand selection",
triggered=self.onExpandSelection,
)
self._collapseSelectionAction = af.createAction(
self,
"Collapse All",
icon=Qt.QIcon("actions:collapse-selection.png"),
tip="Collapse selection",
triggered=self.onCollapseSelection,
)
self.addAction(self._expandAllAction)
self.addAction(self._collapseAllAction)
self.addAction(self._expandSelectionAction)
self.addAction(self._collapseSelectionAction)
def onExpandAll(self):
self.expandTriggered.emit()
def onCollapseAll(self):
self.collapseTriggered.emit()
def onExpandSelection(self):
self.expandSelectionTriggered.emit()
def onCollapseSelection(self):
self.collapseSelectionTriggered.emit()
[docs]
class QBaseTreeWidget(QBaseModelWidget):
"""A pure Qt tree widget implementing a tree with a navigation toolbar"""
def __init__(
self,
parent=None,
designMode=False,
with_navigation_bar=True,
with_filter_widget=True,
with_selection_widget=True,
with_refresh_widget=True,
perspective=None,
proxy=None,
):
if with_navigation_bar:
if isinstance(with_navigation_bar, (bool, int)):
self._with_navigation_bar = NavigationToolBar
else:
self._with_navigation_bar = with_navigation_bar
else:
self._with_navigation_bar = None
QBaseModelWidget.__init__(
self,
parent,
with_filter_widget=with_filter_widget,
with_selection_widget=with_selection_widget,
with_refresh_widget=with_refresh_widget,
perspective=perspective,
proxy=proxy,
)
[docs]
def createToolArea(self):
ta = QBaseModelWidget.createToolArea(self)
e_bar = self._expandBar = ExpansionBar(view=self, parent=self)
e_bar.expandTriggered.connect(self.expandAllTree)
e_bar.collapseTriggered.connect(self.collapseAllTree)
e_bar.expandSelectionTriggered.connect(self.expandSelectionTree)
e_bar.collapseSelectionTriggered.connect(self.collapseSelectionTree)
ta.append(e_bar)
if self._with_navigation_bar:
n_bar = self._navigationToolBar = self._with_navigation_bar(
view=self, parent=self
)
n_bar.goIntoTriggered.connect(self.goIntoTree)
n_bar.goTopTriggered.connect(self.goTopTree)
n_bar.goUpTriggered.connect(self.goUpTree)
ta.append(n_bar)
else:
self._navigationToolBar = None
return ta
[docs]
def createViewWidget(self, klass=None):
if klass is None:
klass = Qt.QTreeView
tree = klass()
tree.setSortingEnabled(True)
tree.sortByColumn(0, Qt.Qt.AscendingOrder)
tree.setUniformRowHeights(True)
tree.setAlternatingRowColors(True)
tree.setSelectionBehavior(Qt.QAbstractItemView.SelectRows)
tree.setSelectionMode(Qt.QAbstractItemView.ExtendedSelection)
tree.setDragEnabled(True)
tree.setDropIndicatorShown(True)
tree.expanded.connect(self.onExpanded)
tree.clicked.connect(self._onClicked)
tree.doubleClicked.connect(self._onDoubleClicked)
h = tree.header()
if h.length() > 0:
try:
h.setSectionResizeMode(0, h.Stretch)
except AttributeError:
h.setResizeMode(0, h.Stretch)
return tree
[docs]
def expandAllTree(self):
self.statusBar().showMessage(
"Expanding all items... (it may take a few seconds)"
)
Qt.QTimer.singleShot(0, self._expandTree)
def _expandTree(self):
tree = self.viewWidget()
tree.expandAll()
self.statusBar().showMessage("All items expanded!", 3000)
[docs]
def expandSelectionTree(self):
tree = self.viewWidget()
index = tree.currentIndex()
if index.isValid():
tree.expand(index)
[docs]
def collapseSelectionTree(self):
tree = self.viewWidget()
index = tree.currentIndex()
if index.isValid():
tree.collapse(index)
[docs]
def resizeColumns(self):
tree = self.viewWidget()
model = tree.model()
if model is None:
return
for c in range(model.columnCount()):
tree.resizeColumnToContents(c)
[docs]
def goIntoTree(self):
tree = self.viewWidget()
index = tree.currentIndex()
base_index = self._mapToSource(index)
if not index.isValid():
return
# do not enter if the item doesn't have any children
if base_index.internalPointer().childCount() == 0:
return
tree.setRootIndex(index)
tree.setCurrentIndex(index.child(0, 0))
self._updateToolBar()
[docs]
def goUpTree(self):
tree = self.viewWidget()
index = tree.rootIndex()
if not index.isValid():
return
index_parent = index.parent()
tree.setRootIndex(index_parent)
tree.setCurrentIndex(index)
self._updateToolBar()
[docs]
def goTopTree(self):
tree = self.viewWidget()
current_root = tree.rootIndex()
p = current_root.parent()
while p.isValid():
p = p.parent()
tree.setRootIndex(p)
tree.setCurrentIndex(p)
self._updateToolBar()
def _updateToolBar(self, current=None, previous=None):
if not self._with_navigation_bar:
return
tree = self.viewWidget()
if current is None:
current = tree.currentIndex()
goInto = False
base_current = self._mapToSource(current)
if current.isValid():
ip = base_current.internalPointer()
if ip is not None:
goInto = ip.childCount() > 0
self._navigationToolBar._goIntoAction.setEnabled(goInto)
self._expandBar._expandSelectionAction.setEnabled(goInto)
self._expandBar._collapseSelectionAction.setEnabled(goInto)
goUp = tree.rootIndex().isValid()
self._navigationToolBar._goUpAction.setEnabled(goUp)
self._navigationToolBar._goTopAction.setEnabled(goUp)
index = tree.rootIndex()
self._navigationToolBar._navigationWidget.updateSelection(index)