fixes for rec.get
[sface.git] / sface / screens / userscreen.py
index 92089d1..4eb7793 100644 (file)
@@ -5,21 +5,77 @@ import pickle
 from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 
 from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 
-from sfa.util.record import SfaRecord, SliceRecord, AuthorityRecord, UserRecord
 from sface.config import config
 from sface.sfiprocess import SfiProcess
 from sface.screens.sfascreen import SfaScreen
 from sface.config import config
 from sface.sfiprocess import SfiProcess
 from sface.screens.sfascreen import SfaScreen
+from sface.sfidata import SfiData
 
 NAME_COLUMN = 0
 #ROLE_COLUMN = 1
 MEMBERSHIP_STATUS_COLUMN = 1
 SERVER_MEMBERSHIP_STATUS_COLUMN = 2
 
 
 NAME_COLUMN = 0
 #ROLE_COLUMN = 1
 MEMBERSHIP_STATUS_COLUMN = 1
 SERVER_MEMBERSHIP_STATUS_COLUMN = 2
 
+# maximum length of a name to display before clipping
+NAME_MAX_LEN = 48
+
 user_status = { "in": "Already Selected",
                 "out": "Not Selected",
                 "add": "To be Added",
                 "remove": "To be Removed"}
 
 user_status = { "in": "Already Selected",
                 "out": "Not Selected",
                 "add": "To be Added",
                 "remove": "To be Removed"}
 
+color_status = { "in": QColor.fromRgb(0, 250, 250),
+                 "add": QColor.fromRgb(0, 250, 0),
+                 "remove": QColor.fromRgb(250, 0, 0) }
+
+
+class UserNameDelegate(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))
+
+        for x in user_status.keys():
+            if (user_status[x] == status_data) and (x in color_status):
+                painter.fillPath(path, color_status[x])
+
+        painter.setPen(QColor.fromRgb(0, 0, 0))
+        painter.drawText(textRect, Qt.AlignVCenter, QString(data))
+
+        painter.restore()
+
 class UserView(QTableView):
     def __init__(self, parent=None):
         QTableView.__init__(self, parent)
 class UserView(QTableView):
     def __init__(self, parent=None):
         QTableView.__init__(self, parent)
@@ -31,7 +87,18 @@ class UserView(QTableView):
         self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
         self.setToolTip("Double click on a row to change its status.")
 
         self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
         self.setToolTip("Double click on a row to change its status.")
 
+        self.setItemDelegateForColumn(0, UserNameDelegate(self))
+
+    def keyPressEvent(self, event):
+        if (event.key() == Qt.Key_Space):
+            self.toggleSelection()
+        else:
+            QTableView.keyPressEvent(self, event)
+
     def mouseDoubleClickEvent(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())
         index = self.currentIndex()
         model = index.model()
         status_index = model.index(index.row(), MEMBERSHIP_STATUS_COLUMN, index.parent())
@@ -57,7 +124,6 @@ class UserView(QTableView):
         model = current.model()
         node_index = model.index(current.row(), 0, current.parent())
         node_data = node_index.data().toString()
         model = current.model()
         node_index = model.index(current.row(), 0, current.parent())
         node_data = node_index.data().toString()
-        self.emit(SIGNAL('hostnameClicked(QString)'), node_data)
 
     def hideUnusableColumns(self):
         self.hideColumn(SERVER_MEMBERSHIP_STATUS_COLUMN)
 
     def hideUnusableColumns(self):
         self.hideColumn(SERVER_MEMBERSHIP_STATUS_COLUMN)
@@ -73,39 +139,39 @@ class UserModel(QStandardItemModel):
         slice_persons = []
 
         if sliceRec:
         slice_persons = []
 
         if sliceRec:
-            #for pi in sliceRec.get_field("PI", default=[]):
+            #for pi in sliceRec.get("PI", []):
             #    name = str(pi)
             #    if not name in added_persons:
             #         slice_persons.append({"name": name, "role": "PI", "member": user_status["in"]})
             #         added_persons.append(name)
 
             #    name = str(pi)
             #    if not name in added_persons:
             #         slice_persons.append({"name": name, "role": "PI", "member": user_status["in"]})
             #         added_persons.append(name)
 
-            for researcher in sliceRec.get_field("researcher", default=[]):
+            for researcher in sliceRec.get("researcher", []):
                 name = str(researcher)
                 if not name in added_persons:
                      slice_persons.append({"name": name, "role": "researcher", "member": user_status["in"]})
                      added_persons.append(name)
 
                 name = str(researcher)
                 if not name in added_persons:
                      slice_persons.append({"name": name, "role": "researcher", "member": user_status["in"]})
                      added_persons.append(name)
 
