00001
00002
00003 import bisect
00004
00005 import QtCore
00006
00007 import rospy
00008 import rospkg
00009
00010 from python_qt_binding.QtCore import Qt, QObject, QAbstractItemModel
00011
00012 from vigir_pluginlib_msgs.msg import PluginState, PluginDescription
00013
00014
00015
00016 class PluginTreeModel(QtCore.QAbstractItemModel):
00017
00018 def __init__(self, parent=None, *args):
00019 super(PluginTreeModel, self).__init__(parent)
00020 self._root_item = PluginTreeItem()
00021 self._plugin_states = []
00022
00023 def clear(self):
00024 self._root_item.clear()
00025
00026 def columnCount(self, parent=QtCore.QModelIndex()):
00027 if parent.isValid():
00028 return parent.internalPointer().columnCount()
00029 else:
00030 return self._root_item.columnCount()
00031
00032 def rowCount(self, parent=QtCore.QModelIndex()):
00033 if parent.isValid():
00034 return parent.internalPointer().childCount()
00035 else:
00036 return self._root_item.childCount()
00037
00038 def headerData(self, section, orientation, role):
00039 if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
00040 if section == 0:
00041 return 'Class'
00042 elif section == 1:
00043 return 'Name'
00044 return None
00045
00046 def insertRows(self, row, count, parent=QtCore.QModelIndex()):
00047 parent_item = self.getItem(parent)
00048
00049 self.beginInsertRows(parent, row, row + count - 1)
00050 success = parent_item.insertChildren(row, count)
00051 self.endInsertRows()
00052
00053 return success
00054
00055 def removeRows(self, row, count, parent=QtCore.QModelIndex()):
00056 parent_item = self.getItem(parent)
00057
00058 self.beginRemoveRows(parent, row, row + count - 1)
00059 success = parent_item.removeChildren(row, count)
00060 self.endRemoveRows()
00061
00062
00063 if success and parent_item.parentItem() and not parent_item.childCount():
00064 return self.removeRows(parent_item.childNumber(), 1)
00065
00066 return success
00067
00068 def addBranch(self, base_class):
00069
00070 branch = self.findBranch(base_class)
00071 if branch.isValid():
00072 return branch
00073
00074 state = PluginState()
00075 state.description.base_class.data = base_class
00076
00077
00078 temp_list = [child.getPluginState().description.base_class.data for child in self._root_item.childs()]
00079 position = bisect.bisect(temp_list, base_class)
00080
00081 if self.insertRows(position, 1):
00082 branch_item = self._root_item.child(position)
00083 branch_item.setData(state)
00084 return self.index(position, 0)
00085
00086 return QtCore.QModelIndex()
00087
00088 def addItem(self, state):
00089
00090 branch = self.addBranch(state.description.base_class.data)
00091 branch_item = self.getItem(branch)
00092
00093
00094 child = self.findChild(state.description, branch)
00095 if child.isValid():
00096 return child
00097
00098
00099 entry = (state.description.type_class.data, state.description.name.data)
00100 temp_list = [(child.getPluginState().description.type_class.data, child.getPluginState().description.name.data) for child in branch_item.childs()]
00101 position = bisect.bisect(temp_list, entry)
00102
00103 if self.insertRows(position, 1, branch):
00104 child_item = branch_item.child(position)
00105 child_item.setData(state)
00106 return self.index(position, 0, branch)
00107
00108 return QtCore.QModelIndex()
00109
00110 def getItem(self, index=QtCore.QModelIndex()):
00111 if index.isValid():
00112 return index.internalPointer()
00113 else:
00114 return self._root_item
00115
00116 def setData(self, data):
00117 self.clear()
00118 self.updateData(data)
00119
00120 def updateData(self, data):
00121
00122 for state in data:
00123 if not state.description.base_class.data:
00124 state.description.base_class.data = 'Unknown'
00125 if not state.description.type_class.data:
00126 state.description.type_class.data = 'Unknown'
00127
00128
00129 rows = []
00130 for branch_item in self._root_item.childs():
00131 branch_index = self.index(branch_item.childNumber(), 0)
00132 for child_item in branch_item.childs():
00133 result = filter(lambda state: state.description == child_item.getPluginState().description, data)
00134 if not result:
00135 rows.append((child_item.childNumber(), branch_index))
00136
00137
00138 rows.sort(reverse=True)
00139 for row in rows:
00140 self.removeRows(row[0], 1, row[1])
00141
00142
00143 for state in data:
00144
00145 self.addItem(state)
00146
00147 def data(self, index, role):
00148 if not index.isValid():
00149 return None
00150 elif role == QtCore.Qt.DisplayRole:
00151 return index.internalPointer().data(index.column())
00152 else:
00153 return None
00154
00155 def flags(self, index=QtCore.QModelIndex()):
00156 if index.isValid():
00157 return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | super(PluginTreeModel, self).flags(index)
00158 else:
00159 return QtCore.Qt.NoItemFlags
00160
00161 def index(self, row, column, parent=QtCore.QModelIndex()):
00162 if not self.hasIndex(row, column, parent):
00163 return QtCore.QModelIndex()
00164
00165 if parent.isValid() and parent.column() != 0:
00166 return QtCore.QModelIndex()
00167
00168 parent_item = self.getItem(parent)
00169
00170 child_item = parent_item.child(row)
00171 if child_item:
00172 return self.createIndex(row, column, child_item)
00173 else:
00174 return QtCore.QModelIndex()
00175
00176 def parent(self, index=QtCore.QModelIndex()):
00177 if not index.isValid():
00178 return QtCore.QModelIndex()
00179
00180 child_item = self.getItem(index)
00181 parent_item = child_item.parentItem()
00182
00183 if parent_item == self._root_item:
00184 return QtCore.QModelIndex()
00185
00186 return self.createIndex(parent_item.childNumber(), 0, parent_item)
00187
00188 def findChild(self, description, parent=QtCore.QModelIndex()):
00189 parent_item = self.getItem(parent)
00190 if parent_item == self._root_item:
00191 parent = self.findBranch(description.base_class.data, parent)
00192
00193 if not parent.isValid():
00194 return QtCore.QModelIndex()
00195
00196 child_item = parent_item.findChild(description)
00197 if child_item:
00198 return self.index(child_item.childNumber(), 0, parent)
00199 else:
00200 return QtCore.QModelIndex()
00201
00202 def findBranch(self, base_class, parent=QtCore.QModelIndex()):
00203 parent_item = self.getItem(parent)
00204
00205 child_item = parent_item.findBranch(base_class)
00206 if child_item:
00207 return self.index(child_item.childNumber(), 0, parent)
00208 else:
00209 return QtCore.QModelIndex()
00210
00211 def expandChildren(self, index, view):
00212 if not index.isValid():
00213 return
00214
00215 for i in range(0, index.model().rowCount(index)):
00216 child = index.child(i, 0)
00217 self.expandChildren(child, view)
00218
00219 if not view.expanded(index):
00220 view.expand(index)
00221
00222 def expandAll(self):
00223 self.expandChildren(self.createIndex(0, 0, self._root_item))
00224
00225
00226
00227 class PluginTreeItem:
00228
00229 def __init__(self, state=PluginState(), parent=None):
00230 self._parent_item = parent
00231 self._child_items = []
00232 self._plugin_state = PluginState()
00233 self.setData(state)
00234
00235 def clear(self):
00236 for child in self._child_items:
00237 child.clear()
00238 self._child_items = []
00239 self._plugin_state = PluginState()
00240
00241 def child(self, row):
00242 if row < self.childCount():
00243 return self._child_items[row]
00244 else:
00245 return None
00246
00247 def childs(self):
00248 return self._child_items
00249
00250 def childCount(self):
00251 return len(self._child_items)
00252
00253 def childNumber(self):
00254 if self._parent_item is not None:
00255 return self._parent_item._child_items.index(self)
00256 return 0
00257
00258 def insertChildren(self, position, count):
00259 if position < 0 or position > self.childCount():
00260 return False
00261
00262 for row in range(0, count):
00263 self._child_items.insert(position, PluginTreeItem(parent=self))
00264
00265 return True
00266
00267 def removeChildren(self, position, count):
00268 if position < 0 or position > self.childCount():
00269 return False
00270
00271 del self._child_items[position:position+count]
00272
00273 return True
00274
00275 def columnCount(self):
00276 return 2
00277
00278 def data(self, column):
00279 if column == 0:
00280 if self.childCount() > 0:
00281 return self._plugin_state.description.base_class.data
00282 else:
00283 return self._plugin_state.description.type_class.data
00284 elif column == 1:
00285 if self.childCount() > 0:
00286 return ""
00287 else:
00288 return self._plugin_state.description.name.data
00289 else:
00290 return None
00291
00292 def setData(self, state):
00293 self._plugin_state = state
00294
00295 def getPluginState(self):
00296 return self._plugin_state
00297
00298 def findChild(self, description):
00299 child_item = filter(lambda child: child.getPluginState().description == description, self._child_items)
00300 if not child_item:
00301 return None
00302 else:
00303 return child_item[0]
00304
00305 def findBranch(self, base_class):
00306 branch_item = filter(lambda child: child.getPluginState().description.base_class.data == base_class, self._child_items)
00307 if not branch_item:
00308 return None
00309 else:
00310 return branch_item[0]
00311
00312 def parentItem(self):
00313 return self._parent_item