예제 #1
0
    def _export_composition_as_image(self, composition, file_path):
        """
        Export the composition as a raster image.
        """
        num_pages = composition.numPages()

        for p in range(num_pages):
            img = composition.printPageAsRaster(p)

            if img.isNull():
                msg = QApplication.translate("DocumentGenerator",
                                        "Memory allocation error. Please try "
                                        "a lower resolution or a smaller paper size.")
                raise Exception(msg)

            if p == 0:
                state = img.save(file_path)

            else:
                fi = QFileInfo(file_path)
                file_path = "{0}/{1}_{2}.{3}".format(fi.absolutePath(),
                                                             fi.baseName(),
                    (p+1), fi.suffix())
                state = img.save(file_path)

            if not state:
                msg = QApplication.translate("DocumentGenerator",
                                        "Error creating {0}.".format(file_path))
                raise Exception(msg)
예제 #2
0
    def on_upload_document(self):
        '''
        Slot raised when the user clicks
        to upload a supporting document.
        '''
        document_str = QApplication.translate(
            "SupportingDocuments", "Specify the Document File Location")
        documents = self.select_file_dialog(document_str)

        cbo_index = self.doc_type_cbo.currentIndex()
        doc_id = self.doc_type_cbo.itemData(cbo_index)

        for doc in documents:
            self.supporting_doc_manager.insertDocumentFromFile(
                doc, doc_id, self.social_tenure, self.current_party_count)

        # Set last path
        if len(documents) > 0:
            doc = documents[0]
            fi = QFileInfo(doc)
            dir_path = fi.absolutePath()
            set_last_document_path(dir_path)

            model_objs = self.supporting_doc_manager.model_objects()
            self.onUploadDocument.emit(model_objs)
예제 #3
0
    def select_output_file(self):
        prjfi = QFileInfo(QgsProject.instance().fileName())

        filename, __ = QFileDialog.getSaveFileName(self.dlg,
                                                   "Select output file ",
                                                   prjfi.absolutePath(),
                                                   '*.shp')

        self.dlg.outputPath.setText(filename)
예제 #4
0
    def loadList(self):
        self.fileName, _ = QFileDialog.getOpenFileName(
            None, "Load data separated by ';'", self.fPath, ""
        )
        if not os.path.exists(self.fileName):
            return 0
        # update selected file's folder
        fInfo = QFileInfo(self.fileName)
        self.fPath = fInfo.absolutePath()
        self.saveConf()

        self.render_temp_band()
        # get saved data
        try:
            f = open(self.fileName)
            lines = f.readlines()
            f.close()
            self.clearList()
            for line in lines:
                # remove trailing 'new lines', etc and break into parts
                parts = ((line.strip()).lower()).split("=")
                if len(parts) > 1:
                    # self.say("line="+line+'\nparts[0]='+parts[0]+'\nparts[1]='+parts[1])
                    if parts[0].lower() == "angle":
                        self.setAngle(parts[1].lower())
                    elif parts[0].lower() == "heading":
                        self.setHeading(parts[1].lower())
                    elif parts[0].lower() == "declination":
                        self.setDeclination(parts[1].lower())
                    elif parts[0].lower() == "dist_units":
                        self.setDistanceUnits(parts[1].lower())
                    elif parts[0].lower() == "angle_unit":
                        self.setAngleUnit(parts[1].lower())
                    elif parts[0].lower() == "startat":
                        self.setStartAt(parts[1].lower())
                    elif parts[0].lower() == "survey":
                        self.setSurvey(parts[1].lower())
                else:
                    coords = tuple((line.strip()).split(";"))
                    if coords[0].lower() == "[data]":
                        pass
                    else:
                        self.addrow(*coords)
        except:
            self.say("Invalid input")
예제 #5
0
    def _on_add_supporting_document(self):
        # Slot raised when the user select to add a supporting document
        if self.count == 0:
            return

        select = self.tr('Select')
        supporting_docs_str = 'Supporting Documents'
        title = '{0} {1} {2}'.format(select, self.current_document_type(),
                                     supporting_docs_str)

        filter_str = '{0} (*.jpg *.jpeg *.png *.bmp *.tiff *.svg *.pdf)'.format(
            supporting_docs_str)

        # Get last path for supporting documents
        last_path = last_document_path()
        if last_path is None:
            last_path = '/home'

        else:
            dir = QDir(last_path)
            if not dir.exists():
                last_path = '/home'

        source_docs, _ = QFileDialog.getOpenFileNames(self, title, last_path,
                                                      filter_str)

        doc_type_id = self._cbo_doc_type.itemData(
            self._cbo_doc_type.currentIndex())
        parent_entity = self._entity_supporting_doc.parent_entity

        for doc in source_docs:
            self.source_document_manager.insertDocumentFromFile(
                doc, doc_type_id, parent_entity)

        # Set last path
        if len(source_docs) > 0:
            doc = source_docs[0]
            fi = QFileInfo(doc)
            dir_path = fi.absolutePath()
            set_last_document_path(dir_path)
