示例#1
0
class ImportProjectDialog(QDialog, Ui_ImportProject):
    projectsDatabaseHasChanged = pyqtSignal()

    def __init__(self, iface, parent=None):
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.iface = iface
        self.message_bar = self.iface.messageBar()

        self.okButton = self.buttonBox.button(QDialogButtonBox.Ok)
        self.okButton.setText("Import")

        self.settings = QSettings("CatAIS", "VeriSO")
        self.input_itf_path = QFileInfo(
            self.settings.value("file/import/input_itf_path")).absolutePath()

        # members
        self.modules = None
        self.app_module = None
        self.app_module_name = None
        self.ili = None
        self.epsg = None
        self.itf = None
        self.data_date = None
        self.notes = None
        self.db_host = None
        self.db_name = None
        self.db_schema = None
        self.db_port = None
        self.db_user = None
        self.db_pwd = None
        self.db_admin = None
        self.db_admin_pwd = None
        self.projects_database = None
        self.projects_root_directory = None
        self.process = None

    def init_gui(self):
        """Initialize the dialog:
        Set the current date.
        Accept only lower characters as project name (= database schema).
        Fill modules combobox.
        """
        today = QDateTime.currentDateTime()
        self.dateTimeEdit.setDateTime(today)
        self.dateTimeEdit.setCalendarPopup(True)

        # You are only allowed to use lower case characters as project name (
        # = database schema).
        self.lineEditDbSchema.setValidator(
            QRegExpValidator(QRegExp("^[a-z][a-z0-9_]+"),
                             self.lineEditDbSchema))

        # Fill out the modules combobox.
        try:
            modules_dir = os.path.join(get_modules_dir())
            modules = []

            for module_name in get_subdirs(modules_dir):
                module_file = os.path.join(modules_dir, module_name,
                                           'module.yml')
                if os.path.isfile(module_file):
                    module = yaml_load_file(module_file)
                    module['dirname'] = module_name
                    modules.append(module)

            if modules:
                sorted_modules_list = sorted(modules,
                                             key=lambda k: k['displayname'])
                self.cmbBoxAppModule.clear()
                for module in sorted_modules_list:
                    self.cmbBoxAppModule.addItem(str(module["displayname"]),
                                                 module)
                self.cmbBoxAppModule.insertItem(0, "", None)
                self.cmbBoxAppModule.setCurrentIndex(0)
        except Exception as e:
            message = "Error while parsing the available modules."
            self.message_bar.pushMessage("VeriSO",
                                         tr(message),
                                         QgsMessageBar.CRITICAL,
                                         duration=0)
            QgsMessageLog.logMessage(str(e), "VeriSO", QgsMessageLog.CRITICAL)
            return

        self.cmbBoxIliModelName.insertItem(0, "", None)

        return True

    # noinspection PyPep8Naming
    @pyqtSignature("on_btnProjectName_clicked()")
    def on_btnProjectName_clicked(self):
        """Check wether the project (=database schema) already exists.
        """
        project_name = self.lineEditDbSchema.text().strip()

        if len(project_name) <= 0:
            self.lineEditDbSchema.setPlaceholderText(tr('Enter a valid name'))
        else:
            project_found = self.check_project_name(project_name)

            if project_found == -1:
                message = "An error occured while connecting the database."
                self.message_bar.pushMessage("VeriSO",
                                             tr(message),
                                             QgsMessageBar.CRITICAL,
                                             duration=0)
                return

            elif project_found == 1:
                message = "Project name already exists."
                self.message_bar.pushWarning("VeriSO", tr(message))
                return

            elif project_found == 0:
                message = "Project name is valid."
                self.message_bar.pushSuccess("VeriSO", tr(message))
                return True

    def check_project_name(self, project_name):
        """Makes a database request and checks if the given schema already
        exists.
        
        Returns:
            -1 if an error occured. 0 if schema was not found. 1 if schema
            already exists.
        """

        self.db_host = self.settings.value("options/db/host")
        self.db_name = self.settings.value("options/db/name")
        self.db_port = self.settings.value("options/db/port")
        self.db_user = self.settings.value("options/db/user")
        self.db_pwd = self.settings.value("options/db/pwd")
        self.db_admin = self.settings.value("options/db/admin")
        self.db_admin_pwd = self.settings.value("options/db/adminpwd")

        # 'public' will not be found with the query.
        if project_name == "public":
            return 1

        try:
            db = open_psql_db(self.db_host, self.db_name, self.db_port,
                              self.db_admin, self.db_admin_pwd)

            sql = "SELECT schema_name FROM information_schema.schemata WHERE " \
                  "schema_name = '%s';" % self.lineEditDbSchema.text().strip()
            query = db.exec_(sql)

            if query.isActive():
                count = query.size()
                db.close
                del db

                if count > 0:
                    return 1
                else:
                    return 0

        except Exception as e:
            QgsMessageLog.logMessage(str(e), "VeriSO", QgsMessageLog.CRITICAL)
            return -1

    # noinspection PyPep8Naming
    @pyqtSignature("on_cmbBoxAppModule_currentIndexChanged(int)")
    def on_cmbBoxAppModule_currentIndexChanged(self, idx):
        """Fill out the model name combobox with all interlis models you can
        use with a specific module.
        """
        self.cmbBoxIliModelName.clear()
        module_data = self.cmbBoxAppModule.itemData(idx)

        if module_data:
            ilimodels = module_data["ilimodels"]

            self.app_module = module_data["dirname"]
            self.app_module_name = self.cmbBoxAppModule.currentText()

            for i in range(len(ilimodels)):
                model_name = ilimodels[i]["ilimodel"]
                reference_frame = ilimodels[i]["referenceframe"]
                self.cmbBoxIliModelName.insertItem(
                    self.cmbBoxIliModelName.count(), str(model_name),
                    ilimodels[i])
            self.cmbBoxIliModelName.insertItem(0, "", None)

            if len(ilimodels) == 1:
                self.cmbBoxIliModelName.setCurrentIndex(1)
                self.cmbBoxIliModelName.setEnabled(False)
            else:
                self.cmbBoxIliModelName.setCurrentIndex(0)
                self.cmbBoxIliModelName.setEnabled(True)

        else:
            self.app_module = ""
            self.app_module_name = ""

    # noinspection PyPep8Naming,PyPep8Naming
    @pyqtSignature("on_cmbBoxIliModelName_currentIndexChanged(int)")
    def on_cmbBoxIliModelName_currentIndexChanged(self, idx):
        """Fill out the reference frame lineedit (read only). 
        """
        module_data = self.cmbBoxIliModelName.itemData(idx)

        if module_data:
            self.ili = module_data["ilimodel"]
            self.epsg = module_data["epsg"]
            reference_frame = module_data["referenceframe"]
            self.lineEditRefFrame.setText(
                str(reference_frame) + " (EPSG:" + str(self.epsg) + ")")
        else:
            self.ili = ""
            self.epsg = ""
            self.lineEditRefFrame.clear()

    # noinspection PyPep8Naming,PyPep8Naming
    @pyqtSignature("on_btnBrowseInputFile_clicked()")
    def on_btnBrowseInputFile_clicked(self):
        file_path = QFileDialog.getOpenFileName(
            self, tr("Choose interlis transfer file"), self.input_itf_path,
            "ITF (*.itf *.ITF)")
        file_info = QFileInfo(file_path)
        self.lineEditInputFile.setText(file_info.absoluteFilePath())

    def accept(self):
        """Collecting all the stuff we need to know to start the import process.
        """
        # Save the settings.
        self.settings.setValue("file/import/input_itf_path",
                               self.lineEditInputFile.text())
        self.settings.setValue("file/import/ili", self.ili)

        # Check if project name (db schema) already exists.
        project_name = self.lineEditDbSchema.text().strip()
        if len(project_name) > 0:
            project_found = self.check_project_name(project_name)

            if project_found == -1:
                message = "An error occured while connecting the database."
                self.message_bar.pushMessage("VeriSO",
                                             tr(message),
                                             QgsMessageBar.CRITICAL,
                                             duration=0)
                return

            elif project_found == 1:
                message = "Project name already exists."
                self.message_bar.pushWarning("VeriSO", tr(message))
                QgsMessageLog.logMessage(tr(message), "VeriSO",
                                         QgsMessageLog.WARNING)
                return

        # Gather all data/information for ili2pg arguments.
        self.itf = self.lineEditInputFile.text().strip()
        self.db_schema = self.lineEditDbSchema.text().strip()

        self.data_date = self.dateTimeEdit.date().toString("yyyy-MM-dd")

        self.notes = self.textEditNotes.toPlainText().strip()
        if len(self.notes) > 10000:
            message = "Notes are to big (allowed 10000 characters): "
            self.message_bar.pushMessage("VeriSO",
                                         tr(message) + str(len(self.notes)),
                                         QgsMessageBar.CRITICAL,
                                         duration=0)
            QgsMessageLog.logMessage(
                str(message) + str(len(self.notes)), "VeriSO",
                QgsMessageLog.WARNING)
            return

        self.projects_database = self.settings.value(
            "options/general/projects_database", "")
        self.projects_root_directory = self.settings.value(
            "options/general/projects_root_directory", "")

        import_jar = self.settings.value("options/import/jar", "")
        import_vm_arguments = self.settings.value(
            "options/import/vm_arguments", "")
        # Check if we have everything we need.
        if not os.path.isfile(
                self.projects_database) and self.projects_database != "":
            self.message_bar.pushWarning(
                "VeriSO",
                tr("Projects database not "
                   "found: ") + str(self.projects_database))
            return

        if self.itf == "":
            self.message_bar.pushWarning(
                "VeriSO", tr("No Interlis transfer file "
                             "set."))
            return

        if self.ili == "":
            self.message_bar.pushWarning("VeriSO",
                                         tr("No Interlis model name set."))
            return

        if self.db_schema == "":
            self.message_bar.pushWarning("VeriSO", tr("No project name set."))
            return

        if self.cmbBoxAppModule.currentIndex() == 0:
            self.message_bar.pushWarning(
                "VeriSO", tr("No application module "
                             "chosen."))
            return

        if not self.db_host:
            self.message_bar.pushWarning(
                "VeriSO", tr("Missing database host "
                             "parameter."))
            return

        if not self.db_name:
            self.message_bar.pushWarning(
                "VeriSO", tr("Missing database name "
                             "parameter."))
            return

        if not self.db_port:
            self.message_bar.pushWarning(
                "VeriSO", tr("Missing database port "
                             "parameter."))
            return

        if not self.db_user:
            self.message_bar.pushWarning(
                "VeriSO", tr("Missing database user "
                             "parameter."))
            return

        if not self.db_pwd:
            self.message_bar.pushWarning(
                "VeriSO", tr("Missing database password "
                             "parameter."))
            return

        if not self.db_admin:
            self.message_bar.pushWarning(
                "VeriSO", tr("Missing database administrator parameter."))
            return

        if not self.db_admin_pwd:
            self.message_bar.pushWarning(
                "VeriSO",
                tr("Missing database administrator password parameter."))
            return

        if self.projects_root_directory == "":
            self.message_bar.pushWarning(
                "VeriSO", tr("No root directory for "
                             "projects "
                             "set."))
            return

        if self.projects_database == "":
            self.message_bar.pushInfo(
                "VeriSO",
                tr("No projects database found. Will create one in the "
                   "project root directory."))

        if import_jar == "":
            self.message_bar.pushWarning("VeriSO",
                                         tr("No jar file set for import."))
            return

        self.textEditImportOutput.clear()

        # Set all the arguments for ili2pg.
        arguments = []

        vm_arguments_list = import_vm_arguments.split(" ")
        for arg in vm_arguments_list:
            arguments.append(arg)

        arguments.append("-jar")
        arguments.append(import_jar)
        arguments.append("--import")
        arguments.append("--dbhost")
        arguments.append(self.db_host)
        arguments.append("--dbport")
        arguments.append(self.db_port)
        arguments.append("--dbdatabase")
        arguments.append(self.db_name)
        arguments.append("--dbschema")
        arguments.append(self.db_schema)
        arguments.append("--dbusr")
        arguments.append(self.db_admin)
        arguments.append("--dbpwd")
        arguments.append(self.db_admin_pwd)
        arguments.append("--modeldir")
        model_dir = ';'.join(
            self.settings.value("options/model_repositories/repositories"))
        arguments.append(model_dir)
        arguments.append("--models")
        arguments.append(self.ili)
        arguments.append("--defaultSrsAuth")
        arguments.append("EPSG")
        arguments.append("--defaultSrsCode")
        arguments.append(self.epsg)
        # TODO: ili2pg has a lot of  options. At least some of them should be
        #  exposed to the user.
        arguments.append("--t_id_Name")
        arguments.append("ogc_fid")
        arguments.append("--importTid")
        arguments.append("--createGeomIdx")
        arguments.append("--createEnumTabs")
        arguments.append("--createEnumTxtCol")
        arguments.append("--createEnumColAsItfCode")
        arguments.append("--nameByTopic")
        arguments.append("--strokeArcs")
        arguments.append(self.itf)

        self.process = QProcess()
        self.process.readyReadStandardOutput.connect(self.read_output)
        self.process.readyReadStandardError.connect(self.read_error)
        self.process.finished.connect(self.finish_import)

        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.buttonBox.setEnabled(False)
        self.report_progress("Info: Starting ili2pg")
        self.report_progress("Info: java %s" % ' '.join(arguments))

        try:
            self.process.start("java", arguments)
        except Exception as e:
            self.restore_cursor()
            message = "Could not start import process."
            self.message_bar.pushMessage("VeriSO",
                                         tr(message),
                                         QgsMessageBar.CRITICAL,
                                         duration=0)
            QgsMessageLog.logMessage(str(e), "VeriSO", QgsMessageLog.CRITICAL)

    def restore_cursor(self):
        QApplication.restoreOverrideCursor()
        self.buttonBox.setEnabled(True)

    def read_output(self):
        output = self.process.readAllStandardOutput()
        self.show_output(output)

    def read_error(self):
        error = self.process.readAllStandardError()
        self.show_output(error)

    def show_output(self, byte_array):
        unicode_text = byte_array.data().decode('utf-8')
        self.report_progress(unicode_text)

    def finish_import(self, exit_code):
        """
        Check if import was successful.
        :param exitCode: the exit code of the process
        :return: None
        """
        try:
            # read the output of ili2pg
            self.read_import_output()

            # Get the postprocessing queries that are stored in a sqlite
            # database.
            # Placeholder (e.g. $$DBSCHEMA, $$EPSG etc ) will be replaced.
            sql_queries = self.get_postprocessing_queries()

            # Do the postprocessing in the postgresql database.
            self.postprocess_data(sql_queries)

            # Update the projects database
            self.update_projects_database()

            # Create the project directory in the root directory.
            directory = self.create_project_directory()

        except VerisoError as e:
            self.message_bar.pushMessage("VeriSO",
                                         tr(str(e)),
                                         QgsMessageBar.CRITICAL,
                                         duration=0)
            return
        finally:
            self.restore_cursor()

        # When we reach here we can claim a successful import.
        message = "Import process finished."
        self.report_progress(message, 'green')
        self.message_bar.pushInfo("VeriSO", tr(message))

    def read_import_output(self):
        """
        Reads the output of the ili2pg conversion
        :return:
        """
        output = self.textEditImportOutput.toPlainText()
        if output.find("Info: ...import done") < 0 or output.find(
                "compiler failed") >= 0:
            message = "Import process not successfully finished."
            raise VerisoError(message)

    def create_project_directory(self):
        """Creates a directory with the same name as the project (db schema) 
        in the project root directory. This will be for exports, maps etc.
        It emits a projects database changed signal.
        
        Returns:
          False: If the directory could not be created. Otherwise True.
        """
        try:
            os.makedirs(
                os.path.join(str(self.projects_root_directory),
                             str(self.db_schema)))
            return True
        except Exception as e:
            message = "Something went wrong while creating project directory."
            raise VerisoError(message, e)

    def update_projects_database(self):
        """Updates the sqlite projects database.
        
        Returns:
          False: When there an error occured. Otherswise True.
        """
        error_message = ("Something went wrong while updating projects "
                         "database. You need to delete the database schema "
                         "manually.")

        try:
            # Create a new projects database if there is none (copy one from
            # the templates).
            if self.projects_database == "":
                template = QDir.convertSeparators(
                    QDir.cleanPath(
                        QgsApplication.qgisSettingsDirPath() +
                        "/python/plugins/veriso/templates/template_projects"
                        ".db"))
                self.projects_database = QDir.convertSeparators(
                    QDir.cleanPath(self.projects_root_directory +
                                   "/projects.db"))
                shutil.copyfile(template, self.projects_database)
                self.settings.setValue("options/general/projects_database",
                                       self.projects_database)

            db = get_projects_db()

            project_root_directory = QDir.convertSeparators(
                QDir.cleanPath(self.projects_root_directory + "/" +
                               str(self.db_schema)))

            values = (self.db_schema, self.db_schema, self.db_host,
                      self.db_name, self.db_port, self.db_schema, self.db_user,
                      self.db_pwd, self.db_admin, self.db_admin_pwd, self.epsg,
                      self.ili, self.app_module, self.app_module_name,
                      self.projects_root_directory, project_root_directory,
                      self.data_date, self.notes, self.itf)
            values = "VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'," \
                     "'%s', '%s', 'postgres', '%s', '%s', '%s', '%s', '%s', " \
                     "'%s', '%s', '%s', '%s')" % values

            sql = "INSERT INTO projects (id, displayname, dbhost, dbname, " \
                  "dbport, dbschema, dbuser, dbpwd, dbadmin, dbadminpwd, " \
                  "provider, epsg, ilimodelname, appmodule, appmodulename, " \
                  "projectrootdir, projectdir, datadate, notes, itf)" + values

            query = db.exec_(sql)

            if not query.isActive():
                message = "Error while updating projects database."
                raise VerisoError(
                    message, long_message=QSqlQuery.lastError(query).text())

            db.close()

            self.projectsDatabaseHasChanged.emit()

            return True
        except Exception as e:
            raise VerisoError(error_message, e)

    def postprocess_data(self, queries):
        """Does the postprocessing in the postgresql/postgis database.

        Returns:
          -1: If the process fails (e.g. no db connection etc.). Otherwise
          number of errors occured while postprocessing.
        """
        try:
            db = open_psql_db(self.db_host, self.db_name, self.db_port,
                              self.db_admin, self.db_admin_pwd)
            errors = 0
            self.report_progress("\n\nInfo: Starting postprocessing...")
            for sql in queries:
                self.report_progress("\n\n%s" % sql)

                query = db.exec_(str(sql))

                if not query.isActive():
                    errors += 1
                    message = "Error while postprocessing data:"
                    QgsMessageLog.logMessage(tr(message), "VeriSO",
                                             QgsMessageLog.CRITICAL)
                    QgsMessageLog.logMessage(
                        str(QSqlQuery.lastError(query).text()), "VeriSO",
                        QgsMessageLog.CRITICAL)
                    self.report_progress("--> error, see log", 'orange')

            if errors > 0:
                self.report_progress(
                    "Error: ...postprocessing completed with errors", "red")
                raise Exception()
            self.report_progress("Info: ...postprocessing completed")

            db.close
            del db

        except Exception as e:
            message = "Something went wrong while postprocessing data. You " \
                      "need to delete the database schema manually."
            raise VerisoError(message, e)

    def get_postprocessing_queries(self):
        """Gets the SQL queries that are stored in the sqlite database for
        the postprocessing process which is done in postgis.
        
        Language support: Everything that is not french or italian will be
        german.
        
        Returns:
          False: If the queries could not be fetched from the sqlite
          database. Otherwise a list with the SQL queries.
        """

        # originial
        """ filename = QDir.convertSeparators(QDir.cleanPath(
                QgsApplication.qgisSettingsDirPath() +
                "/python/plugins/veriso/modules/" + self.app_module +
                "/postprocessing/postprocessing.db"))"""

        # Hack
        filename = QDir.convertSeparators(
            QDir.cleanPath((os.path.realpath(__file__)).split("python")[0] +
                           "/python/plugins/veriso/modules/" +
                           self.app_module +
                           "/postprocessing/postprocessing.db"))

        self.report_progress("Info: getting postprocessing queries...")

        try:
            # This is NOT the project db
            connection_name = 'postprocessing_' + self.app_module
            db = open_sqlite_db(filename, connection_name)

            locale = QSettings().value('locale/userLocale')[0:2]
            if locale == "fr":
                lang = locale
            elif locale == "it":
                lang = locale
            else:
                lang = "de"

            sql = "SELECT * FROM postprocessing " \
                  "WHERE (lang = '%s' " \
                  "OR lang IS NULL) AND apply = 1 " \
                  "ORDER BY 'order', ogc_fid;" % lang

            query = db.exec_(sql)

            if not query.isActive():
                message = "Database query not active."
                raise VerisoError(
                    message, long_message=QSqlQuery.lastError(query).text())

            queries = []
            record = query.record()
            while next(query):
                sql_query = str(query.value(record.indexOf("sql_query")))

                sql_query = sql_query.replace("$$DBSCHEMA", self.db_schema)
                sql_query = sql_query.replace("$$USER", self.db_user)
                sql_query = sql_query.replace("$$EPSG", self.epsg)

                queries.append(sql_query)

            db.close()
            del db

            return queries

        except Exception as e:
            message = "Something went wrong while catching postprocessing " \
                      "queries from sqlite database. You need to delete the " \
                      "database schema manually."

            raise VerisoError(message, e)

    def report_progress(self, text, color=None):
        """
        Print the text in the output window
        :param text: str
        :return: None
        """

        if color is None:
            if text.lower().startswith('warning'):
                color = 'orange'
            elif text.lower().startswith('error'):
                color = 'red'
            elif text.lower().startswith('info'):
                color = 'blue'

        if color is not None:
            self.textEditImportOutput.appendHtml(
                "<span style='color:%s'>%s</span>" % (color, text))
        else:
            self.textEditImportOutput.appendPlainText("%s\n" %
                                                      text.rstrip("\n "))
        self.textEditImportOutput.ensureCursorVisible()
