3 from PyQt4.QtCore import *
4 from PyQt4.QtGui import *
6 from sfa.util.rspecHelper import RSpec
7 from sface.sfahelper import *
8 from sface.config import config
9 from sface.sfiprocess import SfiProcess
10 from sface.screens.sfascreen import SfaScreen
12 class NodeView(QTreeView):
13 def __init__(self, parent):
14 QTreeView.__init__(self, parent)
16 self.setAnimated(True)
17 self.setItemsExpandable(True)
18 self.setRootIsDecorated(True)
19 self.setAlternatingRowColors(True)
20 self.setAttribute(Qt.WA_MacShowFocusRect, 0)
21 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
23 class SelectDelegate(QStyledItemDelegate):
26 class NodeNameDelegate(QStyledItemDelegate):
27 def __init__(self, parent):
28 QStyledItemDelegate.__init__(self)
30 def paint(self, painter, option, index):
31 data = "%s" % index.data().toString()
33 select_index = model.index(index.row(), 2, index.parent())
34 select_data = select_index.data().toString()
35 # if select_data == "false":
37 # model.setData(index, QString("*%s" % data), Qt.EditRole)
38 # model.setData(select_index, QString("true"), Qt.EditRole)
41 if select_data == "true": # already in the sliver
42 fm = QFontMetrics(option.font)
44 rect.setWidth(fm.width(QString(data)))
45 rect.setHeight(rect.height() - 2)
46 rect.setX(rect.x() + 1)
47 x, y, h, w = rect.x(), rect.y(), rect.height(), rect.width()
50 path.addRoundedRect(x, y, w, h, 4, 4)
53 painter.setRenderHint(QPainter.Antialiasing)
54 painter.drawRoundedRect(rect, 4, 4)
55 painter.fillPath(path, QColor.fromRgb(0, 250, 0))
56 painter.setPen(QColor.fromRgb(0, 0, 0))
57 painter.drawText(option.rect, 0, QString(data))
59 else: # others, fall back to default view
60 QStyledItemDelegate.paint(self, painter, option, index)
63 def __init__(self, data, parent=None):
64 self.parentItem = parent
69 for child in self.childItems:
75 def appendChild(self, child):
76 self.childItems.append(child)
79 return self.childItems[row]
82 return len(self.childItems)
84 def childNumber(self):
86 return self.parentItem.childItems.index(self)
89 def columnCount(self):
90 return len(self.itemData)
92 def data(self, column):
93 return self.itemData[column]
95 def insertChildren(self, position, count, columns):
96 if position < 0 or position > len(self.childItems):
99 for row in range(count):
100 data = self.data(columns)
101 item = TreeItem(data, self)
102 self.childItems.insert(position, item)
106 def insertColumns(self, position, columns):
107 if position < 0 or position > len(self.itemData):
110 for column in range(columns):
111 self.itemData.insert(position, QVariant())
113 for child in self.childItems:
114 child.insertColumns(position, columns)
118 def setData(self, column, value):
119 if column < 0 or column >= len(self.itemData):
122 self.itemData[column] = value
126 if (self.parentItem):
128 return self.parentItem.childItems.index(self)
134 return self.parentItem
138 class NodeModel(QAbstractItemModel):
139 def __init__(self, parent):
140 QAbstractItemModel.__init__(self, parent)
144 self.rootItem.clear()
147 def __initRoot(self):
148 self.rootItem = TreeItem([QString("Testbed"), QString("Hostname"), QString("Selected")])
151 def getItem(self, index):
153 item = index.internalPointer()
157 def headerData(self, section, orientation, role):
158 if orientation == Qt.Horizontal and role == Qt.DisplayRole:
159 return self.rootItem.data(section)
162 def index(self, row, column, parent):
163 if not self.hasIndex(row, column, parent):
166 parentItem = self.getItem(parent)
168 childItem = parentItem.child(row)
170 return self.createIndex(row, column, childItem)
174 def insertColumns(self, position, columns, parent):
175 self.beginInsertColumns(parent, position, position + columns -1)
176 ret = self.rootItem.insertColumns(position, columns)
177 self.endInsertColumns()
180 def insertRows(self, position, rows, parent):
181 parentItem = self.getItem(parent)
182 self.beginInsertRows(parent, position, position + rows -1)
183 ret = parentItem.insertChildren(position, rows, self.rootItem.columnCount())
187 def parent(self, index):
188 if not index.isValid():
191 childItem = self.getItem(index)
192 parentItem = childItem.parent()
194 if parentItem is self.rootItem:
197 return self.createIndex(parentItem.row(), 0, parentItem)
199 def rowCount(self, parent=QModelIndex()):
200 parentItem = self.getItem(parent)
201 return parentItem.childCount()
203 def columnCount(self, parent=None):
204 return self.rootItem.columnCount()
206 def data(self, index, role):
207 if not index.isValid():
210 if role != Qt.DisplayRole and role != Qt.EditRole:
213 item = self.getItem(index)
214 return item.data(index.column())
216 def flags(self, index):
217 if not index.isValid():
219 return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable
221 def setData(self, index, value, role):
222 if role != Qt.EditRole:
225 item = self.getItem(index)
226 ret = item.setData(index.column(), value)
228 self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), index, index)
233 class SliceWidget(QWidget):
234 def __init__(self, parent):
235 QWidget.__init__(self, parent)
237 slicename = QLabel ("Slice : %s"%(config.getSlice() or "None"),self)
238 slicename.setScaledContents(False)
239 searchlabel = QLabel ("Search: ", self)
240 searchlabel.setScaledContents(False)
241 searchbox = QLineEdit(self)
242 searchbox.setAttribute(Qt.WA_MacShowFocusRect, 0)
244 toplayout = QHBoxLayout()
245 toplayout.addWidget(slicename, 0, Qt.AlignLeft)
246 toplayout.addStretch()
247 toplayout.addWidget(searchlabel, 0, Qt.AlignRight)
248 toplayout.addWidget(searchbox, 0, Qt.AlignRight)
250 self.nodeView = NodeView(self)
251 self.nodeModel = NodeModel(self)
252 self.filterModel = QSortFilterProxyModel(self) # enable filtering
253 self.filterModel.setSourceModel(self.nodeModel)
254 self.nodeView.setModel(self.filterModel)
255 self.filterModel.setDynamicSortFilter(True)
256 self.nodeView.setModel(self.nodeModel)
258 self.nodeNameDelegate = NodeNameDelegate(self)
259 self.selectDelegate = SelectDelegate(self)
261 refresh = QPushButton("Update Slice Data", self)
262 refresh.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
263 submit = QPushButton("Submit", self)
264 submit.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
266 bottomlayout = QHBoxLayout()
267 bottomlayout.addWidget(refresh, 0, Qt.AlignLeft)
268 bottomlayout.addStretch()
269 bottomlayout.addWidget(submit, 0, Qt.AlignRight)
271 layout = QVBoxLayout()
272 layout.addLayout(toplayout)
273 layout.addWidget(self.nodeView)
274 layout.addLayout(bottomlayout)
275 self.setLayout(layout)
276 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
278 self.connect(refresh, SIGNAL('clicked()'), self.refresh)
279 self.connect(submit, SIGNAL('clicked()'), self.submit)
280 self.connect(searchbox, SIGNAL('textChanged(QString)'), self.filter)
284 def filter(self, filter):
285 self.filterModel.setFilterRegExp(QRegExp(filter))
288 self.parent().setStatus("TODO: Submit not implemented yet!", 3000)
290 def readSliceRSpec(self):
291 rspec_file = config.getSliceRSpecFile()
292 if os.path.exists(rspec_file):
293 xml = open(rspec_file).read()
298 if not config.getSlice():
299 self.parent().setStatus("<font color='red'>Slice not set yet!</font>", timeout=None)
302 self.process = SfiProcess()
303 outfile = self.process.getRSpecFromSM()
304 self.parent().setStatus("Updating slice data. This may take some time...", timeout=None)
306 self.connect(self.process, SIGNAL('finished()'), self.refreshFinished)
308 def refreshFinished(self):
310 self.parent().setStatus("<font color='green'>Slice data updated.</font>", timeout=5000)
313 def updateView(self):
314 self.nodeModel.clear()
315 rspec_string = self.readSliceRSpec()
319 networks = rspec_get_networks(rspec_string)
320 for network in networks:
321 networkItem = TreeItem([QString(network), QString(""), QString("")], self.nodeModel.rootItem)
323 all_nodes = rspec_get_nodes_from_network(rspec_string, network)
324 sliver_nodes = rspec_get_sliver_nodes_from_network(rspec_string, network)
325 available_nodes = filter(lambda x:x not in sliver_nodes, all_nodes)
327 for node in sliver_nodes:
328 nodeItem = TreeItem([QString(""), QString("%s" % node), QString("true")], networkItem)
329 networkItem.appendChild(nodeItem)
331 for node in available_nodes:
332 nodeItem = TreeItem([QString(""), QString(node), QString("false")], networkItem)
333 networkItem.appendChild(nodeItem)
335 self.nodeModel.rootItem.appendChild(networkItem)
337 self.nodeView.expandAll()
338 self.nodeView.resizeColumnToContents(1)
339 self.nodeView.setItemDelegateForColumn(1, self.nodeNameDelegate)
340 self.nodeView.setItemDelegateForColumn(2, self.selectDelegate)
343 class MainScreen(SfaScreen):
344 def __init__(self, parent):
345 SfaScreen.__init__(self, parent)
347 slice = SliceWidget(self)
348 self.init(slice, "Main Window", "OneLab Federation GUI")