예제 #6
0
class GeoPackage(DataStore):
    """
    GeoPackage DataStore

    .. versionadded:: 4.0
    """
    def __init__(self, uri):
        """
        Constructor for the GeoPackage DataStore.

        :param uri: A filepath which doesn't exist
        :type uri: QFileInfo, str

        .. versionadded:: 4.0
        """
        super(GeoPackage, self).__init__(uri)
        self.vector_driver = ogr.GetDriverByName('GPKG')
        self.raster_driver = gdal.GetDriverByName('GPKG')

        if isinstance(uri, QFileInfo):
            self._uri = uri
        elif isinstance(uri, str):
            self._uri = QFileInfo(uri)
        else:
            raise ErrorDataStore('Unknown type')

        if self.uri.exists():
            raster_datasource = gdal.Open(self.uri.absoluteFilePath())
            if raster_datasource is None:
                # Let's try if it's a vector one.
                vector_datasource = self.vector_driver.Open(
                    self.uri.absoluteFilePath())
                if vector_datasource is None:
                    msg = 'The file is not a geopackage or it doesn\'t ' \
                          'contain any layers.'
                    raise ErrorDataStore(msg)
        else:
            path = self.uri.absoluteFilePath()
            # We need this variable to be created. The delete will create it.
            datasource = self.vector_driver.CreateDataSource(path)  # NOQA
            del datasource

    @property
    def uri_path(self):
        """Return the URI of the datastore as a path. It's not a layer URI.

        :return: The URI.
        :rtype: str

        .. versionadded:: 4.0
        """
        return self.uri.absolutePath()

    def is_writable(self):
        """Check if the folder is writable.

        :return: If it's writable or not.
        :rtype: bool

        .. versionadded:: 4.0
        """
        # Fixme, need to check DB permissions ?
        return self._uri.absolutePath().isWritable()

    def supports_rasters(self):
        """Check if we can support raster in the geopackage.

        :return: If it's writable or not.
        :rtype: bool

        .. versionadded:: 4.0
        """
        if int(gdal.VersionInfo('VERSION_NUM')) < 2000000:
            return False
        else:
            return True

    def _vector_layers(self):
        """Return a list of vector layers available.

        :return: List of vector layers available in the geopackage.
        :rtype: list

        .. versionadded:: 4.0
        """
        layers = []
        vector_datasource = self.vector_driver.Open(
            self.uri.absoluteFilePath())
        if vector_datasource:
            for i in range(vector_datasource.GetLayerCount()):
                layers.append(vector_datasource.GetLayer(i).GetName())
        return layers

    def _raster_layers(self):
        """Return a list of raster layers available.

        :return: List of raster layers available in the geopackage.
        :rtype: list

        .. versionadded:: 4.0
        """
        layers = []

        raster_datasource = gdal.Open(self.uri.absoluteFilePath())
        if raster_datasource:
            subdatasets = raster_datasource.GetSubDatasets()
            if len(subdatasets) == 0:
                metadata = raster_datasource.GetMetadata()
                layers.append(metadata['IDENTIFIER'])
            else:
                for subdataset in subdatasets:
                    layers.append(subdataset[0].split(':')[2])

        return layers

    def layers(self):
        """Return a list of layers available.

        :return: List of layers available in the datastore.
        :rtype: list

        .. versionadded:: 4.0
        """
        return self._vector_layers() + self._raster_layers()

    def layer_uri(self, layer_name):
        """Get layer URI.

        For a vector layer :
        /path/to/the/geopackage.gpkg|layername=my_vector_layer

        For a raster :
        GPKG:/path/to/the/geopackage.gpkg:my_raster_layer

        :param layer_name: The name of the layer to fetch.
        :type layer_name: str

        :return: The URI to the layer.
        :rtype: str

        .. versionadded:: 4.0
        """
        for layer in self._vector_layers():
            if layer == layer_name:
                uri = '{}|layername={}'.format(self.uri.absoluteFilePath(),
                                               layer_name)
                return uri
        else:
            for layer in self._raster_layers():
                if layer == layer_name:
                    uri = 'GPKG:{}:{}'.format(self.uri.absoluteFilePath(),
                                              layer_name)
                    return uri
            else:
                return None

    def _add_vector_layer(self, vector_layer, layer_name, save_style=False):
        """Add a vector layer to the geopackage.

        :param vector_layer: The layer to add.
        :type vector_layer: QgsVectorLayer

        :param layer_name: The name of the layer in the datastore.
        :type layer_name: str

        :param save_style: If we have to save a QML too. Default to False.
        Not implemented in geopackage !
        :type save_style: bool

        :returns: A two-tuple. The first element will be True if we could add
            the layer to the datastore. The second element will be the layer
            name which has been used or the error message.
        :rtype: (bool, str)

        .. versionadded:: 4.0
        """

        # Fixme
        # if not self.is_writable():
        #    return False, 'The destination is not writable.'

        geometry = QGIS_OGR_GEOMETRY_MAP[vector_layer.wkbType()]

        spatial_reference = osr.SpatialReference()
        qgis_spatial_reference = vector_layer.crs().authid()
        # Use 4326 as default if the spatial reference is not found
        epsg = 4326
        epsg_string = qgis_spatial_reference
        if epsg_string:
            epsg = int(epsg_string.split(':')[1])
        spatial_reference.ImportFromEPSG(epsg)

        vector_datasource = self.vector_driver.Open(
            self.uri.absoluteFilePath(), True)
        vector_datasource.CreateLayer(layer_name, spatial_reference, geometry)
        uri = '{}|layerid=0'.format(self.uri.absoluteFilePath())
        vector_layer = QgsVectorLayer(uri, layer_name, 'ogr')

        data_provider = vector_layer.dataProvider()
        for feature in vector_layer.getFeatures():
            data_provider.addFeatures([feature])

        return True, layer_name

    def _add_raster_layer(self, raster_layer, layer_name, save_style=False):
        """Add a raster layer to the folder.

        :param raster_layer: The layer to add.
        :type raster_layer: QgsRasterLayer

        :param layer_name: The name of the layer in the datastore.
        :type layer_name: str

        :param save_style: If we have to save a QML too. Default to False.
        Not implemented in geopackage !
        :type save_style: bool

        :returns: A two-tuple. The first element will be True if we could add
            the layer to the datastore. The second element will be the layer
            name which has been used or the error message.
        :rtype: (bool, str)

        .. versionadded:: 4.0
        """

        source = gdal.Open(raster_layer.source())
        array = source.GetRasterBand(1).ReadAsArray()

        x_size = source.RasterXSize
        y_size = source.RasterYSize

        output = self.raster_driver.Create(
            self.uri.absoluteFilePath(), x_size, y_size, 1, gdal.GDT_Byte,
            ['APPEND_SUBDATASET=YES',
             'RASTER_TABLE=%s' % layer_name])

        output.SetGeoTransform(source.GetGeoTransform())
        output.SetProjection(source.GetProjection())
        output.GetRasterBand(1).WriteArray(array)

        # Once we're done, close properly the dataset
        output = None
        source = None
        return True, layer_name

    def _add_tabular_layer(self, tabular_layer, layer_name, save_style=False):
        """Add a tabular layer to the geopackage.

        :param tabular_layer: The layer to add.
        :type tabular_layer: QgsVectorLayer

        :param layer_name: The name of the layer in the datastore.
        :type layer_name: str

        :param save_style: If we have to save a QML too. Default to False.
        Not implemented in geopackage !
        :type save_style: bool

        :returns: A two-tuple. The first element will be True if we could add
            the layer to the datastore. The second element will be the layer
            name which has been used or the error message.
        :rtype: (bool, str)

        .. versionadded:: 4.0
        """
        return self._add_vector_layer(tabular_layer, layer_name, save_style)
 def workerFinished(self, ok, ret):
     """Handles the output from the worker and cleans up after the
        worker has finished."""
     # clean up the worker and thread
     self.showInfo("Handling the result")
     self.worker.deleteLater()
     self.thread.quit()
     self.thread.wait()
     self.thread.deleteLater()
     # remove widget from message bar (pop)
     self.iface.messageBar().popWidget(self.messageBar)
     if ok and ret is not None:
         #self.showInfo("Ret: "+str(ret[10,]))
         # Transformation:
         self.minx = self.thinninglayer.extent().xMinimum()
         self.maxx = self.thinninglayer.extent().xMaximum()
         self.miny = self.thinninglayer.extent().yMinimum()
         self.maxy = self.thinninglayer.extent().yMaximum()
         self.rows = self.thinninglayer.height()
         self.cols = self.thinninglayer.width()
         self.xres = (self.maxx - self.minx) / float(self.cols)
         self.yres = (self.maxy - self.miny) / float(self.rows)
         geotransform = (self.minx, self.xres, 0, self.maxy, 0, -self.yres)
         try:
             format = self.DEFAULTPROVIDER
             driver = gdal.GetDriverByName(format)
             NOVALUE = 0
             metadata = driver.GetMetadata()
             fileName = self.outputRaster.text()
             if self.outputRaster.text() == "":
                 self.showInfo("No output file specified, " +
                                      "creating a temporary file")
                 # Get a temporary file
                 fileName = mktemp(prefix='greyskel',
                        suffix=self.DEFAULTEXTENSION)
             fileInfo = QFileInfo(fileName)
             filepath = fileInfo.absolutePath()
             baseName = fileInfo.baseName()
             suffix = fileInfo.suffix()
             thisfilename = filepath + baseName + '.' + suffix
             thisfilename = fileName
             self.showInfo("File name: " + thisfilename)
             gdaldatatype = gdal.GDT_Byte
             skelmatrix = None
             if self.levelValuesCheckBox.isChecked():
                 # Transform the pixel values back to the original
                 # level values
                 my_dict = {}
                 # Add zero to handle the "empty" pixels
                 my_dict[0] = 0
                 for i in range(len(self.levels)):
                     my_dict[i + 1] = self.levels[i]
                 skelmatrix = np.vectorize(my_dict.__getitem__,
                                           otypes=[np.float])(ret)
                 gdaldatatype = gdal.GDT_Int32
                 if not self.intband:
                     gdaldatatype = gdal.GDT_Float32
             else:
                 skelmatrix = ret
             outDataset = driver.Create(thisfilename, self.cols,
                                        self.rows, 1, gdaldatatype)
             if self.thinninglayer.dataProvider().crs() is not None:
                 srs = self.thinninglayer.dataProvider().crs()
                 outDataset.SetProjection(srs.toWkt().encode('ascii',
                                                            'ignore'))
             skeletonband = outDataset.GetRasterBand(1)
             skeletonband.WriteArray(skelmatrix)
             skeletonband.SetNoDataValue(NOVALUE)
             #stats = skeletonband.GetStatistics(False, True)
             #skeletonband.SetStatistics(stats[0], stats[1],
             #                                 stats[2], stats[3])
             outDataset.SetGeoTransform(geotransform)
             outDataset = None  # To close the file
             # report the result
             rlayer = QgsRasterLayer(thisfilename, baseName)
             self.layerlistchanging = True
             #QgsMapLayerRegistry.instance().addMapLayer(rlayer)
             QgsProject.instance().addMapLayer(rlayer)
             self.layerlistchanging = False
         except:
             import traceback
             self.showError("Can't write the skeleton file:  %s" %
                                self.outputRaster.text() + ' - ' +
                                traceback.format_exc())
             okb = self.button_box.button(QDialogButtonBox.Ok)
             okb.setEnabled(True)
             closb = self.button_box.button(QDialogButtonBox.Close)
             closb.setEnabled(True)
             cancb = self.button_box.button(QDialogButtonBox.Cancel)
             cancb.setEnabled(False)
             return
         QgsMessageLog.logMessage(self.tr('ThinGreyscale finished'),
                             self.THINGREYSCALE, Qgis.Info)
     else:
         # notify the user that something went wrong
         if not ok:
             self.showError(self.tr('Aborted') + '!')
         else:
             self.showError(self.tr('No skeleton created') + '!')
     self.progressBar.setValue(0.0)
     #self.aprogressBar.setValue(0.0)
     self.iterProgressBar.setValue(0.0)
     self.button_box.button(QDialogButtonBox.Ok).setEnabled(True)
     self.button_box.button(QDialogButtonBox.Close).setEnabled(True)
     self.button_box.button(QDialogButtonBox.Cancel).setEnabled(False)
 def workerFinished(self, ok, ret):
     """Handles the output from the worker and cleans up after the
        worker has finished."""
     # clean up the worker and thread
     self.showInfo("Handling the result")
     self.worker.deleteLater()
     self.thread.quit()
     self.thread.wait()
     self.thread.deleteLater()
     # remove widget from message bar (pop)
     self.iface.messageBar().popWidget(self.messageBar)
     if ok and ret is not None:
         #self.showInfo("Ret: "+str(ret[10,]))
         # Transformation:
         self.minx = self.thinninglayer.extent().xMinimum()
         self.maxx = self.thinninglayer.extent().xMaximum()
         self.miny = self.thinninglayer.extent().yMinimum()
         self.maxy = self.thinninglayer.extent().yMaximum()
         self.rows = self.thinninglayer.height()
         self.cols = self.thinninglayer.width()
         self.xres = (self.maxx - self.minx) / float(self.cols)
         self.yres = (self.maxy - self.miny) / float(self.rows)
         geotransform = (self.minx, self.xres, 0, self.maxy, 0, -self.yres)
         try:
             format = self.DEFAULTPROVIDER
             driver = gdal.GetDriverByName(format)
             NOVALUE = 0
             metadata = driver.GetMetadata()
             fileName = self.outputRaster.text()
             if self.outputRaster.text() == "":
                 self.showInfo("No output file specified, " +
                               "creating a temporary file")
                 # Get a temporary file
                 fileName = mktemp(prefix='greyskel',
                                   suffix=self.DEFAULTEXTENSION)
             fileInfo = QFileInfo(fileName)
             filepath = fileInfo.absolutePath()
             baseName = fileInfo.baseName()
             suffix = fileInfo.suffix()
             thisfilename = filepath + baseName + '.' + suffix
             thisfilename = fileName
             self.showInfo("File name: " + thisfilename)
             gdaldatatype = gdal.GDT_Byte
             skelmatrix = None
             if self.levelValuesCheckBox.isChecked():
                 # Transform the pixel values back to the original
                 # level values
                 my_dict = {}
                 # Add zero to handle the "empty" pixels
                 my_dict[0] = 0
                 for i in range(len(self.levels)):
                     my_dict[i + 1] = self.levels[i]
                 skelmatrix = np.vectorize(my_dict.__getitem__,
                                           otypes=[np.float])(ret)
                 gdaldatatype = gdal.GDT_Int32
                 if not self.intband:
                     gdaldatatype = gdal.GDT_Float32
             else:
                 skelmatrix = ret
             outDataset = driver.Create(thisfilename, self.cols, self.rows,
                                        1, gdaldatatype)
             if self.thinninglayer.dataProvider().crs() is not None:
                 srs = self.thinninglayer.dataProvider().crs()
                 outDataset.SetProjection(srs.toWkt().encode(
                     'ascii', 'ignore'))
             skeletonband = outDataset.GetRasterBand(1)
             skeletonband.WriteArray(skelmatrix)
             skeletonband.SetNoDataValue(NOVALUE)
             #stats = skeletonband.GetStatistics(False, True)
             #skeletonband.SetStatistics(stats[0], stats[1],
             #                                 stats[2], stats[3])
             outDataset.SetGeoTransform(geotransform)
             outDataset = None  # To close the file
             # report the result
             rlayer = QgsRasterLayer(thisfilename, baseName)
             self.layerlistchanging = True
             #QgsMapLayerRegistry.instance().addMapLayer(rlayer)
             QgsProject.instance().addMapLayer(rlayer)
             self.layerlistchanging = False
         except:
             import traceback
             self.showError("Can't write the skeleton file:  %s" %
                            self.outputRaster.text() + ' - ' +
                            traceback.format_exc())
             okb = self.button_box.button(QDialogButtonBox.Ok)
             okb.setEnabled(True)
             closb = self.button_box.button(QDialogButtonBox.Close)
             closb.setEnabled(True)
             cancb = self.button_box.button(QDialogButtonBox.Cancel)
             cancb.setEnabled(False)
             return
         QgsMessageLog.logMessage(self.tr('ThinGreyscale finished'),
                                  self.THINGREYSCALE, Qgis.Info)
     else:
         # notify the user that something went wrong
         if not ok:
             self.showError(self.tr('Aborted') + '!')
         else:
             self.showError(self.tr('No skeleton created') + '!')
     self.progressBar.setValue(0.0)
     #self.aprogressBar.setValue(0.0)
     self.iterProgressBar.setValue(0.0)
     self.button_box.button(QDialogButtonBox.Ok).setEnabled(True)
     self.button_box.button(QDialogButtonBox.Close).setEnabled(True)
     self.button_box.button(QDialogButtonBox.Cancel).setEnabled(False)
