CMS 3D CMS Logo

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