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.setItemsExpandable(True)
17 self.setRootIsDecorated(True)
18 self.setAlternatingRowColors(True)
19 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
20 self.setAttribute(Qt.WA_MacShowFocusRect, 0)
22 class ItemDelegate(QStyledItemDelegate):
23 def __init__(self, parent):
24 QStyledItemDelegate.__init__(self)
26 def paint(self, painter, option, index):
27 data = "%s" % index.data().toString()
29 if data.startswith("*"): # already in the sliver
30 data = " %s " % data[1:]
32 fm = QFontMetrics(option.font)
34 rect.setWidth(fm.width(QString(data)))
35 rect.setHeight(rect.height() - 2)
36 rect.setX(rect.x() + 1)
37 x, y, h, w = rect.x(), rect.y(), rect.height(), rect.width()
40 path.addRoundedRect(x, y, w, h, 4, 4)
43 painter.setRenderHint(QPainter.Antialiasing)
44 painter.drawRoundedRect(rect, 4, 4)
45 painter.fillPath(path, QColor.fromRgb(0, 250, 0))
46 painter.setPen(QColor.fromRgb(0, 0, 0))
47 painter.drawText(option.rect, 0, QString(data))
49 else: # others, fall back to default view
50 QStyledItemDelegate.paint(self, painter, option, index)
53 def __init__(self, data, parent=None):
54 self.parentItem = parent
59 for child in self.childItems:
65 def appendChild(self, child):
66 self.childItems.append(child)
69 return self.childItems[row]
72 return len(self.childItems)
74 def columnCount(self):
75 return len(self.itemData)
77 def data(self, column):
78 return self.itemData[column]
83 return self.parentItem.childItems.index(self)
89 return self.parentItem
93 class NodeModel(QAbstractItemModel):
94 def __init__(self, parent):
95 QAbstractItemModel.__init__(self, parent)
102 def __initRoot(self):
103 self.rootItem = TreeItem([QString("Testbed"), QString("Hostname"), QString("Selected")])
105 def columnCount(self, parent):
107 return parent.internalPointer().columnCount()
109 return self.rootItem.columnCount()
111 def data(self, index, role):
112 if not index.isValid():
115 if role != Qt.DisplayRole:
118 item = index.internalPointer()
119 return item.data(index.column())
121 def headerData(self, section, orientation, role):
122 if orientation == Qt.Horizontal and role == Qt.DisplayRole:
123 return self.rootItem.data(section)
126 def flags(self, index):
127 if not index.isValid():
129 return Qt.ItemIsEnabled | Qt.ItemIsSelectable # | Qt.ItemIsEditable
131 def index(self, row, column, parent):
132 if not self.hasIndex(row, column, parent):
136 if not parent.isValid():
137 parentItem = self.rootItem
139 parentItem = parent.internalPointer()
141 childItem = parentItem.child(row)
143 return self.createIndex(row, column, childItem)
147 def parent(self, index):
148 if not index.isValid():
151 childItem = index.internalPointer()
152 parentItem = childItem.parent()
157 if parentItem is self.rootItem:
160 return self.createIndex(parentItem.row(), 0, parentItem)
162 def rowCount(self, parent):
163 if parent.column() > 0:
167 if not parent.isValid():
168 parentItem = self.rootItem
170 parentItem = parent.internalPointer()
172 return parentItem.childCount()
175 class SliceWidget(QWidget):
176 def __init__(self, parent):
177 QWidget.__init__(self, parent)
179 slicename = QLabel ("Slice : %s"%(config.getSlice() or "None"),self)
180 slicename.setScaledContents(False)
182 self.nodeView = NodeView(self)
183 self.nodeModel = NodeModel(self)
184 self.nodeView.setModel(self.nodeModel)
186 refresh = QPushButton("Update Slice Data", self)
187 refresh.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
188 submit = QPushButton("Submit", self)
189 submit.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
191 hlayout = QHBoxLayout()
192 hlayout.addWidget(refresh, 0, Qt.AlignLeft)
194 hlayout.addWidget(submit, 0, Qt.AlignRight)
196 layout = QVBoxLayout()
197 layout.addWidget(slicename)
198 layout.addWidget(self.nodeView)
199 layout.addLayout(hlayout)
201 self.setLayout(layout)
202 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
204 self.connect(refresh, SIGNAL('clicked()'), self.refresh)
205 self.connect(submit, SIGNAL('clicked()'), self.submit)
207 rspec_file = os.path.expanduser("~/.sfi/%s.rspec" % config.getSlice())
208 if os.path.exists(rspec_file):
212 self.parent().setStatus("TODO: Submit not implemented yet!", 3000)
214 def readSliceRSpec(self):
215 rspec_file = config.getSliceRSpecFile()
216 xml = open(rspec_file).read()
220 if not config.getSlice():
221 self.parent().setStatus("<font color='red'>Slice not set yet!</font>", timeout=None)
224 self.process = SfiProcess()
225 outfile = self.process.getRSpecFromSM()
226 self.parent().setStatus("Updating slice data. This may take some time...", timeout=None)
228 self.connect(self.process, SIGNAL('finished()'), self.refreshFinished)
230 def refreshFinished(self):
232 self.parent().setStatus("<font color='green'>Slice data updated.</font>", timeout=5000)
235 def updateView(self):
236 self.nodeModel.clear()
237 rspec_string = self.readSliceRSpec()
238 networks = rspec_get_networks(rspec_string)
240 for network in networks:
241 networkItem = TreeItem([QString(network), QString(""), QString("")], self.nodeModel.rootItem)
243 all_nodes = rspec_get_nodes_from_network(rspec_string, network)
244 sliver_nodes = rspec_get_sliver_nodes_from_network(rspec_string, network)
245 available_nodes = filter(lambda x:x not in sliver_nodes, all_nodes)
247 for node in sliver_nodes:
248 nodeItem = TreeItem([QString(""), QString("*%s" % node), QString("Implement Checkbox")], networkItem)
249 networkItem.appendChild(nodeItem)
251 for node in available_nodes:
252 nodeItem = TreeItem([QString(""), QString(node), QString("Implement Checkbox")], networkItem)
253 networkItem.appendChild(nodeItem)
255 self.nodeModel.rootItem.appendChild(networkItem)
257 self.nodeView.expandAll()
258 self.nodeView.resizeColumnToContents(1)
260 self.delegate = ItemDelegate(self)
261 self.nodeView.setItemDelegateForColumn(1, self.delegate)
264 class MainScreen(SfaScreen):
265 def __init__(self, parent):
266 SfaScreen.__init__(self, parent)
268 slice = SliceWidget(self)
269 self.init(slice, "Main Window", "OneLab Federation GUI")