コード例 #1
0
ファイル: view_str.py プロジェクト: timlinux/stdm_plugin
    def initGui(self):
        '''
        Initialize widget
        '''
        self.loadEntityConfig()
        #Hook up signals
        self.connect(self.tbSTREntity, SIGNAL("currentChanged(int)"),
                     self.entityTabIndexChanged)
        self.connect(self.btnSearch, SIGNAL("clicked()"),
                     self.searchEntityRelations)
        self.connect(self.btnClearSearch, SIGNAL("clicked()"),
                     self.clearSearch)
        self.connect(self.tvSTRResults, SIGNAL("expanded(const QModelIndex&)"),
                     self.onTreeViewItemExpanded)

        #Configure notification bars
        self.notifSearchConfig = NotificationBar(self.vlSearchEntity)

        #Set the results treeview to accept requests for context menus
        self.tvSTRResults.setContextMenuPolicy(Qt.CustomContextMenu)
        self.connect(self.tvSTRResults,
                     SIGNAL("customContextMenuRequested(const QPoint&)"),
                     self.onResultsContextMenuRequested)

        #Load async for the current widget
        self.entityTabIndexChanged(0)
コード例 #2
0
ファイル: new_str_wiz.py プロジェクト: SolomonN/stdm_plugin
 def initConflict(self):
     '''
     Initialize 'Conflict' GUI controls
     '''
     loadComboSelections(self.cboConflictOccurrence, CheckConflictState) 
     
     self.notifConflict = NotificationBar(self.vlConflictNotif,3000)
コード例 #3
0
ファイル: new_str_wiz.py プロジェクト: 7o9/stdm-plugin
 def initSourceDocument(self):
     '''
     Initialize source document page
     '''
     #Set currency regular expression and currency prefix
     rx = QRegExp("^\\d{1,12}(([.]\\d{2})*),(\\d{2})$")
     rxValidator = QRegExpValidator(rx,self)
     '''
     self.txtCFBPAmount.setValidator(rxValidator)
     self.txtStateReceiptAmount.setValidator(rxValidator)
     
     self.dtLastYearCFBP.setMaximumDate(QDate.currentDate())
     self.dtStateReceiptDate.setMaximumDate(QDate.currentDate())
     self.dtStateLeaseYear.setMaximumDate(QDate.currentDate())  
     '''
     self.notifSourceDoc = NotificationBar(self.vlSourceDocNotif)
     
     #Set source document manager
     self.sourceDocManager = SourceDocumentManager()
     #self.privateTaxDocManager = SourceDocumentManager()
     #self.stateTaxDocManager = SourceDocumentManager()
     self.sourceDocManager.registerContainer(self.vlDocTitleDeed, TITLE_DEED)
            
     '''
     #Connect signals
     self.connect(self.rbPrivateProperty, SIGNAL("toggled(bool)"),self.onSelectPrivateProperty)
     self.connect(self.rbStateland, SIGNAL("toggled(bool)"),self.onSelectStateland)
     
     self.connect(self.btnPrivateReceiptScan, SIGNAL("clicked()"),self.onUploadPrivateReceiptScan)
     self.connect(self.btnPublicReceiptScan, SIGNAL("clicked()"),self.onUploadStateReceiptScan)
     self.connect(self.btnAddStatRefPaper, SIGNAL("clicked()"),self.onUploadStatutoryRefPaper)
     self.connect(self.btnAddSurveyorRef, SIGNAL("clicked()"),self.onUploadSurveyorRef)
     self.connect(self.btnAddNotaryRef, SIGNAL("clicked()"),self.onUploadNotaryRef)
     '''
     self.connect(self.btnAddTitleDeed, SIGNAL("clicked()"),self.onUploadTitleDeed)
コード例 #4
0
ファイル: new_str_wiz.py プロジェクト: SolomonN/stdm_plugin
 def initProperty(self):
     '''
     Initialize property config
     '''
     self.notifProp = NotificationBar(self.vlPropNotif)
     self.gpOLTitle = self.gpOpenLayers.title()
     
     #Flag for checking whether OpenLayers basemaps have been loaded
     self.olLoaded = False
     
     #Initialize lookup for properties
     propertyWorker = PropertyWorker(self)
     self.connect(propertyWorker, SIGNAL("retrieved(PyQt_PyObject)"), self._onPropertiesLoaded)
     
     #Connect signals
     QObject.connect(self.gpOpenLayers, SIGNAL("toggled(bool)"), self._onEnableOLGroupbox)             
     QObject.connect(self.zoomSlider, SIGNAL("sliderReleased()"), self._onZoomChanged)
     QObject.connect(self.btnResetMap , SIGNAL("clicked()"), self._onResetMap)
     
     #Start background thread
     propertyWorker.start()   
     
     self.propBrowser = PropertyBrowser(self.propWebView,self)
     self.connect(self.propBrowser,SIGNAL("loadError(QString)"),self._onPropertyBrowserError)
     self.connect(self.propBrowser,SIGNAL("loadProgress(int)"),self._onPropertyBrowserLoading)
     self.connect(self.propBrowser,SIGNAL("loadFinished(bool)"),self._onPropertyBrowserFinished)
     self.connect(self.propBrowser,SIGNAL("zoomChanged(int)"),self.onMapZoomLevelChanged)
         
     #Connect signals
     QObject.connect(self.rbGMaps, SIGNAL("toggled(bool)"),self.onLoadGMaps)          
     QObject.connect(self.rbOSM, SIGNAL("toggled(bool)"),self.onLoadOSM)                               
コード例 #5
0
    def __init__(self, parent=None, selectMode=True):
        QDialog.__init__(self, parent)
        self.setupUi(self)

        self.notifBar = NotificationBar(self.vlNotification)

        if selectMode:
            self.buttonBox.setVisible(True)
            self.manageButtonBox.setVisible(False)
            currHeight = self.size().height()
            self.resize(200, currHeight)

        else:
            self.buttonBox.setVisible(False)
            self.manageButtonBox.setVisible(True)
            self.setWindowTitle(
                QApplication.translate("TemplateDocumentSelector",
                                       "Template Manager"))

        #Configure manage buttons
        btnEdit = self.manageButtonBox.button(QDialogButtonBox.Ok)
        btnEdit.setText(
            QApplication.translate("TemplateDocumentSelector", "Edit..."))
        btnEdit.setIcon(QIcon(":/plugins/stdm/images/icons/edit.png"))

        btnDelete = self.manageButtonBox.button(QDialogButtonBox.Save)
        btnDelete.setText(
            QApplication.translate("TemplateDocumentSelector", "Delete"))
        btnDelete.setIcon(QIcon(":/plugins/stdm/images/icons/delete.png"))

        #Connect signals
        self.buttonBox.accepted.connect(self.onAccept)
        btnEdit.clicked.connect(self.onEditTemplate)
        btnDelete.clicked.connect(self.onDeleteTemplate)

        #Get saved document templates then add to the model
        templates = documentTemplates()

        self._docItemModel = QStandardItemModel(parent)
        self._docItemModel.setColumnCount(2)

        for name, path in templates.iteritems():
            docNameItem = self._createDocNameItem(name)
            filePathItem = QStandardItem(path)
            self._docItemModel.appendRow([docNameItem, filePathItem])

        self.lstDocs.setModel(self._docItemModel)
コード例 #6
0
ファイル: new_str_wiz.py プロジェクト: SolomonN/stdm_plugin
 def initSTRType(self):
     '''
     Initialize 'Social Tenure Relationship' GUI controls
     '''
     loadComboSelections(self.cboSTRType, CheckSocialTenureRelationship) 
     
     self.notifSTR = NotificationBar(self.vlSTRTypeNotif)
     
     #Register STR selection field
     self.frmWizSTRType.registerField("STR_Type",self.cboSTRType)
コード例 #7
0
ファイル: new_str_wiz.py プロジェクト: SolomonN/stdm_plugin
 def initEnjoymentRight(self):
     '''
     Initialize 'Right of Enjoyment' GUI controls
     '''
     self.dtReceivingDate.setMaximumDate(QDate.currentDate())
     
     loadComboSelections(self.cboInheritanceType, CheckInheritanceType) 
     loadComboSelections(self.cboDeadAlive, CheckDeadAlive) 
     
     self.notifEnjoyment = NotificationBar(self.vlEnjoymentNotif)
コード例 #8
0
 def __init__(self, parent=None):
     """
     This class checks if the user has accepted the
     license terms and conditions or not . It shows the
     terms and conditions if not.
     :param parent: The container of the dialog
     :type parent: QMainWindow or None
     :return: None
     :rtype: NoneType
     """
     QDialog.__init__(self, parent)
     self.setupUi(self)
     self.reg_config = RegistryConfig()
     self.notice_bar = NotificationBar(self.notifBar)
     self.accepted = False
     self.btnAccept.clicked.connect(self.accept_action)
     self.btnDecline.clicked.connect(self.decline_action)
     self.label.setStyleSheet('''
         QLabel {
             font: bold;
         }
         ''')
コード例 #9
0
ファイル: new_str_wiz.py プロジェクト: Guillon88/stdm
 def initSourceDocument(self):
     '''
     Initialize source document page
     '''
     #Set currency regular expression and currency prefix
     rx = QRegExp("^\\d{1,12}(([.]\\d{2})*),(\\d{2})$")
     rxValidator = QRegExpValidator(rx,self)
     '''
     '''
     self.notifSourceDoc = NotificationBar(self.vlSourceDocNotif)
     
     #Set source document manager
     self.sourceDocManager = SourceDocumentManager()
     self.sourceDocManager.registerContainer(self.vlDocTitleDeed, DEFAULT_DOCUMENT)
     self.connect(self.btnAddTitleDeed, SIGNAL("clicked()"),self.onUploadTitleDeed)
コード例 #10
0
ファイル: new_str_wiz.py プロジェクト: Guillon88/stdm
    def initSTRType(self):
        '''
        Initialize 'Social Tenure Relationship' GUI controls
        '''
        person = self.mapping.tableMapping('check_social_tenure_type')
        Person = person()
        strTypeFormatter =Person.queryObject().all()
        strType=[ids.value for ids in strTypeFormatter]
        strType.insert(0, " ")
        self.cboSTRType.insertItems(0,strType)

        self.cboSTRType.setCurrentIndex(-1)
        
        self.notifSTR = NotificationBar(self.vlSTRTypeNotif)
        
        #Register STR selection field
        self.frmWizSTRType.registerField("STR_Type",self.cboSTRType)
コード例 #11
0
ファイル: new_str_wiz.py プロジェクト: 7o9/stdm-plugin
 def initSTRType(self):
     '''
     Initialize 'Social Tenure Relationship' GUI controls
     '''
     pty=Table('check_social_tenure_type',Base.metadata,autoload=True,autoload_with=STDMDb.instance().engine)
     session=STDMDb.instance().session
     strTypeFormatter =session.query(pty.c.value).all()
     strType=[str(ids[0]) for ids in strTypeFormatter]
     
     self.cboSTRType.insertItems(0,strType)
     strType.insert(0, " ")
     self.cboSTRType.setCurrentIndex(-1)
     #loadComboSelections(self.cboSTRType, CheckSocialTenureRelationship) 
     
     self.notifSTR = NotificationBar(self.vlSTRTypeNotif)
     
     #Register STR selection field
     self.frmWizSTRType.registerField("STR_Type",self.cboSTRType)
コード例 #12
0
ファイル: new_str_wiz.py プロジェクト: olivierdalang/stdm
    def initSTRType(self):
        '''
        Initialize 'Social Tenure Relationship' GUI controls
        '''
        # pty=Table('check_social_tenure_type',Base.metadata,autoload=True,autoload_with=STDMDb.instance().engine)
        # session=STDMDb.instance().session
        person = self.mapping.tableMapping('check_social_tenure_type')
        Person = person()
        strTypeFormatter =Person.queryObject().all()
        strType=[ids.value for ids in strTypeFormatter]
        strType.insert(0, " ")
        self.cboSTRType.insertItems(0,strType)

        self.cboSTRType.setCurrentIndex(-1)
        
        self.notifSTR = NotificationBar(self.vlSTRTypeNotif)
        
        #Register STR selection field
        self.frmWizSTRType.registerField("STR_Type",self.cboSTRType)
コード例 #13
0
    def __init__(self,parent = None,selectMode=True):
        QDialog.__init__(self,parent)
        self.setupUi(self)
        
        self.notifBar = NotificationBar(self.vlNotification)
        
        if selectMode:
            self.buttonBox.setVisible(True)
            self.manageButtonBox.setVisible(False)
            currHeight = self.size().height()
            self.resize(200,currHeight)
            
        else:
            self.buttonBox.setVisible(False)
            self.manageButtonBox.setVisible(True)
            self.setWindowTitle(QApplication.translate("TemplateDocumentSelector","Template Manager"))
            
        #Configure manage buttons
        btnEdit = self.manageButtonBox.button(QDialogButtonBox.Ok)
        btnEdit.setText(QApplication.translate("TemplateDocumentSelector","Edit..."))
        btnEdit.setIcon(QIcon(":/plugins/stdm/images/icons/edit.png"))
        
        btnDelete = self.manageButtonBox.button(QDialogButtonBox.Save)
        btnDelete.setText(QApplication.translate("TemplateDocumentSelector","Delete"))
        btnDelete.setIcon(QIcon(":/plugins/stdm/images/icons/delete.png"))
        
        #Connect signals
        self.buttonBox.accepted.connect(self.onAccept)
        btnEdit.clicked.connect(self.onEditTemplate)
        btnDelete.clicked.connect(self.onDeleteTemplate)
        
        #Get saved document templates then add to the model
        templates = documentTemplates()

        self._docItemModel = QStandardItemModel(parent)
        self._docItemModel.setColumnCount(2)
        
        for name,path in templates.iteritems():
            docNameItem =  self._createDocNameItem(name)
            filePathItem = QStandardItem(path)
            self._docItemModel.appendRow([docNameItem,filePathItem])
            
        self.lstDocs.setModel(self._docItemModel)
コード例 #14
0
ファイル: new_str_wiz.py プロジェクト: SolomonN/stdm_plugin
 def initPerson(self):
     '''
     Initialize person config
     '''
     self.notifPerson = NotificationBar(self.vlPersonNotif)
     
     self._initPersonFilter()
     
     #Initialize person worker thread for fetching person objects
     self.personWorker = PersonWorker(self)
     self.connect(self.personWorker, SIGNAL("retrieved(PyQt_PyObject)"),self._loadPersonInfo)
     
     #Init summary tree loaders
     self.personTreeLoader = TreeSummaryLoader(self.tvPersonInfo,QApplication.translate("newSTRWiz","Occupant Information"))
             
     #Connect signals
     QObject.connect(self.cboPersonFilterCols, SIGNAL("currentIndexChanged(int)"),self._updatePersonCompleter)
     
     #Start background thread
     self.personWorker.start()
コード例 #15
0
ファイル: view_str.py プロジェクト: SolomonN/stdm_plugin
 def initGui(self):
     '''
     Initialize widget
     '''
     self.loadEntityConfig()
     #Hook up signals
     self.connect(self.tbSTREntity, SIGNAL("currentChanged(int)"),self.entityTabIndexChanged)
     self.connect(self.btnSearch, SIGNAL("clicked()"),self.searchEntityRelations)
     self.connect(self.btnClearSearch, SIGNAL("clicked()"),self.clearSearch)
     self.connect(self.tvSTRResults,SIGNAL("expanded(const QModelIndex&)"),self.onTreeViewItemExpanded)
     
     #Configure notification bars
     self.notifSearchConfig = NotificationBar(self.vlSearchEntity)
     
     #Set the results treeview to accept requests for context menus
     self.tvSTRResults.setContextMenuPolicy(Qt.CustomContextMenu)
     self.connect(self.tvSTRResults,SIGNAL("customContextMenuRequested(const QPoint&)"),
                  self.onResultsContextMenuRequested)
             
     #Load async for the current widget
     self.entityTabIndexChanged(0)
コード例 #16
0
ファイル: license_agreement.py プロジェクト: gltn/stdm
 def __init__(self, parent=None):
     """
     This class checks if the user has accepted the
     license terms and conditions or not . It shows the
     terms and conditions if not.
     :param parent: The container of the dialog
     :type parent: QMainWindow or None
     :return: None
     :rtype: NoneType
     """
     QDialog.__init__(self, parent)
     self.setupUi(self)
     self.reg_config = RegistryConfig()
     self.notice_bar = NotificationBar(self.notifBar)
     self.accepted = False
     self.btnAccept.clicked.connect(self.accept_action)
     self.btnDecline.clicked.connect(self.decline_action)
     self.label.setStyleSheet(
         '''
         QLabel {
             font: bold;
         }
         '''
     )
コード例 #17
0
ファイル: view_str.py プロジェクト: mwasjos/stdm
    def initGui(self):
        """
        Initialize widget
        """
        self.tb_actions.setVisible(False)
        self._load_entity_configurations()

        # self.gb_supporting_docs.setCollapsed(True)

        # Connect signals
        self.tbSTREntity.currentChanged.connect(self.entityTabIndexChanged)
        self.btnSearch.clicked.connect(self.searchEntityRelations)
        self.btnClearSearch.clicked.connect(self.clearSearch)
        self.tvSTRResults.expanded.connect(self.onTreeViewItemExpanded)

        # Configure notification bar
        self._notif_search_config = NotificationBar(self.vl_notification)

        # Set the results treeview to accept requests for context menus
        self.tvSTRResults.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tvSTRResults.customContextMenuRequested.connect(self.onResultsContextMenuRequested)

        # Load async for the current widget
        self.entityTabIndexChanged(0)
