6a2b95b508e2c9ea0a309c4800caccf24d9cef60
[sface.git] / sface / screens / mainscreen.py
1
2 import os
3 from PyQt4.QtCore import *
4 from PyQt4.QtGui import *
5
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
11
12 class NodeView(QTreeView):
13     def __init__(self, parent):
14         QTreeView.__init__(self, parent)
15
16         self.setItemsExpandable(True)
17         self.setRootIsDecorated(False)
18         self.setAlternatingRowColors(True)
19         self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
20
21 class TreeItem:
22     def __init__(self, data, parent=None):
23         self.parentItem = parent
24         self.itemData = data
25         self.childItems = []
26
27     def clear(self):
28         print "TODO: TreeItem.clear()"
29         for child in self.childItems:
30             child.clear()
31             del child
32         del self.childItems
33         self.childItems = []
34
35     def appendChild(self, child):
36         self.childItems.append(child)
37
38     def child(self, row):
39         return self.childItems[row]
40     
41     def childCount(self):
42         return len(self.childItems)
43
44     def columnCount(self):
45         return len(self.itemData)
46
47     def data(self, column):
48         return self.itemData[column]
49
50     def row(self):
51         if (self.parentItem):
52             try:
53                 return self.parentItem.childItems.index(self)
54             except ValueError:
55                 return 0
56         return 0
57     
58     def parent(self):
59         return self.parentItem
60
61
62
63 class NodeModel(QAbstractItemModel):
64     def __init__(self, parent):
65         QAbstractItemModel.__init__(self, parent)
66         self.__initRoot()
67
68     def clear(self):
69         self.rootItem.clear()
70         self.__initRoot()
71
72     def __initRoot(self):
73         self.rootItem = TreeItem([QString("Testbed"), QString("Hostname")])
74
75     def columnCount(self, parent):
76         if parent.isValid():
77             return parent.internalPointer().columnCount()
78         else:
79             return self.rootItem.columnCount()
80
81     def data(self, index, role):
82         if not index.isValid():
83             return QVariant()
84
85         if role != Qt.DisplayRole:
86             return QVariant()
87
88         item = index.internalPointer()
89         return item.data(index.column())
90
91     def headerData(self, section, orientation, role):
92         if orientation == Qt.Horizontal and role == Qt.DisplayRole:
93             return self.rootItem.data(section)
94         return QVariant()
95
96     def index(self, row, column, parent):
97         if not self.hasIndex(row, column, parent):
98             return QModelIndex()
99
100         parentItem = None
101         if not parent.isValid():
102             parentItem = self.rootItem
103         else:
104             parentItem = parent.internalPointer()
105             
106         childItem = parentItem.child(row)
107         if childItem:
108             return self.createIndex(row, column, childItem)
109         else:
110             return QModelIndex()
111
112     def parent(self, index):
113         if not index.isValid():
114             return QModelIndex()
115
116         childItem = index.internalPointer()
117         parentItem = childItem.parent()
118
119         if not parentItem:
120             return QModelIndex()
121
122         if parentItem is self.rootItem:
123             return QModelIndex()
124
125         return self.createIndex(parentItem.row(), 0, parentItem)
126
127     def rowCount(self, parent):
128         if parent.column() > 0:
129             return 0
130
131         parentItem = None
132         if not parent.isValid():
133             parentItem = self.rootItem
134         else:
135             parentItem = parent.internalPointer()
136
137         return parentItem.childCount()
138
139
140 class SliceWidget(QWidget):
141     def __init__(self, parent):
142         QWidget.__init__(self, parent)
143
144         self.nodeView = NodeView(self)
145         self.nodeModel = NodeModel(self)
146         self.nodeView.setModel(self.nodeModel)
147
148         refresh = QLabel("<a href='refresh'>Refresh</a>", self)
149         refresh.setScaledContents(False)
150         slicename = QLabel ("Slice : %s"%(config.getSlice() or "None"),self)
151         slicename.setScaledContents(False)
152
153         hlayout = QHBoxLayout()
154         hlayout.addWidget(slicename)
155         hlayout.addStretch()
156         hlayout.addWidget(refresh)
157
158         layout = QVBoxLayout()
159         layout.addLayout(hlayout)
160         layout.addWidget(self.nodeView)
161         self.setLayout(layout)
162         self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
163
164         self.connect(refresh, SIGNAL('linkActivated(QString)'), self.refresh)
165
166         rspec_file = os.path.expanduser("~/.sfi/%s.rspec" % config.getSlice())
167         if os.path.exists(rspec_file):
168             self.updateView()
169         
170     def readSliceRSpec(self):
171         rspec_file = os.path.expanduser("~/.sfi/%s.rspec" % config.getSlice())
172         xml = open(rspec_file).read()
173         return xml
174
175     def refresh(self, link=None):
176         if not config.getSlice():
177             self.parent().setStatus("<font color='red'>Slice not set yet!</font>")
178             return
179
180         self.process = SfiProcess()
181         outfile = self.process.getRSpecFromSM()
182         self.parent().setStatus("Updating slice data. This may take some time...")
183         
184         self.connect(self.process, SIGNAL('finished()'), self.refreshFinished)
185
186     def refreshFinished(self):
187         del self.process
188         self.parent().setStatus("<font color='green'>Slice data updated.</font>")
189         self.updateView()
190
191     def updateView(self):
192         rspec_string = self.readSliceRSpec()
193         networks = rspec_get_networks(rspec_string)
194
195         for network in networks:
196             networkItem = TreeItem([QString(network), QString("")], self.nodeModel.rootItem)
197
198             all_nodes = rspec_get_nodes_from_network(rspec_string, network)
199             for node in all_nodes:
200                 nodeItem = TreeItem([QString(""), QString(node)], networkItem)
201                 networkItem.appendChild(nodeItem)
202
203             self.nodeModel.rootItem.appendChild(networkItem)
204
205         self.nodeView.expandAll()
206
207
208 class MainScreen(SfaScreen):
209     def __init__(self, parent):
210         SfaScreen.__init__(self, parent)
211
212         slice = SliceWidget(self)
213         self.init(slice, "Main Window", "PlanetLab Federation GUI")