Esempio n. 1
0
 def __init__(self, parent, msg = ''):
     '''
     progressBar class instatiation method. It creates a QgsMessageBar with provided msg and a working QProgressBar
     :param parent:
     :param msg: string
     '''
     self.iface = parent.iface
     widget = self.iface.messageBar().createMessage("GooGIS plugin:",msg)
     progressBar = QProgressBar()
     progressBar.setRange(0,0) #(1,steps)
     progressBar.setValue(0)
     progressBar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
     widget.layout().addWidget(progressBar)
     QApplication.processEvents()
     self.iface.messageBar().pushWidget(widget, Qgis.Info, 50)
     QApplication.processEvents()
Esempio n. 2
0
class WaitDialog(IgnoreKeyPressesDialog):
    def __init__(self, parent, title, progress=False):
        super().__init__(parent, Qt.WindowTitleHint)
        vbox = QVBoxLayout()
        self.progress_bar = QProgressBar()
        max_val = PROGRESS_BAR_MAX if progress else 0
        self.progress_bar.setRange(0, max_val)
        self.progress_bar.setTextVisible(False)
        vbox.addWidget(self.progress_bar)
        self.setModal(True)
        self.setWindowTitle(title)
        self.setLayout(vbox)
        self.setMaximumHeight(0)
        self.setFixedWidth(parent.width() * 0.25)
        self.show()

    def update_progress(self, progress: float) -> None:
        self.progress_bar.setValue(int(progress * PROGRESS_BAR_MAX))
        self.progress_bar.repaint()  # otherwise just updates in 1% steps
Esempio n. 3
0
def create_progress_message_bar(msg_bar, msg, no_percentage=False):
    """
    Use the messageBar of QGIS to display a message describing what's going
    on (typically during a time-consuming task), and a bar showing the
    progress of the process.

    :param msg: Message to be displayed, describing the current task
    :type: str

    :returns: progress object on which we can set the percentage of
              completion of the task through progress.setValue(percentage)
    :rtype: QProgressBar
    """
    progress_message_bar = msg_bar.createMessage(msg)
    progress = QProgressBar()
    if no_percentage:
        progress.setRange(0, 0)
    progress_message_bar.layout().addWidget(progress)
    msg_bar.pushWidget(progress_message_bar, Qgis.Info)
    return progress_message_bar, progress
Esempio n. 4
0
class progressBar:
    def __init__(self, parent, title=''):
        '''
        progressBar class instatiation method. It creates a QgsMessageBar with provided msg and a working QProgressBar
        :param parent:
        :param msg: string
        '''
        self.iface = parent.iface
        self.title = title

    def start(self, max=0, msg=''):
        self.widget = self.iface.messageBar().createMessage(self.title, msg)
        self.progressBar = QProgressBar()
        self.progressBar.setRange(0, max)
        self.progressBar.setValue(0)
        self.progressBar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.widget.layout().addWidget(self.progressBar)
        QApplication.processEvents()
        self.iface.messageBar().pushWidget(self.widget, Qgis.Info, 50)
        QApplication.processEvents()

    def setProgress(self, value):
        try:
            self.progressBar.setValue(value)
            QApplication.processEvents()
        except:
            pass

    def setMsg(self, msg):
        self.widget.setText(msg)
        QApplication.processEvents()

    def stop(self, msg=''):
        '''
        the progressbar is stopped with a succes message
        :param msg: string
        :return:
        '''
        self.iface.messageBar().clearWidgets()
        message = self.iface.messageBar().createMessage(self.title, msg)
        self.iface.messageBar().pushWidget(message, Qgis.Info, 2)
Esempio n. 5
0
    def generate_report(self, db, report_type):
        # Check if mapfish and Jasper are installed, otherwise show where to
        # download them from and return
        if not self.report_dependency.check_if_dependency_is_valid():
            self.report_dependency.download_dependency(URL_REPORTS_LIBRARIES)
            return

        java_home_set = self.java_dependency.set_java_home()
        if not java_home_set:
            self.java_dependency.get_java_on_demand()
            self.logger.info_msg(
                __name__,
                QCoreApplication.translate(
                    "ReportGenerator",
                    "Java is a prerequisite. Since it was not found, it is being configured..."
                ))
            return

        plot_layer = self.app.core.get_layer(db, db.names.LC_PLOT_T, load=True)
        if not plot_layer:
            return

        selected_plots = plot_layer.selectedFeatures()
        if not selected_plots:
            self.logger.warning_msg(
                __name__,
                QCoreApplication.translate(
                    "ReportGenerator",
                    "To generate reports, first select at least a plot!"))
            return

        # Where to store the reports?
        previous_folder = QSettings().value(
            "Asistente-LADM-COL/reports/save_into_dir", ".")
        save_into_folder = QFileDialog.getExistingDirectory(
            None,
            QCoreApplication.translate(
                "ReportGenerator",
                "Select a folder to save the reports to be generated"),
            previous_folder)
        if not save_into_folder:
            self.logger.warning_msg(
                __name__,
                QCoreApplication.translate(
                    "ReportGenerator",
                    "You need to select a folder where to save the reports before continuing."
                ))
            return
        QSettings().setValue("Asistente-LADM-COL/reports/save_into_dir",
                             save_into_folder)

        config_path = os.path.join(DEPENDENCY_REPORTS_DIR_NAME, report_type)
        json_spec_file = os.path.join(config_path, 'spec_json_file.json')

        script_name = ''
        if os.name == 'posix':
            script_name = 'print'
        elif os.name == 'nt':
            script_name = 'print.bat'

        script_path = os.path.join(DEPENDENCY_REPORTS_DIR_NAME, 'bin',
                                   script_name)
        if not os.path.isfile(script_path):
            self.logger.warning(
                __name__,
                "Script file for reports wasn't found! {}".format(script_path))
            return

        self.enable_action_requested.emit(report_type, False)

        # Update config file
        yaml_config_path = self.update_yaml_config(db, config_path)
        self.logger.debug(
            __name__, "Config file for reports: {}".format(yaml_config_path))

        total = len(selected_plots)
        step = 0
        count = 0
        tmp_dir = self.get_tmp_dir()

        # Progress bar setup
        progress = QProgressBar()
        if total == 1:
            progress.setRange(0, 0)
        else:
            progress.setRange(0, 100)
        progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.app.gui.create_progress_message_bar(
            QCoreApplication.translate("ReportGenerator",
                                       "Generating {} report{}...").format(
                                           total, '' if total == 1 else 's'),
            progress)

        polygons_with_holes = []
        multi_polygons = []

        for selected_plot in selected_plots:
            plot_id = selected_plot[db.names.T_ID_F]

            geometry = selected_plot.geometry()
            abstract_geometry = geometry.get()
            if abstract_geometry.ringCount() > 1:
                polygons_with_holes.append(str(plot_id))
                self.logger.warning(
                    __name__,
                    QCoreApplication.translate(
                        "ReportGenerator",
                        "Skipping Annex 17 for plot with {}={} because it has holes. The reporter module does not support such polygons."
                    ).format(db.names.T_ID_F, plot_id))
                continue
            if abstract_geometry.numGeometries() > 1:
                multi_polygons.append(str(plot_id))
                self.logger.warning(
                    __name__,
                    QCoreApplication.translate(
                        "ReportGenerator",
                        "Skipping Annex 17 for plot with {}={} because it is a multi-polygon. The reporter module does not support such polygons."
                    ).format(db.names.T_ID_F, plot_id))
                continue

            # Generate data file
            json_file = self.update_json_data(db, json_spec_file, plot_id,
                                              tmp_dir, report_type)
            self.logger.debug(__name__,
                              "JSON file for reports: {}".format(json_file))

            # Run sh/bat passing config and data files
            proc = QProcess()
            proc.readyReadStandardError.connect(
                functools.partial(self.stderr_ready, proc=proc))
            proc.readyReadStandardOutput.connect(
                functools.partial(self.stdout_ready, proc=proc))

            parcel_number = self.ladm_data.get_parcels_related_to_plots(
                db, [plot_id], db.names.LC_PARCEL_T_PARCEL_NUMBER_F) or ['']
            file_name = '{}_{}_{}.pdf'.format(report_type, plot_id,
                                              parcel_number[0])

            current_report_path = os.path.join(save_into_folder, file_name)
            proc.start(script_path, [
                '-config', yaml_config_path, '-spec', json_file, '-output',
                current_report_path
            ])

            if not proc.waitForStarted():
                # Grant execution permissions
                os.chmod(
                    script_path, stat.S_IXOTH | stat.S_IXGRP | stat.S_IXUSR
                    | stat.S_IRUSR | stat.S_IRGRP)
                proc.start(script_path, [
                    '-config', yaml_config_path, '-spec', json_file, '-output',
                    current_report_path
                ])

            if not proc.waitForStarted():
                proc = None
                self.logger.warning(
                    __name__, "Couldn't execute script to generate report...")
            else:
                loop = QEventLoop()
                proc.finished.connect(loop.exit)
                loop.exec()

                self.logger.debug(__name__,
                                  "{}:{}".format(plot_id, proc.exitCode()))
                if proc.exitCode() == 0:
                    count += 1

                step += 1
                progress.setValue(step * 100 / total)

        os.remove(yaml_config_path)

        self.enable_action_requested.emit(report_type, True)
        self.logger.clear_message_bar()

        if total == count:
            if total == 1:
                msg = QCoreApplication.translate(
                    "ReportGenerator",
                    "The report <a href='file:///{}'>{}</a> was successfully generated!"
                ).format(normalize_local_url(save_into_folder), file_name)
            else:
                msg = QCoreApplication.translate(
                    "ReportGenerator",
                    "All reports were successfully generated in folder <a href='file:///{path}'>{path}</a>!"
                ).format(path=normalize_local_url(save_into_folder))

            self.logger.success_msg(__name__, msg)
        else:
            details_msg = ''
            if polygons_with_holes:
                details_msg += QCoreApplication.translate(
                    "ReportGenerator",
                    " The following polygons were skipped because they have holes and are not supported: {}."
                ).format(", ".join(polygons_with_holes))
            if multi_polygons:
                details_msg += QCoreApplication.translate(
                    "ReportGenerator",
                    " The following polygons were skipped because they are multi-polygons and are not supported: {}."
                ).format(", ".join(multi_polygons))

            if total == 1:
                msg = QCoreApplication.translate(
                    "ReportGenerator",
                    "The report for plot {} couldn't be generated!{} See QGIS log (tab '{}') for details."
                ).format(plot_id, details_msg, self.LOG_TAB)
            else:
                if count == 0:
                    msg = QCoreApplication.translate(
                        "ReportGenerator",
                        "No report could be generated!{} See QGIS log (tab '{}') for details."
                    ).format(details_msg, self.LOG_TAB)
                else:
                    msg = QCoreApplication.translate(
                        "ReportGenerator",
                        "At least one report couldn't be generated!{details_msg} See QGIS log (tab '{log_tab}') for details. Go to <a href='file:///{path}'>{path}</a> to see the reports that were generated."
                    ).format(details_msg=details_msg,
                             path=normalize_local_url(save_into_folder),
                             log_tab=self.LOG_TAB)

            self.logger.warning_msg(__name__, msg)