コード例 #18
0
class TemplateDocumentSelector(QDialog,Ui_frmDocumentSelector):
    """
    Dialog for selecting a document template from the saved list.
    """
    def __init__(self,parent = None,selectMode=True):
        QDialog.__init__(self,parent)
        self.setupUi(self)
        
        self.notifBar = NotificationBar(self.vlNotification)
        
        if selectMode:
            self.buttonBox.setVisible(True)
            self.manageButtonBox.setVisible(False)
            currHeight = self.size().height()
            self.resize(200,currHeight)
            
        else:
            self.buttonBox.setVisible(False)
            self.manageButtonBox.setVisible(True)
            self.setWindowTitle(QApplication.translate("TemplateDocumentSelector","Template Manager"))
            
        #Configure manage buttons
        btnEdit = self.manageButtonBox.button(QDialogButtonBox.Ok)
        btnEdit.setText(QApplication.translate("TemplateDocumentSelector","Edit..."))
        btnEdit.setIcon(QIcon(":/plugins/stdm/images/icons/edit.png"))
        
        btnDelete = self.manageButtonBox.button(QDialogButtonBox.Save)
        btnDelete.setText(QApplication.translate("TemplateDocumentSelector","Delete"))
        btnDelete.setIcon(QIcon(":/plugins/stdm/images/icons/delete.png"))
        
        #Connect signals
        self.buttonBox.accepted.connect(self.onAccept)
        btnEdit.clicked.connect(self.onEditTemplate)
        btnDelete.clicked.connect(self.onDeleteTemplate)
        
        #Get saved document templates then add to the model
        templates = documentTemplates()

        self._docItemModel = QStandardItemModel(parent)
        self._docItemModel.setColumnCount(2)
        
        for name,path in templates.iteritems():
            docNameItem =  self._createDocNameItem(name)
            filePathItem = QStandardItem(path)
            self._docItemModel.appendRow([docNameItem,filePathItem])
            
        self.lstDocs.setModel(self._docItemModel)
        
    def _createDocNameItem(self,docName):
        """
        Create a template document standard item.
        """
        #Set icon
        icon = QIcon()
        icon.addPixmap(QPixmap(":/plugins/stdm/images/icons/document.png"), QIcon.Normal, QIcon.Off)
        
        dnItem = QStandardItem(icon,docName)
        
        return dnItem
    
    def onEditTemplate(self):
        """
        Slot raised to edit document template.
        """
        self.notifBar.clear()
        
        if self.documentMapping() == None:
            self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "Please select a document template to edit"))
            return
        
        templateName,filePath = self.documentMapping()
        
        docName,ok = QInputDialog.getText(self, \
                                              QApplication.translate("TemplateDocumentSelector","Edit Template"), \
                                              QApplication.translate("TemplateDocumentSelector","Please enter the new template name below"), \
                                              text = templateName)
        if ok and docName == "":
            self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "Template name cannot be empty"))
            return
        
        elif docName == templateName:
            return
        
        elif ok and docName != "":
            result,newTemplatePath = self._editTemplate(filePath, docName)
            
            if result:
                #Update view
                mIndices = self._selectedMappings()
        
                docNameItem = self._docItemModel.itemFromIndex(mIndices[0])
                filePathItem = self._docItemModel.itemFromIndex(mIndices[1])
                
                docNameItem.setText(docName)
                filePathItem.setText(newTemplatePath)
                
                self.notifBar.insertInfoNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "'{0}' template has been successfully updated".format(docName)))
                
            else:
                self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "Error: '{0}' template could not be updated".format(templateName)))
            
    def onDeleteTemplate(self):
        """
        Slot raised to delete document template.
        """
        self.notifBar.clear()
        
        if self.documentMapping() == None:
            self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "Please select a document template to delete"))
            return
        
        templateName,filePath = self.documentMapping()
        
        result = QMessageBox.warning(self, QApplication.translate("TemplateDocumentSelector", \
                                                                         "Confirm delete"), 
                                     QApplication.translate("TemplateDocumentSelector", \
                                                                         "Are you sure you want to delete '{0}' template?" \
                                                                         "This action cannot be undone.\nClick Yes to proceed " \
                                                                         "or No to cancel.".format(templateName)), 
                                     QMessageBox.Yes|QMessageBox.No)
        
        if result == QMessageBox.No:
            return
        
        status = self._deleteDocument(filePath)
        
        if status:
            #Remove item from list using model index row number
            selectedDocNameIndices = self.lstDocs.selectionModel().selectedRows(0)
            row = selectedDocNameIndices[0].row()
            self._docItemModel.removeRow(row)
            self.notifBar.insertInfoNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "'{0}' template has been successfully removed".format(templateName)))
        
        else:
            self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "Error: '{0}' template could not be removed".format(templateName)))
    
    def onAccept(self):
        """
        Slot raised to close the dialog only when a selection has been made by the user.
        """
        self.notifBar.clear()
        
        if self.documentMapping() == None:
            self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "Please select a document"))
            return
        
        self.accept()
        
    def _selectedMappings(self):
        """
        Returns the model indices for the selected row.
        """
        selectedDocNameIndices = self.lstDocs.selectionModel().selectedRows(0)
        selectedFilePathIndices = self.lstDocs.selectionModel().selectedRows(1)
        
        if len(selectedDocNameIndices) == 0:
            return None
        
        docNameIndex = selectedDocNameIndices[0]
        filePathIndex = selectedFilePathIndices[0]
        
        return (docNameIndex,filePathIndex)
    
    def documentMapping(self):
        """
        Returns a tuple containing the selected document name and the corresponding file name.
        """
        mIndices = self._selectedMappings()
        
        if mIndices == None:
            return None
        
        docNameItem = self._docItemModel.itemFromIndex(mIndices[0])
        filePathItem = self._docItemModel.itemFromIndex(mIndices[1])
        
        return (docNameItem.text(),filePathItem.text())
    
    def _editTemplate(self,templatePath,newName):
        """
        Updates the template document to use the new name.
        """
        templateFile = QFile(templatePath)
        
        if not templateFile.open(QIODevice.ReadOnly):
            QMessageBox.critical(self, QApplication.translate("TemplateDocumentSelector","Open Operation Error"), \
                                            "{0}\n{1}".format(QApplication.translate("TemplateDocumentSelector","Cannot read template file."), \
                                                      templateFile.errorString()
                                                      ))
            return (False,"")
         
        templateDoc = QDomDocument()
        
        if templateDoc.setContent(templateFile):
            composerElement = templateDoc.documentElement()
            titleAttr = composerElement.attributeNode("title")
            if not titleAttr.isNull():
                titleAttr.setValue(newName)
                
            #Try remove file
            status = templateFile.remove()
            
            if not status:
                return (False,"")
            
            #Create new file
            newTemplatePath = self._composerTemplatesPath() + "/" + newName + ".sdt"  
            newTemplateFile = QFile(newTemplatePath)
            
            if not newTemplateFile.open(QIODevice.WriteOnly):
                QMessageBox.critical(self, QApplication.translate("TemplateDocumentSelector","Save Operation Error"), \
                                                "{0}\n{1}".format(QApplication.translate("TemplateDocumentSelector","Could not save template file."), \
                                                          newTemplateFile.errorString()
                                                          ))
                return (False,"")
            
            if newTemplateFile.write(templateDoc.toByteArray()) == -1:
                QMessageBox.critical(self, QApplication.translate("TemplateDocumentSelector","Save Error"), \
                                                QApplication.translate("TemplateDocumentSelector","Could not save template file."))
                return (False,"")
            
            newTemplateFile.close()  
            
            return (True,newTemplatePath)
    
    def _deleteDocument(self,templatePath):
        """
        Delete the document template from the file system.
        """
        docFile = QFile(templatePath)
        
        return docFile.remove()
    
    def _composerTemplatesPath(self):
        """
        Reads the path of composer templates in the registry.
        """
        regConfig = RegistryConfig()
        keyName = "ComposerTemplates"
        
        valueCollection = regConfig.read([keyName])
        
        if len(valueCollection) == 0:
            return None
        
        else:
            return valueCollection[keyName]
コード例 #19
0
class TemplateDocumentSelector(QDialog, Ui_frmDocumentSelector):
    """
    Dialog for selecting a document template from the saved list.
    """
    def __init__(self, parent=None, selectMode=True):
        QDialog.__init__(self, parent)
        self.setupUi(self)

        self.notifBar = NotificationBar(self.vlNotification)

        if selectMode:
            self.buttonBox.setVisible(True)
            self.manageButtonBox.setVisible(False)
            currHeight = self.size().height()
            self.resize(200, currHeight)

        else:
            self.buttonBox.setVisible(False)
            self.manageButtonBox.setVisible(True)
            self.setWindowTitle(
                QApplication.translate("TemplateDocumentSelector",
                                       "Template Manager"))

        #Configure manage buttons
        btnEdit = self.manageButtonBox.button(QDialogButtonBox.Ok)
        btnEdit.setText(
            QApplication.translate("TemplateDocumentSelector", "Edit..."))
        btnEdit.setIcon(QIcon(":/plugins/stdm/images/icons/edit.png"))

        btnDelete = self.manageButtonBox.button(QDialogButtonBox.Save)
        btnDelete.setText(
            QApplication.translate("TemplateDocumentSelector", "Delete"))
        btnDelete.setIcon(QIcon(":/plugins/stdm/images/icons/delete.png"))

        #Connect signals
        self.buttonBox.accepted.connect(self.onAccept)
        btnEdit.clicked.connect(self.onEditTemplate)
        btnDelete.clicked.connect(self.onDeleteTemplate)

        #Get saved document templates then add to the model
        templates = documentTemplates()

        self._docItemModel = QStandardItemModel(parent)
        self._docItemModel.setColumnCount(2)

        for name, path in templates.iteritems():
            docNameItem = self._createDocNameItem(name)
            filePathItem = QStandardItem(path)
            self._docItemModel.appendRow([docNameItem, filePathItem])

        self.lstDocs.setModel(self._docItemModel)

    def _createDocNameItem(self, docName):
        """
        Create a template document standard item.
        """
        #Set icon
        icon = QIcon()
        icon.addPixmap(QPixmap(":/plugins/stdm/images/icons/document.png"),
                       QIcon.Normal, QIcon.Off)

        dnItem = QStandardItem(icon, docName)

        return dnItem

    def onEditTemplate(self):
        """
        Slot raised to edit document template.
        """
        self.notifBar.clear()

        if self.documentMapping() == None:
            self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "Please select a document template to edit"))
            return

        templateName, filePath = self.documentMapping()

        docName,ok = QInputDialog.getText(self, \
                                              QApplication.translate("TemplateDocumentSelector","Edit Template"), \
                                              QApplication.translate("TemplateDocumentSelector","Please enter the new template name below"), \
                                              text = templateName)
        if ok and docName == "":
            self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "Template name cannot be empty"))
            return

        elif docName == templateName:
            return

        elif ok and docName != "":
            result, newTemplatePath = self._editTemplate(filePath, docName)

            if result:
                #Update view
                mIndices = self._selectedMappings()

                docNameItem = self._docItemModel.itemFromIndex(mIndices[0])
                filePathItem = self._docItemModel.itemFromIndex(mIndices[1])

                docNameItem.setText(docName)
                filePathItem.setText(newTemplatePath)

                self.notifBar.insertInfoNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "'{0}' template has been successfully updated".format(docName)))

            else:
                self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "Error: '{0}' template could not be updated".format(templateName)))

    def onDeleteTemplate(self):
        """
        Slot raised to delete document template.
        """
        self.notifBar.clear()

        if self.documentMapping() == None:
            self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "Please select a document template to delete"))
            return

        templateName, filePath = self.documentMapping()

        result = QMessageBox.warning(self, QApplication.translate("TemplateDocumentSelector", \
                                                                         "Confirm delete"),
                                     QApplication.translate("TemplateDocumentSelector", \
                                                                         "Are you sure you want to delete '{0}' template?" \
                                                                         "This action cannot be undone.\nClick Yes to proceed " \
                                                                         "or No to cancel.".format(templateName)),
                                     QMessageBox.Yes|QMessageBox.No)

        if result == QMessageBox.No:
            return

        status = self._deleteDocument(filePath)

        if status:
            #Remove item from list using model index row number
            selectedDocNameIndices = self.lstDocs.selectionModel(
            ).selectedRows(0)
            row = selectedDocNameIndices[0].row()
            self._docItemModel.removeRow(row)
            self.notifBar.insertInfoNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "'{0}' template has been successfully removed".format(templateName)))

        else:
            self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "Error: '{0}' template could not be removed".format(templateName)))

    def onAccept(self):
        """
        Slot raised to close the dialog only when a selection has been made by the user.
        """
        self.notifBar.clear()

        if self.documentMapping() == None:
            self.notifBar.insertErrorNotification(QApplication.translate("TemplateDocumentSelector", \
                                                                         "Please select a document"))
            return

        self.accept()

    def _selectedMappings(self):
        """
        Returns the model indices for the selected row.
        """
        selectedDocNameIndices = self.lstDocs.selectionModel().selectedRows(0)
        selectedFilePathIndices = self.lstDocs.selectionModel().selectedRows(1)

        if len(selectedDocNameIndices) == 0:
            return None

        docNameIndex = selectedDocNameIndices[0]
        filePathIndex = selectedFilePathIndices[0]

        return (docNameIndex, filePathIndex)

    def documentMapping(self):
        """
        Returns a tuple containing the selected document name and the corresponding file name.
        """
        mIndices = self._selectedMappings()

        if mIndices == None:
            return None

        docNameItem = self._docItemModel.itemFromIndex(mIndices[0])
        filePathItem = self._docItemModel.itemFromIndex(mIndices[1])

        return (docNameItem.text(), filePathItem.text())

    def _editTemplate(self, templatePath, newName):
        """
        Updates the template document to use the new name.
        """
        templateFile = QFile(templatePath)

        if not templateFile.open(QIODevice.ReadOnly):
            QMessageBox.critical(self, QApplication.translate("TemplateDocumentSelector","Open Operation Error"), \
                                            "{0}\n{1}".format(QApplication.translate("TemplateDocumentSelector","Cannot read template file."), \
                                                      templateFile.errorString()
                                                      ))
            return (False, "")

        templateDoc = QDomDocument()

        if templateDoc.setContent(templateFile):
            composerElement = templateDoc.documentElement()
            titleAttr = composerElement.attributeNode("title")
            if not titleAttr.isNull():
                titleAttr.setValue(newName)

            #Try remove file
            status = templateFile.remove()

            if not status:
                return (False, "")

            #Create new file
            newTemplatePath = self._composerTemplatesPath(
            ) + "/" + newName + ".sdt"
            newTemplateFile = QFile(newTemplatePath)

            if not newTemplateFile.open(QIODevice.WriteOnly):
                QMessageBox.critical(self, QApplication.translate("TemplateDocumentSelector","Save Operation Error"), \
                                                "{0}\n{1}".format(QApplication.translate("TemplateDocumentSelector","Could not save template file."), \
                                                          newTemplateFile.errorString()
                                                          ))
                return (False, "")

            if newTemplateFile.write(templateDoc.toByteArray()) == -1:
                QMessageBox.critical(self, QApplication.translate("TemplateDocumentSelector","Save Error"), \
                                                QApplication.translate("TemplateDocumentSelector","Could not save template file."))
                return (False, "")

            newTemplateFile.close()

            return (True, newTemplatePath)

    def _deleteDocument(self, templatePath):
        """
        Delete the document template from the file system.
        """
        docFile = QFile(templatePath)

        return docFile.remove()

    def _composerTemplatesPath(self):
        """
        Reads the path of composer templates in the registry.
        """
        regConfig = RegistryConfig()
        keyName = "ComposerTemplates"

        valueCollection = regConfig.read([keyName])

        if len(valueCollection) == 0:
            return None

        else:
            return valueCollection[keyName]
コード例 #20
0
ファイル: license_agreement.py プロジェクト: gltn/stdm
class LicenseAgreement(QDialog, Ui_LicenseAgreement):
    def __init__(self, parent=None):
        """
        This class checks if the user has accepted the
        license terms and conditions or not . It shows the
        terms and conditions if not.
        :param parent: The container of the dialog
        :type parent: QMainWindow or None
        :return: None
        :rtype: NoneType
        """
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.reg_config = RegistryConfig()
        self.notice_bar = NotificationBar(self.notifBar)
        self.accepted = False
        self.btnAccept.clicked.connect(self.accept_action)
        self.btnDecline.clicked.connect(self.decline_action)
        self.label.setStyleSheet(
            '''
            QLabel {
                font: bold;
            }
            '''
        )

    def check_show_license(self):
        """
        Checks if you need to show the license page.
        Checks if the flag in the registry has been set.
        Returns True to show license. If registry key
        is not yet set, show the license page.
        :rtype: boolean
        """
        show_lic = 1
        license_key = self.reg_config.read(
            [SHOW_LICENSE]
        )

        if len(license_key) > 0:
            show_lic = license_key[SHOW_LICENSE]

        if show_lic == 1 or show_lic == unicode(1):
            return True
        elif show_lic == 0 or show_lic == unicode(0):
            self.accepted = True
            return False

    def show_license(self):
        """
        Show STDM license window if the user have never
        accepted the license terms and conditions.
        :return: None
        :rtype: NoneType
        """
        # validate if to show license
        show_lic = self.check_show_license()
        # THe user didn't accept license
        if show_lic:
            license = LicenseDocument()

            self.termsCondArea.setText(
                license.read_license_info()
            )

            self.exec_()

    def accept_action(self):
        """
        A slot raised when the user clicks on the Accept button.
        :return: None
        :rtype: NoneType
        """
        if not self.checkBoxAgree.isChecked():
            msg = QApplication.translate(
                'LicenseAgreement',
                'To use STDM, please accept the terms '
                'and conditions by selecting'
                ' the checkbox "I have read and agree ..."'
            )

            self.notice_bar.clear()
            self.notice_bar.insertNotification(msg, ERROR)
            return

        else:
            self.reg_config.write({SHOW_LICENSE: 0})
            self.accepted = True
            self.close()

    def decline_action(self):
        """
        A slot raised when the user clicks on
        the decline button.
        :return: None
        :rtype: NoneType
        """
        self.accepted = False
        self.close()
