class GenerateProjectDialog(QDialog, DIALOG_UI): ValidExtensions = ['ili', 'ILI'] def __init__(self, iface, base_config, parent=None): QDialog.__init__(self, parent) self.setupUi(self) self.iface = iface self.db_simple_factory = DbSimpleFactory() QgsGui.instance().enableAutoGeometryRestore(self) self.buttonBox.accepted.disconnect() self.buttonBox.accepted.connect(self.accepted) self.buttonBox.clear() self.buttonBox.addButton(QDialogButtonBox.Cancel) create_button = self.buttonBox.addButton(self.tr('Create'), QDialogButtonBox.AcceptRole) create_button.setDefault(True) self.ili_file_browse_button.clicked.connect( make_file_selector( self.ili_file_line_edit, title=self.tr('Open Interlis Model'), file_filter=self.tr('Interlis Model File (*.ili *.ILI)'))) self.buttonBox.addButton(QDialogButtonBox.Help) self.buttonBox.helpRequested.connect(self.help_requested) self.crs = QgsCoordinateReferenceSystem() self.ili2db_options = Ili2dbOptionsDialog() self.ili2db_options_button.clicked.connect(self.ili2db_options.open) self.ili2db_options.finished.connect(self.fill_toml_file_info_label) self.multiple_models_dialog = MultipleModelsDialog(self) self.multiple_models_button.clicked.connect( self.multiple_models_dialog.open) self.multiple_models_dialog.accepted.connect( self.fill_models_line_edit) self.type_combo_box.clear() self._lst_panel = dict() for db_id in self.db_simple_factory.get_db_list(True): self.type_combo_box.addItem(displayDbIliMode[db_id], db_id) for db_id in self.db_simple_factory.get_db_list(False): db_factory = self.db_simple_factory.create_factory(db_id) item_panel = db_factory.get_config_panel(self, DbActionType.GENERATE) self._lst_panel[db_id] = item_panel self.db_layout.addWidget(item_panel) self.type_combo_box.currentIndexChanged.connect(self.type_changed) self.txtStdout.anchorClicked.connect(self.link_activated) self.crsSelector.crsChanged.connect(self.crs_changed) self.base_configuration = base_config self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.txtStdout.setLayout(QGridLayout()) self.txtStdout.layout().setContentsMargins(0, 0, 0, 0) self.txtStdout.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) self.validators = Validators() nonEmptyValidator = NonEmptyStringValidator() fileValidator = FileValidator( pattern=['*.' + ext for ext in self.ValidExtensions], allow_empty=True) self.restore_configuration() self.ili_models_line_edit.setValidator(nonEmptyValidator) self.ili_file_line_edit.setValidator(fileValidator) self.ili_models_line_edit.textChanged.connect( self.validators.validate_line_edits) self.ili_models_line_edit.textChanged.emit( self.ili_models_line_edit.text()) self.ili_models_line_edit.textChanged.connect(self.on_model_changed) self.ili_models_line_edit.textChanged.connect( self.complete_models_completer) self.ili_models_line_edit.punched.connect( self.complete_models_completer) self.ilicache = IliCache(self.base_configuration) self.refresh_ili_cache() self.ili_models_line_edit.setPlaceholderText( self.tr('[Search model from repository]')) self.ili_file_line_edit.textChanged.connect( self.validators.validate_line_edits) self.ili_file_line_edit.textChanged.connect(self.ili_file_changed) self.ili_file_line_edit.textChanged.emit( self.ili_file_line_edit.text()) def accepted(self): configuration = self.updated_configuration() ili_mode = self.type_combo_box.currentData() db_id = ili_mode & ~DbIliMode.ili interlis_mode = ili_mode & DbIliMode.ili if interlis_mode: if not self.ili_file_line_edit.text().strip(): if not self.ili_models_line_edit.text().strip(): self.txtStdout.setText( self. tr('Please set a valid INTERLIS model before creating the project.' )) self.ili_models_line_edit.setFocus() return if self.ili_file_line_edit.text().strip() and \ self.ili_file_line_edit.validator().validate(configuration.ilifile, 0)[0] != QValidator.Acceptable: self.txtStdout.setText( self. tr('Please set a valid INTERLIS file before creating the project.' )) self.ili_file_line_edit.setFocus() return res, message = self._lst_panel[db_id].is_valid() if not res: self.txtStdout.setText(message) return configuration.dbschema = configuration.dbschema or configuration.database self.save_configuration(configuration) # create schema with superuser db_factory = self.db_simple_factory.create_factory(db_id) res, message = db_factory.pre_generate_project(configuration) if not res: self.txtStdout.setText(message) return with OverrideCursor(Qt.WaitCursor): self.progress_bar.show() self.progress_bar.setValue(0) self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() if interlis_mode: importer = iliimporter.Importer() importer.tool = self.type_combo_box.currentData() importer.configuration = configuration importer.stdout.connect(self.print_info) importer.stderr.connect(self.on_stderr) importer.process_started.connect(self.on_process_started) importer.process_finished.connect(self.on_process_finished) try: if importer.run() != iliimporter.Importer.SUCCESS: self.enable() self.progress_bar.hide() return except JavaNotFoundError as e: self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(e.error_string) self.enable() self.progress_bar.hide() return try: config_manager = db_factory.get_db_command_config_manager( configuration) uri = config_manager.get_uri() generator = Generator(configuration.tool, uri, configuration.inheritance, configuration.dbschema) self.progress_bar.setValue(50) except DBConnectorError: self.txtStdout.setText( self. tr('There was an error connecting to the database. Check connection parameters.' )) self.enable() self.progress_bar.hide() return if not interlis_mode: if not generator.db_or_schema_exists(): self.txtStdout.setText( self. tr('Source {} does not exist. Check connection parameters.' ).format(db_factory.get_specific_messages() ['db_or_schema'])) self.enable() self.progress_bar.hide() return res, message = db_factory.post_generate_project_validations( configuration) if not res: self.txtStdout.setText(message) self.enable() self.progress_bar.hide() return self.print_info( self.tr('\nObtaining available layers from the database…')) available_layers = generator.layers() if not available_layers: text = self.tr( 'The {} has no layers to load into QGIS.').format( db_factory.get_specific_messages()['layers_source']) self.txtStdout.setText(text) self.enable() self.progress_bar.hide() return self.progress_bar.setValue(70) self.print_info(self.tr('Obtaining relations from the database…')) relations, bags_of_enum = generator.relations(available_layers) self.progress_bar.setValue(75) self.print_info(self.tr('Arranging layers into groups…')) legend = generator.legend(available_layers) self.progress_bar.setValue(85) project = Project() project.layers = available_layers project.relations = relations project.bags_of_enum = bags_of_enum project.legend = legend self.print_info(self.tr('Configuring forms and widgets…')) project.post_generate() self.progress_bar.setValue(90) qgis_project = QgsProject.instance() self.print_info(self.tr('Generating QGIS project…')) project.create(None, qgis_project) # Set the extent of the mapCanvas from the first layer extent found for layer in project.layers: if layer.extent is not None: self.iface.mapCanvas().setExtent(layer.extent) self.iface.mapCanvas().refresh() break self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) self.progress_bar.setValue(100) self.print_info(self.tr('\nDone!'), '#004905') def print_info(self, text, text_color='#000000'): self.txtStdout.setTextColor(QColor(text_color)) self.txtStdout.append(text) QCoreApplication.processEvents() def on_stderr(self, text): color_log_text(text, self.txtStdout) self.advance_progress_bar_by_text(text) QCoreApplication.processEvents() def on_process_started(self, command): self.txtStdout.setText(command) self.progress_bar.setValue(10) QCoreApplication.processEvents() def on_process_finished(self, exit_code, result): if exit_code == 0: color = '#004905' message = self.tr( 'Interlis model(s) successfully imported into the database!') else: color = '#aa2222' message = self.tr('Finished with errors!') self.txtStdout.setTextColor(QColor(color)) self.txtStdout.append(message) self.progress_bar.setValue(50) def updated_configuration(self): """ Get the configuration that is updated with the user configuration changes on the dialog. :return: Configuration """ configuration = SchemaImportConfiguration() mode = self.type_combo_box.currentData() db_id = mode & ~DbIliMode.ili self._lst_panel[db_id].get_fields(configuration) configuration.tool = mode configuration.epsg = self.epsg configuration.inheritance = self.ili2db_options.inheritance_type() configuration.tomlfile = self.ili2db_options.toml_file() configuration.create_basket_col = self.ili2db_options.create_basket_col( ) configuration.create_import_tid = self.ili2db_options.create_import_tid( ) configuration.stroke_arcs = self.ili2db_options.stroke_arcs() configuration.base_configuration = self.base_configuration if self.ili_file_line_edit.text().strip(): configuration.ilifile = self.ili_file_line_edit.text().strip() if self.ili_models_line_edit.text().strip(): configuration.ilimodels = self.ili_models_line_edit.text().strip() return configuration def save_configuration(self, configuration): settings = QSettings() settings.setValue('QgisModelBaker/ili2db/ilifile', configuration.ilifile) settings.setValue('QgisModelBaker/ili2db/epsg', self.epsg) settings.setValue('QgisModelBaker/importtype', self.type_combo_box.currentData().name) mode = self.type_combo_box.currentData() db_factory = self.db_simple_factory.create_factory(mode) config_manager = db_factory.get_db_command_config_manager( configuration) config_manager.save_config_in_qsettings() def restore_configuration(self): settings = QSettings() self.ili_file_line_edit.setText( settings.value('QgisModelBaker/ili2db/ilifile')) self.crs = QgsCoordinateReferenceSystem( settings.value('QgisModelBaker/ili2db/epsg', 21781, int)) self.fill_toml_file_info_label() self.update_crs_info() for db_id in self.db_simple_factory.get_db_list(False): configuration = SchemaImportConfiguration() db_factory = self.db_simple_factory.create_factory(db_id) config_manager = db_factory.get_db_command_config_manager( configuration) config_manager.load_config_from_qsettings() self._lst_panel[db_id].set_fields(configuration) mode = settings.value('QgisModelBaker/importtype') mode = DbIliMode[ mode] if mode else self.db_simple_factory.default_database self.type_combo_box.setCurrentIndex(self.type_combo_box.findData(mode)) self.type_changed() self.crs_changed() def disable(self): self.type_combo_box.setEnabled(False) for key, value in self._lst_panel.items(): value.setEnabled(False) self.ili_config.setEnabled(False) self.buttonBox.setEnabled(False) def enable(self): self.type_combo_box.setEnabled(True) for key, value in self._lst_panel.items(): value.setEnabled(True) self.ili_config.setEnabled(True) self.buttonBox.setEnabled(True) def type_changed(self): self.txtStdout.clear() self.progress_bar.hide() ili_mode = self.type_combo_box.currentData() db_id = ili_mode & ~DbIliMode.ili interlis_mode = bool(ili_mode & DbIliMode.ili) self.ili_config.setVisible(interlis_mode) self.db_wrapper_group_box.setTitle(displayDbIliMode[db_id]) # Refresh panels for key, value in self._lst_panel.items(): value.interlis_mode = interlis_mode is_current_panel_selected = db_id == key value.setVisible(is_current_panel_selected) if is_current_panel_selected: value._show_panel() def on_model_changed(self, text): if not text: return for pattern, crs in CRS_PATTERNS.items(): if re.search(pattern, text): self.crs = QgsCoordinateReferenceSystem(crs) self.update_crs_info() break self.ili2db_options.set_toml_file_key(text) self.fill_toml_file_info_label() def link_activated(self, link): if link.url() == '#configure': cfg = OptionsDialog(self.base_configuration) if cfg.exec_(): settings = QSettings() settings.beginGroup('QgisModelBaker/ili2db') self.base_configuration.save(settings) else: QDesktopServices.openUrl(link) def update_crs_info(self): self.crsSelector.setCrs(self.crs) def crs_changed(self): if self.crsSelector.crs().authid()[:5] != 'EPSG:': self.crs_label.setStyleSheet('color: orange') self.crs_label.setToolTip( self.tr('Please select an EPSG Coordinate Reference System')) self.epsg = 21781 else: self.crs_label.setStyleSheet('') self.crs_label.setToolTip(self.tr('Coordinate Reference System')) authid = self.crsSelector.crs().authid() self.epsg = int(authid[5:]) def ili_file_changed(self): # If ili file is valid, models is optional if self.ili_file_line_edit.text().strip() and \ self.ili_file_line_edit.validator().validate(self.ili_file_line_edit.text().strip(), 0)[0] == QValidator.Acceptable: self.ili_models_line_edit.setValidator(None) self.ili_models_line_edit.textChanged.emit( self.ili_models_line_edit.text()) # Update completer to add models from given ili file self.ilicache = IliCache(None, self.ili_file_line_edit.text().strip()) self.refresh_ili_cache() models = self.ilicache.process_ili_file( self.ili_file_line_edit.text().strip()) self.ili_models_line_edit.setText(models[-1]['name']) self.ili_models_line_edit.setPlaceholderText(models[-1]['name']) else: nonEmptyValidator = NonEmptyStringValidator() self.ili_models_line_edit.setValidator(nonEmptyValidator) self.ili_models_line_edit.textChanged.emit( self.ili_models_line_edit.text()) # Update completer to add models from given ili file self.ilicache = IliCache(self.base_configuration) self.refresh_ili_cache() self.ili_models_line_edit.setPlaceholderText( self.tr('[Search model from repository]')) def refresh_ili_cache(self): self.ilicache.new_message.connect(self.show_message) self.ilicache.refresh() self.update_models_completer() def complete_models_completer(self): if not self.ili_models_line_edit.text(): self.ili_models_line_edit.completer().setCompletionMode( QCompleter.UnfilteredPopupCompletion) self.ili_models_line_edit.completer().complete() else: self.ili_models_line_edit.completer().setCompletionMode( QCompleter.PopupCompletion) def update_models_completer(self): completer = QCompleter(self.ilicache.model, self.ili_models_line_edit) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setFilterMode(Qt.MatchContains) self.delegate = ModelCompleterDelegate() completer.popup().setItemDelegate(self.delegate) self.ili_models_line_edit.setCompleter(completer) self.multiple_models_dialog.models_line_edit.setCompleter(completer) def show_message(self, level, message): if level == Qgis.Warning: self.bar.pushMessage(message, Qgis.Info, 10) elif level == Qgis.Critical: self.bar.pushMessage(message, Qgis.Warning, 10) def fill_models_line_edit(self): self.ili_models_line_edit.setText( self.multiple_models_dialog.get_models_string()) def fill_toml_file_info_label(self): text = None if self.ili2db_options.toml_file(): text = self.tr('Extra Model Information File: {}').format(( '…' + self.ili2db_options.toml_file( )[len(self.ili2db_options.toml_file()) - 40:]) if len(self.ili2db_options.toml_file() ) > 40 else self.ili2db_options.toml_file()) self.toml_file_info_label.setText(text) self.toml_file_info_label.setToolTip(self.ili2db_options.toml_file()) def help_requested(self): os_language = QLocale( QSettings().value('locale/userLocale')).name()[:2] if os_language in ['es', 'de']: webbrowser.open( "https://opengisch.github.io/QgisModelBaker/docs/{}/user-guide.html#generate-project" .format(os_language)) else: webbrowser.open( "https://opengisch.github.io/QgisModelBaker/docs/user-guide.html#generate-project" ) def advance_progress_bar_by_text(self, text): if text.strip() == 'Info: compile models…': self.progress_bar.setValue(20) elif text.strip() == 'Info: create table structure…': self.progress_bar.setValue(30)
class DialogImportData(QDialog, DIALOG_UI): def __init__(self, iface, db, qgis_utils): QDialog.__init__(self) self.setupUi(self) QgsGui.instance().enableAutoGeometryRestore(self) self.iface = iface self.db = db self.qgis_utils = qgis_utils self.base_configuration = BaseConfiguration() self.ilicache = IliCache(self.base_configuration) self.ilicache.refresh() self._conf_db = ConfigDbSupported() self._params = None self._current_db = None self.xtf_file_browse_button.clicked.connect( make_file_selector( self.xtf_file_line_edit, title=QCoreApplication.translate( "DialogImportData", 'Open Transfer or Catalog File'), file_filter=QCoreApplication.translate( "DialogImportData", 'Transfer File (*.xtf *.itf);;Catalogue File (*.xml *.xls *.xlsx)' ))) self.validators = Validators() self.xtf_file_line_edit.setPlaceholderText( QCoreApplication.translate("DialogImportData", "[Name of the XTF to be created]")) fileValidator = FileValidator(pattern=['*.xtf', '*.itf', '*.xml']) self.xtf_file_line_edit.setValidator(fileValidator) self.xtf_file_line_edit.textChanged.connect(self.update_import_models) self.xtf_file_line_edit.textChanged.emit( self.xtf_file_line_edit.text()) # db self.connection_setting_button.clicked.connect(self.show_settings) self.connection_setting_button.setText( QCoreApplication.translate("DialogImportData", 'Connection Settings')) # LOG self.log_config.setTitle( QCoreApplication.translate("DialogImportData", "Show log")) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) self.buttonBox.accepted.disconnect() self.buttonBox.accepted.connect(self.accepted) self.buttonBox.clear() self.buttonBox.addButton(QDialogButtonBox.Cancel) self._accept_button = self.buttonBox.addButton( QCoreApplication.translate("DialogImportData", "Import data"), QDialogButtonBox.AcceptRole) self.buttonBox.addButton(QDialogButtonBox.Help) self.buttonBox.helpRequested.connect(self.show_help) self.update_connection_info() self.restore_configuration() def update_connection_info(self): db_description = self.db.get_description_conn_string() if db_description: self.db_connect_label.setText(db_description) self.db_connect_label.setToolTip(self.db.get_display_conn_string()) self._accept_button.setEnabled(True) else: self.db_connect_label.setText( QCoreApplication.translate("DialogImportData", "The database is not defined!")) self.db_connect_label.setToolTip('') self._accept_button.setEnabled(False) def update_import_models(self): message_error = None if not self.xtf_file_line_edit.text().strip(): color = '#ffd356' # Light orange self.import_models_qmodel = QStandardItemModel() self.import_models_list_view.setModel(self.import_models_qmodel) else: if os.path.isfile(self.xtf_file_line_edit.text().strip()): color = '#fff' # White self.import_models_qmodel = QStandardItemModel() models_name = self.find_models_xtf( self.xtf_file_line_edit.text().strip()) for model_name in models_name: if not model_name in DEFAULT_HIDDEN_MODELS: item = QStandardItem(model_name) item.setCheckable(False) item.setEditable(False) self.import_models_qmodel.appendRow(item) if self.import_models_qmodel.rowCount() > 0: self.import_models_list_view.setModel( self.import_models_qmodel) else: message_error = QCoreApplication.translate( "DialogImportData", "No models were found in the XTF. Is it a valid file?") color = '#ffd356' # Light orange self.import_models_qmodel = QStandardItemModel() self.import_models_list_view.setModel( self.import_models_qmodel) else: message_error = QCoreApplication.translate( "DialogImportData", "Please set a valid XTF file") color = '#ffd356' # Light orange self.import_models_qmodel = QStandardItemModel() self.import_models_list_view.setModel( self.import_models_qmodel) self.xtf_file_line_edit.setStyleSheet( 'QLineEdit {{ background-color: {} }}'.format(color)) if message_error: self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.import_models_list_view.setFocus() return def find_models_xtf(self, xtf_path): models_name = list() pattern = re.compile(r'<MODEL[^>]*>(?P<text>[^<]*)</MODEL>') with open(xtf_path, 'r') as f: for txt in pattern.finditer(f.read()): model_tag = str(txt.group(0)) name = re.findall('NAME="(.*?)"', model_tag, re.IGNORECASE) models_name.extend(name) return models_name def get_ili_models(self): ili_models = list() for index in range(self.import_models_qmodel.rowCount()): item = self.import_models_qmodel.item(index) ili_models.append(item.text()) return ili_models def show_settings(self): dlg = self.qgis_utils.get_settings_dialog() dlg.set_action_type(EnumDbActionType.IMPORT) dlg.tabWidget.setCurrentIndex(SETTINGS_CONNECTION_TAB_INDEX) if dlg.exec_(): self.db = dlg.get_db_connection() self.update_connection_info() def accepted(self): configuration = self.update_configuration() if not os.path.isfile(self.xtf_file_line_edit.text().strip()): message_error = 'Please set a valid XTF file before importing data. XTF file does not exist' self.txtStdout.setText( QCoreApplication.translate("DialogImportData", message_error)) self.show_message(message_error, Qgis.Warning) self.xtf_file_line_edit.setFocus() return if not self.xtf_file_line_edit.validator().validate( configuration.xtffile, 0)[0] == QValidator.Acceptable: message_error = 'Please set a valid XTF before importing data.' self.txtStdout.setText( QCoreApplication.translate("DialogImportData", message_error)) self.show_message(message_error, Qgis.Warning) self.xtf_file_line_edit.setFocus() return if not self.get_ili_models(): message_error = QCoreApplication.translate( "DialogImportData", "The selected XTF file does not have information according to the LADM-COL model to import." ) self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.import_models_list_view.setFocus() return with OverrideCursor(Qt.WaitCursor): self.progress_bar.show() self.progress_bar.setValue(0) self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() dataImporter = iliimporter.Importer(dataImport=True) item_db = self._conf_db.get_db_items()[self.db.mode] dataImporter.tool_name = item_db.get_model_baker_tool_name() dataImporter.configuration = configuration self.save_configuration(configuration) dataImporter.stdout.connect(self.print_info) dataImporter.stderr.connect(self.on_stderr) dataImporter.process_started.connect(self.on_process_started) dataImporter.process_finished.connect(self.on_process_finished) self.progress_bar.setValue(25) try: if dataImporter.run() != iliimporter.Importer.SUCCESS: self.enable() self.progress_bar.hide() self.show_message( QCoreApplication.translate( "DialogImportData", "An error occurred when importing the data. For more information see the log..." ), Qgis.Warning) return except JavaNotFoundError: # Set JAVA PATH get_java_path_dlg = DialogGetJavaPath() get_java_path_dlg.setModal(True) if get_java_path_dlg.exec_(): configuration = self.update_configuration() if not get_java_path_from_qgis_model_baker(): message_error_java = QCoreApplication.translate( "DialogImportData", """Java could not be found. You can configure the JAVA_HOME environment variable, restart QGIS and try again.""" ) self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(message_error_java) self.show_message(message_error_java, Qgis.Warning) self.enable() self.progress_bar.hide() return self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) self.progress_bar.setValue(100) self.show_message( QCoreApplication.translate( "DialogImportData", "Import of the data was successfully completed"), Qgis.Success) def save_configuration(self, configuration): settings = QSettings() settings.setValue( 'Asistente-LADM_COL/QgisModelBaker/ili2pg/xtffile_import', configuration.xtffile) settings.setValue('Asistente-LADM_COL/QgisModelBaker/show_log', not self.log_config.isCollapsed()) def restore_configuration(self): settings = QSettings() self.xtf_file_line_edit.setText( settings.value( 'Asistente-LADM_COL/QgisModelBaker/ili2pg/xtffile_import')) # Show log value_show_log = settings.value( 'Asistente-LADM_COL/QgisModelBaker/show_log', False, type=bool) self.log_config.setCollapsed(not value_show_log) # set model repository # if there is no option by default use online model repository self.use_local_models = settings.value( 'Asistente-LADM_COL/models/custom_model_directories_is_checked', type=bool) if self.use_local_models: self.custom_model_directories = settings.value( 'Asistente-LADM_COL/models/custom_models') if settings.value( 'Asistente-LADM_COL/models/custom_models') else None def update_configuration(self): """ Get the configuration that is updated with the user configuration changes on the dialog. :return: Configuration """ item_db = self._conf_db.get_db_items()[self.db.mode] configuration = ImportDataConfiguration() item_db.set_db_configuration_params(self.db.dict_conn_params, configuration) configuration.xtffile = self.xtf_file_line_edit.text().strip() configuration.delete_data = False configuration.epsg = DEFAULT_EPSG configuration.inheritance = DEFAULT_INHERITANCE configuration.create_basket_col = CREATE_BASKET_COL configuration.create_import_tid = CREATE_IMPORT_TID configuration.stroke_arcs = STROKE_ARCS java_path = get_java_path_from_qgis_model_baker() if java_path: self.base_configuration.java_path = java_path # Check custom model directories if self.use_local_models: if self.custom_model_directories is None: self.base_configuration.custom_model_directories_enabled = False else: self.base_configuration.custom_model_directories = self.custom_model_directories self.base_configuration.custom_model_directories_enabled = True configuration.base_configuration = self.base_configuration if self.get_ili_models(): configuration.ilimodels = ';'.join(self.get_ili_models()) configuration.disable_validation = not QSettings().value( 'Asistente-LADM_COL/advanced_settings/validate_data_importing_exporting', True, bool) return configuration def print_info(self, text, text_color='#000000', clear=False): self.txtStdout.setTextColor(QColor(text_color)) self.txtStdout.append(text) QCoreApplication.processEvents() def on_stderr(self, text): color_log_text(text, self.txtStdout) self.advance_progress_bar_by_text(text) def on_process_started(self, command): self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(command) QCoreApplication.processEvents() def on_process_finished(self, exit_code, result): color = '#004905' if exit_code == 0 else '#aa2222' self.txtStdout.setTextColor(QColor(color)) self.txtStdout.append('Finished ({})'.format(exit_code)) if result == iliimporter.Importer.SUCCESS: self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) else: self.show_message( QCoreApplication.translate("DialogImportData", "Error when importing data"), Qgis.Warning) self.enable() # Open log if self.log_config.isCollapsed(): self.log_config.setCollapsed(False) def advance_progress_bar_by_text(self, text): if text.strip() == 'Info: compile models...': self.progress_bar.setValue(50) QCoreApplication.processEvents() elif text.strip() == 'Info: create table structure...': self.progress_bar.setValue(55) QCoreApplication.processEvents() elif text.strip() == 'Info: first validation pass...': self.progress_bar.setValue(60) QCoreApplication.processEvents() elif text.strip() == 'Info: second validation pass...': self.progress_bar.setValue(80) QCoreApplication.processEvents() def show_help(self): self.qgis_utils.show_help("import_data") def disable(self): self.db_config.setEnabled(False) self.ili_config.setEnabled(False) self.buttonBox.setEnabled(False) def enable(self): self.db_config.setEnabled(True) self.ili_config.setEnabled(True) self.buttonBox.setEnabled(True) def show_message(self, message, level): self.bar.pushMessage("Asistente LADM_COL", message, level, duration=0)
class DialogImportData(QDialog, DIALOG_UI): open_dlg_import_schema = pyqtSignal(dict) # dict with key-value params BUTTON_NAME_IMPORT_DATA = QCoreApplication.translate( "DialogImportData", "Import data") BUTTON_NAME_GO_TO_CREATE_STRUCTURE = QCoreApplication.translate( "DialogImportData", "Go to Create Structure...") def __init__(self, iface, conn_manager, context, link_to_import_schema=True, parent=None): QDialog.__init__(self, parent) self.setupUi(self) QgsGui.instance().enableAutoGeometryRestore(self) self.iface = iface self.conn_manager = conn_manager self.db_source = context.get_db_sources()[0] self.link_to_import_schema = link_to_import_schema self.db = self.conn_manager.get_db_connector_from_source( self.db_source) self.base_configuration = BaseConfiguration() self.logger = Logger() self.app = AppInterface() self.__ladmcol_models = LADMColModelRegistry() self.java_dependency = JavaDependency() self.java_dependency.download_dependency_completed.connect( self.download_java_complete) self.java_dependency.download_dependency_progress_changed.connect( self.download_java_progress_change) self.ilicache = IliCache(self.base_configuration) self.ilicache.refresh() self._dbs_supported = ConfigDBsSupported() self._running_tool = False # There may be 1 case where we need to emit a db_connection_changed from the Import Data dialog: # 1) Connection Settings was opened and the DB conn was changed. self._db_was_changed = False # To postpone calling refresh gui until we close this dialog instead of settings # Similarly, we could call a refresh on layers and relations cache in 1 case: # 1) If the ID dialog was called for the COLLECTED source: opening Connection Settings and changing the DB # connection. self._schedule_layers_and_relations_refresh = False # We need bar definition above calling clear_messages self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) self.xtf_file_browse_button.clicked.connect( make_file_selector( self.xtf_file_line_edit, title=QCoreApplication.translate( "DialogImportData", "Open Transfer or Catalog File"), file_filter=QCoreApplication.translate( "DialogImportData", 'Transfer File (*.xtf *.itf);;Catalogue File (*.xml *.xls *.xlsx)' ))) self.validators = Validators() self.xtf_file_line_edit.setPlaceholderText( QCoreApplication.translate("DialogImportData", "[Name of the XTF to be imported]")) fileValidator = FileValidator(pattern=['*.xtf', '*.itf', '*.xml']) self.xtf_file_line_edit.setValidator(fileValidator) self.xtf_file_line_edit.textChanged.connect(self.update_import_models) self.xtf_file_line_edit.textChanged.emit( self.xtf_file_line_edit.text()) # db self.connection_setting_button.clicked.connect(self.show_settings) self.connection_setting_button.setText( QCoreApplication.translate("DialogImportData", "Connection Settings")) # LOG self.log_config.setTitle( QCoreApplication.translate("DialogImportData", "Show log")) self.buttonBox.accepted.disconnect() self.buttonBox.clicked.connect(self.accepted_import_data) self.buttonBox.clear() self.buttonBox.addButton(QDialogButtonBox.Cancel) self._accept_button = self.buttonBox.addButton( self.BUTTON_NAME_IMPORT_DATA, QDialogButtonBox.AcceptRole) self.buttonBox.addButton(QDialogButtonBox.Help) self.buttonBox.helpRequested.connect(self.show_help) self.update_connection_info() self.restore_configuration() def accepted_import_data(self, button): if self.buttonBox.buttonRole(button) == QDialogButtonBox.AcceptRole: if button.text() == self.BUTTON_NAME_IMPORT_DATA: self.accepted() elif button.text() == self.BUTTON_NAME_GO_TO_CREATE_STRUCTURE: self.close() # Close import data dialog self.open_dlg_import_schema.emit({ 'selected_models': self.get_ili_models() }) # Emit signal to open import schema dialog def reject(self): if self._running_tool: QMessageBox.information( self, QCoreApplication.translate("DialogImportData", "Warning"), QCoreApplication.translate( "DialogImportData", "The Import Data tool is still running. Please wait until it finishes." )) else: self.close_dialog() def close_dialog(self): """ We use this method to be safe when emitting the db_connection_changed, otherwise we could trigger slots that unload the plugin, destroying dialogs and thus, leading to crashes. """ if self._schedule_layers_and_relations_refresh: self.conn_manager.db_connection_changed.connect( self.app.core.cache_layers_and_relations) if self._db_was_changed: # If the db was changed, it implies it complies with ladm_col, hence the second parameter self.conn_manager.db_connection_changed.emit( self.db, True, self.db_source) if self._schedule_layers_and_relations_refresh: self.conn_manager.db_connection_changed.disconnect( self.app.core.cache_layers_and_relations) self.logger.info(__name__, "Dialog closed.") self.done(QDialog.Accepted) def update_connection_info(self): db_description = self.db.get_description_conn_string() if db_description: self.db_connect_label.setText(db_description) self.db_connect_label.setToolTip(self.db.get_display_conn_string()) self._accept_button.setEnabled(True) else: self.db_connect_label.setText( QCoreApplication.translate("DialogImportData", "The database is not defined!")) self.db_connect_label.setToolTip('') self._accept_button.setEnabled(False) def update_import_models(self): self.clear_messages() error_msg = None if not self.xtf_file_line_edit.text().strip(): color = '#ffd356' # Light orange self.import_models_qmodel = QStandardItemModel() self.import_models_list_view.setModel(self.import_models_qmodel) else: if os.path.isfile(self.xtf_file_line_edit.text().strip()): color = '#fff' # White self.import_models_qmodel = QStandardItemModel() model_names = get_models_from_xtf( self.xtf_file_line_edit.text().strip()) for model in self.__ladmcol_models.supported_models(): if not model.hidden() and model.full_name() in model_names: item = QStandardItem(model.full_alias()) item.setData(model.full_name(), Qt.UserRole) item.setCheckable(False) item.setEditable(False) self.import_models_qmodel.appendRow(item) if self.import_models_qmodel.rowCount() > 0: self.import_models_list_view.setModel( self.import_models_qmodel) else: error_msg = QCoreApplication.translate( "DialogImportData", "No models were found in the XTF. Is it a valid file?") color = '#ffd356' # Light orange self.import_models_qmodel = QStandardItemModel() self.import_models_list_view.setModel( self.import_models_qmodel) else: error_msg = QCoreApplication.translate( "DialogImportData", "Please set a valid XTF file") color = '#ffd356' # Light orange self.import_models_qmodel = QStandardItemModel() self.import_models_list_view.setModel( self.import_models_qmodel) self.xtf_file_line_edit.setStyleSheet( 'QLineEdit {{ background-color: {} }}'.format(color)) if error_msg: self.txtStdout.setText(error_msg) self.show_message(error_msg, Qgis.Warning) self.import_models_list_view.setFocus() return def get_ili_models(self): ili_models = list() for index in range(self.import_models_qmodel.rowCount()): item = self.import_models_qmodel.item(index) ili_models.append(item.data(Qt.UserRole)) return ili_models def show_settings(self): # We only need those tabs related to Model Baker/ili2db operations dlg = SettingsDialog(self.conn_manager, parent=self) dlg.setWindowTitle( QCoreApplication.translate("DialogImportData", "Target DB Connection Settings")) dlg.show_tip( QCoreApplication.translate( "DialogImportData", "Configure where do you want the XTF data to be imported.")) dlg.set_db_source(self.db_source) dlg.set_tab_pages_list( [SETTINGS_CONNECTION_TAB_INDEX, SETTINGS_MODELS_TAB_INDEX]) # Connect signals (DBUtils, Core) dlg.db_connection_changed.connect(self.db_connection_changed) if self.db_source == COLLECTED_DB_SOURCE: self._schedule_layers_and_relations_refresh = True dlg.set_action_type(EnumDbActionType.IMPORT) if dlg.exec_(): self.db = dlg.get_db_connection() self.update_connection_info() def db_connection_changed(self, db, ladm_col_db, db_source): self._db_was_changed = True self.clear_messages() def accepted(self): self._running_tool = True self.txtStdout.clear() self.progress_bar.setValue(0) self.bar.clearWidgets() if not os.path.isfile(self.xtf_file_line_edit.text().strip()): self._running_tool = False error_msg = QCoreApplication.translate( "DialogImportData", "Please set a valid XTF file before importing data. XTF file does not exist." ) self.txtStdout.setText(error_msg) self.show_message(error_msg, Qgis.Warning) self.xtf_file_line_edit.setFocus() return java_home_set = self.java_dependency.set_java_home() if not java_home_set: message_java = QCoreApplication.translate( "DialogImportData", """Configuring Java {}...""").format(JAVA_REQUIRED_VERSION) self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(message_java) self.java_dependency.get_java_on_demand() self.disable() return configuration = self.update_configuration() if configuration.disable_validation: # If data validation at import is disabled, we ask for confirmation self.msg = QMessageBox() self.msg.setIcon(QMessageBox.Question) self.msg.setText( QCoreApplication.translate( "DialogImportData", "Are you sure you want to import your data without validation?" )) self.msg.setWindowTitle( QCoreApplication.translate("DialogImportData", "Import XTF without validation?")) self.msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) res = self.msg.exec_() if res == QMessageBox.No: self._running_tool = False return if not self.xtf_file_line_edit.validator().validate( configuration.xtffile, 0)[0] == QValidator.Acceptable: self._running_tool = False error_msg = QCoreApplication.translate( "DialogImportData", "Please set a valid XTF before importing data.") self.txtStdout.setText(error_msg) self.show_message(error_msg, Qgis.Warning) self.xtf_file_line_edit.setFocus() return if not self.get_ili_models(): self._running_tool = False error_msg = QCoreApplication.translate( "DialogImportData", "The selected XTF file does not have information according to the LADM-COL model to import." ) self.txtStdout.setText(error_msg) self.show_message(error_msg, Qgis.Warning) self.import_models_list_view.setFocus() return # Get list of models present in the XTF file, in the DB and in the list of required models (by the plugin) ili_models = set([ili_model for ili_model in self.get_ili_models()]) supported_models_in_ili = set([ m.full_name() for m in self.__ladmcol_models.supported_models() ]).intersection(ili_models) if not supported_models_in_ili: self._running_tool = False error_msg = QCoreApplication.translate("DialogImportData", "The selected XTF file does not have data from any LADM-COL model supported by the LADM-COL Assistant. " \ "Therefore, you cannot import it! These are the models supported:\n\n * {}").format(" \n * ".join([m.full_alias() for m in self.__ladmcol_models.supported_models()])) self.txtStdout.setText(error_msg) self.show_message(error_msg, Qgis.Warning) self.import_models_list_view.setFocus() return db_models = set(self.db.get_models()) suggested_models = sorted(ili_models.difference(db_models)) if not ili_models.issubset(db_models): self._running_tool = False error_msg = QCoreApplication.translate("DialogImportData", "IMPORT ERROR: The XTF file to import does not have the same models as the target database schema. " \ "Please create a schema that also includes the following missing modules:\n\n * {}").format( " \n * ".join(suggested_models)) self.txtStdout.clear() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.setText(error_msg) self.show_message(error_msg, Qgis.Warning) self.xtf_file_line_edit.setFocus() # button is removed to define order in GUI for button in self.buttonBox.buttons(): if button.text() == self.BUTTON_NAME_IMPORT_DATA: self.buttonBox.removeButton(button) # Check if button was previously added self.remove_create_structure_button() if self.link_to_import_schema: self.buttonBox.addButton( self.BUTTON_NAME_GO_TO_CREATE_STRUCTURE, QDialogButtonBox.AcceptRole).setStyleSheet( "color: #aa2222;") self.buttonBox.addButton(self.BUTTON_NAME_IMPORT_DATA, QDialogButtonBox.AcceptRole) return with OverrideCursor(Qt.WaitCursor): self.progress_bar.show() self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() dataImporter = iliimporter.Importer(dataImport=True) db_factory = self._dbs_supported.get_db_factory(self.db.engine) dataImporter.tool = db_factory.get_model_baker_db_ili_mode() dataImporter.configuration = configuration self.save_configuration(configuration) dataImporter.stdout.connect(self.print_info) dataImporter.stderr.connect(self.on_stderr) dataImporter.process_started.connect(self.on_process_started) dataImporter.process_finished.connect(self.on_process_finished) self.progress_bar.setValue(25) try: if dataImporter.run() != iliimporter.Importer.SUCCESS: self._running_tool = False self.show_message( QCoreApplication.translate( "DialogImportData", "An error occurred when importing the data. For more information see the log..." ), Qgis.Warning) return except JavaNotFoundError: self._running_tool = False error_msg_java = QCoreApplication.translate( "DialogImportData", "Java {} could not be found. You can configure the JAVA_HOME environment variable manually, restart QGIS and try again." ).format(JAVA_REQUIRED_VERSION) self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(error_msg_java) self.show_message(error_msg_java, Qgis.Warning) return self._running_tool = False self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) self.progress_bar.setValue(100) self.show_message( QCoreApplication.translate( "DialogImportData", "Import of the data was successfully completed"), Qgis.Success) def download_java_complete(self): self.accepted() def download_java_progress_change(self, progress): self.progress_bar.setValue(progress / 2) if (progress % 20) == 0: self.txtStdout.append('...') def remove_create_structure_button(self): for button in self.buttonBox.buttons(): if button.text() == self.BUTTON_NAME_GO_TO_CREATE_STRUCTURE: self.buttonBox.removeButton(button) def save_configuration(self, configuration): settings = QSettings() settings.setValue( 'Asistente-LADM-COL/QgisModelBaker/ili2pg/xtffile_import', configuration.xtffile) settings.setValue('Asistente-LADM-COL/QgisModelBaker/show_log', not self.log_config.isCollapsed()) def restore_configuration(self): settings = QSettings() self.xtf_file_line_edit.setText( settings.value( 'Asistente-LADM-COL/QgisModelBaker/ili2pg/xtffile_import')) # Show log value_show_log = settings.value( 'Asistente-LADM-COL/QgisModelBaker/show_log', False, type=bool) self.log_config.setCollapsed(not value_show_log) # set model repository # if there is no option by default use online model repository self.use_local_models = settings.value( 'Asistente-LADM-COL/models/custom_model_directories_is_checked', DEFAULT_USE_CUSTOM_MODELS, type=bool) if self.use_local_models: self.custom_model_directories = settings.value( 'Asistente-LADM-COL/models/custom_models', DEFAULT_MODELS_DIR) def update_configuration(self): """ Get the configuration that is updated with the user configuration changes on the dialog. :return: Configuration """ db_factory = self._dbs_supported.get_db_factory(self.db.engine) configuration = ImportDataConfiguration() db_factory.set_ili2db_configuration_params(self.db.dict_conn_params, configuration) configuration.xtffile = self.xtf_file_line_edit.text().strip() configuration.delete_data = False configuration.srs_auth = QSettings().value( 'Asistente-LADM-COL/QgisModelBaker/srs_auth', DEFAULT_SRS_AUTH, str) configuration.srs_code = QSettings().value( 'Asistente-LADM-COL/QgisModelBaker/srs_code', int(DEFAULT_SRS_CODE), int) configuration.inheritance = ILI2DBNames.DEFAULT_INHERITANCE configuration.create_basket_col = ILI2DBNames.CREATE_BASKET_COL configuration.create_import_tid = ILI2DBNames.CREATE_IMPORT_TID configuration.stroke_arcs = ILI2DBNames.STROKE_ARCS configuration.with_importtid = True full_java_exe_path = JavaDependency.get_full_java_exe_path() if full_java_exe_path: self.base_configuration.java_path = full_java_exe_path # User could have changed the default values self.use_local_models = QSettings().value( 'Asistente-LADM-COL/models/custom_model_directories_is_checked', DEFAULT_USE_CUSTOM_MODELS, type=bool) self.custom_model_directories = QSettings().value( 'Asistente-LADM-COL/models/custom_models', DEFAULT_MODELS_DIR) # Check custom model directories if self.use_local_models: if not self.custom_model_directories: self.base_configuration.custom_model_directories_enabled = False else: self.base_configuration.custom_model_directories = self.custom_model_directories self.base_configuration.custom_model_directories_enabled = True configuration.base_configuration = self.base_configuration if self.get_ili_models(): configuration.ilimodels = ';'.join(self.get_ili_models()) configuration.disable_validation = not QSettings().value( 'Asistente-LADM-COL/models/validate_data_importing_exporting', True, bool) return configuration def print_info(self, text, text_color='#000000', clear=False): self.txtStdout.setTextColor(QColor(text_color)) self.txtStdout.append(text) QCoreApplication.processEvents() def on_stderr(self, text): color_log_text(text, self.txtStdout) self.advance_progress_bar_by_text(text) def on_process_started(self, command): self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(command) QCoreApplication.processEvents() def on_process_finished(self, exit_code, result): color = '#004905' if exit_code == 0 else '#aa2222' self.txtStdout.setTextColor(QColor(color)) self.txtStdout.append('Finished ({})'.format(exit_code)) if result == iliimporter.Importer.SUCCESS: self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) else: self.show_message( QCoreApplication.translate("DialogImportData", "Error when importing data"), Qgis.Warning) # Open log if self.log_config.isCollapsed(): self.log_config.setCollapsed(False) def advance_progress_bar_by_text(self, text): if text.strip() == 'Info: compile models...': self.progress_bar.setValue(50) QCoreApplication.processEvents() elif text.strip() == 'Info: create table structure...': self.progress_bar.setValue(55) QCoreApplication.processEvents() elif text.strip() == 'Info: first validation pass...': self.progress_bar.setValue(60) QCoreApplication.processEvents() elif text.strip() == 'Info: second validation pass...': self.progress_bar.setValue(80) QCoreApplication.processEvents() def clear_messages(self): self.bar.clearWidgets( ) # Remove previous messages before showing a new one self.txtStdout.clear() # Clear previous log messages self.progress_bar.setValue(0) # Initialize progress bar def show_help(self): show_plugin_help("import_data") def disable(self): self.source_config.setEnabled(False) self.target_config.setEnabled(False) self.buttonBox.setEnabled(False) def enable(self): self.source_config.setEnabled(True) self.target_config.setEnabled(True) self.buttonBox.setEnabled(True) def show_message(self, message, level): if level == Qgis.Warning: self.enable() self.bar.clearWidgets( ) # Remove previous messages before showing a new one self.bar.pushMessage("Asistente LADM-COL", message, level, duration=0)
class ImportDataDialog(QDialog, DIALOG_UI): def __init__(self, base_config, parent=None): QDialog.__init__(self, parent) self.setupUi(self) QgsGui.instance().enableAutoGeometryRestore(self) self.db_simple_factory = DbSimpleFactory() self.buttonBox.accepted.disconnect() self.buttonBox.accepted.connect(self.accepted) self.buttonBox.clear() self.buttonBox.addButton(QDialogButtonBox.Cancel) self.buttonBox.addButton(self.tr('Import Data'), QDialogButtonBox.AcceptRole) self.buttonBox.addButton(QDialogButtonBox.Help) self.buttonBox.helpRequested.connect(self.help_requested) self.xtf_file_browse_button.clicked.connect( make_file_selector( self.xtf_file_line_edit, title=self.tr('Open Transfer or Catalog File'), file_filter=self. tr('Transfer File (*.xtf *.itf);;Catalogue File (*.xml *.xls *.xlsx)' ))) self.type_combo_box.clear() self._lst_panel = dict() for db_id in self.db_simple_factory.get_db_list(False): self.type_combo_box.addItem(displayDbIliMode[db_id], db_id) db_factory = self.db_simple_factory.create_factory(db_id) item_panel = db_factory.get_config_panel(self, DbActionType.IMPORT_DATA) self._lst_panel[db_id] = item_panel self.db_layout.addWidget(item_panel) self.type_combo_box.currentIndexChanged.connect(self.type_changed) self.ili2db_options = Ili2dbOptionsDialog() self.ili2db_options_button.clicked.connect(self.ili2db_options.open) self.ili2db_options.finished.connect(self.fill_toml_file_info_label) self.multiple_models_dialog = MultipleModelsDialog(self) self.multiple_models_button.clicked.connect( self.multiple_models_dialog.open) self.multiple_models_dialog.accepted.connect( self.fill_models_line_edit) self.base_configuration = base_config self.restore_configuration() self.validators = Validators() fileValidator = FileValidator( pattern=['*.xtf', '*.itf', '*.pdf', '*.xml', '*.xls', '*.xlsx']) self.xtf_file_line_edit.setValidator(fileValidator) self.ili_models_line_edit.setPlaceholderText( self.tr('[Search model in repository]')) self.ili_models_line_edit.textChanged.connect( self.complete_models_completer) self.ili_models_line_edit.punched.connect( self.complete_models_completer) self.xtf_file_line_edit.textChanged.connect( self.validators.validate_line_edits) self.xtf_file_line_edit.textChanged.emit( self.xtf_file_line_edit.text()) settings = QSettings() ilifile = settings.value('QgisModelBaker/ili2db/ilifile') self.ilicache = IliCache(base_config, ilifile or None) self.update_models_completer() self.ilicache.refresh() def accepted(self): configuration = self.updated_configuration() if not self.xtf_file_line_edit.validator().validate( configuration.xtffile, 0)[0] == QValidator.Acceptable: self.txtStdout.setText( self. tr('Please set a valid INTERLIS transfer or catalogue file before importing data.' )) self.xtf_file_line_edit.setFocus() return db_id = self.type_combo_box.currentData() res, message = self._lst_panel[db_id].is_valid() if not res: self.txtStdout.setText(message) return # create schema with superuser db_factory = self.db_simple_factory.create_factory(db_id) res, message = db_factory.pre_generate_project(configuration) if not res: self.txtStdout.setText(message) return with OverrideCursor(Qt.WaitCursor): self.progress_bar.show() self.progress_bar.setValue(0) self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() dataImporter = iliimporter.Importer(dataImport=True) dataImporter.tool = self.type_combo_box.currentData() dataImporter.configuration = configuration self.save_configuration(configuration) dataImporter.stdout.connect(self.print_info) dataImporter.stderr.connect(self.on_stderr) dataImporter.process_started.connect(self.on_process_started) dataImporter.process_finished.connect(self.on_process_finished) self.progress_bar.setValue(25) try: if dataImporter.run() != iliimporter.Importer.SUCCESS: self.enable() self.progress_bar.hide() return except JavaNotFoundError as e: self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(e.error_string) self.enable() self.progress_bar.hide() return self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) self.progress_bar.setValue(100) def print_info(self, text, text_color='#000000'): self.txtStdout.setTextColor(QColor(text_color)) self.txtStdout.append(text) QCoreApplication.processEvents() def on_stderr(self, text): color_log_text(text, self.txtStdout) self.advance_progress_bar_by_text(text) def on_process_started(self, command): self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(command) QCoreApplication.processEvents() def on_process_finished(self, exit_code, result): color = '#004905' if exit_code == 0 else '#aa2222' self.txtStdout.setTextColor(QColor(color)) self.txtStdout.append('Finished ({})'.format(exit_code)) if result == iliimporter.Importer.SUCCESS: self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) else: self.enable() def updated_configuration(self): """ Get the configuration that is updated with the user configuration changes on the dialog. :return: Configuration """ configuration = ili2dbconfig.ImportDataConfiguration() mode = self.type_combo_box.currentData() self._lst_panel[mode].get_fields(configuration) configuration.tool = mode configuration.xtffile = self.xtf_file_line_edit.text().strip() configuration.delete_data = self.chk_delete_data.isChecked() configuration.ilimodels = self.ili_models_line_edit.text().strip() configuration.inheritance = self.ili2db_options.inheritance_type() configuration.create_basket_col = self.ili2db_options.create_basket_col( ) configuration.create_import_tid = self.ili2db_options.create_import_tid( ) configuration.stroke_arcs = self.ili2db_options.stroke_arcs() configuration.base_configuration = self.base_configuration return configuration def save_configuration(self, configuration): settings = QSettings() settings.setValue('QgisModelBaker/ili2pg/xtffile_import', configuration.xtffile) settings.setValue('QgisModelBaker/ili2pg/deleteData', configuration.delete_data) settings.setValue('QgisModelBaker/importtype', self.type_combo_box.currentData().name) mode = self.type_combo_box.currentData() db_factory = self.db_simple_factory.create_factory(mode) config_manager = db_factory.get_db_command_config_manager( configuration) config_manager.save_config_in_qsettings() def restore_configuration(self): settings = QSettings() self.fill_toml_file_info_label() self.xtf_file_line_edit.setText( settings.value('QgisModelBaker/ili2pg/xtffile_import')) self.chk_delete_data.setChecked( settings.value('QgisModelBaker/ili2pg/deleteData', False, bool)) for db_id in self.db_simple_factory.get_db_list(False): configuration = iliimporter.ImportDataConfiguration() db_factory = self.db_simple_factory.create_factory(db_id) config_manager = db_factory.get_db_command_config_manager( configuration) config_manager.load_config_from_qsettings() self._lst_panel[db_id].set_fields(configuration) mode = settings.value('QgisModelBaker/importtype') mode = DbIliMode[ mode] if mode else self.db_simple_factory.default_database mode = mode & ~DbIliMode.ili self.type_combo_box.setCurrentIndex(self.type_combo_box.findData(mode)) self.type_changed() def disable(self): for key, value in self._lst_panel.items(): value.setEnabled(False) self.ili_config.setEnabled(False) self.buttonBox.setEnabled(False) def enable(self): for key, value in self._lst_panel.items(): value.setEnabled(True) self.ili_config.setEnabled(True) self.buttonBox.setEnabled(True) def type_changed(self): self.progress_bar.hide() db_id = self.type_combo_box.currentData() self.db_wrapper_group_box.setTitle(displayDbIliMode[db_id]) for key, value in self._lst_panel.items(): value.setVisible(db_id == key) def link_activated(self, link): if link.url() == '#configure': cfg = OptionsDialog(self.base_configuration) if cfg.exec_(): settings = QSettings() settings.beginGroup('QgisModelBaker/ili2db') self.base_configuration.save(settings) else: QDesktopServices.openUrl(link) def complete_models_completer(self): if not self.ili_models_line_edit.text(): self.ili_models_line_edit.completer().setCompletionMode( QCompleter.UnfilteredPopupCompletion) self.ili_models_line_edit.completer().complete() else: self.ili_models_line_edit.completer().setCompletionMode( QCompleter.PopupCompletion) def update_models_completer(self): completer = QCompleter(self.ilicache.model, self.ili_models_line_edit) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setFilterMode(Qt.MatchContains) self.delegate = ModelCompleterDelegate() completer.popup().setItemDelegate(self.delegate) self.ili_models_line_edit.setCompleter(completer) self.multiple_models_dialog.models_line_edit.setCompleter(completer) def fill_models_line_edit(self): self.ili_models_line_edit.setText( self.multiple_models_dialog.get_models_string()) def fill_toml_file_info_label(self): text = None if self.ili2db_options.toml_file(): text = self.tr('Extra Model Information File: {}').format(( '…' + self.ili2db_options.toml_file( )[len(self.ili2db_options.toml_file()) - 40:]) if len(self.ili2db_options.toml_file() ) > 40 else self.ili2db_options.toml_file()) self.toml_file_info_label.setText(text) self.toml_file_info_label.setToolTip(self.ili2db_options.toml_file()) def help_requested(self): os_language = QLocale( QSettings().value('locale/userLocale')).name()[:2] if os_language in ['es', 'de']: webbrowser.open( "https://opengisch.github.io/QgisModelBaker/docs/{}/user-guide.html#import-an-interlis-transfer-file-xtf" .format(os_language)) else: webbrowser.open( "https://opengisch.github.io/QgisModelBaker/docs/user-guide.html#import-an-interlis-transfer-file-xtf" ) def advance_progress_bar_by_text(self, text): if text.strip() == 'Info: compile models...': self.progress_bar.setValue(50) QCoreApplication.processEvents() elif text.strip() == 'Info: create table structure...': self.progress_bar.setValue(75) QCoreApplication.processEvents()
class ImportDataDialog(QDialog, DIALOG_UI): ValidExtensions = [ "xtf", "XTF", "itf", "ITF", "pdf", "PDF", "xml", "XML", "xls", "XLS", "xlsx", "XLSX", ] ModelMissingRegExp = re.compile(r"Error: failed to query .*\.t_ili2db_seq") def __init__(self, iface, base_config, parent=None): QDialog.__init__(self, parent) self.iface = iface self.setupUi(self) QgsGui.instance().enableAutoGeometryRestore(self) self.db_simple_factory = DbSimpleFactory() self.buttonBox.accepted.disconnect() self.buttonBox.clear() self.buttonBox.addButton(QDialogButtonBox.Cancel) self.buttonBox.addButton(QDialogButtonBox.Help) self.buttonBox.helpRequested.connect(self.help_requested) self.import_text = self.tr("Import Data") self.set_button_to_import_action = QAction(self.import_text, None) self.set_button_to_import_action.triggered.connect( self.set_button_to_import) self.import_without_validation_text = self.tr( "Import without validation") self.set_button_to_import_without_validation_action = QAction( self.import_without_validation_text, None) self.set_button_to_import_without_validation_action.triggered.connect( self.set_button_to_import_without_validation) self.edit_command_action = QAction(self.tr("Edit ili2db command"), None) self.edit_command_action.triggered.connect(self.edit_command) self.import_tool_button.addAction( self.set_button_to_import_without_validation_action) self.import_tool_button.addAction(self.edit_command_action) self.import_tool_button.setText(self.import_text) self.import_tool_button.clicked.connect(self.accepted) self.xtf_file_browse_button.clicked.connect( make_file_selector( self.xtf_file_line_edit, title=self.tr("Open Transfer or Catalog File"), file_filter=self. tr("Transfer File (*.xtf *.itf *.XTF *.ITF);;Catalogue File (*.xml *.XML *.xls *.XLS *.xlsx *.XLSX)" ), )) self.type_combo_box.clear() self._lst_panel = dict() for db_id in self.db_simple_factory.get_db_list(False): self.type_combo_box.addItem(displayDbIliMode[db_id], db_id) db_factory = self.db_simple_factory.create_factory(db_id) item_panel = db_factory.get_config_panel(self, DbActionType.IMPORT_DATA) self._lst_panel[db_id] = item_panel self.db_layout.addWidget(item_panel) self.type_combo_box.currentIndexChanged.connect(self.type_changed) self.ili2db_options = Ili2dbOptionsDialog(self, False) self.ili2db_options_button.clicked.connect(self.ili2db_options.open) self.ili2db_options.finished.connect(self.fill_toml_file_info_label) self.multiple_models_dialog = MultipleModelsDialog(self) self.multiple_models_button.clicked.connect( self.multiple_models_dialog.open) self.multiple_models_dialog.accepted.connect( self.fill_models_line_edit) self.validate_data = True # validates imported data by default, We use --disableValidation when is False self.base_configuration = base_config self.restore_configuration() self.validators = Validators() fileValidator = FileValidator( pattern=["*." + ext for ext in self.ValidExtensions]) self.xtf_file_line_edit.setValidator(fileValidator) self.ili_models_line_edit.setPlaceholderText( self.tr("[Search model in repository]")) self.ili_models_line_edit.textChanged.connect( self.complete_models_completer) self.ili_models_line_edit.punched.connect( self.complete_models_completer) self.xtf_file_line_edit.textChanged.connect( self.validators.validate_line_edits) self.xtf_file_line_edit.textChanged.emit( self.xtf_file_line_edit.text()) # Reset to import as default text self.xtf_file_line_edit.textChanged.connect(self.set_button_to_import) settings = QSettings() ilifile = settings.value("QgisModelBaker/ili2db/ilifile") self.ilicache = IliCache(base_config, ilifile or None) self.update_models_completer() self.ilicache.refresh() self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.txtStdout.setLayout(QGridLayout()) self.txtStdout.layout().setContentsMargins(0, 0, 0, 0) self.txtStdout.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) def set_button_to_import(self): """ Changes the text of the button to import (with validation) and sets the validate_data to true. So on clicking the button the import will start with validation. The buttons actions are changed to be able to switch the without-validation mode. """ self.validate_data = True self.import_tool_button.removeAction(self.set_button_to_import_action) self.import_tool_button.removeAction(self.edit_command_action) self.import_tool_button.addAction( self.set_button_to_import_without_validation_action) self.import_tool_button.addAction(self.edit_command_action) self.import_tool_button.setText(self.import_text) def set_button_to_import_without_validation(self): """ Changes the text of the button to import without validation and sets the validate_data to false. So on clicking the button the import will start without validation. The buttons actions are changed to be able to switch the with-validation mode. """ self.validate_data = False self.import_tool_button.removeAction( self.set_button_to_import_without_validation_action) self.import_tool_button.removeAction(self.edit_command_action) self.import_tool_button.addAction(self.set_button_to_import_action) self.import_tool_button.addAction(self.edit_command_action) self.import_tool_button.setText(self.import_without_validation_text) def edit_command(self): """ A dialog opens giving the user the possibility to edit the ili2db command used for the import """ importer = iliimporter.Importer() importer.tool = self.type_combo_box.currentData() importer.configuration = self.updated_configuration() command = importer.command(True) edit_command_dialog = EditCommandDialog(self) edit_command_dialog.command_edit.setPlainText(command) if edit_command_dialog.exec_(): edited_command = edit_command_dialog.command_edit.toPlainText() self.accepted(edited_command) def accepted(self, edited_command=None): db_id = self.type_combo_box.currentData() res, message = self._lst_panel[db_id].is_valid() if not res: self.txtStdout.setText(message) return configuration = self.updated_configuration() if not edited_command: if (not self.xtf_file_line_edit.validator().validate( configuration.xtffile, 0)[0] == QValidator.Acceptable): self.txtStdout.setText( self. tr("Please set a valid INTERLIS transfer or catalogue file before importing data." )) self.xtf_file_line_edit.setFocus() return # create schema with superuser db_factory = self.db_simple_factory.create_factory(db_id) res, message = db_factory.pre_generate_project(configuration) if not res: self.txtStdout.setText(message) return with OverrideCursor(Qt.WaitCursor): self.progress_bar.show() self.progress_bar.setValue(0) self.disable() self.txtStdout.setTextColor(QColor(LogColor.COLOR_INFO)) self.txtStdout.clear() dataImporter = iliimporter.Importer(dataImport=True) dataImporter.tool = self.type_combo_box.currentData() dataImporter.configuration = configuration self.save_configuration(configuration) dataImporter.stdout.connect(self.print_info) dataImporter.stderr.connect(self.on_stderr) dataImporter.process_started.connect(self.on_process_started) dataImporter.process_finished.connect(self.on_process_finished) self.progress_bar.setValue(25) try: if dataImporter.run( edited_command) != iliimporter.Importer.SUCCESS: self.enable() self.progress_bar.hide() return except JavaNotFoundError as e: self.txtStdout.setTextColor(QColor(LogColor.COLOR_INFO)) self.txtStdout.clear() self.txtStdout.setText(e.error_string) self.enable() self.progress_bar.hide() return self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) self.progress_bar.setValue(100) self.refresh_layers() def refresh_layers(self): # refresh layers try: for layer in self.iface.mapCanvas().layers(): layer.dataProvider().reloadData() self.iface.layerTreeView().layerTreeModel( ).recursivelyEmitDataChanged() except AttributeError: pass def print_info(self, text, text_color=LogColor.COLOR_INFO): self.txtStdout.setTextColor(QColor(text_color)) self.txtStdout.append(text) QCoreApplication.processEvents() def on_stderr(self, text): color_log_text(text, self.txtStdout) match = re.match(ImportDataDialog.ModelMissingRegExp, text) if match: color_log_text( "=======================================================================", self.txtStdout, ) color_log_text( self. tr("It looks like the required schema for the imported data has not been generated." ), self.txtStdout, ) color_log_text( self.tr("Did you generate the model in the database?"), self.txtStdout) color_log_text( self. tr("Note: the model for a catalogue may be different from the data model itself." ), self.txtStdout, ) color_log_text( "=======================================================================", self.txtStdout, ) self.advance_progress_bar_by_text(text) def show_message(self, level, message): if level == Qgis.Warning: self.bar.pushMessage(message, Qgis.Info, 10) elif level == Qgis.Critical: self.bar.pushMessage(message, Qgis.Warning, 10) def on_process_started(self, command): self.disable() self.txtStdout.setTextColor(QColor(LogColor.COLOR_INFO)) self.txtStdout.clear() self.txtStdout.setText(command) QCoreApplication.processEvents() def on_process_finished(self, exit_code, result): color = "#004905" if exit_code == 0 else "#aa2222" self.txtStdout.setTextColor(QColor(color)) self.txtStdout.append("Finished ({})".format(exit_code)) if result == iliimporter.Importer.SUCCESS: self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) else: if self.import_without_validate(): self.set_button_to_import_without_validation() self.enable() def import_without_validate(self): """ Valid if an error occurred that prevents executing the import without validations :return: True if you can execute the import without validations, False in other case """ log = self.txtStdout.toPlainText().lower() if "no models given" in log: return False if "attribute bid missing in basket" in log: return False return True def db_ili_version(self, configuration): """ Returns the ili2db version the database has been created with or None if the database could not be detected as a ili2db database """ db_connector = self.__db_connector(configuration) if db_connector: return db_connector.ili_version() return None def updated_configuration(self): """ Get the configuration that is updated with the user configuration changes on the dialog. :return: Configuration """ configuration = ili2dbconfig.ImportDataConfiguration() mode = self.type_combo_box.currentData() self._lst_panel[mode].get_fields(configuration) configuration.tool = mode configuration.xtffile = self.xtf_file_line_edit.text().strip() configuration.delete_data = self.chk_delete_data.isChecked() configuration.ilimodels = self.ili_models_line_edit.text().strip() configuration.inheritance = self.ili2db_options.inheritance_type() configuration.create_basket_col = self.ili2db_options.create_basket_col( ) configuration.create_import_tid = self.ili2db_options.create_import_tid( ) configuration.stroke_arcs = self.ili2db_options.stroke_arcs() configuration.pre_script = self.ili2db_options.pre_script() configuration.post_script = self.ili2db_options.post_script() configuration.base_configuration = self.base_configuration configuration.db_ili_version = self.db_ili_version(configuration) configuration.with_schemaimport = True db_connector = self.__db_connector(configuration) if db_connector and db_connector.db_or_schema_exists(): configuration.with_schemaimport = False if not self.validate_data: configuration.disable_validation = True return configuration def save_configuration(self, configuration): settings = QSettings() settings.setValue("QgisModelBaker/ili2pg/xtffile_import", configuration.xtffile) settings.setValue("QgisModelBaker/ili2pg/deleteData", configuration.delete_data) settings.setValue("QgisModelBaker/importtype", self.type_combo_box.currentData().name) mode = self.type_combo_box.currentData() db_factory = self.db_simple_factory.create_factory(mode) config_manager = db_factory.get_db_command_config_manager( configuration) config_manager.save_config_in_qsettings() def restore_configuration(self): settings = QSettings() self.fill_toml_file_info_label() self.xtf_file_line_edit.setText( settings.value("QgisModelBaker/ili2pg/xtffile_import")) # set chk_delete_data always to unchecked because otherwise the user could delete the data accidentally self.chk_delete_data.setChecked(False) for db_id in self.db_simple_factory.get_db_list(False): configuration = iliimporter.ImportDataConfiguration() db_factory = self.db_simple_factory.create_factory(db_id) config_manager = db_factory.get_db_command_config_manager( configuration) config_manager.load_config_from_qsettings() self._lst_panel[db_id].set_fields(configuration) mode = settings.value("QgisModelBaker/importtype") mode = DbIliMode[ mode] if mode else self.db_simple_factory.default_database mode = mode & ~DbIliMode.ili self.type_combo_box.setCurrentIndex(self.type_combo_box.findData(mode)) self.type_changed() def disable(self): self.type_combo_box.setEnabled(False) for key, value in self._lst_panel.items(): value.setEnabled(False) self.ili_config.setEnabled(False) self.buttonBox.setEnabled(False) def enable(self): self.type_combo_box.setEnabled(True) for key, value in self._lst_panel.items(): value.setEnabled(True) self.ili_config.setEnabled(True) self.buttonBox.setEnabled(True) def type_changed(self): self.txtStdout.clear() self.set_button_to_import() self.progress_bar.hide() db_id = self.type_combo_box.currentData() self.db_wrapper_group_box.setTitle(displayDbIliMode[db_id]) # Refresh panels for key, value in self._lst_panel.items(): value.interlis_mode = False is_current_panel_selected = db_id == key value.setVisible(is_current_panel_selected) if is_current_panel_selected: value._show_panel() def link_activated(self, link): if link.url() == "#configure": cfg = OptionsDialog(self.base_configuration) if cfg.exec_(): settings = QSettings() settings.beginGroup("QgisModelBaker/ili2db") self.base_configuration.save(settings) else: QDesktopServices.openUrl(link) def complete_models_completer(self): if not self.ili_models_line_edit.text(): self.ili_models_line_edit.completer().setCompletionMode( QCompleter.UnfilteredPopupCompletion) self.ili_models_line_edit.completer().complete() else: match_contains = (self.ili_models_line_edit.completer( ).completionModel().match( self.ili_models_line_edit.completer().completionModel().index( 0, 0), Qt.DisplayRole, self.ili_models_line_edit.text(), -1, Qt.MatchContains, )) if len(match_contains) > 1: self.ili_models_line_edit.completer().setCompletionMode( QCompleter.PopupCompletion) self.ili_models_line_edit.completer().complete() def update_models_completer(self): completer = QCompleter(self.ilicache.model, self.ili_models_line_edit) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setFilterMode(Qt.MatchContains) self.delegate = ModelCompleterDelegate() completer.popup().setItemDelegate(self.delegate) self.ili_models_line_edit.setCompleter(completer) self.multiple_models_dialog.models_line_edit.setCompleter(completer) def fill_models_line_edit(self): self.ili_models_line_edit.setText( self.multiple_models_dialog.get_models_string()) def fill_toml_file_info_label(self): text = None if self.ili2db_options.toml_file(): text = self.tr("Extra Model Information File: {}").format(( "…" + self.ili2db_options.toml_file( )[len(self.ili2db_options.toml_file()) - 40:]) if len(self.ili2db_options.toml_file() ) > 40 else self.ili2db_options.toml_file()) self.toml_file_info_label.setText(text) self.toml_file_info_label.setToolTip(self.ili2db_options.toml_file()) def help_requested(self): os_language = QLocale( QSettings().value("locale/userLocale")).name()[:2] if os_language in ["es", "de"]: webbrowser.open( "https://opengisch.github.io/QgisModelBaker/docs/{}/user-guide.html#import-an-interlis-transfer-file-xtf" .format(os_language)) else: webbrowser.open( "https://opengisch.github.io/QgisModelBaker/docs/user-guide.html#import-an-interlis-transfer-file-xtf" ) def advance_progress_bar_by_text(self, text): if text.strip() == "Info: compile models...": self.progress_bar.setValue(50) QCoreApplication.processEvents() elif text.strip() == "Info: create table structure...": self.progress_bar.setValue(75) QCoreApplication.processEvents() def __db_connector(self, configuration): db_factory = self.db_simple_factory.create_factory(configuration.tool) config_manager = db_factory.get_db_command_config_manager( configuration) try: db_connector = db_factory.get_db_connector( config_manager.get_uri(configuration.db_use_super_login) or config_manager.get_uri(), configuration.dbschema, ) db_connector.new_message.connect(self.show_message) return db_connector except (DBConnectorError, FileNotFoundError): return None
class DialogExportData(QDialog, DIALOG_UI): on_result = pyqtSignal( bool) # whether the tool was run successfully or not ValidExtensions = ['xtf', 'itf', 'gml', 'xml'] current_row_schema = 0 def __init__(self, iface, qgis_utils, conn_manager, context): QDialog.__init__(self) self.setupUi(self) QgsGui.instance().enableAutoGeometryRestore(self) self.iface = iface self.conn_manager = conn_manager self.db_source = context.get_db_sources()[0] self.db = self.conn_manager.get_db_connector_from_source( self.db_source) self.qgis_utils = qgis_utils self.logger = Logger() self.java_utils = JavaUtils() self.java_utils.download_java_completed.connect( self.download_java_complete) self.java_utils.download_java_progress_changed.connect( self.download_java_progress_change) self.base_configuration = BaseConfiguration() self.ilicache = IliCache(self.base_configuration) self.ilicache.refresh() self._dbs_supported = ConfigDbSupported() self._running_tool = False # There may be 1 case where we need to emit a db_connection_changed from the Export Data dialog: # 1) Connection Settings was opened and the DB conn was changed. self._db_was_changed = False # To postpone calling refresh gui until we close this dialog instead of settings # Similarly, we could call a refresh on layers and relations cache in 1 case: # 1) If the ED dialog was called for the COLLECTED source: opening Connection Settings and changing the DB # connection. self._schedule_layers_and_relations_refresh = False # We need bar definition above calling clear_messages self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) self.xtf_file_browse_button.clicked.connect( make_save_file_selector( self.xtf_file_line_edit, title=QCoreApplication.translate("DialogExportData", "Save in XTF Transfer File"), file_filter=QCoreApplication.translate( "DialogExportData", "XTF Transfer File (*.xtf);;Interlis 1 Transfer File (*.itf);;XML (*.xml);;GML (*.gml)" ), extension='.xtf', extensions=['.' + ext for ext in self.ValidExtensions])) self.xtf_file_browse_button.clicked.connect( self.xtf_browser_opened_to_true) self.xtf_browser_was_opened = False self.validators = Validators() fileValidator = FileValidator( pattern=['*.' + ext for ext in self.ValidExtensions], allow_non_existing=True) self.xtf_file_line_edit.setPlaceholderText( QCoreApplication.translate("DialogExportData", "[Name of the XTF to be created]")) self.xtf_file_line_edit.setValidator(fileValidator) self.xtf_file_line_edit.textChanged.connect( self.validators.validate_line_edits) self.xtf_file_line_edit.textChanged.connect( self.xtf_browser_opened_to_false) self.xtf_file_line_edit.textChanged.emit( self.xtf_file_line_edit.text()) self.connection_setting_button.clicked.connect(self.show_settings) self.connection_setting_button.setText( QCoreApplication.translate("DialogExportData", "Connection Settings")) # LOG self.log_config.setTitle( QCoreApplication.translate("DialogExportData", "Show log")) self.log_config.setFlat(True) self.buttonBox.accepted.disconnect() self.buttonBox.accepted.connect(self.accepted) self.buttonBox.clear() self.buttonBox.addButton(QDialogButtonBox.Cancel) self._accept_button = self.buttonBox.addButton( QCoreApplication.translate("DialogExportData", "Export data"), QDialogButtonBox.AcceptRole) self.buttonBox.addButton(QDialogButtonBox.Help) self.buttonBox.helpRequested.connect(self.show_help) self.update_connection_info() self.update_model_names() self.restore_configuration() def update_connection_info(self): db_description = self.db.get_description_conn_string() if db_description: self.db_connect_label.setText(db_description) self.db_connect_label.setToolTip(self.db.get_display_conn_string()) self._accept_button.setEnabled(True) else: self.db_connect_label.setText( QCoreApplication.translate("DialogExportData", "The database is not defined!")) self.db_connect_label.setToolTip('') self._accept_button.setEnabled(False) def update_model_names(self): self.export_models_qmodel = QStandardItemModel() model_names = self.db.get_models() if model_names: for model_name in model_names: if model_name not in LADMNames.DEFAULT_HIDDEN_MODELS: item = QStandardItem(model_name) item.setCheckable(False) item.setEditable(False) self.export_models_qmodel.appendRow(item) self.export_models_list_view.setModel(self.export_models_qmodel) def reject(self): if self._running_tool: QMessageBox.information( self, QCoreApplication.translate("DialogExportData", "Warning"), QCoreApplication.translate( "DialogExportData", "The Export Data tool is still running. Please wait until it finishes." )) else: self.close_dialog() def close_dialog(self): """ We use this method to be safe when emitting the db_connection_changed, otherwise we could trigger slots that unload the plugin, destroying dialogs and thus, leading to crashes. """ if self._schedule_layers_and_relations_refresh: self.conn_manager.db_connection_changed.connect( self.qgis_utils.cache_layers_and_relations) if self._db_was_changed: # If the db was changed, it implies it complies with ladm_col, hence the second parameter self.conn_manager.db_connection_changed.emit( self.db, True, self.db_source) if self._schedule_layers_and_relations_refresh: self.conn_manager.db_connection_changed.disconnect( self.qgis_utils.cache_layers_and_relations) self.logger.info(__name__, "Dialog closed.") self.done(QDialog.Accepted) def get_ili_models(self): ili_models = list() for index in range(self.export_models_qmodel.rowCount()): item = self.export_models_qmodel.item(index) ili_models.append(item.text()) return ili_models def show_settings(self): # We only need those tabs related to Model Baker/ili2db operations dlg = SettingsDialog(qgis_utils=self.qgis_utils, conn_manager=self.conn_manager) dlg.set_db_source(self.db_source) dlg.set_tab_pages_list( [SETTINGS_CONNECTION_TAB_INDEX, SETTINGS_MODELS_TAB_INDEX]) # Connect signals (DBUtils, QgisUtils) dlg.db_connection_changed.connect(self.db_connection_changed) if self.db_source == COLLECTED_DB_SOURCE: self._schedule_layers_and_relations_refresh = True dlg.set_action_type(EnumDbActionType.EXPORT) if dlg.exec_(): self.db = dlg.get_db_connection() self.update_model_names() self.update_connection_info() def db_connection_changed(self, db, ladm_col_db, db_source): self._db_was_changed = True self.clear_messages() def accepted(self): self._running_tool = True self.bar.clearWidgets() java_home_set = self.java_utils.set_java_home() if not java_home_set: message_java = QCoreApplication.translate( "DialogExportData", """Configuring Java {}...""").format(JAVA_REQUIRED_VERSION) self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(message_java) self.java_utils.get_java_on_demand() self.disable() return configuration = self.update_configuration() if not self.xtf_file_line_edit.validator().validate( configuration.xtffile, 0)[0] == QValidator.Acceptable: self._running_tool = False message_error = QCoreApplication.translate( "DialogExportData", "Please set a valid XTF file before exporting data.") self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.xtf_file_line_edit.setFocus() return if not self.get_ili_models(): self._running_tool = False message_error = QCoreApplication.translate( "DialogExportData", "Please set a valid schema to export. This schema does not have information to export." ) self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.export_models_list_view.setFocus() return if not configuration.iliexportmodels: self._running_tool = False message_error = QCoreApplication.translate( "DialogExportData", "Please set a model before exporting data.") self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.export_models_list_view.setFocus() return # If xtf browser was opened and the file exists, the user already chose # to overwrite the file if os.path.isfile(self.xtf_file_line_edit.text().strip() ) and not self.xtf_browser_was_opened: self.msg = QMessageBox() self.msg.setIcon(QMessageBox.Warning) self.msg.setText( QCoreApplication.translate( "DialogExportData", "{filename} already exists.\nDo you want to replace it?"). format(filename=os.path.basename( self.xtf_file_line_edit.text().strip()))) self.msg.setWindowTitle( QCoreApplication.translate("DialogExportData", "Save in XTF Transfer File")) self.msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg_box = self.msg.exec_() if msg_box == QMessageBox.No: self._running_tool = False return with OverrideCursor(Qt.WaitCursor): self.progress_bar.show() self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() exporter = iliexporter.Exporter() db_factory = self._dbs_supported.get_db_factory(self.db.engine) exporter.tool = db_factory.get_mbaker_db_ili_mode() exporter.configuration = configuration self.save_configuration(configuration) exporter.stdout.connect(self.print_info) exporter.stderr.connect(self.on_stderr) exporter.process_started.connect(self.on_process_started) exporter.process_finished.connect(self.on_process_finished) self.progress_bar.setValue(25) try: if exporter.run() != iliexporter.Exporter.SUCCESS: self._running_tool = False self.show_message( QCoreApplication.translate( "DialogExportData", "An error occurred when exporting the data. For more information see the log..." ), Qgis.Warning) self.on_result.emit( False ) # Inform other classes that the execution was not successful return except JavaNotFoundError: self._running_tool = False message_error_java = QCoreApplication.translate( "DialogExportData", "Java {} could not be found. You can configure the JAVA_HOME environment variable manually, restart QGIS and try again." ).format(JAVA_REQUIRED_VERSION) self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(message_error_java) self.show_message(message_error_java, Qgis.Warning) return self._running_tool = False self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) self.progress_bar.setValue(100) self.show_message( QCoreApplication.translate( "DialogExportData", "Export of the data was successfully completed."), Qgis.Success) self.on_result.emit( True) # Inform other classes that the execution was successful def download_java_complete(self): self.accepted() def download_java_progress_change(self, progress): self.progress_bar.setValue(progress / 2) if (progress % 20) == 0: self.txtStdout.append('...') def save_configuration(self, configuration): settings = QSettings() settings.setValue( 'Asistente-LADM_COL/QgisModelBaker/ili2pg/xtffile_export', configuration.xtffile) settings.setValue('Asistente-LADM_COL/QgisModelBaker/show_log', not self.log_config.isCollapsed()) def restore_configuration(self): settings = QSettings() self.xtf_file_line_edit.setText( settings.value( 'Asistente-LADM_COL/QgisModelBaker/ili2pg/xtffile_export')) # Show log value_show_log = settings.value( 'Asistente-LADM_COL/QgisModelBaker/show_log', False, type=bool) self.log_config.setCollapsed(not value_show_log) # set model repository # if there is no option by default use online model repository custom_model_is_checked = settings.value( 'Asistente-LADM_COL/models/custom_model_directories_is_checked', DEFAULT_USE_CUSTOM_MODELS, type=bool) if custom_model_is_checked: self.custom_model_directories = settings.value( 'Asistente-LADM_COL/models/custom_models', DEFAULT_MODELS_DIR) def update_configuration(self): """ Get the configuration that is updated with the user configuration changes on the dialog. :return: Configuration """ db_factory = self._dbs_supported.get_db_factory(self.db.engine) configuration = ExportConfiguration() db_factory.set_ili2db_configuration_params(self.db.dict_conn_params, configuration) configuration.xtffile = self.xtf_file_line_edit.text().strip() full_java_exe_path = JavaUtils.get_full_java_exe_path() if full_java_exe_path: self.base_configuration.java_path = full_java_exe_path # User could have changed the default values self.use_local_models = QSettings().value( 'Asistente-LADM_COL/models/custom_model_directories_is_checked', DEFAULT_USE_CUSTOM_MODELS, type=bool) self.custom_model_directories = QSettings().value( 'Asistente-LADM_COL/models/custom_models', DEFAULT_MODELS_DIR) # Check custom model directories if self.use_local_models: if not self.custom_model_directories: self.base_configuration.custom_model_directories_enabled = False else: self.base_configuration.custom_model_directories = self.custom_model_directories self.base_configuration.custom_model_directories_enabled = True configuration.base_configuration = self.base_configuration if self.get_ili_models(): configuration.iliexportmodels = ';'.join(self.get_ili_models()) configuration.ilimodels = ';'.join(self.get_ili_models()) configuration.disable_validation = not QSettings().value( 'Asistente-LADM_COL/advanced_settings/validate_data_importing_exporting', True, bool) return configuration def print_info(self, text, text_color='#000000', clear=False): self.txtStdout.setTextColor(QColor(text_color)) self.txtStdout.append(text) QCoreApplication.processEvents() def on_stderr(self, text): color_log_text(text, self.txtStdout) self.advance_progress_bar_by_text(text) def on_process_started(self, command): self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(command) QCoreApplication.processEvents() def on_process_finished(self, exit_code, result): color = '#004905' if exit_code == 0 else '#aa2222' self.txtStdout.setTextColor(QColor(color)) self.txtStdout.append( QCoreApplication.translate("DialogExportData", "Finished ({})").format(exit_code)) if result == iliexporter.Exporter.SUCCESS: self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) else: self.enable() # Open log if self.log_config.isCollapsed(): self.log_config.setCollapsed(False) def advance_progress_bar_by_text(self, text): if text.strip() == 'Info: compile models...': self.progress_bar.setValue(50) QCoreApplication.processEvents() elif text.strip() == 'Info: process data...': self.progress_bar.setValue(55) QCoreApplication.processEvents() elif text.strip() == 'Info: first validation pass...': self.progress_bar.setValue(70) QCoreApplication.processEvents() elif text.strip() == 'Info: second validation pass...': self.progress_bar.setValue(85) QCoreApplication.processEvents() def clear_messages(self): self.bar.clearWidgets( ) # Remove previous messages before showing a new one self.txtStdout.clear() # Clear previous log messages self.progress_bar.setValue(0) # Initialize progress bar def show_help(self): self.qgis_utils.show_help("export_data") def disable(self): self.db_config.setEnabled(False) self.ili_config.setEnabled(False) self.buttonBox.setEnabled(False) def enable(self): self.db_config.setEnabled(True) self.ili_config.setEnabled(True) self.buttonBox.setEnabled(True) def show_message(self, message, level): if level == Qgis.Warning: self.enable() self.bar.clearWidgets( ) # Remove previous messages before showing a new one self.bar.pushMessage("Asistente LADM_COL", message, level, duration=0) def xtf_browser_opened_to_true(self): """ Slot. Sets a flag to true to eventually avoid asking a user whether to overwrite a file. """ self.xtf_browser_was_opened = True def xtf_browser_opened_to_false(self): """ Slot. Sets a flag to false to eventually ask a user whether to overwrite a file. """ self.xtf_browser_was_opened = False self.clear_messages()
class DialogExportData(QDialog, DIALOG_UI): ValidExtensions = ['xtf', 'itf', 'gml', 'xml'] current_row_schema = 0 def __init__(self, iface, qgis_utils, conn_manager): QDialog.__init__(self) self.setupUi(self) QgsGui.instance().enableAutoGeometryRestore(self) self.iface = iface self.conn_manager = conn_manager self.db = self.conn_manager.get_db_connector_from_source() self.qgis_utils = qgis_utils self.base_configuration = BaseConfiguration() self.ilicache = IliCache(self.base_configuration) self.ilicache.refresh() self._conf_db = ConfigDbSupported() self._params = None self._current_db = None self.xtf_file_browse_button.clicked.connect( make_save_file_selector( self.xtf_file_line_edit, title=QCoreApplication.translate("DialogExportData", "Save in XTF Transfer File"), file_filter=QCoreApplication.translate( "DialogExportData", "XTF Transfer File (*.xtf);;Interlis 1 Transfer File (*.itf);;XML (*.xml);;GML (*.gml)" ), extension='.xtf', extensions=['.' + ext for ext in self.ValidExtensions])) self.xtf_file_browse_button.clicked.connect( self.xtf_browser_opened_to_true) self.xtf_browser_was_opened = False self.validators = Validators() fileValidator = FileValidator( pattern=['*.' + ext for ext in self.ValidExtensions], allow_non_existing=True) self.xtf_file_line_edit.setPlaceholderText( QCoreApplication.translate("DialogExportData", "[Name of the XTF to be created]")) self.xtf_file_line_edit.setValidator(fileValidator) self.xtf_file_line_edit.textChanged.connect( self.validators.validate_line_edits) self.xtf_file_line_edit.textChanged.connect( self.xtf_browser_opened_to_false) self.xtf_file_line_edit.textChanged.emit( self.xtf_file_line_edit.text()) self.connection_setting_button.clicked.connect(self.show_settings) self.connection_setting_button.setText( QCoreApplication.translate("DialogExportData", "Connection Settings")) # LOG self.log_config.setTitle( QCoreApplication.translate("DialogExportData", "Show log")) self.log_config.setFlat(True) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) self.buttonBox.accepted.disconnect() self.buttonBox.accepted.connect(self.accepted) self.buttonBox.clear() self.buttonBox.addButton(QDialogButtonBox.Cancel) self._accept_button = self.buttonBox.addButton( QCoreApplication.translate("DialogExportData", "Export data"), QDialogButtonBox.AcceptRole) self.buttonBox.addButton(QDialogButtonBox.Help) self.buttonBox.helpRequested.connect(self.show_help) self.update_connection_info() self.update_model_names() self.restore_configuration() def update_connection_info(self): db_description = self.db.get_description_conn_string() if db_description: self.db_connect_label.setText(db_description) self.db_connect_label.setToolTip(self.db.get_display_conn_string()) self._accept_button.setEnabled(True) else: self.db_connect_label.setText( QCoreApplication.translate("DialogExportData", "The database is not defined!")) self.db_connect_label.setToolTip('') self._accept_button.setEnabled(False) def update_model_names(self): self.export_models_qmodel = QStandardItemModel() db_models = None db_models = self.db.get_models() if db_models: for db_model in db_models: regex = re.compile(r'(?:\{[^\}]*\}|\s)') for modelname in regex.split(db_model['modelname']): if modelname and modelname not in DEFAULT_HIDDEN_MODELS: item = QStandardItem(modelname.strip()) item.setCheckable(False) item.setEditable(False) self.export_models_qmodel.appendRow(item) self.export_models_list_view.setModel(self.export_models_qmodel) def get_ili_models(self): ili_models = list() for index in range(self.export_models_qmodel.rowCount()): item = self.export_models_qmodel.item(index) ili_models.append(item.text()) return ili_models def show_settings(self): dlg = SettingsDialog(qgis_utils=self.qgis_utils, conn_manager=self.conn_manager) # Connect signals (DBUtils, QgisUtils) dlg.db_connection_changed.connect( self.conn_manager.db_connection_changed) dlg.db_connection_changed.connect( self.qgis_utils.cache_layers_and_relations) dlg.organization_tools_changed.connect( self.qgis_utils.organization_tools_changed) dlg.set_action_type(EnumDbActionType.EXPORT) dlg.tabWidget.setCurrentIndex(SETTINGS_CONNECTION_TAB_INDEX) if dlg.exec_(): self.db = dlg.get_db_connection() self.update_model_names() self.update_connection_info() def accepted(self): configuration = self.update_configuration() if not self.xtf_file_line_edit.validator().validate( configuration.xtffile, 0)[0] == QValidator.Acceptable: message_error = QCoreApplication.translate( "DialogExportData", "Please set a valid XTF file before exporting data.") self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.xtf_file_line_edit.setFocus() return if not self.get_ili_models(): message_error = QCoreApplication.translate( "DialogExportData", "Please set a valid schema to export. This schema does not have information to export." ) self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.export_models_list_view.setFocus() return if not configuration.iliexportmodels: message_error = QCoreApplication.translate( "DialogExportData", "Please set a model before exporting data.") self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.export_models_list_view.setFocus() return # If xtf browser was opened and the file exists, the user already chose # to overwrite the file if os.path.isfile(self.xtf_file_line_edit.text().strip() ) and not self.xtf_browser_was_opened: self.msg = QMessageBox() self.msg.setIcon(QMessageBox.Warning) self.msg.setText( QCoreApplication.translate( "DialogExportData", "{filename} already exists.\nDo you want to replace it?"). format(filename=os.path.basename( self.xtf_file_line_edit.text().strip()))) self.msg.setWindowTitle( QCoreApplication.translate("DialogExportData", "Save in XTF Transfer File")) self.msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg_box = self.msg.exec_() if msg_box == QMessageBox.No: return with OverrideCursor(Qt.WaitCursor): self.progress_bar.show() self.progress_bar.setValue(0) self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() exporter = iliexporter.Exporter() item_db = self._conf_db.get_db_items()[self.db.mode] exporter.tool = item_db.get_mbaker_db_ili_mode() exporter.configuration = configuration self.save_configuration(configuration) exporter.stdout.connect(self.print_info) exporter.stderr.connect(self.on_stderr) exporter.process_started.connect(self.on_process_started) exporter.process_finished.connect(self.on_process_finished) self.progress_bar.setValue(25) try: if exporter.run() != iliexporter.Exporter.SUCCESS: self.enable() self.progress_bar.hide() self.show_message( QCoreApplication.translate( "DialogExportData", "An error occurred when exporting the data. For more information see the log..." ), Qgis.Warning) return except JavaNotFoundError: # Set JAVA PATH get_java_path_dlg = GetJavaPathDialog() get_java_path_dlg.setModal(True) if get_java_path_dlg.exec_(): configuration = self.update_configuration() if not get_java_path_from_qgis_model_baker(): message_error_java = QCoreApplication.translate( "DialogExportData", """Java could not be found. You can configure the JAVA_HOME environment variable, restart QGIS and try again.""" ) self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(message_error_java) self.show_message(message_error_java, Qgis.Warning) self.enable() self.progress_bar.hide() return self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) self.progress_bar.setValue(100) self.show_message( QCoreApplication.translate( "DialogExportData", "Export of the data was successfully completed."), Qgis.Success) def save_configuration(self, configuration): settings = QSettings() settings.setValue( 'Asistente-LADM_COL/QgisModelBaker/ili2pg/xtffile_export', configuration.xtffile) settings.setValue('Asistente-LADM_COL/QgisModelBaker/show_log', not self.log_config.isCollapsed()) def restore_configuration(self): settings = QSettings() self.xtf_file_line_edit.setText( settings.value( 'Asistente-LADM_COL/QgisModelBaker/ili2pg/xtffile_export')) # Show log value_show_log = settings.value( 'Asistente-LADM_COL/QgisModelBaker/show_log', False, type=bool) self.log_config.setCollapsed(not value_show_log) # set model repository # if there is no option by default use online model repository custom_model_is_checked = settings.value( 'Asistente-LADM_COL/models/custom_model_directories_is_checked', type=bool) if custom_model_is_checked: self.custom_model_directories = settings.value( 'Asistente-LADM_COL/models/custom_models') def update_configuration(self): """ Get the configuration that is updated with the user configuration changes on the dialog. :return: Configuration """ item_db = self._conf_db.get_db_items()[self.db.mode] configuration = ExportConfiguration() item_db.set_db_configuration_params(self.db.dict_conn_params, configuration) configuration.xtffile = self.xtf_file_line_edit.text().strip() java_path = get_java_path_from_qgis_model_baker() if java_path: self.base_configuration.java_path = java_path # Check custom model directories if QSettings().value( 'Asistente-LADM_COL/models/custom_model_directories_is_checked', type=bool): if self.custom_model_directories is None: self.base_configuration.custom_model_directories_enabled = False else: self.base_configuration.custom_model_directories = self.custom_model_directories self.base_configuration.custom_model_directories_enabled = True configuration.base_configuration = self.base_configuration if self.get_ili_models(): configuration.iliexportmodels = ';'.join(self.get_ili_models()) configuration.ilimodels = ';'.join(self.get_ili_models()) configuration.disable_validation = not QSettings().value( 'Asistente-LADM_COL/advanced_settings/validate_data_importing_exporting', True, bool) return configuration def print_info(self, text, text_color='#000000', clear=False): self.txtStdout.setTextColor(QColor(text_color)) self.txtStdout.append(text) QCoreApplication.processEvents() def on_stderr(self, text): color_log_text(text, self.txtStdout) self.advance_progress_bar_by_text(text) def on_process_started(self, command): self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(command) QCoreApplication.processEvents() def on_process_finished(self, exit_code, result): color = '#004905' if exit_code == 0 else '#aa2222' self.txtStdout.setTextColor(QColor(color)) self.txtStdout.append( QCoreApplication.translate("DialogExportData", "Finished ({})").format(exit_code)) if result == iliexporter.Exporter.SUCCESS: self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) else: self.enable() # Open log if self.log_config.isCollapsed(): self.log_config.setCollapsed(False) def advance_progress_bar_by_text(self, text): if text.strip() == 'Info: compile models...': self.progress_bar.setValue(50) QCoreApplication.processEvents() elif text.strip() == 'Info: process data...': self.progress_bar.setValue(55) QCoreApplication.processEvents() elif text.strip() == 'Info: first validation pass...': self.progress_bar.setValue(70) QCoreApplication.processEvents() elif text.strip() == 'Info: second validation pass...': self.progress_bar.setValue(85) QCoreApplication.processEvents() def show_help(self): self.qgis_utils.show_help("export_data") def disable(self): self.db_config.setEnabled(False) self.ili_config.setEnabled(False) self.buttonBox.setEnabled(False) def enable(self): self.db_config.setEnabled(True) self.ili_config.setEnabled(True) self.buttonBox.setEnabled(True) def show_message(self, message, level): self.bar.pushMessage("Asistente LADM_COL", message, level, duration=0) def xtf_browser_opened_to_true(self): """ Slot. Sets a flag to true to eventually avoid asking a user whether to overwrite a file. """ self.xtf_browser_was_opened = True def xtf_browser_opened_to_false(self): """ Slot. Sets a flag to false to eventually ask a user whether to overwrite a file. """ self.xtf_browser_was_opened = False
class BasketExporter(QObject): total_progress_updated = pyqtSignal(int) # percentage def __init__(self, db, basket_dict, export_dir): QObject.__init__(self) self._db = db self._basket_dict = basket_dict # {t_ili_tids: receiver_name} self._export_dir = export_dir self.logger = Logger() self.log = '' self.java_dependency = JavaDependency() self.java_dependency.download_dependency_completed.connect( self.download_java_complete) self._dbs_supported = ConfigDBsSupported() def export_baskets(self): java_home_set = self.java_dependency.set_java_home() if not java_home_set: message_java = QCoreApplication.translate( "BasketExporter", """Configuring Java {}...""").format(JAVA_REQUIRED_VERSION) self.logger.status(message_java) self.java_dependency.get_java_on_demand() return self.base_configuration = BaseConfiguration() self.ilicache = IliCache(self.base_configuration) self.ilicache.refresh() db_factory = self._dbs_supported.get_db_factory(self._db.engine) self.configuration = ExportConfiguration() db_factory.set_ili2db_configuration_params(self._db.dict_conn_params, self.configuration) self.configuration.with_exporttid = True full_java_exe_path = JavaDependency.get_full_java_exe_path() if full_java_exe_path: self.base_configuration.java_path = full_java_exe_path # Check custom model directories if QSettings().value( 'Asistente-LADM-COL/models/custom_model_directories_is_checked', DEFAULT_USE_CUSTOM_MODELS, type=bool): custom_model_directories = QSettings().value( 'Asistente-LADM-COL/models/custom_models', DEFAULT_MODELS_DIR) if not custom_model_directories: self.base_configuration.custom_model_directories_enabled = False else: self.base_configuration.custom_model_directories = custom_model_directories self.base_configuration.custom_model_directories_enabled = True self.configuration.base_configuration = self.base_configuration if self.get_ili_models(): self.configuration.ilimodels = ';'.join(self.get_ili_models()) self.exporter = iliexporter.Exporter() self.exporter.tool = db_factory.get_model_baker_db_ili_mode() self.exporter.process_started.connect(self.on_process_started) self.exporter.stderr.connect(self.on_stderr) #self.exporter.process_finished.connect(self.on_process_finished) res = dict() count = 0 total = len(self._basket_dict) with OverrideCursor(Qt.WaitCursor): for basket, name in self._basket_dict.items(): self.log = '' self.configuration.xtffile = os.path.join( self._export_dir, "{}.xtf".format(name)) self.configuration.baskets = basket self.exporter.configuration = self.configuration try: if self.exporter.run() != iliexporter.Exporter.SUCCESS: msg = QCoreApplication.translate( "BasketExporter", "An error occurred when exporting the data for '{}' (check the QGIS log panel)." ).format(name) res[basket] = (False, msg) QgsMessageLog.logMessage( self.log, QCoreApplication.translate( "BasketExporter", "Allocate to coordinators"), Qgis.Critical) else: res[basket] = (True, QCoreApplication.translate( "BasketExporter", "XTF export for '{}' successful!"). format(name)) except JavaNotFoundError: msg = QCoreApplication.translate( "BasketExporter", "Java {} could not be found. You can configure the JAVA_HOME environment variable manually, restart QGIS and try again." ).format(JAVA_REQUIRED_VERSION) res[basket] = (False, msg) count += 1 self.total_progress_updated.emit(count / total * 100) return res def get_ili_models(self): ili_models = list() model_names = self._db.get_models() if model_names: for model in LADMColModelRegistry().supported_models(): if not model.hidden() and model.full_name() in model_names: ili_models.append(model.full_name()) return ili_models def download_java_complete(self): self.export_baskets() #def on_process_finished(self): # self.run_export() #if self._basket_dict: # basket, = self._basket_dict.popitem() def on_process_started(self, command): self.log += command + '\n' def on_stderr(self, text): self.log += text
class DialogExportData(QDialog, DIALOG_UI): ValidExtensions = ['xtf', 'itf', 'gml', 'xml'] current_row_schema = 0 def __init__(self, iface, db, qgis_utils): QDialog.__init__(self) self.setupUi(self) QgsGui.instance().enableAutoGeometryRestore(self) self.iface = iface self.db = db self.qgis_utils = qgis_utils self.base_configuration = BaseConfiguration() self.ilicache = IliCache(self.base_configuration) self.ilicache.refresh() self.type_combo_box.clear() self.type_combo_box.addItem( QCoreApplication.translate("DialogExportData", "PostgreSQL/PostGIS"), 'pg') self.type_combo_box.addItem( QCoreApplication.translate("DialogExportData", "GeoPackage"), 'gpkg') self.type_combo_box.currentIndexChanged.connect(self.type_changed) self.type_changed() self.xtf_file_browse_button.clicked.connect( make_save_file_selector( self.xtf_file_line_edit, title=QCoreApplication.translate("DialogExportData", "Save in XTF Transfer File"), file_filter=QCoreApplication.translate( "DialogExportData", "XTF Transfer File (*.xtf);;Interlis 1 Transfer File (*.itf);;XML (*.xml);;GML (*.gml)" ), extension='.xtf', extensions=['.' + ext for ext in self.ValidExtensions])) self.xtf_file_browse_button.clicked.connect( self.xtf_browser_opened_to_true) self.xtf_browser_was_opened = False self.validators = Validators() fileValidator = FileValidator( pattern=['*.' + ext for ext in self.ValidExtensions], allow_non_existing=True) self.xtf_file_line_edit.setPlaceholderText( QCoreApplication.translate("DialogExportData", "[Name of the XTF to be created]")) self.xtf_file_line_edit.setValidator(fileValidator) self.xtf_file_line_edit.textChanged.connect( self.validators.validate_line_edits) self.xtf_file_line_edit.textChanged.connect( self.xtf_browser_opened_to_false) self.xtf_file_line_edit.textChanged.emit( self.xtf_file_line_edit.text()) # PG self.db_connect_label.setToolTip(self.db.get_display_conn_string()) self.db_connect_label.setText(self.db.dict_conn_params["database"]) self.connection_setting_button.clicked.connect(self.show_settings) self.connection_setting_button.setText( QCoreApplication.translate("DialogExportData", "Connection Settings")) # GPKG self.gpkg_file_line_edit.setPlaceholderText( QCoreApplication.translate( "DialogExportData", "[Name of the Geopackage to be created]")) self.gpkg_file_browse_button.clicked.connect( make_file_selector(self.gpkg_file_line_edit, title=QCoreApplication.translate( "DialogExportData", "Open GeoPackage database file"), file_filter=QCoreApplication.translate( "DialogExportData", "GeoPackage Database (*.gpkg)"))) gpkgFileValidator = FileValidator(pattern='*.gpkg') self.gpkg_file_line_edit.setValidator(gpkgFileValidator) self.gpkg_file_line_edit.textChanged.connect( self.validators.validate_line_edits) self.gpkg_file_line_edit.textChanged.emit( self.gpkg_file_line_edit.text()) # LOG self.log_config.setTitle( QCoreApplication.translate("DialogExportData", "Show log")) self.log_config.setFlat(True) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) self.buttonBox.accepted.disconnect() self.buttonBox.accepted.connect(self.accepted) self.buttonBox.clear() self.buttonBox.addButton(QDialogButtonBox.Cancel) self.buttonBox.addButton( QCoreApplication.translate("DialogExportData", "Export data"), QDialogButtonBox.AcceptRole) self.buttonBox.addButton(QDialogButtonBox.Help) self.buttonBox.helpRequested.connect(self.show_help) def showEvent(self, event): # update after create dialog self.update_schema_names_model() self.update_model_names(self.get_checked_schema()) self.restore_configuration() def update_schema_names_model(self): res, msg = self.db.test_connection() schema_names = self.db._schema_names_list() if schema_names: for schema_name in schema_names: item = QListWidgetItem(schema_name['schema_name']) item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable) item.setCheckState(Qt.Unchecked) self.schema_names_list_widget.addItem(item) default_item = self.schema_names_list_widget.item(0) default_item.setCheckState(Qt.Checked) else: self.schema_names_list_widget.clear() self.export_models_list_view.setModel(QStandardItemModel()) message_error = 'There are no schemes to export into the database. Please select another database.' self.txtStdout.setText( QCoreApplication.translate("DialogExportData", message_error)) self.show_message(message_error, Qgis.Warning) self.schema_names_list_widget.currentRowChanged.connect( self.on_current_row_changed_schema_names) self.schema_names_list_widget.itemChanged.connect( self.on_itemchanged_schema_name) def on_itemchanged_schema_name(self, selected_item): # disconnect signal to do changes in the items self.schema_names_list_widget.itemChanged.disconnect( self.on_itemchanged_schema_name) for index in range(self.schema_names_list_widget.count()): item = self.schema_names_list_widget.item(index) item.setCheckState(Qt.Unchecked) item.setSelected(False) if item == selected_item: select_index = index item = self.schema_names_list_widget.item(select_index) item.setCheckState(Qt.Checked) item.setSelected(True) # Update list view with models name info schema_name = item.text() self.update_model_names(schema_name) # connect signal to check when the items change self.schema_names_list_widget.itemChanged.connect( self.on_itemchanged_schema_name) def on_current_row_changed_schema_names(self, current_row): for index in range(self.schema_names_list_widget.count()): item = self.schema_names_list_widget.item(index) item.setCheckState(Qt.Unchecked) item = self.schema_names_list_widget.item(current_row) if item: item.setCheckState(Qt.Checked) # Update list view with models name info schema_name = item.text() self.update_model_names(schema_name) def update_model_names(self, dbschema): self.export_models_qmodel = QStandardItemModel() db_models = None if self.type_combo_box.currentData() == 'gpkg': db_models = self.db.get_models() elif self.type_combo_box.currentData() == 'pg': db_models = self.db.get_models(dbschema) if dbschema else None if db_models: for db_model in db_models: regex = re.compile(r'(?:\{[^\}]*\}|\s)') for modelname in regex.split(db_model['modelname']): if modelname and modelname not in DEFAULT_HIDDEN_MODELS: item = QStandardItem(modelname.strip()) item.setCheckable(False) item.setEditable(False) self.export_models_qmodel.appendRow(item) self.export_models_list_view.setModel(self.export_models_qmodel) def get_checked_schema(self): checked_schema = None for index in range(self.schema_names_list_widget.count()): item = self.schema_names_list_widget.item(index) if item.checkState() == Qt.Checked: checked_schema = item.text() break return checked_schema def get_ili_models(self): ili_models = list() for index in range(self.export_models_qmodel.rowCount()): item = self.export_models_qmodel.item(index) ili_models.append(item.text()) return ili_models def show_settings(self): dlg = self.qgis_utils.get_settings_dialog() dlg.tabWidget.setCurrentIndex(SETTINGS_CONNECTION_TAB_INDEX) if dlg.exec_(): self.db = self.qgis_utils.get_db_connection() self.db_connect_label.setToolTip(self.db.get_display_conn_string()) self.db_connect_label.setText(self.db.dict_conn_params['database']) self.update_schema_names_model() def accepted(self): configuration = self.update_configuration() if not self.get_checked_schema(): message_error = QCoreApplication.translate( "DialogExportData", "You need to select a valid schema where to get the data from." ) self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.connection_setting_button.setFocus() return if not self.xtf_file_line_edit.validator().validate( configuration.xtffile, 0)[0] == QValidator.Acceptable: message_error = QCoreApplication.translate( "DialogExportData", "Please set a valid XTF file before exporting data.") self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.xtf_file_line_edit.setFocus() return if not self.get_ili_models(): message_error = QCoreApplication.translate( "DialogExportData", "Please set a valid schema to export. This schema does not have information to export." ) self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.export_models_list_view.setFocus() return if not configuration.iliexportmodels: message_error = QCoreApplication.translate( "DialogExportData", "Please set a model before exporting data.") self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.export_models_list_view.setFocus() return if self.type_combo_box.currentData() == 'gpkg': if not configuration.dbfile or self.gpkg_file_line_edit.validator( ).validate(configuration.dbfile, 0)[0] != QValidator.Acceptable: message_error = QCoreApplication.translate( "DialogExportData", "Please set an existing database file before creating the project." ) self.txtStdout.setText(message_error) self.show_message(message_error, Qgis.Warning) self.gpkg_file_line_edit.setFocus() return # If xtf browser was opened and the file exists, the user already chose # to overwrite the file if os.path.isfile(self.xtf_file_line_edit.text().strip() ) and not self.xtf_browser_was_opened: self.msg = QMessageBox() self.msg.setIcon(QMessageBox.Warning) self.msg.setText( QCoreApplication.translate( "DialogExportData", "{filename} already exists.\nDo you want to replace it?"). format(filename=os.path.basename( self.xtf_file_line_edit.text().strip()))) self.msg.setWindowTitle( QCoreApplication.translate("DialogExportData", "Save in XTF Transfer File")) self.msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg_box = self.msg.exec_() if msg_box == QMessageBox.No: return with OverrideCursor(Qt.WaitCursor): self.progress_bar.show() self.progress_bar.setValue(0) self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() exporter = iliexporter.Exporter() exporter.tool_name = 'ili2pg' if self.type_combo_box.currentData( ) == 'pg' else 'ili2gpkg' exporter.configuration = configuration self.save_configuration(configuration) exporter.stdout.connect(self.print_info) exporter.stderr.connect(self.on_stderr) exporter.process_started.connect(self.on_process_started) exporter.process_finished.connect(self.on_process_finished) self.progress_bar.setValue(25) try: if exporter.run() != iliexporter.Exporter.SUCCESS: self.enable() self.progress_bar.hide() self.show_message( QCoreApplication.translate( "DialogExportData", "An error occurred when exporting the data. For more information see the log..." ), Qgis.Warning) return except JavaNotFoundError: # Set JAVA PATH get_java_path_dlg = DialogGetJavaPath() get_java_path_dlg.setModal(True) if get_java_path_dlg.exec_(): configuration = self.update_configuration() if not get_java_path_from_qgis_model_baker(): message_error_java = QCoreApplication.translate( "DialogExportData", """Java could not be found. You can configure the JAVA_HOME environment variable, restart QGIS and try again.""" ) self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(message_error_java) self.show_message(message_error_java, Qgis.Warning) self.enable() self.progress_bar.hide() return self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) self.progress_bar.setValue(100) self.show_message( QCoreApplication.translate( "DialogExportData", "Export of the data was successfully completed."), Qgis.Success) def save_configuration(self, configuration): settings = QSettings() settings.setValue( 'Asistente-LADM_COL/QgisModelBaker/ili2pg/xtffile_export', configuration.xtffile) settings.setValue('Asistente-LADM_COL/db_connection_source', self.type_combo_box.currentData()) settings.setValue('Asistente-LADM_COL/QgisModelBaker/show_log', not self.log_config.isCollapsed()) if self.type_combo_box.currentData() == 'gpkg': settings.setValue( 'Asistente-LADM_COL/QgisModelBaker/ili2gpkg/dbfile', configuration.dbfile) def restore_configuration(self): settings = QSettings() self.xtf_file_line_edit.setText( settings.value( 'Asistente-LADM_COL/QgisModelBaker/ili2pg/xtffile_export')) self.type_combo_box.setCurrentIndex( self.type_combo_box.findData( settings.value('Asistente-LADM_COL/db_connection_source', 'pg'))) self.type_changed() # Show log value_show_log = settings.value( 'Asistente-LADM_COL/QgisModelBaker/show_log', False, type=bool) self.log_config.setCollapsed(not value_show_log) # set model repository # if there is no option by default use online model repository custom_model_is_checked = settings.value( 'Asistente-LADM_COL/models/custom_model_directories_is_checked', type=bool) if custom_model_is_checked: self.custom_model_directories = settings.value( 'Asistente-LADM_COL/models/custom_models') def update_configuration(self): """ Get the configuration that is updated with the user configuration changes on the dialog. :return: Configuration """ configuration = ExportConfiguration() if self.type_combo_box.currentData() == 'pg': # PostgreSQL specific options configuration.dbhost = self.db.dict_conn_params["host"] configuration.dbport = self.db.dict_conn_params["port"] configuration.dbusr = self.db.dict_conn_params["username"] configuration.database = self.db.dict_conn_params["database"] configuration.dbschema = self.get_checked_schema() configuration.dbpwd = self.db.dict_conn_params["password"] elif self.type_combo_box.currentData() == 'gpkg': configuration.dbfile = self.db.dict_conn_params["dbfile"] configuration.xtffile = self.xtf_file_line_edit.text().strip() java_path = get_java_path_from_qgis_model_baker() if java_path: self.base_configuration.java_path = java_path # Check custom model directories if QSettings().value( 'Asistente-LADM_COL/models/custom_model_directories_is_checked', type=bool): if self.custom_model_directories is None: self.base_configuration.custom_model_directories_enabled = False else: self.base_configuration.custom_model_directories = self.custom_model_directories self.base_configuration.custom_model_directories_enabled = True configuration.base_configuration = self.base_configuration if self.get_ili_models(): configuration.iliexportmodels = ';'.join(self.get_ili_models()) configuration.ilimodels = ';'.join(self.get_ili_models()) return configuration def print_info(self, text, text_color='#000000', clear=False): self.txtStdout.setTextColor(QColor(text_color)) self.txtStdout.append(text) QCoreApplication.processEvents() def on_stderr(self, text): color_log_text(text, self.txtStdout) self.advance_progress_bar_by_text(text) def on_process_started(self, command): self.disable() self.txtStdout.setTextColor(QColor('#000000')) self.txtStdout.clear() self.txtStdout.setText(command) QCoreApplication.processEvents() def on_process_finished(self, exit_code, result): color = '#004905' if exit_code == 0 else '#aa2222' self.txtStdout.setTextColor(QColor(color)) self.txtStdout.append( QCoreApplication.translate("DialogExportData", "Finished ({})").format(exit_code)) if result == iliexporter.Exporter.SUCCESS: self.buttonBox.clear() self.buttonBox.setEnabled(True) self.buttonBox.addButton(QDialogButtonBox.Close) else: self.enable() def advance_progress_bar_by_text(self, text): if text.strip() == 'Info: compile models...': self.progress_bar.setValue(50) QCoreApplication.processEvents() elif text.strip() == 'Info: process data...': self.progress_bar.setValue(55) QCoreApplication.processEvents() elif text.strip() == 'Info: first validation pass...': self.progress_bar.setValue(70) QCoreApplication.processEvents() elif text.strip() == 'Info: second validation pass...': self.progress_bar.setValue(85) QCoreApplication.processEvents() def show_help(self): self.qgis_utils.show_help("export_data") def disable(self): self.type_combo_box.setEnabled(False) self.pg_config.setEnabled(False) self.ili_config.setEnabled(False) self.buttonBox.setEnabled(False) def enable(self): self.type_combo_box.setEnabled(True) self.pg_config.setEnabled(True) self.ili_config.setEnabled(True) self.buttonBox.setEnabled(True) def show_message(self, message, level): self.bar.pushMessage("Asistente LADM_COL", message, level, duration=0) def type_changed(self): self.progress_bar.hide() if self.type_combo_box.currentData() == 'pg': self.pg_config.show() self.gpkg_config.hide() elif self.type_combo_box.currentData() == 'gpkg': self.pg_config.hide() self.gpkg_config.show() def xtf_browser_opened_to_true(self): """ Slot. Sets a flag to true to eventually avoid asking a user whether to overwrite a file. """ self.xtf_browser_was_opened = True def xtf_browser_opened_to_false(self): """ Slot. Sets a flag to false to eventually ask a user whether to overwrite a file. """ self.xtf_browser_was_opened = False
class ImportSourceSelectionPage(QWizardPage, PAGE_UI): ValidExtensions = gui_utils.IliExtensions + gui_utils.TransferExtensions def __init__(self, parent, title): QWizardPage.__init__(self, parent) self.workflow_wizard = parent self.setupUi(self) self.setTitle(title) self.file_browse_button.clicked.connect( make_file_selector( self.input_line_edit, title=self.tr( "Open Interlis Model, Transfer or Catalogue File"), file_filter=self. tr("Interlis Model / Transfer / Catalogue File (*.ili *.xtf *.itf *.XTF *.ITF *.xml *.XML *.xls *.XLS *.xlsx *.XLSX)" ), )) self.fileValidator = FileValidator( pattern=["*." + ext for ext in self.ValidExtensions], allow_empty=False) self.ilicache = IliCache( self.workflow_wizard.import_schema_configuration.base_configuration ) self.model_delegate = ModelCompleterDelegate() self._refresh_ili_models_cache() self.input_line_edit.setPlaceholderText( self.tr("[Browse for file or search model from repository]")) # very unhappy about this behavior, but okay for prototype self.first_time_punched = False self.input_line_edit.punched.connect(self._first_time_punch) self.source_list_view.setModel(self.workflow_wizard.source_model) self.add_button.clicked.connect(self._add_row) self.remove_button.clicked.connect(self._remove_selected_rows) self.add_button.setEnabled(self._valid_source()) self.input_line_edit.textChanged.connect( lambda: self.add_button.setEnabled(self._valid_source())) self.remove_button.setEnabled(self._valid_selection()) self.source_list_view.clicked.connect( lambda: self.remove_button.setEnabled(self._valid_selection())) self.add_button.setIcon( QgsApplication.getThemeIcon("/symbologyAdd.svg")) self.remove_button.setIcon( QgsApplication.getThemeIcon("/symbologyRemove.svg")) self.source_list_view.files_dropped.connect( self.workflow_wizard.append_dropped_files) def nextId(self): self._disconnect_punch_slots() return self.workflow_wizard.next_id() def _first_time_punch(self): # might be nicer self.input_line_edit.punched.disconnect(self._first_time_punch) self.input_line_edit.textChanged.emit(self.input_line_edit.text()) self.input_line_edit.textChanged.connect( self._complete_models_completer) self.input_line_edit.punched.connect(self._complete_models_completer) self.first_time_punched = True def _disconnect_punch_slots(self): # might be nicer if self.first_time_punched: self.input_line_edit.textChanged.disconnect( self._complete_models_completer) self.input_line_edit.punched.disconnect( self._complete_models_completer) self.input_line_edit.punched.connect(self._first_time_punch) self.first_time_punched = False def _refresh_ili_models_cache(self): self.ilicache.new_message.connect( self.workflow_wizard.log_panel.show_message) self.ilicache.refresh() self.update_models_completer() def _complete_models_completer(self): if self.input_line_edit.hasFocus(): if not self.input_line_edit.text(): self.input_line_edit.completer().setCompletionMode( QCompleter.UnfilteredPopupCompletion) self.input_line_edit.completer().complete() else: match_contains = (self.input_line_edit.completer( ).completionModel().match( self.input_line_edit.completer().completionModel().index( 0, 0), Qt.DisplayRole, self.input_line_edit.text(), -1, Qt.MatchContains, )) if len(match_contains) > 1: self.input_line_edit.completer().setCompletionMode( QCompleter.PopupCompletion) self.input_line_edit.completer().complete() def _valid_source(self): match_contains = ( self.input_line_edit.completer().completionModel().match( self.input_line_edit.completer().completionModel().index(0, 0), Qt.DisplayRole, self.input_line_edit.text(), -1, Qt.MatchExactly, )) return (len(match_contains) == 1 or self.fileValidator.validate( self.input_line_edit.text(), 0)[0] == QValidator.Acceptable) def _valid_selection(self): return bool(self.source_list_view.selectedIndexes()) def update_models_completer(self): completer = QCompleter(self.ilicache.model, self.input_line_edit) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setFilterMode(Qt.MatchContains) completer.popup().setItemDelegate(self.model_delegate) self.input_line_edit.setCompleter(completer) def _add_row(self): source = self.input_line_edit.text() self.workflow_wizard.add_source( source, self.tr("Added by user over the wizard.")) self.input_line_edit.clearFocus() self.input_line_edit.clear() def _remove_selected_rows(self): indices = self.source_list_view.selectionModel().selectedIndexes() self.source_list_view.model().remove_sources(indices) self.remove_button.setEnabled(self._valid_selection())