Beispiel #1
0
    def __init__(self, parent=None, iface=None):
        QTabWidget.__init__(self, parent)
        self.setupUi(self)

        self._notif_bar = None
        self._ol_loaded = False
        self._overlay_layer = None
        self.sel_highlight = None
        self.memory_layer = None
        self._db_session = STDMDb.instance().session

        self.set_iface(iface)

        #Web config
        self._web_spatial_loader = WebSpatialLoader(self.spatial_web_view,
                                                    self)

        #Connect signals
        self._web_spatial_loader.loadError.connect(
            self.on_spatial_browser_error)
        self._web_spatial_loader.loadProgress.connect(
            self.on_spatial_browser_loading)
        self._web_spatial_loader.loadFinished.connect(
            self.on_spatial_browser_finished)
        self._web_spatial_loader.zoomChanged.connect(
            self.on_map_zoom_level_changed)
        self.rbGMaps.toggled.connect(self.on_load_GMaps)
        self.rbOSM.toggled.connect(self.on_load_OSM)
        self.zoomSlider.sliderReleased.connect(self.on_zoom_changed)
        self.btnResetMap.clicked.connect(self.on_reset_web_map)
        self.btnSync.clicked.connect(self.on_sync_extents)
        QgsMapLayerRegistry.instance().layersWillBeRemoved.connect(
            self._on_overlay_to_be_removed)
Beispiel #2
0
    def __init__(self, parent=None, iface=None):
        QTabWidget.__init__(self, parent)
        self.setupUi(self)

        self._notif_bar = None
        self._ol_loaded = False
        self._overlay_layer = None
        self.sel_highlight = None
        self.memory_layer = None
        self._db_session = STDMDb.instance().session

        self.set_iface(iface)

        #Web config
        self._web_spatial_loader = WebSpatialLoader(self.spatial_web_view, self)

        #Connect signals
        self._web_spatial_loader.loadError.connect(self.on_spatial_browser_error)
        self._web_spatial_loader.loadProgress.connect(self.on_spatial_browser_loading)
        self._web_spatial_loader.loadFinished.connect(self.on_spatial_browser_finished)
        self._web_spatial_loader.zoomChanged.connect(self.on_map_zoom_level_changed)
        self.rbGMaps.toggled.connect(self.on_load_GMaps)
        self.rbOSM.toggled.connect(self.on_load_OSM)
        self.zoomSlider.sliderReleased.connect(self.on_zoom_changed)
        self.btnResetMap.clicked.connect(self.on_reset_web_map)
        self.btnSync.clicked.connect(self.on_sync_extents)
        QgsMapLayerRegistry.instance().layersWillBeRemoved.connect(self._on_overlay_to_be_removed)
Beispiel #3
0
 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)                               