-        i=0
-        while (os.path.exists(config.getAuthorityListFile(i))):
-            rec = self.readUserRecord(i)
-            if rec:
-                name = str(rec.get_name())
-                if not name in added_persons:
-                    slice_persons.append({"name": name, "role": "", "member": user_status["out"]})
-                    added_persons.append(name)
-            i=i+1
+        userNames = SfiData().getAuthorityHrns(type="user")
+        for name in userNames:
+            if not name in added_persons:
+                slice_persons.append({"name": name, "role": "", "member": user_status["out"]})
+                added_persons.append(name)
 
         rootItem = self.invisibleRootItem()
 
         for person in slice_persons:
 
         rootItem = self.invisibleRootItem()
 
         for person in slice_persons:
-            rootItem.appendRow([QStandardItem(QString(person["name"])),
-                               #QStandardItem(QString(person["role"])),
-                               QStandardItem(QString(person["member"])),
-                               QStandardItem(QString(person["member"]))])
+            rootItem.appendRow([self.readOnlyItem(person["name"]),
+                                self.readOnlyItem(person["member"]),
+                                self.readOnlyItem(person["member"])])
 
         headers = QStringList() << "User Name" << "Status" << "ServerStatus"
         self.setHorizontalHeaderLabels(headers)
 
 
         headers = QStringList() << "User Name" << "Status" << "ServerStatus"
         self.setHorizontalHeaderLabels(headers)
 
+    def readOnlyItem(self, x):
+        item = QStandardItem(QString(x))
+        item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
+        return item
+
     def updateRecord(self, slicerec):
         change = False
 
     def updateRecord(self, slicerec):
         change = False
 
@@ -116,15 +182,15 @@ class UserModel(QStandardItemModel):
             childStatus = str(item.child(row, MEMBERSHIP_STATUS_COLUMN).data(Qt.DisplayRole).toString())
 
             if (childStatus == user_status['add']):
             childStatus = str(item.child(row, MEMBERSHIP_STATUS_COLUMN).data(Qt.DisplayRole).toString())
 
             if (childStatus == user_status['add']):
-                researcher = slicerec.get_field("researcher", [])
+                researcher = slicerec.get("researcher", [])
                 researcher.append(childName)
                 slicerec["researcher"] = researcher
                 change = True
             elif (childStatus == user_status['remove']):
                 researcher.append(childName)
                 slicerec["researcher"] = researcher
                 change = True
             elif (childStatus == user_status['remove']):
-                if childName in slicerec.get_field("PI"):
-                     slicerec.get_field("PI").remove(childName)
-                if childName in slicerec.get_field("researcher"):
-                     slicerec.get_field("researcher").remove(childName)
+                if childName in slicerec.get("PI"):
+                     slicerec.get("PI").remove(childName)
+                if childName in slicerec.get("researcher"):
+                     slicerec.get("researcher").remove(childName)
                 change = True
 
         return change
                 change = True
 
         return change
@@ -142,15 +208,6 @@ class UserModel(QStandardItemModel):
 
         return researchers
 
 
         return researchers
 
-    def readUserRecord(self, i):
-        rec_file = config.getAuthorityListFile(i)
-        if os.path.exists(rec_file):
-            xml = open(rec_file).read()
-            rec = UserRecord()
-            rec.load_from_string(xml)
-            return rec
-        return None
-
 class UsersWidget(QWidget):
     def __init__(self, parent):
         QWidget.__init__(self, parent)
 class UsersWidget(QWidget):
     def __init__(self, parent):
         QWidget.__init__(self, parent)
@@ -198,35 +255,35 @@ class UsersWidget(QWidget):
         self.updateView()
 
     def submitFinished(self):
         self.updateView()
 
     def submitFinished(self):
-        self.setStatus("<font color='green'>Slice data submitted.</font>")
-        QTimer.singleShot(1000, self.refresh)
+        self.disconnect(self.process, SIGNAL('finished()'), self.submitFinished)
+
+        faultString = self.process.getFaultString()
+        if not faultString:
+            self.setStatus("<font color='green'>Slice user data submitted.</font>")
+            QTimer.singleShot(1000, self.refresh)
+        else:
+            self.setStatus("<font color='red'>Slice user submit failed: %s</font>" % (faultString))
 
     def getSliceRecordFinished(self):
 
     def getSliceRecordFinished(self):