Esempio n. 6
0
    def generate_report(self, db, button):
        # Check if mapfish and Jasper are installed, otherwise show where to
        # download them from and return
        base_path = os.path.join(os.path.expanduser('~'), 'Asistente-LADM_COL',
                                 'impresion')
        bin_path = os.path.join(base_path, 'bin')
        if not os.path.exists(bin_path):
            self.qgis_utils.message_with_button_download_report_dependency_emitted.emit(
                QCoreApplication.translate(
                    "ReportGenerator",
                    "The dependency library to generate reports is not installed. Click on the button to download and install it."
                ))
            return

        # Check version
        required_version_found = True
        version_path = os.path.join(base_path, 'version')
        if not os.path.exists(version_path):
            required_version_found = False
        else:
            version_found = ''
            with open(version_path) as f:
                version_found = f.read()
            if version_found != REPORTS_REQUIRED_VERSION:
                required_version_found = False

        if not required_version_found:
            self.qgis_utils.message_with_button_remove_report_dependency_emitted.emit(
                QCoreApplication.translate(
                    "ReportGenerator",
                    "The dependency library to generate reports was found, but does not match with the version required. Click the button to remove the installed version and try again."
                ))
            return

        # Check if JAVA_HOME path is set, otherwise use path from project Generator
        if os.name == 'nt':
            if 'JAVA_HOME' not in os.environ:
                java_path = self.get_java_path_from_project_generator()
                if not java_path:
                    self.qgis_utils.message_emitted.emit(
                        QCoreApplication.translate(
                            "ReportGenerator",
                            "Please set JAVA_HOME path in Project Generator Settings or in Environmental Variables for your OS"
                        ), Qgis.Warning)
                    return
                else:
                    os.environ["JAVA_HOME"] = java_path
                    self.log.logMessage(
                        "The JAVA_HOME path has been set using Project Generator Settings for reports.",
                        PLUGIN_NAME, Qgis.Info)

        plot_layer = self.qgis_utils.get_layer(db,
                                               PLOT_TABLE,
                                               QgsWkbTypes.PolygonGeometry,
                                               load=True)
        if plot_layer is None:
            self.qgis_utils.message_emitted.emit(
                QCoreApplication.translate(
                    "ReportGenerator",
                    "Layer 'Plot' not found in DB! {}").format(
                        db.get_description()), Qgis.Warning)
            return

        selected_plots = plot_layer.selectedFeatures()
        if not selected_plots:
            self.qgis_utils.message_emitted.emit(
                QCoreApplication.translate(
                    "ReportGenerator",
                    "To generate reports, first select at least a plot!"),
                Qgis.Warning)
            return

        # Where to store the reports?
        previous_folder = QSettings().value(
            "Asistente-LADM_COL/reports/save_into_dir", ".")
        save_into_folder = QFileDialog.getExistingDirectory(
            None,
            QCoreApplication.translate(
                "ReportGenerator",
                "Select a folder to save the reports to be generated"),
            previous_folder)
        if not save_into_folder:
            self.qgis_utils.message_emitted.emit(
                QCoreApplication.translate(
                    "ReportGenerator",
                    "You need to select a folder where to save the reports before continuing."
                ), Qgis.Warning)
            return
        QSettings().setValue("Asistente-LADM_COL/reports/save_into_dir",
                             save_into_folder)

        config_path = os.path.join(base_path, 'ANT')
        json_spec_file = os.path.join(config_path, 'spec_json_file.json')

        script_name = ''
        if os.name == 'posix':
            script_name = 'print'
        elif os.name == 'nt':
            script_name = 'print.bat'

        script_path = os.path.join(bin_path, script_name)
        if not os.path.isfile(script_path):
            print("### SCRIPT FILE WASN'T FOUND")
            return

        button.setEnabled(False)

        # Update config file
        yaml_config_path = self.update_yaml_config(db, config_path)
        print("CONFIG FILE:", yaml_config_path)

        total = len(selected_plots)
        step = 0
        count = 0
        tmp_dir = self.get_tmp_dir()

        # Progress bar setup
        progress = QProgressBar()
        if total == 1:
            progress.setRange(0, 0)
        else:
            progress.setRange(0, 100)
        progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.qgis_utils.create_progress_message_bar_emitted.emit(
            QCoreApplication.translate("ReportGenerator",
                                       "Generating {} report{}...").format(
                                           total, '' if total == 1 else 's'),
            progress)

        for selected_plot in selected_plots:
            plot_id = selected_plot[ID_FIELD]

            # Generate data file
            json_file = self.update_json_data(db, json_spec_file, plot_id,
                                              tmp_dir)
            print("JSON FILE:", json_file)

            # Run sh/bat passing config and data files
            proc = QProcess()
            proc.readyReadStandardError.connect(
                functools.partial(self.stderr_ready, proc=proc))
            proc.readyReadStandardOutput.connect(
                functools.partial(self.stdout_ready, proc=proc))

            current_report_path = os.path.join(
                save_into_folder, 'anexo_17_{}.pdf'.format(plot_id))
            proc.start(script_path, [
                '-config', yaml_config_path, '-spec', json_file, '-output',
                current_report_path
            ])

            if not proc.waitForStarted():
                # Grant execution permissions
                os.chmod(
                    script_path, stat.S_IXOTH | stat.S_IXGRP | stat.S_IXUSR
                    | stat.S_IRUSR | stat.S_IRGRP)
                proc.start(script_path, [
                    '-config', yaml_config_path, '-spec', json_file, '-output',
                    current_report_path
                ])

            if not proc.waitForStarted():
                proc = None
                print("### COULDN'T EXECUTE SCRIPT TO GENERATE REPORT...")
            else:
                loop = QEventLoop()
                proc.finished.connect(loop.exit)
                loop.exec()

                print(plot_id, ':', proc.exitCode())
                if proc.exitCode() == 0:
                    count += 1

                step += 1
                progress.setValue(step * 100 / total)

        os.remove(yaml_config_path)
        button.setEnabled(True)
        self.qgis_utils.clear_message_bar_emitted.emit()

        if total == count:
            if total == 1:
                msg = QCoreApplication.translate(
                    "ReportGenerator",
                    "The report <a href='file://{}'>anexo_17_{}.pdf</a> was successfully generated!"
                ).format(save_into_folder, plot_id)
            else:
                msg = QCoreApplication.translate(
                    "ReportGenerator",
                    "All reports were successfully generated in folder <a href='file://{path}'>{path}</a>!"
                ).format(path=save_into_folder)

            self.qgis_utils.message_with_duration_emitted.emit(
                msg, Qgis.Success, 0)
        else:
            if total == 1:
                msg = QCoreApplication.translate(
                    "ReportGenerator",
                    "The report for plot {} couldn't be generated! See QGIS log (tab 'Anexo_17') for details."
                ).format(plot_id)
            else:
                if count == 0:
                    msg = QCoreApplication.translate(
                        "ReportGenerator",
                        "No report could be generated! See QGIS log (tab 'Anexo_17') for details."
                    )
                else:
                    msg = QCoreApplication.translate(
                        "ReportGenerator",
                        "At least one report couldn't be generated! See QGIS log (tab 'Anexo_17') for details. Go to <a href='file://{path}'>{path}</a> to see the reports that were generated."
                    ).format(path=save_into_folder)

            self.qgis_utils.message_with_duration_emitted.emit(
                msg, Qgis.Warning, 0)
Esempio n. 7
0
    def doRemoveNode(self):

        toolname = "RemoveNode"

        # check that a layer is selected
        layer = self.iface.mapCanvas().currentLayer()
        if not layer:
          QMessageBox.information(None, toolname, "A topology node layer must be selected")
          return

        # check that the selected layer is a postgis one
        if layer.providerType() != 'postgres':
          QMessageBox.information(None, toolname, "A PostGIS layer must be selected")
          return

        uri = QgsDataSourceUri(layer.source())

        # get the layer schema
        toponame = str(uri.schema())
        if not toponame:
          QMessageBox.information(None, toolname, "Layer " + layer.name() + " doesn't look like a topology node layer.\n(no schema set in datasource)")
          return;

        node_id_fno = layer.dataProvider().fieldNameIndex('node_id')
        if ( node_id_fno < 0 ):
          QMessageBox.information(None, toolname, "Layer " + layer.name() + " does not have an 'node_id' field (not a topology node layer?)")
          return 

        # get the selected features
        errors = []
        selected = layer.selectedFeatures()
        if not selected:
          QMessageBox.information(None, toolname, "Select the node(s) you want to remove")
          return
        msgBar = self.iface.messageBar()
        pb = QProgressBar( msgBar )
        msgBar.pushWidget( pb, Qgis.Info, 5 )
        pb.setRange( 0, len(selected) )
        pb.setValue( 0 )
        conn = psycopg2.connect( str(uri.connectionInfo()) )
        for feature in selected:
          pb.setValue(pb.value()+1)
          # get its node_id
          node_id = getIntAttributeByIndex(feature, node_id_fno)
          try:
            cur = conn.cursor()
            cur.execute("SELECT abs((getnodeedges(%s, %s)).edge)", (toponame, node_id))
            if cur.rowcount == 2:
              (edge1_id) = cur.fetchone()
              (edge2_id) = cur.fetchone()
              cur.close()
              if edge1_id != edge2_id:
                cur = conn.cursor()
                cur.execute("SELECT ST_ModEdgeHeal(%s, %s, %s)", (toponame, edge1_id, edge2_id))
                conn.commit()
                cur.close()
              else:
                errors.append("Node " + str(node_id) + " is the only node in a ring, cannot be removed")
            elif cur.rowcount == 0:
              cur.close()
              cur = conn.cursor()
              cur.execute("SELECT ST_RemIsoNode(%s, %s)", (toponame, node_id))
              conn.commit()
              cur.close()
            else:
              cur.close()
              errors.append("Node " + str(node_id) + " is not of degree 2 nor isolated")

          except psycopg2.Error as e:
            errors.append("Removing node " + str(node_id) + ":\n" + str(e))
            conn.commit()
            cur.close()
            continue
        conn.close()

        removed = len(selected) - len(errors)
        report = "Removed " + str(removed) + " nodes over " + str(len(selected)) + " selected\n"
        if errors:
          report += "\nFailures ("
          if len(errors) > 5:
            report += "first 5 of "
          report += str(len(errors)) + "):\n\n" + "\n".join(errors[:5])
        QMessageBox.information(None, toolname, report)

        layer.removeSelection()
        self.iface.mapCanvas().refresh()
Esempio n. 8
0
class OSMDownloaderDialog(QDialog, FORM_CLASS):
    def __init__(self, iface, startX, startY, endX, endY, parent=None):
        """Constructor."""
        super(OSMDownloaderDialog, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)

        self.iface = iface

        self.setCoordinates(startX, startY, endX, endY)

        self.threadpool = QThreadPool()

        self.size = 0

        self.plugin_dir = os.path.dirname(__file__)

    def setCoordinates(self, startX, startY, endX, endY):
        if startX < endX:
            minLong = startX
            maxLong = endX
        else:
            minLong = endX
            maxLong = startX

        if startY < endY:
            minLat = startY
            maxLat = endY
        else:
            minLat = endY
            maxLat = startY

        self.wEdit.setText(str(minLong))
        self.sEdit.setText(str(minLat))
        self.eEdit.setText(str(maxLong))
        self.nEdit.setText(str(maxLat))

    @pyqtSlot()
    def on_saveButton_clicked(self):
        ret = QFileDialog.getSaveFileName(
            parent=None,
            caption='Define file name and location',
            filter='OSM Files(*.osm)')
        fileName = ret[0]

        split = fileName.split('.')
        if len(split) > 0 and split[-1] == 'osm':
            pass
        else:
            fileName += '.osm'

        self.filenameEdit.setText(fileName)

    @pyqtSlot()
    def on_button_box_accepted(self):
        if self.filenameEdit.text() == '':
            QMessageBox.warning(
                self, self.tr("Warning!"),
                self.tr("Please, select a location to save the file."))
            return

        # Initiating processing
        osmRequest = OSMRequest(self.filenameEdit.text())
        osmRequest.setParameters(self.wEdit.text(), self.sEdit.text(),
                                 self.eEdit.text(), self.nEdit.text())
        # Connecting end signal
        osmRequest.signals.processFinished.connect(self.processFinished)
        osmRequest.signals.sizeReported.connect(self.reportSize)
        osmRequest.signals.proxyOpened.connect(self.proxy)
        osmRequest.signals.errorOccurred.connect(self.errorOccurred)
        osmRequest.signals.userCanceled.connect(self.userCanceled)
        # Setting the progress bar
        # << Updated by SIGMOÉ
        self.msgBar = self.iface.messageBar()
        self.progressMessageBar = self.msgBar.createMessage(
            'Downloading data...')
        # >>
        self.progressBar = QProgressBar()
        self.progressBar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.progressMessageBar.layout().addWidget(self.progressBar)
        self.iface.messageBar().pushWidget(self.progressMessageBar, Qgis.Info)
        self.progressBar.setRange(0, 0)
        self.progressMessageBar.destroyed.connect(osmRequest.signals.cancel)
        # Starting process
        self.threadpool.start(osmRequest)

    @pyqtSlot(str)
    def proxy(self, proxy):
        self.progressMessageBar.setText('Proxy set to: ' + proxy)

    @pyqtSlot(str)
    def errorOccurred(self, message):
        QMessageBox.warning(self, 'Fatal!', message)
        self.close()

    @pyqtSlot()
    def userCanceled(self):
        QMessageBox.warning(self, 'Info!', 'Process canceled by user!')
        self.close()

    @pyqtSlot(float)
    def reportSize(self, size):
        self.size = size
        self.progressMessageBar.setText('Downloading: ' +
                                        "{0:.2f}".format(size) +
                                        ' megabytes from OSM servers...')

    @pyqtSlot(str)
    def processFinished(self, message):
        self.progressBar.setRange(0, 100)
        self.progressBar.setValue(100)
        self.progressMessageBar.setText('Downloaded ' +
                                        "{0:.2f}".format(self.size) +
                                        ' megabytes in total from OSM servers')

        if self.checkBox.isChecked():
            # << Updated by SIGMOÉ
            # Add each OSM layer with specific style
            lyr_types = [['multipolygons', 'polygon'],
                         ['multilinestrings', 'line'], ['lines', 'line'],
                         ['points', 'point']]
            for lt in lyr_types:
                lyr = self.iface.addVectorLayer(
                    self.filenameEdit.text() + '|layername=' + lt[0], 'osm',
                    'ogr')
                style = "styles/osm_mapnik_" + lt[1] + ".qml"
                qml_file = os.path.join(self.plugin_dir, style)
                lyr.loadNamedStyle(qml_file)
            # >>

        QMessageBox.warning(self, 'Info!', message)
        # << Updated by SIGMOÉ
        self.msgBar.clearWidgets()
        # >>
        self.close()