コード例 #21
0
ファイル: new_str_wiz.py プロジェクト: SolomonN/stdm_plugin
class newSTRWiz(QWizard, Ui_frmNewSTR):
    '''
    This class handles the listing of locality information
    '''
    def __init__(self,plugin):
        QWizard.__init__(self,plugin.iface.mainWindow())
        self.setupUi(self)
        
        #STR Variables
        self.selPerson = None
        self.selProperty = None
        self.enjoymentRight = None
        self.conflict = None
        
        #Initialize GUI wizard pages
        self.initPerson()
        
        self.initProperty()
        
        self.initSTRType()
       
        self.initEnjoymentRight()
        
        self.initSourceDocument()
        
        self.initConflict()
        
        #Connect signal when the finish button is clicked
        btnFinish = self.button(QWizard.FinishButton)
        
    def initPerson(self):
        '''
        Initialize person config
        '''
        self.notifPerson = NotificationBar(self.vlPersonNotif)
        
        self._initPersonFilter()
        
        #Initialize person worker thread for fetching person objects
        self.personWorker = PersonWorker(self)
        self.connect(self.personWorker, SIGNAL("retrieved(PyQt_PyObject)"),self._loadPersonInfo)
        
        #Init summary tree loaders
        self.personTreeLoader = TreeSummaryLoader(self.tvPersonInfo,QApplication.translate("newSTRWiz","Occupant Information"))
                
        #Connect signals
        QObject.connect(self.cboPersonFilterCols, SIGNAL("currentIndexChanged(int)"),self._updatePersonCompleter)
        
        #Start background thread
        self.personWorker.start()
        
    def initProperty(self):
        '''
        Initialize property config
        '''
        self.notifProp = NotificationBar(self.vlPropNotif)
        self.gpOLTitle = self.gpOpenLayers.title()
        
        #Flag for checking whether OpenLayers basemaps have been loaded
        self.olLoaded = False
        
        #Initialize lookup for properties
        propertyWorker = PropertyWorker(self)
        self.connect(propertyWorker, SIGNAL("retrieved(PyQt_PyObject)"), self._onPropertiesLoaded)
        
        #Connect signals
        QObject.connect(self.gpOpenLayers, SIGNAL("toggled(bool)"), self._onEnableOLGroupbox)             
        QObject.connect(self.zoomSlider, SIGNAL("sliderReleased()"), self._onZoomChanged)
        QObject.connect(self.btnResetMap , SIGNAL("clicked()"), self._onResetMap)
        
        #Start background thread
        propertyWorker.start()   
        
        self.propBrowser = PropertyBrowser(self.propWebView,self)
        self.connect(self.propBrowser,SIGNAL("loadError(QString)"),self._onPropertyBrowserError)
        self.connect(self.propBrowser,SIGNAL("loadProgress(int)"),self._onPropertyBrowserLoading)
        self.connect(self.propBrowser,SIGNAL("loadFinished(bool)"),self._onPropertyBrowserFinished)
        self.connect(self.propBrowser,SIGNAL("zoomChanged(int)"),self.onMapZoomLevelChanged)
            
        #Connect signals
        QObject.connect(self.rbGMaps, SIGNAL("toggled(bool)"),self.onLoadGMaps)          
        QObject.connect(self.rbOSM, SIGNAL("toggled(bool)"),self.onLoadOSM)                               
            
    def initializePage(self,id):
        '''
        Initialize summary page based on user selections.
        '''
        if id == 7:
            self.buildSummary()
            
    def nextId(self):
        '''
        Filter subsequent pages based on user selections.
        If the user has specified 'Heir' as an STR type the load the 'Right of Enjoyment' wizard page.
        '''
        currentId = self.currentId()
        
        #Validate STR type selection
        if currentId == 3:
            #Determine STR selection then return the appropriate page
            heir = QApplication.translate("Lookup","Heir")
            selIndex,ok = self.field("STR_Type").toInt()          
            if ok:    
                #Get index of heir selection
                heirIndex = self.cboSTRType.findText(heir)   
                if selIndex == heirIndex:
                    return 4
                else:
                    return 5
            else:
                return 5
            
        else:
            return QWizard.nextId(self)
            
    def initSTRType(self):
        '''
        Initialize 'Social Tenure Relationship' GUI controls
        '''
        loadComboSelections(self.cboSTRType, CheckSocialTenureRelationship) 
        
        self.notifSTR = NotificationBar(self.vlSTRTypeNotif)
        
        #Register STR selection field
        self.frmWizSTRType.registerField("STR_Type",self.cboSTRType)
    
    def initEnjoymentRight(self):
        '''
        Initialize 'Right of Enjoyment' GUI controls
        '''
        self.dtReceivingDate.setMaximumDate(QDate.currentDate())
        
        loadComboSelections(self.cboInheritanceType, CheckInheritanceType) 
        loadComboSelections(self.cboDeadAlive, CheckDeadAlive) 
        
        self.notifEnjoyment = NotificationBar(self.vlEnjoymentNotif)
        
    def initSourceDocument(self):
        '''
        Initialize source document page
        '''
        #Set currency regular expression and currency prefix
        rx = QRegExp("^\\d{1,12}(([.]\\d{2})*),(\\d{2})$")
        rxValidator = QRegExpValidator(rx,self)
        self.txtCFBPAmount.setValidator(rxValidator)
        self.txtStateReceiptAmount.setValidator(rxValidator)
        
        self.dtLastYearCFBP.setMaximumDate(QDate.currentDate())
        self.dtStateReceiptDate.setMaximumDate(QDate.currentDate())
        self.dtStateLeaseYear.setMaximumDate(QDate.currentDate())  
        
        self.notifSourceDoc = NotificationBar(self.vlSourceDocNotif)
        
        #Set source document manager
        self.sourceDocManager = SourceDocumentManager()
        self.privateTaxDocManager = SourceDocumentManager()
        self.stateTaxDocManager = SourceDocumentManager()
        self.sourceDocManager.registerContainer(self.vlDocTitleDeed, TITLE_DEED)
        self.sourceDocManager.registerContainer(self.vlDocStatRefPaper, STATUTORY_REF_PAPER)
        self.sourceDocManager.registerContainer(self.vlDocSurveyorRef, SURVEYOR_REF)
        self.sourceDocManager.registerContainer(self.vlDocNotaryRef, NOTARY_REF)  
        
        #Receipt scan document managers
        self.privateTaxDocManager.registerContainer(self.vlPrivateReceiptScan, TAX_RECEIPT_PRIVATE)  
        self.stateTaxDocManager.registerContainer(self.vlStateScanReceipt, TAX_RECEIPT_STATE)        
        
        #Connect signals
        self.connect(self.rbPrivateProperty, SIGNAL("toggled(bool)"),self.onSelectPrivateProperty)
        self.connect(self.rbStateland, SIGNAL("toggled(bool)"),self.onSelectStateland)
        self.connect(self.btnAddTitleDeed, SIGNAL("clicked()"),self.onUploadTitleDeed)
        self.connect(self.btnPrivateReceiptScan, SIGNAL("clicked()"),self.onUploadPrivateReceiptScan)
        self.connect(self.btnPublicReceiptScan, SIGNAL("clicked()"),self.onUploadStateReceiptScan)
        self.connect(self.btnAddStatRefPaper, SIGNAL("clicked()"),self.onUploadStatutoryRefPaper)
        self.connect(self.btnAddSurveyorRef, SIGNAL("clicked()"),self.onUploadSurveyorRef)
        self.connect(self.btnAddNotaryRef, SIGNAL("clicked()"),self.onUploadNotaryRef)
        
    def initConflict(self):
        '''
        Initialize 'Conflict' GUI controls
        '''
        loadComboSelections(self.cboConflictOccurrence, CheckConflictState) 
        
        self.notifConflict = NotificationBar(self.vlConflictNotif,3000)
        
    def buildSummary(self):
        '''
        Display summary information.
        '''
        personMapping = self._mapPersonAttributes(self.selPerson)
        propertyMapping = self._mapPropertyAttributes(self.selProperty)
        STRMapping = self._mapSTRTypeSelection()
        
        #Load summary information in the tree view
        summaryTreeLoader = TreeSummaryLoader(self.twSTRSummary)
        summaryTreeLoader.addCollection(personMapping, QApplication.translate("newSTRWiz","Occupant Information"), 
                                             ":/plugins/stdm/images/icons/user.png")    
        summaryTreeLoader.addCollection(propertyMapping, QApplication.translate("newSTRWiz","Property Information"), 
                                             ":/plugins/stdm/images/icons/property.png")
        summaryTreeLoader.addCollection(STRMapping, QApplication.translate("newSTRWiz","Social Tenure Relationship Information"), 
                                             ":/plugins/stdm/images/icons/social_tenure.png")    
        
        #Check if enjoyment right is specified
        heir = QApplication.translate("Lookup","Heir")
        selIndex= self.cboSTRType.currentIndex()        
        #Get index of heir item
        heirIndex = self.cboSTRType.findText(heir)   
        if selIndex == heirIndex:
            if self.enjoymentRight != None:
                enjoyRightMapping = self._mapEnjoyRightSelection(self.enjoymentRight)
                summaryTreeLoader.addCollection(enjoyRightMapping, QApplication.translate("newSTRWiz","Right of Enjoyment Information"), 
                                             ":/plugins/stdm/images/icons/inherit.png") 
                
        #Check the source documents based on the type of property
        if self.rbPrivateProperty.isChecked():
            srcDocMapping = self.sourceDocManager.attributeMapping()
            summaryTreeLoader.addCollection(srcDocMapping, QApplication.translate("newSTRWiz","Source Documents"), 
                                             ":/plugins/stdm/images/icons/attachment.png") 
            #Tax information
            if self.gpPrivateTaxInfo.isChecked():
                privatePropTaxMapping = self._mapPrivatePropertyTax()
                taxDocMapping = self.privateTaxDocManager.attributeMapping()
                privatePropTaxMapping.update(taxDocMapping)
                summaryTreeLoader.addCollection(privatePropTaxMapping, QApplication.translate("newSTRWiz","Tax Information"), 
                                             ":/plugins/stdm/images/icons/receipt.png")
        elif self.rbStateland.isChecked():
            #Tax information only
            statePropTaxMapping = self._mapStatePropertyTax()
            taxDocMapping = self.stateTaxDocManager.attributeMapping()
            statePropTaxMapping.update(taxDocMapping)
            summaryTreeLoader.addCollection(statePropTaxMapping, QApplication.translate("newSTRWiz","Tax Information"), 
                                             ":/plugins/stdm/images/icons/receipt.png")
            
        #Map conflict
        if self.cboConflictOccurrence.currentIndex() != 0:
            conflictMapping = self._mapConflict(self.conflict)
            summaryTreeLoader.addCollection(conflictMapping, QApplication.translate("newSTRWiz","Conflict Information"), 
                                             ":/plugins/stdm/images/icons/conflict.png")
        
        summaryTreeLoader.display()  
    
    def validateCurrentPage(self):
        '''
        Validate the current page before proceeding to the next one
        '''
        isValid = True
        currPageIndex = self.currentId()       
        
        #Validate person information
        if currPageIndex == 1:
            if self.selPerson == None:
                msg = QApplication.translate("newSTRWiz", 
                                             "Please choose a person for whom you are defining the social tenure relationship for.")
                self.notifPerson.clear()
                self.notifPerson.insertNotification(msg, ERROR)
                isValid = False
        
        #Validate property information
        if currPageIndex == 2:
            if self.selProperty == None:
                    msg = QApplication.translate("newSTRWiz", 
                                                 "Please specify the property to reference. Use the filter capability below.")
                    self.notifProp.clear()
                    self.notifProp.insertNotification(msg, ERROR)
                    isValid = False
        
        #Validate STR   
        if currPageIndex == 3:
            #Get current selected index
            currIndex = self.cboSTRType.currentIndex()
            if currIndex == 0:
                msg = QApplication.translate("newSTRWiz", 
                                                 "Please specify the social tenure relationship type.")     
                self.notifSTR.clear()
                self.notifSTR.insertErrorNotification(msg)
                isValid = False
         
        #Validate right of enjoyment details
        if currPageIndex == 4:
            isValid = self.validateEnjoymentRight()
        
        #Validate source document    
        if currPageIndex == 5:
            isValid = self.validateSourceDocuments()
            
        #Validate conflict details
        if currPageIndex == 6:
            isValid = self.validateConflict()
            
        if currPageIndex == 7:
            isValid = self.onCreateSTR()
        
        return isValid
    
    def onCreateSTR(self):
        '''
        Slot raised when the user clicks on Finish button in order to create a new STR entry.
        '''
        isValid = True
        
        #Create a progress dialog
        progDialog = QProgressDialog(self)
        progDialog.setWindowTitle(QApplication.translate("newSTRWiz", "Creating New STR"))
        progDialog.setRange(0,7)
        progDialog.show()
        
        try:
            progDialog.setValue(1)
            socialTenure = SocialTenureRelationship()
            socialTenure.PersonID = self.selPerson.id
            progDialog.setValue(2)
            socialTenure.PropertyID = self.selProperty.id
            progDialog.setValue(3)
                
            if self.rbPrivateProperty.isChecked():
                progDialog.setValue(4)
                socialTenure.SourceDocuments = self.sourceDocManager.sourceDocuments()
                if self.gpPrivateTaxInfo.isChecked():
                    taxInfo = Taxation()
                    taxInfo.Amount = Decimal(str(self.txtCFBPAmount.text()))
                    taxInfo.ReferenceDate = self.dtLastYearCFBP.date().toPyDate()
                    taxDocs = self.privateTaxDocManager.sourceDocuments(TAX_RECEIPT_PRIVATE)
                    if len(taxDocs) > 0:
                        taxInfo.Document = taxDocs[0]
                    socialTenure.Taxation = taxInfo
                    
            elif self.rbStateland.isChecked():
                progDialog.setValue(4)
                taxInfo = Taxation()
                taxInfo.Amount = Decimal(str(self.txtStateReceiptAmount.text()))
                taxInfo.ReferenceDate = self.dtStateReceiptDate.date().toPyDate()
                taxInfo.LeaseDate = self.dtStateLeaseYear.date().toPyDate()
                taxInfo.TaxOffice = str(self.txtStateTaxOffice.text())
                taxDocs = self.stateTaxDocManager.sourceDocuments(TAX_RECEIPT_STATE)
                if len(taxDocs) > 0:
                        taxInfo.Document = taxDocs[0]
                socialTenure.Taxation = taxInfo
                
            progDialog.setValue(5)
            
            socialTenure.AgreementAvailable = self.chkSTRAgreement.isChecked()
            socialTenure.SocialTenureType,ok = self.cboSTRType.itemData(self.cboSTRType.currentIndex()).toInt()
            
            if self.enjoymentRight != None:
                socialTenure.EnjoymentRight = self.enjoymentRight
                
            if self.conflict != None:
                socialTenure.Conflict = self.conflict
                
            progDialog.setValue(6)
                    
            socialTenure.save()
            
            progDialog.setValue(7)
            
            strPerson = "%s %s"%(self.selPerson.firstname,self.selPerson.lastname)          
            strMsg = str(QApplication.translate("newSTRWiz", 
                                            "The social tenure relationship for %s has been successfully created!"))           
            QMessageBox.information(self, QApplication.translate("newSTRWiz", "STR Creation"),strMsg%(strPerson))

        except sqlalchemy.exc.OperationalError as oe:
            errMsg = oe.message
            QMessageBox.critical(self, QApplication.translate("newSTRWiz", "Unexpected Error"),errMsg)
            progDialog.hide()
            isValid = False
            
        except Exception as e:
            errMsg = str(e)
            QMessageBox.critical(self, QApplication.translate("newSTRWiz", "Unexpected Error"),errMsg)
            progDialog.hide()
            isValid = False
        
        return isValid
            
    def _loadPersonInfo(self,persons):
        '''
        Load person objects
        '''
        self.persons = persons 
        self._updatePersonCompleter(0)
        
    def _onPropertiesLoaded(self,propids):
        '''
        Slot raised once the property worker has finished retrieving the property IDs.
        Creates a completer and populates it with the property IDs.
        '''
        #Get the items in a tuple and put them in a list
        propertyIds = [pid[0] for pid in propids]
        
        #Configure completer   
        propCompleter = QCompleter(propertyIds,self)         
        propCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        propCompleter.setCompletionMode(QCompleter.PopupCompletion)
        self.txtPropID.setCompleter(propCompleter)  
        
        #Connect 'activated' slot for the completer to load property information
        self.connect(propCompleter, SIGNAL("activated(const QString&)"),self._updatePropertySummary)      
        
    def _onPropertyBrowserError(self,err):
        '''
        Slot raised when an error occurs when loading items in the property browser
        '''
        self.notifProp.clear()
        self.notifProp.insertNotification(err, ERROR)
        
    def _onPropertyBrowserLoading(self,progress):
        '''
        Slot raised when the property browser is loading.
        Displays the progress of the page loading as a percentage.
        '''
        if progress <= 0 or progress >= 100:
            self.gpOpenLayers.setTitle(self.gpOLTitle)
        else:
            self.gpOpenLayers.setTitle("%s (Loading...%s%%)"%(str(self.gpOLTitle),str(progress)))
            
    def _onPropertyBrowserFinished(self,status):
        '''
        Slot raised when the property browser finishes loading the content
        '''
        if status:
            self.olLoaded = True
            self.overlayProperty()
        else:
            self.notifProp.clear()
            msg = QApplication.translate("newSTRWiz", "Error - The property map cannot be loaded.")   
            self.notifProp.insertErrorNotification(msg)
        
    def _onEnableOLGroupbox(self,state):
        '''
        Slot raised when a user chooses to select the group box for enabling/disabling to view
        the property in OpenLayers.
        '''
        if state:
            if self.selProperty is None:
                self.notifProp.clear()
                msg = QApplication.translate("newSTRWiz", "You need to specify a property in order to be able to preview it.")   
                self.notifProp.insertWarningNotification(msg)                
                self.gpOpenLayers.setChecked(False)
                return  
            
            #Load property overlay
            if not self.olLoaded:                
                self.propBrowser.load()            
                   
        else:
            #Remove overlay
            self.propBrowser.removeOverlay()     
            
    def _onZoomChanged(self):
        '''
        Slot raised when the zoom value in the slider changes.
        This is only raised once the user releases the slider with the mouse.
        '''
        zoom = self.zoomSlider.value()        
        self.propBrowser.zoomTo(zoom)
            
    def _initPersonFilter(self):
        '''
        Initializes person filter settings
        '''         
        self.cboPersonFilterCols.addItem(str(QApplication.translate("newSTRWiz","First Name")), "firstname")
        self.cboPersonFilterCols.addItem(str(QApplication.translate("newSTRWiz","Last Name")), "lastname")
        self.cboPersonFilterCols.addItem(str(QApplication.translate("newSTRWiz","Nick Name")), "nickname")
        self.cboPersonFilterCols.addItem(str(QApplication.translate("newSTRWiz","Identification Number")), "identification_number")            
        
    def _updatePersonCompleter(self,index):
        '''
        Updates the person completer based on the person attribute item that the user has selected
        '''
        #Clear dependent controls
        self.txtFilterPattern.clear()
        self.tvPersonInfo.clear()
        
        self.currPersonAttr = str(self.cboPersonFilterCols.itemData(index).toString())            
        
        #Create standard model which will always contain the id of the person row then the attribute for use in the completer
        self.personStandardModel = QStandardItemModel(self)
        self.personStandardModel.setColumnCount(2)
        self.personStandardModel.clear()
       
        for p in self.persons:
            pVal = getattr(p,self.currPersonAttr)
            if pVal != "" or pVal != None:
                idItem = QStandardItem()
                idItem.setData(p.id,Qt.EditRole)
                attrItem = QStandardItem()
                attrItem.setData(pVal,Qt.EditRole)
                self.personStandardModel.appendRow([idItem,attrItem])
             
        #Configure completer   
        personCompleter = QCompleter(self) 
        personCompleter.setModel(self.personStandardModel)        
        personCompleter.setCompletionColumn(1)        
        personCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        personCompleter.setCompletionMode(QCompleter.PopupCompletion)
        self.txtFilterPattern.setCompleter(personCompleter)
        
        #Connect 'activated' slot for the completer to load person information
        self.connect(personCompleter, SIGNAL("activated(const QModelIndex&)"),self._updatePersonSummary)        
                
    def _updatePersonSummary(self,index):
        '''
        Slot for updating the person information into the tree widget based on the user-selected value
        '''
        #Get the id from the model then the value of the ID model index
        row = index.row()
        idIndex = self.personStandardModel.index(row, 0)
        personId,ok = idIndex.data().toInt()  
        
        #Get person info
        person = Person()
        p = person.queryObject().filter(Person.id == personId).first()
        if p:   
            self.selPerson = p
                     
            personInfoMapping = self._mapPersonAttributes(p)
            personTreeLoader = TreeSummaryLoader(self.tvPersonInfo)
            personTreeLoader.addCollection(personInfoMapping, QApplication.translate("newSTRWiz","Occupant Information"), 
                                           ":/plugins/stdm/images/icons/user.png")
            personTreeLoader.display()
            
    def _mapPersonAttributes(self,person):
        '''
        Maps the attributes of a person to a more friendly user representation 
        '''   
        #Setup formatters 
        genderFormatter = LookupFormatter(CheckGender)
        dobFormatter = DoBFormatter()
        maritalStatFormatter = LookupFormatter(CheckMaritalStatus)
                     
        pMapping = OrderedDict()
        
        pMapping["First Name"] = person.firstname
        pMapping["Last Name"] = person.lastname
        pMapping["Nick Name"] = person.nickname
        pMapping["Position"] = person.firstname
        pMapping["Gender"] = str(genderFormatter.setDisplay(person.gender_id).toString())
        pMapping["Age"] = str(dobFormatter.setDisplay(person.date_of_birth))        
        pMapping["Marital Status"] = str(maritalStatFormatter.setDisplay(person.marital_status_id).toString())
        pMapping["National Identification Number"] = str(person.identification_number)
        pMapping["Telephone Number"] = person.telephone     
        pMapping["Address"] = person.address
                    
        return pMapping  
    
    def _updatePropertySummary(self,propid):
        '''
        Update the summary information for the selected property
        '''       
        propty = Property()
        prop = propty.queryObject().filter(Property.PropertyID == str(propid)).first()
        
        if prop:
            propMapping = self._mapPropertyAttributes(prop)
            
            #Load information in the tree view
            propertyTreeLoader = TreeSummaryLoader(self.tvPropInfo)
            propertyTreeLoader.addCollection(propMapping, QApplication.translate("newSTRWiz","Property Information"), 
                                             ":/plugins/stdm/images/icons/property.png")       
            propertyTreeLoader.display()  
            
            self.selProperty = prop
            
            #Show property in OpenLayers
            if self.gpOpenLayers.isChecked():
                if self.olLoaded:
                    self.overlayProperty()                      
    
    def _mapPropertyAttributes(self,prop):
            #Configure formatters
            useTypeFormatter = LookupFormatter(CheckBuildingUseType)
            descFormatter = LookupFormatter(CheckBuildingDescription)
            roofTypeFormatter = LookupFormatter(CheckRoofType)
            wallNatureFormatter = LookupFormatter(CheckWallNature)
            boundTypeFormatter = LookupFormatter(CheckBoundaryType)
            accessionFormatter = LookupFormatter(CheckAccessionMode)

            #Check for nulls
            if prop.locality:
                locArea = prop.locality.area
                locStreetNum = prop.locality.street_number
            else:
                locArea = ""
                locStreetNum = ""
            
            propMapping = OrderedDict()
            propMapping[str(QApplication.translate("newSTRWiz","Identifier"))] = prop.PropertyID
            propMapping[str(QApplication.translate("newSTRWiz","Locality"))] = {
                                                                                unicode(QApplication.translate("newSTRWiz","Area")):locArea,
                                                                                unicode(QApplication.translate("newSTRWiz","Street Number")):locStreetNum
                                                                                }
            propMapping[str(QApplication.translate("newSTRWiz","Property Use Type"))] = unicode(useTypeFormatter.setDisplay(prop.UseTypeID).toString())
            propMapping[str(QApplication.translate("newSTRWiz","Description"))] = unicode(descFormatter.setDisplay(prop.DescriptionID).toString())
            propMapping[str(QApplication.translate("newSTRWiz","Number of Floors"))] = unicode(prop.NumFloors)
            propMapping[str(QApplication.translate("newSTRWiz","Type of Building Roof"))] = unicode(roofTypeFormatter.setDisplay(prop.RoofTypeID).toString())            
            propMapping[str(QApplication.translate("newSTRWiz","Nature of Walls"))] = unicode(wallNatureFormatter.setDisplay(prop.NatureWalls).toString())
            propMapping[str(QApplication.translate("newSTRWiz","Type of Boundary"))] = unicode(boundTypeFormatter.setDisplay(prop.BoundaryType).toString())
            propMapping[str(QApplication.translate("newSTRWiz","Number of Rooms"))] = unicode(prop.NumRooms)
            propMapping[str(QApplication.translate("newSTRWiz","Land Value"))] = unicode(prop.LandValue)
            propMapping[str(QApplication.translate("newSTRWiz","Building Value"))] = unicode(prop.BuildingValue)
            propMapping[str(QApplication.translate("newSTRWiz","Combined Value"))] = unicode(prop.CombinedValue)
            propMapping[str(QApplication.translate("newSTRWiz","Type of Land Accession"))] = unicode(accessionFormatter.setDisplay(prop.LandAccessionID).toString())
            propMapping[str(QApplication.translate("newSTRWiz","Land Accession Year"))] = unicode(prop.LandAccessionYear)
            propMapping[str(QApplication.translate("newSTRWiz","Type of Building Accession"))] = unicode(accessionFormatter.setDisplay(prop.BuildingAccessionID).toString())
            propMapping[str(QApplication.translate("newSTRWiz","Building Accession Year"))] = unicode(prop.BuildingAccessionYear)
            
            return propMapping
        
    def _mapSTRTypeSelection(self):
        strTypeFormatter = LookupFormatter(CheckSocialTenureRelationship)
        strTypeSelection,ok = self.cboSTRType.itemData(self.cboSTRType.currentIndex()).toInt()
        
        strMapping = OrderedDict()
        strMapping[str(QApplication.translate("newSTRWiz","STR Type"))] = str(strTypeFormatter.setDisplay(strTypeSelection).toString())
        
        if self.chkSTRAgreement.isChecked():
            agreementText = str(QApplication.translate("newSTRWiz","Yes"))
        else:
            agreementText = str(QApplication.translate("newSTRWiz","No"))
        strMapping[str(QApplication.translate("newSTRWiz","Written Agreement Available"))] = agreementText
        
        return strMapping
    
    def _mapEnjoyRightSelection(self,enjoyRight):
        deadAliveFormatter = LookupFormatter(CheckDeadAlive)
        inheritanceFormatter = LookupFormatter(CheckInheritanceType)
                
        enjoyRightMapping = OrderedDict()
        enjoyRightMapping[str(QApplication.translate("newSTRWiz","Inheritance From"))] = str(inheritanceFormatter.setDisplay(enjoyRight.InheritanceType).toString())
        enjoyRightMapping[str(QApplication.translate("newSTRWiz","State"))] = str(deadAliveFormatter.setDisplay(enjoyRight.State).toString())
        enjoyRightMapping[str(QApplication.translate("newSTRWiz","Receiving Date"))] = str(enjoyRight.ReceivingDate.year)
        
        return enjoyRightMapping
    
    def _mapPrivatePropertyTax(self):
        privateTaxMapping = OrderedDict()
        
        privateTaxMapping[str(QApplication.translate("newSTRWiz","CFPB Payment Year"))] = str(self.dtLastYearCFBP.date().toPyDate().year)
        
        taxDec = Decimal(str(self.txtCFBPAmount.text()))
        taxFormatted = moneyfmt(taxDec,curr=CURRENCY_CODE)
        privateTaxMapping[str(QApplication.translate("newSTRWiz","CFPB Amount"))] = taxFormatted
        
        return privateTaxMapping
    
    def _mapStatePropertyTax(self):
        stateTaxMapping = OrderedDict()
        
        stateTaxMapping[str(QApplication.translate("newSTRWiz","Latest Receipt Date"))] = str(self.dtStateReceiptDate.date().toPyDate())
        
        taxDec = Decimal(str(self.txtStateReceiptAmount.text()))
        taxFormatted = moneyfmt(taxDec,curr=CURRENCY_CODE)
        stateTaxMapping[str(QApplication.translate("newSTRWiz","Amount"))] = taxFormatted
        stateTaxMapping[str(QApplication.translate("newSTRWiz","Lease Starting Year"))] = str(self.dtStateLeaseYear.date().toPyDate().year)
        stateTaxMapping[str(QApplication.translate("newSTRWiz","Tax Office"))] = str(self.txtStateTaxOffice.text())
        
        return stateTaxMapping
    
    def _mapConflict(self,conflict):
        conflictFormatter = LookupFormatter(CheckConflictState)
        conflictMapping = OrderedDict()
        
        if conflict == None:
            return conflictMapping
        
        conflictMapping[str(QApplication.translate("newSTRWiz","Status"))] = str(conflictFormatter.setDisplay(conflict.StateID).toString())
        
        if conflict.Description:
            conflictMapping[str(QApplication.translate("newSTRWiz","Description"))] = conflict.Description
            
        if conflict.Solution:
            conflictMapping[str(QApplication.translate("newSTRWiz","Solution"))] = conflict.Solution
         
        return conflictMapping
    
    def onLoadGMaps(self,state):
        '''
        Slot raised when a user clicks to set Google Maps Satellite
        as the base layer
        '''
        if state:                     
            self.propBrowser.setBaseLayer(GMAP_SATELLITE)
        
    def onLoadOSM(self,state):
        '''
        Slot raised when a user clicks to set OSM as the base layer
        '''
        if state:                     
            self.propBrowser.setBaseLayer(OSM)
            
    def onMapZoomLevelChanged(self,level):
        '''
        Slot which is raised when the zoom level of the map changes.
        '''
        self.zoomSlider.setValue(level)
       
    def _onResetMap(self):
        '''
        Slot raised when the user clicks to reset the property
        location in the map.
        '''
        self.propBrowser.zoomToPropertyExtents()
       
    def overlayProperty(self):
        '''
        Overlay property boundaries on the basemap imagery
        '''                    
        self.propBrowser.addOverlay(self.selProperty,"PropertyID")
        
    def validateEnjoymentRight(self): 
        '''
        Validate whether the user has specified all the required information
        '''
        self.notifEnjoyment.clear()
        
        if self.cboDeadAlive.currentIndex() == 0:
            msg = QApplication.translate("newSTRWiz", 
                                             "Please specify whether the person is 'Dead' or 'Alive'.")
            self.notifEnjoyment.insertErrorNotification(msg)
            return False
        
        if self.cboInheritanceType.currentIndex() == 0:
            msg = QApplication.translate("newSTRWiz", 
                                             "Please specify the Inheritance Type.")
            self.notifEnjoyment.insertErrorNotification(msg)
            return False
        
        #Set the right of enjoyment details if both inheritance type and state have been defined
        if self.cboInheritanceType.currentIndex() != 0 and self.cboDeadAlive.currentIndex() != 0:
            eRight = EnjoymentRight()
            #Set the properties
            setModelAttrFromCombo(eRight,"InheritanceType",self.cboInheritanceType)
            setModelAttrFromCombo(eRight,"State",self.cboDeadAlive)
            eRight.ReceivingDate = self.dtReceivingDate.date().toPyDate()
            
            self.enjoymentRight = eRight
            
            return True
        
    def validateSourceDocuments(self):
        '''
        Basically validates the entry of tax information.
        '''
        isValid = True
        
        if self.rbPrivateProperty.isChecked():
            if self.gpPrivateTaxInfo.isChecked():
                self.notifSourceDoc.clear()
                if str(self.txtCFBPAmount.text()) == "": 
                    self.txtCFBPAmount.setFocus()
                    msg1 = QApplication.translate("newSTRWiz", 
                                             "Please enter the tax amount.")
                    self.notifSourceDoc.insertErrorNotification(msg1)
                    isValid = False
                    
        elif self.rbStateland.isChecked():
            self.notifSourceDoc.clear()
            if str(self.txtStateReceiptAmount.text()) == "": 
                    self.txtStateReceiptAmount.setFocus()
                    msg2 = QApplication.translate("newSTRWiz", 
                                             "Please enter the tax amount.")
                    self.notifSourceDoc.insertErrorNotification(msg2)
                    isValid = False
            if str(self.txtStateTaxOffice.text()) == "": 
                    self.txtStateTaxOffice.setFocus()
                    msg3 = QApplication.translate("newSTRWiz", 
                                             "Please specify the tax office.")
                    self.notifSourceDoc.insertErrorNotification(msg3)
                    isValid = False
   
        return isValid
    
    def validateConflict(self): 
        '''
        Check if the user has selected that there is a conflict and validate whether the description 
        and solution have been specified.
        '''
        isValid = True
        
        nonConflict = QApplication.translate("Lookup","No Conflict")
        nonConflictIndex = self.cboConflictOccurrence.findText(nonConflict)
        conflictOccurrence = QApplication.translate("Lookup","Conflict Present")
        occIndex = self.cboConflictOccurrence.findText(conflictOccurrence)
        
        if self.cboConflictOccurrence.currentIndex() == occIndex:
            self.notifConflict.clear()
            if str(self.txtConflictDescription.toPlainText()) == "":
                msg1 = QApplication.translate("newSTRWiz", 
                                             "Please provide a brief description of the conflict.")
                self.notifConflict.insertErrorNotification(msg1)
                isValid = False
            if str(self.txtConflictSolution.toPlainText()) == "":
                msg2 = QApplication.translate("newSTRWiz", 
                                             "Please provide a proposed solution for the specified conflict.")
                self.notifConflict.insertErrorNotification(msg2)
                isValid = False
                
            if str(self.txtConflictSolution.toPlainText()) != "" and str(self.txtConflictDescription.toPlainText()) != "":
                self.conflict = Conflict()
                stateId,ok = self.cboConflictOccurrence.itemData(occIndex).toInt()
                self.conflict.StateID = stateId
                self.conflict.Description = str(self.txtConflictDescription.toPlainText())
                self.conflict.Solution = str(self.txtConflictSolution.toPlainText())
                
        #Set conflict object properties
        if self.cboConflictOccurrence.currentIndex() == nonConflictIndex:
            self.conflict = Conflict()
            stateId,ok = self.cboConflictOccurrence.itemData(nonConflictIndex).toInt()
            self.conflict.StateID = stateId
   
        return isValid
    
    def onSelectPrivateProperty(self,state):
        '''
        Slot raised when the user clicks to load source document page for private property
        '''
        if state:
            self.stkSrcDocList.setCurrentIndex(0)
        
    def onSelectStateland(self,state):
        '''
        Slot raised when the user clicks to load source document page for private property
        '''
        if state:
            self.stkSrcDocList.setCurrentIndex(1)
            
    def onUploadTitleDeed(self):
        '''
        Slot raised when the user clicks to upload a title deed
        '''
        titleStr = QApplication.translate("newSTRWiz", 
                                             "Specify Title Deed File Location")
        titles = self.selectSourceDocumentDialog(titleStr)
        
        for title in titles:
            self.sourceDocManager.insertDocumentFromFile(title,TITLE_DEED)
            
    def onUploadStatutoryRefPaper(self):
        '''
        Slot raised when the user clicks to upload a statutory reference paper
        '''
        statStr = QApplication.translate("newSTRWiz", 
                                             "Specify Statutory Reference Paper File Location")
        stats = self.selectSourceDocumentDialog(statStr)
        
        for stat in stats:
            self.sourceDocManager.insertDocumentFromFile(stat,STATUTORY_REF_PAPER)
            
    def onUploadSurveyorRef(self):
        '''
        Slot raised when the user clicks to upload a surveyor reference
        '''
        surveyorStr = QApplication.translate("newSTRWiz", 
                                             "Specify Surveyor Reference File Location")
        surveyorRefs = self.selectSourceDocumentDialog(surveyorStr)
        
        for surveyorRef in surveyorRefs:
            self.sourceDocManager.insertDocumentFromFile(surveyorRef,SURVEYOR_REF)
            
    def onUploadNotaryRef(self):
        '''
        Slot raised when the user clicks to upload a notary reference
        '''
        notaryStr = QApplication.translate("newSTRWiz", 
                                             "Specify Notary Reference File Location")
        notaryRefs = self.selectSourceDocumentDialog(notaryStr)
        
        for notaryRef in notaryRefs:
            self.sourceDocManager.insertDocumentFromFile(notaryRef,NOTARY_REF)
            
    def onUploadPrivateReceiptScan(self):
        '''
        Slot raised when the user clicks to upload a receipt scan for private property
        '''
        receiptScan = QApplication.translate("newSTRWiz", 
                                             "Specify Receipt Scan File Location")
        scan = self.selectReceiptScanDialog(receiptScan)
        
        if scan != "" or scan != None:
            #Ensure that there is only one tax receipt document before inserting
            self.validateReceiptScanInsertion(self.privateTaxDocManager, scan, TAX_RECEIPT_PRIVATE)
            
    def onUploadStateReceiptScan(self):
        '''
        Slot raised when the user clicks to upload a receipt scan for stateland
        '''
        receiptScan = QApplication.translate("newSTRWiz", 
                                             "Specify Receipt Scan File Location")
        scan = self.selectReceiptScanDialog(receiptScan)
        
        if scan != "" or scan != None:
            #Ensure that there is only one tax receipt document before inserting
            self.validateReceiptScanInsertion(self.stateTaxDocManager, scan, TAX_RECEIPT_STATE)
            
    def validateReceiptScanInsertion(self,documentmanager,scan,containerid):
        '''
        Checks and ensures that only one document exists in the specified container.
        '''
        container = documentmanager.container(containerid)
        if container.count() > 0:
            msg = QApplication.translate("newSTRWiz", "Only one receipt scan can be uploaded.\nWould you like to replace " \
                                         "the existing one?")
            result = QMessageBox.warning(self,QApplication.translate("newSTRWiz","Replace Receipt Scan"),msg, QMessageBox.Yes|
                                         QMessageBox.No)
            if result == QMessageBox.Yes:
                docWidget = container.itemAt(0).widget()
                docWidget.removeDocument()
                documentmanager.insertDocumentFromFile(scan,containerid)
            else:
                return
        else:
            documentmanager.insertDocumentFromFile(scan,containerid)
        
    def selectSourceDocumentDialog(self,title):
        '''
        Displays a file dialog for a user to specify a source document
        '''
        files = QFileDialog.getOpenFileNames(self,title,"/home","Source Documents (*.pdf)")
        return files
    
    def selectReceiptScanDialog(self,title):
        '''
        Displays a file dialog for a user to specify a file location of a receipt scan
        '''
        file = QFileDialog.getOpenFileName(self,title,"/home","Tax Receipt Scan (*.pdf)")
        return file
        
    def uploadDocument(self,path,containerid):
        '''
        Upload source document
        '''
        self.sourceDocManager.insertDocumentFromFile(path, containerid)