示例#2
0
class GdalToolsBaseDialog(QDialog, Ui_Dialog):
    refreshArgs = pyqtSignal()
    okClicked = pyqtSignal()
    closeClicked = pyqtSignal()
    helpClicked = pyqtSignal()
    processError = pyqtSignal(QProcess.ProcessError)
    processFinished = pyqtSignal(int, QProcess.ExitStatus)
    finished = pyqtSignal(bool)
    valuesChanged = pyqtSignal(list)

    def __init__(self, parent, iface, pluginBase, pluginName, pluginCommand):
        QDialog.__init__(self, parent)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.iface = iface

        self.process = QProcess(self)
        Utils.setProcessEnvironment(self.process)
        self.process.error.connect(self.processError)
        self.process.finished.connect(self.processFinished)

        self.setupUi(self)
        self.arguments = []

        self.editCmdBtn.setIcon(QIcon(":/icons/edit.png"))
        self.editCmdBtn.toggled.connect(self.editCommand)
        self.resetCmdBtn.setIcon(QIcon(":/icons/reset.png"))
        self.resetCmdBtn.clicked.connect(self.resetCommand)
        self.editCommand(False)

        self.buttonBox.rejected.connect(self.reject)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.helpRequested.connect(self.help)

        self.buttonBox.button(QDialogButtonBox.Ok).setDefault(True)

        self.plugin = pluginBase
        self.valuesChanged.connect(self.handleRefreshArgs)

        self.pluginLayout.addWidget(self.plugin)
        self.plugin.setFocus()

        self.setWindowTitle(pluginName)
        self.setPluginCommand(pluginCommand)

    def setPluginCommand(self, cmd):
        # on Windows replace the .py with .bat extension
        if platform.system() == "Windows" and cmd[-3:] == ".py":
            self.command = cmd[:-3] + ".bat"
        else:
            self.command = cmd

        if cmd[-3:] == ".py":
            self.helpFileName = cmd[:-3] + ".html"
        else:
            self.helpFileName = cmd + ".html"

    def editCommand(self, enabled):
        if not self.commandIsEnabled():
            return
        self.editCmdBtn.setChecked(enabled)
        self.resetCmdBtn.setEnabled(enabled)
        self.textEditCommand.setReadOnly(not enabled)
        self.controlsWidget.setEnabled(not enabled)
        self.refreshArgs.emit()

    def resetCommand(self):
        if not self.commandIsEditable():
            return
        self.refreshArgs.emit()

    def commandIsEditable(self):
        return self.commandIsEnabled() and self.editCmdBtn.isChecked()

    def setCommandViewerEnabled(self, enable):
        if not enable:
            self.editCommand(False)
        self.commandWidget.setEnabled(enable)

    def commandIsEnabled(self):
        return self.commandWidget.isEnabled()

    def reject(self):
        if self.process.state() != QProcess.NotRunning:
            ret = QMessageBox.warning(self, self.tr("Warning"), self.tr("The command is still running. \nDo you want terminate it anyway?"), QMessageBox.Yes | QMessageBox.No)
            if ret == QMessageBox.No:
                return

            self.process.error.disconnect(self.processError)
            self.process.finished.disconnect(self.processFinished)

        self.closeClicked.emit()

    def accept(self):
        self.okClicked.emit()

    def help(self):
        self.helpClicked.emit()

    # show the online tool documentation in the default browser
    def onHelp(self):
        helpPath = Utils.getHelpPath()
        if helpPath == '':
            url = QUrl("http://www.gdal.org/" + self.helpFileName)
        else:
            url = QUrl.fromLocalFile(helpPath + '/' + self.helpFileName)
        QDesktopServices.openUrl(url)

    # called when a value in the plugin widget interface changed
    def handleRefreshArgs(self, args):
        self.arguments = [str(a) for a in args]

        if not self.commandIsEnabled():
            self.textEditCommand.setPlainText(self.command)
        else:
            self.textEditCommand.setPlainText(self.command + " " + Utils.escapeAndJoin(self.arguments))

    # enables the OK button
    def enableRun(self, enable=True):
        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(enable)

    # start the command execution
    def onRun(self):
        self.enableRun(False)
        self.setCursor(Qt.WaitCursor)
        if not self.commandIsEditable():
            #print(self.command+' '+unicode(self.arguments))
            self.process.start(self.command, self.arguments, QIODevice.ReadOnly)
        else:
            self.process.start(self.textEditCommand.toPlainText(), QIODevice.ReadOnly)

    # stop the command execution
    def stop(self):
        self.enableRun(True)
        self.setCursor(Qt.ArrowCursor)
        self.process.kill()

    # called on closing the dialog, stop the process if it's running
    def onClosing(self):
        self.stop()
        QDialog.reject(self)

    # called if an error occurs when the command has not already finished, shows the occurred error message
    def onError(self, error):
        if error == QProcess.FailedToStart:
            msg = QCoreApplication.translate("GdalTools", "The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program.")
        elif error == QProcess.Crashed:
            msg = QCoreApplication.translate("GdalTools", "The process crashed some time after starting successfully.")
        else:
            msg = QCoreApplication.translate("GdalTools", "An unknown error occurred.")

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

        self.stop()

    # called when the command finished its execution, shows an error message if there's one
    # and, if required, load the output file in canvas
    def onFinished(self, exitCode, status):
        if status == QProcess.CrashExit:
            self.stop()
            return

        if self.command.find("gdalinfo") != -1 and exitCode == 0:
            self.finished.emit(self.loadCheckBox.isChecked())
            self.stop()
            return

        # show the error message if there's one, otherwise show the process output message
        msg = str(self.process.readAllStandardError())
        if msg == '':
            outMessages = str(self.process.readAllStandardOutput()).splitlines()

            # make sure to not show the help
            for m in outMessages:
                m = string.strip(m)
                if m == '':
                    continue
                # TODO fix this
                #if m.contains( QRegExp( "^(?:[Uu]sage:\\s)?" + QRegExp.escape(self.command) + "\\s" ) ):
                #  if msg.isEmpty():
                #    msg = self.tr ( "Invalid parameters." )
                #  break
                #if m.contains( QRegExp( "0(?:\\.+[1-9]0{1,2})+" ) ):
                #  continue

                if msg:
                    msg += "\n"
                msg += m

        QErrorMessage(self).showMessage(msg.replace("\n", "<br>"))

        if exitCode == 0:
            self.finished.emit(self.loadCheckBox.isChecked())

        self.stop()