class ProjectFromOSMDialog(QtWidgets.QDialog, FORM_CLASS):
    def __init__(self, iface):
        QtWidgets.QDialog.__init__(self)
        self.iface = iface
        self.setupUi(self)

        self.path = standard_path()
        self.error = None
        self.report = []
        self.worker_thread = None
        self.running = False
        self.bbox = None
        self.json = []
        self.project = None
        self.logger = logging.getLogger("aequilibrae")

        self._run_layout = QGridLayout()

        # Area to import network for
        self.choose_place = QRadioButton()
        self.choose_place.setText("Place name")
        self.choose_place.toggled.connect(self.change_place_type)
        self.choose_place.setChecked(False)

        self.choose_canvas = QRadioButton()
        self.choose_canvas.setText("Current map canvas area")
        self.choose_canvas.setChecked(True)

        self.place = QLineEdit()
        self.place.setVisible(False)

        self.source_type_frame = QVBoxLayout()
        self.source_type_frame.setAlignment(Qt.AlignLeft)
        self.source_type_frame.addWidget(self.choose_place)
        self.source_type_frame.addWidget(self.choose_canvas)
        self.source_type_frame.addWidget(self.place)

        self.source_type_widget = QGroupBox('Target')
        self.source_type_widget.setLayout(self.source_type_frame)

        # Buttons and output
        self.but_choose_output = QPushButton()
        self.but_choose_output.setText("Choose file output")
        self.but_choose_output.clicked.connect(self.choose_output)

        self.output_path = QLineEdit()

        self.but_run = QPushButton()
        self.but_run.setText("Import network and create project")
        self.but_run.clicked.connect(self.run)

        self.buttons_frame = QVBoxLayout()
        self.buttons_frame.addWidget(self.but_choose_output)
        self.buttons_frame.addWidget(self.output_path)
        self.buttons_frame.addWidget(self.but_run)

        self.buttons_widget = QWidget()
        self.buttons_widget.setLayout(self.buttons_frame)

        self.progressbar = QProgressBar()
        self.progress_label = QLabel()

        self.update_widget = QWidget()
        self.update_frame = QVBoxLayout()
        self.update_frame.addWidget(self.progressbar)
        self.update_frame.addWidget(self.progress_label)
        self.update_widget.setLayout(self.update_frame)
        self.update_widget.setVisible(False)

        self._run_layout.addWidget(self.source_type_widget)
        self._run_layout.addWidget(self.buttons_widget)
        self._run_layout.addWidget(self.update_widget)

        self.setLayout(self._run_layout)
        self.resize(280, 250)

    def choose_output(self):
        new_name, file_type = GetOutputFileName(self, '',
                                                ["SQLite database(*.sqlite)"],
                                                ".sqlite", self.path)
        if new_name is not None:
            self.output_path.setText(new_name)

    def run(self):
        self.update_widget.setVisible(True)
        self.resize(280, 300)
        if self.choose_canvas.isChecked():
            self.report.append(
                reporter('Chose to download network for canvas area'))
            e = self.iface.mapCanvas().extent()
            bbox = [e.xMinimum(), e.yMinimum(), e.xMaximum(), e.yMaximum()]
        else:
            self.progress_label.setText('Establishing area for download')
            self.report.append(reporter('Chose to download network for place'))
            bbox, r = placegetter(self.place.text())
            self.report.extend(r)

        if bbox is None:
            self.leave()
            return

        west, south, east, north = bbox[0], bbox[1], bbox[2], bbox[3]
        self.report.append(
            reporter(
                'Downloading network for bounding box ({} {}, {}, {})'.format(
                    west, south, east, north)))

        self.bbox = bbox
        surveybox = QgsRectangle(QgsPointXY(west, south),
                                 QgsPointXY(east, north))
        geom = QgsGeometry().fromRect(surveybox)
        conv = QgsDistanceArea()
        area = conv.convertAreaMeasurement(conv.measureArea(geom),
                                           QgsUnitTypes.AreaSquareMeters)
        self.report.append(
            reporter(
                'Area for which we will download a network: {:,} km.sq'.format(
                    area / 1000000)))

        if area <= max_query_area_size:
            geometries = [[west, south, east, north]]
        else:
            parts = math.ceil(area / max_query_area_size)
            horizontal = math.ceil(math.sqrt(parts))
            vertical = math.ceil(parts / horizontal)
            dx = east - west
            dy = north - south
            geometries = []
            for i in range(horizontal):
                xmin = west + i * dx
                xmax = west + (i + 1) * dx
                for j in range(vertical):
                    ymin = south + j * dy
                    ymax = south + (j + 1) * dy
                    box = [xmin, ymin, xmax, ymax]
                    geometries.append(box)

        p = Parameters().parameters
        modes = [list(k.keys())[0] for k in p['network']['modes']]

        self.progress_label.setText('Downloading data')
        self.downloader = OSMDownloader(geometries, modes)
        self.run_download_thread()

    def final_steps(self):
        self.project = Project(self.output_path.text(), True)
        self.project.network.create_empty_tables()
        curr = self.project.conn.cursor()
        curr.execute("""ALTER TABLE links ADD COLUMN osm_id integer""")
        curr.execute("""ALTER TABLE nodes ADD COLUMN osm_id integer""")
        self.project.conn.commit()
        self.project.conn.close()
        self.builder = OSMBuilder(self.downloader.json, self.project.source)
        self.run_thread()

    def run_download_thread(self):
        self.downloader.downloading.connect(self.signal_downloader_handler)
        self.downloader.start()
        self.exec_()

    def run_thread(self):
        self.builder.building.connect(self.signal_handler)
        self.builder.start()
        self.exec_()

    def change_place_type(self):
        if self.choose_place.isChecked():
            self.place.setVisible(True)
        else:
            self.place.setVisible(False)

    def leave(self):
        self.close()
        dlg2 = ReportDialog(self.iface, self.report)
        dlg2.show()
        dlg2.exec_()

    def signal_downloader_handler(self, val):
        if val[0] == "Value":
            self.progressbar.setValue(val[1])
        elif val[0] == "maxValue":
            self.progressbar.setRange(0, val[1])
        elif val[0] == "text":
            self.progress_label.setText(val[1])
        elif val[0] == "FinishedDownloading":
            self.final_steps()

    def signal_handler(self, val):
        if val[0] == "Value":
            self.progressbar.setValue(val[1])
        elif val[0] == "maxValue":
            self.progressbar.setRange(0, val[1])
        elif val[0] == "text":
            self.progress_label.setText(val[1])
        elif val[0] == "finished_threaded_procedure":
            self.project = Project(self.output_path.text())
            self.progress_label.setText('Adding spatial indices')
            self.project.network.add_spatial_index()
            self.project.network.add_triggers()
            l = self.project.network.count_links()
            n = self.project.network.count_nodes()
            self.report.append(reporter(f'{l:,} links generated'))
            self.report.append(reporter(f'{n:,} nodes generated'))
            self.leave()
Esempio n. 10
0
    def generate_report(self, db, report_type):
        # Check if mapfish and Jasper are installed, otherwise show where to
        # download them from and return
        base_path = os.path.join(os.path.expanduser('~'), 'Asistente-LADM_COL',
                                 'impresion')
        bin_path = os.path.join(base_path, 'bin')
        if not os.path.exists(bin_path):
            self.qgis_utils.message_with_button_download_report_dependency_emitted.emit(
                QCoreApplication.translate(
                    "ReportGenerator",
                    "The dependency library to generate reports is not installed. Click on the button to download and install it."
                ))
            return

        # Check version
        required_version_found = True
        version_path = os.path.join(base_path, 'version')
        if not os.path.exists(version_path):
            required_version_found = False
        else:
            version_found = ''
            with open(version_path) as f:
                version_found = f.read()
            if version_found.strip() != REPORTS_REQUIRED_VERSION:
                required_version_found = False

        if not required_version_found:
            self.qgis_utils.message_with_button_remove_report_dependency_emitted.emit(
                QCoreApplication.translate(
                    "ReportGenerator",
                    "The dependency library to generate reports was found, but does not match with the version required. Click the button to remove the installed version and try again."
                ))
            return

        # Check if JAVA_HOME path is set, otherwise use path from QGIS Model Baker
        if os.name == 'nt':
            if 'JAVA_HOME' not in os.environ:
                self.msg = QMessageBox()
                self.msg.setIcon(QMessageBox.Information)
                self.msg.setText(
                    QCoreApplication.translate(
                        "ReportGenerator",
                        "JAVA_HOME environment variable is not defined, please define it as an enviroment variable on Windows and restart QGIS before generating the annex 17."
                    ))
                self.msg.setWindowTitle(
                    QCoreApplication.translate("ReportGenerator",
                                               "JAVA_HOME not defined"))
                self.msg.setStandardButtons(QMessageBox.Close)
                self.msg.exec_()
                return

        plot_layer = self.qgis_utils.get_layer(db,
                                               PLOT_TABLE,
                                               QgsWkbTypes.PolygonGeometry,
                                               load=True)
        if plot_layer is None:
            self.qgis_utils.message_emitted.emit(
                QCoreApplication.translate(
                    "ReportGenerator",
                    "Layer 'Plot' not found in DB! {}").format(
                        db.get_description()), Qgis.Warning)
            return

        selected_plots = plot_layer.selectedFeatures()
        if not selected_plots:
            self.qgis_utils.message_emitted.emit(
                QCoreApplication.translate(
                    "ReportGenerator",
                    "To generate reports, first select at least a plot!"),
                Qgis.Warning)
            return

        # Where to store the reports?
        previous_folder = QSettings().value(
            "Asistente-LADM_COL/reports/save_into_dir", ".")
        save_into_folder = QFileDialog.getExistingDirectory(
            None,
            QCoreApplication.translate(
                "ReportGenerator",
                "Select a folder to save the reports to be generated"),
            previous_folder)
        if not save_into_folder:
            self.qgis_utils.message_emitted.emit(
                QCoreApplication.translate(
                    "ReportGenerator",
                    "You need to select a folder where to save the reports before continuing."
                ), Qgis.Warning)
            return
        QSettings().setValue("Asistente-LADM_COL/reports/save_into_dir",
                             save_into_folder)

        config_path = os.path.join(base_path, report_type)

        json_spec_file = os.path.join(config_path, 'spec_json_file.json')

        script_name = ''
        if os.name == 'posix':
            script_name = 'print'
        elif os.name == 'nt':
            script_name = 'print.bat'

        script_path = os.path.join(bin_path, script_name)
        if not os.path.isfile(script_path):
            print("### SCRIPT FILE WASN'T FOUND")
            return

        self.enable_action_requested.emit(report_type, False)

        # Update config file
        yaml_config_path = self.update_yaml_config(db, config_path)
        print("CONFIG FILE:", yaml_config_path)

        total = len(selected_plots)
        step = 0
        count = 0
        tmp_dir = self.get_tmp_dir()

        # Progress bar setup
        progress = QProgressBar()
        if total == 1:
            progress.setRange(0, 0)
        else:
            progress.setRange(0, 100)
        progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.qgis_utils.create_progress_message_bar_emitted.emit(
            QCoreApplication.translate("ReportGenerator",
                                       "Generating {} report{}...").format(
                                           total, '' if total == 1 else 's'),
            progress)

        polygons_with_holes = []
        multi_polygons = []

        for selected_plot in selected_plots:
            plot_id = selected_plot[ID_FIELD]

            geometry = selected_plot.geometry()
            abstract_geometry = geometry.get()
            if abstract_geometry.ringCount() > 1:
                polygons_with_holes.append(str(plot_id))
                self.log.logMessage(
                    QCoreApplication.translate(
                        "ReportGenerator",
                        "Skipping Annex 17 for plot with {}={} because it has holes. The reporter module does not support such polygons."
                    ).format(ID_FIELD, plot_id), PLUGIN_NAME, Qgis.Warning)
                continue
            if abstract_geometry.numGeometries() > 1:
                multi_polygons.append(str(plot_id))
                self.log.logMessage(
                    QCoreApplication.translate(
                        "ReportGenerator",
                        "Skipping Annex 17 for plot with {}={} because it is a multi-polygon. The reporter module does not support such polygons."
                    ).format(ID_FIELD, plot_id), PLUGIN_NAME, Qgis.Warning)
                continue

            # Generate data file
            json_file = self.update_json_data(db, json_spec_file, plot_id,
                                              tmp_dir, report_type)
            print("JSON FILE:", json_file)

            # Run sh/bat passing config and data files
            proc = QProcess()
            proc.readyReadStandardError.connect(
                functools.partial(self.stderr_ready, proc=proc))
            proc.readyReadStandardOutput.connect(
                functools.partial(self.stdout_ready, proc=proc))

            parcel_number = self.ladm_data.get_parcels_related_to_plot(
                db, plot_id, PARCEL_NUMBER_FIELD) or ['']
            file_name = '{}_{}_{}.pdf'.format(report_type, plot_id,
                                              parcel_number[0])
            current_report_path = os.path.join(save_into_folder, file_name)
            proc.start(script_path, [
                '-config', yaml_config_path, '-spec', json_file, '-output',
                current_report_path
            ])

            if not proc.waitForStarted():
                # Grant execution permissions
                os.chmod(
                    script_path, stat.S_IXOTH | stat.S_IXGRP | stat.S_IXUSR
                    | stat.S_IRUSR | stat.S_IRGRP)
                proc.start(script_path, [
                    '-config', yaml_config_path, '-spec', json_file, '-output',
                    current_report_path
                ])

            if not proc.waitForStarted():
                proc = None
                print("### COULDN'T EXECUTE SCRIPT TO GENERATE REPORT...")
            else:
                loop = QEventLoop()
                proc.finished.connect(loop.exit)
                loop.exec()

                print(plot_id, ':', proc.exitCode())
                if proc.exitCode() == 0:
                    count += 1

                step += 1
                progress.setValue(step * 100 / total)

        os.remove(yaml_config_path)

        self.enable_action_requested.emit(report_type, True)
        self.qgis_utils.clear_message_bar_emitted.emit()

        if total == count:
            if total == 1:
                msg = QCoreApplication.translate(
                    "ReportGenerator",
                    "The report <a href='file:///{}'>{}</a> was successfully generated!"
                ).format(normalize_local_url(save_into_folder), file_name)
            else:
                msg = QCoreApplication.translate(
                    "ReportGenerator",
                    "All reports were successfully generated in folder <a href='file:///{path}'>{path}</a>!"
                ).format(path=normalize_local_url(save_into_folder))

            self.qgis_utils.message_with_duration_emitted.emit(
                msg, Qgis.Success, 0)
        else:
            details_msg = ''
            if polygons_with_holes:
                details_msg += QCoreApplication.translate(
                    "ReportGenerator",
                    " The following polygons were skipped because they have holes and are not supported: {}."
                ).format(", ".join(polygons_with_holes))
            if multi_polygons:
                details_msg += QCoreApplication.translate(
                    "ReportGenerator",
                    " The following polygons were skipped because they are multi-polygons and are not supported: {}."
                ).format(", ".join(multi_polygons))

            if total == 1:
                msg = QCoreApplication.translate(
                    "ReportGenerator",
                    "The report for plot {} couldn't be generated!{} See QGIS log (tab '{}') for details."
                ).format(plot_id, details_msg, self.LOG_TAB)
            else:
                if count == 0:
                    msg = QCoreApplication.translate(
                        "ReportGenerator",
                        "No report could be generated!{} See QGIS log (tab '{}') for details."
                    ).format(details_msg, self.LOG_TAB)
                else:
                    msg = QCoreApplication.translate(
                        "ReportGenerator",
                        "At least one report couldn't be generated!{details_msg} See QGIS log (tab '{log_tab}') for details. Go to <a href='file:///{path}'>{path}</a> to see the reports that were generated."
                    ).format(details_msg=details_msg,
                             path=normalize_local_url(save_into_folder),
                             log_tab=self.LOG_TAB)

            self.qgis_utils.message_with_duration_emitted.emit(
                msg, Qgis.Warning, 0)