コード例 #22
0
ファイル: view_str.py プロジェクト: mwasjos/stdm
class ViewSTRWidget(QMainWindow, Ui_frmManageSTR):
    """
    Search and browse the social tenure relationship of all participating entities.
    """

    def __init__(self, plugin):
        QMainWindow.__init__(self, plugin.iface.mainWindow())
        self.setupUi(self)

        self._plugin = plugin
        self.tbPropertyPreview.set_iface(self._plugin.iface)

        # Center me
        self.move(QDesktopWidget().availableGeometry().center() - self.frameGeometry().center())

        # set whether currently logged in user has permissions to edit existing STR records
        self._can_edit = self._plugin.STRCntGroup.canUpdate()

        """
        Variable used to store a reference to the currently selected social tenure relationship
        when displaying documents in the supporting documents tab window.
        This ensures that there are no duplicates when the same item is selected over and over again.
        """
        self._strID = None

        # Used to store the root hash of the currently selected node.
        self._curr_rootnode_hash = ""
        self._source_doc_manager = SourceDocumentManager()
        self._source_doc_manager.documentRemoved.connect(self.onSourceDocumentRemoved)
        self._source_doc_manager.setEditPermissions(self._can_edit)

        self._config_table_reader = ConfigTableReader()

        self.initGui()

    def initGui(self):
        """
        Initialize widget
        """
        self.tb_actions.setVisible(False)
        self._load_entity_configurations()

        # self.gb_supporting_docs.setCollapsed(True)

        # Connect signals
        self.tbSTREntity.currentChanged.connect(self.entityTabIndexChanged)
        self.btnSearch.clicked.connect(self.searchEntityRelations)
        self.btnClearSearch.clicked.connect(self.clearSearch)
        self.tvSTRResults.expanded.connect(self.onTreeViewItemExpanded)

        # Configure notification bar
        self._notif_search_config = NotificationBar(self.vl_notification)

        # Set the results treeview to accept requests for context menus
        self.tvSTRResults.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tvSTRResults.customContextMenuRequested.connect(self.onResultsContextMenuRequested)

        # Load async for the current widget
        self.entityTabIndexChanged(0)

    def _check_permissions(self):
        """
        Enable/disable actions based on the permissions defined in the content
        group.
        """
        if self._can_edit:
            self.tb_actions.addAction(self._new_str_action)
        else:
            self.tb_actions.removeAction(self._new_str_action)

        if len(self.tb_actions.actions()) == 0:
            self.tb_actions.setVisible(False)

        else:
            self.tb_actions.setVisible(True)

    def _load_entity_configurations(self):
        """
        Specify the entity configurations.
        """
        try:
            tables = self._config_table_reader.social_tenure_tables()

            for t in tables:
                # Ensure 'supporting_document' table is not in the list
                if t.find("supporting_document") == -1:
                    entity_cfg = self._entity_config_from_table(t)

                    if not entity_cfg is None:
                        entity_widget = self.add_entity_config(entity_cfg)
                        entity_widget.setNodeFormatter(EntityNodeFormatter(entity_cfg, self.tvSTRResults, self))

        except ProfileException as pe:
            self._notif_bar.clear()
            self._notif_bar.insertErrorNotification(pe.message)

    def _entity_config_from_table(self, table_name):
        """
        Creates an EntityConfig object from the table name.
        :param table_name: Name of the database table.
        :type table_name: str
        :return: Entity configuration object.
        :rtype: EntityConfig
        """
        table_display_name = display_name(table_name)
        model = DeclareMapping.instance().tableMapping(table_name)

        if model is not None:
            # Entity configuration
            entity_cfg = EntityConfiguration()
            entity_cfg.Title = table_display_name
            entity_cfg.STRModel = model
            entity_cfg.data_source_name = table_name

            """
            Load filter and display columns using only those which are of
            numeric/varchar type
            """
            cols = numeric_varchar_columns(table_name)
            search_cols = self._config_table_reader.table_searchable_columns(table_name)
            disp_cols = self._config_table_reader.table_columns(table_name)

            for c in search_cols:
                # Ensure it is a numeric or text type column
                if c in cols:
                    entity_cfg.filterColumns[c] = display_name(c)

            if len(disp_cols) == 0:
                entity_cfg.displayColumns = entity_cfg.displayColumns

            else:
                for dc in disp_cols:
                    if dc in cols:
                        entity_cfg.displayColumns[dc] = display_name(dc)

            return entity_cfg

        else:
            return None

    def add_entity_config(self, config):
        """
        Set an entity configuration option and add it to the 'Search Entity' tab.
        """
        entityWidg = STRViewEntityWidget(config)
        entityWidg.asyncStarted.connect(self._progressStart)
        entityWidg.asyncFinished.connect(self._progressFinish)
        tabIndex = self.tbSTREntity.addTab(entityWidg, config.Title)

        return entityWidg

    def entityTabIndexChanged(self, index):
        """
        Raised when the tab index of the entity search tab widget changes.
        """
        # Get the current widget in the tab container
        entityWidget = self.tbSTREntity.currentWidget()

        if isinstance(entityWidget, EntitySearchItem):
            entityWidget.loadAsync()

    def searchEntityRelations(self):
        """
        Slot that searches for matching items for the specified entity and corresponding STR entities.
        """
        self._reset_controls()

        entityWidget = self.tbSTREntity.currentWidget()
        if isinstance(entityWidget, EntitySearchItem):
            valid, msg = entityWidget.validate()

            if not valid:
                self._notif_search_config.clear()
                self._notif_search_config.insertErrorNotification(msg)

                return

            formattedNode, results, searchWord = entityWidget.executeSearch()

            # Show error message
            if len(results) == 0:
                noResultsMsg = QApplication.translate("ViewSTR", "No results found for '" + searchWord + "'")
                self._notif_search_config.clear()
                self._notif_search_config.insertErrorNotification(noResultsMsg)

                return

            if formattedNode is not None:
                self._load_root_node(formattedNode)

    def clearSearch(self):
        """
        Clear search input parameters (for current widget) and results.
        """
        entityWidget = self.tbSTREntity.currentWidget()
        if isinstance(entityWidget, EntitySearchItem):
            entityWidget.reset()

        self._reset_controls()

    def _reset_controls(self):
        # Clear tree view
        self._resetTreeView()

        # Clear document listings
        self._deleteSourceDocTabs()

        # Remove spatial unit memory layer
        self.tbPropertyPreview.remove_layer()

    def on_select_results(self, selected, deselected):
        """
        Slot which is raised when the selection is changed in the tree view
        selection model.
        """
        selIndexes = selected.indexes()

        # Check type of node and perform corresponding action
        for mi in selIndexes:
            if mi.isValid():
                node = mi.internalPointer()

                if mi.column() == 0:
                    # Assert if node represents another entity has been clicked
                    self._on_node_reference_changed(node.rootHash())

                    if isinstance(node, SupportsDocumentsNode):
                        src_docs = node.documents()
                        str_id = node.id()

                        if str_id != self._strID:
                            self._strID = str_id
                            self._load_source_documents(src_docs)

                    if isinstance(node, SpatialUnitNode):
                        self.draw_spatial_unit(node.model())

    def onSourceDocumentRemoved(self, container_id):
        """
        Slot raised when a source document is removed from the container.
        If there are no documents in the specified container then remove
        the tab.
        """
        for i in range(self.tbSupportingDocs.count()):
            docwidget = self.tbSupportingDocs.widget(i)
            if docwidget.containerId() == container_id:
                docCount = docwidget.container().count()
                if docCount == 0:
                    self.tbSupportingDocs.removeTab(i)
                    del docwidget
                    break

    def draw_spatial_unit(self, model):
        """
        Render the geometry of the given spatial unit in the spatial view.
        :param row_id: Sqlalchemy oject representing a feature.
        """
        self.tbPropertyPreview.draw_spatial_unit(model)

    def removeSourceDocumentWidget(self, container_id):
        """
        Convenience method that removes the tab widget that lists the source documents
        with the given container id.
        """
        for i in range(self.tbSupportingDocs.count()):
            docwidget = self.tbSupportingDocs.widget(i)
            if docwidget.containerId() == container_id:
                self.tbSupportingDocs.removeTab(i)
                self._source_doc_manager.removeContainer(container_id)
                del docwidget
                break

    def onTreeViewItemExpanded(self, modelindex):
        """
        Raised when a tree view item is expanded.
        Reset the document listing and map view if the hash
        of the parent node is different.
        """
        if modelindex.isValid():
            node = modelindex.internalPointer()
            # Assert if node representing another entity has been clicked
            self._on_node_reference_changed(node.rootHash())

    def onResultsContextMenuRequested(self, pnt):
        """
        Slot raised when the user right-clicks on a node item to request the
        corresponding context menu.
        """
        # Get the model index at the specified point
        mi = self.tvSTRResults.indexAt(pnt)
        if mi.isValid():
            node = mi.internalPointer()
            rMenu = QMenu(self)
            # Load node actions items into the context menu
            node.manageActions(mi, rMenu)
            rMenu.exec_(QCursor.pos())

    def showEvent(self, event):
        """
        (Re)load map layers in the viewer canvas.
        :param event: Window event
        :type event: QShowEvent
        """
        # Check if there are entity configurations defined
        if self.tbSTREntity.count() == 0:
            msg = QApplication.translate(
                "ViewSTR",
                "There are no configured "
                "entities to search against. Please "
                "check the social tenure relationship "
                "tables in the Form Designer.",
            )
            QMessageBox.critical(self, QApplication.translate("ViewSTR", "Social Tenure Relationship"), msg)
            self.setEnabled(False)
            event.ignore()

            return QMainWindow.showEvent(self, event)

        if not self._check_str_table():
            msg = QApplication.translate(
                "ViewSTR",
                "'social_tenure_relationship' "
                "table could not be found. Please "
                "recreate the table in the Form "
                "Designer and configure the related "
                "entities.",
            )
            QMessageBox.critical(self, QApplication.translate("ViewSTR", "Social Tenure Relationship"), msg)
            self.setEnabled(False)
            event.ignore()

            return QMainWindow.showEvent(self, event)

        self.setEnabled(True)

        self._notify_no_base_layers()

        self.tbPropertyPreview.refresh_canvas_layers()
        self.tbPropertyPreview.load_web_map()

        return QMainWindow.showEvent(self, event)

    def _check_str_table(self):
        """
        Checks whether a table explicitly named 'social_tenure_relationship'
        exists in th database.
        :return: True if the table exists.Otherwise False.
        :rtype: bool
        """
        return pg_table_exists("social_tenure_relationship", False)

    def _notify_no_base_layers(self):
        """
        Checks if there are any base layers that will be used when
        visualizing the spatial units. If there are no base layers
        then insert warning message.
        """
        self._notif_search_config.clear()

        num_layers = len(self._plugin.iface.legendInterface().layers())
        if num_layers == 0:
            msg = QApplication.translate(
                "ViewSTR",
                "No basemap layers are loaded in the current project. "
                "Basemap layers enhance the visualization of"
                " spatial units.",
            )
            self._notif_search_config.insertWarningNotification(msg)

    def _deleteSourceDocTabs(self):
        """
        Removes all source document tabs and deletes their references.
        """
        tabCount = self.tbSupportingDocs.count()

        while tabCount != 0:
            srcDocWidget = self.tbSupportingDocs.widget(tabCount - 1)
            self.tbSupportingDocs.removeTab(tabCount - 1)
            del srcDocWidget
            tabCount -= 1

        self._strID = None
        self._source_doc_manager.reset()

    def _resetTreeView(self):
        """
        Clears the results tree view.
        """
        # Reset tree view
        strModel = self.tvSTRResults.model()
        resultsSelModel = self.tvSTRResults.selectionModel()

        if strModel:
            strModel.clear()

        if resultsSelModel:
            self.disconnect(
                resultsSelModel,
                SIGNAL("selectionChanged(const QItemSelection&,const QItemSelection&)"),
                self.on_select_results,
            )

    def _load_root_node(self, root):
        """
        Load the search results (formatted into an object of type 'stdm.navigaion.STR') into
        the tree view.
        """
        strTreeViewModel = STRTreeViewModel(root, view=self.tvSTRResults)
        self.tvSTRResults.setModel(strTreeViewModel)

        # Resize tree columns to fit contents
        self._resize_columns()

        # Capture selection changes signals when results are returned in the tree view
        resultsSelModel = self.tvSTRResults.selectionModel()
        resultsSelModel.selectionChanged.connect(self.on_select_results)

    def _resize_columns(self):
        """
        Adjusts the column sizes to fit its contents
        """
        qModel = self.tvSTRResults.model()
        columnCount = qModel.columnCount()

        for i in range(columnCount):
            self.tvSTRResults.resizeColumnToContents(i)

        # Once resized then slightly increase the width of the first column so that text for 'No STR Defined' visible.
        currColWidth = self.tvSTRResults.columnWidth(0)
        newColWidth = currColWidth + 100
        self.tvSTRResults.setColumnWidth(0, newColWidth)

    def _load_source_documents(self, source_docs):
        """
        Load source documents into document listing widget.
        """
        # Configure progress dialog
        progressMsg = QApplication.translate("ViewSTR", "Loading supporting documents...")
        progressDialog = QProgressDialog(progressMsg, "", 0, len(source_docs), self)
        progressDialog.setWindowModality(Qt.WindowModal)

        for i, doc in enumerate(source_docs):
            progressDialog.setValue(i)
            type_id = doc.document_type
            container = self._source_doc_manager.container(type_id)

            # Check if a container has been defined and create if None is found
            if container is None:
                src_doc_widget = SourceDocumentContainerWidget(type_id)
                container = src_doc_widget.container()
                self._source_doc_manager.registerContainer(container, type_id)

                # Add widget to tab container for source documents
                tab_title = QApplication.translate("ViewSTR", "General")
                if type_id in DOC_TYPE_MAPPING:
                    tab_title = DOC_TYPE_MAPPING[type_id]

                else:
                    if type_id in STR_DOC_TYPE_MAPPING:
                        tab_title = STR_DOC_TYPE_MAPPING[type_id]

                self.tbSupportingDocs.addTab(src_doc_widget, tab_title)

            self._source_doc_manager.insertDocFromModel(doc, type_id)

        progressDialog.setValue(len(source_docs))

    def _on_node_reference_changed(self, rootHash):
        """
        Method for resetting document listing and map preview if another root node and its children
        are selected then the documents are reset as well as the map preview control.
        """
        if rootHash != self._curr_rootnode_hash:
            self._deleteSourceDocTabs()
            self._curr_rootnode_hash = rootHash

    def _progressStart(self):
        """
        Load progress dialog window.
        For items whose durations is unknown, 'isindefinite' = True by default.
        If 'isindefinite' is False, then 'rangeitems' has to be specified.
        """
        pass

    def _progressFinish(self):
        """
        Hide progress dialog window.
        """
        pass

    def _edit_permissions(self):
        """
        Returns True/False whether the current logged in user has permissions to create new social tenure relationships.
        If true, then the system assumes that they can also edit STR records.
        """
        canEdit = False
        userName = stdm.data.app_dbconn.User.UserName
        authorizer = Authorizer(userName)
        newSTRCode = "9576A88D-C434-40A6-A318-F830216CA15A"

        # Get the name of the content from the code
        cnt = Content()
        createSTRCnt = cnt.queryObject().filter(Content.code == newSTRCode).first()
        if createSTRCnt:
            name = createSTRCnt.name
            canEdit = authorizer.CheckAccess(name)

        return canEdit
