CMS 3D CMS Logo

TableView.py
Go to the documentation of this file.
1 from builtins import range
2 import logging
3 
4 from PyQt4.QtGui import *
5 from PyQt4.QtCore import *
6 
7 from Vispa.Main.Application import Application
8 from Vispa.Share.BasicDataAccessor import BasicDataAccessor
9 from Vispa.Views.AbstractView import AbstractView
10 from Vispa.Views.PropertyView import PropertyView,Property
11 from Vispa.Share.ThreadChain import ThreadChain
12 
13 class TableWidgetItem(QTableWidgetItem):
14  def __lt__(self,other):
15  return str(self.text()).lower()<str(other.text()).lower()
16 
17 class TableView(AbstractView, QTableWidget):
18  """ The TableView widget fills itself using a DataAccessor.
19  """
20 
21  LABEL = "&Table View"
22  UPDATE_EVERY = 20
23 
24  def __init__(self, parent=None):
25  logging.debug(__name__ + ": __init__")
26  AbstractView.__init__(self)
27  QTableWidget.__init__(self, parent)
28 
29  self._operationId = 0
30  self._selection = (None,None)
31  self._updatingFlag = 0
32  self._columns=[]
33  self._sortingFlag=False
35  self._firstColumn=0
37  self._autosizeColumns=True
38 
39  self.setSortingEnabled(False)
40  self.verticalHeader().hide()
41  self.setSelectionMode(QTableWidget.SingleSelection)
42  self.setSelectionBehavior(QAbstractItemView.SelectRows)
43  self.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding))
44 
45  self.connect(self, SIGNAL("itemSelectionChanged()"), self.itemSelectionChanged)
46 
47  def setSorting(self,sort):
48  self._sortingFlag=sort
49 
50  def setColumns(self,columns):
51  """ Set a list of columns that shall be shown.
52  """
53  self._filteredColumns=columns
54 
55  def setDataAccessor(self, accessor):
56  """ Sets the DataAccessor from which the nodes are created.
57 
58  You need to call updateContent() in order to make the changes visible.
59  """
60  if not isinstance(accessor, BasicDataAccessor):
61  raise TypeError(__name__ + " requires data accessor of type BasicDataAccessor.")
62  AbstractView.setDataAccessor(self, accessor)
63 
64  def cancel(self):
65  """ Stop all running operations.
66  """
67  self._operationId += 1
68 
69  def clear(self):
70  """ Deletes all items in the TableView
71  """
72  #logging.debug(__name__ + ": clear")
73  QTableWidget.clear(self)
74  self.setRowCount(0)
75  self.setSortingEnabled(False)
76  self._columns=[]
77 
78  def updateContent(self):
79  """ Clear the TableView and refill it.
80  """
81  logging.debug(__name__ + ": updateContent")
82  self.cancel()
83  if self.dataAccessor() == None:
84  return False
85  self._updatingFlag+=1
86  self.clear()
87  if self.dataObject()==None:
88  self._updatingFlag-=1
89  return True
90  operationId = self._operationId
91  objects=self.allDataObjectChildren()
92  properties=[]
93  for object in objects:
94  thread = ThreadChain(self.dataAccessor().properties, object)
95  while thread.isRunning():
96  if not Application.NO_PROCESS_EVENTS:
97  QCoreApplication.instance().processEvents()
98  if operationId != self._operationId:
99  self._updatingFlag-=1
100  return False
101  properties+=[thread.returnValue()]
102  if self._filteredColumns!=[]:
103  self._columns=self._filteredColumns
104  else:
105  self._columns=[]
106  ranking={}
107  for ps in properties:
108  for property in ps:
109  if not property[1] in ranking.keys():
110  ranking[property[1]]=1
111  if property[0]!="Category":
112  self._columns+=[property[1]]
113  elif property[1]=="Label":
114  ranking[property[1]]+=100000
115  elif property[1]=="Name":
116  ranking[property[1]]+=10000
117  else:
118  ranking[property[1]]+=1
119  self._columns.sort(lambda x,y: cmp(-ranking[x],-ranking[y]))
120  self.setColumnCount(len(self._columns))
121  self.setHorizontalHeaderLabels(self._columns)
122  i=0
123  for object in objects:
124  # Process application event loop in order to accept user input during time consuming drawing operation
125  self._updateCounter+=1
126  if self._updateCounter>=self.UPDATE_EVERY:
127  self._updateCounter=0
128  if not Application.NO_PROCESS_EVENTS:
129  QCoreApplication.instance().processEvents()
130  # Abort drawing if operationId out of date
131  if operationId != self._operationId:
132  break
133  self._createItem(object,properties[i])
134  i+=1
135  if self._autosizeColumns:
136  for i in range(len(self._columns)):
137  self.resizeColumnToContents(i)
138  self.setSortingEnabled(self._sortingFlag)
139  self._updatingFlag-=1
140  return self._operationId==operationId
141 
142  def _createItem(self, object, properties):
143  """ Create item for an object.
144  """
145  row=self.rowCount()
146  self.setRowCount(self.rowCount()+1)
147  height=Property.DEFAULT_HEIGHT
148  firstColumnDone=False
149  for property in properties:
150  if property!=None and property[1] in self._columns:
151  i=self._columns.index(property[1])
152  if property[0] in ["MultilineString","Double"]:
153  propertyWidget=PropertyView.propertyWidgetFromProperty(property)
154  if propertyWidget.properyHeight()>height:
155  height=propertyWidget.properyHeight()
156  text=str(propertyWidget.value())
157  else:
158  text=str(property[2])
159  item=TableWidgetItem(text)
160  item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable)
161  item.object=object
162  self.setItem(row,i,item)
163  if i==self._firstColumn:
164  firstColumnDone=True
165  if not firstColumnDone:
166  item=QTableWidgetItem("")
167  item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsSelectable)
168  item.object=object
169  self.setItem(row,self._firstColumn,item)
170  self.verticalHeader().resizeSection(row,height)
171 
173  """ Emits signal selected that the TabController can connect to.
174  """
175  logging.debug(__name__ + ": itemSelectionChanged")
176  if not self._updatingFlag:
177  self._selection = (self.currentRow(),self.item(self.currentRow(),self._firstColumn).text())
178  if self.item(self.currentRow(),self._firstColumn)!=None:
179  self.emit(SIGNAL("selected"), self.item(self.currentRow(),self._firstColumn).object)
180  else:
181  self.emit(SIGNAL("selected"), None)
182 
183  def select(self, object):
184  """ Mark an object in the TableView as selected.
185  Remember position an name of object in order to restore the selection.
186  """
187  logging.debug(__name__ + ": select")
188  items = []
189  for i in range(self.rowCount()):
190  if self.item(i,self._firstColumn).object == object:
191  items += [(i,self.item(i,self._firstColumn))]
192  if len(items) > 0:
193  index = items[0][0]
194  item = items[0][1]
195  self._selection = (index,item.text())
196  self._updatingFlag +=1
197  self.setCurrentItem(item)
198  self._updatingFlag -=1
199 
200  def _selectedRow(self):
201  """ Return the row containing the selected object.
202  First search for object by name. If it is not found use position.
203  """
204  for i in range(self.rowCount()):
205  if self.item(i,self._firstColumn).text() == self._selection[1]:
206  return i
207  if self._selection[0]<self.rowCount():
208  return self._selection[0]
209  if self.rowCount()>0:
210  return 0
211  else:
212  return None
213 
214  def restoreSelection(self):
215  """ Restore selection.
216  """
217  logging.debug(__name__ + ": restoreSelection")
218  select=self._selectedRow()
219  if select != None:
220  self._updatingFlag +=1
221  self.setCurrentCell(select,0)
222  self._updatingFlag -=1
223 
224  def selection(self):
225  """ Return currently selected object.
226 
227  If selection unknown return first object.
228  """
229  #logging.debug(__name__ + ": selection")
230  select=self._selectedRow()
231  if select != None:
232  return self.item(select,self._firstColumn).object
233  else:
234  return None
235 
236  def isBusy(self):
237  return self._updatingFlag>0
238 
239  def mousePressEvent(self,event):
240  QTableWidget.mousePressEvent(self,event)
241  if event.button()==Qt.RightButton:
242  self.emit(SIGNAL("mouseRightPressed"), event.globalPos())
def mousePressEvent(self, event)
Definition: TableView.py:239
def setDataAccessor(self, accessor)
Definition: TableView.py:55
def setColumns(self, columns)
Definition: TableView.py:50
def setSorting(self, sort)
Definition: TableView.py:47
def allDataObjectChildren(self, objects=None)
def select(self, object)
Definition: TableView.py:183
def _createItem(self, object, properties)
Definition: TableView.py:142
def __init__(self, parent=None)
Definition: TableView.py:24
#define str(s)