예제 #9
0
class GeoPackage(DataStore):
    """
    GeoPackage DataStore

    .. versionadded:: 4.0
    """

    def __init__(self, uri):
        """
        Constructor for the GeoPackage DataStore.

        :param uri: A filepath which doesn't exist
        :type uri: QFileInfo, str

        .. versionadded:: 4.0
        """
        super(GeoPackage, self).__init__(uri)
        self.vector_driver = ogr.GetDriverByName('GPKG')
        self.raster_driver = gdal.GetDriverByName('GPKG')

        if isinstance(uri, QFileInfo):
            self._uri = uri
        elif isinstance(uri, str):
            self._uri = QFileInfo(uri)
        else:
            raise ErrorDataStore('Unknown type')

        if self.uri.exists():
            raster_datasource = gdal.Open(self.uri.absoluteFilePath())
            if raster_datasource is None:
                # Let's try if it's a vector one.
                vector_datasource = self.vector_driver.Open(
                    self.uri.absoluteFilePath())
                if vector_datasource is None:
                    msg = 'The file is not a geopackage or it doesn\'t ' \
                          'contain any layers.'
                    raise ErrorDataStore(msg)
        else:
            path = self.uri.absoluteFilePath()
            # We need this variable to be created. The delete will create it.
            datasource = self.vector_driver.CreateDataSource(path)  # NOQA
            del datasource

    @property
    def uri_path(self):
        """Return the URI of the datastore as a path. It's not a layer URI.

        :return: The URI.
        :rtype: str

        .. versionadded:: 4.0
        """
        return self.uri.absolutePath()

    def is_writable(self):
        """Check if the folder is writable.

        :return: If it's writable or not.
        :rtype: bool

        .. versionadded:: 4.0
        """
        # Fixme, need to check DB permissions ?
        return self._uri.absolutePath().isWritable()

    def supports_rasters(self):
        """Check if we can support raster in the geopackage.

        :return: If it's writable or not.
        :rtype: bool

        .. versionadded:: 4.0
        """
        if int(gdal.VersionInfo('VERSION_NUM')) < 2000000:
            return False
        else:
            return True

    def _vector_layers(self):
        """Return a list of vector layers available.

        :return: List of vector layers available in the geopackage.
        :rtype: list

        .. versionadded:: 4.0
        """
        layers = []
        vector_datasource = self.vector_driver.Open(
            self.uri.absoluteFilePath())
        if vector_datasource:
            for i in range(vector_datasource.GetLayerCount()):
                layers.append(vector_datasource.GetLayer(i).GetName())
        return layers

    def _raster_layers(self):
        """Return a list of raster layers available.

        :return: List of raster layers available in the geopackage.
        :rtype: list

        .. versionadded:: 4.0
        """
        layers = []

        raster_datasource = gdal.Open(self.uri.absoluteFilePath())
        if raster_datasource:
            subdatasets = raster_datasource.GetSubDatasets()
            if len(subdatasets) == 0:
                metadata = raster_datasource.GetMetadata()
                layers.append(metadata['IDENTIFIER'])
            else:
                for subdataset in subdatasets:
                    layers.append(subdataset[0].split(':')[2])

        return layers

    def layers(self):
        """Return a list of layers available.

        :return: List of layers available in the datastore.
        :rtype: list

        .. versionadded:: 4.0
        """
        return self._vector_layers() + self._raster_layers()

    def layer_uri(self, layer_name):
        """Get layer URI.

        For a vector layer :
        /path/to/the/geopackage.gpkg|layername=my_vector_layer

        For a raster :
        GPKG:/path/to/the/geopackage.gpkg:my_raster_layer

        :param layer_name: The name of the layer to fetch.
        :type layer_name: str

        :return: The URI to the layer.
        :rtype: str

        .. versionadded:: 4.0
        """
        for layer in self._vector_layers():
            if layer == layer_name:
                uri = '{}|layername={}'.format(
                    self.uri.absoluteFilePath(), layer_name)
                return uri
        else:
            for layer in self._raster_layers():
                if layer == layer_name:
                    uri = 'GPKG:{}:{}'.format(
                        self.uri.absoluteFilePath(), layer_name)
                    return uri
            else:
                return None

    def _add_vector_layer(self, vector_layer, layer_name, save_style=False):
        """Add a vector layer to the geopackage.

        :param vector_layer: The layer to add.
        :type vector_layer: QgsVectorLayer

        :param layer_name: The name of the layer in the datastore.
        :type layer_name: str

        :param save_style: If we have to save a QML too. Default to False.
        Not implemented in geopackage !
        :type save_style: bool

        :returns: A two-tuple. The first element will be True if we could add
            the layer to the datastore. The second element will be the layer
            name which has been used or the error message.
        :rtype: (bool, str)

        .. versionadded:: 4.0
        """

        # Fixme
        # if not self.is_writable():
        #    return False, 'The destination is not writable.'

        geometry = QGIS_OGR_GEOMETRY_MAP[vector_layer.wkbType()]

        spatial_reference = osr.SpatialReference()
        qgis_spatial_reference = vector_layer.crs().authid()
        # Use 4326 as default if the spatial reference is not found
        epsg = 4326
        epsg_string = qgis_spatial_reference
        if epsg_string:
            epsg = int(epsg_string.split(':')[1])
        spatial_reference.ImportFromEPSG(epsg)

        vector_datasource = self.vector_driver.Open(
            self.uri.absoluteFilePath(), True)
        vector_datasource.CreateLayer(layer_name, spatial_reference, geometry)
        uri = '{}|layerid=0'.format(self.uri.absoluteFilePath())
        vector_layer = QgsVectorLayer(uri, layer_name, 'ogr')

        data_provider = vector_layer.dataProvider()
        for feature in vector_layer.getFeatures():
            data_provider.addFeatures([feature])

        return True, layer_name

    def _add_raster_layer(self, raster_layer, layer_name, save_style=False):
        """Add a raster layer to the folder.

        :param raster_layer: The layer to add.
        :type raster_layer: QgsRasterLayer

        :param layer_name: The name of the layer in the datastore.
        :type layer_name: str

        :param save_style: If we have to save a QML too. Default to False.
        Not implemented in geopackage !
        :type save_style: bool

        :returns: A two-tuple. The first element will be True if we could add
            the layer to the datastore. The second element will be the layer
            name which has been used or the error message.
        :rtype: (bool, str)

        .. versionadded:: 4.0
        """

        source = gdal.Open(raster_layer.source())
        array = source.GetRasterBand(1).ReadAsArray()

        x_size = source.RasterXSize
        y_size = source.RasterYSize

        output = self.raster_driver.Create(
            self.uri.absoluteFilePath(),
            x_size,
            y_size,
            1,
            gdal.GDT_Byte,
            ['APPEND_SUBDATASET=YES', 'RASTER_TABLE=%s' % layer_name]
        )

        output.SetGeoTransform(source.GetGeoTransform())
        output.SetProjection(source.GetProjection())
        output.GetRasterBand(1).WriteArray(array)

        # Once we're done, close properly the dataset
        output = None
        source = None
        return True, layer_name

    def _add_tabular_layer(self, tabular_layer, layer_name, save_style=False):
        """Add a tabular layer to the geopackage.

        :param tabular_layer: The layer to add.
        :type tabular_layer: QgsVectorLayer

        :param layer_name: The name of the layer in the datastore.
        :type layer_name: str

        :param save_style: If we have to save a QML too. Default to False.
        Not implemented in geopackage !
        :type save_style: bool

        :returns: A two-tuple. The first element will be True if we could add
            the layer to the datastore. The second element will be the layer
            name which has been used or the error message.
        :rtype: (bool, str)

        .. versionadded:: 4.0
        """
        return self._add_vector_layer(tabular_layer, layer_name, save_style)
