'''
Created on Apr 4, 2014

@author: mandy
'''

from PyQt4.QtGui import QTableView, QStandardItemModel, QStandardItem, \
                        QHeaderView, QSplitter, QWidget, QBrush, QColor, QFont,\
                        QLabel, QPushButton, QLineEdit, QDialog, QRadioButton, \
                        QMessageBox, QVBoxLayout, QGridLayout, QSizePolicy, QGraphicsDropShadowEffect, \
                        QItemSelectionModel, QTableWidget
from PyQt4.QtCore import QString, Qt, QRect
from Ui_NewItemDlg import Ui_NewItemDlg
from rbacpolicy import *
from EdgeItem import EdgeItem
from UserNode import UserNode
import MyFunctions
import re
try:
    _fromUtf8 = QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class NewItemDialog(QDialog):
    def __init__(self, manager, main):
        QDialog.__init__(self, main)
        self.main = main
        self.manager = manager
        self.ui = Ui_NewItemDlg()      
        self.ui.setupUi(self)
        self.setLayout(self.ui.verticalLayout)
    
    def selectedItemIndex(self):
        for i in xrange(len(self.radioBtnList)):
            if self.radioBtnList[i].isChecked():
                return i
        return -1
    
    def eraseVerticalLayout(self):
        for i in range(self.ui.verticalLayout.count()): self.ui.verticalLayout.itemAt(i).widget().close()
        
    def insertItemDialog(self):
        self.radioBtnList = []
        self.eraseVerticalLayout()
        self.ui.labNewItem = QLabel(self.ui.verticalLayoutWidget)
        self.ui.labNewItem.setGeometry(QRect(10,10,130,20))
        self.ui.labNewItem.setObjectName(_fromUtf8("labNewItem"))
        self.ui.verticalLayout.addWidget(self.ui.labNewItem)
        self.ui.leName = QLineEdit(self.ui.verticalLayoutWidget)
        self.ui.leName.setGeometry(QRect(10, 40, 130, 20))
        self.ui.leName.setObjectName(_fromUtf8("lineEditName"))
        self.ui.verticalLayout.addWidget(self.ui.leName)
        
        self.setFixedHeight(120)
        self.ui.btnOK = QPushButton('OK', self.ui.verticalLayoutWidget)
        self.ui.btnOK.setDefault(True)
        self.ui.btnOK.setGeometry(QRect(10, 70, 130, 20))
        self.ui.btnOK.setObjectName(_fromUtf8("btnOK"))
        self.ui.verticalLayout.addWidget(self.ui.btnOK)
        self.ui.btnOK.clicked.connect(self.insertConfirm)
        
    def deleteItemDialog(self):
        if self.itemId == 0:
            myList = self.main.userList
        elif self.itemId == 1:
            myList = self.main.roleList
        else:
            myList = self.main.dirList
        listLen = len(myList)
        if listLen>0:
            self.radioBtnList = []
            self.eraseVerticalLayout()
            self.ui.labNewItem = QLabel(self.ui.verticalLayoutWidget)
            self.ui.labNewItem.setGeometry(QRect(10,10,130,20))
            self.ui.labNewItem.setObjectName(_fromUtf8("labNewItem"))
            self.ui.verticalLayout.addWidget(self.ui.labNewItem)
            self.setFixedHeight(40*listLen+40)
            for i in xrange(listLen):
                radiobutton = QRadioButton(QString(myList[i]), self)
                if i==0:
                    radiobutton.setChecked(True)
                self.ui.verticalLayout.addWidget(radiobutton)
                radiobutton.show()
                self.radioBtnList.append(radiobutton)
            self.ui.btnOK = QPushButton('OK', self.ui.verticalLayoutWidget)
            self.ui.btnOK.setDefault(True)
            self.ui.btnOK.setGeometry(QRect(10, 70, 130, 20))
            self.ui.btnOK.setObjectName(_fromUtf8("btnOK"))
            self.ui.verticalLayout.addWidget(self.ui.btnOK)
            self.ui.btnOK.clicked.connect(self.deleteConfirm)
            
    def insertConfirm(self):
        name = str(self.ui.leName.text())
        if len(name)>0: 
            if MyFunctions.nameOnlyContainLetterNumbers(name):
                if self.itemId == 0:
                    if MyFunctions.checkNameDuplication(name, self.main.userList):
                        QMessageBox.warning(self, '', 'Duplicated name. Please input another name!', buttons = QMessageBox.Close)
                    else:
                        self.main.userList.append(name)
                        self.main.numUsers = len(self.main.userList)
                        self.manager.updateRoleUserTableView()
                        self.close()
                elif self.itemId == 1:
                    if MyFunctions.checkNameDuplication(name, self.main.roleList):
                        QMessageBox.warning(self, '', 'Duplicated name. Please input another name', buttons = QMessageBox.Close)
                    else:
                        self.main.roleList.append(name)
                        self.main.numRoles = len(self.main.roleList)
                        self.manager.updateRoleUserTableView()
                        self.manager.updateRolePermTableView()
                        self.close()
                elif self.itemId == 2:
                    if MyFunctions.checkNameDuplication(name, self.main.dirList):
                        QMessageBox.warning(self, '', 'Duplicated name. Please input another name', buttons = QMessageBox.Close)
                    else:
                        self.main.dirList.append(name)
                        self.main.numDirs = self.main.computeSpec.getNumDirs()
                        self.manager.updateRolePermTableView()
                        self.close()
            else:
                QMessageBox.warning(self, '', 'Please input a name that only contains letters and numbers', buttons = QMessageBox.Close)
        else:
            QMessageBox.warning(self, '', 'Please input a name', buttons = QMessageBox.Close)
            
    def deleteConfirm(self):
        index = self.selectedItemIndex()
        if self.itemId == 0:
            ret = QMessageBox.warning(self, '', 'Are you sure to delete selected user?', buttons = QMessageBox.Yes| QMessageBox.No, defaultButton=QMessageBox.No)
            if ret == QMessageBox.Yes and index != -1:
                del self.main.user_role_mat[self.main.userList[index]]
                del self.main.userList[index] 
                self.main.numUsers = self.main.computeSpec.getNumUsers()
                self.manager.updateRoleUserTableView()
        elif self.itemId == 1:
            ret = QMessageBox.warning(self, '', 'Are you sure to delete selected role?', buttons = QMessageBox.Yes| QMessageBox.No, defaultButton=QMessageBox.No)
            if ret == QMessageBox.Yes and index != -1:
                for r in self.main.user_role_mat.values():
                    if self.main.roleList[index] in r:
                        r.remove(self.main.roleList[index])
                del self.main.role_res_mat[self.main.roleList[index]]
                del self.main.roleList[index]
                self.main.numRoles = self.main.computeSpec.getNumRoles()
                self.manager.updateRoleUserTableView()
                self.manager.updateRolePermTableView()
        else:
            ret = QMessageBox.warning(self, '', 'Are you sure to delete selected directory?', buttons = QMessageBox.Yes| QMessageBox.No, defaultButton=QMessageBox.No)
            if ret == QMessageBox.Yes and index != -1:
                for perm in self.main.role_res_mat.values():
                    for direc in perm.keys():
                        if direc == self.main.dirList[index]:
                            del perm[dir]
                del self.main.dirList[index]
                self.main.dirSet = self.main.computeSpec.getDirSet()
                self.main.numDirs = self.main.computeSpec.getNumDirs()
                self.manager.updateRolePermTableView()
        self.close()
            