Esempio n. 11
0
class ProgressDialog(QDialog):
    """ Progress dialog shows progress bar for algorithm.
    """
    
    def __init__(self, iface):
        QDialog.__init__(self, iface.mainWindow())
        
        self.workerThread = None
        self.state = False
        self.outputLoc = None
        self.resultStatus = None
        self.reRun = False
        self.savedProj = None
        
        # Build GUI Elements
        self.setWindowTitle("SEILAPLAN wird ausgeführt")
        self.resize(500, 100)
        self.container = QVBoxLayout()
        self.progressBar = QProgressBar(self)
        self.progressBar.setMinimumWidth(500)
        self.statusLabel = QLabel(self)
        self.hbox = QHBoxLayout()
        self.cancelButton = QDialogButtonBox()
        self.closeButton = QDialogButtonBox()
        self.resultLabel = ClickLabel(self)
        self.resultLabel.setMaximumWidth(500)
        self.resultLabel.setSizePolicy(
            QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding))
        self.resultLabel.setWordWrap(True)
        self.rerunButton = QPushButton("Berechnungen wiederholen")
        self.rerunButton.setVisible(False)
        spacer = QSpacerItem(40, 20, QSizePolicy.Expanding,
                             QSizePolicy.Minimum)
        self.cancelButton.setStandardButtons(QDialogButtonBox.Cancel)
        self.cancelButton.clicked.connect(self.onAbort)
        self.closeButton.setStandardButtons(QDialogButtonBox.Close)
        self.closeButton.clicked.connect(self.onClose)
        self.hbox.addWidget(self.rerunButton)
        self.hbox.addItem(spacer)
        self.hbox.addWidget(self.cancelButton)
        self.hbox.setAlignment(self.cancelButton, Qt.AlignHCenter)
        self.hbox.addWidget(self.closeButton)
        self.hbox.setAlignment(self.closeButton, Qt.AlignHCenter)
        self.closeButton.hide()
        
        self.container.addWidget(self.progressBar)
        self.container.addWidget(self.statusLabel)
        self.container.addWidget(self.resultLabel)
        self.container.addLayout(self.hbox)
        self.container.setSizeConstraint(QLayout.SetFixedSize)
        self.setLayout(self.container)
        
    def setThread(self, workerThread):
        self.workerThread = workerThread
        self.connectProgressSignals()
    
    def connectProgressSignals(self):
        # Connet signals of thread
        self.workerThread.sig_jobEnded.connect(self.jobEnded)
        self.workerThread.sig_jobError.connect(self.onError)
        self.workerThread.sig_value.connect(self.valueFromThread)
        self.workerThread.sig_range.connect(self.rangeFromThread)
        self.workerThread.sig_text.connect(self.textFromThread)
        self.workerThread.sig_result.connect(self.resultFromThread)
        self.rerunButton.clicked.connect(self.onRerun)
        
    def run(self):
        # Show modal dialog window (QGIS is still responsive)
        self.show()
        # start event loop
        self.exec_()
    
    def jobEnded(self, success):
        self.setWindowTitle("SEILAPLAN")
        if success:
            self.statusLabel.setText("Berechnungen abgeschlossen.")
            self.progressBar.setValue(self.progressBar.maximum())
            self.setFinalMessage()
        
        else:  # If there was an abort by the user
            self.statusLabel.setText("Berechnungen abgebrochen.")
            self.progressBar.setValue(self.progressBar.minimum())
        self.finallyDo()
        self.rerunButton.setVisible(True)
    
    def valueFromThread(self, value):
        self.progressBar.setValue(value)
    
    def rangeFromThread(self, range_vals):
        self.progressBar.setRange(range_vals[0], range_vals[1])
    
    def maxFromThread(self, max):
        self.progressBar.setValue(self.progressBar.maximum())
    
    def textFromThread(self, value):
        self.statusLabel.setText(value)
    
    def resultFromThread(self, result):
        [self.outputLoc, self.resultStatus] = result
    
    def setFinalMessage(self):
        self.resultLabel.clicked.connect(self.onResultClicked)
        self.resultLabel.blockSignals(True)
        linkToFolder = ('<html><head/><body><p></p><p><a href='
                        '"file:////{0}"><span style="text-decoration: '
                        'underline; color:#0000ff;">{0}</span></a></p>'
                        '</body></html>'.format(self.outputLoc))
        # Optimization successful
        if self.resultStatus == 1:
            self.resultLabel.setText(textOK + linkToFolder)
            self.resultLabel.blockSignals(False)
        # Cable takes off of support
        elif self.resultStatus == 2:
            self.resultLabel.setText(textSeil + linkToFolder)
            self.resultLabel.blockSignals(False)
        # Optimization partially successful
        elif self.resultStatus == 3:
            self.resultLabel.setText(textHalf + linkToFolder)
            self.resultLabel.blockSignals(False)
        # Optimization not successful
        elif self.resultStatus == 4:
            self.resultLabel.setText(textBad)
        self.setLayout(self.container)
    
    def onResultClicked(self):
        # Open a folder window
        if sys.platform == 'darwin':  # MAC
            subprocess.call(["open", "-R", self.outputLoc])
        elif sys.platform.startswith('linux'):  # LINUX
            subprocess.Popen(["xdg-open", self.outputLoc])
        elif 'win32' in sys.platform:  # WINDOWS
            from subprocess import CalledProcessError
            try:
                subprocess.check_call(['explorer', self.outputLoc])
            except CalledProcessError:
                pass
    
    def onAbort(self):
        self.setWindowTitle("SEILAPLAN")
        self.statusLabel.setText("Laufender Prozess wird abgebrochen...")
        self.workerThread.cancel()  # Terminates process cleanly
    
    def onError(self, exception_string):
        self.setWindowTitle("SEILAPLAN: Berechnung fehlgeschlagen")
        self.statusLabel.setText("Ein Fehler ist aufgetreten:")
        self.resultLabel.setText(exception_string)
        self.progressBar.setValue(self.progressBar.minimum())
        self.finallyDo()
    
    def onRerun(self):
        self.reRun = True
        self.onClose()
    
    def finallyDo(self):
        self.cancelButton.hide()
        self.closeButton.show()
    
    def onClose(self):
        self.close()
