Exemple #1
1
    def onError(self, error):
        if error == QProcess.FailedToStart:
            msg = QCoreApplication.translate("GdalTools", "The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program.")
        elif error == QProcess.Crashed:
            msg = QCoreApplication.translate("GdalTools", "The process crashed some time after starting successfully.")
        else:
            msg = QCoreApplication.translate("GdalTools", "An unknown error occurred.")

        QErrorMessage(self).showMessage(msg)
        QApplication.processEvents()  # give the user chance to see the message

        self.stop()
Exemple #2
0
 def end_process(self):
     """
     Make some stuff after the process
     """
     self.pushButton_runQuery.setDisabled(False)
     self.pushButton_runQuery.setText(self.pushButton_runQuery.initialText)
     self.progressBar_execution.setMinimum(0)
     self.progressBar_execution.setMaximum(100)
     self.progressBar_execution.setValue(100)
     QApplication.processEvents()
def execute(func, message = None, useThread = False):
    global _dialog
    cursor = QApplication.overrideCursor()
    waitCursor = (cursor is not None and cursor.shape() == Qt.WaitCursor)
    dialogCreated = False
    try:
        QCoreApplication.processEvents()
        if not waitCursor:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        if message is not None and useThread:
            t = Thread(func)
            loop = QEventLoop()
            t.finished.connect(loop.exit, Qt.QueuedConnection)
            if _dialog is None:
                dialogCreated = True
                _dialog = QProgressDialog(message, "Mapstory", 0, 0, config.iface.mainWindow())
                _dialog.setWindowTitle("Mapstory")
                _dialog.setWindowModality(Qt.WindowModal);
                _dialog.setMinimumDuration(1000)
                _dialog.setMaximum(100)
                _dialog.setValue(0)
                _dialog.setMaximum(0)
                _dialog.setCancelButton(None)
            else:
                oldText = _dialog.labelText()
                _dialog.setLabelText(message)
            QApplication.processEvents()
            t.start()
            loop.exec_(flags = QEventLoop.ExcludeUserInputEvents)
            if t.exception is not None:
                raise t.exception
            return t.returnValue
        else:
            return func()
    finally:
        if message is not None and useThread:
            if dialogCreated:
                _dialog.reset()
                _dialog = None
            else:
                _dialog.setLabelText(oldText)
        if not waitCursor:
            QApplication.restoreOverrideCursor()
        QCoreApplication.processEvents()
Exemple #4
0
def process_query(
        dialog=None,
        query=None,
        nominatim=None,
        bbox=None,
        output_dir=None,
        prefix_file=None,
        output_geometry_types=None,
        layer_name="OsmQuery",
        white_list_values=None,
        config_outputs=None):
    """execute a query and send the result file to open_file."""

    # Prepare outputs
    dialog.set_progress_text(tr('Prepare outputs'))

    # Getting the default overpass api and running the query
    server = get_setting('defaultOAPI', OVERPASS_SERVERS[0]) + 'interpreter'
    dialog.set_progress_text(
        tr('Downloading data from Overpass {}').format(server))
    # Replace Nominatim or BBOX
    query = QueryPreparation(query, bbox, nominatim, server)
    QApplication.processEvents()
    final_query = query.prepare_query()
    url = query.prepare_url()
    connexion_overpass_api = ConnexionOAPI(url)
    LOGGER.debug('Encoded URL: {}'.format(url))
    osm_file = connexion_overpass_api.run()

    return open_file(
        dialog=dialog,
        osm_file=osm_file,
        output_geom_types=output_geometry_types,
        white_list_column=white_list_values,
        layer_name=layer_name,
        output_dir=output_dir,
        prefix_file=prefix_file,
        final_query=final_query,
        config_outputs=config_outputs)
Exemple #5
0
    def returnedBounds(self):
        rb = self.tool.rb

        warning = True
        ok = True
        active = False
        errBuffer_noAtt = False
        errBuffer_Vertices = False
        
        buffer_geom = None
        buffer_geom_crs = None
        
        # we check if there's at least one visible layer
        for layer in QgsProject().instance().mapLayers().values():
            if QgsProject.instance().layerTreeRoot().findLayer(layer.id()).isVisible():
                warning = False
                active = True
                break
                
        # buffer creation on the current layer
        if self.request == 'buffer':
            layer = self.iface.layerTreeView().currentLayer()
            if layer is not None and layer.type() == QgsMapLayer.VectorLayer and QgsProject.instance().layerTreeRoot().findLayer(layer.id()).isVisible():
                # rubberband reprojection
                g = self.geomTransform(rb.asGeometry(), self.iface.mapCanvas().mapSettings().destinationCrs(), layer.crs())
                features = layer.getFeatures(QgsFeatureRequest(g.boundingBox()))
                rbGeom = []
                for feature in features:
                    geom = feature.geometry()
                    if g.intersects(geom):
                        rbGeom.append(QgsGeometry(feature.geometry()))
                if len(rbGeom) > 0:
                    union_geoms = rbGeom[0]
                    for geometry in rbGeom:
                        if union_geoms.combine(geometry) is not None:
                            union_geoms = union_geoms.combine(geometry)
                    
                    rb.setToGeometry(union_geoms, layer)
                    
                    perim, ok = QInputDialog.getDouble(self.iface.mainWindow(), self.tr('Perimeter'), self.tr('Give a perimeter in m:')+'\n'+self.tr('(works only with metric crs)'), min=0)
                    buffer_geom_crs = layer.crs()
                    buffer_geom = union_geoms.buffer(perim, 40)
                    rb.setToGeometry(buffer_geom, QgsVectorLayer("Polygon?crs="+layer.crs().authid(),"","memory"))
                    
                    if buffer_geom.length == 0 :
                        warning = True
                        errBuffer_Vertices = True
                else:
                    warning = True
                    errBuffer_noAtt = True
            else:
                warning = True
                        
        if len(QgsProject().instance().mapLayers().values()) > 0 and warning == False and ok:
            self.loadingWindow.show()
            self.loadingWindow.activateWindow();
            self.loadingWindow.showNormal();
            for layer in QgsProject().instance().mapLayers().values():
                if layer.type() == QgsMapLayer.VectorLayer and QgsProject.instance().layerTreeRoot().findLayer(layer.id()).isVisible():
                    if self.request == 'buffer' and self.iface.layerTreeView().currentLayer() == layer:
                        layer.selectByIds([])
                        continue
                    self.loadingWindow.reset()
                    self.loadingWindow.setWindowTitle(self.tr('Selecting...'))
                    self.loadingWindow.setLabelText(layer.name())
                    
                    # rubberband reprojection
                    if self.request == 'buffer':
                        if buffer_geom_crs.authid() != layer.crs().authid():
                            g = self.geomTransform(buffer_geom, buffer_geom_crs, layer.crs())
                        else:
                            g = self.geomTransform(buffer_geom, buffer_geom_crs, layer.crs())
                    else:
                        g = self.geomTransform(rb.asGeometry(), self.iface.mapCanvas().mapSettings().destinationCrs(), layer.crs())
                    
                    feat_id = []
                    features = layer.getFeatures(QgsFeatureRequest(g.boundingBox()))
                    count = layer.getFeatures(QgsFeatureRequest(g.boundingBox()))
                    
                    nbfeatures = 0
                    for feature in count:
                        nbfeatures+=1
                                        
                    # Select attributes intersecting with the rubberband
                    index = 0
                    for feature in features:
                        geom = feature.geometry()
                        try:
                            if g.intersects(geom):
                                feat_id.append(feature.id())
                        except:
                            # There's an error but it intersects
                            print('error with '+layer.name()+' on '+str(feature.id()))
                            feat_id.append(feature.id())
                        index += 1
                        self.loadingWindow.setValue(int((float(index)/nbfeatures)*100))
                        if self.loadingWindow.wasCanceled():
                            self.loadingWindow.reset()
                            break
                        QApplication.processEvents()
                    layer.selectByIds(feat_id)
            
            self.loadingWindow.close()
            self.showAttributesTable()
        else:
            # Display a warning in the message bar depending of the error
            if active == False:
                self.iface.messageBar().pushWarning(self.tr('Warning'), self.tr('There is no active layer !'))
            elif ok == False:
                pass
            elif errBuffer_noAtt:
                self.iface.messageBar().pushWarning(self.tr('Warning'), self.tr('You didn\'t click on a layer\'s attribute !'))
            elif errBuffer_Vertices:
                self.iface.messageBar().pushWarning(self.tr('Warning'), self.tr('You must give a non-null value for a point\'s or line\'s perimeter !'))
            else:
                self.iface.messageBar().pushWarning(self.tr('Warning'), self.tr('There is no selected layer, or it is not vector nor visible !'))