class TableView(QWidget):
    lightBlue = QColor(51, 127, 255, 127)
    lightRed = QColor(227, 26, 51, 127)
    main = None
    splitter = None
    viewRect = None
    tableViewRoleUser = None
    tableViewRolePerm = None
    Font_SIZE = 15#25
    
    def __init__(self, parent, main):
        QWidget.__init__(self, parent)
        self.main = main
        self.selectionIndexSet = set()
        self.newItemDialog = NewItemDialog(self, self.main)
        self.font = QFont("Calibri")
        self.font.setPixelSize(self.Font_SIZE)
        self.viewRect = parent.geometry()
        self.verticalLayout = QVBoxLayout(parent)
        self.splitter = QSplitter(Qt.Vertical)
        self.splitter.setStyleSheet("QSplitter { background-color : #CEECF5;}")
        self.verticalLayout.addWidget(self.splitter)
        self.verticalLayout.setMargin(0)
        self.setupTableViews()
        layoutWidget1 = QWidget()
        gridLayout1 = QGridLayout()
        layoutWidget1.setLayout(gridLayout1)
        gridLayout1.setSpacing (0)
        gridLayout1.setMargin(0)
  
        self.splitter.addWidget(layoutWidget1)
        self.titleUserView = QLabel(layoutWidget1)
        self.titleUserView.setText(QString('Users'))
        self.titleUserView.setAlignment(Qt.AlignCenter)