예제 #10
0
    def demProcessed(self):
        """
        Return true if we can proceed with HRU creation.
        
        Return false if any required project setting is not found 
        in the project file
        Return true if:
        Using existing watershed and watershed grid exists and 
        is newer than dem
        or
        Not using existing watershed and filled dem exists and 
        is no older than dem, and
        watershed shapefile exists and is no older than filled dem
        """
        proj = QgsProject.instance()
        if not proj:
            QSWATUtils.loginfo('demProcessed failed: no project')
            return False
        title = proj.title()
        root = proj.layerTreeRoot()
        demFile, found = proj.readEntry(title, 'delin/DEM', '')
        if not found or demFile == '':
            QSWATUtils.loginfo('demProcessed failed: no DEM')
            return False
        demFile = proj.readPath(demFile)
        demLayer, _ = QSWATUtils.getLayerByFilename(root.findLayers(), demFile, FileTypes._DEM,
                                                    self._gv, None, QSWATUtils._WATERSHED_GROUP_NAME)
        if not demLayer:
            QSWATUtils.loginfo('demProcessed failed: no DEM layer')
            return False
        self._gv.demFile = demFile
        self._gv.elevationNoData = demLayer.dataProvider().sourceNoDataValue(1)
        units = demLayer.crs().mapUnits()
        factor = 1 if units == QgsUnitTypes.DistanceMeters else Parameters._FEETTOMETRES if units == QgsUnitTypes.DistanceFeet else 0
        if factor == 0:
            QSWATUtils.loginfo('demProcessed failed: units are {0!s}'.format(units))
            return False
        self._gv.cellArea = demLayer.rasterUnitsPerPixelX() * demLayer.rasterUnitsPerPixelY() * factor * factor
        # hillshade
        Delineation.addHillshade(demFile, root, demLayer, self._gv)
        outletFile, found = proj.readEntry(title, 'delin/outlets', '')
        if found and outletFile != '':
            outletFile = proj.readPath(outletFile)
            outletLayer, _ = \
                QSWATUtils.getLayerByFilename(root.findLayers(), outletFile, FileTypes._OUTLETS,
                                              self._gv, None, QSWATUtils._WATERSHED_GROUP_NAME)
            if not outletLayer:
                QSWATUtils.loginfo('demProcessed failed: no outlet layer')
                return False
        else:
            outletLayer = None
        self._gv.outletFile = outletFile
        self._gv.existingWshed = proj.readBoolEntry(title, 'delin/existingWshed', False)[0]
        self._gv.useGridModel = proj.readBoolEntry(title, 'delin/useGridModel', False)[0]
        self._gv.useLandscapes = proj.readBoolEntry(title, 'lsu/useLandscapes', False)[0]
        streamFile, found = proj.readEntry(title, 'delin/net', '')
        if self._gv.useGridModel or not self._gv.existingWshed:
            if not found or streamFile == '':
                QSWATUtils.loginfo('demProcessed failed: no streams shapefile')
                return False
            streamFile = proj.readPath(streamFile)
            ft = FileTypes._GRIDSTREAMS if self._gv.useGridModel else FileTypes._STREAMS
            streamLayer, _ = \
                QSWATUtils.getLayerByFilename(root.findLayers(), streamFile, ft, 
                                              self._gv, None, QSWATUtils._WATERSHED_GROUP_NAME)
            if not streamLayer:
                QSWATUtils.loginfo('demProcessed failed: no streams layer')
                return False
            self._gv.streamFile = streamFile
        if self._gv.useGridModel:
            self._gv.gridSize, found = proj.readNumEntry(title, 'delin/gridSize', 0)
            if not found or self._gv.gridSize <= 0:
                QSWATUtils.loginfo('demProcessed failed: grid size not set')
                return False
        else:
            channelFile, found = proj.readEntry(title, 'delin/channels', '')
            if not found or channelFile == '':
                QSWATUtils.loginfo('demProcessed failed: no channels shapefile')
                return False
            channelFile = proj.readPath(channelFile)
            channelLayer, _ = \
                QSWATUtils.getLayerByFilename(root.findLayers(), channelFile, FileTypes._CHANNELS, 
                                              self._gv, None, QSWATUtils._WATERSHED_GROUP_NAME)
            if not channelLayer:
                QSWATUtils.loginfo('demProcessed failed: no channels layer')
                return False
            self._gv.channelFile = channelFile
        subbasinsFile, found = proj.readEntry(title, 'delin/subbasins', '')
        if not found or subbasinsFile == '':
            QSWATUtils.loginfo('demProcessed failed: no subbasins shapefile')
            return False
        subbasinsFile = proj.readPath(subbasinsFile)
        subbasinsInfo = QFileInfo(subbasinsFile)
        subbasinsTime = subbasinsInfo.lastModified()
        subbasinsLayer, _ = \
            QSWATUtils.getLayerByFilename(root.findLayers(), subbasinsFile, FileTypes._SUBBASINS, 
                                          self._gv, None, QSWATUtils._WATERSHED_GROUP_NAME)
        if not subbasinsLayer:
            QSWATUtils.loginfo('demProcessed failed: no subbasins layer')
            return False
        self._gv.subbasinsFile = subbasinsFile
        self._gv.subsNoLakesFile, _ = proj.readEntry(title, 'delin/subsNoLakes', '')
        if self._gv.subsNoLakesFile != '':
            self._gv.subsNoLakesFile = proj.readPath(self._gv.subsNoLakesFile)
        if not self._gv.useGridModel:
            wshedFile, found = proj.readEntry(title, 'delin/wshed', '')
            if not found or wshedFile == '':
                QSWATUtils.loginfo('demProcessed failed: no wshed shapefile')
                return False
            wshedFile = proj.readPath(wshedFile)
            if self._gv.existingWshed:
                wshedLayer, _ = \
                    QSWATUtils.getLayerByFilename(root.findLayers(), wshedFile, FileTypes._EXISTINGWATERSHED, 
                                                  self._gv, None, QSWATUtils._WATERSHED_GROUP_NAME)
                if not wshedLayer:
                    QSWATUtils.loginfo('demProcessed failed: no wshed layer')
                    return False
            self._gv.wshedFile = wshedFile
        demInfo = QFileInfo(demFile)
        if not demInfo.exists():
            QSWATUtils.loginfo('demProcessed failed: no DEM info')
            return False
        base = QSWATUtils.join(demInfo.absolutePath(), demInfo.baseName())
        if not self._gv.existingWshed:
            burnFile, found = proj.readEntry(title, 'delin/burn', '')
            if found and burnFile != '':
                burnFile = proj.readPath(burnFile)
                if not os.path.exists(burnFile):
                    QSWATUtils.loginfo('demProcessed failed: no burn file')
                    return False
                self._gv.slopeFile = base + 'slope.tif'
            else:
                self._gv.slopeFile = base + 'slp.tif'
        else:
            self._gv.slopeFile = base + 'slp.tif'
        if not os.path.exists(self._gv.slopeFile):
            QSWATUtils.loginfo('demProcessed failed: no slope raster')
            return False
        self._gv.basinFile = base + 'wStream.tif'
        if not self._gv.useGridModel:
            self._gv.channelBasinFile = base + 'wChannel.tif'
            self._gv.srcChannelFile = base + 'srcChannel.tif'
        streamDrainage = proj.readBoolEntry(title, 'delin/streamDrainage', False)[0]
        if self._gv.existingWshed:
            if not self._gv.useGridModel:
                if not os.path.exists(self._gv.basinFile):
                    QSWATUtils.loginfo('demProcessed failed: no subbasins raster')
                    return False
        else:
            self._gv.pFile = base + 'p.tif'
            if not os.path.exists(self._gv.pFile):
                QSWATUtils.loginfo('demProcessed failed: no p raster')
                return False
            self._gv.felFile = base + 'fel.tif'
            felInfo = QFileInfo(self._gv.felFile)
            if not (felInfo.exists() and subbasinsInfo.exists()):
                QSWATUtils.loginfo('demProcessed failed: no filled raster')
                return False
            self._gv.ad8File = base + 'ad8.tif'
            if not os.path.exists(self._gv.ad8File):
                QSWATUtils.loginfo('demProcessed failed: no D8 accumulation raster')
                return False
            demTime = demInfo.lastModified()
            felTime = felInfo.lastModified()
            if not (demTime <= felTime <= subbasinsTime):
                QSWATUtils.loginfo('demProcessed failed: not up to date')
                return False
            self._gv.distStFile = base + 'distst.tif'
            if not os.path.exists(self._gv.distStFile):
                QSWATUtils.loginfo('demProcessed failed: no distance to outlet raster')
                return False
            self._gv.distChFile = base + 'distch.tif'
            if not self._gv.useGridModel:
                if not os.path.exists(self._gv.distChFile):
                    QSWATUtils.loginfo('demProcessed failed: no distance to channel raster')
                    return False
            valleyDepthsFile = base + 'depths.tif'
            if os.path.exists(valleyDepthsFile):
                self._gv.valleyDepthsFile = valleyDepthsFile
            # no longer compulsory