Exemple #6
0
    def test(self):

        # This test is quite fragile as it depends on windows manager behaviour
        # regarding focus, so not surprising it doesn't pass
        # on other platforms than Linux.
        #if 'TRAVIS_OS_NAME' in os.environ and os.environ['TRAVIS_OS_NAME'] == 'osx':
        #    return

        main_dialog = QgsProviderRegistry.instance().selectWidget("WFS")
        main_dialog.setProperty("hideDialogs", True)

        self.assertIsNotNone(main_dialog)

        # Create new connection
        btnNew = main_dialog.findChild(QWidget, "btnNew")
        self.assertIsNotNone(btnNew)
        QTest.mouseClick(btnNew, Qt.LeftButton)
        new_conn = find_window('QgsNewHttpConnectionBase')
        self.assertIsNotNone(new_conn)
        txtName = new_conn.findChild(QLineEdit, "txtName")
        self.assertIsNotNone(txtName)
        txtName.setText("test_connection")
        txtUrl = new_conn.findChild(QLineEdit, "txtUrl")
        self.assertIsNotNone(txtUrl)
        txtUrl.setText("test_url")
        new_conn.accept()

        # Wait for object to be destroyed
        new_conn = self.wait_object_destruction(new_conn)

        # Try to connect
        btnConnect = main_dialog.findChild(QWidget, "btnConnect")
        self.assertIsNotNone(btnConnect)
        QTest.mouseClick(btnConnect, Qt.LeftButton)
        # Depends on asynchronous signal
        QApplication.processEvents()
        error_box = find_window('WFSCapabilitiesErrorBox')
        self.assertIsNotNone(error_box)
        # Close error box
        error_box.accept()

        # Wait for object to be destroyed
        error_box = self.wait_object_destruction(error_box)

        # Edit connection
        btnEdit = main_dialog.findChild(QWidget, "btnEdit")
        self.assertIsNotNone(btnEdit)
        QTest.mouseClick(btnEdit, Qt.LeftButton)
        new_conn = find_window('QgsNewHttpConnectionBase',)
        self.assertIsNotNone(new_conn)
        txtName = new_conn.findChild(QLineEdit, "txtName")
        self.assertIsNotNone(txtName)
        txtName.setText("test_connection")
        txtUrl = new_conn.findChild(QLineEdit, "txtUrl")
        self.assertIsNotNone(txtUrl)

        endpoint = self.basetestpath + '/fake_qgis_http_endpoint'
        expected_endpoint = endpoint
        if sys.platform == 'win32' and expected_endpoint[1] == ':':
            expected_endpoint = expected_endpoint[0] + expected_endpoint[2:]
        with open(sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?ACCEPTVERSIONS=2.0.0,1.1.0,1.0.0'), 'wb') as f:
            f.write("""
<wfs:WFS_Capabilities version="2.0.0" xmlns="http://www.opengis.net/wfs/2.0" xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:gml="http://schemas.opengis.net/gml/3.2" xmlns:fes="http://www.opengis.net/fes/2.0">
  <FeatureTypeList>
    <FeatureType>
      <Name>my:typename</Name>
      <Title>Title</Title>
      <Abstract>Abstract</Abstract>
      <DefaultCRS>urn:ogc:def:crs:EPSG::4326</DefaultCRS>
      <ows:WGS84BoundingBox>
        <ows:LowerCorner>-71.123 66.33</ows:LowerCorner>
        <ows:UpperCorner>-65.32 78.3</ows:UpperCorner>
      </ows:WGS84BoundingBox>
    </FeatureType>
  </FeatureTypeList>
  <fes:Filter_Capabilities>
    <fes:Spatial_Capabilities>
      <fes:GeometryOperands>
        <fes:GeometryOperand name="gml:Envelope"/>
        <fes:GeometryOperand name="gml:Point"/>
        <fes:GeometryOperand name="gml:MultiPoint"/>
        <fes:GeometryOperand name="gml:LineString"/>
        <fes:GeometryOperand name="gml:MultiLineString"/>
        <fes:GeometryOperand name="gml:Polygon"/>
        <fes:GeometryOperand name="gml:MultiPolygon"/>
        <fes:GeometryOperand name="gml:MultiGeometry"/>
      </fes:GeometryOperands>
      <fes:SpatialOperators>
        <fes:SpatialOperator name="Disjoint"/>
        <fes:SpatialOperator name="Equals"/>
        <fes:SpatialOperator name="DWithin"/>
        <fes:SpatialOperator name="Beyond"/>
        <fes:SpatialOperator name="Intersects"/>
        <fes:SpatialOperator name="Touches"/>
        <fes:SpatialOperator name="Crosses"/>
        <fes:SpatialOperator name="Within"/>
        <fes:SpatialOperator name="Contains"/>
        <fes:SpatialOperator name="Overlaps"/>
        <fes:SpatialOperator name="BBOX"/>
      </fes:SpatialOperators>
    </fes:Spatial_Capabilities>
    <fes:Functions>
      <fes:Function name="abs">
        <fes:Returns>xs:int</fes:Returns>
        <fes:Arguments>
          <fes:Argument name="param">
            <fes:Type>xs:int</fes:Type>
          </fes:Argument>
        </fes:Arguments>
      </fes:Function>
    </fes:Functions>
  </fes:Filter_Capabilities>
</wfs:WFS_Capabilities>""".encode('UTF-8'))

        txtUrl.setText("http://" + endpoint)
        new_conn.accept()

        # Wait for object to be destroyed
        new_conn = self.wait_object_destruction(new_conn)

        # Try to connect
        btnConnect = main_dialog.findChild(QWidget, "btnConnect")
        self.assertIsNotNone(btnConnect)
        QTest.mouseClick(btnConnect, Qt.LeftButton)

        buttonAdd = self.get_button_add(main_dialog)
        for i in range(10):
            QApplication.processEvents()
            if buttonAdd.isEnabled():
                break
        self.assertTrue(buttonAdd.isEnabled())

        # Add layer
        self.addWfsLayer_uri = None
        self.addWfsLayer_layer_name = None
        main_dialog.addWfsLayer.connect(self.slotAddWfsLayer)
        QTest.mouseClick(buttonAdd, Qt.LeftButton)
        self.assertEqual(self.addWfsLayer_uri, ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=')
        self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')

        # Click on Build Query
        buttonBuildQuery = self.get_button_build_query(main_dialog)
        self.assertTrue(buttonBuildQuery.isEnabled())
        QTest.mouseClick(buttonBuildQuery, Qt.LeftButton)
        error_box = find_window('WFSFeatureTypeErrorBox')
        self.assertIsNotNone(error_box)
        # Close error box
        error_box.accept()
        # Wait for object to be destroyed
        error_box = self.wait_object_destruction(error_box)

        # Click again but with valid DescribeFeatureType

        with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=my:typename'), 'wb') as f:
            f.write("""
<xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my">
  <xsd:import namespace="http://www.opengis.net/gml/3.2"/>
  <xsd:complexType name="typenameType">
    <xsd:complexContent>
      <xsd:extension base="gml:AbstractFeatureType">
        <xsd:sequence>
          <xsd:element maxOccurs="1" minOccurs="0" name="intfield" nillable="true" type="xsd:int"/>
          <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:PolygonPropertyType"/>
        </xsd:sequence>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>
  <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/>
</xsd:schema>
""".encode('UTF-8'))
        QTest.mouseClick(buttonBuildQuery, Qt.LeftButton)

        # Check that the combos are properly initialized
        dialog = find_window('QgsSQLComposerDialogBase')
        self.assertIsNotNone(dialog)

        mTablesCombo = dialog.findChild(QComboBox, "mTablesCombo")
        self.assertIsNotNone(mTablesCombo)
        self.assertEqual(mTablesCombo.itemText(1), 'typename (Title)')

        mColumnsCombo = dialog.findChild(QComboBox, "mColumnsCombo")
        self.assertIsNotNone(mColumnsCombo)
        self.assertEqual(mColumnsCombo.itemText(1), 'intfield (int)')
        self.assertEqual(mColumnsCombo.itemText(mColumnsCombo.count() - 2), 'geometryProperty (geometry)')
        self.assertEqual(mColumnsCombo.itemText(mColumnsCombo.count() - 1), '*')

        mFunctionsCombo = dialog.findChild(QComboBox, "mFunctionsCombo")
        self.assertIsNotNone(mFunctionsCombo)
        self.assertEqual(mFunctionsCombo.itemText(1), 'abs(param: int): int')

        mSpatialPredicatesCombo = dialog.findChild(QComboBox, "mSpatialPredicatesCombo")
        self.assertIsNotNone(mSpatialPredicatesCombo)
        self.assertEqual(mSpatialPredicatesCombo.itemText(1), 'ST_Disjoint(geometry, geometry): boolean')

        mWhereEditor = dialog.findChild(QTextEdit, "mWhereEditor")
        self.assertIsNotNone(mWhereEditor)
        mWhereEditor.setText('1 = 1')

        dialog.accept()
        # Wait for object to be destroyed
        dialog = self.wait_object_destruction(dialog)

        # Add layer
        buttonAdd = self.get_button_add(main_dialog)
        self.assertTrue(buttonAdd.isEnabled())

        self.addWfsLayer_uri = None
        self.addWfsLayer_layer_name = None
        main_dialog.addWfsLayer.connect(self.slotAddWfsLayer)
        QTest.mouseClick(buttonAdd, Qt.LeftButton)
        self.assertEqual(self.addWfsLayer_uri, ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=SELECT * FROM typename WHERE 1 = 1')
        self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')
Exemple #7
0
    def open_file(self):
        """
        Open the osm file with the osmconf
        """

        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.start_process()
        QApplication.processEvents()

        # Get fields
        osm_file = self.osm_file.filePath()
        osm_conf = self.osm_conf.filePath()
        output_directory = self.output_directory.filePath()
        prefix_file = self.lineEdit_filePrefix.text()
        load_only = self.radioButton_osmConf.isChecked()

        # Which geometry at the end ?
        output_geometry_types = self.get_output_geometry_types()

        try:
            if not output_geometry_types:
                raise OutPutGeomTypesException

            if not isfile(osm_file):
                raise FileDoesntExistException(suffix="*.osm or *.pbf")

            if load_only:
                if not isfile(osm_conf):
                    raise FileDoesntExistException(suffix="*.ini")

            if output_directory and not isdir(output_directory):
                raise DirectoryOutPutException

            if load_only:
                # Legacy, waiting to remove the OsmParser for QGIS >= 3.6
                # Change in osm_file_dialog.py L131 too
                output_geom_legacy = [
                    l.value.lower() for l in output_geometry_types]
                osm_parser = OsmParser(
                    osm_file,
                    load_only=True,
                    osm_conf=osm_conf,
                    layers=output_geom_legacy)
                layers = osm_parser.parse()

                for item in list(layers.values()):
                    QgsProject.instance().addMapLayer(item)

            else:
                open_file(
                    dialog=self,
                    osm_file=osm_file,
                    output_geom_types=output_geometry_types,
                    output_dir=output_directory,
                    prefix_file=prefix_file)
                display_message_bar(
                    tr('Successful query'),
                    level=Qgis.Success,
                    duration=5)

        except QuickOsmException as e:
            self.display_geo_algorithm_exception(e)
        except Exception as e:  # pylint: disable=broad-except
            self.display_exception(e)
        finally:
            QApplication.restoreOverrideCursor()
            self.end_process()
            QApplication.processEvents()
 def setProgress(self, value):
     try:
         self.progressBar.setValue(value)
         QApplication.processEvents()
     except:
         pass
 def profiles_progress(self, msg):
     self.iface.mainWindow().statusBar().showMessage(msg)
     self.ui.IDC_lblCreateStatus.setText(msg)
     QApplication.processEvents()
Exemple #10
0
def CreateVideoLayers(ele):
    ''' Create Video Layers '''
    if qgsu.selectLayerByName(Footprint_lyr) is None:
        lyr_footprint = newPolygonsLayer(None, [
            "Corner Longitude Point 1", "Corner Latitude Point 1",
            "Corner Longitude Point 2", "Corner Latitude Point 2",
            "Corner Longitude Point 3", "Corner Latitude Point 3",
            "Corner Longitude Point 4", "Corner Latitude Point 4"
        ], epsg, Footprint_lyr)
        SetDefaultFootprintStyle(lyr_footprint)
        addLayerNoCrsDialog(lyr_footprint)

        # 3D Style
        if ele:
            SetDefaultFootprint3DStyle(lyr_footprint)

    if qgsu.selectLayerByName(Beams_lyr) is None:
        lyr_beams = newLinesLayer(None, [
            "longitude", "latitude", "altitude", "Corner Longitude",
            "Corner Latitude"
        ], epsg, Beams_lyr, LineZ)
        SetDefaultBeamsStyle(lyr_beams)
        addLayerNoCrsDialog(lyr_beams)
        # 3D Style
        if ele:
            SetDefaultBeams3DStyle(lyr_beams)

    if qgsu.selectLayerByName(Trajectory_lyr) is None:
        lyr_Trajectory = newLinesLayer(None,
                                       ["longitude", "latitude", "altitude"],
                                       epsg, Trajectory_lyr, LineZ)
        SetDefaultTrajectoryStyle(lyr_Trajectory)
        addLayerNoCrsDialog(lyr_Trajectory)
        # 3D Style
        if ele:
            SetDefaultTrajectory3DStyle(lyr_Trajectory)

    if qgsu.selectLayerByName(FrameAxis_lyr) is None:
        lyr_frameaxis = newLinesLayer(None, [
            "longitude", "latitude", "altitude", "Corner Longitude",
            "Corner Latitude", "Corner altitude"
        ], epsg, FrameAxis_lyr, LineZ)
        SetDefaultFrameAxisStyle(lyr_frameaxis)
        addLayerNoCrsDialog(lyr_frameaxis)
        # 3D Style
        if ele:
            SetDefaultFrameAxis3DStyle(lyr_frameaxis)

    if qgsu.selectLayerByName(Platform_lyr) is None:
        lyr_platform = newPointsLayer(None,
                                      ["longitude", "latitude", "altitude"],
                                      epsg, Platform_lyr, PointZ)
        SetDefaultPlatformStyle(lyr_platform)
        addLayerNoCrsDialog(lyr_platform)
        # 3D Style
        if ele:
            SetDefaultPlatform3DStyle(lyr_platform)

    if qgsu.selectLayerByName(Point_lyr) is None:
        lyr_point = newPointsLayer(
            None, ["number", "longitude", "latitude", "altitude"], epsg,
            Point_lyr)
        SetDefaultPointStyle(lyr_point)
        addLayerNoCrsDialog(lyr_point)

    if qgsu.selectLayerByName(FrameCenter_lyr) is None:
        lyr_framecenter = newPointsLayer(None,
                                         ["longitude", "latitude", "altitude"],
                                         epsg, FrameCenter_lyr)
        SetDefaultFrameCenterStyle(lyr_framecenter)
        addLayerNoCrsDialog(lyr_framecenter)
        # 3D Style
        if ele:
            SetDefaultFrameCenter3DStyle(lyr_framecenter)

    if qgsu.selectLayerByName(Line_lyr) is None:
        #         lyr_line = newLinesLayer(
        # None, ["longitude", "latitude", "altitude"], epsg, Line_lyr)
        lyr_line = newLinesLayer(None, [], epsg, Line_lyr)
        SetDefaultLineStyle(lyr_line)
        addLayerNoCrsDialog(lyr_line)

    if qgsu.selectLayerByName(Polygon_lyr) is None:
        lyr_polygon = newPolygonsLayer(None, [
            "Centroid_longitude", "Centroid_latitude", "Centroid_altitude",
            "Area"
        ], epsg, Polygon_lyr)
        SetDefaultPolygonStyle(lyr_polygon)
        addLayerNoCrsDialog(lyr_polygon)

    QApplication.processEvents()
    return
 def processEvents():
     try:
         qApp.processEvents()
     except:
         QApplication.processEvents()
    def wkblify_raster_level(self,  options, ds, level, band_range, infile, i):
    
        band_from = band_range[0]
        band_to = band_range[1]
        
        # Collect raster and block dimensions
        raster_size = ( ds.RasterXSize, ds.RasterYSize )
        if options['block_size'] is not None:
            block_size = self.parse_block_size(options,  ds)
            read_block_size = ( block_size[0] * level, block_size[1] * level)
            grid_size = self.calculate_grid_size(raster_size, read_block_size)
        else:
            block_size = raster_size # Whole raster as a single block
            read_block_size = block_size
            grid_size = (1, 1)
    
        gen_table = options['schema_table']
    
        # Write (original) raster to hex binary output
        tile_count = 0
        hexwkb = ''
        self.progress_label.setText(self.tr("Uploading tiles..."))
        importString = ""
        sum_tiles = grid_size[0]*grid_size[1]

        copy_size = 500
        
        for ycell in range(0, grid_size[1]):
            for xcell in range(0, grid_size[0]):
    
                xoff = xcell * read_block_size[0]
                yoff = ycell * read_block_size[1]
    
                if options['block_size'] is not None:
                    hexwkb = '' # Reset buffer as single INSERT per tile is generated
                    hexwkb += self.wkblify_raster_header(options, ds, level, (xoff, yoff),
                                                    block_size[0], block_size[1])
                else:
                    hexwkb += self.wkblify_raster_header(options, ds, level, (xoff, yoff))
    
                for b in range(band_from, band_to):
                    band = ds.GetRasterBand(b)
    
                    hexwkb += self.wkblify_band_header(options, band)
                    hexwkb += self.wkblify_band(options, band, level, xoff, yoff, read_block_size, block_size, infile, b)
    
                # Creating COPY String
                importString += str(tile_count)+"\t"+hexwkb+"\n"
                tile_count = tile_count + 1
                
            # Periodically update ui
                if (tile_count % copy_size) == 0:
                    self.cursor.copy_from(StringIO(importString), '%s' % gen_table)
                    importString = ""
                    self.progress_label.setText(self.tr("{table}: {count} of {sum_tiles} tiles uploaded").format(
                        table=gen_table, 
                        count=tile_count,  
                        sum_tiles= sum_tiles))                
                        
                    QApplication.processEvents()

        self.cursor.copy_from(StringIO(importString), '%s' % gen_table)
        self.conn.commit()
        
        self.progress_label.setText(self.tr("Calculating raster params for {sum_tiles} tiles ...").format(
            sum_tiles= sum_tiles))        
        QApplication.processEvents()        

        self.cursor.execute(self.make_sql_addrastercolumn(options))
        self.conn.commit()
        
        return (gen_table, tile_count)
Exemple #13
0
    def run_stats(self):
        """Main function which do the process."""

        # Get the common fields.
        self.admin_layer = self.cbx_aggregation_layer.currentLayer()

        if self.use_point_layer:
            # If we use a point layer.
            point_layer = self.cbx_case_layer.currentLayer()
        else:
            # If we use a column with number of case.
            case_column = self.cbx_case_field.currentField()
            index_case = self.admin_layer.fields().indexFromName(case_column)
            #Replace laer.fieldNameIndex(name) to layer.fields().lookup\Field(name)
            #http://learn.openwaterfoundation.org/owf-app-geoprocessor-python-doc-dev/resources/migrate-qgis2-qgis3/

        if not self.use_area:
            # If we don't use density.
            population = self.cbx_population_field.currentField()
            index_population = self.admin_layer.fields().indexFromName(population)

        self.name_field=self.le_new_column.text()
        if not self.name_field:
            self.name_field = self.le_new_column.placeholderText()

        # Add new column.
        add_nb_intersections = self.checkBox_addNbIntersections.isChecked()

        # Ratio
        ratio = self.cbx_ratio.currentText()
        ratio = ratio.replace(' ', '')

        # Output.
        self.output_file_path = self.le_output_filepath.text()

        try:
            self.button_box_ok.setDisabled(True)
            # noinspection PyArgumentList
            QApplication.setOverrideCursor(Qt.WaitCursor)
            # noinspection PyArgumentList
            QApplication.processEvents()

            if not self.admin_layer:
                QMessageBox.information(None, "DEBUG:", str("There is no layer"))
                raise NoLayerProvidedException

            if not self.admin_layer and self.use_point_layer:
                QMessageBox.information(None, "DEBUG:", str("There is no layer"))
                raise NoLayerProvidedException

            crs_admin_layer = self.admin_layer.crs()

            if self.use_point_layer:
                crs_point_layer = point_layer.crs()
                if crs_admin_layer != crs_point_layer:
                    QMessageBox.information(None, "DEBUG:", str("CRS of two layers are not the same. Please set CRS."))
                    raise DifferentCrsException(
                        epsg1=crs_point_layer.authid(),
                        epsg2=crs_admin_layer.authid())

            if not self.use_point_layer and not self.use_area:
                if index_population == index_case:
                    QMessageBox.information(None, "DEBUG:", str("You are using the same variable for case and population. Please change."))
                    raise FieldException(field_1='Population', field_2='Case')

            try:
                ratio = float(ratio)
            except ValueError:
                QMessageBox.information(None, "DEBUG:", str("The variable is not number."))
                raise NotANumberException(suffix=ratio)

            # Output
            if not self.output_file_path:
                temp_file = NamedTemporaryFile(
                    delete=False,
                    suffix='-geohealth.shp')
                self.output_file_path = temp_file.name
                temp_file.flush()
                temp_file.close()
            else:
                with open(self.output_file_path, 'w') as document: pass

            admin_layer_provider = self.admin_layer.dataProvider()
            fields = self.admin_layer.fields()

            if admin_layer_provider.fields().indexFromName(self.name_field) != -1:
                QMessageBox.information(None, "DEBUG:", str("The field name already exist."))
                raise FieldExistingException(field=self.name_field)

            fields.append(QgsField(self.name_field, QVariant.Double))

            if add_nb_intersections:
                fields.append(QgsField('nb_of_intersections', QVariant.Int))

            data = []

            file_writer = QgsVectorFileWriter(
                self.output_file_path,
                'utf-8',
                fields,
                QgsWkbTypes.Polygon,
                self.admin_layer.crs(),
                'ESRI Shapefile')

            if self.use_point_layer:
                total_case = point_layer.featureCount()
            else:
                total_case = 0

            for i, feature in enumerate(self.admin_layer.getFeatures()):
                attributes = feature.attributes()

                if self.use_point_layer:
                    count = 0
                    for f in point_layer.getFeatures():
                        if f.geometry().intersects(feature.geometry()):
                            count += 1
                else:
                    count = int(attributes[index_case])
                    total_case += count

                try:
                    if self.use_area:
                        area = feature.geometry().area()
                        value = float(count) / area * ratio
                    else:
                        try:
                            population = float(attributes[index_population])
                        except ValueError:
                            QMessageBox.information(None, "DEBUG:", str("This is not a number."))
                            raise NotANumberException(
                                suffix=attributes[index_population])
                        value = float(count) / population * ratio

                except ZeroDivisionError:
                    value = None
                except TypeError:
                    value = None

                data.append(value)
                attributes.append(value)

                if add_nb_intersections:
                    attributes.append(count)

                new_feature = QgsFeature()
                new_geom = QgsGeometry(feature.geometry())
                new_feature.setAttributes(attributes)
                new_feature.setGeometry(new_geom)

                file_writer.addFeature(new_feature)

            del file_writer

            self.output_layer = QgsVectorLayer(
                self.output_file_path,
                self.name_field,
                'ogr')
            QgsProject.instance().addMapLayer(self.output_layer)

            if self.checkBox_incidence_runStats.isChecked():

                stats = Stats(data)

                items_stats = [
                    'Incidence null,%d' % stats.null_values(),
                    'Count(point),%d' % total_case,
                    'Count(polygon),%d' % self.admin_layer.featureCount(),
                    'Min,%d' % stats.min(),
                    'Average,%f' % stats.average(),
                    'Max,%d' % stats.max(),
                    'Median,%f' % stats.median(),
                    'Range,%d' % stats.range(),
                    'Variance,%f' % stats.variance(),
                    'Standard deviation,%f' % stats.standard_deviation()
                ]

                self.tableWidget.clear()
                self.tableWidget.setColumnCount(2)
                labels = ['Parameters', 'Values']
                self.tableWidget.setHorizontalHeaderLabels(labels)
                self.tableWidget.setRowCount(len(items_stats))

                for i, item in enumerate(items_stats):
                    s = item.split(',')
                    self.tableWidget.setItem(i, 0, QTableWidgetItem(s[0]))
                    self.tableWidget.setItem(i, 1, QTableWidgetItem(s[1]))
                self.tableWidget.resizeRowsToContents()

                self.draw_plot(data)

            else:
                self.hide()

            if self.symbology.isChecked():
                self.add_symbology()

            self.signalStatus.emit(3, tr('Successful process'))

        except GeoPublicHealthException as e:
            display_message_bar(msg=e.msg, level=e.level, duration=e.duration)

        finally:
            self.button_box_ok.setDisabled(False)
            # noinspection PyArgumentList
            QApplication.restoreOverrideCursor()
            # noinspection PyArgumentList
            QApplication.processEvents()
Exemple #14
0
def open_file(dialog=None,
              osm_file=None,
              output_geom_types=None,
              white_list_column=None,
              layer_name="OsmFile",
              config_outputs=None,
              output_dir=None,
              prefix_file=None):
    """
    Open an osm file.

    Memory layer if no output directory is set, or Geojson in the output directory.
    """
    outputs = {}
    if output_dir:
        for layer in ['points', 'lines', 'multilinestrings', 'multipolygons']:
            if not prefix_file:
                prefix_file = layer_name

            outputs[layer] = join(output_dir,
                                  prefix_file + "_" + layer + ".geojson")

            if isfile(outputs[layer]):
                raise FileOutPutException(suffix='(' + outputs[layer] + ')')

    # Parsing the file
    osm_parser = OsmParser(osm_file=osm_file,
                           layers=output_geom_types,
                           white_list_column=white_list_column)

    osm_parser.signalText.connect(dialog.set_progress_text)
    osm_parser.signalPercentage.connect(dialog.set_progress_percentage)
    layers = osm_parser.parse()

    # Finishing the process with geojson or memory layer
    num_layers = 0

    for i, (layer, item) in enumerate(layers.items()):
        dialog.set_progress_percentage(i / len(layers) * 100)
        QApplication.processEvents()
        if item['featureCount'] and layer in output_geom_types:

            final_layer_name = layer_name
            # If configOutputs is not None (from My Queries)
            if config_outputs:
                if config_outputs[layer]['namelayer']:
                    final_layer_name = config_outputs[layer]['namelayer']

            if output_dir:
                dialog.set_progress_text(
                    tr("QuickOSM", u"From memory to GeoJSON: " + layer))
                # Transforming the vector file
                osm_geometries = {
                    'points': QgsWkbTypes.Point,
                    'lines': QgsWkbTypes.LineString,
                    'multilinestrings': QgsWkbTypes.MultiLineString,
                    'multipolygons': QgsWkbTypes.MultiPolygon
                }
                memory_layer = item['vector_layer']

                encoding = get_default_encoding()
                writer = QgsVectorFileWriter(outputs[layer], encoding,
                                             memory_layer.fields(),
                                             osm_geometries[layer],
                                             memory_layer.crs(), "GeoJSON")

                for f in memory_layer.getFeatures():
                    writer.addFeature(f)

                del writer

                # Loading the final vector file
                new_layer = QgsVectorLayer(outputs[layer], final_layer_name,
                                           "ogr")
            else:
                new_layer = item['vector_layer']
                new_layer.setName(final_layer_name)

            # Try to set styling if defined
            if config_outputs and config_outputs[layer]['style']:
                new_layer.loadNamedStyle(config_outputs[layer]['style'])
            else:
                # Loading default styles
                if layer == "multilinestrings" or layer == "lines":
                    if "colour" in item['tags']:
                        new_layer.loadNamedStyle(
                            join(dirname(dirname(abspath(__file__))), "styles",
                                 layer + "_colour.qml"))

            # Add action about OpenStreetMap
            actions = new_layer.actions()
            actions.addAction(
                QgsAction.OpenUrl, "OpenStreetMap Browser",
                'http://www.openstreetmap.org/browse/'
                '[% "osm_type" %]/[% "osm_id" %]', False)
            actions.addAction(
                QgsAction.GenericPython, 'JOSM',
                'from QuickOSM.CoreQuickOSM.Actions import Actions;'
                'Actions.run("josm","[% "full_id" %]")', False)
            actions.addAction(
                QgsAction.OpenUrl, "User default editor",
                'http://www.openstreetmap.org/edit?'
                '[% "osm_type" %]=[% "osm_id" %]', False)

            for link in ['url', 'website', 'wikipedia', 'ref:UAI']:
                if link in item['tags']:
                    link = link.replace(":", "_")
                    actions.addAction(
                        QgsAction.GenericPython, link,
                        'from QuickOSM.core.actions import Actions;'
                        'Actions.run("' + link + '","[% "' + link + '" %]")',
                        False)

            if 'network' in item['tags'] and 'ref' in item['tags']:
                actions.addAction(
                    QgsAction.GenericPython, "Sketchline",
                    'from QuickOSM.core.actions import Actions;'
                    'Actions.run_sketch_line("[% "network" %]","[% "ref" %]")',
                    False)

            QgsProject.instance().addMapLayer(new_layer)
            num_layers += 1

    return num_layers
Exemple #15
0
    def upload(self, db, data_sources_items, maxSize):
        import_ok = True
        layers_to_replace = {}
        raster_to_upload = {}

        self.status_bar.showMessage(
            self.tr("Uploading to database '{db}'...").format(db=db.database))
        QApplication.processEvents()

        messages = ""

        # Connect to database
        try:
            conn = db.psycopg_connection()
            cursor = conn.cursor()
        except Exception as e:
            raise RuntimeError("Connection to database failed %s" % str(e))

        for data_source, item in list(data_sources_items.items()):
            # Check available space, block if exceded
            size = DbConnections().db_size()

            if size > float(maxSize):
                QMessageBox.warning(
                    None, self.tr("Database full"),
                    self.
                    tr("You have exceeded the maximum database size for your current QGIS Cloud plan. Please free up some space or upgrade your QGIS Cloud plan."
                       ))
                break

            # Layers contains all layers with shared data source
            layer = item['layers'][0]
            if layer.type() == QgsMapLayer.VectorLayer:
                fields = QgsFields(layer.fields())
                srid = layer.crs().postgisSrid()
                geom_column = "wkb_geometry"
                wkbType = layer.wkbType()

                if wkbType == QgsWkbTypes.NoGeometry:
                    cloudUri = "dbname='%s' host=%s port=%d user='******' password='******' key='' table=\"public\".\"%s\"" % (
                        db.database, db.host, db.port, db.username,
                        db.password, item['table'])
                    geom_column = ""
                else:
                    if not QgsWkbTypes.isMultiType(wkbType):
                        wkbType = QgsWkbTypes.multiType(wkbType)

                    # Create table (pk='' => always generate a new primary key)
                    cloudUri = "dbname='%s' host=%s port=%d user='******' password='******' key='' table=\"public\".\"%s\" (%s)" % (
                        db.database, db.host, db.port, db.username,
                        db.password, item['table'], geom_column)

                self.progress_label.setText(
                    self.tr("Creating table '{table}'...").format(
                        table=item['table']))
                QApplication.processEvents()

                if wkbType != QgsWkbTypes.NoGeometry:
                    # Check if SRID is known on database, otherwise create record
                    cursor.execute(
                        "SELECT srid FROM public.spatial_ref_sys WHERE srid = %s"
                        % layer.crs().postgisSrid())
                    if not cursor.fetchone():
                        try:
                            cursor.execute(
                                "INSERT INTO public.spatial_ref_sys VALUES ({srid},'EPSG',{srid},'{wktstr}','{projstr}')"
                                .format(srid=layer.crs().postgisSrid(),
                                        wktstr=layer.crs().toWkt(),
                                        projstr=layer.crs().toProj4()))
                            conn.commit()
                        except Exception as e:
                            conn.rollback()
                            import_ok &= False
                            messages += "Failed to create SRS record on database: " + str(
                                e) + "\n"
                            continue

    #                cursor.close()

    # TODO: Ask user for overwriting existing table
    # The postgres provider is terribly slow at creating tables with
    # many attribute columns in QGIS < 2.9.0
                vectorLayerImport = PGVectorLayerImport(
                    db, conn, cursor, cloudUri, fields, wkbType, layer.crs(),
                    True)

                if vectorLayerImport.hasError():
                    import_ok &= False
                    messages += "VectorLayerImport-Error: " + vectorLayerImport.errorMessage(
                    ) + "\n"
                    continue

                vectorLayerImport = None

                # Build import string
                attribs = list(range(0, fields.count()))
                count = 0
                importstr = bytearray()
                ok = True

                self.progress_label.setText(self.tr("Uploading features..."))
                QApplication.processEvents()
                for feature in layer.getFeatures():
                    f_geometry = feature.geometry()
                    f_geometry.convertToMultiType()

                    # First field is primary key
                    importstr.extend(str(count).encode('utf-8'))
                    count += 1
                    if not feature.geometry():
                        if layer.isSpatial():
                            QgsMessageLog.logMessage(
                                self.
                                tr("Feature {id} of layer {layer} has no geometry"
                                   ).format(id=feature.id(),
                                            layer=layer.name()), "QGISCloud")
                            importstr.extend(b"\t" + b"\\N")
                    elif f_geometry.wkbType() != wkbType:
                        QgsMessageLog.logMessage(
                            self.
                            tr("Feature {id} of layer {layer} has wrong geometry type {type}"
                               ).format(id=feature.id(),
                                        layer=layer.name(),
                                        type=QgsWkbTypes.displayString(
                                            feature.geometry().wkbType())),
                            "QGISCloud")
                        importstr.extend(b"\t" + b"\\N")
                    else:
                        # Second field is geometry in EWKB Hex format
                        importstr.extend(
                            b"\t" +
                            self._wkbToEWkbHex(f_geometry.asWkb(), srid))

                    # Finally, copy data attributes
                    for attrib in attribs:
                        val = feature[attrib]
                        if val is None or isinstance(val, QVariant):
                            val = b"\\N"
                        elif isinstance(val, QDate) or isinstance(
                                val, QDateTime):
                            val = bytearray(
                                val.toString(Qt.ISODate).encode('utf-8'))
                            if not val:
                                val = b"\\N"
                        else:
                            val = bytearray(str(val).encode('utf-8'))
                            val = val.replace(b'\x00', b'?')
                            val = val.replace(b'\t', b"E'\t'")
                            val = val.replace(b'\n', b"E'\n'")
                            val = val.replace(b'\r', b"E'\r'")
                            val = val.replace(b'\\', b"\\")
                        importstr += b"\t" + val

                    importstr += b"\n"

                    # Upload in chunks
                    if (count % 100) == 0:
                        try:
                            cursor.copy_from(
                                StringIO(importstr.decode('utf-8')),
                                '"public"."%s"' % item['table'])
                        except Exception as e:
                            messages += str(e) + "\n"
                            ok = False
                            break

                        importstr = bytearray()
                        self.progress_label.setText(
                            self.tr(
                                "{table}: {count} features uploaded").format(
                                    table=item['table'], count=count))
                        QApplication.processEvents()
                    # Periodically update ui
                    if (count % 10) == 0:
                        QApplication.processEvents()

                if ok and importstr:
                    try:
                        cursor.copy_from(StringIO(importstr.decode('utf-8')),
                                         '"public"."%s"' % item['table'])
                    except Exception as e:
                        messages += str(e) + "\n"
                        ok = False

                if ok:
                    try:
                        conn.commit()
                    except Exception as e:
                        messages += str(e) + "\n"
                        ok = False
                else:
                    conn.rollback()

                import_ok &= ok

                if ok:
                    for layer in item['layers']:
                        layers_to_replace[layer.id()] = {
                            'layer': layer,
                            'data_source': data_source,
                            'db_name': db.database,
                            'table_name': item['table'],
                            'geom_column': geom_column
                        }

                if wkbType != QgsWkbTypes.NoGeometry:
                    sql = 'create index "%s_%s_idx" on "public"."%s" using gist ("%s");' % (
                        item['table'], geom_column, item['table'], geom_column)
                    cursor.execute(sql)
                    conn.commit()

            elif layer.type() == QgsMapLayer.RasterLayer:
                raster_to_upload = {
                    'layer': layer,
                    'data_source': layer.source(),
                    'db_name': db.database,
                    'table_name': item['table'],
                    'geom_column': 'rast'
                }
                RasterUpload(conn, cursor, raster_to_upload, maxSize,
                             self.progress_label)
                layers_to_replace[layer.id()] = raster_to_upload

        sql = """SELECT 'SELECT SETVAL(' || quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||  
                            ', COALESCE(MAX(' ||quote_ident(C.attname)|| ')+1, 1) ) 
                                FROM ' || quote_ident(PGT.schemaname)|| '.' ||quote_ident(T.relname)|| ';' 
                        FROM pg_class AS S,      pg_depend AS D,      pg_class AS T,      pg_attribute AS C,      
                             pg_tables AS PGT, pg_namespace as PGNS 
                        WHERE S.relkind = 'S'     
                          AND S.oid = D.objid     
                          AND S.relnamespace = PGNS.oid 
                          AND PGNS.nspname = 'public'     
                          AND D.refobjid = T.oid     
                          AND D.refobjid = C.attrelid     
                          AND D.refobjsubid = C.attnum     
                          AND T.relname = PGT.tablename     
                          AND schemaname = 'public'     
                          AND tablename = '%s' ORDER BY S.relname;""" % (
            item['table'])

        cursor.execute(sql)
        rows = cursor.fetchall()

        for row in rows:
            cursor.execute(row[0])

        cursor.close()
        conn.close()
        self._replace_local_layers(layers_to_replace)
        self.progress_label.setText("")
        if not import_ok:
            raise RuntimeError(str(messages))
    def run_stats(self):
        self.progressBar_stats.setValue(0)
        self.label_progressStats.setText('')
        # noinspection PyArgumentList
        QApplication.processEvents()

        blurred_layer = self.comboBox_blurredLayer.currentLayer()
        stats_layer = self.comboBox_statsLayer.currentLayer()

        try:

            if not blurred_layer or not stats_layer:
                raise NoLayerProvidedException

            crs_blurred_layer = blurred_layer.crs()
            crs_stats_layer = stats_layer.crs()

            if crs_blurred_layer != crs_stats_layer:
                raise DifferentCrsException(
                    epsg1=crs_blurred_layer.authid(),
                    epsg2=crs_stats_layer.authid())

            if blurred_layer == stats_layer:
                raise NoLayerProvidedException

            if not blurred_layer or not stats_layer:
                raise NoLayerProvidedException

            nb_feature_stats = stats_layer.featureCount()
            nb_feature_blurred = blurred_layer.featureCount()
            features_stats = {}

            label_preparing = tr('Preparing index on the stats layer')
            label_creating = tr('Creating index on the stats layer')
            label_calculating = tr('Calculating')

            if Qgis.QGIS_VERSION_INT < 20700:
                self.label_progressStats.setText('%s 1/3' % label_preparing)

                for i, feature in enumerate(stats_layer.getFeatures()):
                    features_stats[feature.id()] = feature
                    percent = int((i + 1) * 100 / nb_feature_stats)
                    self.progressBar_stats.setValue(percent)
                    # noinspection PyArgumentList
                    QApplication.processEvents()

                self.label_progressStats.setText('%s 2/3' % label_creating)
                # noinspection PyArgumentList
                QApplication.processEvents()
                index = QgsSpatialIndex()
                for i, f in enumerate(stats_layer.getFeatures()):
                    index.insertFeature(f)

                    percent = int((i + 1) * 100 / nb_feature_stats)
                    self.progressBar_stats.setValue(percent)
                    # noinspection PyArgumentList
                    QApplication.processEvents()

                self.label_progressStats.setText('%s 3/3' % label_calculating)

            else:
                # If QGIS >= 2.7, we can speed up the spatial index.
                # From 1 min 15 to 7 seconds on my PC.
                self.label_progressStats.setText('%s 1/2' % label_creating)
                # noinspection PyArgumentList
                QApplication.processEvents()
                index = QgsSpatialIndex(stats_layer.getFeatures())
                self.label_progressStats.setText('%s 2/2' % label_calculating)

            # noinspection PyArgumentList
            QApplication.processEvents()
            self.tab = []
            for i, feature in enumerate(blurred_layer.getFeatures()):
                count = 0
                ids = index.intersects(feature.geometry().boundingBox())
                for unique_id in ids:
                    request = QgsFeatureRequest().setFilterFid(unique_id)
                    f = next(stats_layer.getFeatures(request))

                    if f.geometry().intersects(feature.geometry()):
                        count += 1
                self.tab.append(count)

                percent = int((i + 1) * 100 / nb_feature_blurred)
                self.progressBar_stats.setValue(percent)
                # noinspection PyArgumentList
                QApplication.processEvents()

            stats = Stats(self.tab)

            items_stats = [
                'Count(blurred),%d' % nb_feature_blurred,
                'Count(stats),%d' % nb_feature_stats,
                'Min,%d' % stats.min(),
                'Average,%f' % stats.average(),
                'Max,%d' % stats.max(), 'Median,%f' % stats.median(),
                'Range,%d' % stats.range(),
                'Variance,%f' % stats.variance(),
                'Standard deviation,%f' % stats.standard_deviation()
            ]

            self.tableWidget.clear()
            self.tableWidget.setColumnCount(2)
            labels = ['Parameters', 'Values']
            self.tableWidget.setHorizontalHeaderLabels(labels)
            self.tableWidget.setRowCount(len(items_stats))

            for i, item in enumerate(items_stats):
                s = item.split(',')
                self.tableWidget.setItem(i, 0, QTableWidgetItem(s[0]))
                self.tableWidget.setItem(i, 1, QTableWidgetItem(s[1]))
            self.tableWidget.resizeRowsToContents()

            self.draw_plot(self.tab)

        except GeoPublicHealthException as e:
            self.label_progressStats.setText('')
            display_message_bar(msg=e.msg, level=e.level, duration=e.duration)
    def wkblify_raster_level(self, options, ds, level, band_range, infile, i):

        band_from = band_range[0]
        band_to = band_range[1]

        # Collect raster and block dimensions
        raster_size = (ds.RasterXSize, ds.RasterYSize)
        if options['block_size'] is not None:
            block_size = self.parse_block_size(options, ds)
            read_block_size = (block_size[0] * level, block_size[1] * level)
            grid_size = self.calculate_grid_size(raster_size, read_block_size)
        else:
            block_size = raster_size  # Whole raster as a single block
            read_block_size = block_size
            grid_size = (1, 1)

        gen_table = options['table']

        # Write (original) raster to hex binary output
        tile_count = 0
        hexwkb = ''
        self.progress_label.setText(self.tr("Uploading tiles..."))
        importString = ""
        sum_tiles = grid_size[0] * grid_size[1]

        copy_size = 500

        for ycell in range(0, grid_size[1]):
            for xcell in range(0, grid_size[0]):

                xoff = xcell * read_block_size[0]
                yoff = ycell * read_block_size[1]

                if options['block_size'] is not None:
                    hexwkb = ''  # Reset buffer as single INSERT per tile is generated
                    hexwkb += self.wkblify_raster_header(
                        options, ds, level, (xoff, yoff), block_size[0],
                        block_size[1])
                else:
                    hexwkb += self.wkblify_raster_header(
                        options, ds, level, (xoff, yoff))

                for b in range(band_from, band_to):
                    band = ds.GetRasterBand(b)

                    hexwkb += self.wkblify_band_header(options, band)
                    hexwkb += self.wkblify_band(options, band, level, xoff,
                                                yoff, read_block_size,
                                                block_size, infile, b)

                # Creating COPY String
                importString += str(tile_count) + "\t" + hexwkb + "\n"
                tile_count = tile_count + 1

                # Periodically update ui
                if (tile_count % copy_size) == 0:
                    self.cursor.copy_from(StringIO(importString),
                                          '"public"."%s"' % gen_table)
                    importString = ""
                    self.progress_label.setText(
                        self.tr(
                            "{table}: {count} of {sum_tiles} tiles uploaded").
                        format(table=gen_table,
                               count=tile_count,
                               sum_tiles=sum_tiles))

                    QApplication.processEvents()

        self.cursor.copy_from(StringIO(importString),
                              '"public"."%s"' % gen_table)
        self.conn.commit()

        self.progress_label.setText(
            self.tr("Calculating raster params for {sum_tiles} tiles ...").
            format(sum_tiles=sum_tiles))
        QApplication.processEvents()

        self.cursor.execute(self.make_sql_addrastercolumn(options))
        self.conn.commit()

        return (gen_table, tile_count)
Exemple #18
0
    def run_query(self):
        """
        Process for running the query
        """

        # Block the button and save the initial text
        self.output_directory.setDisabled(True)
        self.pushButton_generateQuery.setDisabled(True)
        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.start_process()
        QApplication.processEvents()

        # Get all values
        query = self.textEdit_query.toPlainText()
        output_directory = self.output_directory.filePath()
        prefix_file = self.lineEdit_filePrefix.text()
        nominatim = self.nominatim_value()

        # Set bbox
        bbox = None
        if self.cb_query_type.isEnabled():
            query_type = self.cb_query_type.currentData()
            if query_type in ['layer', 'canvas']:
                nominatim = None
                bbox = self.get_bounding_box()

        # Check nominatim
        if nominatim == '':
            nominatim = None

        # Which geometry at the end ?
        output_geometry_types = self.get_output_geometry_types()
        white_list_values = self.get_white_list_values()

        try:
            # Test values
            if not output_geometry_types:
                raise OutPutGeomTypesException

            if output_directory and not isdir(output_directory):
                raise DirectoryOutPutException

            if not nominatim and \
                    re.search(r'\{\{nominatim\}\}', query) or \
                    re.search(r'\{\{nominatimArea:\}\}', query) or \
                    re.search(r'\{\{geocodeArea:\}\}', query):

                raise MissingParameterException(suffix="nominatim field")

            num_layers = process_query(
                dialog=self,
                query=query,
                output_dir=output_directory,
                prefix_file=prefix_file,
                output_geometry_types=output_geometry_types,
                white_list_values=white_list_values,
                nominatim=nominatim,
                bbox=bbox)

            if num_layers:
                display_message_bar(
                    tr('Successful query'),
                    level=Qgis.Success,
                    duration=5)
                self.label_progress.setText(
                    tr('Successful query'))
            else:
                display_message_bar(
                    tr('Successful query, but no result.'),
                    level=Qgis.Warning,
                    duration=7)

        except QuickOsmException as e:
            self.display_geo_algorithm_exception(e)
            pass
        except Exception as e:  # pylint: disable=broad-except
            self.display_exception(e)
            pass

        finally:
            # Resetting the button
            self.output_directory.setDisabled(False)
            self.pushButton_generateQuery.setDisabled(False)
            QApplication.restoreOverrideCursor()
            self.end_process()
            QApplication.processEvents()
Exemple #19
0
    def _init_gui(self):
        # Setup base elements
        self.gridLayout = QGridLayout(self)
        self.gridLayout.setObjectName('glMain')
        self.gridLayout.addLayout(self.vlNotification, 0, 0, 1, 1)
        QApplication.processEvents()

        # set widgets values
        column_widget_area = self._setup_columns_content_area()

        self.gridLayout.addWidget(column_widget_area, 1, 0, 1, 1)

        QApplication.processEvents()
        # Add notification for mandatory columns if applicable
        next_row = 2
        if self.has_mandatory:
            self.required_fields_lbl = QLabel(self)
            msg = self.tr('Please fill out all required (*) fields.')
            msg = self._highlight_asterisk(msg)
            self.required_fields_lbl.setText(msg)
            self.gridLayout.addWidget(self.required_fields_lbl, next_row, 0, 1,
                                      2)
            # Bump up row reference
            next_row += 1

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setObjectName('buttonBox')
        self.gridLayout.addWidget(self.buttonBox, next_row, 0, 1, 1)

        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Save)

        if self.edit_model is None:
            if not self.collect_model:
                self.save_new_button = QPushButton(
                    QApplication.translate('EntityEditorDialog',
                                           'Save and New'))
                self.buttonBox.addButton(self.save_new_button,
                                         QDialogButtonBox.ActionRole)

        # edit model, collect model
        # adding new record for child

        # Saving in parent editor
        if not isinstance(self._parent._parent, EntityEditorDialog):
            # adding a new record
            if self.edit_model is None:
                # saving when digitizing.
                if self.collect_model:
                    self.buttonBox.accepted.connect(self.on_model_added)
                # saving parent editor
                else:
                    self.buttonBox.accepted.connect(self.save_parent_editor)
                    self.save_new_button.clicked.connect(self.save_and_new)
            # updating existing record
            else:
                if not self.collect_model:
                    # updating existing record of the parent editor
                    self.buttonBox.accepted.connect(self.save_parent_editor)
                else:
                    self.buttonBox.accepted.connect(self.on_model_added)
        # Saving in child editor
        else:
            # save and new record
            if self.edit_model is None:
                self.buttonBox.accepted.connect(self.on_child_saved)
                self.save_new_button.clicked.connect(
                    lambda: self.on_child_saved(True))

            else:
                # When updating an existing child editor save to the db
                self.buttonBox.accepted.connect(self.on_child_saved)
                # self.buttonBox.accepted.connect(self.submit)

        self.buttonBox.rejected.connect(self.cancel)
Exemple #20
0
    def run_query(self):
        """
        Process for running the query
        """

        # Block the button and save the initial text
        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.output_directory.setDisabled(True)
        self.pushButton_showQuery.setDisabled(True)
        self.start_process()
        QApplication.processEvents()

        # Get all values
        key = self.comboBox_key.currentText()
        value = self.comboBox_value.currentText()
        nominatim = self.nominatim_value()
        timeout = self.spinBox_timeout.value()
        output_directory = self.output_directory.filePath()
        prefix_file = self.lineEdit_filePrefix.text()

        query_type = self.cb_query_type.currentData()
        is_around = query_type == 'around'
        distance = self.spinBox_distance_point.value()

        # Which geometry at the end ?
        output_geometry_types = self.get_output_geometry_types()

        # Which osm objects ?
        osm_objects = self._get_osm_objects()

        try:
            # Test values
            if not osm_objects:
                raise OsmObjectsException

            if not output_geometry_types:
                raise OutPutGeomTypesException

            # If bbox, we must set None to nominatim, we can't have both
            bbox = None
            if query_type in ['layer', 'canvas']:
                nominatim = None
                bbox = self.get_bounding_box()

            if nominatim == '':
                nominatim = None

            if output_directory and not isdir(output_directory):
                raise DirectoryOutPutException

            num_layers = process_quick_query(
                dialog=self,
                key=key,
                value=value,
                nominatim=nominatim,
                is_around=is_around,
                distance=distance,
                bbox=bbox,
                osm_objects=osm_objects,
                timeout=timeout,
                output_directory=output_directory,
                prefix_file=prefix_file,
                output_geometry_types=output_geometry_types)

            # We can test numLayers to see if there are some results
            if num_layers:
                self.label_progress.setText(
                    tr('Successful query'))

                display_message_bar(
                    tr('Successful query'),
                    level=Qgis.Success,
                    duration=5)
            else:
                self.label_progress.setText(tr('No result'))

                display_message_bar(
                    tr('Successful query, but no result.'),
                    level=Qgis.Warning,
                    duration=7)

        except QuickOsmException as e:
            self.display_geo_algorithm_exception(e)
        except Exception as e:  # pylint: disable=broad-except
            self.display_exception(e)

        finally:
            # Resetting the button
            self.output_directory.setDisabled(False)
            self.pushButton_showQuery.setDisabled(False)
            QApplication.restoreOverrideCursor()
            self.end_process()
            QApplication.processEvents()
Exemple #21
0
    def on_btnRun_clicked(self):

        #Check for combo and list box selections
        if self.ui.cmbBaseLayer.count() < 1 or self.ui.cmbProcessLayer.count(
        ) < 1:
            QMessageBox.critical(self, 'Vector Geoprocessor',
                                 'Invalid layer selection.')
            return
        if len(self.ui.listFields.selectedItems()) < 1:
            QMessageBox.critical(self, 'Vector Geoprocessor',
                                 'Invalid field selection.')
            return

        #Initializations
        self.ui.ProgressBar.setValue(0)
        self.setCursor(Qt.WaitCursor)
        data = []

        #Add new attributes to base layer
        bprovider = self.blayer.dataProvider()
        pprovider = self.player.dataProvider()
        pfields = pprovider.fields()
        for item in self.ui.listFields.selectedItems():
            fname = item.text()
            for fld in pfields.toList():
                if fname == fld.name():
                    newfield = QgsField()
                    newfield.setName(fld.name())
                    newfield.setType(fld.type())
                    newfield.setTypeName(fld.typeName())
                    newfield.setLength(fld.length())
                    newfield.setPrecision(fld.precision())
                    newfield.setComment(fld.comment())
                    bprovider.addAttributes([newfield])

        #Create a spatial index for faster processing
        spindex = QgsSpatialIndex()
        for pfeat in pprovider.getFeatures():
            spindex.insertFeature(pfeat)

        #Find the intersection of process layer features with base layer
        #To increase speed, intersect with a bounding box rectangle first
        #Then further process within the geometric shape
        #Add requested processed information to base layer
        featreq = QgsFeatureRequest()
        bfields = bprovider.fields()
        ddic = {}
        len1 = len(self.ui.listFields.selectedItems())
        len2 = len(bfields)
        b1 = 0
        b2 = bprovider.featureCount()
        attr = {}
        for bfeat in bprovider.getFeatures():
            b1 += 1
            attr.clear()
            bgeom = bfeat.geometry()
            intersect = spindex.intersects(bgeom.boundingBox())
            data[:] = []
            for fid in intersect:
                pfeat = next(self.player.getFeatures(
                    featreq.setFilterFid(fid)))
                if pfeat.geometry().intersects(bgeom) == False:
                    data.append(fid)
            for fid in data:
                intersect.pop(intersect.index(fid))

            count = 0
            for item in self.ui.listFields.selectedItems():
                pfindx = pprovider.fieldNameIndex(item.text())
                if pfindx < 0:
                    self.setCursor(Qt.ArrowCursor)
                    QMessageBox.critical(self, 'Vector Geoprocessor',
                                         'Processing error.')
                    return
                data[:] = []
                for fid in intersect:
                    pfeat = next(
                        self.player.getFeatures(featreq.setFilterFid(fid)))
                    if self.oindex in [0, 1, 2, 3, 4]:
                        data.append(float(pfeat.attribute(item.text())))
                    elif self.oindex in [5, 6]:
                        data.append(str(pfeat.attribute(item.text())))
                if len(data) == 0:
                    value = None
                elif self.oindex == 0:  #Find mean value of points within polygons
                    value = sum(data) / float(len(data))
                elif self.oindex == 1:  #Find median value of points within polygons
                    data = sorted(data)
                    lendata = len(data)
                    if lendata % 2:
                        value = data[(lendata + 1) / 2 - 1]
                    else:
                        d1 = data[lendata / 2 - 1]
                        d2 = data[lendata / 2]
                        value = (d1 + d2) / 2.0
                elif self.oindex == 2:  #Find maximum value of points within polygons
                    value = max(data)
                elif self.oindex == 3:  #Find minimum value of points within polygons
                    value = min(data)
                elif self.oindex == 4:  #Find mean value (area-weighted) of polygons within polygons
                    value = 0.0
                    totalarea = 0.0
                    for fid in intersect:
                        pfeat = next(
                            self.player.getFeatures(featreq.setFilterFid(fid)))
                        pgeom = pfeat.geometry()
                        isect = bgeom.intersection(pgeom)
                        parea = isect.area()
                        value += (float(pfeat.attribute(item.text()) * parea))
                        totalarea += parea
                    value = value / totalarea
                elif self.oindex == 5:  #Find largest area polygon within polygons
                    data = list(set(data))  #Get unique items in data
                    ddic.clear()
                    for i in data:
                        ddic.update({i: 0.0})
                    for fid in intersect:
                        pfeat = next(
                            self.player.getFeatures(featreq.setFilterFid(fid)))
                        pgeom = pfeat.geometry()
                        isect = bgeom.intersection(pgeom)
                        parea = isect.area()
                        key = str(pfeat.attribute(item.text()))
                        parea = parea + ddic[key]
                        ddic.update({key: parea})
                    parea = -1
                    for key in list(ddic.keys()):
                        if ddic[key] > parea:
                            parea = ddic[key]
                            value = key
                elif self.oindex == 6:  #Add polygon attribute to points
                    if len(data) != 1:
                        QMessageBox.warning(
                            self, 'Vector Geoprocessor',
                            'Point intersects more than one polygon.')
                    value = data[0]

                attr.update({(len2 - len1 + count): value})
                count += 1
            result = bprovider.changeAttributeValues({bfeat.id(): attr})
            if not result:
                QMessageBox.critical(self, 'Vector Geoprocessor',
                                     'Could not change attribute value.')
                return
            self.ui.ProgressBar.setValue(float(b1) / float(b2) * 100.0)
            QApplication.processEvents()

        self.setCursor(Qt.ArrowCursor)
    def __init__(self, conn, cursor, raster, max_size, progress_label):
        QObject.__init__(self)
        self.cursor = cursor
        self.conn = conn
        self.progress_label = progress_label
        self.messages = ""

        opts = {}
        opts['version'] = g_rt_version
        opts['endian'] = NDR
        opts['column'] = 'rast'
        opts['create_table'] = 1
        opts['drop_table'] = 1
        opts['overview_level'] = 1
        opts['block_size'] = 'auto'
        opts['band'] = None
        opts['register'] = None

        # Create PostGIS Raster Tool Functions
        raster_tools_file = "%s/raster_tools.sql" % os.path.dirname(__file__)
        sql = open(raster_tools_file).read().encode('ascii', errors='ignore')
        self.cursor.execute(sql)
        self.conn.commit()

        i = 0

        # Burn all specified input raster files into single WKTRaster table
        gt = None
        layer_info = raster
        opts['srid'] = layer_info['layer'].dataProvider().crs().postgisSrid()
        infile = layer_info['data_source']

        file_info = QFileInfo(infile)
        file_size = file_info.size()
        size = DbConnections().db_size()
        file_size /= 1024 * 1024
        size = size + file_size

        if size > float(max_size):
            QMessageBox.warning(
                None, self.tr("Database full"),
                self.
                tr("Upload would exceeded the maximum database size for your current QGIS Cloud plan. Please free up some space or upgrade your QGIS Cloud plan."
                   ))
            return False

        opts['table'] = layer_info['table_name']

        self.progress_label.setText(
            self.tr("Creating table '{table}'...").format(table=opts['table']))
        QApplication.processEvents()

        self.cursor.execute(self.make_sql_drop_raster_table(opts['table']))
        self.conn.commit()

        self.cursor.execute(self.make_sql_create_table(opts, opts['table']))
        self.conn.commit()

        gt = self.wkblify_raster(opts, infile.replace('\\', '/'), i, gt)
        i += 1

        self.cursor.execute(
            self.make_sql_create_gist(opts['table'], opts['column']))
        self.conn.commit()

        # create raster overviews
        for level in [4, 8, 16, 32]:

            sql = 'drop table if exists o_%d_%s' % (level, opts['table'])
            self.cursor.execute(sql)
            self.conn.commit()

            sql = "select st_createoverview_qgiscloud('%s'::regclass, '%s'::name, %d)" % (
                opts['table'], opts['column'], level)
            self.progress_label.setText(
                self.tr(
                    "Creating overview-level {level} for table '{table}'...").
                format(level=level, table=opts['table']))
            QApplication.processEvents()
            self.cursor.execute(sql)
            self.conn.commit()

            index_table = 'o_' + str(level) + '_' + opts['table']
            self.cursor.execute(
                self.make_sql_create_gist(index_table, opts['column']))
            self.conn.commit()

        self.progress_label.setText(
            self.tr("Registering raster columns of table '%s'..." %
                    (opts['table'])))
        QApplication.processEvents()
        self.cursor.execute(self.make_sql_addrastercolumn(opts))
        self.conn.commit()
Exemple #23
0
    def run_query(self):
        """
        Process for running the query
        """

        # Block the button and save the initial text
        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.output_directory.setDisabled(True)
        self.pushButton_showQuery.setDisabled(True)
        self.start_process()
        QApplication.processEvents()

        # Get all values
        key = str(self.comboBox_key.currentText())
        value = str(self.comboBox_value.currentText())
        nominatim = self.nominatim_value()
        timeout = self.spinBox_timeout.value()
        output_directory = self.output_directory.filePath()
        prefix_file = self.lineEdit_filePrefix.text()
        if self.comboBox_in_around.currentIndex() == 1:
            is_around = True
        else:
            is_around = False
        distance = self.spinBox_distance_point.value()

        # Which geometry at the end ?
        output_geometry_types = self.get_output_geometry_types()

        # Which osm objects ?
        osm_objects = self._get_osm_objects()

        try:
            # Test values
            if not osm_objects:
                raise OsmObjectsException

            if not output_geometry_types:
                raise OutPutGeomTypesException

            # If bbox, we must set None to nominatim, we can't have both
            bbox = None
            if self.radioButton_extentLayer.isChecked() or \
                    self.radioButton_extentMapCanvas.isChecked():
                nominatim = None
                bbox = self.get_bounding_box()

            if nominatim == '':
                nominatim = None

            if output_directory and not isdir(output_directory):
                raise DirectoryOutPutException

            num_layers = process_quick_query(
                dialog=self,
                key=key,
                value=value,
                nominatim=nominatim,
                is_around=is_around,
                distance=distance,
                bbox=bbox,
                osm_objects=osm_objects,
                timeout=timeout,
                output_directory=output_directory,
                prefix_file=prefix_file,
                output_geometry_types=output_geometry_types)

            # We can test numLayers to see if there are some results
            if num_layers:
                self.label_progress.setText(
                    tr('QuickOSM', u'Successful query !'))

                display_message_bar(tr('QuickOSM', u'Successful query !'),
                                    level=Qgis.Success,
                                    duration=5)
            else:
                self.label_progress.setText(tr("QuickOSM", u'No result'))

                display_message_bar(tr('QuickOSM',
                                       u'Successful query, but no result.'),
                                    level=Qgis.Warning,
                                    duration=7)

        except QuickOsmException as e:
            self.display_geo_algorithm_exception(e)
        except Exception as e:  # pylint: disable=broad-except
            self.display_exception(e)

        finally:
            # Resetting the button
            self.output_directory.setDisabled(False)
            self.pushButton_showQuery.setDisabled(False)
            QApplication.restoreOverrideCursor()
            self.end_process()
            QApplication.processEvents()
Exemple #24
0
    def compute(self):
        from AcATaMa.gui.acatama_dockwidget import AcATaMaDockWidget as AcATaMa
        AcATaMa.dockwidget.QPBtn_ComputeViewAccurasyAssessment.setText("Processing, please wait ...")
        QApplication.processEvents()

        # get labels from classification buttons
        labels = {}
        for button_config in self.classification.buttons_config.values():
            labels[button_config["thematic_class"]] = button_config["name"]

        # get the classified and thematic map values
        thematic_map_values = []
        classified_values = []
        samples_outside_the_thematic = []
        classification_points = [point for point in self.classification.points if point.is_classified]
        points_ordered = sorted(classification_points, key=lambda p: p.shape_id)
        for point in points_ordered:
            # classification from the pixel values in the thematic map
            thematic_map_value = self.ThematicR.get_pixel_value_from_pnt(point.QgsPnt)
            if not thematic_map_value:
                samples_outside_the_thematic.append(point)
                continue
            thematic_map_values.append(int(thematic_map_value))
            # classified value made/checked by user with classification buttons
            classified_value = self.classification.buttons_config[point.classif_id]["thematic_class"]
            classified_values.append(int(classified_value))

        # all unique and sorted values
        values = sorted(set(thematic_map_values + classified_values))
        # Construct a value->index dictionary
        indices = dict((val, i) for (i, val) in enumerate(values))

        # calculate the error/confusion matrix
        # https://github.com/nltk/nltk/blob/develop/nltk/metrics/confusionmatrix.py
        #
        #             classified
        #   t |    | L1 | L2 | L3 | L4 |
        #   h | L1 |    |    |    |    |
        #   e | L2 |    |    |    |    |
        #   m | L3 |    |    |    |    |
        #   a | L4 |    |    |    |    |
        #
        error_matrix = [[0 for column in values] for row in values]
        for thematic, classified in zip(thematic_map_values, classified_values):
            error_matrix[indices[thematic]][indices[classified]] += 1

        # calculate the total number of pixel in the thematic raster
        # by each thematic raster class used in the classification buttons
        for thematic_map_value in values:
            if thematic_map_value not in self.thematic_pixels_count:
                self.thematic_pixels_count[thematic_map_value] = self.ThematicR.get_total_pixels_by_value(thematic_map_value)

        # values necessary for results
        self.values = values
        self.labels = labels
        self.error_matrix = error_matrix
        self.samples_outside_the_thematic = samples_outside_the_thematic
        # set area by pixel
        self.pixel_area_base = self.ThematicR.qgs_layer.rasterUnitsPerPixelX() * self.ThematicR.qgs_layer.rasterUnitsPerPixelY()
        self.pixel_area_value = self.pixel_area_base * QgsUnitTypes.fromUnitToUnitFactor(self.base_area_unit, self.area_unit)
        self.pixel_area_unit = QgsUnitTypes.toAbbreviatedString(self.area_unit)
Exemple #25
0
from QGIS_FMV.utils.QgsFmvInstaller import WindowsInstaller
import platform
windows = platform.system() == 'Windows'
from QGIS_FMV.utils.QgsUtils import QgsUtils as qgsu
from qgis.PyQt.QtWidgets import QMessageBox
from qgis.utils import iface
from qgis.utils import reloadPlugin
from qgis.core import Qgis as QGis
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtWidgets import QApplication

# Check dependencies
if windows:
    try:
        QApplication.setOverrideCursor(Qt.PointingHandCursor)
        QApplication.processEvents()
        WindowsInstaller()
        reloadPlugin('QGIS_FMV')
        iface.messageBar().pushMessage(
            "QGIS FMV", "QGIS Full Motion Video installed correctly",
            QGis.Info, 3)
        QApplication.restoreOverrideCursor()
    except Exception as e:
        QApplication.restoreOverrideCursor()
        None
#         buttonReply = qgsu.CustomMessage("QGIS FMV", "", "you need to restart your QGIS,Do you really close?", icon="Information")
#         if buttonReply == QMessageBox.Yes:
#             # TODO : Restart QGIS
#             iface.actionExit().trigger()

Exemple #26
0
def ExpandLayer(layer, value=True):
    '''Collapse/Expand layer'''
    ltl = QgsProject.instance().layerTreeRoot().findLayer(layer.id())
    ltl.setExpanded(value)
    QApplication.processEvents()
    return
Exemple #27
0
 def set_progress_percentage(self, percent):
     """Slot to update percentage during process."""
     self.progress_bar.setValue(percent)
     QApplication.processEvents()
Exemple #28
0
    def CreateMISB(self):
        ''' Create MISB Video '''
        ''' Only tested using DJI Data '''
        # Create ProgressBar
        self.iface.messageBar().clearWidgets()
        progressMessageBar = self.iface.messageBar().createMessage(
            "Creating video packets...")
        progress = QProgressBar()
        progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        progressMessageBar.layout().addWidget(progress)
        self.iface.messageBar().pushWidget(progressMessageBar, QGis.Info)

        QApplication.setOverrideCursor(Qt.WaitCursor)
        QApplication.processEvents()

        HFOV = self.sp_hfov.value()

        index = self.cmb_telemetry.currentIndex()
        out_record = self.cmb_telemetry.itemData(index)
        rowCount = self.GetRows(out_record)
        progress.setMaximum(rowCount)

        d = {}
        with open(out_record, encoding=encoding) as csvfile:
            reader = csv.DictReader(csvfile)
            for row in reader:
                date_start = datetime.strptime(row["CUSTOM.updateTime"],
                                               '%Y/%m/%d %H:%M:%S.%f')
                break

        with open(out_record, encoding=encoding) as csvfile:
            reader = csv.DictReader(csvfile)
            for row in reader:
                for k in row:
                    stripK = k.strip()
                    stripV = row[k].strip()
                    d[stripK] = stripV

                # We create the klv file for every moment
                sizeTotal = 0
                bufferData = b''
                cnt = 0

                for k, v in d.items():
                    try:
                        if k == "CUSTOM.updateTime":
                            # We prevent it from failing in the exact times that don't have milliseconds
                            try:
                                date_end = datetime.strptime(
                                    v, '%Y/%m/%d %H:%M:%S.%f')
                            except:
                                date_end = datetime.strptime(
                                    v, '%Y/%m/%d %H:%M:%S')

                            _bytes = datetime_to_bytes(date_end)
                            _len = int_to_bytes(len(_bytes))
                            _bytes = _key2 + _len + _bytes
                            sizeTotal += len(_bytes)
                            bufferData += _bytes

                        # Platform Heading Angle
                        if k == "OSD.yaw":
                            OSD_yaw = float(v)
                            if OSD_yaw < 0:
                                OSD_yaw = OSD_yaw + 360
                            _bytes = float_to_bytes(round(OSD_yaw, 4),
                                                    _domain5, _range5)
                            _len = int_to_bytes(len(_bytes))
                            _bytes = _key5 + _len + _bytes
                            sizeTotal += len(_bytes)
                            bufferData += _bytes

                        # Platform Pitch Angle
                        if k == "OSD.pitch":
                            OSD_pitch = float(v)
                            _bytes = float_to_bytes(round(OSD_pitch, 4),
                                                    _domain6, _range6)
                            _len = int_to_bytes(len(_bytes))
                            _bytes = _key6 + _len + _bytes
                            sizeTotal += len(_bytes)
                            bufferData += _bytes

                        # Platform Roll Angle
                        if k == "OSD.roll":
                            OSD_roll = float(v)
                            _bytes = float_to_bytes(round(OSD_roll, 4),
                                                    _domain7, _range7)
                            _len = int_to_bytes(len(_bytes))
                            _bytes = _key7 + _len + _bytes
                            sizeTotal += len(_bytes)
                            bufferData += _bytes

                        # Sensor Latitude
                        if k == "OSD.latitude":
                            OSD_latitude = float(v)
                            _bytes = float_to_bytes(round(OSD_latitude, 4),
                                                    _domain13, _range13)
                            _len = int_to_bytes(len(_bytes))
                            _bytes = _key13 + _len + _bytes
                            sizeTotal += len(_bytes)
                            bufferData += _bytes

                        # Sensor Longitude
                        if k == "OSD.longitude":
                            OSD_longitude = float(v)
                            _bytes = float_to_bytes(OSD_longitude, _domain14,
                                                    _range14)
                            _len = int_to_bytes(len(_bytes))
                            _bytes = _key14 + _len + _bytes
                            sizeTotal += len(_bytes)
                            bufferData += _bytes

                        # Sensor True Altitude
                        if k == "OSD.altitude [m]":
                            OSD_altitude = float(v)
                            _bytes = float_to_bytes(round(OSD_altitude, 4),
                                                    _domain15, _range15)
                            _len = int_to_bytes(len(_bytes))
                            _bytes = _key15 + _len + _bytes
                            sizeTotal += len(_bytes)
                            bufferData += _bytes

                        # Sensor Ellipsoid Height
                        if k == "OSD.height [m]":
                            OSD_height = float(v)
                            _bytes = float_to_bytes(round(OSD_height, 4),
                                                    _domain75, _range75)
                            _len = int_to_bytes(len(_bytes))
                            _bytes = _key75 + _len + _bytes
                            sizeTotal += len(_bytes)
                            bufferData += _bytes

                        # Sensor Relative Azimuth Angle
                        if k == "GIMBAL.yaw":
                            # GIMBAL_yaw = float(v)
                            GIMBAL_yaw = 0.0
                            _bytes = float_to_bytes(round(GIMBAL_yaw, 4),
                                                    _domain18, _range18)
                            _len = int_to_bytes(len(_bytes))
                            _bytes = _key18 + _len + _bytes
                            sizeTotal += len(_bytes)
                            bufferData += _bytes

                        # Sensor Relative Elevation Angle
                        if k == "GIMBAL.pitch":
                            GIMBAL_pitch = float(v)
                            _bytes = float_to_bytes(round(GIMBAL_pitch, 4),
                                                    _domain19, _range19)
                            _len = int_to_bytes(len(_bytes))
                            _bytes = _key19 + _len + _bytes
                            sizeTotal += len(_bytes)
                            bufferData += _bytes

                        # Sensor Relative Roll Angle
                        if k == "GIMBAL.roll":
                            GIMBAL_roll = float(v)
                            _bytes = float_to_bytes(round(GIMBAL_roll, 4),
                                                    _domain20, _range20)
                            _len = int_to_bytes(len(_bytes))
                            _bytes = _key20 + _len + _bytes
                            sizeTotal += len(_bytes)
                            bufferData += _bytes

                    except Exception:
                        print("Multiplexer error")
                        continue

                try:
                    # Diference time
                    td = date_end - date_start
                    end_path = self.klv_folder + "/%.1f.klv" % (round(
                        td.total_seconds(), 1))

                    # CheckSum
                    v = abs(hash(end_path)) % (10**4)
                    _bytes = int_to_bytes(v, 4)
                    _len = int_to_bytes(len(_bytes))
                    _bytes = _key1 + _len + _bytes
                    sizeTotal += len(_bytes)
                    bufferData += _bytes

                    # Sensor Horizontal Field of View
                    v = self.sp_hfov.value()
                    _bytes = float_to_bytes(float(v), _domain16, _range16)
                    _len = int_to_bytes(len(_bytes))
                    _bytes = _key16 + _len + _bytes
                    sizeTotal += len(_bytes)
                    bufferData += _bytes

                    # Sensor Vertical Field of View
                    v = self.sp_vfov.value()
                    _bytes = float_to_bytes(float(v), _domain17, _range17)
                    _len = int_to_bytes(len(_bytes))
                    _bytes = _key17 + _len + _bytes
                    sizeTotal += len(_bytes)
                    bufferData += _bytes

                    # TODO : Check these calculations
                    # Slant Range
                    anlge = 180 + (OSD_pitch + GIMBAL_pitch)
                    slantRange = abs(OSD_altitude / (cos(radians(anlge))))

                    _bytes = float_to_bytes(round(slantRange, 4), _domain21,
                                            _range21)
                    _len = int_to_bytes(len(_bytes))
                    _bytes = _key21 + _len + _bytes
                    sizeTotal += len(_bytes)
                    bufferData += _bytes

                    # Target Width
                    # targetWidth = 0.0
                    targetWidth = 2.0 * slantRange * tan(radians(HFOV / 2.0))

                    _bytes = float_to_bytes(round(targetWidth, 4), _domain22,
                                            _range22)
                    _len = int_to_bytes(len(_bytes))
                    _bytes = _key22 + _len + _bytes
                    sizeTotal += len(_bytes)
                    bufferData += _bytes

                    # Frame Center Latitude
                    angle = 90 + (OSD_pitch + GIMBAL_pitch)
                    tgHzDist = OSD_altitude * tan(radians(angle))
                    r_earth = 6371008.8

                    dy = tgHzDist * cos(radians(OSD_yaw))
                    framecenterlatitude = OSD_latitude + (dy /
                                                          r_earth) * (180 / pi)

                    _bytes = float_to_bytes(round(framecenterlatitude, 4),
                                            _domain23, _range23)
                    _len = int_to_bytes(len(_bytes))
                    _bytes = _key23 + _len + _bytes
                    sizeTotal += len(_bytes)
                    bufferData += _bytes

                    # Frame Center Longitude
                    dx = tgHzDist * sin(radians(OSD_yaw))
                    framecenterlongitude = OSD_longitude + (dx / r_earth) * (
                        180 / pi) / cos(OSD_latitude * pi / 180)

                    _bytes = float_to_bytes(round(framecenterlongitude, 4),
                                            _domain24, _range24)
                    _len = int_to_bytes(len(_bytes))
                    _bytes = _key24 + _len + _bytes
                    sizeTotal += len(_bytes)
                    bufferData += _bytes

                    # Frame Center Elevation
                    frameCenterElevation = 0.0

                    _bytes = float_to_bytes(frameCenterElevation, _domain25,
                                            _range25)
                    _len = int_to_bytes(len(_bytes))
                    _bytes = _key25 + _len + _bytes
                    sizeTotal += len(_bytes)
                    bufferData += _bytes

                    # TODO : If we save the corners in the klv have a overflow
                    #                     # CALCULATE CORNERS COORDINATES
                    #                     sensor = (OSD_longitude, OSD_latitude, OSD_altitude)
                    #                     frameCenter = (destPoint[0], destPoint[1], frameCenterElevation)
                    #                     FOV = (VFOV, HFOV)
                    #                     others = (OSD_yaw, GIMBAL_yaw, targetWidth, slantRange)
                    #                     cornerPointUL, cornerPointUR, cornerPointLR, cornerPointLL = CornerEstimationWithoutOffsets(sensor=sensor, frameCenter=frameCenter, FOV=FOV, others=others)
                    #
                    #                     # Corner Latitude Point 1 (Full)
                    #                     _bytes = float_to_bytes(round(cornerPointUL[0],4), _domain82, _range82)
                    #                     _len = int_to_bytes(len(_bytes))
                    #                     _bytes = _key82 + _len + _bytes
                    #                     sizeTotal += len(_bytes)
                    #                     bufferData += _bytes
                    #
                    #                     # Corner Longitude Point 1 (Full)
                    #                     _bytes = float_to_bytes(round(cornerPointUL[1],4), _domain83, _range83)
                    #                     _len = int_to_bytes(len(_bytes))
                    #                     _bytes = _key83 + _len + _bytes
                    #                     sizeTotal += len(_bytes)
                    #                     bufferData += _bytes
                    #
                    #                     # Corner Latitude Point 2 (Full)
                    #                     _bytes = float_to_bytes(round(cornerPointUR[0],4), _domain84, _range84)
                    #                     _len = int_to_bytes(len(_bytes))
                    #                     _bytes = _key84 + _len + _bytes
                    #                     sizeTotal += len(_bytes)
                    #                     bufferData += _bytes
                    #
                    #                     # Corner Longitude Point 2 (Full)
                    #                     _bytes = float_to_bytes(round(cornerPointUR[1],4), _domain85, _range85)
                    #                     _len = int_to_bytes(len(_bytes))
                    #                     _bytes = _key85 + _len + _bytes
                    #                     sizeTotal += len(_bytes)
                    #                     bufferData += _bytes
                    #
                    #                     # Corner Latitude Point 3 (Full)
                    #                     _bytes = float_to_bytes(round(cornerPointLR[0],4), _domain86, _range86)
                    #                     _len = int_to_bytes(len(_bytes))
                    #                     _bytes = _key86 + _len + _bytes
                    #                     sizeTotal += len(_bytes)
                    #                     bufferData += _bytes
                    #
                    #                     # Corner Longitude Point 3 (Full)
                    #                     _bytes = float_to_bytes(round(cornerPointLR[1],4), _domain87, _range87)
                    #                     _len = int_to_bytes(len(_bytes))
                    #                     _bytes = _key87 + _len + _bytes
                    #                     sizeTotal += len(_bytes)
                    #                     bufferData += _bytes
                    #
                    #                     # Corner Latitude Point 4 (Full)
                    #                     _bytes = float_to_bytes(round(cornerPointLL[0],4), _domain88, _range88)
                    #                     _len = int_to_bytes(len(_bytes))
                    #                     _bytes = _key88 + _len + _bytes
                    #                     sizeTotal += len(_bytes)
                    #                     bufferData += _bytes
                    #
                    #                     # Corner Longitude Point 4 (Full)
                    #                     _bytes = float_to_bytes(round(cornerPointLL[1],4), _domain89, _range89)
                    #                     _len = int_to_bytes(len(_bytes))
                    #                     _bytes = _key89 + _len + _bytes
                    #                     sizeTotal += len(_bytes)
                    #                     bufferData += _bytes

                    # Platform Pitch Angle (Full)
                    _bytes = float_to_bytes(round(OSD_pitch, 4), _domain90,
                                            _range90)
                    _len = int_to_bytes(len(_bytes))
                    _bytes = _key90 + _len + _bytes
                    sizeTotal += len(_bytes)
                    bufferData += _bytes

                    # Platform Roll Angle (Full)
                    _bytes = float_to_bytes(round(OSD_roll, 4), _domain91,
                                            _range91)
                    _len = int_to_bytes(len(_bytes))
                    _bytes = _key91 + _len + _bytes
                    sizeTotal += len(_bytes)
                    bufferData += _bytes

                    # set packet header
                    writeData = cle
                    writeData += int_to_bytes(sizeTotal)
                    writeData += bufferData

                    # Write packet
                    f_write = open(end_path, "wb+")
                    f_write.write(writeData)
                    f_write.close()

                    cnt += 1

                    progress.setValue(cnt)

                except Exception as e:
                    print("Multiplexer error : " + str(e))

        QApplication.restoreOverrideCursor()
        QApplication.processEvents()
        progress.setValue(rowCount)
        self.iface.messageBar().clearWidgets()
        # We add it to the manager
        _, name = os.path.split(self.video_file)
        self.parent.AddFileRowToManager(name,
                                        self.video_file,
                                        islocal=True,
                                        klv_folder=self.klv_folder)
        # Close dialog
        self.close()
        return
Exemple #29
0
 def set_progress_text(self, text):
     """Slot to update text during process."""
     self.progress_text.setText(text)
     QApplication.processEvents()
 def setMsg(self, msg):
     self.widget.setText(msg)
     QApplication.processEvents()
Exemple #31
0
    def action_do_export():

        default_folder = QgsSettings().value(
            "qgep_pluging/last_interlis_path",
            QgsProject.instance().absolutePath())
        file_name, _ = QFileDialog.getSaveFileName(
            None,
            plugin.tr("Export to file"),
            os.path.join(default_folder, "qgep-export.xtf"),
            plugin.tr("Interlis transfer files (*.xtf)"),
        )
        if not file_name:
            # Operation canceled
            return
        QgsSettings().setValue("qgep_pluging/last_interlis_path",
                               os.path.dirname(file_name))

        progress_dialog = QProgressDialog("", "", 0, 100,
                                          plugin.iface.mainWindow())
        progress_dialog.setCancelButton(None)
        progress_dialog.setModal(True)
        progress_dialog.show()

        # Prepare the temporary ili2pg model
        progress_dialog.setLabelText("Creating ili schema...")
        QApplication.processEvents()
        log_path = make_log_path(None, "create")
        try:
            create_ili_schema(
                config.ABWASSER_SCHEMA,
                config.ABWASSER_ILI_MODEL,
                log_path,
                recreate_schema=True,
            )
        except CmdException:
            progress_dialog.close()
            show_failure(
                "Could not create the ili2pg schema",
                "Open the logs for more details on the error.",
                log_path,
            )
            return
        progress_dialog.setValue(25)

        # Export to the temporary ili2pg model
        progress_dialog.setLabelText("Converting from QGEP...")
        QApplication.processEvents()
        qgep_export(selection=export_dialog.selected_ids)
        progress_dialog.setValue(50)

        # Export from ili2pg model to file
        progress_dialog.setLabelText("Saving XTF file...")
        QApplication.processEvents()
        log_path = make_log_path(None, "export")
        try:
            export_xtf_data(
                config.ABWASSER_SCHEMA,
                config.ABWASSER_ILI_MODEL_NAME,
                file_name,
                log_path,
            )
        except CmdException:
            progress_dialog.close()
            show_failure(
                "Could not export the ili2pg schema",
                "Open the logs for more details on the error.",
                log_path,
            )
            return
        progress_dialog.setValue(75)

        progress_dialog.setLabelText("Validating the output file...")
        QApplication.processEvents()
        log_path = make_log_path(None, "validate")
        try:
            validate_xtf_data(
                file_name,
                log_path,
            )
        except CmdException:
            progress_dialog.close()
            show_failure(
                "Invalid file",
                "The created file is not a valid XTF file.",
                log_path,
            )
            return
        progress_dialog.setValue(100)

        show_success(
            "Sucess",
            f"Data successfully exported to {file_name}",
            os.path.dirname(log_path),
        )
Exemple #32
0
    def commit_str(self):
        """
        Slot raised when the user clicks on Finish
        button in order to create a new STR entry.
        """
        isValid = True
        # Create a progress dialog
        try:
            progress = STDMProgressDialog(iface.mainWindow())
            progress.show()

            if not self.str_edit_node:
                QApplication.processEvents()
                progress.setRange(0, len(self.data_store))
                progress.overall_progress('Creating a STR...', )

                for i, str_store in enumerate(self.data_store.values()):
                    progress.progress_message('Saving STR {}'.format(i + 1),
                                              '')
                    progress.setValue(i + 1)

                    self.on_add_str(str_store)  # ==>

                progress.deleteLater()
                progress = None

                strMsg = QApplication.translate(
                    "STRDBHandler", "The social tenure relationship has "
                    "been successfully created!")
                QMessageBox.information(
                    iface.mainWindow(),
                    QApplication.translate("STRDBHandler",
                                           "Social Tenure Relationship"),
                    strMsg)
            else:
                QApplication.processEvents()
                progress.setRange(0, 1)
                progress.setValue(0)
                progress.overall_progress('Editing a STR...', )

                progress.progress_message('Updating STR', '')

                updated_str_obj = self.on_edit_str(self.data_store[1])  # ===>

                progress.deleteLater()
                progress = None

                strMsg = QApplication.translate(
                    "STRDBHandler", "The social tenure relationship has "
                    "been successfully updated!")

                QMessageBox.information(
                    iface.mainWindow(),
                    QApplication.translate("STRDBHandler",
                                           "Social Tenure Relationship"),
                    strMsg)

                return updated_str_obj

        except exc.OperationalError as oe:
            errMsg = str(oe)
            QMessageBox.critical(
                iface.mainWindow(),
                QApplication.translate("STRDBHandler", "Unexpected Error"),
                errMsg)
            progress.deleteLater()
            progress = None
            isValid = False
            STDMDb.instance().session.rollback()
            LOGGER.debug(str(oe))

        except exc.IntegrityError as ie:
            errMsg = str(ie)
            QMessageBox.critical(
                iface.mainWindow(),
                QApplication.translate("STRDBHandler",
                                       "Duplicate Relationship Error"), errMsg)
            progress.deleteLater()
            progress = None

            isValid = False
            STDMDb.instance().session.rollback()
            LOGGER.debug(str(ie))
        except exc.InternalError as ie:

            QMessageBox.critical(
                iface.mainWindow(),
                QApplication.translate('STRDBHandler', 'InternalError Error'),
                QApplication.translate(
                    'STRDBHandler', 'Sorry, there is an internal error. \n'
                    'Restart QGIS to fix the issue.'))
            LOGGER.debug(str(ie))
            progress.deleteLater()
            progress = None

            isValid = False
            STDMDb.instance().session.rollback()
        except DummyException as e:
            errMsg = str(e)
            QMessageBox.critical(
                iface.mainWindow(),
                QApplication.translate('STRDBHandler', 'Unexpected Error'),
                errMsg)
            LOGGER.debug(str(e))
            isValid = False
            STDMDb.instance().session.rollback()
            progress.deleteLater()
            progress = None

        finally:

            STDMDb.instance().session.rollback()
            if progress is not None:
                progress.deleteLater()
                progress = None

        return isValid
Exemple #33
0
def action_import(plugin, pgservice=None):
    """
    Is executed when the user clicks the importAction tool
    """
    global import_dialog  # avoid garbage collection

    if not configure_from_modelbaker(plugin.iface):
        return

    if pgservice:
        config.PGSERVICE = pgservice

    default_folder = QgsSettings().value("qgep_pluging/last_interlis_path",
                                         QgsProject.instance().absolutePath())
    file_name, _ = QFileDialog.getOpenFileName(
        None, plugin.tr("Import file"), default_folder,
        plugin.tr("Interlis transfer files (*.xtf)"))
    if not file_name:
        # Operation canceled
        return
    QgsSettings().setValue("qgep_pluging/last_interlis_path",
                           os.path.dirname(file_name))

    progress_dialog = QProgressDialog("", "", 0, 100,
                                      plugin.iface.mainWindow())
    progress_dialog.setCancelButton(None)
    progress_dialog.setModal(True)
    progress_dialog.show()

    # Validating the input file
    progress_dialog.setLabelText("Validating the input file...")
    QApplication.processEvents()
    log_path = make_log_path(None, "validate")
    try:
        validate_xtf_data(
            file_name,
            log_path,
        )
    except CmdException:
        progress_dialog.close()
        show_failure(
            "Invalid file",
            "The input file is not a valid XTF file. Open the logs for more details on the error.",
            log_path,
        )
        return

    # Prepare the temporary ili2pg model
    progress_dialog.setLabelText("Creating ili schema...")
    QApplication.processEvents()
    log_path = make_log_path(None, "create")
    try:
        create_ili_schema(
            config.ABWASSER_SCHEMA,
            config.ABWASSER_ILI_MODEL,
            log_path,
            recreate_schema=True,
        )
    except CmdException:
        progress_dialog.close()
        show_failure(
            "Could not create the ili2pg schema",
            "Open the logs for more details on the error.",
            log_path,
        )
        return
    progress_dialog.setValue(33)

    # Export from ili2pg model to file
    progress_dialog.setLabelText("Importing XTF data...")
    QApplication.processEvents()
    log_path = make_log_path(None, "import")
    try:
        import_xtf_data(
            config.ABWASSER_SCHEMA,
            file_name,
            log_path,
        )
    except CmdException:
        progress_dialog.close()
        show_failure(
            "Could not import data",
            "Open the logs for more details on the error.",
            log_path,
        )
        return
    progress_dialog.setValue(66)

    # Export to the temporary ili2pg model
    progress_dialog.setLabelText("Converting to QGEP...")
    QApplication.processEvents()
    import_dialog = GuiImport(plugin.iface.mainWindow())
    progress_dialog.setValue(100)
    qgep_import(precommit_callback=import_dialog.init_with_session, )
Exemple #34
0
def open_file(dialog=None,
              osm_file=None,
              output_geom_types=None,
              white_list_column=None,
              layer_name="OsmFile",
              config_outputs=None,
              output_dir=None,
              final_query=None,
              prefix_file=None):
    """
    Open an osm file.

    Memory layer if no output directory is set, or Geojson in the output
    directory.

    :param final_query: The query where the file comes from. Might be empty if
    it's a local OSM file.
    :type final_query: basestring
    """
    outputs = {}
    if output_dir:
        for layer in ['points', 'lines', 'multilinestrings', 'multipolygons']:
            if not prefix_file:
                prefix_file = layer_name

            outputs[layer] = join(output_dir,
                                  prefix_file + "_" + layer + ".geojson")

            if isfile(outputs[layer]):
                raise FileOutPutException(suffix='(' + outputs[layer] + ')')

    # Legacy, waiting to remove the OsmParser for QGIS >= 3.6
    # Change in osm_file_dialog.py L131 too
    output_geom_legacy = [l.value.lower() for l in output_geom_types]
    if not white_list_column:
        white_list_column = {}
    white_list_legacy = ({
        l.value.lower(): csv
        for l, csv in white_list_column.items()
    })

    LOGGER.info('The OSM file is: {}'.format(osm_file))

    # Parsing the file
    osm_parser = OsmParser(osm_file=osm_file,
                           layers=output_geom_legacy,
                           white_list_column=white_list_legacy)

    osm_parser.signalText.connect(dialog.set_progress_text)
    osm_parser.signalPercentage.connect(dialog.set_progress_percentage)

    start_time = time.time()
    layers = osm_parser.parse()
    elapsed_time = time.time() - start_time
    parser_time = time.strftime("%Hh %Mm %Ss", time.gmtime(elapsed_time))
    LOGGER.info('The OSM parser took: {}'.format(parser_time))

    # Finishing the process with geojson or memory layer
    num_layers = 0

    for i, (layer, item) in enumerate(layers.items()):
        dialog.set_progress_percentage(i / len(layers) * 100)
        QApplication.processEvents()
        if item['featureCount'] and (LayerType(layer.capitalize())
                                     in output_geom_types):

            final_layer_name = layer_name
            # If configOutputs is not None (from My Queries)
            if config_outputs:
                if config_outputs[layer]['namelayer']:
                    final_layer_name = config_outputs[layer]['namelayer']

            if output_dir:
                dialog.set_progress_text(
                    tr('From memory layer to GeoJSON: ' + layer))
                # Transforming the vector file
                osm_geometries = {
                    'points': QgsWkbTypes.Point,
                    'lines': QgsWkbTypes.LineString,
                    'multilinestrings': QgsWkbTypes.MultiLineString,
                    'multipolygons': QgsWkbTypes.MultiPolygon
                }
                memory_layer = item['vector_layer']

                encoding = get_default_encoding()
                writer = QgsVectorFileWriter(outputs[layer], encoding,
                                             memory_layer.fields(),
                                             osm_geometries[layer],
                                             memory_layer.crs(), "GeoJSON")

                for f in memory_layer.getFeatures():
                    writer.addFeature(f)

                del writer

                # Loading the final vector file
                new_layer = QgsVectorLayer(outputs[layer], final_layer_name,
                                           "ogr")
            else:
                new_layer = item['vector_layer']
                new_layer.setName(final_layer_name)

            # Try to set styling if defined
            if config_outputs and config_outputs[layer]['style']:
                new_layer.loadNamedStyle(config_outputs[layer]['style'])
            else:
                # Loading default styles
                if layer == "multilinestrings" or layer == "lines":
                    if "colour" in item['tags']:
                        new_layer.loadNamedStyle(
                            join(dirname(dirname(abspath(__file__))), "styles",
                                 layer + "_colour.qml"))

            # Add action about OpenStreetMap
            add_actions(new_layer, item['tags'])

            if final_query:
                QgsExpressionContextUtils.setLayerVariable(
                    new_layer, 'quickosm_query', final_query)

            QgsProject.instance().addMapLayer(new_layer)
            num_layers += 1

    return num_layers
Exemple #35
0
def open_file(
        dialog=None,
        osm_file=None,
        output_geom_types=None,
        white_list_column=None,
        layer_name="OsmFile",
        config_outputs=None,
        output_dir=None,
        final_query=None,
        prefix_file=None):
    """
    Open an osm file.

    Memory layer if no output directory is set, or Geojson in the output directory.

    :param final_query: The query where the file comes from. Might be empty if
    it's a local OSM file.
    :type final_query: basestring
    """
    outputs = {}
    if output_dir:
        for layer in ['points', 'lines', 'multilinestrings', 'multipolygons']:
            if not prefix_file:
                prefix_file = layer_name

            outputs[layer] = join(
                output_dir, prefix_file + "_" + layer + ".geojson")

            if isfile(outputs[layer]):
                raise FileOutPutException(suffix='(' + outputs[layer] + ')')

    # Legacy, waiting to remove the OsmParser for QGIS >= 3.6
    # Change in osm_file_dialog.py L131 too
    output_geom_legacy = [l.value.lower() for l in output_geom_types]
    if not white_list_column:
        white_list_column = {}
    white_list_legacy = (
        {l.value.lower(): csv for l, csv in white_list_column.items()}
    )

    LOGGER.info('The OSM file is: {}'.format(osm_file))

    # Parsing the file
    osm_parser = OsmParser(
        osm_file=osm_file,
        layers=output_geom_legacy,
        white_list_column=white_list_legacy)

    osm_parser.signalText.connect(dialog.set_progress_text)
    osm_parser.signalPercentage.connect(dialog.set_progress_percentage)

    start_time = time.time()
    layers = osm_parser.parse()
    elapsed_time = time.time() - start_time
    parser_time = time.strftime("%Hh %Mm %Ss", time.gmtime(elapsed_time))
    LOGGER.info('The OSM parser took: {}'.format(parser_time))

    # Finishing the process with geojson or memory layer
    num_layers = 0

    for i, (layer, item) in enumerate(layers.items()):
        dialog.set_progress_percentage(i / len(layers) * 100)
        QApplication.processEvents()
        if item['featureCount'] and LayerType(layer.capitalize()) in output_geom_types:

            final_layer_name = layer_name
            # If configOutputs is not None (from My Queries)
            if config_outputs:
                if config_outputs[layer]['namelayer']:
                    final_layer_name = config_outputs[layer]['namelayer']

            if output_dir:
                dialog.set_progress_text(tr('From memory to GeoJSON: ' + layer))
                # Transforming the vector file
                osm_geometries = {
                    'points': QgsWkbTypes.Point,
                    'lines': QgsWkbTypes.LineString,
                    'multilinestrings': QgsWkbTypes.MultiLineString,
                    'multipolygons': QgsWkbTypes.MultiPolygon}
                memory_layer = item['vector_layer']

                encoding = get_default_encoding()
                writer = QgsVectorFileWriter(
                    outputs[layer],
                    encoding,
                    memory_layer.fields(),
                    osm_geometries[layer],
                    memory_layer.crs(),
                    "GeoJSON")

                for f in memory_layer.getFeatures():
                    writer.addFeature(f)

                del writer

                # Loading the final vector file
                new_layer = QgsVectorLayer(outputs[layer], final_layer_name, "ogr")
            else:
                new_layer = item['vector_layer']
                new_layer.setName(final_layer_name)

            # Try to set styling if defined
            if config_outputs and config_outputs[layer]['style']:
                new_layer.loadNamedStyle(config_outputs[layer]['style'])
            else:
                # Loading default styles
                if layer == "multilinestrings" or layer == "lines":
                    if "colour" in item['tags']:
                        new_layer.loadNamedStyle(
                            join(dirname(dirname(abspath(__file__))),
                                 "styles",
                                 layer + "_colour.qml"))

            # Add action about OpenStreetMap
            add_actions(new_layer, item['tags'])

            if final_query:
                QgsExpressionContextUtils.setLayerVariable(
                    new_layer, 'quickosm_query', final_query)

            QgsProject.instance().addMapLayer(new_layer)
            num_layers += 1

    return num_layers
    def upload(self, db, data_sources_items, maxSize):
        import_ok = True
        layers_to_replace = {}
        raster_to_upload = {}

        self.status_bar.showMessage(self.tr("Uploading to database '{db}'...").format(db=db.database))
        QApplication.processEvents()

        messages = ""

        # Connect to database
        try:
            conn = db.psycopg_connection()
            cursor = conn.cursor()
        except Exception as e:
            raise RuntimeError("Connection to database failed %s" % str(e))

        for data_source, item in list(data_sources_items.items()):
            # Check available space, block if exceded
            size = DbConnections().db_size()

            if size > float(maxSize):
                QMessageBox.warning(None, self.tr("Database full"), self.tr("You have exceeded the maximum database size for your current QGIS Cloud plan. Please free up some space or upgrade your QGIS Cloud plan."))
                break

            # Layers contains all layers with shared data source
            layer = item['layers'][0]
            if layer.type() == QgsMapLayer.VectorLayer:
                fields = QgsFields(layer.fields())
                srid = layer.crs().postgisSrid()
                geom_column = "wkb_geometry"
                wkbType = layer.wkbType()

# Check if database schema exists
                cursor.execute("SELECT EXISTS(SELECT 1 FROM pg_namespace WHERE nspname = '%s')" % item['schema'])
                schema_exists = cursor.fetchone()[0]
                
                if not schema_exists:
                    cursor.execute("create schema %s" % item['schema'])
                
                if wkbType == QgsWkbTypes.NoGeometry:
                    cloudUri = "dbname='%s' host=%s port=%d user='******' password='******' key='' table=\"%s\".\"%s\"" % (
                    db.database, db.host, db.port, db.username, db.password, item['schema'],  item['table'])
                    geom_column = ""
                else:
                    if not  QgsWkbTypes.isMultiType(wkbType):
                        wkbType = QgsWkbTypes.multiType(wkbType)

                    # Create table (pk='' => always generate a new primary key)
                    cloudUri = "dbname='%s' host=%s port=%d user='******' password='******' key='' table=\"%s\".\"%s\" (%s)" % (
                        db.database, db.host, db.port, db.username, db.password, item['schema'],  item['table'], geom_column
                    )

                self.progress_label.setText(self.tr("Creating table '{table}'...").format(table=item['table']))
                QApplication.processEvents()
                
                if wkbType != QgsWkbTypes.NoGeometry:
                    # Check if SRID is known on database, otherwise create record
                    cursor.execute("SELECT srid FROM public.spatial_ref_sys WHERE srid = %s" % layer.crs().postgisSrid())
                    if not cursor.fetchone():
                        try:
                            cursor.execute("INSERT INTO public.spatial_ref_sys VALUES ({srid},'EPSG',{srid},'{wktstr}','{projstr}')".format(
                                srid = layer.crs().postgisSrid(),
                                wktstr = layer.crs().toWkt(),
                                projstr = layer.crs().toProj4()))
                            conn.commit()
                        except Exception as e:
                            conn.rollback()
                            import_ok &= False
                            messages += "Failed to create SRS record on database: " + str(e) + "\n"
                            continue

    #                cursor.close()

                # TODO: Ask user for overwriting existing table
                # The postgres provider is terribly slow at creating tables with
                # many attribute columns in QGIS < 2.9.0
                vectorLayerImport = PGVectorLayerImport(db, conn,  cursor, cloudUri, fields, wkbType, layer.crs(), True)

                if vectorLayerImport.hasError():
                    import_ok &= False
                    messages += "VectorLayerImport-Error: "+vectorLayerImport.errorMessage() + "\n"
                    continue

                vectorLayerImport = None

                # Build import string
                attribs = list(range(0, fields.count()))
                count = 0
                importstr = bytearray()
                ok = True

                self.progress_label.setText(self.tr("Uploading features..."))
                QApplication.processEvents()
                for feature in layer.getFeatures():
                    f_geometry = feature.geometry()
                    f_geometry.convertToMultiType()
                    
                    # First field is primary key
                    importstr.extend(str(count).encode('utf-8'))
                    count += 1
                    if not feature.geometry():
                        if layer.isSpatial():
                            QgsMessageLog.logMessage(self.tr("Feature {id} of layer {layer} has no geometry").format(id=feature.id(), layer=layer.name()), "QGISCloud")
                            importstr.extend(b"\t" + b"\\N")
                    elif f_geometry.wkbType() != wkbType:
                        QgsMessageLog.logMessage(self.tr("Feature {id} of layer {layer} has wrong geometry type {type}").format(id=feature.id(), layer=layer.name(), type= QgsWkbTypes.displayString(feature.geometry().wkbType())), "QGISCloud")
                        importstr.extend(b"\t" + b"\\N")
                    else:
                        # Second field is geometry in EWKB Hex format
                        importstr.extend(b"\t" + self._wkbToEWkbHex(f_geometry.asWkb(), srid))

                    # Finally, copy data attributes
                    for attrib in attribs:
                        val = feature[attrib]
                        if val is None or isinstance(val, QVariant):
                            val = b"\\N"
                        elif isinstance(val, QDate) or isinstance(val, QDateTime):
                            val = bytearray(val.toString(Qt.ISODate).encode('utf-8'))
                            if not val:
                                val = b"\\N"
                        else:
                            if isinstance( val, list ):
                                listString = '{'
                                if len( val ) > 0:
                                    listString = listString + ('"' + '","'.join( val ) + '"')
                                listString = listString + '}'
                                val = listString
                                             
                            val = bytearray(str(val).encode('utf-8'))
                            val = val.replace(b'\x00',b'?')
                            val = val.replace(b'\t', b"E'\t'")
                            val = val.replace(b'\n', b"E'\n'")
                            val = val.replace(b'\r', b"E'\r'")
                            val = val.replace(b'\\', b"\\")
                        importstr += b"\t" + val

                    importstr += b"\n"

                    # Upload in chunks
                    if (count % 100) == 0:
                        try:
                            cursor.copy_from(StringIO(importstr.decode('utf-8')), '"%s"."%s"' % (item['schema'],  item['table']))
                        except Exception as e:
                            messages += str(e) + "\n"
                            ok = False
                            break
                            
                        importstr = bytearray()
                        self.progress_label.setText(self.tr("{table}: {count} features uploaded").format(
                            table=item['table'], count=count))
                        QApplication.processEvents()
                    # Periodically update ui
                    if (count % 10) == 0:
                        QApplication.processEvents()

                if ok and importstr:
                    try:
                        cursor.copy_from(StringIO(importstr.decode('utf-8')), '"%s"."%s"' % (item['schema'],  item['table']))
                    except Exception as e:
                        messages += str(e) + "\n"
                        ok = False

                if ok:
                    try:
                        conn.commit()
                    except Exception as e:
                        messages += str(e) + "\n"
                        ok = False
                else:
                    conn.rollback()

                import_ok &= ok

                if ok:
                    for layer in item['layers']:
                        layers_to_replace[layer.id()] = {
                            'layer': layer,
                            'data_source': data_source,
                            'db_name': db.database,
                            'schema_name':item['schema'], 
                            'table_name': item['table'],
                            'geom_column': geom_column
                        }

                if wkbType != QgsWkbTypes.NoGeometry:
                    sql = 'create index "{1}_{2}_idx" on "{0}"."{1}" using gist ("{2}");'.format(item['schema'],  item['table'],  geom_column)
                    cursor.execute(sql)
                    conn.commit()
                    
            elif layer.type() == QgsMapLayer.RasterLayer:
                raster_to_upload = {
                            'layer': layer,
                            'data_source': layer.source(),
                            'db_name': db.database,
                            'schema_name': item['schema'], 
                            'table_name': item['table'],
                            'geom_column': 'rast'
                        }
                RasterUpload(conn,  cursor,  raster_to_upload,  maxSize,  self.progress_label)
                layers_to_replace[layer.id()] = raster_to_upload

        sql = """SELECT 'SELECT SETVAL(' || quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||  
                            ', COALESCE(MAX(' ||quote_ident(C.attname)|| ')+1, 1) ) 
                                FROM ' || quote_ident(PGT.schemaname)|| '.' ||quote_ident(T.relname)|| ';' 
                        FROM pg_class AS S,      pg_depend AS D,      pg_class AS T,      pg_attribute AS C,      
                             pg_tables AS PGT, pg_namespace as PGNS 
                        WHERE S.relkind = 'S'     
                          AND S.oid = D.objid     
                          AND S.relnamespace = PGNS.oid 
                          AND PGNS.nspname = '{0}'     
                          AND D.refobjid = T.oid     
                          AND D.refobjid = C.attrelid     
                          AND D.refobjsubid = C.attnum     
                          AND T.relname = PGT.tablename     
                          AND schemaname = '{0}'     
                          AND tablename = '{1}' ORDER BY S.relname;""".format(item['schema'],  item['table'])
        
        cursor.execute(sql)
        rows = cursor.fetchall()
        
        for row in rows:
            cursor.execute(row[0])
            

        cursor.close()
        conn.close()
        self._replace_local_layers(layers_to_replace)
        self.progress_label.setText("")
        if not import_ok:
            raise RuntimeError(str(messages))
Exemple #37
0
 def set_progress_percentage(self, percent):
     """
     Slot to update percentage during process
     """
     self.progressBar_execution.setValue(percent)
     QApplication.processEvents()
    def __init__(self,  conn,  cursor,  raster,  max_size,  progress_label):
        QObject.__init__(self)
        self.cursor = cursor
        self.conn = conn
        self.progress_label = progress_label
        self.messages = ""

        opts = {}
        opts['version'] = g_rt_version
        opts['endian'] = NDR
        opts['column'] = 'rast'
        opts['create_table'] = 1
        opts['drop_table'] = 1
        opts['overview_level'] = 1
        opts['block_size'] = 'auto'
        opts['band'] = None
        opts['register'] = None
        
        # Create PostGIS Raster Tool Functions          
        raster_tools_file = "%s/raster_tools.sql" % os.path.dirname(__file__)
        sql = open(raster_tools_file).read().encode('ascii',errors='ignore')
        self.cursor.execute(sql)
        self.conn.commit()              
         
        i = 0
         
        # Burn all specified input raster files into single WKTRaster table
        gt = None
        layer_info = raster
        opts['srid'] = layer_info['layer'].dataProvider().crs().postgisSrid()
        infile = layer_info['data_source']
        
        file_info = QFileInfo(infile)
        file_size = file_info.size()
        size = DbConnections().db_size()
        file_size /= 1024 * 1024
        size = size + file_size
        
        if size > float(max_size):
            QMessageBox.warning(None, self.tr("Database full"), self.tr("Upload would exceeded the maximum database size for your current QGIS Cloud plan. Please free up some space or upgrade your QGIS Cloud plan."))
            return False
        
        opts['schema_table'] = "\"%s\".\"%s\"" % (layer_info['schema_name'],  layer_info['table_name'])
        opts['table'] = layer_info['table_name']
        opts['schema'] =  layer_info['schema_name']
            
        self.progress_label.setText(self.tr("Creating table '{table}'...").format(table=opts['schema_table'].replace('"',  '')))
        QApplication.processEvents()
        
        self.cursor.execute(self.make_sql_drop_raster_table(opts['schema_table']))
        self.conn.commit()
        
        self.cursor.execute(self.make_sql_create_table(opts,  opts['schema_table']))
        self.conn.commit()
    
        gt = self.wkblify_raster(opts,  infile.replace( '\\', '/') , i, gt)
        i += 1
        
        self.cursor.execute(self.make_sql_create_gist(opts['schema_table'],  opts['column']))
        self.conn.commit()            

   # create raster overviews
        for level in [4, 8, 16, 32]:
            
            sql = 'drop table if exists "%s"."o_%d_%s"' %(opts['schema'],  level,  opts['table'])
            self.cursor.execute(sql)
            self.conn.commit()
            sql = "select st_createoverview_qgiscloud('%s'::text, '%s'::name, %d)" % (opts['schema_table'].replace('"',  ''),  opts['column'],  level)
            self.progress_label.setText(self.tr("Creating overview-level {level} for table '{table}'...").format(level=level,  table=opts['schema_table'].replace('"',  '')))
            QApplication.processEvents()
            self.cursor.execute(sql)
            self.conn.commit()
            
            index_table = opts['schema']+'.o_'+str(level)+'_'+opts['table']
            self.cursor.execute(self.make_sql_create_gist(index_table,  opts['column']))
            self.conn.commit()
                

        self.progress_label.setText(self.tr("Registering raster columns of table '%s'..." % (opts['schema_table'].replace('"',  ''))))
        QApplication.processEvents()
        self.cursor.execute(self.make_sql_addrastercolumn(opts))
        self.conn.commit()
Exemple #39
0
    def on_btnRun_clicked(self):

        if self.ui.cmbProcessLayer.count() <= 0:
            return
        if self.ui.tbxOutput.text() == '':
            QMessageBox.critical(self, 'Raster to Vector Converter',
                                 'Please specify output shapefile.')
            return

        self.setCursor(Qt.WaitCursor)

        #Get raster properties
        numX = self.player.width()
        numY = self.player.height()
        pixsizeX = self.player.rasterUnitsPerPixelX()
        pixsizeY = self.player.rasterUnitsPerPixelY()
        extents = self.player.extent()
        LLX = extents.xMinimum()
        LLY = extents.yMinimum()
        URX = extents.xMaximum()
        URY = extents.yMaximum()
        rprovider = self.player.dataProvider()

        if LLX > URX or LLY > URY:
            self.setCursor(Qt.ArrowCursor)
            QMessageBox.critical(self, 'Raster to Vector Converter',
                                 'Unexpected image extents.')
            return

        #Create vector layer of pixel polygons or points at pixel centers
        #Assumes image extents are given as the LL coordinate of LL pixel
        #and UR coordinate of UR pixel.
        pfeat = QgsFeature()
        crsid = str(self.player.crs().authid())
        if self.ui.rbPoints.isChecked():
            pvlayer = QgsVectorLayer("Point?crs=" + crsid, "templayer",
                                     "memory")
        elif self.ui.rbPolygons.isChecked():
            pvlayer = QgsVectorLayer("Polygon?crs=" + crsid, "templayer",
                                     "memory")
        fields = [QgsField("ID", QVariant.Int)]
        for i in range(self.player.bandCount()):
            bandname = self.player.bandName(i + 1)
            fields.append(QgsField(bandname, QVariant.Double))
        pprovider = pvlayer.dataProvider()
        pprovider.addAttributes(fields)
        pvlayer.startEditing()
        count = 0
        attr = []
        totpix = float(numX * numY)
        for y in range(numY):
            for x in range(numX):
                newpt = QgsPoint(LLX + x * pixsizeX + pixsizeX / 2.0,
                                 LLY + y * pixsizeY + pixsizeY / 2.0)
                data = rprovider.identify(newpt, 1).results()
                if self.ui.rbPoints.isChecked():
                    pfeat.setGeometry(QgsGeometry.fromPoint(newpt))
                elif self.ui.rbPolygons.isChecked():
                    newrect = QgsRectangle(LLX + x * pixsizeX,
                                           LLY + y * pixsizeY,
                                           LLX + x * pixsizeX + pixsizeX,
                                           LLY + y * pixsizeY + pixsizeY)
                    pfeat.setGeometry(QgsGeometry.fromRect(newrect))
                attr = list(data.values())
                attr.insert(0, count)
                pfeat.setAttributes(attr)
                result = pvlayer.addFeature(pfeat)
                if not result:
                    self.setCursor(Qt.ArrowCursor)
                    QMessageBox.critical(self, 'Raster to Vector Converter',
                                         'Processing error 2.')
                    return
                del newpt
                if self.ui.rbPolygons.isChecked():
                    del newrect
                count += 1
                self.ui.ProgressBar.setValue(float(count) / totpix * 100.0)
                QApplication.processEvents()
        pvlayer.commitChanges()
        pvlayer.updateExtents()

        #Write the output shapefile
        if os.path.exists(self.outfile):
            QgsVectorFileWriter.deleteShapeFile(self.outfile)
        result = QgsVectorFileWriter.writeAsVectorFormat(
            pvlayer, self.outfile, 'utf-8', self.player.crs())
        if result != QgsVectorFileWriter.NoError:
            QMessageBox.critical(self, 'Raster to Vector Converter',
                                 'Error creating shapefile.')
        else:  #Ask to add shapfile to map
            name = QFileInfo(self.outfile).completeBaseName()
            result = QMessageBox.question(self, 'Raster to Vector Converter',
                                          'Add shapefile to map?',
                                          QMessageBox.Yes, QMessageBox.No)
            if result == QMessageBox.Yes:
                self.iface.addVectorLayer(self.outfile, name, 'ogr')

        self.setCursor(Qt.ArrowCursor)
        self.close()
Exemple #40
0
 def update_progress_bar(self):
     self.value += 5
     self.progress_bar.setValue(self.value)
     QApplication.processEvents()
class SplashScreen(object):
    def __init__(self, iface):
        self.iface = iface
        self.plugin_dir = os.path.dirname(__file__)

        self.windowTitle = "3Di Modeller Interface - Powered by QGIS"

        self.app = QApplication.instance()
        self.QApp = QCoreApplication.instance()

        if self.QApp is None:
            self.QApp = QApplication(sys.argv)

        self.QApp.startingUp()
        self.QApp.processEvents()
        self.app.startDragTime()

        self.iface.initializationCompleted.connect(self.customization)
        qApp.processEvents()

        self.applyStyle()

    def initGui(self):
        QSettings().setValue("/qgis/hideSplash", True)
        qApp.processEvents()

        icon = QIcon(":/3Di_images/3Di_images/images/logo.png")
        self.app.setWindowIcon(icon)
        self.iface.mainWindow().setWindowIcon(icon)

        self.iface.mainWindow().setWindowTitle(self.windowTitle)

        qApp.processEvents()

        if not self.iface.mainWindow().isVisible():
            self.splash_pix = QPixmap(":/3Di_images/3Di_images/images/splash.png")
            self.splash = QSplashScreen(self.splash_pix, Qt.WindowStaysOnTopHint)
            self.splash = QSplashScreen(self.splash_pix)
            self.splash.setMask(self.splash_pix.mask())
            self.splash.show()
            qApp.processEvents()
        self.applyStyle()
        self.addHelpMenuItem()
        return

    def run(self):
        pass

    def unload(self):
        qApp.processEvents()
        self.iface.initializationCompleted.disconnect(self.customization)
        self.helpAction.deleteLater()
        return

    def customization(self):
        self.splash.finish(self.iface.mainWindow())
        self.iface.mainWindow().setWindowTitle(self.windowTitle)
        qApp.processEvents()
        self.applyStyle()

    def applyStyle(self):
        path = os.path.abspath(
            os.path.join(self.plugin_dir, "Modeler Interface", "stylesheet.qss")
        )
        watch.removePaths(watch.files())
        reload_style(path)

    @staticmethod
    def open3DiHelp(self):
        webbrowser.open_new("https://docs.3di.live")

    @staticmethod
    def about_3di_mi_dialog():
        dialog = About3DiMIDialog(iface.mainWindow())
        dialog.exec_()

    def find_3di_menu(self):
        for i, action in enumerate(self.iface.mainWindow().menuBar().actions()):
            if action.menu().objectName() == "m3Di":
                return action.menu()
        return None

    def addHelpMenuItem(self):
        menu = self.find_3di_menu()
        if not menu:
            menu = QMenu("&3Di", self.iface.mainWindow().menuBar())
            menu.setObjectName("m3Di")
            self.iface.mainWindow().menuBar().addMenu(menu)

        self.helpAction = QAction(
            QIcon(":/3Di_images/3Di_images/images/logo.png"),
            "Documentation",
            self.iface.mainWindow(),
        )
        self.helpAction.triggered.connect(self.open3DiHelp)
        self.helpAction.setWhatsThis("3Di Documentation")

        menu.addAction(self.helpAction)

        about_action = QAction(
            # QIcon(":/3Di_images/3Di_images/images/logo.png"),
            "About 3Di Modeller Interface",
            self.iface.mainWindow(),
        )
        about_action.triggered.connect(self.about_3di_mi_dialog)
        about_action.setWhatsThis("About 3Di Modeller Interface")

        menu.addAction(about_action)
Exemple #42
0
    def run(self):
        """Run method that performs all the real work"""
        self.dlg.show()
        ok_result = self.dlg.exec_()
        if ok_result:

            c = False
            error_msg = str()

            if not self.dlg.LE_input.text():
                error_msg = error_msg + "Ajouter un chemin d'acces " + \
                            "au(x) fichier(s) source.\n\n"
                c = True
            if not self.dlg.LE_output.text():
                error_msg = error_msg + "Ajouter un chemin d'acces pour " + \
                            "le dossier de destination ou seront déposes " + \
                            "les fichiers produits.\n\n"
                c = True

            if c:
                QMessageBox.warning(None, "Erreur(s)", error_msg)
            else:

                options = {
                    # Chemin d'accès au Modèle Numérique de Canopée (entrée)
                    "Path_input":
                    str(self.dlg.LE_input.text()),
                    # Chemin d'accès au dossier de sortie
                    "Path_output":
                    str(self.dlg.LE_output.text()),
                    # Hauteur de la fenêtre de lissage
                    "WinRad":
                    int(self.dlg.LE_gradConvDiameter.text()),
                    # Hauteur minimale des arbres
                    "MinHeightThres":
                    int(self.dlg.LE_minHeightThres.text()),
                    # Hauteur maximale des arbres
                    "MaxHeightThres":
                    int(self.dlg.LE_maxHeightThres.text()),
                    # Degré de recouvrement pour la foret dense
                    "forestRatio":
                    float(self.dlg.LE_DRFD.text()),
                    # Degré de recouvrement pour le paturage boise
                    "woodenPastureRatio":
                    float(self.dlg.LE_DRPB.text()),
                    # largeur minimale forêt
                    "WidthThres":
                    int(self.dlg.LE_minWidthThres.text()),
                    # surface minimum forêt
                    "MinAreaThres":
                    int(self.dlg.LE_minForSurfThres.text()),
                    # surface minimum clairière
                    "MaxAreaThres":
                    int(self.dlg.LE_minClearingSurfThres.text()),
                    # Périmètre max des triangles de Delaunay
                    "MaxTrianglePerimeter":
                    float(self.dlg.txt_triangle_peri.text()),
                    # Calcul selon la convolution uniquement
                    "onlyConvolution":
                    self.dlg.chkConvolution.isChecked(),
                    "AddLayer":
                    self.dlg.CB_addLayer.isChecked(),
                    "plugin":
                    True
                }
                # Set default values of process bar
                self.dlg.progressBar.reset()
                self.dlg.progressBar.setMinimum(0)
                self.dlg.progressBar.setMaximum(1000)

                # Print progress on user window
                self.dlg.label_printActualProcess.setText("ForLim...")
                self.dlg.progressBar.setValue(0)
                QApplication.processEvents()

                now_time = datetime.now()

                name = "forLim_" + str(uuid4())
                options["Path_output"] = \
                    os.path.join(options["Path_output"], name)
                os.mkdir(options["Path_output"])

                # Get file list
                path_input = options["Path_input"]
                files = options["Path_input"].split(";")
                nfiles = len(files)

                options['src'] = str(options['Path_input'])
                options['dst'] = str(options['Path_output'])
                f = open(options['Path_output'] + '/forlim_medatata.txt', 'w')
                f.write(str(options))
                f.close()

                i = 0
                for f in enumerate(files):
                    i += 1
                    self.dlg.label_printActualProcess \
                        .setText("Processing tile " + str(i) + "/" +
                                 str(len((files))))
                    options['Path_input'] = f[1]
                    options['src'] = str(options['Path_input'])
                    delaunayMethod.main(self, options, i)

                self.dlg.label_printActualProcess.setText(u'Calcul terminé')
                self.iface.mapCanvas().zoomToFullExtent()
 def displayPixmapUpdated(self, FIELD, pixmap):
     TOMsMessageLog.logMessage("In utils::displayPixmapUpdated ... ", level=Qgis.Info)
     FIELD.setPixmap(pixmap)
     FIELD.setScaledContents(True)
     QApplication.processEvents()  # processes the event queue - https://stackoverflow.com/questions/43094589/opencv-imshow-prevents-qt-python-crashing
Exemple #44
0
 def set_progress_text(self, text):
     """
     Slot to update text during process
     """
     self.label_progress.setText(text)
     QApplication.processEvents()
Exemple #45
0
    def run_query(self):
        """
        Process for running the query
        """

        # Block the button and save the initial text
        self.output_directory.setDisabled(True)
        self.pushButton_generateQuery.setDisabled(True)
        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.start_process()
        QApplication.processEvents()

        # Get all values
        query = self.textEdit_query.toPlainText()
        output_directory = self.output_directory.filePath()
        prefix_file = self.lineEdit_filePrefix.text()
        nominatim = self.nominatim_value()

        # Set bbox
        bbox = None
        if self.cb_query_type.isEnabled():
            query_type = self.cb_query_type.currentData()
            if query_type in ['layer', 'canvas']:
                nominatim = None
                bbox = self.get_bounding_box()

        # Check nominatim
        if nominatim == '':
            nominatim = None

        # Which geometry at the end ?
        output_geometry_types = self.get_output_geometry_types()
        white_list_values = self.get_white_list_values()

        try:
            # Test values
            if not output_geometry_types:
                raise OutPutGeomTypesException

            if output_directory and not isdir(output_directory):
                raise DirectoryOutPutException

            if not nominatim and \
                    re.search(r'\{\{nominatim\}\}', query) or \
                    re.search(r'\{\{nominatimArea:\}\}', query) or \
                    re.search(r'\{\{geocodeArea:\}\}', query):

                raise MissingParameterException(suffix="nominatim field")

            num_layers = process_query(
                dialog=self,
                query=query,
                output_dir=output_directory,
                prefix_file=prefix_file,
                output_geometry_types=output_geometry_types,
                white_list_values=white_list_values,
                nominatim=nominatim,
                bbox=bbox)

            if num_layers:
                display_message_bar(tr('Successful query'),
                                    level=Qgis.Success,
                                    duration=5)
                self.label_progress.setText(tr('Successful query'))
            else:
                display_message_bar(tr('Successful query, but no result.'),
                                    level=Qgis.Warning,
                                    duration=7)

        except QuickOsmException as e:
            self.display_geo_algorithm_exception(e)
            pass
        except Exception as e:  # pylint: disable=broad-except
            self.display_exception(e)
            pass

        finally:
            # Resetting the button
            self.output_directory.setDisabled(False)
            self.pushButton_generateQuery.setDisabled(False)
            QApplication.restoreOverrideCursor()
            self.end_process()
            QApplication.processEvents()
    def test(self):

        # This test is quite fragile as it depends on windows manager behaviour
        # regarding focus, so not surprising it doesn't pass
        # on other platforms than Linux.
        #if 'TRAVIS_OS_NAME' in os.environ and os.environ['TRAVIS_OS_NAME'] == 'osx':
        #    return

        main_dialog = QgsProviderRegistry.instance().selectWidget("WFS")
        main_dialog.setProperty("hideDialogs", True)

        self.assertIsNotNone(main_dialog)

        # Create new connection
        btnNew = main_dialog.findChild(QWidget, "btnNew")
        self.assertIsNotNone(btnNew)
        QTest.mouseClick(btnNew, Qt.LeftButton)
        new_conn = find_window('QgsNewHttpConnectionBase')
        self.assertIsNotNone(new_conn)
        txtName = new_conn.findChild(QLineEdit, "txtName")
        self.assertIsNotNone(txtName)
        txtName.setText("test_connection")
        txtUrl = new_conn.findChild(QLineEdit, "txtUrl")
        self.assertIsNotNone(txtUrl)
        txtUrl.setText("test_url")
        new_conn.accept()

        # Wait for object to be destroyed
        new_conn = self.wait_object_destruction(new_conn)

        # Try to connect
        btnConnect = main_dialog.findChild(QWidget, "btnConnect")
        self.assertIsNotNone(btnConnect)
        QTest.mouseClick(btnConnect, Qt.LeftButton)
        # Depends on asynchronous signal
        QApplication.processEvents()
        error_box = find_window('WFSCapabilitiesErrorBox')
        self.assertIsNotNone(error_box)
        # Close error box
        error_box.accept()

        # Wait for object to be destroyed
        error_box = self.wait_object_destruction(error_box)

        # Edit connection
        btnEdit = main_dialog.findChild(QWidget, "btnEdit")
        self.assertIsNotNone(btnEdit)
        QTest.mouseClick(btnEdit, Qt.LeftButton)
        new_conn = find_window('QgsNewHttpConnectionBase',)
        self.assertIsNotNone(new_conn)
        txtName = new_conn.findChild(QLineEdit, "txtName")
        self.assertIsNotNone(txtName)
        txtName.setText("test_connection")
        txtUrl = new_conn.findChild(QLineEdit, "txtUrl")
        self.assertIsNotNone(txtUrl)

        endpoint = self.basetestpath + '/fake_qgis_http_endpoint'
        expected_endpoint = endpoint
        if sys.platform == 'win32' and expected_endpoint[1] == ':':
            expected_endpoint = expected_endpoint[0] + expected_endpoint[2:]
        with open(sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?ACCEPTVERSIONS=2.0.0,1.1.0,1.0.0'), 'wb') as f:
            f.write("""
<wfs:WFS_Capabilities version="2.0.0" xmlns="http://www.opengis.net/wfs/2.0" xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:gml="http://schemas.opengis.net/gml/3.2" xmlns:fes="http://www.opengis.net/fes/2.0">
  <FeatureTypeList>
    <FeatureType>
      <Name>my:typename</Name>
      <Title>Title</Title>
      <Abstract>Abstract</Abstract>
      <DefaultCRS>urn:ogc:def:crs:EPSG::4326</DefaultCRS>
      <ows:WGS84BoundingBox>
        <ows:LowerCorner>-71.123 66.33</ows:LowerCorner>
        <ows:UpperCorner>-65.32 78.3</ows:UpperCorner>
      </ows:WGS84BoundingBox>
    </FeatureType>
  </FeatureTypeList>
  <fes:Filter_Capabilities>
    <fes:Spatial_Capabilities>
      <fes:GeometryOperands>
        <fes:GeometryOperand name="gml:Envelope"/>
        <fes:GeometryOperand name="gml:Point"/>
        <fes:GeometryOperand name="gml:MultiPoint"/>
        <fes:GeometryOperand name="gml:LineString"/>
        <fes:GeometryOperand name="gml:MultiLineString"/>
        <fes:GeometryOperand name="gml:Polygon"/>
        <fes:GeometryOperand name="gml:MultiPolygon"/>
        <fes:GeometryOperand name="gml:MultiGeometry"/>
      </fes:GeometryOperands>
      <fes:SpatialOperators>
        <fes:SpatialOperator name="Disjoint"/>
        <fes:SpatialOperator name="Equals"/>
        <fes:SpatialOperator name="DWithin"/>
        <fes:SpatialOperator name="Beyond"/>
        <fes:SpatialOperator name="Intersects"/>
        <fes:SpatialOperator name="Touches"/>
        <fes:SpatialOperator name="Crosses"/>
        <fes:SpatialOperator name="Within"/>
        <fes:SpatialOperator name="Contains"/>
        <fes:SpatialOperator name="Overlaps"/>
        <fes:SpatialOperator name="BBOX"/>
      </fes:SpatialOperators>
    </fes:Spatial_Capabilities>
    <fes:Functions>
      <fes:Function name="abs">
        <fes:Returns>xs:int</fes:Returns>
        <fes:Arguments>
          <fes:Argument name="param">
            <fes:Type>xs:int</fes:Type>
          </fes:Argument>
        </fes:Arguments>
      </fes:Function>
    </fes:Functions>
  </fes:Filter_Capabilities>
</wfs:WFS_Capabilities>""".encode('UTF-8'))

        txtUrl.setText("http://" + endpoint)
        new_conn.accept()

        # Wait for object to be destroyed
        new_conn = self.wait_object_destruction(new_conn)

        # Try to connect
        btnConnect = main_dialog.findChild(QWidget, "btnConnect")
        self.assertIsNotNone(btnConnect)
        QTest.mouseClick(btnConnect, Qt.LeftButton)

        buttonAdd = self.get_button_add(main_dialog)
        for i in range(10):
            QApplication.processEvents()
            if buttonAdd.isEnabled():
                break
        self.assertTrue(buttonAdd.isEnabled())

        # Add layer
        self.addWfsLayer_uri = None
        self.addWfsLayer_layer_name = None
        main_dialog.addWfsLayer.connect(self.slotAddWfsLayer)
        QTest.mouseClick(buttonAdd, Qt.LeftButton)
        self.assertEqual(self.addWfsLayer_uri, ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=')
        self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')

        # Click on Build Query
        buttonBuildQuery = self.get_button_build_query(main_dialog)
        self.assertTrue(buttonBuildQuery.isEnabled())
        QTest.mouseClick(buttonBuildQuery, Qt.LeftButton)
        error_box = find_window('WFSFeatureTypeErrorBox')
        self.assertIsNotNone(error_box)
        # Close error box
        error_box.accept()
        # Wait for object to be destroyed
        error_box = self.wait_object_destruction(error_box)

        # Click again but with valid DescribeFeatureType

        with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=my:typename'), 'wb') as f:
            f.write("""
<xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my">
  <xsd:import namespace="http://www.opengis.net/gml/3.2"/>
  <xsd:complexType name="typenameType">
    <xsd:complexContent>
      <xsd:extension base="gml:AbstractFeatureType">
        <xsd:sequence>
          <xsd:element maxOccurs="1" minOccurs="0" name="intfield" nillable="true" type="xsd:int"/>
          <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:PolygonPropertyType"/>
        </xsd:sequence>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>
  <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/>
</xsd:schema>
""".encode('UTF-8'))
        QTest.mouseClick(buttonBuildQuery, Qt.LeftButton)

        # Check that the combos are properly initialized
        dialog = find_window('QgsSQLComposerDialogBase')
        self.assertIsNotNone(dialog)

        mTablesCombo = dialog.findChild(QComboBox, "mTablesCombo")
        self.assertIsNotNone(mTablesCombo)
        self.assertEqual(mTablesCombo.itemText(1), 'typename (Title)')

        mColumnsCombo = dialog.findChild(QComboBox, "mColumnsCombo")
        self.assertIsNotNone(mColumnsCombo)
        self.assertEqual(mColumnsCombo.itemText(1), 'intfield (int)')
        self.assertEqual(mColumnsCombo.itemText(mColumnsCombo.count() - 2), 'geometryProperty (geometry)')
        self.assertEqual(mColumnsCombo.itemText(mColumnsCombo.count() - 1), '*')

        mFunctionsCombo = dialog.findChild(QComboBox, "mFunctionsCombo")
        self.assertIsNotNone(mFunctionsCombo)
        self.assertEqual(mFunctionsCombo.itemText(1), 'abs(param: int): int')

        mSpatialPredicatesCombo = dialog.findChild(QComboBox, "mSpatialPredicatesCombo")
        self.assertIsNotNone(mSpatialPredicatesCombo)
        self.assertEqual(mSpatialPredicatesCombo.itemText(1), 'ST_Disjoint(geometry, geometry): boolean')

        mWhereEditor = dialog.findChild(QTextEdit, "mWhereEditor")
        self.assertIsNotNone(mWhereEditor)
        mWhereEditor.setText('1 = 1')

        dialog.accept()
        # Wait for object to be destroyed
        dialog = self.wait_object_destruction(dialog)

        # Add layer
        buttonAdd = self.get_button_add(main_dialog)
        self.assertTrue(buttonAdd.isEnabled())

        self.addWfsLayer_uri = None
        self.addWfsLayer_layer_name = None
        main_dialog.addWfsLayer.connect(self.slotAddWfsLayer)
        QTest.mouseClick(buttonAdd, Qt.LeftButton)
        self.assertEqual(self.addWfsLayer_uri, ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=SELECT * FROM typename WHERE 1 = 1')
        self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')
    def run(self):
        """Run method that performs all the real work"""
        
        layers = self.iface.mapCanvas().layers()
        layer_list = []
        self.dlg.layerComboBox.clear()
        for layer in layers:
            layer_list.append(layer.name())
        self.dlg.layerComboBox.addItems(layer_list)
        # TODO: Make the active layer the selected item in combo box  aLayer = qgis.utils.iface.activeLayer()
        
        # TODO: Add signal to update toleranceSpinBox.suffix (Degrees) from layerComboBox.crs.mapUnits when layer is selected:
        #my_UnitType = { 0: 'Meters', 1: 'Feet', 2: 'Degrees', 7: 'NauticalMiles', 8: 'Kilometers', 9: 'Yards', 10: 'Miles', 3: 'UnknownUnit'}
        #suffix = my_UnitType[aLayer.crs().mapUnits()]
        
        # show the dialog
        self.dlg.show()
        # Run the dialog event loop
        result = self.dlg.exec_()
        # See if OK was pressed
        if result:
            if self.checkNetworkXModule() < 0:
                return -4
            import networkx as nx
            
            layerName = self.dlg.layerComboBox.currentText()
            try:
                aLayer = QgsProject.instance().mapLayersByName(layerName)[0]
            except:
                self.iface.messageBar().pushMessage("Error", "Failed to load layer!", level=Qgis.Critical)
                return -1

            try:

                previousEditingMode = True
                if not aLayer.isEditable():
                    aLayer.startEditing()
                    #self.iface.messageBar().pushMessage("Info", "Layer " + aLayer.name() + " needs to be in edit mode", level=Qgis.Info)
                    #self.iface.messageBar().pushMessage("Error", "Layer " + aLayer.name() + " needs to be in edit mode", level=Qgis.Critical)
                    #return -2
                    previousEditingMode = False
                     
                attrIdx = self.getAttributeIndex(aLayer)
                if attrIdx < 0:
                    return -3  

                progressMessageBar = self.iface.messageBar().createMessage("Creating network graph...")
                progress = QProgressBar()
                progress.setMaximum(aLayer.featureCount())
                progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter)
                progressMessageBar.layout().addWidget(progress)
                self.iface.messageBar().pushWidget(progressMessageBar, Qgis.Info)          
                
                G = nx.Graph()

                aLayer.beginEditCommand("Clear group attribute, create graph")
                # construct undirected graph
                tolerance = self.dlg.toleranceSpinBox.value()
                if tolerance == 0:
                    tolerance = 0.000001
                count = 0
                for feat in aLayer.getFeatures():
                    count += 1
                    progress.setValue(count)
                    done = aLayer.changeAttributeValue(feat.id(), attrIdx, -1)
                    geom = feat.geometry()
                    QgsGeometry.convertToSingleType(geom)       # QGIS 3.x seems to load single LineString as MultiLineString??
                    line = geom.asPolyline()
                    
                    for i in range(len(line)-1):
                        G.add_edges_from([((int(line[i][0]/tolerance), int(line[i][1]/tolerance)), (int(line[i+1][0]/tolerance), int(line[i+1][1]/tolerance)), 
                                          {'fid': feat.id()})])     # first scale by tolerance, then convert to int.  Before doing this, there were problems (in NetworkX v1) with floats not equating, thus creating disconnects that weren't there.
                    if count % 100 == 0:
                        QApplication.processEvents()      # keep the UI responsive, every 100 features
                        #TODO: check to see if Esc pressed

                aLayer.endEditCommand()
                
                self.iface.messageBar().pushMessage("Finding connected subgraphs, please wait...",  level=Qgis.Warning)     # WARNING - to highlight the next stage, where we cannot show progress
                QApplication.processEvents()
                connected_components = list(nx.connected_component_subgraphs(G))    # this takes a long time.  TODO: how to show progress?
                self.iface.messageBar().pushMessage("Updating group attribute...",  level=Qgis.Info)
                QApplication.processEvents()
                          
                # gather edges and components to which they belong
                fid_comp = {}
                for i, graph in enumerate(connected_components):
                   for edge in graph.edges(data=True):
                       fid_comp[edge[2].get('fid', None)] = i
                
                # write output to csv file
                #with open('C:/Tmp/Components.csv', 'wb') as f:
                #    w = csv.DictWriter(f, fieldnames=['fid', 'group'])
                #    w.writeheader()
                #    for (fid, group) in fid_comp.items():
                #        w.writerow({'fid': fid, 'group': group})
                
                aLayer.beginEditCommand("Update group attribute")
                for (fid, group) in fid_comp.items():
                    done = aLayer.changeAttributeValue(fid, attrIdx, group)
                aLayer.endEditCommand()
                
                groups = list(set(fid_comp.values()))            
                if self.dlg.stylingCheckBox.isChecked():
                    aLayer.beginEditCommand("Update layer styling")
                    categories = []
                    firstCat = True
                    for cat in groups:
                        symbol = QgsSymbol.defaultSymbol(aLayer.geometryType())
                        symbol.setColor(QColor(randint(0,255), randint(0,255), randint(0,255)))
                        if firstCat:
                            firstCat = False
                        else:
                            symbol.setWidth(symbol.width()*5)
                        category = QgsRendererCategory(cat, symbol, "%d" % cat)
                        categories.append(category)

                    field = self.dlg.attributeNameEditBox.text()
                    renderer = QgsCategorizedSymbolRenderer(field, categories)
                    aLayer.setRenderer(renderer)

#                    if self.iface.mapCanvas().isCachingEnabled():
#                        aLayer.setCacheImage(None)
#                    else:
#                        self.iface.mapCanvas().refresh()
                    aLayer.triggerRepaint()
                    aLayer.endEditCommand()            
                   
                self.iface.messageBar().clearWidgets()   
                self.iface.messageBar().pushMessage("Found main network and %d disconnected islands in layer %s" % (len(groups)-1, aLayer.name()),  level=Qgis.Success)

                aLayer.commitChanges()
#                if not previousEditingMode: 
    
            except Exception as e:
                self.iface.messageBar().pushMessage("Error", "Exception caught: %s.  Please report an issue to the author of the plugin." % repr(e), level=Qgis.Critical)