示例#1
0
class RasterCheckerDialogWidget(QDialog):
    def __init__(self, parent=None, checks=[], command=None):
        """Constructor
        Args:
            parent: Qt parent Widget
            iface: QGiS interface
            command: Command instance with a run_it method which will be
                     called on acceptance of the dialog
        """
        super().__init__(parent)
        self.checks = checks
        self.setupUi(checks)
        self.command = command

        # rasterchecker only works on spatialte db (and not also postgres db)
        self.databases = {}
        self.all_databases = get_databases()
        for k, v in self.all_databases.items():
            if "spatialite" in k:
                if v["db_name"]:
                    self.databases[k] = v

        self.database_combo.addItems(self.databases.keys())

        # Connect signals
        self.buttonBox.accepted.connect(self.on_accept)
        self.buttonBox.rejected.connect(self.on_reject)

    def on_accept(self):
        """Accept and run the Command.run_it method."""
        db_key = self.database_combo.currentText()
        settings = self.databases[db_key]
        db_set = settings["db_settings"]

        if not os.path.isfile(db_set["db_path"]):
            msg = "sqlite %s not found" % str(db_set["db_path"])
            raise Exception(msg)

        # TODO: check_all_rasters always runs. Enable check per model entry
        checks = []
        if self.check_all_rasters.isChecked():
            checks.append("check all rasters")
            # TODO: write improve first
            # improve_when_necessary may only be checked when
            # 'check_all_rasters' is checked
            # if self.improve_when_necessary.isChecked():
            #     checks.append('improve when necessary')

        self.command.run_it(checks, db_set, settings["db_type"])
        self.accept()

    def on_reject(self):
        """Cancel"""
        self.reject()
        logger.debug("Reject")

    def closeEvent(self, event):
        """
        Close widget, called by Qt on close
        :param event: QEvent, close event
        """
        self.buttonBox.accepted.disconnect(self.on_accept)
        self.buttonBox.rejected.disconnect(self.on_reject)

        event.accept()

    def setupUi(self, checks):

        self.resize(815, 266)
        self.verticalLayout = QVBoxLayout(self)

        self.groupBox_2 = QGroupBox(self)
        self.groupBox_2.setObjectName("groupBox_2")
        self.database_combo = QComboBox(self.groupBox_2)
        self.database_combo.setGeometry(QRect(10, 30, 481, 34))
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.database_combo.sizePolicy().hasHeightForWidth())
        self.database_combo.setSizePolicy(sizePolicy)
        self.database_combo.setObjectName("database_combo")
        self.verticalLayout.addWidget(self.groupBox_2)

        self.groupBox = QGroupBox(self)
        self.verticalLayoutBox = QVBoxLayout(self.groupBox)

        self.check_all_rasters = QCheckBox(self.groupBox)
        self.check_all_rasters.setChecked(True)
        self.check_all_rasters.setDisabled(True)
        self.verticalLayoutBox.addWidget(self.check_all_rasters)

        # TODO: write improve function first
        # self.improve_when_necessary = QCheckBox(self.groupBox)
        # self.improve_when_necessary.setChecked(False)
        # self.improve_when_necessary.setDisabled(True)
        # self.verticalLayoutBox.addWidget(self.improve_when_necessary)

        self.verticalLayout.addWidget(self.groupBox)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)

        self.retranslateUi()
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        QMetaObject.connectSlotsByName(self)

    def retranslateUi(self):
        self.setWindowTitle("Raster Checker")
        self.groupBox_2.setTitle("Model schematisation database")

        self.groupBox.setTitle("Options")

        self.check_all_rasters.setText(
            "1. Check all rasters of all v2_global_settings rows")
    def download_finished(self, exception, result=None):
        """
        This is called when download_asset is finished.
        Exception is not None if download_asset raises an exception.
        result is the return value of download_asset.
        """

        # VERY SLOW TO DO HERE
        # def __pszXML(nbands):
        #     specband = '\n'.join([f"""<SpectralBand dstBand="{n+1}">\n</SpectralBand>""" for n in range(nbands)])
        #     return f"""<VRTDataset subClass="VRTPansharpenedDataset">
        # <PansharpeningOptions>
        # {specband}
        # </PansharpeningOptions>
        # </VRTDataset>"""

        def __add_images(images,
                         description,
                         outdir,
                         msgbar,
                         check,
                         vrt=True,
                         shown=True):
            if check.isChecked() and vrt:
                pan = images.pop('pan', None)  # take out pan
                if len(images) > 1:
                    # stack images in a VRT file if there are more than one image left
                    vrtfile = os.path.join(outdir, description + '.vrt')
                    # to sort in r/g/b/nir order here sort(images.keys, key=lambda k: rgbn[k])
                    _RGBN = {'red': 1, 'green': 2, 'blue': 3, 'nir': 4}
                    images_keys_ordered = sorted(images.keys(),
                                                 key=lambda k: _RGBN.get(k, 5))
                    filenames = [images[k] for k in images_keys_ordered
                                 ]  # filenames list in RGBN order
                    ds = gdal.BuildVRT(
                        vrtfile,
                        filenames,
                        options=gdal.BuildVRTOptions(separate=True,
                                                     resolution='highest'))
                    for i, bn in enumerate(images_keys_ordered):
                        b = ds.GetRasterBand(i + 1)
                        b.SetDescription(bn)
                    ds.FlushCache()
                    ds = None
                    if pan is None:
                        # nothing to do anymore, add VRT file
                        __add_images({'vrt': vrtfile},
                                     description,
                                     outdir,
                                     msgbar,
                                     check,
                                     vrt=False)
                    else:
                        # VERY SLOW TO DO HERE (perhaps as ProcessingProvider?)
                        # nbands = len(images)
                        # if nbands > 2: # may be a setting here for pansharpening choice
                        #     pan_ds = gdal.Open(pan)
                        #     pansharpened_ds = gdal.CreatePansharpenedVRT(__pszXML(nbands), pan_ds.GetRasterBand(1),
                        #     [ds.GetRasterBand(i + 1) for i in range(nbands)])
                        #     pansharpened_filename = os.path.join(outdir, description + '_pansharpened.vrt')
                        #     driver = gdal.GetDriverByName('VRT')
                        #     driver.CreateCopy(pansharpened_filename, pansharpened_ds, 0)
                        #     # add ALL
                        #     __add_images({'pansharpened': pansharpened_filename,
                        #                 'pan': pan, 'vrt': vrtfile}, description, outdir, msgbar, check, vrt=False, shown=False)
                        # else:
                        #     # just add pan and vrt files
                        __add_images({
                            'pan': pan,
                            'vrt': vrtfile
                        },
                                     description,
                                     outdir,
                                     msgbar,
                                     check,
                                     vrt=False)
                else:
                    # do not stack since there are not enough images
                    assert pan is not None  # 'pan' should be not 'None' here
                    images.update({'pan': pan})  # restore pan
                    __add_images(images,
                                 description,
                                 outdir,
                                 msgbar,
                                 check,
                                 vrt=False)
            else:
                for k in images.keys():
                    fn = images[k]
                    name = os.path.basename(fn).split('.')[0]
                    layer = QgsRasterLayer(fn, name)
                    if layer.isValid():
                        QgsProject.instance().addMapLayer(layer)
                        if not shown:
                            QgsProject.instance().layerTreeRoot().findLayer(
                                layer.id()).setItemVisibilityChecked(shown)
                msgbar.dismiss()

        # unlock another downloading
        self.downloading = False
        self.dockwidget.options.setEnabled(True)
        self.dockwidget.results.setEnabled(True)
        self.dockwidget.downloadButton.setText('Download')
        self.dockwidget.downloadButton.setStyleSheet(
            'background-color: None')  # restore default background color
        self.dockwidget.assetsList.setEnabled(True)

        if exception is None:
            if result is None:
                self.log(
                    'Finished with no exception and no result (probably manually canceled by the user)',
                    level=Qgis.Warning)
            else:
                assets = result['filenames'].keys()
                images = {
                    asset: result['filenames'][asset]
                    for asset in assets
                    if not asset.lower().endswith(('_xml', 'thumbnail'))
                }
                if images:
                    # ask to add image(s) to canvas
                    widget = self.iface.messageBar().createMessage(
                        f"Download {result['description']} finished")
                    button = QPushButton(widget)
                    button.setText('Add image(s)')
                    widget.layout().addWidget(button)
                    check = QCheckBox(widget)
                    check.setText('Stack in VRT file')
                    widget.layout().addWidget(check)
                    if len(images) < 2:
                        check.setDisabled(True)
                    button.clicked.connect(
                        lambda: __add_images(images, result['description'],
                                             result['outdir'], widget, check))
                    self.iface.messageBar().pushWidget(widget, Qgis.Info)
                else:
                    self.info(f"Download {result['description']} finished")
        else:
            self.log("Exception: {}".format(exception), level=Qgis.Critical)
            raise exception