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 # model = index.model()
34 # select_index = model.index(index.row(), 2, index.parent())
35 # select_data = select_index.data().toString()
36 # if select_data == "true":
38 # model.setData(select_index, QString("TEST"), Qt.DisplayRole)
39 # model.emit(SIGNAL('dataChanged(QModelIndex, QModelIndex)'),
40 # select_index, select_index)
43 if data.startswith("*"): # already in the sliver
44 data = " %s " % data[1:]
46 fm = QFontMetrics(option.font)
48 rect.setWidth(fm.width(QString(data)))
49 rect.setHeight(rect.height() - 2)
50 rect.setX(rect.x() + 1)
51 x, y, h, w = rect.x(), rect.y(), rect.height(), rect.width()
54 path.addRoundedRect(x, y, w, h, 4, 4)
57 painter.setRenderHint(QPainter.Antialiasing)
58 painter.drawRoundedRect(rect, 4, 4)
59 painter.fillPath(path, QColor.fromRgb(0, 250, 0))
60 painter.setPen(QColor.fromRgb(0, 0, 0))
61 painter.drawText(option.rect, 0, QString(data))
63 else: # others, fall back to default view
64 QStyledItemDelegate.paint(self, painter, option, index)
67 def __init__(self, data, parent=None):
68 self.parentItem = parent
73 for child in self.childItems:
79 def appendChild(self, child):
80 self.childItems.append(child)
83 return self.childItems[row]
86 return len(self.childItems)
88 def columnCount(self):
89 return len(self.itemData)
91 def data(self, column):
92 return self.itemData[column]
97 return self.parentItem.childItems.index(self)
103 return self.parentItem
107 class NodeModel(QAbstractItemModel):
108 def __init__(self, parent):
109 QAbstractItemModel.__init__(self, parent)
113 self.rootItem.clear()
116 def __initRoot(self):
117 self.rootItem = TreeItem([QString("Testbed"), QString("Hostname"), QString("Selected")])
119 def columnCount(self, parent):
121 return parent.internalPointer().columnCount()
123 return self.rootItem.columnCount()
125 def data(self, index, role):
126 if not index.isValid():
129 if role != Qt.DisplayRole:
132 item = index.internalPointer()
133 return item.data(index.column())
135 def headerData(self, section, orientation, role):
136 if orientation == Qt.Horizontal and role == Qt.DisplayRole:
137 return self.rootItem.data(section)
140 def flags(self, index):
141 if not index.isValid():
143 return Qt.ItemIsEnabled | Qt.ItemIsSelectable # | Qt.ItemIsEditable
145 def index(self, row, column, parent):
146 if not self.hasIndex(row, column, parent):
150 if not parent.isValid():
151 parentItem = self.rootItem
153 parentItem = parent.internalPointer()
155 childItem = parentItem.child(row)
157 return self.createIndex(row, column, childItem)
161 def parent(self, index):
162 if not index.isValid():
165 childItem = index.internalPointer()
166 parentItem = childItem.parent()
171 if parentItem is self.rootItem:
174 return self.createIndex(parentItem.row(), 0, parentItem)
176 def rowCount(self, parent):
177 if parent.column() > 0:
181 if not parent.isValid():
182 parentItem = self.rootItem
184 parentItem = parent.internalPointer()
186 return parentItem.childCount()
189 class SliceWidget(QWidget):
190 def __init__(self, parent):
191 QWidget.__init__(self, parent)
193 slicename = QLabel ("Slice : %s"%(config.getSlice() or "None"),self)
194 slicename.setScaledContents(False)
196 self.nodeView = NodeView(self)
197 self.nodeModel = NodeModel(self)
198 self.nodeView.setModel(self.nodeModel)
199 self.nodeNameDelegate = NodeNameDelegate(self)
200 self.selectDelegate = SelectDelegate(self)
203 refresh = QPushButton("Update Slice Data", self)
204 refresh.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
205 submit = QPushButton("Submit", self)
206 submit.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
208 hlayout = QHBoxLayout()
209 hlayout.addWidget(refresh, 0, Qt.AlignLeft)
211 hlayout.addWidget(submit, 0, Qt.AlignRight)
213 layout = QVBoxLayout()
214 layout.addWidget(slicename)
215 layout.addWidget(self.nodeView)
216 layout.addLayout(hlayout)
218 self.setLayout(layout)
219 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
221 self.connect(refresh, SIGNAL('clicked()'), self.refresh)
222 self.connect(submit, SIGNAL('clicked()'), self.submit)
224 rspec_file = os.path.expanduser("~/.sfi/%s.rspec" % config.getSlice())
225 if os.path.exists(rspec_file):
229 self.parent().setStatus("TODO: Submit not implemented yet!", 3000)
231 def readSliceRSpec(self):
232 rspec_file = config.getSliceRSpecFile()
233 xml = open(rspec_file).read()
237 if not config.getSlice():
238 self.parent().setStatus("<font color='red'>Slice not set yet!</font>", timeout=None)
241 self.process = SfiProcess()
242 outfile = self.process.getRSpecFromSM()
243 self.parent().setStatus("Updating slice data. This may take some time...", timeout=None)
245 self.connect(self.process, SIGNAL('finished()'), self.refreshFinished)
247 def refreshFinished(self):
249 self.parent().setStatus("<font color='green'>Slice data updated.</font>", timeout=5000)
252 def updateView(self):
253 self.nodeModel.clear()
254 rspec_string = self.readSliceRSpec()
255 networks = rspec_get_networks(rspec_string)
257 for network in networks:
258 networkItem = TreeItem([QString(network), QString(""), QString("")], self.nodeModel.rootItem)
260 all_nodes = rspec_get_nodes_from_network(rspec_string, network)
261 sliver_nodes = rspec_get_sliver_nodes_from_network(rspec_string, network)
262 available_nodes = filter(lambda x:x not in sliver_nodes, all_nodes)
264 for node in sliver_nodes:
265 nodeItem = TreeItem([QString(""), QString("*%s" % node), QString("true")], networkItem)
266 networkItem.appendChild(nodeItem)
268 for node in available_nodes:
269 nodeItem = TreeItem([QString(""), QString(node), QString("false")], networkItem)
270 networkItem.appendChild(nodeItem)
272 self.nodeModel.rootItem.appendChild(networkItem)
274 self.nodeView.expandAll()
275 self.nodeView.resizeColumnToContents(1)
277 self.nodeView.setItemDelegateForColumn(1, self.nodeNameDelegate)
278 self.nodeView.setItemDelegateForColumn(2, self.selectDelegate)
281 class MainScreen(SfaScreen):
282 def __init__(self, parent):
283 SfaScreen.__init__(self, parent)
285 slice = SliceWidget(self)
286 self.init(slice, "Main Window", "OneLab Federation GUI")