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:]
33 fm = QFontMetrics(option.font)
34 w = fm.width(QString(data))
38 painter.fillRect(rect, QColor.fromRgb(0, 250, 0))
39 painter.setPen(QColor.fromRgb(0, 0, 0))
40 painter.drawText(option.rect, 0, QString(data))
42 else: # others, fall back to default view
43 QStyledItemDelegate.paint(self, painter, option, index)
46 def __init__(self, data, parent=None):
47 self.parentItem = parent
52 for child in self.childItems:
58 def appendChild(self, child):
59 self.childItems.append(child)
62 return self.childItems[row]
65 return len(self.childItems)
67 def columnCount(self):
68 return len(self.itemData)
70 def data(self, column):
71 return self.itemData[column]
76 return self.parentItem.childItems.index(self)
82 return self.parentItem
86 class NodeModel(QAbstractItemModel):
87 def __init__(self, parent):
88 QAbstractItemModel.__init__(self, parent)
96 self.rootItem = TreeItem([QString("Testbed"), QString("Hostname"), QString("Selected")])
98 def columnCount(self, parent):
100 return parent.internalPointer().columnCount()
102 return self.rootItem.columnCount()
104 def data(self, index, role):
105 if not index.isValid():
108 if role != Qt.DisplayRole:
111 item = index.internalPointer()
112 return item.data(index.column())
114 def headerData(self, section, orientation, role):
115 if orientation == Qt.Horizontal and role == Qt.DisplayRole:
116 return self.rootItem.data(section)
119 def flags(self, index):
120 if not index.isValid():
122 return Qt.ItemIsEnabled | Qt.ItemIsSelectable # | Qt.ItemIsEditable
124 def index(self, row, column, parent):
125 if not self.hasIndex(row, column, parent):
129 if not parent.isValid():
130 parentItem = self.rootItem
132 parentItem = parent.internalPointer()
134 childItem = parentItem.child(row)
136 return self.createIndex(row, column, childItem)
140 def parent(self, index):
141 if not index.isValid():
144 childItem = index.internalPointer()
145 parentItem = childItem.parent()
150 if parentItem is self.rootItem:
153 return self.createIndex(parentItem.row(), 0, parentItem)
155 def rowCount(self, parent):
156 if parent.column() > 0:
160 if not parent.isValid():
161 parentItem = self.rootItem
163 parentItem = parent.internalPointer()
165 return parentItem.childCount()
168 class SliceWidget(QWidget):
169 def __init__(self, parent):
170 QWidget.__init__(self, parent)
172 refresh = QLabel("<a href='refresh'>Update Slice Data</a>", self)
173 refresh.setScaledContents(False)
174 slicename = QLabel ("Slice : %s"%(config.getSlice() or "None"),self)
175 slicename.setScaledContents(False)
177 hlayout = QHBoxLayout()
178 hlayout.addWidget(slicename)
180 hlayout.addWidget(refresh)
182 self.nodeView = NodeView(self)
183 self.nodeModel = NodeModel(self)
184 self.nodeView.setModel(self.nodeModel)
186 submit = QPushButton("Submit", self)
187 submit.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
189 layout = QVBoxLayout()
190 layout.addLayout(hlayout)
191 layout.addWidget(self.nodeView)
192 layout.addWidget(submit, 0, Qt.AlignRight)
193 self.setLayout(layout)
194 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
196 self.connect(refresh, SIGNAL('linkActivated(QString)'), self.refresh)
197 self.connect(submit, SIGNAL('clicked()'), self.submit)
199 rspec_file = os.path.expanduser("~/.sfi/%s.rspec" % config.getSlice())
200 if os.path.exists(rspec_file):
204 self.parent().setStatus("TODO: Submit not implemented yet!", 3000)
206 def readSliceRSpec(self):
207 rspec_file = config.getSliceRSpecFile()
208 xml = open(rspec_file).read()
211 def refresh(self, link=None):
212 if not config.getSlice():
213 self.parent().setStatus("<font color='red'>Slice not set yet!</font>", timeout=None)
216 self.process = SfiProcess()
217 outfile = self.process.getRSpecFromSM()
218 self.parent().setStatus("Updating slice data. This may take some time...", timeout=None)
220 self.connect(self.process, SIGNAL('finished()'), self.refreshFinished)
222 def refreshFinished(self):
224 self.parent().setStatus("<font color='green'>Slice data updated.</font>", timeout=5000)
227 def updateView(self):
228 self.nodeModel.clear()
229 rspec_string = self.readSliceRSpec()
230 networks = rspec_get_networks(rspec_string)
232 for network in networks:
233 networkItem = TreeItem([QString(network), QString(""), QString("")], self.nodeModel.rootItem)
235 all_nodes = rspec_get_nodes_from_network(rspec_string, network)
236 sliver_nodes = rspec_get_sliver_nodes_from_network(rspec_string, network)
237 available_nodes = filter(lambda x:x not in sliver_nodes, all_nodes)
239 for node in sliver_nodes:
240 nodeItem = TreeItem([QString(""), QString("*%s" % node), QString("Implement Checkbox")], networkItem)
241 networkItem.appendChild(nodeItem)
243 for node in available_nodes:
244 nodeItem = TreeItem([QString(""), QString(node), QString("Implement Checkbox")], networkItem)
245 networkItem.appendChild(nodeItem)
247 self.nodeModel.rootItem.appendChild(networkItem)
249 self.nodeView.expandAll()
250 self.nodeView.resizeColumnToContents(1)
252 self.delegate = ItemDelegate(self)
253 self.nodeView.setItemDelegateForColumn(1, self.delegate)
256 class MainScreen(SfaScreen):
257 def __init__(self, parent):
258 SfaScreen.__init__(self, parent)
260 slice = SliceWidget(self)
261 self.init(slice, "Main Window", "OneLab Federation GUI")