示例#3
0
class ExportProjectDialog(QDialog, FORM_CLASS):
    projectsDatabaseHasChanged = pyqtSignal()

    def __init__(self, iface, parent=None):
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.iface = iface
        self.message_bar = self.iface.messageBar()
        self.okButton = self.buttonBox.button(QDialogButtonBox.Ok)
        self.okButton.setText("Export")
        self.settings = QSettings("CatAIS", "VeriSO")

        # members
        self.modules = None
        self.app_module = None
        self.app_module_name = None
        self.ili = None
        self.epsg = None
        self.itf = None
        self.data_date = None
        self.notes = None
        self.db_host = None
        self.db_name = None
        self.db_port = None
        self.db_schema = None
        self.db_admin = None
        self.db_admin_pwd = None
        self.project_index = None
        self.projects = None
        self.db_user = None
        self.db_pwd = None

        self.btnBrowseOutputFile.clicked.connect(
            self.btnBrowseOutputFile_clicked)

    def init_gui(self):
        projects = get_projects()

        self.cBoxProject.clear()

        if not projects:
            return

        self.projects = projects
        sorted_projects = sorted(self.projects, key=lambda k: k['displayname'])

        for project in sorted_projects:
            self.cBoxProject.addItem(str(project["displayname"]),
                                     project["dbschema"])

        self.cBoxProject.insertItem(0, "", None)
        self.cBoxProject.setCurrentIndex(0)

        return True

    # noinspection PyPep8Naming,PyPep8Naming
    def btnBrowseOutputFile_clicked(self):
        file_path = QFileDialog.getSaveFileName(
            self,
            tr("Choose interlis transfer file"),
            "",
            # self.input_itf_path,
            "ITF (*.itf *.ITF)")[0]
        file_info = QFileInfo(file_path)
        self.lineEditOutputFile.setText(file_info.absoluteFilePath())

    def accept(self):

        """Collecting all the stuff we need to know to start the import process.
        """
        # Save the settings.
        self.settings.value("file/export/output_itf_path",
                            self.lineEditOutputFile.text())

        # Gather all data/information for ili2pg arguments.
        self.itf = self.lineEditOutputFile.text().strip()

        current_index = self.cBoxProject.currentIndex()
        if current_index == 0:
            return

        db_schema = str(self.cBoxProject.itemData(current_index))

        # Get the connections parameters from the projects list we created in
        #  the init_gui method.
        i = 0
        for project in self.projects:
            if db_schema == str(project["dbschema"]):
                self.db_host = str(project["dbhost"])
                self.db_name = str(project["dbname"])
                self.db_port = str(project["dbport"])
                self.db_schema = db_schema
                self.db_admin = str(project["dbadmin"])
                self.db_admin_pwd = str(project["dbadminpwd"])
                self.app_module = str(project["appmodule"])
                self.app_module_name = str(project["appmodulename"])
                self.db_user = str(project["dbuser"])
                self.db_pwd = str(project["dbpwd"])
                self.ili = str(project["ilimodelname"])
                self.project_index = i
                break
            i += 1

        import_vm_arguments = self.settings.value(
            "options/import/vm_arguments", "")

        # Check if we have everything we need.
        if self.itf == "":
            self.message_bar.pushWarning("VeriSO",
                                         tr("No Interlis transfer file "
                                            "set."))
            return

        if self.ili == "":
            self.message_bar.pushWarning("VeriSO",
                                         tr("No Interlis model name set."))
            return

        if self.db_schema == "":
            self.message_bar.pushWarning("VeriSO",
                                         tr("No project name set."))
            return


        if self.app_module == "":
            self.message_bar.pushWarning("VeriSO",
                                         tr("No application module "
                                            "set."))
            return

        if not self.db_host:
            self.message_bar.pushWarning("VeriSO",
                                         tr("Missing database host "
                                            "parameter."))
            return

        if not self.db_name:
            self.message_bar.pushWarning("VeriSO",
                                         tr("Missing database name "
                                            "parameter."))
            return

        if not self.db_port:
            self.message_bar.pushWarning("VeriSO",
                                         tr("Missing database port "
                                            "parameter."))
            return

        if not self.db_user:
            self.message_bar.pushWarning("VeriSO",
                                         tr("Missing database user "
                                            "parameter."))
            return

        if not self.db_pwd:
            self.message_bar.pushWarning("VeriSO",
                                         tr("Missing database password "
                                            "parameter."))
            return

        if not self.db_admin:
            self.message_bar.pushWarning("VeriSO", tr(
                "Missing database administrator parameter."))
            return

        if not self.db_admin_pwd:
            self.message_bar.pushWarning("VeriSO", tr(
                "Missing database administrator password parameter."))
            return

        if jre_version() is None:
            self.message_bar.pushWarning("VeriSO",
                                         tr("No java runtime detected."))
            return

        self.textEditExportOutput.clear()

        # Set all the arguments for ili2pg.
        arguments = []

        vm_arguments_list = import_vm_arguments.split(" ")
        for arg in vm_arguments_list:
            arguments.append(arg)

        import_jar = os.path.dirname(__file__) + '/../../lib/ili2pg-3.6.1/ili2pg.jar'

        arguments.append("-Duser.country=CH")
        arguments.append("-Duser.language=de")

        arguments.append("-jar")
        arguments.append(import_jar)
        arguments.append("--export")
        arguments.append("--dbhost")
        arguments.append(self.db_host)
        arguments.append("--dbport")
        arguments.append(self.db_port)
        arguments.append("--dbdatabase")
        arguments.append(self.db_name)
        arguments.append("--dbschema")
        arguments.append(self.db_schema)
        arguments.append("--dbusr")
        arguments.append(self.db_admin)
        arguments.append("--dbpwd")
        arguments.append(self.db_admin_pwd)
        arguments.append("--modeldir")
        model_dir = ';'.join(self.settings.value(
            "options/model_repositories/repositories"))
        arguments.append(model_dir)
        arguments.append("--models")
        arguments.append(self.ili)
        arguments.append("--defaultSrsAuth")
        arguments.append("EPSG")

        arguments.append(self.itf)

        self.process = QProcess()
        self.process.readyReadStandardOutput.connect(self.read_output)
        self.process.readyReadStandardError.connect(self.read_error)
        self.process.finished.connect(self.finish_import)

        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.buttonBox.setEnabled(False)
        self.report_progress("Info: Starting ili2pg")

        self.report_progress("Info: java %s" % ' '.join(arguments))

        try:
            if(sys.platform == 'win32'):
                j = win_which('java.exe')
                self.process.start(j, arguments)
            else:
                self.process.start("java", arguments)
        except Exception as e:
            self.restore_cursor()
            message = "Could not start export process."
            self.message_bar.pushMessage("VeriSO", tr(message),
                                         Qgis.Critical, duration=0)
            QgsMessageLog.logMessage(str(e), tag="VeriSO",
                                     level=Qgis.Critical)

    def read_output(self):
        output = self.process.readAllStandardOutput()
        self.show_output(output)

    def read_error(self):
        error = self.process.readAllStandardError()
        self.show_output(error)

    def show_output(self, byte_array):
        if(sys.platform == 'win32'):
            unicode_text = byte_array.data().decode('ISO-8859-1')
        else:
            unicode_text = byte_array.data().decode('utf-8')
        self.report_progress(unicode_text)

    def finish_import(self, exit_code):
        """
        Check if import was successful.
        :param exitCode: the exit code of the process
        :return: None
        """
        try:
            # read the output of ili2pg
            self.read_import_output()

        except VerisoError as e:
            self.message_bar.pushMessage("VeriSO", tr(str(e)),
                                         Qgis.Critical, duration=0)
            return
        finally:
            self.restore_cursor()

        # When we reach here we can claim a successful import.
        message = "Export process finished."
        self.report_progress(message, 'green')
        self.message_bar.pushInfo("VeriSO", tr(message))

    def read_import_output(self):
        """
        Reads the output of the ili2pg conversion
        :return:
        """
        output = self.textEditExportOutput.toPlainText()
        if output.find("Info: ...export done") < 0 or output.find(
                "compiler failed") >= 0:
            message = "Export process not successfully finished."
            raise VerisoError(message)

    def report_progress(self, text, color=None):
        """
        Print the text in the output window
        :param text: str
        :return: None
        """

        if color is None:
            if text.lower().startswith('warning'):
                color = 'orange'
            elif text.lower().startswith('error'):
                color = 'red'
            elif text.lower().startswith('info'):
                color = 'blue'

        if color is not None:
            self.textEditExportOutput.appendHtml(
                "<span style='color:%s'>%s</span>" % (color, text))
        else:
            self.textEditExportOutput.appendPlainText(
                "%s\n" % text.rstrip("\n "))
        self.textEditExportOutput.ensureCursorVisible()

    def restore_cursor(self):
        QApplication.restoreOverrideCursor()
        self.buttonBox.setEnabled(True)