Beispiel #4
0
class SpatialPreview(QTabWidget, Ui_frmPropertyPreview):
    """
    Widget for previewing spatial unit on either local map or web source.
    """
    def __init__(self, parent=None, iface=None):
        QTabWidget.__init__(self, parent)
        self.setupUi(self)

        self._notif_bar = None
        self._ol_loaded = False
        self._overlay_layer = None
        self.sel_highlight = None
        self.memory_layer = None
        self._db_session = STDMDb.instance().session

        self.set_iface(iface)

        #Web config
        self._web_spatial_loader = WebSpatialLoader(self.spatial_web_view, self)

        #Connect signals
        self._web_spatial_loader.loadError.connect(self.on_spatial_browser_error)
        self._web_spatial_loader.loadProgress.connect(self.on_spatial_browser_loading)
        self._web_spatial_loader.loadFinished.connect(self.on_spatial_browser_finished)
        self._web_spatial_loader.zoomChanged.connect(self.on_map_zoom_level_changed)
        self.rbGMaps.toggled.connect(self.on_load_GMaps)
        self.rbOSM.toggled.connect(self.on_load_OSM)
        self.zoomSlider.sliderReleased.connect(self.on_zoom_changed)
        self.btnResetMap.clicked.connect(self.on_reset_web_map)
        self.btnSync.clicked.connect(self.on_sync_extents)
        QgsMapLayerRegistry.instance().layersWillBeRemoved.connect(self._on_overlay_to_be_removed)

    def set_iface(self, iface):
        self._iface = iface
        self.local_map.set_iface(iface)

    def set_notification_bar(self, notif_bar):
        """
        Set notification widget.
        :param notif_bar: Notification widget.
        """
        self._notif_bar = notif_bar

    def notification_bar(self):
        """
        :return: Currently configured notification bar.
        """
        return self._notif_bar

    def _insert_notification(self, msg, level, clear_first = True):
        if self._notif_bar is None:
            return

        if clear_first:
            self._notif_bar.clear()

        self._notif_bar.insertNotification(msg, level)

    def iface(self):
        return self._iface

    def _setDefaults(self):
        """
        Set default settings
        """
        self.set_canvas_background_color(self.canvasBgColor)

    def set_canvas_background_color(self,color):
        """
        Set the background color of the map canvas
        """
        self.localMap.setCanvasColor(color)
        self.canvasBgColor = color

    def refresh_canvas_layers(self, process_events=False):
        """
        Reload map layers in the viewer canvas.
        """
        self.local_map.refresh_layers()

    def load_web_map(self):
        """
        Loads the web map into the view using canvas extents if there
        are existing layers in the map canvas.
        """
        if not self._ol_loaded:
            self._web_spatial_loader.load()

    def _create_vector_layer(self, geom_type, prj_code):
        """
        Creates/resets the internal vector layer that will be used to draw
        the spatial unit overlays.
        :param geom_type: Geometry type
        :type geom_type: str
        :param prj_code: EPSG code
        :type prj_code: int
        """
        self._overlay_layer = QgsVectorLayer(
            u"{0}?crs=epsg:{1!s}&field=lbname:string(20)&index=yes".format(geom_type,
                                                                      prj_code),
            "view_str_spatial_unit",
            "memory")

    def draw_spatial_unit(self, spatial_unit, model):
        """
        Draw geometry of the given model in the respective local and web views.
        :param model: Source model whose geometry will be drawn.
        :type model: object
        :param clear_existing: Clears any existing features prior to adding the
        new features.
        :type clear_existing: bool
        """
        if model is None:
            msg = QApplication.translate("SpatialPreview",
                                         "Data model is empty, the spatial "
                                         "unit cannot be rendered.")
            QMessageBox.critical(self,
                                 QApplication.translate(
                                    "SpatialPreview",
                                    "Spatial Unit Preview"),
                                 msg)

            return

        table_name = spatial_unit.name
        if not pg_table_exists(table_name):
            msg = QApplication.translate("SpatialPreview",
                                         "The spatial unit data source could "
                                         "not be retrieved, the feature cannot "
                                         "be rendered.")
            QMessageBox.critical(
                self,
                QApplication.translate(
                    "SpatialPreview",
                    "Spatial Unit Preview"),
                msg
            )

            return

        sp_unit_manager = SpatialUnitManagerDockWidget(self.iface())
        spatial_cols = sp_unit_manager.geom_columns(spatial_unit)

        geom, geom_col = None, ""
        sc_obj = None
        for sc in spatial_cols:

            db_geom = getattr(model, sc.name)
            #Use the first non-empty geometry
            # value in the collection
            if not db_geom is None:
                sc_obj = sc
                geom_col = sc.name
                geom = db_geom
        QApplication.processEvents()

        lyr = sp_unit_manager.geom_col_layer_name(
            table_name, sc_obj
        )

        sp_unit_manager.add_layer_by_name(lyr)

        if geom is not None:

            self.highlight_spatial_unit(
                spatial_unit, geom, self.local_map.canvas
            )
            self._web_spatial_loader.add_overlay(
                model, geom_col
            )

    def clear_sel_highlight(self):
        """
        Removes sel_highlight from the canvas.
        :return:
        """
        if self.sel_highlight is not None:
            self.sel_highlight = None

    def get_layer_source(self, layer):
        """
        Get the layer table name if the source is from the database.
        :param layer: The layer for which the source is checked
        :type QGIS vectorlayer
        :return: String or None
        """
        source = layer.source()
        vals = dict(re.findall('(\S+)="?(.*?)"? ', source))
        try:
            table = vals['table'].split('.')
            table_name = table[1].strip('"')
            return table_name
        except KeyError:
            return None

    def spatial_unit_layer(self, spatial_unit, active_layer):
        """
        Check whether the layer is parcel layer or not.
        :param active_layer: The layer to be checked
        :type QGIS vectorlayer
        :return: Boolean
        """
        if self.active_layer_check():
            layers = self.iface().legendInterface().layers()

            for layer in layers:
                layer_source = self.get_layer_source(layer)
                if layer_source == spatial_unit.name:
                    self.iface().setActiveLayer(layer)
                    return True

            not_sp_msg = QApplication.translate(
                'SpatialPreview',
                'You have selected a non-spatial_unit layer. '
                'Please select a spatial unit layer to preview.'
            )
            QMessageBox.information(
                self._iface.mainWindow(),
                "Error",
                not_sp_msg
            )


    def active_layer_check(self):
        """
        Check if there is active layer and if not, displays
        a message box to select a parcel layer.
        :return:
        """
        active_layer = self._iface.activeLayer()
        if active_layer is None:
            no_layer_msg = QApplication.translate(
                'SpatialPreview',
                'Please add a spatial unit layer '
                'to preview the spatial unit.'
            )
            QMessageBox.critical(
                self._iface.mainWindow(),
                "Error",
                no_layer_msg
            )
            return False
        else:
            return True

    def _add_geom_to_map(self, geom):

        if self._overlay_layer is None:
            return

        geom_func = geom.ST_AsText()
        geom_wkt = self._db_session.scalar(geom_func)

        dp = self._overlay_layer.dataProvider()

        feat = QgsFeature()
        qgis_geom = QgsGeometry.fromWkt(geom_wkt)
        feat.setGeometry(g)
        dp.addFeatures([feat])

        self._overlay_layer.updateExtents()

        return qgis_geom.boundingBox()

    def highlight_spatial_unit(
            self, spatial_unit, geom, map_canvas
    ):
        layer = self._iface.activeLayer()
        map_canvas.setExtent(layer.extent())
        map_canvas.refresh()

        if self.spatial_unit_layer(spatial_unit, layer):

            self.clear_sel_highlight()

            qgis_geom = qgsgeometry_from_wkbelement(geom)

            self.sel_highlight = QgsHighlight(
                map_canvas, qgis_geom, layer
            )
            rgba = selection_color()
            self.sel_highlight.setFillColor(rgba)

            self.sel_highlight.setWidth(3)
            self.sel_highlight.show()

            extent = qgis_geom.boundingBox()
            extent.scale(1.5)
            map_canvas.setExtent(extent)
            map_canvas.refresh()
        else:
            return


    def remove_preview_layer(self, layer, name):
        """
        Removes the preview layer from legend.
        :param layer: The preview polygon layer to be removed.
        :param name: The name of the layer to be removed.
        :return: None
        """
        if layer is not None:
            for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
                if lyr.name() == name:
                    id = lyr.id()
                    QgsMapLayerRegistry.instance().removeMapLayer(id)


    def delete_local_features(self, feature_ids=[]):
        """
        Removes features in the local map overlay.
        """
        del_status = False

        if not self._overlay_layer is None:
            if len(feature_ids) == 0:
                feature_ids = self._overlay_layer.allFeatureIds()

            del_status = self._overlay_layer.dataProvider().deleteFeatures(feature_ids)

        return del_status

    def remove_layer(self):
        """
        Removes both the local and web layers.
        """
        if not self._overlay_layer is None:
            QgsProject.instance().layerTreeRoot().removeLayer(self._overlay_layer)

            #Clear web overlays
            self._web_spatial_loader.removeOverlay()

            self._overlay_layer = None

    def _on_overlay_to_be_removed(self, layers_ids):
        """
        Resets the local layer variable and removes the web overlay.
        """
        if not self._overlay_layer is None:
            if self._overlay_layer.id() in layers_ids:
                self.remove_layer()

    def on_spatial_browser_error(self, err):
        """
        Slot raised when an error occurs when loading items in the property browser
        """
        self._insert_notification(err, ERROR)

    def on_spatial_browser_loading(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.lblInfo.setText("")
            self.lblInfo.setVisible(False)

        else:
            self.lblInfo.setVisible(True)
            self.lblInfo.setText("Loading...%d%%)"%(progress))

    def on_spatial_browser_finished(self, status):
        """
        Slot raised when the property browser finishes loading the content
        """
        if status:
            if len(self.local_map.canvas_layers()) > 0:# and not self._ol_loaded:
                self.on_sync_extents()

            self._ol_loaded = True
            #self._overlay_spatial_unit()

        else:
            msg = QApplication.translate("SpatialPreview",
                                         "Error: Spatial unit cannot be loaded.")
            self._insert_notification(msg, ERROR)

    def on_zoom_changed(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._web_spatial_loader.zoom_to_level(zoom)

    def on_load_GMaps(self, state):
        """
        Slot raised when a user clicks to set Google Maps Satellite
        as the base layer
        """
        if state:
            self._web_spatial_loader.setBaseLayer(GMAP_SATELLITE)

    def on_load_OSM(self, state):
        """
        Slot raised when a user clicks to set OSM as the base layer
        """
        if state:
            self._web_spatial_loader.setBaseLayer(OSM)

    def on_map_zoom_level_changed(self, level):
        """
        Slot which is raised when the zoom level of the map changes.
        """
        self.zoomSlider.setValue(level)

    def on_reset_web_map(self):
        """
        Slot raised when the user clicks to reset the property
        location in the map.
        """
        self._web_spatial_loader.zoom_to_extents()

    def on_sync_extents(self):
        """
        Slot raised to synchronize the webview extents with those of the
        local map canvas.
        """
        if len(self.local_map.canvas_layers()) > 0:# and self._ol_loaded:
            curr_extent = self.map_extents()
            self._web_spatial_loader.zoom_to_map_extents(curr_extent)

    def map_extents(self):
        """
        :returns: Current extents of the local map.
        :rtype: QgsRectangle
        """
        return self.local_map.extent()

    def canvas_zoom_to_extent(self, extent):
        self.local_map.canvas.setExtent(extent)
Beispiel #5
0
class SpatialPreview(QTabWidget, Ui_frmPropertyPreview):
    """
    Widget for previewing spatial unit on either local map or web source.
    """
    def __init__(self, parent=None, iface=None):
        QTabWidget.__init__(self, parent)
        self.setupUi(self)

        self._notif_bar = None
        self._ol_loaded = False
        self._overlay_layer = None
        self.sel_highlight = None
        self.memory_layer = None
        self._db_session = STDMDb.instance().session

        self.set_iface(iface)

        #Web config
        self._web_spatial_loader = WebSpatialLoader(self.spatial_web_view,
                                                    self)

        #Connect signals
        self._web_spatial_loader.loadError.connect(
            self.on_spatial_browser_error)
        self._web_spatial_loader.loadProgress.connect(
            self.on_spatial_browser_loading)
        self._web_spatial_loader.loadFinished.connect(
            self.on_spatial_browser_finished)
        self._web_spatial_loader.zoomChanged.connect(
            self.on_map_zoom_level_changed)
        self.rbGMaps.toggled.connect(self.on_load_GMaps)
        self.rbOSM.toggled.connect(self.on_load_OSM)
        self.zoomSlider.sliderReleased.connect(self.on_zoom_changed)
        self.btnResetMap.clicked.connect(self.on_reset_web_map)
        self.btnSync.clicked.connect(self.on_sync_extents)
        QgsMapLayerRegistry.instance().layersWillBeRemoved.connect(
            self._on_overlay_to_be_removed)

    def set_iface(self, iface):
        self._iface = iface
        self.local_map.set_iface(iface)

    def set_notification_bar(self, notif_bar):
        """
        Set notification widget.
        :param notif_bar: Notification widget.
        """
        self._notif_bar = notif_bar

    def notification_bar(self):
        """
        :return: Currently configured notification bar.
        """
        return self._notif_bar

    def _insert_notification(self, msg, level, clear_first=True):
        if self._notif_bar is None:
            return

        if clear_first:
            self._notif_bar.clear()

        self._notif_bar.insertNotification(msg, level)

    def iface(self):
        return self._iface

    def _setDefaults(self):
        """
        Set default settings
        """
        self.set_canvas_background_color(self.canvasBgColor)

    def set_canvas_background_color(self, color):
        """
        Set the background color of the map canvas
        """
        self.localMap.setCanvasColor(color)
        self.canvasBgColor = color

    def refresh_canvas_layers(self, process_events=False):
        """
        Reload map layers in the viewer canvas.
        """
        self.local_map.refresh_layers()

    def load_web_map(self):
        """
        Loads the web map into the view using canvas extents if there
        are existing layers in the map canvas.
        """
        if not self._ol_loaded:
            self._web_spatial_loader.load()

    def _create_vector_layer(self, geom_type, prj_code):
        """
        Creates/resets the internal vector layer that will be used to draw
        the spatial unit overlays.
        :param geom_type: Geometry type
        :type geom_type: str
        :param prj_code: EPSG code
        :type prj_code: int
        """
        self._overlay_layer = QgsVectorLayer(
            u"{0}?crs=epsg:{1!s}&field=lbname:string(20)&index=yes".format(
                geom_type, prj_code), "view_str_spatial_unit", "memory")

    def draw_spatial_unit(self, spatial_unit, model):
        """
        Draw geometry of the given model in the respective local and web views.
        :param model: Source model whose geometry will be drawn.
        :type model: object
        :param clear_existing: Clears any existing features prior to adding the
        new features.
        :type clear_existing: bool
        """
        if model is None:
            msg = QApplication.translate(
                "SpatialPreview", "Data model is empty, the spatial "
                "unit cannot be rendered.")
            QMessageBox.critical(
                self,
                QApplication.translate("SpatialPreview",
                                       "Spatial Unit Preview"), msg)

            return

        table_name = spatial_unit.name
        if not pg_table_exists(table_name):
            msg = QApplication.translate(
                "SpatialPreview", "The spatial unit data source could "
                "not be retrieved, the feature cannot "
                "be rendered.")
            QMessageBox.critical(
                self,
                QApplication.translate("SpatialPreview",
                                       "Spatial Unit Preview"), msg)

            return

        sp_unit_manager = SpatialUnitManagerDockWidget(self.iface())
        spatial_cols = sp_unit_manager.geom_columns(spatial_unit)

        geom, geom_col = None, ""
        sc_obj = None
        for sc in spatial_cols:

            db_geom = getattr(model, sc.name)
            #Use the first non-empty geometry
            # value in the collection
            if not db_geom is None:
                sc_obj = sc
                geom_col = sc.name
                geom = db_geom
        QApplication.processEvents()

        lyr = sp_unit_manager.geom_col_layer_name(table_name, sc_obj)

        sp_unit_manager.add_layer_by_name(lyr)

        if geom is not None:

            self.highlight_spatial_unit(spatial_unit, geom,
                                        self.local_map.canvas)
            self._web_spatial_loader.add_overlay(model, geom_col)

    def clear_sel_highlight(self):
        """
        Removes sel_highlight from the canvas.
        :return:
        """
        if self.sel_highlight is not None:
            self.sel_highlight = None

    def get_layer_source(self, layer):
        """
        Get the layer table name if the source is from the database.
        :param layer: The layer for which the source is checked
        :type QGIS vectorlayer
        :return: String or None
        """
        source = layer.source()
        vals = dict(re.findall('(\S+)="?(.*?)"? ', source))
        try:
            table = vals['table'].split('.')
            table_name = table[1].strip('"')
            return table_name
        except KeyError:
            return None

    def spatial_unit_layer(self, spatial_unit, active_layer):
        """
        Check whether the layer is parcel layer or not.
        :param active_layer: The layer to be checked
        :type QGIS vectorlayer
        :return: Boolean
        """
        if self.active_layer_check():
            layers = self.iface().legendInterface().layers()

            for layer in layers:
                layer_source = self.get_layer_source(layer)
                if layer_source == spatial_unit.name:
                    self.iface().setActiveLayer(layer)
                    return True

            not_sp_msg = QApplication.translate(
                'SpatialPreview',
                'You have selected a non-spatial_unit layer. '
                'Please select a spatial unit layer to preview.')
            QMessageBox.information(self._iface.mainWindow(), "Error",
                                    not_sp_msg)

    def active_layer_check(self):
        """
        Check if there is active layer and if not, displays
        a message box to select a parcel layer.
        :return:
        """
        active_layer = self._iface.activeLayer()
        if active_layer is None:
            no_layer_msg = QApplication.translate(
                'SpatialPreview', 'Please add a spatial unit layer '
                'to preview the spatial unit.')
            QMessageBox.critical(self._iface.mainWindow(), "Error",
                                 no_layer_msg)
            return False
        else:
            return True

    def _add_geom_to_map(self, geom):

        if self._overlay_layer is None:
            return

        geom_func = geom.ST_AsText()
        geom_wkt = self._db_session.scalar(geom_func)

        dp = self._overlay_layer.dataProvider()

        feat = QgsFeature()
        qgis_geom = QgsGeometry.fromWkt(geom_wkt)
        feat.setGeometry(g)
        dp.addFeatures([feat])

        self._overlay_layer.updateExtents()

        return qgis_geom.boundingBox()

    def highlight_spatial_unit(self, spatial_unit, geom, map_canvas):
        layer = self._iface.activeLayer()
        map_canvas.setExtent(layer.extent())
        map_canvas.refresh()

        if self.spatial_unit_layer(spatial_unit, layer):

            self.clear_sel_highlight()

            qgis_geom = qgsgeometry_from_wkbelement(geom)

            self.sel_highlight = QgsHighlight(map_canvas, qgis_geom, layer)
            rgba = selection_color()
            self.sel_highlight.setFillColor(rgba)

            self.sel_highlight.setWidth(3)
            self.sel_highlight.show()

            extent = qgis_geom.boundingBox()
            extent.scale(1.5)
            map_canvas.setExtent(extent)
            map_canvas.refresh()
        else:
            return

    def remove_preview_layer(self, layer, name):
        """
        Removes the preview layer from legend.
        :param layer: The preview polygon layer to be removed.
        :param name: The name of the layer to be removed.
        :return: None
        """
        if layer is not None:
            for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
                if lyr.name() == name:
                    id = lyr.id()
                    QgsMapLayerRegistry.instance().removeMapLayer(id)

    def delete_local_features(self, feature_ids=[]):
        """
        Removes features in the local map overlay.
        """
        del_status = False

        if not self._overlay_layer is None:
            if len(feature_ids) == 0:
                feature_ids = self._overlay_layer.allFeatureIds()

            del_status = self._overlay_layer.dataProvider().deleteFeatures(
                feature_ids)

        return del_status

    def remove_layer(self):
        """
        Removes both the local and web layers.
        """
        if not self._overlay_layer is None:
            QgsProject.instance().layerTreeRoot().removeLayer(
                self._overlay_layer)

            #Clear web overlays
            self._web_spatial_loader.removeOverlay()

            self._overlay_layer = None

    def _on_overlay_to_be_removed(self, layers_ids):
        """
        Resets the local layer variable and removes the web overlay.
        """
        if not self._overlay_layer is None:
            if self._overlay_layer.id() in layers_ids:
                self.remove_layer()

    def on_spatial_browser_error(self, err):
        """
        Slot raised when an error occurs when loading items in the property browser
        """
        self._insert_notification(err, ERROR)

    def on_spatial_browser_loading(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.lblInfo.setText("")
            self.lblInfo.setVisible(False)

        else:
            self.lblInfo.setVisible(True)
            self.lblInfo.setText("Loading...%d%%)" % (progress))

    def on_spatial_browser_finished(self, status):
        """
        Slot raised when the property browser finishes loading the content
        """
        if status:
            if len(self.local_map.canvas_layers()
                   ) > 0:  # and not self._ol_loaded:
                self.on_sync_extents()

            self._ol_loaded = True
            #self._overlay_spatial_unit()

        else:
            msg = QApplication.translate(
                "SpatialPreview", "Error: Spatial unit cannot be loaded.")
            self._insert_notification(msg, ERROR)

    def on_zoom_changed(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._web_spatial_loader.zoom_to_level(zoom)

    def on_load_GMaps(self, state):
        """
        Slot raised when a user clicks to set Google Maps Satellite
        as the base layer
        """
        if state:
            self._web_spatial_loader.setBaseLayer(GMAP_SATELLITE)

    def on_load_OSM(self, state):
        """
        Slot raised when a user clicks to set OSM as the base layer
        """
        if state:
            self._web_spatial_loader.setBaseLayer(OSM)

    def on_map_zoom_level_changed(self, level):
        """
        Slot which is raised when the zoom level of the map changes.
        """
        self.zoomSlider.setValue(level)

    def on_reset_web_map(self):
        """
        Slot raised when the user clicks to reset the property
        location in the map.
        """
        self._web_spatial_loader.zoom_to_extents()

    def on_sync_extents(self):
        """
        Slot raised to synchronize the webview extents with those of the
        local map canvas.
        """
        if len(self.local_map.canvas_layers()) > 0:  # and self._ol_loaded:
            curr_extent = self.map_extents()
            self._web_spatial_loader.zoom_to_map_extents(curr_extent)

    def map_extents(self):
        """
        :returns: Current extents of the local map.
        :rtype: QgsRectangle
        """
        return self.local_map.extent()

    def canvas_zoom_to_extent(self, extent):
        self.local_map.canvas.setExtent(extent)
Beispiel #6
0
class SpatialPreview(QTabWidget, Ui_frmPropertyPreview):
    """
    Widget for previewing spatial unit on either local map or web source.
    """
    def __init__(self, parent=None, iface=None):
        QTabWidget.__init__(self, parent)
        self.setupUi(self)

        self._notif_bar = None
        self._ol_loaded = False
        self._overlay_layer = None

        self._db_session = STDMDb.instance().session

        self.set_iface(iface)

        #Web config
        self._web_spatial_loader = WebSpatialLoader(self.spatial_web_view, self)

        #Connect signals
        self._web_spatial_loader.loadError.connect(self.on_spatial_browser_error)
        self._web_spatial_loader.loadProgress.connect(self.on_spatial_browser_loading)
        self._web_spatial_loader.loadFinished.connect(self.on_spatial_browser_finished)
        self._web_spatial_loader.zoomChanged.connect(self.on_map_zoom_level_changed)
        self.rbGMaps.toggled.connect(self.on_load_GMaps)
        self.rbOSM.toggled.connect(self.on_load_OSM)
        self.zoomSlider.sliderReleased.connect(self.on_zoom_changed)
        self.btnResetMap.clicked.connect(self.on_reset_web_map)
        self.btnSync.clicked.connect(self.on_sync_extents)
        QgsMapLayerRegistry.instance().layersWillBeRemoved.connect(self._on_overlay_to_be_removed)

    def set_iface(self, iface):
        self._iface = iface
        self.local_map.set_iface(iface)

    def set_notification_bar(self, notif_bar):
        """
        Set notification widget.
        :param notif_bar: Notification widget.
        """
        self._notif_bar = notif_bar

    def notification_bar(self):
        """
        :return: Currently configured notification bar.
        """
        return self._notif_bar

    def _insert_notification(self, msg, level, clear_first = True):
        if self._notif_bar is None:
            return

        if clear_first:
            self._notif_bar.clear()

        self._notif_bar.insertNotification(msg, level)

    def iface(self):
        return self._iface

    def _setDefaults(self):
        """
        Set default settings
        """
        self.set_canvas_background_color(self.canvasBgColor)

    def set_canvas_background_color(self,color):
        """
        Set the background color of the map canvas
        """
        self.localMap.setCanvasColor(color)
        self.canvasBgColor = color

    def refresh_canvas_layers(self, process_events=False):
        """
        Reload map layers in the viewer canvas.
        """
        self.local_map.refresh_layers()

    def load_web_map(self):
        """
        Loads the web map into the view using canvas extents if there
        are existing layers in the map canvas.
        """
        if not self._ol_loaded:
            self._web_spatial_loader.load()

    def _create_vector_layer(self, geom_type, prj_code):
        """
        Creates/resets the internal vector layer that will be used to draw
        the spatial unit overlays.
        :param geom_type: Geometry type
        :type geom_type: str
        :param prj_code: EPSG code
        :type prj_code: int
        """
        self._overlay_layer = QgsVectorLayer(
            u"{0}?crs=epsg:{1!s}&field=lbname:string(20)&index=yes".format(geom_type,
                                                                      prj_code),
            "view_str_spatial_unit",
            "memory")

    def draw_spatial_unit(self, model, clear_existing=True):
        """
        Draw geometry of the given model in the respective local and web views.
        :param model: Source model whose geometry will be drawn.
        :type model: object
        :param clear_existing: Clears any existing features prior to adding the
        new features.
        :type clear_existing: bool
        """
        if model is None:
            msg = QApplication.translate("SpatialPreview",
                                         "Data model is empty, the spatial "
                                         "unit cannot be rendered.")
            QMessageBox.critical(self, QApplication.translate("SpatialPreview",
                                                              "Spatial Unit Preview"),
                                 msg)

            return

        table_name = model.__class__.__name__.replace(' ', '_').lower()
        if not pg_table_exists(table_name):
            msg = QApplication.translate("SpatialPreview",
                                         "The spatial unit data source could "
                                         "not be retrieved, the feature cannot "
                                         "be rendered.")
            QMessageBox.critical(self, QApplication.translate("SpatialPreview",
                                                              "Spatial Unit Preview"),
                                 msg)

            return

        spatial_cols = table_column_names(table_name, True)

        geom, geom_col = None, ""

        for sc in spatial_cols:
            geom = getattr(model, sc)

            #Use the first non-empty geometry value in the collection
            if not geom is None:
                geom_col = sc

        if geom is None:
            msg = QApplication.translate("SpatialPreview",
                                         "The selected spatial unit does not "
                                         "contain a valid geometry.")
            QMessageBox.critical(self, QApplication.translate("SpatialPreview",
                                                              "Spatial Unit Preview"),
                                 msg)

            return

        geom_type, epsg_code = geometryType(table_name, geom_col)

        if self._overlay_layer is None:
            self._create_vector_layer(geom_type, epsg_code)

            #Add layer to map
            QgsMapLayerRegistry.instance().addMapLayer(self._overlay_layer,
                                                       False)
            #Ensure it is always added on top
            QgsProject.instance().layerTreeRoot().insertLayer(0, self._overlay_layer)

        if clear_existing:
            self.delete_local_features()

        feat, extent = self._add_geom_to_map(geom)

        #Add spatial unit to web viewer
        self._web_spatial_loader.add_overlay(model, geom_col)

        #Increase bounding box by 50%, so that layer slightly zoomed out
        extent.scale(1.5)

        #Select feature. Hack for forcing a selection by using inversion
        self._overlay_layer.invertSelection()

        self._iface.mapCanvas().setExtent(extent)
        self._iface.mapCanvas().refresh()
        self.refresh_canvas_layers()

        #Need to force event so that layer is shown
        QCoreApplication.sendEvent(self.local_map, QShowEvent())

    def _add_geom_to_map(self, geom):
        if self._overlay_layer is None:
            return

        geom_func = geom.ST_AsText()
        geom_wkt = self._db_session.scalar(geom_func)

        dp = self._overlay_layer.dataProvider()

        feat = QgsFeature()
        g = QgsGeometry.fromWkt(geom_wkt)
        feat.setGeometry(g)
        dp.addFeatures([feat])

        self._overlay_layer.updateExtents()

        return feat, g.boundingBox()

    def delete_local_features(self, feature_ids=[]):
        """
        Removes features in the local map overlay.
        """
        del_status = False

        if not self._overlay_layer is None:
            if len(feature_ids) == 0:
                feature_ids = self._overlay_layer.allFeatureIds()

            del_status = self._overlay_layer.dataProvider().deleteFeatures(feature_ids)

        return del_status

    def remove_layer(self):
        """
        Removes both the local and web layers.
        """
        if not self._overlay_layer is None:
            QgsProject.instance().layerTreeRoot().removeLayer(self._overlay_layer)

            #Clear web overlays
            self._web_spatial_loader.removeOverlay()

            self._overlay_layer = None

    def _on_overlay_to_be_removed(self, layers_ids):
        """
        Resets the local layer variable and removes the web overlay.
        """
        if not self._overlay_layer is None:
            if self._overlay_layer.id() in layers_ids:
                self.remove_layer()

    def on_spatial_browser_error(self, err):
        """
        Slot raised when an error occurs when loading items in the property browser
        """
        self._insert_notification(err, ERROR)

    def on_spatial_browser_loading(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.lblInfo.setText("")
            self.lblInfo.setVisible(False)

        else:
            self.lblInfo.setVisible(True)
            self.lblInfo.setText("Loading...%d%%)"%(progress))

    def on_spatial_browser_finished(self, status):
        """
        Slot raised when the property browser finishes loading the content
        """
        if status:
            if len(self.local_map.canvas_layers()) > 0 and not self._ol_loaded:
                self.on_sync_extents()

            self._ol_loaded = True
            #self._overlay_spatial_unit()

        else:
            msg = QApplication.translate("SpatialPreview",
                                         "Error: Spatial unit cannot be loaded.")
            self._insert_notification(msg, ERROR)

    def on_zoom_changed(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._web_spatial_loader.zoom_to_level(zoom)

    def on_load_GMaps(self, state):
        """
        Slot raised when a user clicks to set Google Maps Satellite
        as the base layer
        """
        if state:
            self._web_spatial_loader.setBaseLayer(GMAP_SATELLITE)

    def on_load_OSM(self, state):
        """
        Slot raised when a user clicks to set OSM as the base layer
        """
        if state:
            self._web_spatial_loader.setBaseLayer(OSM)

    def on_map_zoom_level_changed(self, level):
        """
        Slot which is raised when the zoom level of the map changes.
        """
        self.zoomSlider.setValue(level)

    def on_reset_web_map(self):
        """
        Slot raised when the user clicks to reset the property
        location in the map.
        """
        self._web_spatial_loader.zoom_to_extents()

    def on_sync_extents(self):
        """
        Slot raised to synchronize the webview extents with those of the
        local map canvas.
        """
        if len(self.local_map.canvas_layers()) > 0 and self._ol_loaded:
            curr_extent = self.map_extents()
            self._web_spatial_loader.zoom_to_map_extents(curr_extent)

    def map_extents(self):
        """
        :returns: Current extents of the local map.
        :rtype: QgsRectangle
        """
        return self.local_map.extent()

    def canvas_zoom_to_extent(self, extent):
        self.local_map.canvas.setExtent(extent)
Beispiel #7
0
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)