4 from PyQt4.QtCore import *
5 from PyQt4.QtGui import *
7 from sfa.util.record import SfaRecord, SliceRecord, AuthorityRecord
8 from sface.config import config
9 from sface.sfidata import SfiData
12 MEMBERSHIP_STATUS_COLUMN = 1
14 # maximum length of a name to display before clipping
17 slice_status = { "in": "Selected",
18 "out": "Not Selected"}
20 color_status = { "in": QColor.fromRgb(0, 250, 250), }
22 class SliceNameDelegate(QStyledItemDelegate):
23 def __init__(self, parent):
24 QStyledItemDelegate.__init__(self, parent)
26 def displayText(self, value, locale):
27 data = str(QStyledItemDelegate.displayText(self, value, locale))
28 if (len(data)>NAME_MAX_LEN):
29 data = data[:(NAME_MAX_LEN-3)] + "..."
32 def paint(self, painter, option, index):
34 data = str(self.displayText(index.data(), QLocale()))
35 status_index = model.index(index.row(), MEMBERSHIP_STATUS_COLUMN, index.parent())
36 status_data = status_index.data().toString()
38 fm = QFontMetrics(option.font)
39 rect = QRect(option.rect)
41 rect.setHeight(rect.height() - 2)
42 rect.setWidth(fm.width(QString(data)) + 6)
43 rect.setX(rect.x() + 5)
44 rect.setY(rect.y() - 1)
46 textRect = QRect(option.rect)
47 textRect.setWidth(fm.width(QString(data)) + 6)
48 textRect.setX(rect.x())
50 x, y, h, w = rect.x(), rect.y(), rect.height(), rect.width()
53 path.addRoundedRect(x - 1, y + 1, w, h, 4, 4)
56 painter.setRenderHint(QPainter.Antialiasing)
58 if option.state & QStyle.State_Selected:
59 painter.fillRect(option.rect, option.palette.color(QPalette.Active, QPalette.Highlight))
62 for x in slice_status.keys():
63 if (slice_status[x] == status_data) and (x in color_status):
64 color = color_status[x]
67 painter.fillPath(path, color)
68 painter.setPen(QColor.fromRgb(0, 0, 0))
69 painter.drawText(textRect, Qt.AlignVCenter, QString(data))
73 class SliceView(QTableView):
74 def __init__(self, parent=None):
75 QTableView.__init__(self, parent)
77 self.setSelectionBehavior(QAbstractItemView.SelectRows)
78 self.setSelectionMode(QAbstractItemView.SingleSelection)
79 self.setAlternatingRowColors(True)
80 self.setAttribute(Qt.WA_MacShowFocusRect, 0)
81 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
82 self.setToolTip("Double click on a row to change its status.")
84 self.setItemDelegateForColumn(0, SliceNameDelegate(self))
86 def keyPressEvent(self, event):
87 if (event.key() == Qt.Key_Space):
88 self.toggleSelection()
90 QTableView.keyPressEvent(self, event)
92 def mouseDoubleClickEvent(self, event):
93 self.toggleSelection()
95 def toggleSelection(self):
96 index = self.currentIndex()
98 status_index = model.index(index.row(), MEMBERSHIP_STATUS_COLUMN, index.parent())
99 status_data = status_index.data().toString()
100 node_index = model.index(index.row(), NAME_COLUMN, index.parent())
101 node_data = node_index.data().toString()
103 if status_data == slice_status['in']:
104 model.setData(status_index, QString(slice_status['out']))
106 model.setData(status_index, QString(slice_status['in']))
108 model.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), node_index, node_index)
110 def currentChanged(self, current, previous):
111 model = current.model()
112 node_index = model.index(current.row(), 0, current.parent())
113 node_data = node_index.data().toString()
115 MODE_AUTHORITY_SLICES = 1
118 class SliceModel(QStandardItemModel):
119 def __init__(self, rows=0, columns=4, parent=None, mode=MODE_AUTHORITY_SLICES):
120 QStandardItemModel.__init__(self, rows, columns, parent)
123 def updateModel(self):
126 if (self.mode == MODE_AUTHORITY_SLICES):
127 slice_names = SfiData().getAuthorityHrns(type="slice")
128 else: # MODE_USER_SLICES
129 slice_names = SfiData().getUserSliceHrns()
131 rootItem = self.invisibleRootItem()
133 for name in slice_names:
134 rootItem.appendRow([self.readOnlyItem(name),
135 self.readOnlyItem(slice_status["out"])])
137 headers = QStringList() << "Slice Name" << "Status"
138 self.setHorizontalHeaderLabels(headers)
140 def readOnlyItem(self, x):
141 item = QStandardItem(QString(x))
142 item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
145 def getSelectedSlices(self):
147 item = self.invisibleRootItem()
148 children = item.rowCount()
149 for row in range(0, children):
150 childName = str(item.child(row, NAME_COLUMN).data(Qt.DisplayRole).toString())
151 childStatus = str(item.child(row, MEMBERSHIP_STATUS_COLUMN).data(Qt.DisplayRole).toString())
153 if (childStatus == slice_status['in']):
154 slices.append(childName)
158 class SlicePickerWindow(QDialog):
159 def __init__(self, parent=None):
160 super(SlicePickerWindow, self).__init__(parent)
161 self.setWindowTitle("Slice Picker")
163 sliceLabel = QLabel("Slices:")
164 self.sliceView = SliceView()
166 self.status = QLabel("")
167 self.status.setMaximumWidth(640)
169 self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
170 self.buttonBox.button(QDialogButtonBox.Ok).setDefault(True)
172 layout = QVBoxLayout()
173 layout.addWidget(sliceLabel)
174 layout.addWidget(self.sliceView)
175 layout.addWidget(self.status)
176 layout.addWidget(self.buttonBox)
177 self.setLayout(layout)
179 self.connect(self.buttonBox, SIGNAL("accepted()"), self, SLOT("accept()"))
180 self.connect(self.buttonBox, SIGNAL("rejected()"), self, SLOT("reject()"))
182 self.sliceModel = SliceModel()
183 self.refreshAuthority()
186 self.slices = self.sliceModel.getSelectedSlices()
189 def setStatus(self, x):
190 self.status.setText(x)
192 def refreshAuthority(self):
193 self.process = SfiProcess(self)
194 self.connect(self.process, SIGNAL('finished()'), self.getAuthorityRecordFinished)
196 self.process.listRecords(config.getAuthority(), None)
197 self.setStatus("Refreshing slice list. This will take a moment...")
199 def getAuthorityRecordFinished(self):
200 self.disconnect(self.process, SIGNAL('finished()'), self.getAuthorityRecordFinished)
202 faultString = self.process.getFaultString()
204 self.setStatus("<font color='green'>Slice list refreshed.</font>")
205 self.updateSliceView()
207 self.setStatus("<font color='red'>Authority rec refresh error: %s</font>" % (faultString))
209 def updateSliceView(self):
210 self.sliceModel.updateModel()
212 self.sliceView.setModel(self.sliceModel)
213 self.sliceView.resizeColumnToContents(0)