#         self.titleUserView.setStyleSheet("QLabel { background-color : #CEECF5; font: 25px;}")
        self.titleUserView.setStyleSheet("QLabel { background-color : #CEECF5; font: 15px;}")
        self.titleUserView.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
        self.titleRoleView = QLabel(layoutWidget1)
        self.titleRoleView.setText(QString('Roles'))
        self.titleRoleView.setAlignment(Qt.AlignCenter)
#         self.titleRoleView.setStyleSheet("QLabel { background-color :#CEECF5; font: 25px;}")
        self.titleRoleView.setStyleSheet("QLabel { background-color :#CEECF5; font: 15px;}")
        self.titleRoleView.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        gridLayout1.addWidget(self.titleRoleView, 0,1, 1, 10)
        gridLayout1.addWidget(self.titleUserView, 1,0, 10, 1)
        gridLayout1.addWidget(self.tableViewRoleUser, 1, 1, 10, 10)
        
        layoutWidget2 = QWidget()
        gridLayout2 = QGridLayout()
        layoutWidget2.setLayout(gridLayout2)
        gridLayout2.setSpacing (0)
        self.splitter.addWidget(layoutWidget2)
        
        self.titleDirView = QLabel(layoutWidget2)
        self.titleDirView.setText(QString('Objects'))
        self.titleDirView.setAlignment(Qt.AlignCenter)
#         self.titleDirView.setStyleSheet("QLabel { background-color : #CEECF5; font: 25px;}")
        self.titleDirView.setStyleSheet("QLabel { background-color : #CEECF5; font: 15px;}")
        self.titleDirView.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.titleRoleView1 = QLabel(layoutWidget2)
        self.titleRoleView1.setText(QString('Roles'))
        self.titleRoleView1.setAlignment(Qt.AlignCenter)