コード例 #23
0
class LicenseAgreement(QDialog, Ui_LicenseAgreement):
    def __init__(self, parent=None):
        """
        This class checks if the user has accepted the
        license terms and conditions or not . It shows the
        terms and conditions if not.
        :param parent: The container of the dialog
        :type parent: QMainWindow or None
        :return: None
        :rtype: NoneType
        """
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.reg_config = RegistryConfig()
        self.notice_bar = NotificationBar(self.notifBar)
        self.accepted = False
        self.btnAccept.clicked.connect(self.accept_action)
        self.btnDecline.clicked.connect(self.decline_action)
        self.label.setStyleSheet('''
            QLabel {
                font: bold;
            }
            ''')

    def check_show_license(self):
        """
        Checks if you need to show the license page.
        Checks if the flag in the registry has been set.
        Returns True to show license. If registry key
        is not yet set, show the license page.
        :rtype: boolean
        """
        show_lic = 1
        license_key = self.reg_config.read([SHOW_LICENSE])

        if len(license_key) > 0:
            show_lic = license_key[SHOW_LICENSE]

        if show_lic == 1 or show_lic == unicode(1):
            return True
        elif show_lic == 0 or show_lic == unicode(0):
            self.accepted = True
            return False

    def show_license(self):
        """
        Show STDM license window if the user have never
        accepted the license terms and conditions.
        :return: None
        :rtype: NoneType
        """
        # validate if to show license
        show_lic = self.check_show_license()
        # THe user didn't accept license
        if show_lic:
            license = LicenseDocument()

            self.termsCondArea.setText(license.read_license_info())

            self.exec_()

    def accept_action(self):
        """
        A slot raised when the user clicks on the Accept button.
        :return: None
        :rtype: NoneType
        """
        if not self.checkBoxAgree.isChecked():
            msg = QApplication.translate(
                'LicenseAgreement', 'To use STDM, please accept the terms '
                'and conditions by selecting'
                ' the checkbox "I have read and agree ..."')

            self.notice_bar.clear()
            self.notice_bar.insertNotification(msg, ERROR)
            return

        else:
            self.reg_config.write({SHOW_LICENSE: 0})
            self.accepted = True
            self.close()

    def decline_action(self):
        """
        A slot raised when the user clicks on
        the decline button.
        :return: None
        :rtype: NoneType
        """
        self.accepted = False
        self.close()
