import datetime import os import pickle from PyQt4.QtCore import * from PyQt4.QtGui import * from sfa.util.record import SfaRecord, SliceRecord, AuthorityRecord from sface.config import config from sface.sfidata import SfiData NAME_COLUMN = 0 MEMBERSHIP_STATUS_COLUMN = 1 # maximum length of a name to display before clipping NAME_MAX_LEN = 48 slice_status = { "in": "Selected", "out": "Not Selected"} color_status = { "in": QColor.fromRgb(0, 250, 250), } class SliceNameDelegate(QStyledItemDelegate): def __init__(self, parent): QStyledItemDelegate.__init__(self, parent) def displayText(self, value, locale): data = str(QStyledItemDelegate.displayText(self, value, locale)) if (len(data)>NAME_MAX_LEN): data = data[:(NAME_MAX_LEN-3)] + "..." return QString(data) def paint(self, painter, option, index): model = index.model() data = str(self.displayText(index.data(), QLocale())) status_index = model.index(index.row(), MEMBERSHIP_STATUS_COLUMN, index.parent()) status_data = status_index.data().toString() fm = QFontMetrics(option.font) rect = QRect(option.rect) rect.setHeight(rect.height() - 2) rect.setWidth(fm.width(QString(data)) + 6) rect.setX(rect.x() + 5) rect.setY(rect.y() - 1) textRect = QRect(option.rect) textRect.setWidth(fm.width(QString(data)) + 6) textRect.setX(rect.x()) x, y, h, w = rect.x(), rect.y(), rect.height(), rect.width() path = QPainterPath() path.addRoundedRect(x - 1, y + 1, w, h, 4, 4) painter.save() painter.setRenderHint(QPainter.Antialiasing) if option.state & QStyle.State_Selected: painter.fillRect(option.rect, option.palette.color(QPalette.Active, QPalette.Highlight)) color = None for x in slice_status.keys(): if (slice_status[x] == status_data) and (x in color_status): color = color_status[x] if color != None: painter.fillPath(path, color) painter.setPen(QColor.fromRgb(0, 0, 0)) painter.drawText(textRect, Qt.AlignVCenter, QString(data)) painter.restore() class SliceView(QTableView): def __init__(self, parent=None): QTableView.__init__(self, parent) self.setSelectionBehavior(QAbstractItemView.SelectRows) self.setSelectionMode(QAbstractItemView.SingleSelection) self.setAlternatingRowColors(True) self.setAttribute(Qt.WA_MacShowFocusRect, 0) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setToolTip("Double click on a row to change its status.") self.setItemDelegateForColumn(0, SliceNameDelegate(self)) def keyPressEvent(self, event): if (event.key() == Qt.Key_Space): self.toggleSelection() else: QTableView.keyPressEvent(self, event) def mouseDoubleClickEvent(self, event): self.toggleSelection() def toggleSelection(self): index = self.currentIndex() model = index.model() status_index = model.index(index.row(), MEMBERSHIP_STATUS_COLUMN, index.parent()) status_data = status_index.data().toString() node_index = model.index(index.row(), NAME_COLUMN, index.parent()) node_data = node_index.data().toString() if status_data == slice_status['in']: model.setData(status_index, QString(slice_status['out'])) else: model.setData(status_index, QString(slice_status['in'])) model.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), node_index, node_index) def currentChanged(self, current, previous): model = current.model() node_index = model.index(current.row(), 0, current.parent()) node_data = node_index.data().toString() MODE_AUTHORITY_SLICES = 1 MODE_USER_SLICES = 2 class SliceModel(QStandardItemModel): def __init__(self, rows=0, columns=4, parent=None, mode=MODE_AUTHORITY_SLICES): QStandardItemModel.__init__(self, rows, columns, parent) self.mode = mode def updateModel(self): self.clear() if (self.mode == MODE_AUTHORITY_SLICES): slice_names = SfiData().getAuthorityHrns(type="slice") else: # MODE_USER_SLICES slice_names = SfiData().getUserSliceHrns() rootItem = self.invisibleRootItem() for name in slice_names: rootItem.appendRow([self.readOnlyItem(name), self.readOnlyItem(slice_status["out"])]) headers = QStringList() << "Slice Name" << "Status" self.setHorizontalHeaderLabels(headers) def readOnlyItem(self, x): item = QStandardItem(QString(x)) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) return item def getSelectedSlices(self): slices = [] item = self.invisibleRootItem() children = item.rowCount() for row in range(0, children): childName = str(item.child(row, NAME_COLUMN).data(Qt.DisplayRole).toString()) childStatus = str(item.child(row, MEMBERSHIP_STATUS_COLUMN).data(Qt.DisplayRole).toString()) if (childStatus == slice_status['in']): slices.append(childName) return slices class SlicePickerWindow(QDialog): def __init__(self, parent=None): super(SlicePickerWindow, self).__init__(parent) self.setWindowTitle("Slice Picker") sliceLabel = QLabel("Slices:") self.sliceView = SliceView() self.status = QLabel("") self.status.setMaximumWidth(640) self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.button(QDialogButtonBox.Ok).setDefault(True) layout = QVBoxLayout() layout.addWidget(sliceLabel) layout.addWidget(self.sliceView) layout.addWidget(self.status) layout.addWidget(self.buttonBox) self.setLayout(layout) self.connect(self.buttonBox, SIGNAL("accepted()"), self, SLOT("accept()")) self.connect(self.buttonBox, SIGNAL("rejected()"), self, SLOT("reject()")) self.sliceModel = SliceModel() self.refreshAuthority() def accept(self): self.slices = self.sliceModel.getSelectedSlices() QDialog.accept(self) def setStatus(self, x): self.status.setText(x) def refreshAuthority(self): self.process = SfiProcess(self) self.connect(self.process, SIGNAL('finished()'), self.getAuthorityRecordFinished) self.process.listRecords(config.getAuthority(), None) self.setStatus("Refreshing slice list. This will take a moment...") def getAuthorityRecordFinished(self): self.disconnect(self.process, SIGNAL('finished()'), self.getAuthorityRecordFinished) faultString = self.process.getFaultString() if not faultString: self.setStatus("Slice list refreshed.") self.updateSliceView() else: self.setStatus("Authority rec refresh error: %s" % (faultString)) def updateSliceView(self): self.sliceModel.updateModel() self.sliceView.setModel(self.sliceModel) self.sliceView.resizeColumnToContents(0)