示例#4
0
class GdalToolsBaseDialog(QDialog, Ui_Dialog):
    refreshArgs = pyqtSignal()
    okClicked = pyqtSignal()
    closeClicked = pyqtSignal()
    helpClicked = pyqtSignal()
    processError = pyqtSignal(QProcess.ProcessError)
    processFinished = pyqtSignal(int, QProcess.ExitStatus)
    finished = pyqtSignal(bool)
    valuesChanged = pyqtSignal(list)

    def __init__(self, parent, iface, pluginBase, pluginName, pluginCommand):
        QDialog.__init__(self, parent)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.iface = iface

        self.process = QProcess(self)
        Utils.setProcessEnvironment(self.process)
        self.process.error.connect(self.processError)
        self.process.finished.connect(self.processFinished)

        self.setupUi(self)
        self.arguments = []

        self.editCmdBtn.setIcon(QIcon(":/icons/edit.png"))
        self.editCmdBtn.toggled.connect(self.editCommand)
        self.resetCmdBtn.setIcon(QIcon(":/icons/reset.png"))
        self.resetCmdBtn.clicked.connect(self.resetCommand)
        self.editCommand(False)

        self.buttonBox.rejected.connect(self.reject)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.helpRequested.connect(self.help)

        self.buttonBox.button(QDialogButtonBox.Ok).setDefault(True)

        self.plugin = pluginBase
        self.valuesChanged.connect(self.handleRefreshArgs)

        self.pluginLayout.addWidget(self.plugin)
        self.plugin.setFocus()

        self.setWindowTitle(pluginName)
        self.setPluginCommand(pluginCommand)

    def setPluginCommand(self, cmd):
        # on Windows replace the .py with .bat extension
        if platform.system() == "Windows" and cmd[-3:] == ".py":
            self.command = cmd[:-3] + ".bat"
        else:
            self.command = cmd

        if cmd[-3:] == ".py":
            self.helpFileName = cmd[:-3] + ".html"
        else:
            self.helpFileName = cmd + ".html"

    def editCommand(self, enabled):
        if not self.commandIsEnabled():
            return
        self.editCmdBtn.setChecked(enabled)
        self.resetCmdBtn.setEnabled(enabled)
        self.textEditCommand.setReadOnly(not enabled)
        self.controlsWidget.setEnabled(not enabled)
        self.refreshArgs.emit()

    def resetCommand(self):
        if not self.commandIsEditable():
            return
        self.refreshArgs.emit()

    def commandIsEditable(self):
        return self.commandIsEnabled() and self.editCmdBtn.isChecked()

    def setCommandViewerEnabled(self, enable):
        if not enable:
            self.editCommand(False)
        self.commandWidget.setEnabled(enable)

    def commandIsEnabled(self):
        return self.commandWidget.isEnabled()

    def reject(self):
        if self.process.state() != QProcess.NotRunning:
            ret = QMessageBox.warning(
                self, self.tr("Warning"),
                self.
                tr("The command is still running. \nDo you want terminate it anyway?"
                   ), QMessageBox.Yes | QMessageBox.No)
            if ret == QMessageBox.No:
                return

            self.process.error.disconnect(self.processError)
            self.process.finished.disconnect(self.processFinished)

        self.closeClicked.emit()

    def accept(self):
        self.okClicked.emit()

    def help(self):
        self.helpClicked.emit()

    # show the online tool documentation in the default browser
    def onHelp(self):
        helpPath = Utils.getHelpPath()
        if helpPath == '':
            url = QUrl("http://www.gdal.org/" + self.helpFileName)
        else:
            url = QUrl.fromLocalFile(helpPath + '/' + self.helpFileName)
        QDesktopServices.openUrl(url)

    # called when a value in the plugin widget interface changed
    def handleRefreshArgs(self, args):
        self.arguments = [unicode(a) for a in args]

        if not self.commandIsEnabled():
            self.textEditCommand.setPlainText(self.command)
        else:
            self.textEditCommand.setPlainText(
                self.command + " " + Utils.escapeAndJoin(self.arguments))

    # enables the OK button
    def enableRun(self, enable=True):
        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(enable)

    # start the command execution
    def onRun(self):
        self.enableRun(False)
        self.setCursor(Qt.WaitCursor)
        if not self.commandIsEditable():
            #print(self.command+' '+unicode(self.arguments))
            self.process.start(self.command, self.arguments,
                               QIODevice.ReadOnly)
        else:
            self.process.start(self.textEditCommand.toPlainText(),
                               QIODevice.ReadOnly)

    # stop the command execution
    def stop(self):
        self.enableRun(True)
        self.setCursor(Qt.ArrowCursor)
        self.process.kill()

    # called on closing the dialog, stop the process if it's running
    def onClosing(self):
        self.stop()
        QDialog.reject(self)

    # called if an error occurs when the command has not already finished, shows the occurred error message
    def onError(self, error):
        if error == QProcess.FailedToStart:
            msg = QCoreApplication.translate(
                "GdalTools",
                "The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program."
            )
        elif error == QProcess.Crashed:
            msg = QCoreApplication.translate(
                "GdalTools",
                "The process crashed some time after starting successfully.")
        else:
            msg = QCoreApplication.translate("GdalTools",
                                             "An unknown error occurred.")

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

        self.stop()

    # called when the command finished its execution, shows an error message if there's one
    # and, if required, load the output file in canvas
    def onFinished(self, exitCode, status):
        if status == QProcess.CrashExit:
            self.stop()
            return

        if self.command.find("gdalinfo") != -1 and exitCode == 0:
            self.finished.emit(self.loadCheckBox.isChecked())
            self.stop()
            return

        # show the error message if there's one, otherwise show the process output message
        msg = unicode(self.process.readAllStandardError())
        if msg == '':
            outMessages = unicode(
                self.process.readAllStandardOutput()).splitlines()

            # make sure to not show the help
            for m in outMessages:
                m = string.strip(m)
                if m == '':
                    continue
                # TODO fix this
                #if m.contains( QRegExp( "^(?:[Uu]sage:\\s)?" + QRegExp.escape(self.command) + "\\s" ) ):
                #  if msg.isEmpty():
                #    msg = self.tr ( "Invalid parameters." )
                #  break
                #if m.contains( QRegExp( "0(?:\\.+[1-9]0{1,2})+" ) ):
                #  continue

                if msg:
                    msg += "\n"
                msg += m

        QErrorMessage(self).showMessage(msg.replace("\n", "<br>"))

        if exitCode == 0:
            self.finished.emit(self.loadCheckBox.isChecked())

        self.stop()