#         self.titleRoleView1.setStyleSheet("QLabel { background-color :#CEECF5; font: 25px;}")
        self.titleRoleView1.setStyleSheet("QLabel { background-color :#CEECF5; font: 15px;}")
        self.titleRoleView1.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
        gridLayout2.addWidget(self.titleDirView, 0,1, 1, 10)
        gridLayout2.addWidget(self.titleRoleView1, 1,0, 10, 1)
        gridLayout2.addWidget(self.tableViewRolePerm, 1, 1, 10, 10)
        gridLayout2.setMargin(0)
        
        self.tableViewRoleUser.verticalHeader().setFont(self.font)
        self.tableViewRolePerm.verticalHeader().setFont(self.font)
        self.tableViewRoleUser.horizontalHeader().setFont(self.font)
        self.tableViewRolePerm.horizontalHeader().setFont(self.font)

        self.tableViewRoleUser.verticalHeader().setResizeMode(QHeaderView.Stretch)
        self.tableViewRolePerm.verticalHeader().setResizeMode(QHeaderView.Stretch)
        self.tableViewRoleUser.horizontalHeader().setResizeMode(QHeaderView.Stretch)
        self.tableViewRolePerm.horizontalHeader().setResizeMode(QHeaderView.Stretch)
        
    def resize(self, rectArea):
        self.viewRect = rectArea
        
    def show(self):
        self.tableViewRoleUser.show()
        self.tableViewRolePerm.show()
        self.splitter.show()
        
    def hide(self):
        self.tableViewRoleUser.hide()
        self.tableViewRolePerm.hide()
        self.splitter.hide()
    
    def clearSelectionInView(self, tView):
        numRows = tView.model().rowCount()
        numCols = tView.model().columnCount()
        for i in xrange(numRows):
            for j in xrange(numCols):
                index = tView.model().index(i, j)
                tView.selectionModel().select(index, QItemSelectionModel.Deselect)
                
    def getHorizontalHeaderText(self, tView, index):
        if tView == self.tableViewRoleUser:
            return self.main.roleList[index]
        elif tView == self.tableViewRolePerm:
            return self.main.dirList[index]
            
    def getVerticalHeaderText(self, tView, index):
        if tView == self.tableViewRoleUser:
            return self.main.userList[index]
        elif tView == self.tableViewRolePerm:
            return self.main.roleList[index]
    
    def highlightCell(self, tView, row, col):
        index = tView.model().index(row, col)
        tView.selectionModel().select(index, QItemSelectionModel.Select)
        
    def readCellContent(self, tView, row, col):
        index = tView.model().index(row, col)
        return index.data(Qt.DisplayRole).toString()
        
    def cellContentEmpty(self, tView, row, col):
        content = self.readCellContent(tView, row, col)
        if content == '':
            return True
        else:
            return False
        
    def updateRoleUserTableView(self):
        self.tableViewRoleUser.model().clear()
        model = QStandardItemModel(self.main.numUsers,self.main.numRoles,self.tableViewRoleUser)
        for i in xrange(self.main.numUsers):
            headerItem = QStandardItem(QString(self.main.userList[i]))
            headerItem.setFont(self.font)
            model.setVerticalHeaderItem(i, headerItem)
            if self.main.userList[i] in self.main.user_role_mat.keys():
                for r in self.main.user_role_mat.get(self.main.userList[i]):
                    index = self.main.roleList.index(r)
                    checkSign = QStandardItem(QString("X"))
                    self.font = QFont("Calibri")
                    self.font.setPixelSize(self.Font_SIZE)
                    checkSign.setFont(self.font)
                    checkSign.setTextAlignment(Qt.AlignCenter)
                    model.setItem(i, index, checkSign)       
        for i in xrange(self.main.numRoles):
            model.setHorizontalHeaderItem(i, QStandardItem(QString(self.main.roleList[i])))
        self.tableViewRoleUser.setModel(model)
        self.tableViewRoleUserModel = model
        self.tableViewRoleUser.model().itemChanged.connect(lambda newItem: self.tableViewRoleUserCellChange(newItem))
        self.tableViewRoleUser.clicked.connect(lambda index: self.highlightChildRoleUsers(index))
        self.tableViewRoleUser.verticalHeader().sectionPressed.connect(lambda row: self.userRowClicked(row))
        self.tableViewRoleUser.horizontalHeader().sectionPressed.connect(self.roleColClicked)
        
    def roleColClicked(self):
        self.clearSelectionInView(self.tableViewRolePerm)
        
    def userRowClicked(self, row):
        self.clearSelectionInView(self.tableViewRoleUser)
        self.clearSelectionInView(self.tableViewRolePerm)
        user = self.main.userList[row]
        roles = set()
        if user in self.main.user_role_mat.keys():
            roles = self.main.user_role_mat[user]
        visited, queue = set(), list(roles)
        while queue:
            vertex = queue.pop(0)
            if vertex not in visited:
                visited.add(vertex)
                if vertex in self.main.role_adjmat.keys():
                    connected = self.main.role_adjmat[vertex].children
                    queue.extend(connected-visited)
        roles = visited
        for r in roles:
            roleindex = self.main.roleList.index(r)
            self.highlightCell(self.tableViewRoleUser, row, roleindex)
            for i in xrange(len(self.main.dirList)):
                if not self.cellContentEmpty(self.tableViewRolePerm, roleindex, i):
                    self.highlightCell(self.tableViewRolePerm, roleindex, i)
        message = "MView: User("+ user+ "): Clicked\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
            
    def dirColClicked(self, col):
        self.clearSelectionInView(self.tableViewRoleUser)
        self.clearSelectionInView(self.tableViewRolePerm)
        odir = self.main.dirList[col]
        roles = set()
        dirnode = None
        for d in self.main.dirNodes:
            if d.dir == odir:
                dirnode = d
        for r in dirnode.roleNodes:
            roles.add(r.name)
        visited, queue = set(), list(roles)
        while queue:
            vertex = queue.pop(0)
            if vertex not in visited:
                visited.add(vertex)
                if vertex in self.main.role_adjmat.keys():
                    connected = self.main.role_adjmat[vertex].parents
                    queue.extend(connected-visited)
        roles = visited
        for r in roles:
            roleindex = self.main.roleList.index(r)
            self.highlightCell(self.tableViewRolePerm, roleindex, col)
            for i in xrange(len(self.main.userList)):
                if not self.cellContentEmpty(self.tableViewRoleUser, i, roleindex):
                    self.highlightCell(self.tableViewRoleUser, i, roleindex)
        message = "MView: Obj("+ odir+ "): Clicked\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        
    def highlightChildRoleUsers(self, index):
        self.clearSelectionInView(self.tableViewRolePerm)
        col = index.column()
        row = index.row()
        role = self.getHorizontalHeaderText(self.tableViewRoleUser, col)
        user = self.getVerticalHeaderText(self.tableViewRoleUser, row)
        roleindex = self.main.roleList.index(role)
        rolenode = None
        pos = set()
        for r in self.main.roleCompactNodes:
            if role == r.name:
                rolenode = r
        for r in rolenode.allChildrenNodes:
            index = self.main.roleList.index(r.name)
            pos.add(index)
        for i in pos:
            self.highlightCell(self.tableViewRoleUser, row, i)
        for i in xrange(len(self.main.dirList)):
            for j in pos:
                if not self.cellContentEmpty(self.tableViewRolePerm, j, i):
                    self.highlightCell(self.tableViewRolePerm, j, i)
            if not self.cellContentEmpty(self.tableViewRolePerm, roleindex, i):
                self.highlightCell(self.tableViewRolePerm, roleindex, i)
        message = "MView: CellRolUser("+ role+','+user +"): Clicked to get all objs and roles that user has access to\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        
    def highlightParentRoleDirs(self, index):
        self.clearSelectionInView(self.tableViewRoleUser)
        row = index.row()
        col = index.column()
        role = self.getVerticalHeaderText(self.tableViewRolePerm, row)
        obj = self.getHorizontalHeaderText(self.tableViewRolePerm, col)
        roleindex = self.main.roleList.index(role)
        rolenode = None
        pos = set()
        for r in self.main.roleCompactNodes:
            if role == r.name:
                rolenode = r
        for r in rolenode.allParentNodes:
            index = self.main.roleList.index(r.name)
            pos.add(index)
        for j in pos:
            self.highlightCell(self.tableViewRolePerm, j, col)
        for j in xrange(len(self.main.userList)):
            for i in pos:
                if not self.cellContentEmpty(self.tableViewRoleUser, j, i):
                    self.highlightCell(self.tableViewRoleUser, j, i)
            if not self.cellContentEmpty(self.tableViewRoleUser, j, roleindex):
                self.highlightCell(self.tableViewRoleUser, j, roleindex)
        message = "MView: CellRolObj("+ role+','+obj +"): Clicked to get all users and roles accessible to the object\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        
    def updateRolePermTableView(self):
        model = QStandardItemModel(self.main.numRoles,self.main.numDirs,self.tableViewRolePerm)
        for i in xrange(self.main.numRoles):
            model.setVerticalHeaderItem(i, QStandardItem(QString(self.main.roleList[i])))
            if self.main.roleList[i] in self.main.role_res_mat.keys():
                objList, permIter, permissions, permissionStrings, completePermStringList = self.main.computeSpec.getObjPermForRole(self.main.roleList[i])
                for k in xrange(len(objList)):
                    index = self.main.dirList.index(objList[k])
                    if permIter[k]:
                        pStr = QStandardItem(QString('-r | '+permissionStrings[k]))
                        pStr.setBackground(QBrush(Qt.yellow))
                    else:
                        pStr = QStandardItem(QString(permissionStrings[k]))
                    self.font = QFont("Calibri")
                    self.font.setPixelSize(self.Font_SIZE)
                    pStr.setFont(self.font)
                    pStr.setTextAlignment(Qt.AlignCenter)
                    model.setItem(i, index, pStr)
        for i in xrange(self.main.numDirs):
            model.setHorizontalHeaderItem(i, QStandardItem(QString(self.main.dirList[i])))
        self.tableViewRolePerm.setModel(model)
        self.tableViewRolePermModel = model
        self.tableViewRolePerm.model().itemChanged.connect(lambda newItem: self.tableViewRolePermCellChange(newItem))
        self.tableViewRolePerm.clicked.connect(lambda index: self.highlightParentRoleDirs(index))
        self.tableViewRolePerm.horizontalHeader().sectionPressed.connect(lambda col: self.dirColClicked(col))
        self.tableViewRolePerm.verticalHeader().sectionPressed.connect(self.roleRowClicked)
        
    def roleRowClicked(self):
        self.clearSelectionInView(self.tableViewRoleUser)
        
    def setupTableViews(self):
        self.tableViewRoleUser = QTableView()
        self.tableViewRoleUser.setCornerButtonEnabled(False)
        model = QStandardItemModel(self.main.numUsers,self.main.numRoles,self.tableViewRoleUser)
        for i in xrange(self.main.numUsers):
            model.setVerticalHeaderItem(i, QStandardItem(QString(self.main.userList[i])))
            for r in self.main.user_role_mat.get(self.main.userList[i]):
                index = self.main.roleList.index(r)
                checkSign = QStandardItem(QString("X"))
                self.font = QFont("Calibri")
                self.font.setPixelSize(self.Font_SIZE)
                checkSign.setFont(self.font)
                checkSign.setForeground(Qt.red)
                checkSign.setTextAlignment(Qt.AlignCenter)
                model.setItem(i, index, checkSign)       
        for i in xrange(self.main.numRoles):
            model.setHorizontalHeaderItem(i, QStandardItem(QString(self.main.roleList[i])))
        self.tableViewRoleUser.setModel(model)
        self.tableViewRoleUserModel = model
        self.tableViewRoleUser.model().itemChanged.connect(lambda newItem: self.tableViewRoleUserCellChange(newItem))
        
        self.tableViewRolePerm = QTableView()
        self.tableViewRolePerm.setCornerButtonEnabled(False)
        model = QStandardItemModel(self.main.numRoles,self.main.numDirs,self.tableViewRolePerm)
        for i in xrange(self.main.numRoles):
            model.setVerticalHeaderItem(i, QStandardItem(QString(self.main.roleList[i])))
            if self.main.roleList[i] in self.main.role_res_mat.keys():
                objList, permIter, permissions, permissionStrings, completePermStringList = self.main.computeSpec.getObjPermForRole(self.main.roleList[i])
                for k in xrange(len(objList)):
                    index = self.main.dirList.index(objList[k])
                    if permIter[k]:
                        pStr = QStandardItem(QString('-r | '+permissionStrings[k]))
                        pStr.setBackground(QBrush(Qt.yellow))
                    else:
                        pStr = QStandardItem(QString(permissionStrings[k]))
                    pStr.setFont(self.font)
                    pStr.setTextAlignment(Qt.AlignCenter)
                    model.setItem(i, index, pStr) 
        for i in xrange(self.main.numDirs):
            model.setHorizontalHeaderItem(i, QStandardItem(QString(self.main.dirList[i])))
         
        self.tableViewRolePerm.setModel(model)
        self.tableViewRolePermModel = model
        self.tableViewRolePerm.model().itemChanged.connect(lambda newItem: self.tableViewRolePermCellChange(newItem))
            
    def tableViewRoleUserCellChange(self, newItem):
        user = self.main.userList[newItem.row()]
        role = self.main.roleList[newItem.column()]
        rolenode = self.main.policyManager.findRoleNode(role, self.main.roleCompactNodes)
        if newItem.text() == '' or re.match("^ *$", newItem.text()):
            self.tableViewRoleUser.model().setData(newItem.index(), '')
            if role in self.main.user_role_mat[user]:
                self.main.user_role_mat[user].remove(role)
                if self.main.user_role_mat[user] == set():
                    del self.main.user_role_mat[user]
                for u in rolenode.userNodes:
                    if u.name == user:
                        rolenode.userNodes.remove(u)
                        self.main.userNodes.remove(u)
                        self.main.scene.removeItem(u)
                        for e in self.main.scene.items():
                            if isinstance(e, EdgeItem):
                                if e.startItem==u or e.endItem == u:
                                    self.main.scene.removeItem(e)
                                    del e
                        del u
            message = "MView: CellRolUser("+ role+','+user +"): Assign Change(Yes>No)\n"
        else:
            self.tableViewRoleUserModel.setData(newItem.index(), 'X')
            self.tableViewRoleUserModel.item(newItem.row(), newItem.column()).setTextAlignment(Qt.AlignCenter)
            if user not in self.main.user_role_mat.keys():
                self.main.user_role_mat[user] = set()
            if role not in self.main.user_role_mat[user]:
                self.main.user_role_mat[user].add(role)
                freeusernodeExistFlag = False
                for u in self.main.userNodes:
                    if u.name == user and u.roleNode==None:
                        usernode = u
                        freeusernodeExistFlag = True
                if not freeusernodeExistFlag:
                    usernode = UserNode(user, self.main)
                    self.main.userNodes.append(usernode)
                    self.main.scene.addItem(usernode)
                rolenode.userNodes.append(usernode)
                usernode.roleNode = rolenode
                edge = EdgeItem(EdgeItem.SEPARATE_ROLEUSER_CONN, rolenode, usernode, self.main)
                usernode.edgeList.append(edge)
                self.main.scene.addItem(edge)
            message = "MView: CellRolUser("+ role+','+user +"): Assign Change(No>Yes)\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)

        self.main.toolBox.ui.getContentForComboBox()
        self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
        if self.main.hasSolidEdgeFlag or self.main.role_adjmat == {}:
            self.main.evenlyLayout(self.main.scene, self.main.roleCompactHier)
        if len(self.main.roleCompactHier) == len(self.main.roleSet):
            self.main.evenlyLayout(self.main.scene, self.main.roleCompactCompleteHier)

    def tableViewRoleUserClick(self, index):
        self.main.ui.actionInsertUser.setEnabled(True)
        self.main.ui.actionDeleteUser.setEnabled(True)
        self.main.ui.actionInsertRole.setEnabled(True)
        self.main.ui.actionDeleteRole.setEnabled(True)
    
    def getPermissionsFromInput(self, text):
        perms=set()
        if text.find('r')!=-1:
            perms.add('r')
        if text.find('w')!=-1:
            perms.add('w')
        if text.find('x')!=-1:
            perms.add('x')
        return perms
    
    def tableViewRolePermCellChange(self, newItem):
        role = self.main.roleList[newItem.row()]
        obj = self.main.dirList[newItem.column()]
        content = self.readCellContent(self.tableViewRolePerm, newItem.row(), newItem.column())