#             if not os.path.exists(self._gv.valleyDepthsFile):
#                 QSWATUtils.loginfo('demProcessed failed: no valley depths raster')
#                 return False
        if not self._gv.useGridModel:
            if not os.path.exists(self._gv.channelBasinFile):
                QSWATUtils.loginfo('demProcessed failed: no channel basins raster')
                return False
        snapFile, found = proj.readEntry(title, 'delin/snapOutlets', '')
        if found and snapFile != '':
            snapFile = proj.readPath(snapFile)
            if os.path.exists(snapFile):
                self._gv.snapFile = snapFile
            else:
                snapFile = ''
        else:
            snapFile = ''
        lakeLayer = None
        lakeFile, found = proj.readEntry(title, 'delin/lakes', '')
        if found and lakeFile != '':
            lakeFile = proj.readPath(lakeFile)
            if os.path.exists(lakeFile):
                self._gv.lakeFile = lakeFile
                lakeLayer = QgsVectorLayer(lakeFile, 'Lakes', 'ogr')
                if self._gv.useGridModel:
                    gridLakesAdded = proj.readBoolEntry(title, 'delin/gridLakesAdded', False)[0]
                    if not gridLakesAdded:
                        QSWATUtils.loginfo('demProcessed failed: grid lakes not added')
                        return False
                else:
                    chBasinNoLakeFile = base + 'wChannelNoLake.tif'
                    if os.path.exists(chBasinNoLakeFile):
                        self._gv.chBasinNoLakeFile = chBasinNoLakeFile
                        if not self._gv.existingWshed:
                            lakePointsAdded = proj.readBoolEntry(title, 'delin/lakePointsAdded', False)[0]
                            if not lakePointsAdded:
                                QSWATUtils.loginfo('demProcessed failed: lake points not added')
                                return False
                    else:
                        QSWATUtils.loginfo('demProcessed failed: no channel basins without lakes raster')
                        return False
                playaFile = os.path.splitext(self._gv.demFile)[0] + 'playa.tif'
                if QSWATUtils.isUpToDate(lakeFile, playaFile):
                    self._gv.playaFile = playaFile
        snapLayer = outletLayer if snapFile == '' else QgsVectorLayer(self._gv.snapFile, 'Snapped outlets', 'ogr')
        chanLayer = streamLayer if self._gv.useGridModel else channelLayer
        if self._gv.existingWshed:
            ad8Layer = None
        else:
            ad8Layer = QgsRasterLayer(self._gv.ad8File, 'Accumulation')
        if not self._gv.topo.setUp0(demLayer, chanLayer, snapLayer, ad8Layer, self._gv):
            return False
        basinIndex = self._gv.topo.getIndex(subbasinsLayer, QSWATTopology._POLYGONID)
        if basinIndex < 0:
            return False
        for feature in subbasinsLayer.getFeatures():
            basin = feature.attributes()[basinIndex]
            centroid = feature.geometry().centroid().asPoint()
            self._gv.topo.basinCentroids[basin] = (centroid.x(), centroid.y())
        if lakeLayer is not None:
            if not self._gv.topo.readLakesData(self._gv.db):
                QSWATUtils.loginfo('demProcessed failed: lakes data not read')
                return False
        # this can go wrong if eg the streams and watershed files exist but are inconsistent
        try:
            if not self._gv.topo.setUp(demLayer, chanLayer, subbasinsLayer, snapLayer, lakeLayer,
                                       self._gv, self._gv.existingWshed, False, self._gv.useGridModel, streamDrainage, False):
                QSWATUtils.loginfo('demProcessed failed: topo setup failed')
                return False
            if len(self._gv.topo.inlets) == 0:
                # no inlets, so no need to expand subbasins layer legend
                treeSubbasinsLayer = root.findLayer(subbasinsLayer.id())
                treeSubbasinsLayer.setExpanded(False)
        except Exception:
            QSWATUtils.loginfo('demProcessed failed: topo setup raised exception: {0}'.format(traceback.format_exc()))
            return False
        return True