示例#5
0
class BatchFileSync(SyncProvider):
    def __init__(self, name, project, **kwargs):
        super(BatchFileSync, self).__init__(name, project)
        self.cmd = kwargs['cmd']
        if self.project:
            self.rootfolder = os.path.abspath(self.project.folder)
        else:
            self.rootfolder = kwargs['rootfolder']

        self.project = project
        self.closeproject = kwargs.get("close_project", False)
        self.process = QProcess()
        self.parser = kwargs.get("parser", None)
        self.parsermodule = None
        variables = kwargs.get("variables", {})
        variables["ROAM_PROJECT_ROOT"] = project.folder
        variables["ROAM_PROJECT_DATA"] = project.datafolder()
        variables['ROAM_PROJECTS_HOME'] = os.path.abspath(
            os.path.join(project.folder, ".."))
        variables['ROAM_MASTER_DATA_FOLDER'] = os.path.abspath(
            os.path.join(project.folder, "..", "_data"))
        env = QProcessEnvironment.systemEnvironment()
        for varname, value in variables.items():
            env.insert(varname, str(value))
        self.process.setProcessEnvironment(env)
        self.process.setWorkingDirectory(
            os.path.dirname(os.path.realpath(self.cmd)))
        self.process.finished.connect(self.complete)
        self.process.started.connect(self.syncStarted)
        self.process.readyReadStandardError.connect(self.error)
        self.process.readyReadStandardOutput.connect(self.readOutput)
        self._output = ""
        self.haserror = False

    def import_parser_module(self):
        import imp
        name = self.parser
        module = imp.find_module(name, [self.rootfolder])
        module = imp.load_module(name, *module)
        self.parsermodule = module
        print(self.parsermodule)

    def start(self):
        if not self.parsermodule and self.parser:
            self.import_parser_module()

        self._output = ""
        self.haserror = False
        self.process.start(self.cmd, [])

    @property
    def output(self):
        return self._output

    @output.setter
    def output(self, value):
        self._output = value

    def error(self):
        self.haserror = True

    def complete(self, error, status):
        if error > 0 or self.haserror:
            stderr = self.process.readAllStandardError().data()
            self.syncError.emit(stderr.decode("utf-8"))
        else:
            self.syncComplete.emit()
        self.syncFinished.emit()

    def readOutput(self):
        output = self.process.readAll().data().decode("utf-8")
        ok = True
        if self.parsermodule:
            ok, output = self.parsermodule.sync_output(output)

        if not ok:
            self.haserror = True
            self.process.kill()
            self.syncError.emit(output)
        else:
            if output:
                self.syncMessage.emit(output)