コード例 #24
0
ファイル: view_str.py プロジェクト: timlinux/stdm_plugin
class ViewSTRWidget(QWidget, Ui_frmViewSTR):
    '''
    Search and browse the social tenure relationship of all participating entities.
    '''
    def __init__(self, plugin):
        QWidget.__init__(self, plugin.iface.mainWindow(), Qt.Window)
        self.setupUi(self)

        #Center me
        self.move(QDesktopWidget().availableGeometry().center() -
                  self.frameGeometry().center())

        #set whether currently logged in user has permissions to edit existing STR records
        self._canEdit = self._getEditPermissions()
        '''
        Variable used to store a reference to the currently selected social tenure relationship
        when displaying documents in the supporting documents tab window.
        This ensures that there are no duplicates when the same item is selected over and over again.
        '''
        self._strID = None
        #Used to store the root hash of the currently selected node.
        self._currRootNodeHash = ""
        self._sourceDocManager = SourceDocumentManager()
        self.connect(self._sourceDocManager, SIGNAL("documentRemoved(int)"),
                     self.onSourceDocumentRemoved)
        self._sourceDocManager.setEditPermissions(self._canEdit)

        self.initGui()

    def initGui(self):
        '''
        Initialize widget
        '''
        self.loadEntityConfig()
        #Hook up signals
        self.connect(self.tbSTREntity, SIGNAL("currentChanged(int)"),
                     self.entityTabIndexChanged)
        self.connect(self.btnSearch, SIGNAL("clicked()"),
                     self.searchEntityRelations)
        self.connect(self.btnClearSearch, SIGNAL("clicked()"),
                     self.clearSearch)
        self.connect(self.tvSTRResults, SIGNAL("expanded(const QModelIndex&)"),
                     self.onTreeViewItemExpanded)

        #Configure notification bars
        self.notifSearchConfig = NotificationBar(self.vlSearchEntity)

        #Set the results treeview to accept requests for context menus
        self.tvSTRResults.setContextMenuPolicy(Qt.CustomContextMenu)
        self.connect(self.tvSTRResults,
                     SIGNAL("customContextMenuRequested(const QPoint&)"),
                     self.onResultsContextMenuRequested)

        #Load async for the current widget
        self.entityTabIndexChanged(0)

    def loadEntityConfig(self):
        '''
        Specify the entity configurations.
        '''
        #Person configuration
        personCfg = EntityConfiguration()
        personCfg.Title = str(QApplication.translate("ViewSTR", "Person"))
        personCfg.filterColumns["firstname"] = str(
            QApplication.translate("ViewSTR", "First Name"))
        personCfg.filterColumns["lastname"] = str(
            QApplication.translate("ViewSTR", "Last Name"))
        personCfg.filterColumns["identification_number"] = str(
            QApplication.translate("ViewSTR", "Identification Number"))
        personCfg.STRModel = Person
        personWidget = self.setEntityConfigWidget(personCfg)
        personWidget.setNodeFormatter(
            PersonNodeFormatter(self.tvSTRResults, self))

        #Property configuration
        propertyCfg = EntityConfiguration()
        propertyCfg.Title = str(QApplication.translate("ViewSTR", "Property"))
        propertyCfg.filterColumns["PropertyID"] = str(
            QApplication.translate("ViewSTR", "Property Identifier"))
        propertyCfg.STRModel = Property
        self.setEntityConfigWidget(propertyCfg)

    def setEntityConfigWidget(self, config):
        '''
        Set an entity configuration option and add it to the 'Search Entity' tab.
        '''
        entityWidg = STRViewEntityWidget(config)
        self.connect(entityWidg, SIGNAL("asyncStarted()"), self._progressStart)
        self.connect(entityWidg, SIGNAL("asyncFinished()"),
                     self._progressFinish)
        tabIndex = self.tbSTREntity.addTab(entityWidg, config.Title)

        return entityWidg

    def entityTabIndexChanged(self, index):
        '''
        Raised when the tab index of the entity search tab widget changes.
        '''
        #Get the current widget in the tab container
        entityWidget = self.tbSTREntity.currentWidget()
        if isinstance(entityWidget, EntitySearchItem):
            entityWidget.loadAsync()

    def searchEntityRelations(self):
        '''
        Slot that searches for matching items for the specified entity and corresponding STR entities.
        '''
        self._resetTreeView()

        entityWidget = self.tbSTREntity.currentWidget()
        if isinstance(entityWidget, EntitySearchItem):
            valid, msg = entityWidget.validate()

            if not valid:
                self.notifSearchConfig.clear()
                self.notifSearchConfig.insertErrorNotification(msg)
                return

            formattedNode, results, searchWord = entityWidget.executeSearch()

            #Show error message
            if len(results) == 0:
                noResultsMsg = QApplication.translate(
                    "ViewSTR", "No results found for '" + searchWord + "'")
                self.notifSearchConfig.clear()
                self.notifSearchConfig.insertErrorNotification(noResultsMsg)
                return

            if formattedNode is not None:
                self._loadRootNodeinTree(formattedNode)

    def clearSearch(self):
        '''
        Clear search input parameters (for current widget) and results.
        '''
        entityWidget = self.tbSTREntity.currentWidget()
        if isinstance(entityWidget, EntitySearchItem):
            entityWidget.reset()

        #Clear tree view
        self._resetTreeView()

        #Clear document listings
        self._deleteSourceDocTabs()

    def onSelectResults(self, selected, deselected):
        '''
        Slot which is raised when the selection is changed in the tree view 
        selection model.
        '''
        selIndexes = selected.indexes()

        #Check type of node and perform corresponding action
        for mi in selIndexes:
            if mi.isValid():
                node = mi.internalPointer()
                #Assert if node representing another entity has been clicked
                self._onNodeReferenceChanged(node.rootHash())
                if isinstance(node, STRNode):
                    srcDocs = node.sourceDocuments()
                    strId = node.id()
                    if strId != self._strID:
                        self._strID = strId
                        self._loadSourceDocuments(srcDocs)
                    break

    def onSourceDocumentRemoved(self, containerid):
        '''
        Slot raised when a source document is removed from the container.
        If there are no documents in the specified container then remove 
        the tab.
        '''
        for i in range(self.tbSupportingDocs.count()):
            docwidget = self.tbSupportingDocs.widget(i)
            if docwidget.containerId() == containerid:
                docCount = docwidget.container().count()
                if docCount == 0:
                    self.tbSupportingDocs.removeTab(i)
                    del docwidget
                    break

    def removeSourceDocumentWidget(self, containerid):
        '''
        Convenience method that removes the tab widget that lists the source documents
        with the given container id.
        '''
        for i in range(self.tbSupportingDocs.count()):
            docwidget = self.tbSupportingDocs.widget(i)
            if docwidget.containerId() == containerid:
                self.tbSupportingDocs.removeTab(i)
                self._sourceDocManager.removeContainer(containerid)
                del docwidget
                break

    def onTreeViewItemExpanded(self, modelindex):
        '''
        Raised when a tree view item is expanded.
        Reset the document listing and map view if the hash
        of the parent node is different.
        '''
        if modelindex.isValid():
            node = modelindex.internalPointer()
            #Assert if node representing another entity has been clicked
            self._onNodeReferenceChanged(node.rootHash())

    def onResultsContextMenuRequested(self, pnt):
        '''
        Slot raised when the user right-clicks on a node item to request the
        corresponding context menu.
        '''
        #Get the model index at the specified point
        mi = self.tvSTRResults.indexAt(pnt)
        if mi.isValid():
            node = mi.internalPointer()
            rMenu = QMenu(self)
            #Load node actions items into the context menu
            node.manageActions(mi, rMenu)
            rMenu.exec_(QCursor.pos())

    def _deleteSourceDocTabs(self):
        '''
        Removes all source document tabs and deletes their references.
        '''
        tabCount = self.tbSupportingDocs.count()

        while tabCount != 0:
            srcDocWidget = self.tbSupportingDocs.widget(tabCount - 1)
            self.tbSupportingDocs.removeTab(tabCount - 1)
            del srcDocWidget
            tabCount -= 1

        self._strID = None
        self._sourceDocManager.reset()

    def _resetTreeView(self):
        '''
        Clears the results tree view.
        '''
        #Reset tree view
        strModel = self.tvSTRResults.model()
        resultsSelModel = self.tvSTRResults.selectionModel()

        if strModel:
            strModel.clear()

        if resultsSelModel:
            self.disconnect(
                resultsSelModel,
                SIGNAL(
                    "selectionChanged(const QItemSelection&,const QItemSelection&)"
                ), self.onSelectResults)

    def _loadRootNodeinTree(self, root):
        '''
        Load the search results (formatted into an object of type 'stdm.navigaion.STR') into
        the tree view.
        '''
        strTreeViewModel = STRTreeViewModel(root, view=self.tvSTRResults)
        self.tvSTRResults.setModel(strTreeViewModel)
        # Resize tree columns to fit contents
        self._resizeTreeColumns()

        #Capture selection changes signals when results are returned in the tree view
        resultsSelModel = self.tvSTRResults.selectionModel()
        self.connect(
            resultsSelModel,
            SIGNAL(
                "selectionChanged(const QItemSelection&,const QItemSelection&)"
            ), self.onSelectResults)

    def _resizeTreeColumns(self):
        '''
        Adjusts the column sizes to fit its contents
        '''
        qModel = self.tvSTRResults.model()
        columnCount = qModel.columnCount()

        for i in range(columnCount):
            self.tvSTRResults.resizeColumnToContents(i)

        #Once resized then slightly increase the width of the first column so that text for 'No STR Defined' visible.
        currColWidth = self.tvSTRResults.columnWidth(0)
        newColWidth = currColWidth + 100
        self.tvSTRResults.setColumnWidth(0, newColWidth)

    def _loadSourceDocuments(self, sourcedocs):
        '''
        Load source documents into document listing widget.
        '''
        #Check the
        #Configure progress dialog
        progressMsg = QApplication.translate(
            "ViewSTR", "Loading supporting documents...")
        progressDialog = QProgressDialog(progressMsg, QString(), 0,
                                         len(sourcedocs), self)
        progressDialog.setWindowModality(Qt.WindowModal)

        for i, doc in enumerate(sourcedocs):
            progressDialog.setValue(i)
            typeId = doc.DocumentType
            container = self._sourceDocManager.container(typeId)

            #Check if a container has been defined and create if none is found
            if container is None:
                srcDocWidget = SourceDocumentContainerWidget(typeId)
                container = srcDocWidget.container()
                self._sourceDocManager.registerContainer(container, typeId)
                #Add widget to tab container for source documents
                self.tbSupportingDocs.addTab(srcDocWidget,
                                             docTypeMapping[typeId])

            self._sourceDocManager.InsertDocFromModel(doc, typeId)

        progressDialog.setValue(len(sourcedocs))

    def _onNodeReferenceChanged(self, rootHash):
        '''
        Method for resetting document listing and map preview if another root node and its children
        are selected then the documents are reset as well as the map preview control.
        '''
        if rootHash != self._currRootNodeHash:
            self._deleteSourceDocTabs()
            self._currRootNodeHash = rootHash

    def _progressStart(self):
        '''
        Load progress dialog window.
        For items whose durations is unknown, 'isindefinite' = True by default.
        If 'isindefinite' is False, then 'rangeitems' has to be specified.
        '''
        pass

    def _progressFinish(self):
        '''
        Hide progress dialog window.
        '''
        pass

    def _getEditPermissions(self):
        '''
        Returns True/False whether the current logged in user has permissions to create new social tenure relationships.
        If true, then the system assumes that they can also edit STR records.
        '''
        canEdit = False
        userName = stdm.data.app_dbconn.User.UserName
        authorizer = Authorizer(userName)
        newSTRCode = "9576A88D-C434-40A6-A318-F830216CA15A"

        #Get the name of the content from the code
        cnt = Content()
        createSTRCnt = cnt.queryObject().filter(
            Content.code == newSTRCode).first()
        if createSTRCnt:
            name = createSTRCnt.name
            canEdit = authorizer.CheckAccess(name)

        return canEdit
コード例 #25
0
ファイル: view_str.py プロジェクト: SolomonN/stdm_plugin
class ViewSTRWidget(QWidget, Ui_frmViewSTR):
    '''
    Search and browse the social tenure relationship of all participating entities.
    '''
    def __init__(self,plugin):
        QWidget.__init__(self,plugin.iface.mainWindow(),Qt.Window)
        self.setupUi(self)
        
        #Center me
        self.move(QDesktopWidget().availableGeometry().center() - self.frameGeometry().center())
        
        #set whether currently logged in user has permissions to edit existing STR records
        self._canEdit = self._getEditPermissions()
        
        '''
        Variable used to store a reference to the currently selected social tenure relationship
        when displaying documents in the supporting documents tab window.
        This ensures that there are no duplicates when the same item is selected over and over again.
        '''
        self._strID = None
        #Used to store the root hash of the currently selected node.
        self._currRootNodeHash = ""
        self._sourceDocManager = SourceDocumentManager()
        self.connect(self._sourceDocManager,SIGNAL("documentRemoved(int)"),self.onSourceDocumentRemoved)
        self._sourceDocManager.setEditPermissions(self._canEdit)
        
        self.initGui()
        
    def initGui(self):
        '''
        Initialize widget
        '''
        self.loadEntityConfig()
        #Hook up signals
        self.connect(self.tbSTREntity, SIGNAL("currentChanged(int)"),self.entityTabIndexChanged)
        self.connect(self.btnSearch, SIGNAL("clicked()"),self.searchEntityRelations)
        self.connect(self.btnClearSearch, SIGNAL("clicked()"),self.clearSearch)
        self.connect(self.tvSTRResults,SIGNAL("expanded(const QModelIndex&)"),self.onTreeViewItemExpanded)
        
        #Configure notification bars
        self.notifSearchConfig = NotificationBar(self.vlSearchEntity)
        
        #Set the results treeview to accept requests for context menus
        self.tvSTRResults.setContextMenuPolicy(Qt.CustomContextMenu)
        self.connect(self.tvSTRResults,SIGNAL("customContextMenuRequested(const QPoint&)"),
                     self.onResultsContextMenuRequested)
                
        #Load async for the current widget
        self.entityTabIndexChanged(0)
        
    def loadEntityConfig(self):
        '''
        Specify the entity configurations.
        '''
        #Person configuration
        personCfg = EntityConfiguration()
        personCfg.Title = str(QApplication.translate("ViewSTR", "Person"))
        personCfg.filterColumns["firstname"] = str(QApplication.translate("ViewSTR", "First Name"))
        personCfg.filterColumns["lastname"] = str(QApplication.translate("ViewSTR", "Last Name"))
        personCfg.filterColumns["identification_number"] = str(QApplication.translate("ViewSTR", "Identification Number"))
        personCfg.STRModel = Person
        personWidget = self.setEntityConfigWidget(personCfg)
        personWidget.setNodeFormatter(PersonNodeFormatter(self.tvSTRResults,self))
        
        #Property configuration
        propertyCfg = EntityConfiguration()
        propertyCfg.Title = str(QApplication.translate("ViewSTR", "Property"))
        propertyCfg.filterColumns["PropertyID"] = str(QApplication.translate("ViewSTR", "Property Identifier"))
        propertyCfg.STRModel = Property
        self.setEntityConfigWidget(propertyCfg)
    
    def setEntityConfigWidget(self,config):
        '''
        Set an entity configuration option and add it to the 'Search Entity' tab.
        '''
        entityWidg = STRViewEntityWidget(config)
        self.connect(entityWidg, SIGNAL("asyncStarted()"),self._progressStart)
        self.connect(entityWidg, SIGNAL("asyncFinished()"),self._progressFinish)
        tabIndex = self.tbSTREntity.addTab(entityWidg, config.Title)
        
        return entityWidg
        
    def entityTabIndexChanged(self,index):
        '''
        Raised when the tab index of the entity search tab widget changes.
        '''
        #Get the current widget in the tab container
        entityWidget = self.tbSTREntity.currentWidget()
        if isinstance(entityWidget,EntitySearchItem):
            entityWidget.loadAsync()
            
    def searchEntityRelations(self):
        '''
        Slot that searches for matching items for the specified entity and corresponding STR entities.
        '''
        self._resetTreeView()
        
        entityWidget = self.tbSTREntity.currentWidget()
        if isinstance(entityWidget,EntitySearchItem):
            valid,msg = entityWidget.validate()
            
            if not valid:
                self.notifSearchConfig.clear()
                self.notifSearchConfig.insertErrorNotification(msg)
                return
            
            formattedNode,results,searchWord = entityWidget.executeSearch()
            
            #Show error message 
            if len(results) == 0:
                noResultsMsg = QApplication.translate("ViewSTR", "No results found for '" + searchWord + "'")
                self.notifSearchConfig.clear()
                self.notifSearchConfig.insertErrorNotification(noResultsMsg)
                return
            
            if formattedNode is not None:
                self._loadRootNodeinTree(formattedNode)
                
    def clearSearch(self):
        '''
        Clear search input parameters (for current widget) and results.
        '''
        entityWidget = self.tbSTREntity.currentWidget()
        if isinstance(entityWidget,EntitySearchItem):
            entityWidget.reset()
            
        #Clear tree view
        self._resetTreeView()
        
        #Clear document listings
        self._deleteSourceDocTabs()
        
    def onSelectResults(self,selected,deselected):
        '''
        Slot which is raised when the selection is changed in the tree view 
        selection model.
        '''
        selIndexes = selected.indexes()
        
        #Check type of node and perform corresponding action
        for mi in selIndexes:
            if mi.isValid():
                node = mi.internalPointer()
                #Assert if node representing another entity has been clicked
                self._onNodeReferenceChanged(node.rootHash())
                if isinstance(node,STRNode):
                    srcDocs = node.sourceDocuments()
                    strId = node.id()
                    if strId != self._strID:
                        self._strID = strId
                        self._loadSourceDocuments(srcDocs)
                    break
                
    def onSourceDocumentRemoved(self,containerid):
        '''
        Slot raised when a source document is removed from the container.
        If there are no documents in the specified container then remove 
        the tab.
        '''
        for i in range(self.tbSupportingDocs.count()):
            docwidget = self.tbSupportingDocs.widget(i)
            if docwidget.containerId() == containerid:
                docCount = docwidget.container().count()
                if docCount == 0:
                    self.tbSupportingDocs.removeTab(i)
                    del docwidget
                    break
                
    def removeSourceDocumentWidget(self,containerid):
        '''
        Convenience method that removes the tab widget that lists the source documents
        with the given container id.
        '''
        for i in range(self.tbSupportingDocs.count()):
            docwidget = self.tbSupportingDocs.widget(i)
            if docwidget.containerId() == containerid:
                self.tbSupportingDocs.removeTab(i)
                self._sourceDocManager.removeContainer(containerid)
                del docwidget
                break
                
    def onTreeViewItemExpanded(self,modelindex):
        '''
        Raised when a tree view item is expanded.
        Reset the document listing and map view if the hash
        of the parent node is different.
        '''
        if modelindex.isValid():
            node = modelindex.internalPointer()
            #Assert if node representing another entity has been clicked
            self._onNodeReferenceChanged(node.rootHash())
    
    def onResultsContextMenuRequested(self,pnt):
        '''
        Slot raised when the user right-clicks on a node item to request the
        corresponding context menu.
        '''
        #Get the model index at the specified point
        mi = self.tvSTRResults.indexAt(pnt)
        if mi.isValid():
            node = mi.internalPointer()
            rMenu = QMenu(self)
            #Load node actions items into the context menu
            node.manageActions(mi,rMenu)
            rMenu.exec_(QCursor.pos())
    
    def _deleteSourceDocTabs(self):
        '''
        Removes all source document tabs and deletes their references.
        '''
        tabCount = self.tbSupportingDocs.count()
        
        while tabCount != 0:
            srcDocWidget = self.tbSupportingDocs.widget(tabCount-1)
            self.tbSupportingDocs.removeTab(tabCount-1)
            del srcDocWidget
            tabCount -= 1
            
        self._strID = None
        self._sourceDocManager.reset()
            
    def _resetTreeView(self):
        '''
        Clears the results tree view.
        '''
        #Reset tree view
        strModel = self.tvSTRResults.model()
        resultsSelModel = self.tvSTRResults.selectionModel()
        
        if strModel:
            strModel.clear()
            
        if resultsSelModel:
            self.disconnect(resultsSelModel, SIGNAL("selectionChanged(const QItemSelection&,const QItemSelection&)"),
                                     self.onSelectResults)
           
    def _loadRootNodeinTree(self,root):
        '''
        Load the search results (formatted into an object of type 'stdm.navigaion.STR') into
        the tree view.
        '''
        strTreeViewModel = STRTreeViewModel(root,view = self.tvSTRResults)
        self.tvSTRResults.setModel(strTreeViewModel)
        # Resize tree columns to fit contents
        self._resizeTreeColumns()
        
        #Capture selection changes signals when results are returned in the tree view
        resultsSelModel = self.tvSTRResults.selectionModel()
        self.connect(resultsSelModel, SIGNAL("selectionChanged(const QItemSelection&,const QItemSelection&)"),
                     self.onSelectResults)
        
    def _resizeTreeColumns(self):
        '''
        Adjusts the column sizes to fit its contents
        '''
        qModel = self.tvSTRResults.model()
        columnCount = qModel.columnCount()
        
        for i in range(columnCount):
            self.tvSTRResults.resizeColumnToContents(i)
            
        #Once resized then slightly increase the width of the first column so that text for 'No STR Defined' visible.
        currColWidth = self.tvSTRResults.columnWidth(0)
        newColWidth = currColWidth + 100
        self.tvSTRResults.setColumnWidth(0,newColWidth)
        
    def _loadSourceDocuments(self,sourcedocs):
        '''
        Load source documents into document listing widget.
        '''
        #Check the 
        #Configure progress dialog
        progressMsg = QApplication.translate("ViewSTR", "Loading supporting documents...")
        progressDialog = QProgressDialog(progressMsg,QString(),0,len(sourcedocs),self)
        progressDialog.setWindowModality(Qt.WindowModal)
        
        for i,doc in enumerate(sourcedocs):
            progressDialog.setValue(i)
            typeId = doc.DocumentType
            container = self._sourceDocManager.container(typeId)
            
            #Check if a container has been defined and create if none is found
            if container is None:
                srcDocWidget = SourceDocumentContainerWidget(typeId)
                container = srcDocWidget.container()
                self._sourceDocManager.registerContainer(container, typeId)
                #Add widget to tab container for source documents
                self.tbSupportingDocs.addTab(srcDocWidget, docTypeMapping[typeId])
                
            self._sourceDocManager.InsertDocFromModel(doc, typeId)
                
        progressDialog.setValue(len(sourcedocs))
        
    def _onNodeReferenceChanged(self,rootHash):
        '''
        Method for resetting document listing and map preview if another root node and its children
        are selected then the documents are reset as well as the map preview control.
        '''
        if rootHash != self._currRootNodeHash:
            self._deleteSourceDocTabs()
            self._currRootNodeHash = rootHash
    
    def _progressStart(self):
        '''
        Load progress dialog window.
        For items whose durations is unknown, 'isindefinite' = True by default.
        If 'isindefinite' is False, then 'rangeitems' has to be specified.
        '''
        pass
    
    def _progressFinish(self):
        '''
        Hide progress dialog window.
        '''
        pass
    
    def _getEditPermissions(self):
        '''
        Returns True/False whether the current logged in user has permissions to create new social tenure relationships.
        If true, then the system assumes that they can also edit STR records.
        '''
        canEdit = False
        userName = stdm.data.app_dbconn.User.UserName
        authorizer = Authorizer(userName)
        newSTRCode = "9576A88D-C434-40A6-A318-F830216CA15A"
        
        #Get the name of the content from the code
        cnt = Content()
        createSTRCnt = cnt.queryObject().filter(Content.code == newSTRCode).first()
        if createSTRCnt:
            name = createSTRCnt.name
            canEdit = authorizer.CheckAccess(name)
        
        return canEdit