Esempio n. 12
0
class ProgressDialog(QDialog):
    """ Progress dialog shows progress bar for algorithm.
    """

    def __init__(self, iface):
        QDialog.__init__(self, iface.mainWindow())
        self.workerThread = None
        self.state = False
        self.resultStatus = None
        self.doReRun = False
        self.wasCanceled = False
        self.wasSuccessful = False
        self.savedProj = None
        self.result = None
        self.messageTxt = {
            'msg_optimierung': self.tr('Berechnung der optimalen Stuetzenpositionen...'),
            'msg_seillinie': self.tr('Berechnung der optimale Seillinie...')
        }
        
        # Build GUI Elements
        self.setWindowTitle(self.tr("SEILAPLAN wird ausgefuehrt"))
        self.resize(500, 100)
        self.container = QVBoxLayout()
        self.progressBar = QProgressBar(self)
        self.progressBar.setMinimumWidth(500)
        self.statusLabel = QLabel(self)
        self.hbox = QHBoxLayout()
        self.cancelButton = QDialogButtonBox()
        self.closeButton = QDialogButtonBox()
        self.resultLabel = QLabel(self)
        self.resultLabel.setMaximumWidth(500)
        self.resultLabel.setSizePolicy(
            QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding))
        self.resultLabel.setWordWrap(True)
        spacer1 = QSpacerItem(20, 20, QSizePolicy.Fixed,
                              QSizePolicy.Fixed)
        self.rerunButton = QPushButton(self.tr("zurueck zum Startfenster"))
        self.rerunButton.setVisible(False)
        spacer2 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                             QSizePolicy.Minimum)
        self.cancelButton.setStandardButtons(QDialogButtonBox.Cancel)
        self.cancelButton.button(QDialogButtonBox.Cancel).setText(self.tr("Abbrechen"))
        self.cancelButton.clicked.connect(self.onAbort)
        self.closeButton.setStandardButtons(QDialogButtonBox.Close)
        self.closeButton.button(QDialogButtonBox.Close).setText(self.tr("Schliessen"))
        self.closeButton.clicked.connect(self.onClose)
        self.hbox.addWidget(self.rerunButton)
        self.hbox.addItem(spacer2)
        self.hbox.addWidget(self.cancelButton)
        self.hbox.setAlignment(self.cancelButton, Qt.AlignHCenter)
        self.hbox.addWidget(self.closeButton)
        self.hbox.setAlignment(self.closeButton, Qt.AlignHCenter)
        self.closeButton.hide()
        
        self.container.addWidget(self.progressBar)
        self.container.addWidget(self.statusLabel)
        self.container.addWidget(self.resultLabel)
        self.container.addItem(spacer1)
        self.container.addLayout(self.hbox)
        self.container.setSizeConstraint(QLayout.SetFixedSize)
        self.setLayout(self.container)

    # noinspection PyMethodMayBeStatic
    def tr(self, message, **kwargs):
        """Get the translation for a string using Qt translation API.
        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString

        Parameters
        ----------
        **kwargs
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate(type(self).__name__, message)
        
    def setThread(self, workerThread):
        self.workerThread = workerThread
        self.connectThreadSignals()
    
    def connectThreadSignals(self):
        # Connect signals of thread
        self.workerThread.sig_jobEnded.connect(self.jobEnded)
        self.workerThread.sig_jobError.connect(self.onError)
        self.workerThread.sig_value.connect(self.valueFromThread)
        self.workerThread.sig_range.connect(self.rangeFromThread)
        self.workerThread.sig_text.connect(self.textFromThread)
        self.workerThread.sig_result.connect(self.resultFromThread)
        self.rerunButton.clicked.connect(self.onRerun)
        
    def run(self):
        # Show modal dialog window (QGIS is still responsive)
        self.show()
        # start event loop
        self.exec()
    
    def jobEnded(self, success):
        self.setWindowTitle("SEILAPLAN")
        if success:
            self.progressBar.setValue(self.progressBar.maximum())
            self.wasSuccessful = True
            # Close progress dialog so that adjustment window can be opened
            self.close()
        else:  # If there was an abort by the user
            self.statusLabel.setText(self.tr("Berechnungen abgebrochen."))
            self.progressBar.setValue(self.progressBar.minimum())
            self.finallyDo()
    
    def valueFromThread(self, value):
        self.progressBar.setValue(int(value))
    
    def rangeFromThread(self, range_vals):
        self.progressBar.setRange(int(round(range_vals[0])), int(round(range_vals[1])))
    
    def maxFromThread(self, max):
        self.progressBar.setValue(self.progressBar.maximum())
    
    def textFromThread(self, message):
        self.statusLabel.setText(self.messageTxt[message])
    
    def resultFromThread(self, resultStatus):
        self.resultStatus = resultStatus
        # resultStatus:
        #   1 = Optimization successful
        #   2 = Cable takes off from support
        #   3 = Optimization partially successful
    
    def onAbort(self):
        self.setWindowTitle('SEILAPLAN')
        self.statusLabel.setText(self.tr(
            'Laufender Prozess wird abgebrochen...'))
        self.workerThread.cancel()  # Terminates process cleanly
        self.wasCanceled = True
    
    def onError(self, exception_string):
        self.setWindowTitle(self.tr('SEILAPLAN: Berechnung fehlgeschlagen'))
        self.statusLabel.setText(self.tr('Ein Fehler ist aufgetreten:'))
        self.resultLabel.setText(self.tr(exception_string))
        self.resultLabel.setHidden(False)
        self.progressBar.setValue(self.progressBar.minimum())
        self.setLayout(self.container)
        self.finallyDo()
    
    def onRerun(self):
        self.doReRun = True
        self.onClose()
    
    def finallyDo(self):
        self.rerunButton.setVisible(True)
        self.cancelButton.hide()
        self.closeButton.show()
    
    def onClose(self):
        self.close()
Esempio n. 13
0
class IDESCaliWebServices:
    def __init__(self, iFace):
        self.iFace = iFace
        self.plugin_dir = os.path.dirname(__file__)
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(self.plugin_dir, 'i18n',
                                   'IDESCaliWebServices_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)
            QCoreApplication.installTranslator(self.translator)

        self.dlg = IDESCaliWebServicesDialog()
        self.dlginfo = InfoDialog()
        self.generatedService = None
        self.bar = QProgressBar()
        self.bar.setRange(0, 0)
        self.bar.setGeometry(950, 500, 200, 25)
        self.actions = []
        self.menu = self.tr(u'&Servicios WMS - Geoportal IDESC')
        self.first_start = None

    def tr(self, message):
        return QCoreApplication.translate('IDESCaliWebServices', message)

    def add_action(self,
                   icon_path,
                   text,
                   callback,
                   enabled_flag=True,
                   add_to_menu=True,
                   add_to_toolbar=True,
                   status_tip=None,
                   whats_this=None,
                   parent=None):

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            self.iFace.addToolBarIcon(action)

        if add_to_menu:
            self.iFace.addPluginToWebMenu(self.menu, action)

        self.actions.append(action)

        return action

    def initGui(self):
        self.add_all_action()
        self.dlg.table_widget.itemSelectionChanged.connect(self.updateDesc)
        self.dlg.help_button.clicked.connect(self.openDlgInfo)
        self.dlg.close_button.clicked.connect(self.closeDlg)
        self.dlg.search_box.textEdited.connect(self.search)
        self.dlg.add_button.released.connect(self.loadWebService)
        self.dlginfo.ok_dialog.released.connect(self.closeAbout)
        self.first_start = True

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iFace.removePluginWebMenu(
                self.tr(u'&Servicios WMS - Geoportal IDESC'), action)
            self.iFace.removeToolBarIcon(action)

    def run(self):
        if self.generatedService.web_map_service is not None:
            self.dlg.search_box.clear()
            self.fill_table(self.generatedService.web_map_service.contents)
            self.dlg.show()
            result = self.dlg.exec_()
            if result:
                pass

    def run_0(self):
        self.loadServiceList(Service.IDESCaliDataset.value)
        self.run()

    def add_all_action(self):
        icon_path = ':/plugins/idescali_ws/icon.png'

        self.add_action(icon_path,
                        text=self.tr(
                            service_text_map[Service.IDESCaliDataset.value]),
                        callback=self.run_0,
                        whats_this=str(Service.IDESCaliDataset.value),
                        parent=self.iFace.mainWindow())

    def loadServiceList(self, service_id: int):
        self.generatedService = WebMapServiceClass(service_id)
        url = self.generatedService.service_url
        self.bar.show()
        if self.generatedService.service_type == ServiceType.WebMapService.value:
            try:
                wms = WebMapService(url)
                self.generatedService.setWebMapService(wms)
            except Exception as e:
                QMessageBox.information(
                    None, "ERROR:",
                    'No se puede cargar este servicio en este momento.' +
                    str(e))
        elif self.generatedService.service_type == ServiceType.WebMapTileService.value:
            try:
                wmts = WebMapTileService(url)
                self.generatedService.setWebMapService(wmts)
            except Exception as e:
                QMessageBox.information(
                    None, "ERROR:",
                    'No se puede acceder a este servicio en este momento.' +
                    str(e))
        self.bar.close()

    def openDlgInfo(self):
        self.dlginfo.show()

    def closeDlg(self):
        self.generatedService = None
        self.dlg.search_box.clear()
        self.dlg.table_widget.setRowCount(0)
        self.dlg.table_widget.setColumnCount(0)
        self.dlg.layer_name_box.clear()
        self.dlg.close()
        if self.dlginfo:
            self.dlginfo.close()

    def closeAbout(self):
        if self.dlginfo:
            self.dlginfo.close()

    def fill_table(self, contentOrderedDict):
        self.dlg.table_widget.setRowCount(0)
        count = self.dlg.table_widget.rowCount()
        self.dlg.table_widget.setColumnCount(4)

        for content in contentOrderedDict:
            index = count
            name = contentOrderedDict[content].name
            title = contentOrderedDict[content].title
            abstract = contentOrderedDict[content].abstract
            self.dlg.table_widget.insertRow(index)
            self.dlg.table_widget.setItem(index, 1,
                                          QTableWidgetItem(str(name)))
            self.dlg.table_widget.setItem(index, 2,
                                          QTableWidgetItem(str(title)))
            self.dlg.table_widget.setItem(index, 3,
                                          QTableWidgetItem(str(abstract)))

        self.dlg.table_widget.setHorizontalHeaderLabels(
            ["ID", "Capa", "Nombre", "Resumen"])
        self.dlg.label_conteo.setText("Capas disponibles: " +
                                      str(len(contentOrderedDict)))
        self.setTableWidgetBehaviour()

    def setTableWidgetBehaviour(self):
        self.dlg.table_widget.setColumnWidth(0, 0)
        self.dlg.table_widget.setColumnWidth(1, 200)
        self.dlg.table_widget.setColumnWidth(2, 200)
        self.dlg.table_widget.setColumnWidth(3, 200)
        self.dlg.table_widget.horizontalHeader().setSectionResizeMode(
            QHeaderView.Fixed)
        self.dlg.table_widget.verticalHeader().setSectionResizeMode(
            QHeaderView.Fixed)

        self.dlg.table_widget.setSelectionBehavior(
            QAbstractItemView.SelectRows)
        self.dlg.table_widget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.dlg.table_widget.setSelectionMode(
            QAbstractItemView.ExtendedSelection)

    def search(self):
        criteria = self.dlg.search_box.text()
        criteria = criteria.lower()
        wms_filtered_contents = OrderedDict()
        contents = self.generatedService.web_map_service.contents
        for content in contents:
            name = contents[content].name
            if criteria in name:
                wms_filtered_contents[content] = contents[content]
        self.fill_table(wms_filtered_contents)

    def getSelectedItemsFromTable(self):
        rowNames = []
        selected = self.dlg.table_widget.selectedItems()
        if len(selected) > 0:
            for i in range(0, len(selected), 4):
                row = self.dlg.table_widget.row(selected[i])
                name = self.dlg.table_widget.item(row, 1).text()
                rowNames.append(name)

        selectedServices = OrderedDict()
        contents = self.generatedService.web_map_service.contents
        for rowName in rowNames:
            for content in contents:
                name_itr = contents[content].name
                if name_itr == rowName:
                    selectedServices[content] = contents[content]

        return selectedServices

    def updateDesc(self):
        try:
            selectedServices = self.getSelectedItemsFromTable()
            self.dlg.layer_name_box.clear()
            names = ''
            for selectedService in selectedServices:
                name_itr = selectedServices[selectedService].name
                names += name_itr + ','
            names = names[:-1]
            self.dlg.layer_name_box.setText(names)
            self.dlg.layer_name_box.setReadOnly(True)
        except:
            QgsMessageLog.logMessage(
                "No selecciono ninguna capa WMS para cargar")

    def loadWebService(self):
        # get selected items and add to the map
        self.bar.show()
        EPSG_CODE_4326 = 'EPSG:4326'
        selectedServices = self.getSelectedItemsFromTable()
        web_map_service = self.generatedService.web_map_service
        for selectedService in selectedServices:
            if self.generatedService.service_url is not None:
                layer_name = selectedServices[selectedService].name
                url = 'contextualWMSLegend=0'
                if hasattr(web_map_service[layer_name], 'crsOptions'):
                    if len(web_map_service[layer_name].crsOptions) > 0:
                        if EPSG_CODE_4326 in web_map_service[
                                layer_name].crsOptions:
                            url += '&crs=' + EPSG_CODE_4326
                            if self.generatedService.service_type == ServiceType.WebMapTileService.value:
                                url += '&tileMatrixSet=' + EPSG_CODE_4326
                        else:
                            url += '&crs=' + web_map_service[
                                layer_name].crsOptions[0]
                            if self.generatedService.service_type == ServiceType.WebMapTileService.value:
                                url += '&tileMatrixSet=' + web_map_service[
                                    layer_name].crsOptions[0]
                else:
                    url += '&crs=' + EPSG_CODE_4326
                    if self.generatedService.service_type == ServiceType.WebMapTileService.value:
                        url += '&tileMatrixSet=' + EPSG_CODE_4326
                url += '&dpiMode=7&featureCount=10&format=image/png&styles' + \
                       '&layers=' + layer_name + \
                       '&url=' + str(self.generatedService.service_url)
                rlayer = QgsRasterLayer(
                    url, selectedServices[selectedService].title, 'wms')
                if not rlayer.isValid():
                    QMessageBox.information(
                        None, "ERROR:", 'Imposible cargar las capas ' +
                        selectedServices[selectedService].title +
                        ' en este momento.')
                else:
                    QgsProject.instance().addMapLayer(rlayer)
                    self.iFace.messageBar().pushMessage(
                        "Mensaje:",
                        "Fueron cargadas las capas WMS con exito",
                        level=Qgis.Success,
                        duration=3)
            else:
                QMessageBox.information(
                    None, "ERROR:",
                    'No selecciono ninguna capa WMS para cargar')
        self.bar.close()
class OSMDownloaderDialog(QDialog, FORM_CLASS):
    def __init__(self, iface, startX, startY, endX, endY, parent=None):
        """Constructor."""
        super(OSMDownloaderDialog, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)

        self.iface = iface

        self.setCoordinates(startX, startY, endX, endY)

        self.threadpool = QThreadPool()

        self.size = 0

    def setCoordinates(self, startX, startY, endX, endY):
        if startX < endX:
            minLong = startX
            maxLong = endX
        else:
            minLong = endX
            maxLong = startX

        if startY < endY:
            minLat = startY
            maxLat = endY
        else:
            minLat = endY
            maxLat = startY

        self.wEdit.setText(str(minLong))
        self.sEdit.setText(str(minLat))
        self.eEdit.setText(str(maxLong))
        self.nEdit.setText(str(maxLat))

    @pyqtSlot()
    def on_saveButton_clicked(self):
        ret = QFileDialog.getSaveFileName(parent=None, caption='Define file name and location', filter='OSM Files(*.osm)')
        fileName = ret[0]

        split = fileName.split('.')
        if len(split)>0 and split[-1] == 'osm':
            pass
        else:
            fileName += '.osm'

        self.filenameEdit.setText(fileName)

    @pyqtSlot()
    def on_button_box_accepted(self):
        if self.filenameEdit.text() == '':
            QMessageBox.warning(self, self.tr("Warning!"), self.tr("Please, select a location to save the file."))
            return

        # Initiating processing
        osmRequest = OSMRequest(self.filenameEdit.text())
        osmRequest.setParameters(self.wEdit.text(), self.sEdit.text(), self.eEdit.text(), self.nEdit.text())
        # Connecting end signal
        osmRequest.signals.processFinished.connect(self.processFinished)
        osmRequest.signals.sizeReported.connect(self.reportSize)
        osmRequest.signals.proxyOpened.connect(self.proxy)
        osmRequest.signals.errorOccurred.connect(self.errorOccurred)
        osmRequest.signals.userCanceled.connect(self.userCanceled)
        # Setting the progress bar
        self.progressMessageBar = self.iface.messageBar().createMessage('Downloading data...')
        self.progressBar = QProgressBar()
        self.progressBar.setAlignment(Qt.AlignLeft|Qt.AlignVCenter)
        self.progressMessageBar.layout().addWidget(self.progressBar)
        self.iface.messageBar().pushWidget(self.progressMessageBar, Qgis.Info)
        self.progressBar.setRange(0, 0)
        self.progressMessageBar.destroyed.connect(osmRequest.signals.cancel)
        # Starting process
        self.threadpool.start(osmRequest)

    @pyqtSlot(str)
    def proxy(self, proxy):
        self.progressMessageBar.setText('Proxy set to: '+proxy)

    @pyqtSlot(str)
    def errorOccurred(self, message):
        QMessageBox.warning(self, 'Fatal!', message)
        self.close()

    @pyqtSlot()
    def userCanceled(self):
        QMessageBox.warning(self, 'Info!', 'Process canceled by user!')
        self.close()

    @pyqtSlot(float)
    def reportSize(self, size):
        self.size = size
        self.progressMessageBar.setText('Downloading: '+"{0:.2f}".format(size)+' megabytes from OSM servers...')

    @pyqtSlot(str)
    def processFinished(self, message):
        self.progressBar.setRange(0, 100)
        self.progressBar.setValue(100)
        self.progressMessageBar.setText('Downloaded '+"{0:.2f}".format(self.size)+' megabytes in total from OSM servers')
        QMessageBox.warning(self, 'Info!', message)

        if self.checkBox.isChecked():
            self.iface.addVectorLayer(self.filenameEdit.text(), 'osm_data', 'ogr')

        self.close()
Esempio n. 15
0
class Isogeo:
    """Isogeo plugin for QGIS LTR."""

    # attributes
    plg_version = plg_tools.plugin_metadata(base_path=plg_basepath)

    logger.info("\n\n\t========== Isogeo Search Engine for QGIS ==========")
    logger.info("OS: {0}".format(platform.platform()))
    logger.info("QGIS Version: {0}".format(Qgis.QGIS_VERSION))
    logger.info("Plugin version: {0}".format(plg_version))
    logger.info("Log level: {0}".format(log_level))

    # Screens resolution
    screens_count = QDesktopWidget().screenCount()
    for screenNbr in range(screens_count):
        sizeObject = QDesktopWidget().screenGeometry(screenNbr)
        logger.info("Screen: {}/{} - Size: {}x{}".format(
            screenNbr + 1, screens_count, sizeObject.height(),
            sizeObject.width()))
    del screens_count, sizeObject

    def __init__(self, iface):
        """Constructor.

        :param QgsInterface iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        """
        # Save reference to the QGIS interface
        self.iface = iface

        # initialize plugin directory
        self.plugin_dir = Path(__file__).parent

        # requiered `_auth` subfolder
        plg_authdir = Path(plg_basepath) / "_auth"
        if not plg_authdir.exists():
            plg_authdir.mkdir()
        else:
            pass

        # initialize locale
        try:
            locale = str(qsettings.value("locale/userLocale", "fr",
                                         type=str))[0:2]
        except TypeError as exc:
            logger.error(
                "Bad type in QSettings: {}. Original error: {}".format(
                    type(qsettings.value("locale/userLocale")), exc))
            locale = "fr"
        # load localized translation
        locale_path = (self.plugin_dir / "i18n" /
                       "isogeo_search_engine_{}.qm".format(locale))
        logger.info("Language applied: {0}".format(locale))

        if locale_path.exists():
            self.translator = QTranslator()
            self.translator.load(str(locale_path))

            if qVersion() > "4.3.3":
                QCoreApplication.installTranslator(self.translator)
            else:
                pass
        else:
            pass

        if locale == "fr":
            self.lang = "fr"
        else:
            self.lang = "en"

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr("&Isogeo")
        self.toolbar = self.iface.addToolBar("Isogeo")
        self.toolbar.setObjectName("Isogeo")
        self.pluginIsActive = False
        self.form_mng = None

        # UI submodules
        self.credits_dialog = IsogeoCredits()

        # SUBMODULES
        # instanciating
        self.informer = UserInformer(message_bar=msgBar, trad=self.tr)

        self.md_display = MetadataDisplayer()
        self.md_display.tr = self.tr

        self.approps_mng = SharesParser()
        self.approps_mng.tr = self.tr

        self.authenticator = Authenticator()

        self.api_requester = ApiRequester()
        self.api_requester.tr = self.tr

        self.form_mng = SearchFormManager(self.tr)
        self.form_mng.qs_mng.url_builder = self.api_requester.build_request_url
        self.form_mng.qs_mng.lang = self.lang

        # connecting
        self.api_requester.api_sig.connect(self.token_slot)
        self.api_requester.api_sig.connect(self.informer.request_slot)
        self.api_requester.search_sig.connect(self.search_slot)
        self.api_requester.details_sig.connect(
            self.md_display.show_complete_md)
        self.api_requester.shares_sig.connect(self.approps_mng.send_share_info)

        self.authenticator.auth_sig.connect(self.auth_slot)
        self.authenticator.ask_shares.connect(self.shares_slot)

        self.approps_mng.shares_ready.connect(self.write_shares_info)
        self.approps_mng.shares_ready.connect(self.informer.shares_slot)

        # start variables
        self.savedSearch = str
        self.loopCount = 0
        self.hardReset = False
        self.showResult = False
        self.showDetails = False
        self.store = False
        self.PostGISdict = self.form_mng.results_mng.build_postgis_dict(
            qsettings)

        self.old_text = ""
        self.page_index = 1
        self.json_path = plg_basepath / "_user/quicksearches.json"

    # noinspection PyMethodMayBeStatic
    def tr(self, message, context="Isogeo"):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.
        :param message: String for translation.
        :type message: str, QString
        :context: str, QString
        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate(context, message)

    def add_action(
        self,
        ico_path,
        text,
        callback,
        enabled_flag=True,
        add_to_menu=True,
        add_to_toolbar=True,
        status_tip=None,
        whats_this=None,
        parent=None,
    ):
        """Add a toolbar icon to the toolbar.

        :param str icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :param str text: Text that should be shown in menu items for this action.
        :param function callback: Function to be called when the action is triggered.
        :param bool enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :param bool add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :param bool add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :param str status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :param QWidget parent: Parent widget for the new action. Defaults None.
        :param str whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.
        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        """
        ico = QIcon(ico_path)
        action = QAction(ico, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)
        action.setToolTip("Isogeo (v{})".format(self.plg_version))

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            self.toolbar.addAction(action)

        if add_to_menu:
            self.iface.addPluginToWebMenu(self.menu, action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""
        ico_path = ":/plugins/Isogeo/icon.png"
        self.add_action(
            ico_path,
            text=self.tr("Search within Isogeo catalogs"),
            callback=self.run,
            parent=self.iface.mainWindow(),
        )

    # -------------------------------------------------------------------------
    def onClosePlugin(self):
        """Cleanup necessary items here when plugin dockwidget is closed."""
        # save base portal URL in qsettings
        qsettings.setValue("isogeo/settings/portal_base_url",
                           self.form_mng.input_portal_url.text())
        # save cache
        self.form_mng.results_mng.cache_mng.dumper()
        # disconnects
        self.form_mng.closingPlugin.disconnect(self.onClosePlugin)

        # remove this statement if dockwidget is to remain
        # for reuse if plugin is reopened
        # Commented next statement since it causes QGIS crashe
        # when closing the docked window:
        self.form_mng = None
        self.pluginIsActive = False

    def unload(self):
        """Remove the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginWebMenu(self.tr("&Isogeo"), action)
            try:
                self.iface.mainWindow().statusBar().removeWidget(self.bar)
            except:
                pass
            self.iface.removeToolBarIcon(action)
            self.form_mng = None
            logger.handlers = []
        # remove the toolbar
        del self.toolbar

    # --- AUTHENTICATION ------------------------------------------------------
    def user_authentication(self):
        """Test the validity of the user id and secret.
        This is the first major function the plugin calls when executed. It
        retrieves the id and secret from the config file. If they are set to
        their default value, it asks for them.
        If not, it tries to send a request.
        """
        self.savedSearch = "first"
        self.form_mng.switch_widgets_on_and_off(0)
        api_init = self.authenticator.manage_api_initialization()
        if api_init[0]:
            self.api_requester.setup_api_params(api_init[1])
        else:
            pass

    def auth_slot(self, auth_signal: str):
        if auth_signal == "ok":
            self.user_authentication()
        else:
            self.authenticator.ui_auth_form.btn_ok_cancel.buttons(
            )[0].setEnabled(False)
            pass

    def token_slot(self, token_signal: str):
        """ Slot connected to ApiRequester.api_sig signal emitted when a response to
        a token request has been received from Isogeo's API or when the content of
        a response to any type of request can't be parsed. The 'api_sig' parameter
        correspond to the string passed by ApiRequester.handle_reply method (see
        modules/api/request.py). The value of this parameter depend on the response's
        content received from Isogeo's API.

        :param str token_signal: a string passed by the signal whose value determines
        what will be done. Options :
            - "ok" : Authentication has succeeded, the token is stored so it sends
            a search request to the API.
            - "creds_issue" : User's credentials are wrong so it displays the authentication
            form to provide good ones.
            - "NoInternet" : Asks to user to check his Internet connection.
        """
        if token_signal == "ok":
            if self.savedSearch == "first":
                logger.debug("First search since plugin started.")
                self.authenticator.first_auth = False
                self.shares_slot()
            else:
                self.api_requester.send_request()

        elif token_signal == "creds_issue":
            self.authenticator.ui_auth_form.btn_ok_cancel.buttons(
            )[0].setEnabled(False)
        else:
            self.pluginIsActive = False

    def shares_slot(self):
        logger.debug("Asking application properties to the Isogeo API.")
        self.api_requester.send_request(request_type="shares")

    # --- SEARCH --------------------------------------------------------------
    def search(self, show: bool = False, page_change: int = 0):
        """ Slot connected to signals emitted by 'advances search', 'order' or
        'keywords' comboboxes, also by 'show results', 'next page' or 'previous
        page' buttons when a user interacts with one of them. It retrieves the
        selected parameters and establishes the corresponding URL, and then sends
        a search request to the API, by calling ApiRequester.send_request().

        :param bool show: True if the 'show results', 'next page' or 'previous page'
        button was pressed
        :param int page_change: -1 if 'previous page' button was pressed, 1 if
        'next page' button was pressed, 0 otherwise
        """
        logger.debug(
            "Search function called. Building the url that is to be sent"
            "to the API")
        # Disabling all user inputs during the search function is running
        self.form_mng.switch_widgets_on_and_off(0)

        if self.store is True:
            # Store the previous search
            name = self.tr("Last search")
            self.form_mng.qs_mng.write_params(name, "Last")
            # update quick searches combobox
            saved_searches = list(self.form_mng.qs_mng.load_file())
            self.form_mng.pop_qs_cbbs(items_list=saved_searches)
            self.store = False
        else:
            pass

        # STORING ALL THE INFORMATIONS NEEDED TO BUILD THE URL
        # Widget position
        params = self.form_mng.save_params()
        # Info for _limit parameter
        if show is True:
            # Adding the loading bar
            self.add_loading_bar()
            self.showResult = True
            params["show"] = True
        else:
            params["show"] = False
        # Info for _offset parameter
        if page_change != 0:
            if page_change < 0 and self.page_index > 1:
                self.page_index -= 1
            elif page_change > 0 and self.page_index < plg_tools.results_pages_counter(
                    total=self.results_count):
                self.page_index += 1
            else:
                return False
        else:
            self.page_index = 1
        params["page"] = self.page_index
        # Info for _lang parameter
        params["lang"] = self.lang
        # URL BUILDING FUNCTION CALLED.
        self.api_requester.currentUrl = self.api_requester.build_request_url(
            params)
        # Sending the request to Isogeo API
        self.api_requester.send_request()
        return

    def search_slot(self, result: dict, tags: dict):
        """ Slot connected to ApiRequester.search_sig signal. It updates widgets, using
        SearchFormManager appropiate methods to fill them from 'tags' parameter and put
        them in the right status. It also display the results contained in 'result'
        parameter by calling ResultManager.show_results method if necessary.

        :param dict result: parsed content of API's reply to a search request (passed by
        ApiRequester.handle_reply method)
        :param dict tags: tags contained in API's reply parsed and classed into a dict
        (passed by ApiRequester.handle_reply method)
        """
        QgsMessageLog.logMessage(
            message="Query sent & received: {}".format(result.get("query")),
            tag="Isogeo",
            level=0,
        )
        # Save entered text and filters in search form
        self.form_mng.old_text = self.form_mng.txt_input.text()
        params = self.form_mng.save_params()

        # Show how many results there are
        self.results_count = result.get("total")
        self.form_mng.btn_show.setText(
            str(self.results_count) + self.tr(" results"))
        page_count = str(
            plg_tools.results_pages_counter(total=self.results_count))
        self.form_mng.lbl_page.setText("page " + str(self.page_index) +
                                       self.tr(" on ") + page_count)

        # Clear widgets
        self.form_mng.tbl_result.clearContents()
        self.form_mng.tbl_result.setRowCount(0)

        # Initialize the widgets that dont't need to be updated
        if self.savedSearch == "_default" or self.hardReset is True:
            logger.debug("Default search or reset.")
            self.form_mng.init_steps()
        else:
            logger.debug("Not default search nor reset.")
            pass

        # Filling Advanced search comboboxes from tags
        self.form_mng.pop_as_cbbs(tags)
        # Filling quick searches comboboxes from json file (also the one in settings tab)
        qs_list = list(self.form_mng.qs_mng.load_file().keys())
        self.form_mng.pop_qs_cbbs(qs_list)
        # Sorting Advanced search comboboxes
        for cbb in self.cbbs_search_advanced:
            cbb.model().sort(0)

        # Putting comboboxes' selected index to the appropriate location
        # and updating key words checkable combobox
        if self.hardReset is True:
            # In case of a hard reset, we don't have to worry about comboboxes' selected index
            logger.debug("Reset search")
            self.form_mng.update_cbb_keywords(
                tags_keywords=tags.get("keywords"))
        else:
            logger.debug("Classical search or quicksearch (no reset search)")
            if self.savedSearch == "":
                # Putting all the comboboxes selected index to their previous location.
                logger.debug("Classic search case (not quicksearch)")
                # Setting widgets to their previous index
                self.form_mng.set_ccb_index(params=params)
                # Updating the keywords special combobox (filling + indexing)
                self.form_mng.update_cbb_keywords(
                    tags_keywords=tags.get("keywords"),
                    selected_keywords=params.get("keys"),
                )
            else:
                # Putting all the comboboxes selected index
                # according to params found in the json file
                logger.debug("Quicksearch case: {}".format(self.savedSearch))
                # Opening the json to get quick search's params
                search_params = self.form_mng.qs_mng.load_file().get(
                    self.savedSearch)
                # Putting widgets to their previous states according to the json content
                self.form_mng.set_ccb_index(params=search_params,
                                            quicksearch=self.savedSearch)
                self.savedSearch = ""
                # Updating the keywords special combobox (filling + indexing)
                keywords_list = [
                    v for k, v in search_params.items()
                    if k.startswith("keyword")
                ]
                self.form_mng.update_cbb_keywords(
                    tags_keywords=tags.get("keywords"),
                    selected_keywords=keywords_list)

        # tweaking
        plg_tools._ui_tweaker(
            ui_widgets=self.form_mng.tab_search.findChildren(QComboBox))

        # Formatting show result button according to the number of results
        if self.results_count == 0:
            self.form_mng.btn_show.setEnabled(False)
            self.form_mng.btn_show.setStyleSheet("QPushButton { }")
        else:
            self.form_mng.btn_show.setEnabled(True)
            self.form_mng.btn_show.setStyleSheet(
                "QPushButton "
                "{background-color: rgb(255, 144, 0); color: white}")

        # Showing result : if button 'show result', 'next page' or 'previous page' pressed
        if self.showResult is True:
            self.form_mng.fill_tbl_result(
                content=result,
                page_index=self.page_index,
                results_count=self.results_count,
            )
            iface.mainWindow().statusBar().removeWidget(self.bar)
            self.store = True
        else:
            pass

        # Re enable all user input fields now the search function is
        # finished.
        self.form_mng.switch_widgets_on_and_off(1)
        # Reseting attributes values
        self.hardReset = False
        self.showResult = False

    def set_widget_status(self):
        """Set a few variable and send the request to Isogeo API."""
        selected_search = self.form_mng.cbb_quicksearch_use.currentText()
        logger.debug("Quicksearch selected: {}".format(selected_search))
        # load quicksearches
        saved_searches = self.form_mng.qs_mng.load_file()
        if selected_search != self.tr("Quicksearches"):
            self.form_mng.switch_widgets_on_and_off(0)  # disable search form
            # check if selected search can be found
            if selected_search in saved_searches:
                self.savedSearch = selected_search
                search_params = saved_searches.get(selected_search)
                logger.debug(
                    "Quicksearch found in saved searches and"
                    " related search params have just been loaded from.")
            elif selected_search not in saved_searches and "_default" in saved_searches:
                logger.warning("Selected search ({}) not found."
                               "'_default' will be used instead.")
                self.savedSearch = "_default"
                search_params = saved_searches.get("_default")
            else:
                logger.error(
                    "Selected search ({}) and '_default' do not exist.".format(
                        selected_search))
                return

            # Check projection settings in loaded search params
            if "epsg" in search_params:
                epsg = int(plg_tools.get_map_crs().split(":")[1])
                logger.debug(
                    "Specific SRS found in search params: {}".format(epsg))
                if epsg == search_params.get("epsg"):
                    canvas = iface.mapCanvas()
                    e = search_params.get("extent")
                    rect = QgsRectangle(e[0], e[1], e[2], e[3])
                    canvas.setExtent(rect)
                    canvas.refresh()
                else:
                    canvas = iface.mapCanvas()
                    canvas.mapRenderer().setProjectionsEnabled(True)
                    canvas.mapRenderer().setDestinationCrs(
                        QgsCoordinateReferenceSystem(
                            search_params.get("epsg"),
                            QgsCoordinateReferenceSystem.EpsgCrsId,
                        ))
                    e = search_params.get("extent")
                    rect = QgsRectangle(e[0], e[1], e[2], e[3])
                    canvas.setExtent(rect)
                    canvas.refresh()
            # load request
            self.api_requester.currentUrl = search_params.get("url")
            self.api_requester.send_request()
        else:
            if self.savedSearch == "first":
                logger.debug("First search. Launch '_default' search.")

                self.savedSearch = "_default"
                search_params = saved_searches.get("_default")

                self.api_requester.currentUrl = search_params.get("url")
                self.api_requester.send_request()

            else:
                logger.debug("No quicksearch selected.")

    def edited_search(self):
        """On the Qline edited signal, decide weither a search has to be launched."""
        try:
            logger.debug("Editing finished signal sent.")
        except AttributeError:
            pass
        if self.form_mng.txt_input.text() == self.old_text:
            logger.debug("The lineEdit text hasn't changed."
                         " So pass without sending a request.")
        else:
            logger.debug("The line Edit text changed."
                         " Calls the search function.")
            if self.form_mng.txt_input.text() == "Ici c'est Isogeo !":
                plg_tools.special_search("isogeo")
                self.form_mng.txt_input.clear()
                return
            elif self.form_mng.txt_input.text() == "Picasa":
                plg_tools.special_search("picasa")
                self.form_mng.txt_input.clear()
                return
            else:
                pass
            self.search()

    def reinitialize_search(self):
        """Clear all widget, putting them all back to their default value.

        Clear all widget and send a request to the API (which ends up updating
        the fields : send_request() calls handle_reply(), which calls
        update_fields())
        """
        logger.debug("Reset search function called.")
        self.hardReset = True
        # clear widgets
        self.form_mng.reinit_widgets()
        # launch search
        self.search()

    # -- UTILS ----------------------------------------------------------------
    def add_loading_bar(self):
        """Display a progress bar."""
        self.bar = QProgressBar()
        self.bar.setRange(0, 0)
        self.bar.setFixedWidth(120)
        self.iface.mainWindow().statusBar().insertPermanentWidget(0, self.bar)

    def send_details_request(self, md_id):
        """Send a request for aditionnal info about one data.

        :param str md_id: UUID of metadata to retrieve
        """
        logger.debug("Full metatada sheet asked. Building the url.")
        self.api_requester.currentUrl = "{}/resources/{}{}".format(
            self.api_requester.api_url_base,
            md_id,
            "?_include=conditions,contacts,coordinate-system,events,"
            "feature-attributes,limitations,keywords,specifications",
        )
        self.api_requester.send_request("details")

    def write_shares_info(self, text: str):
        """Write informations about the shares in the Settings pannel.
        See: #87

        :param text str: share informations from Isogeo API
        """
        if text != "no_shares":
            logger.info("Displaying application properties.")
            self.authenticator.ui_auth_form.btn_ok_cancel.buttons(
            )[0].setEnabled(True)
            self.form_mng.txt_shares.setText(text)
            if self.savedSearch == "first":
                self.set_widget_status()
            else:
                pass
        else:
            self.pluginIsActive = False
        # method ending
        return

    # -- LAUNCH PAD------------------------------------------------------------
    # This function is launched when the plugin is activated.
    def run(self):
        """Run method that loads and starts the plugin."""
        if not self.pluginIsActive:
            logger.info("Opening (display) the plugin...")
            self.pluginIsActive = True
            # dockwidget may not exist if:
            #    first run of plugin
            #    removed on close (see self.onClosePlugin method)
            if self.form_mng is None:
                # Create the dockwidget (after translation) and keep reference
                self.form_mng = SearchFormManager(self.tr)
                self.form_mng.qs_mng.url_builder = self.api_requester.build_request_url
                self.form_mng.qs_mng.lang = self.lang
                logger.debug("Plugin load time: {}".format(
                    plugin_times.get(plg_reg_name, "NR")))
            else:
                pass

            # connect to provide cleanup on closing of dockwidget
            self.form_mng.closingPlugin.connect(self.onClosePlugin)

            # show the dockwidget
            # TODO: fix to allow choice of dock location
            self.iface.addDockWidget(Qt.RightDockWidgetArea, self.form_mng)
            self.form_mng.show()
        else:
            pass

        # Fixing a qgis.core bug that shows a warning banner "connexion time
        # out" whenever a request is sent (even successfully) See :
        # http://gis.stackexchange.com/questions/136369/download-file-from-network-using-pyqgis-2-x#comment299999_136427
        # msgBar.widgetAdded.connect(msgBar.clearWidgets)
        """ --- CONNECTING UI WIDGETS <-> FUNCTIONS --- """
        # shortcuts
        self.cbbs_search_advanced = self.form_mng.grp_filters.findChildren(
            QComboBox)
        # -- Search form ------------------------------------------------------
        # search terms text input
        self.form_mng.txt_input.editingFinished.connect(self.edited_search)
        # reset search button
        self.form_mng.btn_reinit.pressed.connect(self.reinitialize_search)
        # filters comboboxes
        self.form_mng.cbb_contact.activated.connect(self.search)
        self.form_mng.cbb_format.activated.connect(self.search)
        self.form_mng.cbb_geofilter.activated.connect(self.search)
        self.form_mng.cbb_inspire.activated.connect(self.search)
        self.form_mng.cbb_license.activated.connect(self.search)
        self.form_mng.cbb_owner.activated.connect(self.search)
        self.form_mng.cbb_srs.activated.connect(self.search)
        self.form_mng.cbb_type.activated.connect(self.search)
        self.form_mng.kw_sig.connect(self.search)

        # -- Results table ----------------------------------------------------
        # show and order results
        self.form_mng.btn_show.pressed.connect(partial(self.search, show=True))
        self.form_mng.cbb_ob.activated.connect(partial(self.search, show=True))
        self.form_mng.cbb_od.activated.connect(partial(self.search, show=True))
        # pagination
        self.form_mng.btn_next.pressed.connect(
            partial(self.search, show=True, page_change=1))
        self.form_mng.btn_previous.pressed.connect(
            partial(self.search, show=True, page_change=-1))
        # metadata display
        self.form_mng.results_mng.md_asked.connect(self.send_details_request)

        # -- Quicksearches ----------------------------------------------------

        # select and use
        self.form_mng.cbb_quicksearch_use.activated.connect(
            self.set_widget_status)

        # # -- Settings tab - Search --------------------------------------------
        # button to empty the cache of filepaths #135
        self.form_mng.btn_cache_trash.pressed.connect(
            self.form_mng.results_mng.cache_mng.cleaner)

        # -- Settings tab - Application authentication ------------------------
        # Change user -> see below for authentication form
        self.form_mng.btn_change_user.pressed.connect(
            self.authenticator.display_auth_form)
        # share text window
        self.form_mng.txt_shares.setOpenLinks(False)
        self.form_mng.txt_shares.anchorClicked.connect(plg_tools.open_webpage)

        # -- Settings tab - Resources -----------------------------------------
        # report and log - see #53 and  #139
        self.form_mng.btn_log_dir.setIcon(ico_log)
        self.form_mng.btn_log_dir.pressed.connect(
            partial(plg_tools.open_dir_file, target=plg_logdir))
        self.form_mng.btn_report.pressed.connect(
            partial(
                plg_tools.open_webpage,
                link="https://github.com/isogeo/isogeo-plugin-qgis/issues/new?"
                "assignees=&template=bug_report.md&title={}"
                " - plugin v{} QGIS {} ({})&labels=bug&milestone=4".format(
                    self.tr("TITLE ISSUE REPORTED"),
                    plg_tools.plugin_metadata(base_path=plg_basepath),
                    Qgis.QGIS_VERSION,
                    platform.platform(),
                ),
            ))
        # help button
        self.form_mng.btn_help.pressed.connect(
            partial(plg_tools.open_webpage,
                    link="http://help.isogeo.com/qgis/"))
        # view credits - see: #52
        self.form_mng.btn_credits.pressed.connect(self.credits_dialog.show)

        # -- Settings tab - Isogeo Portal settings ------------------------
        self.form_mng.input_portal_url.setText(
            qsettings.value("isogeo/settings/portal_base_url"))
        """ ------- EXECUTED AFTER PLUGIN IS LAUNCHED --------------------- """
        self.form_mng.setWindowTitle("Isogeo - {}".format(self.plg_version))
        # add translator method in others modules
        plg_tools.tr = self.tr
        self.authenticator.tr = self.tr
        self.authenticator.lang = self.lang
        # checks
        plg_tools.check_proxy_configuration()  # 22
        self.form_mng.cbb_chck_kw.setEnabled(
            plg_tools.test_qgis_style())  # see #137
        # self.form_mng.cbb_chck_kw.setMaximumSize(QSize(250, 25))
        self.form_mng.txt_input.setFocus()
        # load cache file
        self.form_mng.results_mng.cache_mng.loader()
        # connect limitations checker to user informer
        self.form_mng.results_mng.lim_checker.lim_sig.connect(
            self.informer.lim_slot)
        # launch authentication
        self.user_authentication()