#         p = re.compile("^(\s)*(-r)*(\s)*|*(\s)*(r(wx?|xw?)?|w(rx?|xr?)?|x(rw?|wr?)?)$")
#         p = re.compile('^(\s)*(-r)*(\s)*|*(\s)*[crxdw]+$')
#         if not p.match(newItem.text()):
#             QMessageBox.warning(self, '', "Invalid entry. Please enter a combination of 'r', 'w', and 'x' with or without '-r|' in front!", buttons = QMessageBox.Close)
#             return
        if newItem.text() == '' or re.match("^ *$", newItem.text()):
        #if newItem.text() == '':
        #if newItem.text() == '' or re.match("^(\s)*(-r)*(\s)*|*(\s)*[r,w,x]$", newItem.text()):
            '''remove role dir relation'''
            self.tableViewRolePerm.model().setData(newItem.index(), '')
            del self.main.role_res_mat[role][obj]
            if self.main.role_res_mat[role] == {}:
                del self.main.role_res_mat[role]
            rolenode = self.main.policyManager.findRoleNode(role, self.main.roleCompactNodes)
            dirnode = self.main.policyManager.findDirNode(obj, self.main.dirNodes)
            rolenode.dirNodes.remove(dirnode)
            dirnode.roleNodes.remove(rolenode)
            message = "MView: CellRolObj("+ role+','+obj+"): Permission Change("+content+'>'+newItem.text()+")\n"
        else:
            text = str(newItem.text())
            if text.find('-r')!= -1:
                permIter = True
                permissions = text[text.find('|')+1:]
                perms = self.getPermissionsFromInput(permissions)
                #permset = makepermset(set(permissions), permIter)
                self.tableViewRolePermModel.item(newItem.row(), newItem.column()).setBackground(QBrush(Qt.yellow))
            else:
                '''add role dir relation'''
                permIter = False
                perms = self.getPermissionsFromInput(text)
                self.tableViewRolePermModel.item(newItem.row(), newItem.column()).setBackground(QBrush(Qt.white))
            self.tableViewRolePermModel.item(newItem.row(), newItem.column()).setTextAlignment(Qt.AlignCenter)
            self.main.policyManager.addRole_modifyDirInPolicy(obj, role, permIter, perms)
            message = "MView: CellRolObj("+ role+','+obj +"): Permission Change("+content+'>'+text+")\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        self.main.toolBox.ui.getContentForComboBox()
        self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
        if self.main.hasSolidEdgeFlag or self.main.role_adjmat == {}:
            self.main.evenlyLayout(self.main.scene, self.main.roleCompactHier)
        if len(self.main.roleCompactHier) == len(self.main.roleSet):
            self.main.evenlyLayout(self.main.scene, self.main.roleCompactCompleteHier)

    def tableViewRolePermClick(self, index):
        self.main.ui.actionInsertRole.setEnabled(True)
        self.main.ui.actionDeleteRole.setEnabled(True)
        self.main.ui.actionInsertDir.setEnabled(True)
        self.main.ui.actionDeleteDir.setEnabled(True)
        
    '''toolbar response'''
    def insertNewUser(self):
        self.newItemDialog.itemId = 0
        self.newItemDialog.insertItemDialog()
        self.newItemDialog.ui.labNewItem.setText('New User:')
        self.newItemDialog.show()
        
    def insertNewRole(self):
        self.newItemDialog.itemId = 1
        self.newItemDialog.insertItemDialog()
        self.newItemDialog.ui.labNewItem.setText('New Role:')
        self.newItemDialog.show()
        
    def insertNewDir(self):
        self.newItemDialog.itemId = 2
        self.newItemDialog.insertItemDialog()
        self.newItemDialog.ui.labNewItem.setText('New Directory:')
        self.newItemDialog.show()
        
    def deleteSelectedUser(self):
        self.newItemDialog.itemId = 0
        self.newItemDialog.deleteItemDialog()
        self.newItemDialog.ui.labNewItem.setText('Delete User:')
        self.newItemDialog.show()
        
    def deleteSelectedRole(self):
        self.newItemDialog.itemId = 1
        self.newItemDialog.deleteItemDialog()
        self.newItemDialog.ui.labNewItem.setText('Delete Role:')
        self.newItemDialog.show()
        
    def deleteSelectedDir(self):
        self.newItemDialog.itemId = 2
        self.newItemDialog.deleteItemDialog()
        self.newItemDialog.ui.labNewItem.setText('Delete Directory:')
        self.newItemDialog.show()
        
        
    