コード例 #26
0
ファイル: new_str_wiz.py プロジェクト: olivierdalang/stdm
class newSTRWiz(QWizard, Ui_frmNewSTR):
    '''
    This class handles the listing of locality information
    '''
    def __init__(self,plugin):
        QWizard.__init__(self,plugin.iface.mainWindow())
        self.setupUi(self)
        
        #STR Variables
        self.selPerson = None
        self.selProperty = None
        self.enjoymentRight = None
        self.conflict = None
        
        #Initialize GUI wizard pages
        self.mapping=DeclareMapping.instance()
        self.initPerson()
        
        self.initProperty()
        
        self.initSTRType()
       
        self.init_document_type()
        
        self.initSourceDocument()
        
        #self.initConflict()
        
        #Connect signal when the finish button is clicked
        btnFinish = self.button(QWizard.FinishButton)
        
    def initPerson(self):
        '''
        Initialize person config
        '''
        self.notifPerson = NotificationBar(self.vlPersonNotif)
        
        self._initPersonFilter()
        
        #Initialize person worker thread for fetching person objects
        self.personWorker = PersonWorker(self)
        self.connect(self.personWorker, SIGNAL("retrieved(PyQt_PyObject)"),self._loadPersonInfo)
        
        #Init summary tree loaders
        self.personTreeLoader = TreeSummaryLoader(self.tvPersonInfo,QApplication.translate("newSTRWiz","Party Information"))
                
        #Connect signals
        QObject.connect(self.cboPersonFilterCols, SIGNAL("currentIndexChanged(int)"),self._updatePersonCompleter)
        
        #QObject.connect(self.cboPersonFilterCols, SIGNAL("currentIndexChanged(int)"),self.dataReceieved)
        
        #Start background thread
        self.personWorker.start()
        
    def initProperty(self):
        '''
        Initialize property config
        '''
        self.notifProp = NotificationBar(self.vlPropNotif)
        self.gpOLTitle = self.gpOpenLayers.title()
        
        #Flag for checking whether OpenLayers basemaps have been loaded
        self.olLoaded = False
        
        #Initialize lookup for properties
        propertyWorker = PropertyWorker(self)
        self.connect(propertyWorker, SIGNAL("retrieved(PyQt_PyObject)"), self._onPropertiesLoaded)
        
        #Connect signals
        QObject.connect(self.gpOpenLayers, SIGNAL("toggled(bool)"), self._onEnableOLGroupbox)             
        QObject.connect(self.zoomSlider, SIGNAL("sliderReleased()"), self._onZoomChanged)
        QObject.connect(self.btnResetMap , SIGNAL("clicked()"), self._onResetMap)
        
        #Start background thread
        propertyWorker.start()   
        
        self.propBrowser = WebSpatialLoader(self.propWebView,self)
        self.connect(self.propBrowser,SIGNAL("loadError(QString)"),self._onPropertyBrowserError)
        self.connect(self.propBrowser,SIGNAL("loadProgress(int)"),self._onPropertyBrowserLoading)
        self.connect(self.propBrowser,SIGNAL("loadFinished(bool)"),self._onPropertyBrowserFinished)
        self.connect(self.propBrowser,SIGNAL("zoomChanged(int)"),self.onMapZoomLevelChanged)
            
        #Connect signals
        QObject.connect(self.rbGMaps, SIGNAL("toggled(bool)"),self.onLoadGMaps)
        QObject.connect(self.rbOSM, SIGNAL("toggled(bool)"),self.onLoadOSM)                               
            
    def initializePage(self,id):
        '''
        Initialize summary page based on user selections.
        '''
        if id == 5:
            self.buildSummary()
            
    def initSTRType(self):
        '''
        Initialize 'Social Tenure Relationship' GUI controls
        '''
        # pty=Table('check_social_tenure_type',Base.metadata,autoload=True,autoload_with=STDMDb.instance().engine)
        # session=STDMDb.instance().session
        person = self.mapping.tableMapping('check_social_tenure_type')
        Person = person()
        strTypeFormatter =Person.queryObject().all()
        strType=[ids.value for ids in strTypeFormatter]
        strType.insert(0, " ")
        self.cboSTRType.insertItems(0,strType)

        self.cboSTRType.setCurrentIndex(-1)
        
        self.notifSTR = NotificationBar(self.vlSTRTypeNotif)
        
        #Register STR selection field
        self.frmWizSTRType.registerField("STR_Type",self.cboSTRType)
    
    def init_document_type(self):
        '''
        Initialize 'Right of Enjoyment' GUI controls
        '''
        doc_type_model = self.mapping.tableMapping('check_document_type')
        Docs = doc_type_model()
        doc_type_list = Docs.queryObject().all()
        doc_types = [doc.value for doc in doc_type_list]
        doc_types.insert(0," ")
        self.cboDocType.insertItems(0,doc_types)
        self.cboDocType.setCurrentIndex(-1)

        self.vlSourceDocNotif = NotificationBar(self.vlSourceDocNotif)
        
    def initSourceDocument(self):
        '''
        Initialize source document page
        '''
        #Set currency regular expression and currency prefix
        rx = QRegExp("^\\d{1,12}(([.]\\d{2})*),(\\d{2})$")
        rxValidator = QRegExpValidator(rx,self)
        '''
        '''
        self.notifSourceDoc = NotificationBar(self.vlSourceDocNotif)
        
        #Set source document manager
        self.sourceDocManager = SourceDocumentManager()
        #self.privateTaxDocManager = SourceDocumentManager()
        #self.stateTaxDocManager = SourceDocumentManager()
        self.sourceDocManager.registerContainer(self.vlDocTitleDeed, DEFAULT_DOCUMENT)
               
        '''
        #Connect signals

        '''
        self.connect(self.btnAddTitleDeed, SIGNAL("clicked()"),self.onUploadTitleDeed)
        
        
    def initConflict(self):
        '''
        Initialize 'Conflict' GUI controls
        '''
        #loadComboSelections(self.cboConflictOccurrence, CheckConflictState) 
        
        self.notifConflict = NotificationBar(self.vlConflictNotif,3000)
        
    def buildSummary(self):
        '''
        Display summary information.
        '''
        personMapping = self._mapPersonAttributes(self.selPerson)
        propertyMapping = self._mapPropertyAttributes(self.selProperty)
        STRMapping = self._mapSTRTypeSelection()
        
        #Load summary information in the tree view
        summaryTreeLoader = TreeSummaryLoader(self.twSTRSummary)
        summaryTreeLoader.addCollection(personMapping, QApplication.translate("newSTRWiz","Party Information"),
                                             ":/plugins/stdm/images/icons/user.png")    
        
        summaryTreeLoader.addCollection(propertyMapping, QApplication.translate("newSTRWiz","Spatial Unit Information"),
                                             ":/plugins/stdm/images/icons/property.png")
                                             
        summaryTreeLoader.addCollection(STRMapping, QApplication.translate("newSTRWiz","Social Tenure Relationship Information"), 
                                             ":/plugins/stdm/images/icons/social_tenure.png")    

        #Check the source documents based on the type of property
        srcDocMapping = self.sourceDocManager.attributeMapping()

        summaryTreeLoader.addCollection(srcDocMapping, QApplication.translate("newSTRWiz","Source Documents"), 
                                             ":/plugins/stdm/images/icons/attachment.png") 
      
        summaryTreeLoader.display()  
    
    def validateCurrentPage(self):
        '''
        Validate the current page before proceeding to the next one
        '''
        isValid = True
        currPageIndex = self.currentId()       
        
        #Validate person information
        if currPageIndex == 1:
            if self.selPerson == None:
                msg = QApplication.translate("newSTRWiz", 
                                             "Please choose a person for whom you are defining the social tenure relationship for.")
                self.notifPerson.clear()
                self.notifPerson.insertNotification(msg, ERROR)
                isValid = False
        
        #Validate property information
        if currPageIndex == 2:
            if self.selProperty == None:
                    msg = QApplication.translate("newSTRWiz", 
                                                 "Please specify the property to reference. Use the filter capability below.")
                    self.notifProp.clear()
                    self.notifProp.insertNotification(msg, ERROR)
                    isValid = False
        
        #Validate STR   
        if currPageIndex == 3:
            #Get current selected index
            currIndex = self.cboSTRType.currentIndex()
            if currIndex ==-1:
                msg = QApplication.translate("newSTRWiz", 
                                                 "Please specify the social tenure relationship type.")     
                self.notifSTR.clear()
                self.notifSTR.insertErrorNotification(msg)
                isValid = False

        #Validate source document    
        if currPageIndex == 4:
            currIndex = self.cboDocType.currentIndex()
            if currIndex ==-1:
                msg = QApplication.translate("newSTRWiz",
                                                 "Please select document type from the list")
                self.notifSourceDoc.clear()
                self.notifSourceDoc.insertErrorNotification(msg)

        if currPageIndex == 5:
            isValid = self.onCreateSTR()
        return isValid
    
    def onCreateSTR(self):
        '''
        Slot raised when the user clicks on Finish button in order to create a new STR entry.
        '''
        isValid = True
        
        #Create a progress dialog
        progDialog = QProgressDialog(self)
        progDialog.setWindowTitle(QApplication.translate("newSTRWiz", "Creating New STR"))
        progDialog.setRange(0,7)
        progDialog.show()
        
        
        socialTenureRel=self.mapping.tableMapping('social_tenure_relationship')
        str_relation_table =self.mapping.tableMapping('str_relations')
        STR_relation = str_relation_table()
        try:
            progDialog.setValue(1)
            socialTenure = socialTenureRel()
            socialTenure.party = self.selPerson.id
            progDialog.setValue(2)
            socialTenure.spatial_unit = self.selProperty.id
            progDialog.setValue(3)

            socialTenure.social_tenure_type=str(self.cboSTRType.currentText())
            progDialog.setValue(6)
            """
            Save new STR relations and supporting documentation
            """
            socialTenure.save()
            model_objs = self.sourceDocManager.model_objects()
            if model_objs is not None:
                if len(model_objs)>0:
                    for model_obj in model_objs:
                        model_obj.save()
                        STR_relation.social_tenure_id = socialTenure.id
                        STR_relation.source_doc_id = model_obj.id
                        STR_relation.save()
            progDialog.setValue(7)
            #source_doc_model = self.sourceDocManager.sourceDocuments(dtype ="TITLE DEED")

            #strPerson = "%s %s"%(str(self.selPerson.family_name),str(self.selPerson.other_names))
            strMsg = str(QApplication.translate("newSTRWiz",
                                            "The social tenure relationship for has been successfully created!"))
            QMessageBox.information(self, QApplication.translate("newSTRWiz", "STR Creation"),strMsg)

        except sqlalchemy.exc.OperationalError as oe:
            errMsg = oe.message
            QMessageBox.critical(self, QApplication.translate("newSTRWiz", "Unexpected Error"),errMsg)
            progDialog.hide()
            isValid = False

        except sqlalchemy.exc.IntegrityError as ie:
            errMsg = ie.message
            QMessageBox.critical(self, QApplication.translate("newSTRWiz", "Dublicate Relationship Error"),errMsg)
            progDialog.hide()
            isValid = False

        except Exception as e:
            errMsg = str(e)
            QMessageBox.critical(self, QApplication.translate("newSTRWiz", "Unexpected Error"),errMsg)

            isValid = False
        finally:
            STDMDb.instance().session.rollback()
            progDialog.hide()
        return isValid
            
    def _loadPersonInfo(self,persons):
        '''
        Load person objects
        '''
        self.persons = persons 
        self._updatePersonCompleter(0)
        
    def _onPropertiesLoaded(self,propids):
        '''
        Slot raised once the property worker has finished retrieving the property IDs.
        Creates a completer and populates it with the property IDs.
        '''
        #Get the items in a tuple and put them in a list
        
        propertyIds = [str(pid[0]) for pid in propids]
       
        #Configure completer   
        propCompleter = QCompleter(propertyIds,self)         
        propCompleter.setCaseSensitivity(Qt.CaseInsensitive)
        propCompleter.setCompletionMode(QCompleter.PopupCompletion)
        self.txtPropID.setCompleter(propCompleter)  
        
        #Connect 'activated' slot for the completer to load property information
        self.connect(propCompleter, SIGNAL("activated(const QString&)"),self._updatePropertySummary)      
        
    def _onPropertyBrowserError(self,err):
        '''
        Slot raised when an error occurs when loading items in the property browser
        '''
        self.notifProp.clear()
        self.notifProp.insertNotification(err, ERROR)
        
    def _onPropertyBrowserLoading(self,progress):
        '''
        Slot raised when the property browser is loading.
        Displays the progress of the page loading as a percentage.
        '''
        if progress <= 0 or progress >= 100:
            self.gpOpenLayers.setTitle(self.gpOLTitle)
        else:
            self.gpOpenLayers.setTitle("%s (Loading...%s%%)"%(str(self.gpOLTitle),str(progress)))
            
    def _onPropertyBrowserFinished(self,status):
        '''
        Slot raised when the property browser finishes loading the content
        '''
        if status:
            self.olLoaded = True
            self.overlayProperty()
        else:
            self.notifProp.clear()
            msg = QApplication.translate("newSTRWiz", "Error - The property map cannot be loaded.")   
            self.notifProp.insertErrorNotification(msg)
        
    def _onEnableOLGroupbox(self,state):
        '''
        Slot raised when a user chooses to select the group box for enabling/disabling to view
        the property in OpenLayers.
        '''
        if state:
            if self.selProperty is None:
                self.notifProp.clear()
                msg = QApplication.translate("newSTRWiz", "You need to specify a property in order to be able to preview it.")   
                self.notifProp.insertWarningNotification(msg)                
                self.gpOpenLayers.setChecked(False)
                return  
            
            #Load property overlay
            if not self.olLoaded:                
                self.propBrowser.load()            
                   
        else:
            #Remove overlay
            self.propBrowser.removeOverlay()     
            
    def _onZoomChanged(self):
        '''
        Slot raised when the zoom value in the slider changes.
        This is only raised once the user releases the slider with the mouse.
        '''
        zoom = self.zoomSlider.value()        
        self.propBrowser.zoom_to_level(zoom)
            
    def _initPersonFilter(self):
        '''
        Initializes person filter settings
        '''

        cols=table_searchable_cols('party')
        if len(cols)>0:
            for col in cols:
                self.cboPersonFilterCols.addItem(str(QApplication.translate("newSTRWiz",col.replace('_',' ').title())), col)
        
    def _updatePersonCompleter(self,index):
        '''
        Updates the person completer based on the person attribute item that the user has selected
        '''
        #Clear dependent controls
        #self.txtFilterPattern.clear()
        self.cboFilterPattern.clear()
        self.tvPersonInfo.clear()
        try:
            field_name = self.cboPersonFilterCols.currentText().replace(" ","_").lower()
            data_list =[getattr(array,field_name) for array in self.persons if getattr(array,field_name)!=None]
            model =QCompleter(data_list)
            model.setCompletionMode(QCompleter.PopupCompletion)
            model.setCaseSensitivity(Qt.CaseInsensitive)
            self.cboFilterPattern.setCompleter(model)
            self.cboFilterPattern.showPopup()
        except Exception as ex:
            msg =ex.message
            QMessageBox.critical(self,QApplication.translate("SocialTenureRelationship", u"Error Loading values"),
                                 QApplication.translate("SocialTenureRelationship",
                                 u"The was an error in sorting the data with the given column, try another %s"%msg))
            return
        self.currPersonAttr = str(self.cboPersonFilterCols.itemData(index))            
        
        #Create standard model which will always contain the id of the person row then the attribute for use in the completer
        self.cboFilterPattern.addItem("")
        for p in self.persons:
            pVal = getattr(p,self.currPersonAttr)
            if pVal != "" or pVal != None:
                self.cboFilterPattern.addItem(pVal,p.id)

        self.cboFilterPattern.activated.connect(self._updatePersonSummary)
         #self.connect(self.cboFilterPattern, SIGNAL("currentIndexChanged(int)"),self._updatePersonSummary)
                
    def _updatePersonSummary(self,index):
        '''
        Slot for updating the person information into the tree widget based on the user-selected value
        '''
        Person=self.mapping.tableMapping('party')
        person=Person()
        #Get the id from the model then the value of the ID model index



        index =self.cboFilterPattern.currentIndex()
        personId = self.cboFilterPattern.itemData(index)
        #QMessageBox.information(None,'index',str(data))
        # personId = pData
        if personId is not None:
        #Get person info
            p = person.queryObject().filter(Person.id == str(personId)).first()
            if p:
                self.selPerson = p
                personInfoMapping = self._mapPersonAttributes(p)
                personTreeLoader = TreeSummaryLoader(self.tvPersonInfo)
                personTreeLoader.addCollection(personInfoMapping, QApplication.translate("newSTRWiz","Party Information"),
                                               ":/plugins/stdm/images/icons/user.png")
                personTreeLoader.display()
            
    def _mapPersonAttributes(self,person):
        '''
        Maps the attributes of a person to a more friendly user representation 
        '''   
        #Setup formatters        
        pmapper=self.mapping.tableMapping('party')
        colMapping = pmapper.displayMapping()
        colMapping.pop('id')
        pMapping=OrderedDict()
        try:
            for attrib,label in colMapping.iteritems():
                pMapping[label] = getattr(person,attrib)
        except:
            pass
