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 __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 runProcess(self, runStr, progress): process = QProcess(iface) process.start(runStr) process.waitForFinished() returnedstring = str(process.readAllStandardOutput()) # print returnedstring progress.pushInfo(returnedstring) process.kill()
def run(self, edited_command=None): proc = QProcess() proc.readyReadStandardError.connect( functools.partial(self.stderr_ready, proc=proc) ) proc.readyReadStandardOutput.connect( functools.partial(self.stdout_ready, proc=proc) ) if not edited_command: ili2db_jar_arg = self._ili2db_jar_arg() if ili2db_jar_arg == self.ILI2DB_NOT_FOUND: return self.ILI2DB_NOT_FOUND args = self._args(False) java_path = get_java_path(self.configuration.base_configuration) proc.start(java_path, ili2db_jar_arg + args) else: proc.start(self.command_with_password(edited_command)) if not proc.waitForStarted(): proc = None if not proc: raise JavaNotFoundError() self.process_started.emit(self.command_without_password(edited_command)) self.__result = self.ERROR loop = QEventLoop() proc.finished.connect(loop.exit) loop.exec() self.process_finished.emit(proc.exitCode(), self.__result) return self.__result
def runSurfit(self): runStr = os.path.join(self.plugin_dir, "bin/surfit ") + os.path.realpath(self.tclFilename) process = QProcess(iface) process.start(runStr) process.waitForFinished() # returnedstring = str(process.readAllStandardOutput()) # print returnedstring # progress.setText(returnedstring) process.kill()
def run(self): ili2db_bin = get_ili2db_bin(self.tool_name, self.stdout, self.stderr, ili2db_tools) if not ili2db_bin: return ili2db_jar_arg = ["-jar", ili2db_bin] self.configuration.tool_name = self.tool_name args = self.configuration.to_ili2db_args() if self.configuration.base_configuration.java_path: # A java path is configured: respect it no mather what java_paths = [self.configuration.base_configuration.java_path] else: # By default try JAVA_HOME and PATH java_paths = [] if 'JAVA_HOME' in os.environ: paths = os.environ['JAVA_HOME'].split(";") for path in paths: java_paths += [ os.path.join( path.replace("\"", "").replace("'", ""), 'java') ] java_paths += ['java'] proc = None for java_path in java_paths: proc = QProcess() proc.readyReadStandardError.connect( functools.partial(self.stderr_ready, proc=proc)) proc.readyReadStandardOutput.connect( functools.partial(self.stdout_ready, proc=proc)) proc.start(java_path, ili2db_jar_arg + args) if not proc.waitForStarted(): proc = None else: break if not proc: raise JavaNotFoundError() safe_args = ili2db_jar_arg + self.configuration.to_ili2db_args( hide_password=True) safe_command = java_path + ' ' + ' '.join(safe_args) self.process_started.emit(safe_command) self.__result = Exporter.ERROR loop = QEventLoop() proc.finished.connect(loop.exit) loop.exec() self.process_finished.emit(proc.exitCode(), self.__result) return self.__result
def run(self, mode, value): java_home_set = self.java_dependency.set_java_home() if not java_home_set: self.java_dependency.get_java_on_demand() return if not self.crypto_dependency.check_if_dependency_is_valid(): self.crypto_dependency.download_dependency(URL_CRYPTO_LIBRARY) return java_path = self.java_dependency.get_full_java_exe_path() args = ["-jar", CRYPTO_LIBRARY_PATH] args += [mode, self._secret_key, self._salt, value] proc = QProcess() proc.setProcessChannelMode(QProcess.MergedChannels) proc.start(java_path, args) proc.waitForReadyRead() output = bytearray(proc.readAllStandardOutput()) output = output.decode("ascii") return output.strip()
def run(self): ili2db_bin = get_ili2db_bin(self.tool, self.stdout, self.stderr) if not ili2db_bin: return ili2db_jar_arg = ["-jar", ili2db_bin] self.configuration.tool = self.tool db_simple_factory = DbSimpleFactory() db_factory = db_simple_factory.create_factory(self.tool) config_manager = db_factory.get_db_command_config_manager( self.configuration) args = config_manager.get_ili2db_args(False) args_hide_password = config_manager.get_ili2db_args(True) java_path = get_java_path(self.configuration.base_configuration) proc = QProcess() proc.readyReadStandardError.connect( functools.partial(self.stderr_ready, proc=proc)) proc.readyReadStandardOutput.connect( functools.partial(self.stdout_ready, proc=proc)) proc.start(java_path, ili2db_jar_arg + args) if not proc.waitForStarted(): proc = None if not proc: raise JavaNotFoundError() safe_args = ili2db_jar_arg + args_hide_password safe_command = java_path + ' ' + ' '.join(safe_args) self.process_started.emit(safe_command) self.__result = Importer.ERROR loop = QEventLoop() proc.finished.connect(loop.exit) loop.exec() self.process_finished.emit(proc.exitCode(), self.__result) return self.__result
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)
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)
def adjust(self): """ Export data to GNU Gama xml, adjust the network and read result :returns: result list of adjusment from GNU Gama """ # fix = 0 free network fix = 0 adj = 0 for p, s in self.points: if s == 'FIX': fix += 1 else: adj += 1 if adj == 0 or len(self.observations) == 0: # no unknowns or observations return None doc = QDomDocument() doc.appendChild( doc.createComment( 'Gama XML created by SurveyingCalculation plugin for QGIS')) gama_local = doc.createElement('gama-local') gama_local.setAttribute('version', '2.0') doc.appendChild(gama_local) network = doc.createElement('network') network.setAttribute('axes-xy', 'ne') network.setAttribute('angles', 'left-handed') gama_local.appendChild(network) description = doc.createElement('description') if self.dimension == 1: description.appendChild(doc.createTextNode('GNU Gama 1D network')) elif self.dimension == 2: description.appendChild(doc.createTextNode('GNU Gama 2D network')) elif self.dimension == 3: description.appendChild(doc.createTextNode('GNU Gama 3D network')) network.appendChild(description) parameters = doc.createElement('parameters') parameters.setAttribute('sigma-apr', '1') parameters.setAttribute('conf-pr', str(self.probability)) parameters.setAttribute('tol-abs', '1000') parameters.setAttribute('sigma-act', 'aposteriori') parameters.setAttribute('update-constrained-coordinates', 'yes') network.appendChild(parameters) points_observations = doc.createElement('points-observations') points_observations.setAttribute( 'distance-stdev', str(self.stdev_dist) + ' ' + str(self.stdev_dist1)) points_observations.setAttribute('direction-stdev', str(self.stdev_angle)) points_observations.setAttribute('angle-stdev', str(math.sqrt(self.stdev_angle * 2))) points_observations.setAttribute('zenith-angle-stdev', str(self.stdev_angle)) network.appendChild(points_observations) for p, s in self.points: if self.dimension == 1: tmp = doc.createElement('point') tmp.setAttribute('id', p.id) if p.z is not None: tmp.setAttribute('z', str(p.z)) if s == 'FIX': tmp.setAttribute('fix', 'z') else: if fix == 0: tmp.setAttribute('adj', 'Z') else: tmp.setAttribute('adj', 'z') points_observations.appendChild(tmp) elif self.dimension == 2: tmp = doc.createElement('point') tmp.setAttribute('id', p.id) if p.e is not None and p.n is not None: tmp.setAttribute('y', str(p.e)) tmp.setAttribute('x', str(p.n)) if s == 'FIX': tmp.setAttribute('fix', 'xy') else: if fix == 0: # free network tmp.setAttribute('adj', 'XY') else: tmp.setAttribute('adj', 'xy') points_observations.appendChild(tmp) elif self.dimension == 3: tmp = doc.createElement('point') tmp.setAttribute('id', p.id) if p.e is not None and p.n is not None: tmp.setAttribute('y', str(p.e)) tmp.setAttribute('x', str(p.n)) if p.z is not None: tmp.setAttribute('z', str(p.z)) if s == 'FIX': tmp.setAttribute('fix', 'xyz') else: if fix == 0: tmp.setAttribute('adj', 'XYZ') else: tmp.setAttribute('adj', 'xyz') points_observations.appendChild(tmp) if self.dimension == 1: hd = doc.createElement('height-differences') points_observations.appendChild(hd) for o in self.observations: if o.station == 'station': # station record st_id = o.point_id if o.th is None: ih = 0 else: ih = o.th if self.dimension in [2, 3]: sta = doc.createElement('obs') sta.setAttribute('from', o.point_id) points_observations.appendChild(sta) else: # observation if self.dimension == 2: # horizontal network if o.hz is not None: tmp = doc.createElement('direction') tmp.setAttribute('to', o.point_id) tmp.setAttribute('val', str(o.hz.get_angle('GON'))) sta.appendChild(tmp) if o.d is not None: # horizontal distance hd = o.horiz_dist() if hd is not None: tmp = doc.createElement('distance') tmp.setAttribute('to', o.point_id) tmp.setAttribute('val', str(hd)) sta.appendChild(tmp) elif self.dimension == 1: # elevations only 1d if o.th is None: th = 0 else: th = o.th if o.d is not None and o.v is not None: tmp = doc.createElement('dh') tmp.setAttribute('from', st_id) tmp.setAttribute('to', o.point_id) # TODO hibaterjedes tmp.setAttribute('stdev', '1') sz = math.sin(o.v.get_angle()) w = self.stdev_dist + self.stdev_dist1 * o.d.d / 1000 ro_cc = 200 * 100 * 100 / math.pi if o.d.mode == 'SD': cz = math.cos(o.v.get_angle()) tmp.setAttribute('val', str(o.d.d * cz + ih - th)) tmp.setAttribute( 'stdev', str( math.sqrt(cz**2 * w**2 + (o.d.d * 1000)**2 * sz**2 * (self.stdev_angle / RO_CC)**2))) else: tz = math.tan(o.v.get_angle()) tmp.setAttribute( 'val', str(o.d.d / math.tan(o.v.get_angle()) + ih - th)) tmp.setAttribute( 'stdev', str( math.sqrt((1 / tz)**2 * w**2 + (o.d.d * 1000)**2 * (o.d.d * 1000)**2 * (1 / sz**2)**2 * (self.stdev_angle / RO_CC)**2))) hd.appendChild(tmp) elif self.dimension == 3: # 3d if o.th is None: th = 0 else: th = o.th if o.hz is not None: tmp = doc.createElement('direction') tmp.setAttribute('to', o.point_id) tmp.setAttribute('val', str(o.hz.get_angle('GON'))) sta.appendChild(tmp) if o.d is not None: if o.d.mode == 'SD': tmp = doc.createElement('s-distance') tmp.setAttribute('val', str(o.d.d)) tmp.setAttribute('from_dh', str(ih)) tmp.setAttribute('to_dh', str(th)) else: tmp = doc.createElement('distance') tmp.setAttribute('val', str(o.d.d)) tmp.setAttribute('to', o.point_id) sta.appendChild(tmp) if o.v is not None: tmp = doc.createElement('z-angle') tmp.setAttribute('to', o.point_id) tmp.setAttribute('val', str(o.v.get_angle('GON'))) tmp.setAttribute('from_dh', str(ih)) tmp.setAttribute('to_dh', str(th)) sta.appendChild(tmp) else: # unknown dimension return None # generate temp file name tmpf = QTemporaryFile(QDir.temp().absoluteFilePath('w')) tmpf.open(QIODevice.WriteOnly) tmpf.close() tmp_name = tmpf.fileName() f = QFile(tmp_name + '.xml') if f.open(QIODevice.WriteOnly): f.write(doc.toByteArray()) f.close() # run gama-local if self.gama_prog is None: return None status = QProcess.execute(self.gama_prog, [ tmp_name + '.xml', '--angles', '360', '--text', tmp_name + '.txt', '--xml', tmp_name + 'out.xml' ]) if status != 0: return None xmlParser = QXmlSimpleReader() xmlFile = QFile(tmp_name + 'out.xml') xmlInputSource = QXmlInputSource(xmlFile) doc.setContent(xmlInputSource, xmlParser) f_txt = QFile(tmp_name + '.txt') f_txt.open(QIODevice.ReadOnly) res = f_txt.readAll().data() f_txt.close() # store coordinates adj_nodes = doc.elementsByTagName('adjusted') if adj_nodes.count() < 1: return res adj_node = adj_nodes.at(0) for i in range(len(adj_node.childNodes())): pp = adj_node.childNodes().at(i) if pp.nodeName() == 'point': for ii in range(len(pp.childNodes())): ppp = pp.childNodes().at(ii) if ppp.nodeName() == 'id': p = Point(ppp.firstChild().nodeValue()) elif ppp.nodeName() == 'Y' or ppp.nodeName() == 'y': p.e = float(ppp.firstChild().nodeValue()) elif ppp.nodeName() == 'X' or ppp.nodeName() == 'x': p.n = float(ppp.firstChild().nodeValue()) elif ppp.nodeName() == 'Z' or ppp.nodeName() == 'z': p.z = float(ppp.firstChild().nodeValue()) ScPoint(p).store_coord(self.dimension) # remove input xml and output xml tmpf.remove() f_txt.remove() f.remove() xmlFile.remove() return res
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)
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), Qgis.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", Qgis.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)), Qgis.Critical, duration=0) QgsMessageLog.logMessage( str(message) + str(len(self.notes)), "VeriSO", Qgis.Warning) return self.projects_database = self.settings.value( "options/general/projects_database", "") if self.projects_database is None: self.projects_database = "" self.projects_root_directory = self.settings.value( "options/general/projects_root_directory", "") import_jar = self.settings.value("options/import/jar", "") self.use_pg_projects_database = self.settings.value( "options/general/use_pg_projects_database", False, type=bool) self.ignore_ili2pg_errors = self.settings.value( "options/import/ignore_ili2pg_errors", False, type=bool) self.ignore_postprocessing_errors = self.settings.value( "options/import/ignore_postprocessing_errors", False, type=bool) 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 == "": # in veriti, if no itf file is set, use a "empty" default itf file if self.app_module == 'veriti': self.itf = os.path.dirname( __file__) + "/../../modules/veriti/varia/default.itf" else: 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 jre_version() is None: self.message_bar.pushWarning("VeriSO", tr("No java runtime detected.")) return max_scale_role = self.get_module_allow_max_scale_role() self.max_scale = 0 if self.max_scale_check.isChecked(): if db_user_has_role(self.db_user, max_scale_role): self.max_scale = self.max_scale_value.value() else: self.max_scale = 1000 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) if import_jar == "": import_jar = os.path.join(os.path.dirname(__file__), '..', '..', 'lib', 'ili2pg-3.10.7', 'ili2pg.jar') arguments.append("-Duser.country=CH") arguments.append("-Duser.language=de") 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") if self.app_module == 'veriti': arguments.append("--createEnumTabs") arguments.append("--createFk") else: arguments.append("--createEnumColAsItfCode") arguments.append("--createEnumTxtCol") 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: 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 import process." self.message_bar.pushMessage("VeriSO", tr(message), Qgis.Critical, duration=0) QgsMessageLog.logMessage(str(e), "VeriSO", Qgis.Critical)
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()
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()
def run(self): ili2db_bin = get_ili2db_bin(self.tool_name, self.stdout, self.stderr, ili2db_tools) if not ili2db_bin: return args = ["-jar", ili2db_bin] args += ["--export"] if self.tool_name == 'ili2pg': # PostgreSQL specific options args += ["--dbhost", self.configuration.host] if self.configuration.port: args += ["--dbport", self.configuration.port] args += ["--dbusr", self.configuration.user] if self.configuration.password: args += ["--dbpwd", self.configuration.password] args += ["--dbdatabase", self.configuration.database] args += [ "--dbschema", self.configuration.schema or self.configuration.database ] elif self.tool_name == 'ili2gpkg': args += ["--dbfile", self.configuration.dbfile] args += self.configuration.base_configuration.to_ili2db_args(False) if self.configuration.ilimodels: args += ['--models', self.configuration.ilimodels] args += [self.configuration.xtffile] if self.configuration.base_configuration.java_path: # A java path is configured: respect it no mather what java_paths = [self.configuration.base_configuration.java_path] else: # By default try JAVA_HOME and PATH java_paths = [] if 'JAVA_HOME' in os.environ: paths = os.environ['JAVA_HOME'].split(";") for path in paths: java_paths += [ os.path.join( path.replace("\"", "").replace("'", ""), 'java') ] java_paths += ['java'] proc = None for java_path in java_paths: proc = QProcess() proc.readyReadStandardError.connect( functools.partial(self.stderr_ready, proc=proc)) proc.readyReadStandardOutput.connect( functools.partial(self.stdout_ready, proc=proc)) proc.start(java_path, args) if not proc.waitForStarted(): proc = None else: break if not proc: raise JavaNotFoundError() self.process_started.emit(java_path + ' ' + ' '.join(args)) self.__result = Exporter.ERROR loop = QEventLoop() proc.finished.connect(loop.exit) loop.exec() self.process_finished.emit(proc.exitCode(), self.__result) return self.__result
def run(self): ili2db_bin = get_ili2db_bin(self.tool_name, self.stdout, self.stderr, ili2db_tools) if not ili2db_bin: return args = ["-jar", ili2db_bin] args += ["--schemaimport"] if self.tool_name == 'ili2pg': # PostgreSQL specific options args += ["--dbhost", self.configuration.host] if self.configuration.port: args += ["--dbport", self.configuration.port] args += ["--dbusr", self.configuration.user] if self.configuration.password: args += ["--dbpwd", self.configuration.password] args += ["--dbdatabase", self.configuration.database] args += [ "--dbschema", self.configuration.schema or self.configuration.database ] args += ["--setupPgExt"] elif self.tool_name == 'ili2gpkg': args += ["--dbfile", self.configuration.dbfile] args += ["--coalesceCatalogueRef"] args += ["--createEnumTabs"] args += ["--createNumChecks"] args += ["--coalesceMultiSurface"] args += ["--coalesceMultiLine"] args += ["--strokeArcs"] args += ["--beautifyEnumDispName"] #args += ["--createBasketCol"] args += ["--createUnique"] args += ["--createGeomIdx"] args += ["--createFk"] args += ["--createFkIdx"] args += ["--createMetaInfo"] if self.configuration.inheritance == 'smart1': args += ["--smart1Inheritance"] elif self.configuration.inheritance == 'smart2': args += ["--smart2Inheritance"] else: args += ["--noSmartMapping"] proxy = QgsNetworkAccessManager.instance().fallbackProxy() if proxy.type() == QNetworkProxy.HttpProxy: args += ["--proxy", proxy.hostName()] args += ["--proxyPort", str(proxy.port())] if self.configuration.epsg != 21781: args += ["--defaultSrsCode", "{}".format(self.configuration.epsg)] if self.configuration.ilimodels: args += ['--models', self.configuration.ilimodels] if self.configuration.ilifile: # Valid ili file, don't pass --modelDir (it can cause ili2db # errors) args += self.configuration.base_configuration.to_ili2db_args( export_modeldir=False) args += [self.configuration.ilifile] else: args += self.configuration.base_configuration.to_ili2db_args() if self.configuration.base_configuration.java_path: # A java path is configured: respect it no mather what java_paths = [self.configuration.base_configuration.java_path] else: # By default try JAVA_HOME and PATH java_paths = [] if 'JAVA_HOME' in os.environ: paths = os.environ['JAVA_HOME'].split(os.pathsep) for path in paths: java_paths += [ os.path.join( path.replace("\"", "").replace("'", ""), 'java') ] java_paths += ['java'] proc = None for java_path in java_paths: proc = QProcess() proc.readyReadStandardError.connect( functools.partial(self.stderr_ready, proc=proc)) proc.readyReadStandardOutput.connect( functools.partial(self.stdout_ready, proc=proc)) proc.start(java_path, args) if not proc.waitForStarted(): proc = None else: break if not proc: raise JavaNotFoundError() command = java_path + ' ' + ' '.join(args) safe_command = command.replace( "--dbpwd {}".format(self.configuration.password), "--dbpwd ***") self.process_started.emit(safe_command) self.__result = Importer.ERROR loop = QEventLoop() proc.finished.connect(loop.exit) loop.exec() self.process_finished.emit(proc.exitCode(), self.__result) return self.__result
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)
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)
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)
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 run(self): ili2db_bin = get_ili2db_bin(self.tool_name, self.stdout, self.stderr, ili2db_tools) if not ili2db_bin: return args = ["-jar", ili2db_bin] args += ["--import"] if self.configuration.delete_data: args += ["--deleteData"] if self.tool_name == 'ili2pg': # PostgreSQL specific options args += ["--dbhost", self.configuration.host] if self.configuration.port: args += ["--dbport", self.configuration.port] args += ["--dbusr", self.configuration.user] if self.configuration.password: args += ["--dbpwd", self.configuration.password] args += ["--dbdatabase", self.configuration.database] args += [ "--dbschema", self.configuration.schema or self.configuration.database ] elif self.tool_name == 'ili2gpkg': args += ["--dbfile", self.configuration.dbfile] args += self.configuration.base_configuration.to_ili2db_args() if self.configuration.ilimodels: args += ['--models', self.configuration.ilimodels] # Use our default schema-import parameters and get others from QSettings. # They're used by ili2db in case the schema doesn't exist. If it exists, # this doesn't have any effect on the import. args += ["--createEnumTabs"] args += ["--createNumChecks"] args += ["--coalesceMultiSurface"] args += ["--createGeomIdx"] args += ["--createFk"] args += ["--createMetaInfo"] if self.tool_name == 'ili2pg': args += ["--setupPgExt"] proxy = QgsNetworkAccessManager.instance().fallbackProxy() if proxy.type() == QNetworkProxy.HttpProxy: args += ["--proxy", proxy.hostName()] args += ["--proxyPort", str(proxy.port())] settings = QSettings() epsg = settings.value('QgsProjectGenerator/ili2pg/epsg') if epsg: args += ["--defaultSrsCode", "{}".format(epsg)] inheritance = settings.value('QgsProjectGenerator/ili2pg/inheritance', 'smart2') if inheritance == 'smart1': args += ["--smart1Inheritance"] elif inheritance == 'smart2': args += ["--smart2Inheritance"] else: args += ["--noSmartMapping"] args += [self.configuration.xtffile] if self.configuration.base_configuration.java_path: # A java path is configured: respect it no mather what java_paths = [self.configuration.base_configuration.java_path] else: # By default try JAVA_HOME and PATH java_paths = [] if 'JAVA_HOME' in os.environ: paths = os.environ['JAVA_HOME'].split(";") for path in paths: java_paths += [ os.path.join( path.replace("\"", "").replace("'", ""), 'java') ] java_paths += ['java'] proc = None for java_path in java_paths: proc = QProcess() proc.readyReadStandardError.connect( functools.partial(self.stderr_ready, proc=proc)) proc.readyReadStandardOutput.connect( functools.partial(self.stdout_ready, proc=proc)) proc.start(java_path, args) if not proc.waitForStarted(): proc = None else: break if not proc: raise JavaNotFoundError() self.process_started.emit(java_path + ' ' + ' '.join(args)) self.__result = DataImporter.ERROR loop = QEventLoop() proc.finished.connect(loop.exit) loop.exec() self.process_finished.emit(proc.exitCode(), self.__result) return self.__result