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