-        self.setStatus("<font color='green'>Authority data refreshed.</font>", timeout=5000)
-        self.refreshAuthority()
+        self.disconnect(self.process, SIGNAL('finished()'), self.getSliceRecordFinished)
+
+        faultString = self.process.getFaultString()
+        if not faultString:
+            self.setStatus("<font color='green'>Slice record refreshed.</font>")
+            self.refreshAuthority()
+        else:
+            self.setStatus("<font color='red'>Slice rec refresh error: %s</font>" % (faultString))
 
     def getAuthorityRecordFinished(self):
 
     def getAuthorityRecordFinished(self):
-        self.setStatus("<font color='green'>Slice data refreshed.</font>", timeout=5000)
-        self.updateView()
-        #self.parent().signalAll("usersUpdated")
+        self.disconnect(self.process, SIGNAL('finished()'), self.getAuthorityRecordFinished)
 
 
-    def readSliceRecord(self):
-        rec_file = config.getSliceRecordFile()
-        if os.path.exists(rec_file):
-            xml = open(rec_file).read()
-            rec = SliceRecord()
-            rec.load_from_string(xml)
-            return rec
-        return None
-
-    def readAuthorityRecord(self):
-        rec_file = config.getAuthorityRecordFile()
-        if os.path.exists(rec_file):
-            xml = open(rec_file).read()
-            rec = AuthorityRecord()
-            rec.load_from_string(xml)
-            return rec
-        return None
+        faultString = self.process.getFaultString()
+        if not faultString:
+            self.setStatus("<font color='green'>User data refreshed.</font>")
+            self.updateView()
+            #self.parent().signalAll("usersUpdated")
+        else:
+            self.setStatus("<font color='red'>Authority rec refresh error: %s</font>" % (faultString))
 
     def setStatus(self, msg, timeout=None):
         self.parent().setStatus(msg, timeout)
 
     def setStatus(self, msg, timeout=None):
         self.parent().setStatus(msg, timeout)
@@ -241,7 +298,7 @@ class UsersWidget(QWidget):
         if self.checkRunningProcess():
             return
 
         if self.checkRunningProcess():
             return
 
-        rec = self.readSliceRecord()
+        rec = SfiData().getSliceRecord()
         change = self.userModel.updateRecord(rec)
 
         if not change:
         change = self.userModel.updateRecord(rec)
 
         if not change:
@@ -251,7 +308,6 @@ class UsersWidget(QWidget):
         rec_file = config.getSliceRecordFile()
         file(rec_file, "w").write(rec.save_to_string())
 
         rec_file = config.getSliceRecordFile()
         file(rec_file, "w").write(rec.save_to_string())
 
-        self.disconnect(self.process, SIGNAL('finished()'), self.getAuthorityRecordFinished)
         self.connect(self.process, SIGNAL('finished()'), self.submitFinished)
 
         self.process.updateRecord(rec_file)
         self.connect(self.process, SIGNAL('finished()'), self.submitFinished)
 
         self.process.updateRecord(rec_file)
@@ -266,21 +322,19 @@ class UsersWidget(QWidget):
             self.setStatus("<font color='red'>There is already a process running. Please wait.</font>")
             return
 
             self.setStatus("<font color='red'>There is already a process running. Please wait.</font>")
             return
 
-        self.disconnect(self.process, SIGNAL('finished()'), self.submitFinished)
         self.connect(self.process, SIGNAL('finished()'), self.getSliceRecordFinished)
 
         self.process.getSliceRecord()
         self.setStatus("Refreshing slice record. This will take some time...")
 
     def refreshAuthority(self):
         self.connect(self.process, SIGNAL('finished()'), self.getSliceRecordFinished)
 
         self.process.getSliceRecord()
         self.setStatus("Refreshing slice record. This will take some time...")
 
     def refreshAuthority(self):
-        self.disconnect(self.process, SIGNAL('finished()'), self.getSliceRecordFinished)
         self.connect(self.process, SIGNAL('finished()'), self.getAuthorityRecordFinished)
 
         self.connect(self.process, SIGNAL('finished()'), self.getAuthorityRecordFinished)
 
-        self.process.listRecords(config.getAuthority(), "user", config.getAuthorityListFile())
+        self.process.listRecords(config.getAuthority(), None)
         self.setStatus("Refreshing user records. This will take some time...")
 
     def updateView(self):
         self.setStatus("Refreshing user records. This will take some time...")
 
     def updateView(self):
-        sliceRec = self.readSliceRecord()
+        sliceRec = SfiData().getSliceRecord()
 
         if not sliceRec:
             # wait until we've resolved the slicerecord before displaying
 
         if not sliceRec:
             # wait until we've resolved the slicerecord before displaying