예제 #11
0
    def saveList(self):
        file, _ = QFileDialog.getSaveFileName(
            None, "Save segment list to file.", self.fileName, ""
        )
        if file == "":
            return
        f = open(file, "w")
        # update selected file's folder
        fInfo = QFileInfo(file)
        self.fPath = fInfo.absolutePath()
        self.saveConf()

        if self.pluginGui.radioButton_azimuthAngle.isChecked():
            s = "Azimuth"
        elif self.pluginGui.radioButton_bearingAngle.isChecked():
            s = "Bearing"
        f.write("angle=" + s + "\n")

        if self.pluginGui.radioButton_defaultNorth.isChecked():
            s = "Coordinate_System"
        elif self.pluginGui.radioButton_magNorth.isChecked():
            s = "Magnetic"
        f.write("heading=" + s + "\n")

        if hasattr(self, "magDev") and self.magDev != 0.0:
            f.write("declination=" + str(self.magDev) + "\n")

        if self.pluginGui.radioButton_defaultUnits.isChecked():
            s = "Default"
        elif self.pluginGui.radioButton_englishUnits.isChecked():
            s = "Feet"
        f.write("dist_units=" + s + "\n")

        if self.pluginGui.radioButton_degreeUnit.isChecked():
            s = "degree"
        elif self.pluginGui.radioButton_gradianUnit.isChecked():
            s = "gradian"
        f.write("angle_unit=" + s + "\n")

        f.write(
            "startAt="
            + str(self.pluginGui.lineEdit_vertexX0.text())
            + ";"
            + str(self.pluginGui.lineEdit_vertexY0.text())
            + ";"
            + str(self.pluginGui.lineEdit_vertexZ0.text())
            + "\n"
        )

        if self.pluginGui.radioButton_boundarySurvey.isChecked():
            s = "Polygonal"
        elif self.pluginGui.radioButton_radialSurvey.isChecked():
            s = "Radial"
        f.write("survey=" + s + "\n")

        f.write("[data]\n")
        for row in range(self.pluginGui.table_segmentList.rowCount()):
            line = (
                str(self.pluginGui.table_segmentList.item(row, 0).text())
                + ";"
                + str(self.pluginGui.table_segmentList.item(row, 1).text())
                + ";"
                + str(self.pluginGui.table_segmentList.item(row, 2).text())
                + ";"
                + str(self.pluginGui.table_segmentList.item(row, 3).text())
                + ";"
                + str(self.pluginGui.table_segmentList.item(row, 4).text())
            )
            f.write(line + "\n")

        f.close()