Esempio n. 16
0
class BhuvanWebServices:

    def __init__(self, iFace):
        # Save reference to the QGIS interface
        self.iFace = iFace
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(
            self.plugin_dir,
            'i18n',
            'BhuvanWebServices_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)
            QCoreApplication.installTranslator(self.translator)

        self.dlg = BhuvanWebServicesDialog()
        self.dlginfo = InfoDialog()
        self.generatedService = None
        self.bar = QProgressBar()
        self.bar.setRange(0, 0)
        self.bar.setGeometry(950, 500, 200, 25)

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&Bhuvan Web Services')

        # Check if plugin was started the first time in current QGIS session
        # Must be set in initGui() to survive plugin reloads
        self.first_start = None

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('BhuvanWebServices', message)

    def add_action(
            self,
            icon_path,
            text,
            callback,
            enabled_flag=True,
            add_to_menu=True,
            add_to_toolbar=True,
            status_tip=None,
            whats_this=None,
            parent=None):
        """Add a toolbar icon to the toolbar.

        :param icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :type icon_path: str

        :param text: Text that should be shown in menu items for this action.
        :type text: str

        :param callback: Function to be called when the action is triggered.
        :type callback: function

        :param enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :type enabled_flag: bool

        :param add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :type add_to_menu: bool

        :param add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool

        :param status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :type status_tip: str

        :param parent: Parent widget for the new action. Defaults None.
        :type parent: QWidget

        :param whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.

        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        """

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            # Adds plugin icon to Plugins toolbar
            self.iFace.addToolBarIcon(action)

        if add_to_menu:
            self.iFace.addPluginToWebMenu(
                self.menu,
                action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        self.add_all_action()
        self.dlg.table_widget.itemSelectionChanged.connect(self.updateDesc)
        self.dlg.help_button.clicked.connect(self.openDlgInfo)
        self.dlg.close_button.clicked.connect(self.closeDlg)
        self.dlg.search_box.textEdited.connect(self.search)
        self.dlg.add_button.released.connect(self.loadWebService)

        # will be set False in run()
        self.first_start = True

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iFace.removePluginWebMenu(
                self.tr(u'&Bhuvan Web Services'),
                action)
            self.iFace.removeToolBarIcon(action)

    def run(self):
        if self.generatedService.web_map_service is not None:
            self.dlg.search_box.clear()
            self.fill_table(self.generatedService.web_map_service.contents)
            self.dlg.show()
            result = self.dlg.exec_()
            if result:
                pass

    def run_0(self):
        self.loadServiceList(Service.BhuvanPanchayat.value)
        self.run()

    def run_1(self):
        self.loadServiceList(Service.LULC205KDataset.value)
        self.run()

    def run_2(self):
        self.loadServiceList(Service.BhuvanV1WMS.value)
        self.run()

    def run_3(self):
        self.loadServiceList(Service.BhuvanV2WMS.value)
        self.run()

    def run_4(self):
        self.loadServiceList(Service.BhuvanV1WMTS.value)
        self.run()

    def run_5(self):
        self.loadServiceList(Service.BhuvanV2WMTS.value)
        self.run()

    def add_all_action(self):
        icon_path = ':/plugins/bhuvan_web_services/icon.png'

        self.add_action(icon_path,
                        text=self.tr(service_text_map[Service.BhuvanPanchayat.value]),
                        callback=self.run_0,
                        whats_this=str(Service.BhuvanPanchayat.value),
                        parent=self.iFace.mainWindow())

        self.add_action(icon_path,
                        text=self.tr(service_text_map[Service.LULC205KDataset.value]),
                        callback=self.run_1,
                        whats_this=str(Service.LULC205KDataset.value),
                        parent=self.iFace.mainWindow())

        self.add_action(icon_path,
                        text=self.tr(service_text_map[Service.BhuvanV1WMS.value]),
                        callback=self.run_2,
                        whats_this=str(Service.BhuvanV1WMS.value),
                        parent=self.iFace.mainWindow())

        self.add_action(icon_path,
                        text=self.tr(service_text_map[Service.BhuvanV2WMS.value]),
                        callback=self.run_3,
                        whats_this=str(Service.BhuvanV2WMS.value),
                        parent=self.iFace.mainWindow())

        self.add_action(icon_path,
                        text=self.tr(service_text_map[Service.BhuvanV1WMTS.value]),
                        callback=self.run_4,
                        whats_this=str(Service.BhuvanV1WMTS.value),
                        parent=self.iFace.mainWindow())

        self.add_action(icon_path,
                        text=self.tr(service_text_map[Service.BhuvanV2WMTS.value]),
                        callback=self.run_5,
                        whats_this=str(Service.BhuvanV2WMTS.value),
                        parent=self.iFace.mainWindow())


    def loadServiceList(self, service_id: int):
        self.iFace.messageBar().pushMessage('Info: ', 'Please wait loading layers ... ', level=Qgis.Info)
        self.bar.show()
        self.iFace.mainWindow().repaint()
        self.generatedService = WebMapServiceClass(service_id)
        url = self.generatedService.service_url
        if self.generatedService.service_type == ServiceType.WebMapService.value:
            try:
                wms = WebMapService(url)
                self.generatedService.setWebMapService(wms)
            except Exception as e:
                QMessageBox.information(None, "ERROR:", 'Unable to load this service now.' + str(e))
        elif self.generatedService.service_type == ServiceType.WebMapTileService.value:
            try:
                wmts = WebMapTileService(url)
                self.generatedService.setWebMapService(wmts)
            except Exception as e:
                QMessageBox.information(None, "ERROR:", 'Unable to load this service now.' + str(e))
        self.bar.close()

    def openDlgInfo(self):
        self.dlginfo.show()

    def closeDlg(self):
        self.generatedService = None
        self.dlg.search_box.clear()
        self.dlg.table_widget.setRowCount(0)
        self.dlg.table_widget.setColumnCount(0)
        self.dlg.layer_name_box.clear()
        self.dlg.close()
        if self.dlginfo:
            self.dlginfo.close()

    def fill_table(self, contentOrderedDict):
        self.dlg.table_widget.setRowCount(0)
        count = self.dlg.table_widget.rowCount()
        self.dlg.table_widget.setColumnCount(4)

        for content in contentOrderedDict:
            index = count
            # id_int = int(contentOrderedDict[content].index[2:])
            name = contentOrderedDict[content].name
            title = contentOrderedDict[content].title
            abstract = contentOrderedDict[content].abstract
            self.dlg.table_widget.insertRow(index)  # inserts a blank row
            # lets fill that row:
            # self.dlg.table_widget.setItem(index, 0, QTableWidgetItem(str(id_int)))  # fills in with the ID
            self.dlg.table_widget.setItem(index, 1, QTableWidgetItem(str(name)))  # fills in with the Name
            self.dlg.table_widget.setItem(index, 2, QTableWidgetItem(str(title)))  # fills in with the Title
            self.dlg.table_widget.setItem(index, 3, QTableWidgetItem(str(abstract)))  # fills in with Abstract

        self.dlg.table_widget.setHorizontalHeaderLabels(["ID", "Name", "Title", "Abstract"])
        self.setTableWidgetBehaviour()

    def setTableWidgetBehaviour(self):
        # set row and column sizes and lock them
        self.dlg.table_widget.setColumnWidth(0, 0)
        self.dlg.table_widget.setColumnWidth(1, 200)
        self.dlg.table_widget.setColumnWidth(2, 200)
        self.dlg.table_widget.setColumnWidth(3, 200)
        self.dlg.table_widget.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed)
        self.dlg.table_widget.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)

        self.dlg.table_widget.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.dlg.table_widget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.dlg.table_widget.setSelectionMode(QAbstractItemView.ExtendedSelection)

    def search(self):
        criteria = self.dlg.search_box.text()
        criteria = criteria.lower()
        wms_filtered_contents = OrderedDict()
        contents = self.generatedService.web_map_service.contents
        for content in contents:
            name = contents[content].name
            if criteria in name:
                wms_filtered_contents[content] = contents[content]
        self.fill_table(wms_filtered_contents)

    def getSelectedItemsFromTable(self):
        rowNames = []
        selected = self.dlg.table_widget.selectedItems()
        if len(selected) > 0:
            for i in range(0, len(selected), 4):
                row = self.dlg.table_widget.row(selected[i])
                name = self.dlg.table_widget.item(row, 1).text()
                rowNames.append(name)

        selectedServices = OrderedDict()
        contents = self.generatedService.web_map_service.contents
        for rowName in rowNames:
            for content in contents:
                name_itr = contents[content].name
                if name_itr == rowName:
                    selectedServices[content] = contents[content]

        return selectedServices

    def updateDesc(self):
        selectedServices = self.getSelectedItemsFromTable()
        self.dlg.layer_name_box.clear()
        names = ''
        for selectedService in selectedServices:
            name_itr = selectedServices[selectedService].name
            names += name_itr + ','
        names = names[:-1]
        self.dlg.layer_name_box.setText(names)
        self.dlg.layer_name_box.setReadOnly(True)

    def loadWebService(self):
        # get selected items and add to the map
        self.bar.show()
        EPSG_CODE_4326 = 'EPSG:4326'
        selectedServices = self.getSelectedItemsFromTable()
        web_map_service = self.generatedService.web_map_service
        for selectedService in selectedServices:
            if self.generatedService.service_url is not None:
                layer_name = selectedServices[selectedService].name
                url = 'contextualWMSLegend=0'
                if hasattr(web_map_service[layer_name], 'crsOptions'):
                    if len(web_map_service[layer_name].crsOptions) > 0:
                        if EPSG_CODE_4326 in web_map_service[layer_name].crsOptions:
                            url += '&crs=' + EPSG_CODE_4326
                            if self.generatedService.service_type == ServiceType.WebMapTileService.value:
                                    url += '&tileMatrixSet=' + EPSG_CODE_4326
                        else:
                            url += '&crs=' + web_map_service[layer_name].crsOptions[0]
                            if self.generatedService.service_type == ServiceType.WebMapTileService.value:
                                    url += '&tileMatrixSet=' + web_map_service[layer_name].crsOptions[0]
                else:
                    url += '&crs=' + EPSG_CODE_4326
                    if self.generatedService.service_type == ServiceType.WebMapTileService.value:
                        url += '&tileMatrixSet=' + EPSG_CODE_4326
                url += '&dpiMode=7&featureCount=10&format=image/png&styles' + \
                       '&layers=' + layer_name + \
                       '&url=' + str(self.generatedService.service_url)
                rlayer = QgsRasterLayer(url, selectedServices[selectedService].title, 'wms')
                if not rlayer.isValid():
                    QMessageBox.information(None, "ERROR:", 'Unable to load ' +
                                            selectedServices[selectedService].title +
                                            ' this layer now.')
                else:
                    QgsProject.instance().addMapLayer(rlayer)
            else:
                QMessageBox.information(None, "ERROR:", 'Service url is None')
        self.bar.close()