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.sficonfig 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)
23 def __init__(self, data, parent=None):
24 self.parentItem = parent
29 for child in self.childItems:
35 def appendChild(self, child):
36 self.childItems.append(child)
39 return self.childItems[row]
42 return len(self.childItems)
44 def columnCount(self):
45 return len(self.itemData)
47 def data(self, column):
48 return self.itemData[column]
53 return self.parentItem.childItems.index(self)
59 return self.parentItem
63 class NodeModel(QAbstractItemModel):
64 def __init__(self, parent):
65 QAbstractItemModel.__init__(self, parent)
73 self.rootItem = TreeItem([QString("Testbed"), QString("Hostname")])
75 def columnCount(self, parent):
77 return parent.internalPointer().columnCount()
79 return self.rootItem.columnCount()
81 def data(self, index, role):
82 if not index.isValid():
85 if role != Qt.DisplayRole:
88 item = index.internalPointer()
89 return item.data(index.column())
91 def headerData(self, section, orientation, role):
92 if orientation == Qt.Horizontal and role == Qt.DisplayRole:
93 return self.rootItem.data(section)
96 def flags(self, index):
97 if not index.isValid():
99 return Qt.ItemIsEnabled | Qt.ItemIsSelectable
101 def index(self, row, column, parent):
102 if not self.hasIndex(row, column, parent):
106 if not parent.isValid():
107 parentItem = self.rootItem
109 parentItem = parent.internalPointer()
111 childItem = parentItem.child(row)
113 return self.createIndex(row, column, childItem)
117 def parent(self, index):
118 if not index.isValid():
121 childItem = index.internalPointer()
122 parentItem = childItem.parent()
127 if parentItem is self.rootItem:
130 return self.createIndex(parentItem.row(), 0, parentItem)
132 def rowCount(self, parent):
133 if parent.column() > 0:
137 if not parent.isValid():
138 parentItem = self.rootItem
140 parentItem = parent.internalPointer()
142 return parentItem.childCount()
145 class SliceWidget(QWidget):
146 def __init__(self, parent):
147 QWidget.__init__(self, parent)
149 refresh = QLabel("<a href='refresh'>Refresh</a>", self)
150 refresh.setScaledContents(False)
151 slicename = QLabel ("Slice : %s"%(config.getSlice() or "None"),self)
152 slicename.setScaledContents(False)
154 hlayout = QHBoxLayout()
155 hlayout.addWidget(slicename)
157 hlayout.addWidget(refresh)
159 self.nodeView = NodeView(self)
160 self.nodeModel = NodeModel(self)
161 self.nodeView.setModel(self.nodeModel)
163 submit = QPushButton("Submit", self)
164 submit.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
166 layout = QVBoxLayout()
167 layout.addLayout(hlayout)
168 layout.addWidget(self.nodeView)
169 layout.addWidget(submit, 0, Qt.AlignRight)
170 self.setLayout(layout)
171 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
173 self.connect(refresh, SIGNAL('linkActivated(QString)'), self.refresh)
174 self.connect(submit, SIGNAL('clicked()'), self.submit)
176 rspec_file = os.path.expanduser("~/.sfi/%s.rspec" % config.getSlice())
177 if os.path.exists(rspec_file):
181 self.parent().setStatus("TODO: Submit not implemented yet!")
183 def readSliceRSpec(self):
184 rspec_file = os.path.expanduser("~/.sfi/%s.rspec" % config.getSlice())
185 xml = open(rspec_file).read()
188 def refresh(self, link=None):
189 if not config.getSlice():
190 self.parent().setStatus("<font color='red'>Slice not set yet!</font>")
193 self.process = SfiProcess()
194 outfile = self.process.getRSpecFromSM()
195 self.parent().setStatus("Updating slice data. This may take some time...")
197 self.connect(self.process, SIGNAL('finished()'), self.refreshFinished)
199 def refreshFinished(self):
201 self.parent().setStatus("<font color='green'>Slice data updated.</font>")
204 def updateView(self):
205 self.nodeModel.clear()
206 rspec_string = self.readSliceRSpec()
207 networks = rspec_get_networks(rspec_string)
209 for network in networks:
210 networkItem = TreeItem([QString(network), QString("")], self.nodeModel.rootItem)
212 all_nodes = rspec_get_nodes_from_network(rspec_string, network)
213 sliver_nodes = rspec_get_sliver_nodes_from_network(rspec_string, network)
214 available_nodes = filter(lambda x:x not in sliver_nodes, all_nodes)
216 for node in sliver_nodes:
217 nodeItem = TreeItem([QString(""), QString("%s (selected)" % node)], networkItem)
218 networkItem.appendChild(nodeItem)
220 for node in available_nodes:
221 nodeItem = TreeItem([QString(""), QString(node)], networkItem)
222 networkItem.appendChild(nodeItem)
224 self.nodeModel.rootItem.appendChild(networkItem)
226 self.nodeView.expandAll()
229 class MainScreen(SfaScreen):
230 def __init__(self, parent):
231 SfaScreen.__init__(self, parent)
233 slice = SliceWidget(self)
234 self.init(slice, "Main Window", "PlanetLab Federation GUI")