add batch mode for renewing slices
[sface.git] / sface / sliceview.py
diff --git a/sface/sliceview.py b/sface/sliceview.py
new file mode 100644 (file)
index 0000000..92dd844
--- /dev/null
@@ -0,0 +1,167 @@
+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
+
+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()
+
+class SliceModel(QStandardItemModel):
+    def __init__(self, rows=0, columns=4, parent=None):
+         QStandardItemModel.__init__(self, rows, columns, parent)
+
+    def updateModel(self):
+        self.clear()
+
+        slice_names = []
+
+        i=0
+        while (os.path.exists(config.getAuthorityListFile(i))):
+            rec = self.readSliceRecord(i)
+            if rec:
+                name = str(rec.get_name())
+                if (rec.get_type() == "slice"):
+                    slice_names.append(name)
+            i=i+1
+
+        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
+
+    def readSliceRecord(self, i):
+        rec_file = config.getAuthorityListFile(i)
+        if os.path.exists(rec_file):
+            xml = open(rec_file).read()
+            rec = SliceRecord()
+            rec.load_from_string(xml)
+            return rec
+        return None
+