#                             
        return pMapping  
    
    def _updatePropertySummary(self,propid):
        '''
        Update the summary information for the selected property
        '''
        property = self.mapping.tableMapping('spatial_unit')
        Property =property()
        #propty=Table('spatial_unit',Base.metadata,autoload=True,autoload_with=STDMDb.instance().engine)
        #session=STDMDb.instance().session
        prop =Property.queryObject().filter(property.code == unicode(propid)).first()
        if prop:
            propMapping = self._mapPropertyAttributes(prop)
            
            #Load information in the tree view
            propertyTreeLoader = TreeSummaryLoader(self.tvPropInfo)
            propertyTreeLoader.addCollection(propMapping, QApplication.translate("newSTRWiz","Spatial Unit Information"),
                                             ":/plugins/stdm/images/icons/property.png")       
            propertyTreeLoader.display()  
            
            self.selProperty = prop
            
            #Show property in OpenLayers
            if self.gpOpenLayers.isChecked():
                if self.olLoaded:
                    self.overlayProperty()                      
    
    def _mapPropertyAttributes(self,prop):
            #Configure formatters
            spMapper = self.mapping.tableMapping('spatial_unit')
            colMapping = spMapper.displayMapping()
            colMapping.pop('id')
            propMapping=OrderedDict()
            for attrib,label in colMapping.iteritems():
                propMapping[label] = getattr(prop,attrib)
            return propMapping
        
    def _mapSTRTypeSelection(self):
        #strTypeFormatter = LookupFormatter(CheckSocialTenureRelationship)
        #self.cboSTRType.clear()
        
        strTypeSelection=self.cboSTRType.currentText()
        
        strMapping = OrderedDict()
        strMapping[str(QApplication.translate("newSTRWiz","STR Type"))] = str(strTypeSelection)

        return strMapping
    
    def _mapEnjoyRightSelection(self,enjoyRight):
        deadAliveFormatter = LookupFormatter(CheckDeadAlive)
        inheritanceFormatter = LookupFormatter(CheckInheritanceType)
                
        enjoyRightMapping = OrderedDict()
        enjoyRightMapping[str(QApplication.translate("newSTRWiz","Inheritance From"))] = str(inheritanceFormatter.setDisplay(enjoyRight.InheritanceType).toString())
        enjoyRightMapping[str(QApplication.translate("newSTRWiz","State"))] = str(deadAliveFormatter.setDisplay(enjoyRight.State).toString())
        enjoyRightMapping[str(QApplication.translate("newSTRWiz","Receiving Date"))] = str(enjoyRight.ReceivingDate.year)
        
        return enjoyRightMapping
    
    def _mapPrivatePropertyTax(self):
        privateTaxMapping = OrderedDict()
        
        privateTaxMapping[str(QApplication.translate("newSTRWiz","CFPB Payment Year"))] = str(self.dtLastYearCFBP.date().toPyDate().year)
        
        taxDec = Decimal(str(self.txtCFBPAmount.text()))
        taxFormatted = moneyfmt(taxDec,curr = CURRENCY_CODE)
        privateTaxMapping[str(QApplication.translate("newSTRWiz","CFPB Amount"))] = taxFormatted
        
        return privateTaxMapping
    
    def _mapStatePropertyTax(self):
        stateTaxMapping = OrderedDict()
        
        stateTaxMapping[str(QApplication.translate("newSTRWiz","Latest Receipt Date"))] = str(self.dtStateReceiptDate.date().toPyDate())
        
        taxDec = Decimal(str(self.txtStateReceiptAmount.text()))
        taxFormatted = moneyfmt(taxDec,curr = CURRENCY_CODE)
        stateTaxMapping[str(QApplication.translate("newSTRWiz","Amount"))] = taxFormatted
        stateTaxMapping[str(QApplication.translate("newSTRWiz","Lease Starting Year"))] = str(self.dtStateLeaseYear.date().toPyDate().year)
        stateTaxMapping[str(QApplication.translate("newSTRWiz","Tax Office"))] = str(self.txtStateTaxOffice.text())
        
        return stateTaxMapping
    
    def _mapConflict(self,conflict):
        conflictFormatter = LookupFormatter(CheckConflictState)
        conflictMapping = OrderedDict()
        
        if conflict == None:
            return conflictMapping
        
        conflictMapping[str(QApplication.translate("newSTRWiz","Status"))] = str(conflictFormatter.setDisplay(conflict.StateID).toString())
        
        if conflict.Description:
            conflictMapping[str(QApplication.translate("newSTRWiz","Description"))] = conflict.Description
            
        if conflict.Solution:
            conflictMapping[str(QApplication.translate("newSTRWiz","Solution"))] = conflict.Solution
         
        return conflictMapping
    
    def onLoadGMaps(self,state):
        '''
        Slot raised when a user clicks to set Google Maps Satellite
        as the base layer
        '''
        if state:                     
            self.propBrowser.setBaseLayer(GMAP_SATELLITE)
        
    def onLoadOSM(self,state):
        '''
        Slot raised when a user clicks to set OSM as the base layer
        '''
        if state:                     
            self.propBrowser.setBaseLayer(OSM)
            
    def onMapZoomLevelChanged(self,level):
        '''
        Slot which is raised when the zoom level of the map changes.
        '''
        self.zoomSlider.setValue(level)
       
    def _onResetMap(self):
        '''
        Slot raised when the user clicks to reset the property
        location in the map.
        '''
        self.propBrowser.zoom_to_extents()
       
    def overlayProperty(self):
        '''
        Overlay property boundaries on the basemap imagery
        '''                    
        self.propBrowser.add_overlay(self.selProperty,'geom_polygon')
        
    def validateEnjoymentRight(self): 
        '''
        Validate whether the user has specified all the required information
        '''
        self.notifEnjoyment.clear()
        
        if self.cboDeadAlive.currentIndex() == 0:
            msg = QApplication.translate("newSTRWiz", 
                                             "Please specify whether the person is 'Dead' or 'Alive'.")
            self.notifEnjoyment.insertErrorNotification(msg)
            return False
        
        if self.cboInheritanceType.currentIndex() == 0:
            msg = QApplication.translate("newSTRWiz", 
                                             "Please specify the Inheritance Type.")
            self.notifEnjoyment.insertErrorNotification(msg)
            return False
        
        #Set the right of enjoyment details if both inheritance type and state have been defined
        if self.cboInheritanceType.currentIndex() != 0 and self.cboDeadAlive.currentIndex() != 0:
            eRight = EnjoymentRight()
            #Set the properties
            setModelAttrFromCombo(eRight,"InheritanceType",self.cboInheritanceType)
            setModelAttrFromCombo(eRight,"State",self.cboDeadAlive)
            eRight.ReceivingDate = self.dtReceivingDate.date().toPyDate()
            
            self.enjoymentRight = eRight
            
            return True
        
    def validateSourceDocuments(self):
        '''
        Basically validates the entry of tax information.
        '''
        isValid = True
        
        if self.rbPrivateProperty.isChecked():
            if self.gpPrivateTaxInfo.isChecked():
                self.notifSourceDoc.clear()
                if str(self.txtCFBPAmount.text()) == "": 
                    self.txtCFBPAmount.setFocus()
                    msg1 = QApplication.translate("newSTRWiz", 
                                             "Please enter the tax amount.")
                    self.notifSourceDoc.insertErrorNotification(msg1)
                    isValid = False
                    
        elif self.rbStateland.isChecked():
            self.notifSourceDoc.clear()
            if str(self.txtStateReceiptAmount.text()) == "": 
                    self.txtStateReceiptAmount.setFocus()
                    msg2 = QApplication.translate("newSTRWiz", 
                                             "Please enter the tax amount.")
                    self.notifSourceDoc.insertErrorNotification(msg2)
                    isValid = False
            if str(self.txtStateTaxOffice.text()) == "": 
                    self.txtStateTaxOffice.setFocus()
                    msg3 = QApplication.translate("newSTRWiz", 
                                             "Please specify the tax office.")
                    self.notifSourceDoc.insertErrorNotification(msg3)
                    isValid = False
   
        return isValid
    
    def validateConflict(self): 
        '''
        Check if the user has selected that there is a conflict and validate whether the description 
        and solution have been specified.
        '''
        isValid = True
        
        nonConflict = QApplication.translate("Lookup","No Conflict")
        nonConflictIndex = self.cboConflictOccurrence.findText(nonConflict)
        conflictOccurrence = QApplication.translate("Lookup","Conflict Present")
        occIndex = self.cboConflictOccurrence.findText(conflictOccurrence)
        
        if self.cboConflictOccurrence.currentIndex() == occIndex:
            self.notifConflict.clear()
            if str(self.txtConflictDescription.toPlainText()) == "":
                msg1 = QApplication.translate("newSTRWiz", 
                                             "Please provide a brief description of the conflict.")
                self.notifConflict.insertErrorNotification(msg1)
                isValid = False
            if str(self.txtConflictSolution.toPlainText()) == "":
                msg2 = QApplication.translate("newSTRWiz", 
                                             "Please provide a proposed solution for the specified conflict.")
                self.notifConflict.insertErrorNotification(msg2)
                isValid = False
                
            if str(self.txtConflictSolution.toPlainText()) != "" and str(self.txtConflictDescription.toPlainText()) != "":
                self.conflict = Conflict()
                stateId,ok = self.cboConflictOccurrence.itemData(occIndex).toInt()
                self.conflict.StateID = stateId
                self.conflict.Description = str(self.txtConflictDescription.toPlainText())
                self.conflict.Solution = str(self.txtConflictSolution.toPlainText())
                
        #Set conflict object properties
        if self.cboConflictOccurrence.currentIndex() == nonConflictIndex:
            self.conflict = Conflict()
            stateId,ok = self.cboConflictOccurrence.itemData(nonConflictIndex).toInt()
            self.conflict.StateID = stateId
   
        return isValid
    
    def onSelectPrivateProperty(self,state):
        '''
        Slot raised when the user clicks to load source document page for private property
        '''
        if state:
            self.stkSrcDocList.setCurrentIndex(0)
        
    def onSelectStateland(self,state):
        '''
        Slot raised when the user clicks to load source document page for private property
        '''
        if state:
            self.stkSrcDocList.setCurrentIndex(1)
            
    def onUploadTitleDeed(self):
        '''
        Slot raised when the user clicks to upload a title deed
        '''
        titleStr = QApplication.translate("newSTRWiz", 
                                             "Specify the Document File Location")
        titles = self.selectSourceDocumentDialog(titleStr)
        
        for title in titles:
            self.sourceDocManager.insertDocumentFromFile(title,DEFAULT_DOCUMENT)
            
    def onUploadStatutoryRefPaper(self):
        '''
        Slot raised when the user clicks to upload a statutory reference paper
        '''
        statStr = QApplication.translate("newSTRWiz", 
                                             "Specify Statutory Reference Paper File Location")
        stats = self.selectSourceDocumentDialog(statStr)
        
        for stat in stats:
            self.sourceDocManager.insertDocumentFromFile(stat,STATUTORY_REF_PAPER)
            
    def onUploadSurveyorRef(self):
        '''
        Slot raised when the user clicks to upload a surveyor reference
        '''
        surveyorStr = QApplication.translate("newSTRWiz", 
                                             "Specify Surveyor Reference File Location")
        surveyorRefs = self.selectSourceDocumentDialog(surveyorStr)
        
        for surveyorRef in surveyorRefs:
            self.sourceDocManager.insertDocumentFromFile(surveyorRef,SURVEYOR_REF)
            
    def onUploadNotaryRef(self):
        '''
        Slot raised when the user clicks to upload a notary reference
        '''
        notaryStr = QApplication.translate("newSTRWiz", 
                                             "Specify Notary Reference File Location")
        notaryRefs = self.selectSourceDocumentDialog(notaryStr)
        
        for notaryRef in notaryRefs:
            self.sourceDocManager.insertDocumentFromFile(notaryRef,NOTARY_REF)
            
    def onUploadPrivateReceiptScan(self):
        '''
        Slot raised when the user clicks to upload a receipt scan for private property
        '''
        receiptScan = QApplication.translate("newSTRWiz", 
                                             "Specify Receipt Scan File Location")
        scan = self.selectReceiptScanDialog(receiptScan)
        
        if scan != "" or scan != None:
            #Ensure that there is only one tax receipt document before inserting
            self.validateReceiptScanInsertion(self.privateTaxDocManager, scan, TAX_RECEIPT_PRIVATE)
            
    def onUploadStateReceiptScan(self):
        '''
        Slot raised when the user clicks to upload a receipt scan for stateland
        '''
        receiptScan = QApplication.translate("newSTRWiz", 
                                             "Specify Receipt Scan File Location")
        scan = self.selectReceiptScanDialog(receiptScan)
        
        if scan != "" or scan != None:
            #Ensure that there is only one tax receipt document before inserting
            self.validateReceiptScanInsertion(self.stateTaxDocManager, scan, TAX_RECEIPT_STATE)
            
    def validateReceiptScanInsertion(self,documentmanager,scan,containerid):
        '''
        Checks and ensures that only one document exists in the specified container.
        '''
        container = documentmanager.container(containerid)
        if container.count() > 0:
            msg = QApplication.translate("newSTRWiz", "Only one receipt scan can be uploaded.\nWould you like to replace " \
                                         "the existing one?")
            result = QMessageBox.warning(self,QApplication.translate("newSTRWiz","Replace Receipt Scan"),msg, QMessageBox.Yes|
                                         QMessageBox.No)
            if result == QMessageBox.Yes:
                docWidget = container.itemAt(0).widget()
                docWidget.removeDocument()
                documentmanager.insertDocumentFromFile(scan,containerid)
            else:
                return
        else:
            documentmanager.insertDocumentFromFile(scan,containerid)
        
    def selectSourceDocumentDialog(self,title):
        '''
        Displays a file dialog for a user to specify a source document
        '''
        files = QFileDialog.getOpenFileNames(self,title,"/home","Source Documents (*.*)")
        return files
    
    def selectReceiptScanDialog(self,title):
        '''
        Displays a file dialog for a user to specify a file location of a receipt scan
        '''
        file = QFileDialog.getOpenFileName(self,title,"/home","Tax Receipt Scan (*.pdf)")
        return file
        
    def uploadDocument(self,path,containerid):
        '''
        Upload source document
        '''
        self.sourceDocManager.insertDocumentFromFile(path, containerid)