class CreateUnbefFl: """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join(self.plugin_dir, 'i18n', 'CreateUnbefFl_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlg = CreateUnbefFlDialog() # Anfang Eigene Funktionen ------------------------------------------------- # (jh, 12.06.2017) logger.info(u'\n\nQKan_CreateUnbefFlaechen initialisiert...') # -------------------------------------------------------------------------- # Pfad zum Arbeitsverzeichnis sicherstellen wordir = os.path.join(site.getuserbase(), u'qkan') if not os.path.isdir(wordir): os.makedirs(wordir) # -------------------------------------------------------------------------------------------------- # Konfigurationsdatei qkan.json lesen # self.configfil = os.path.join(wordir, u'qkan.json') if os.path.exists(self.configfil): with open(self.configfil, 'r') as fileconfig: self.config = json.loads(fileconfig.read()) else: self.config = {'epsg': '25832'} # Projektionssystem with open(self.configfil, 'w') as fileconfig: fileconfig.write(json.dumps(self.config)) # Formularereignisse anbinden ---------------------------------------------- self.dlg.tw_selAbflparamTeilgeb.itemClicked.connect( self.tw_selAbflparamTeilgebClick) self.dlg.cb_selActive.stateChanged.connect(self.selActiveClick) self.dlg.button_box.helpRequested.connect(self.helpClick) # Ende Eigene Funktionen --------------------------------------------------- # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('CreateUnbefFl', message) def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/qkan/createunbeffl/icon.png' Dummy.instance.add_action( icon_path, text=self.tr(u'Erzeuge unbefestigte Flächen...'), callback=self.run, parent=self.iface.mainWindow()) def unload(self): pass # ------------------------------------------------------------------------- # Formularfunktionen def helpClick(self): """Reaktion auf Klick auf Help-Schaltfläche""" helpfile = os.path.join( self.plugin_dir, '../doc/sphinx/build/html/Qkan_Formulare.html#erzeugen-der-unbefestigten-flachen' ) webbrowser.open_new_tab(helpfile) def tw_selAbflparamTeilgebClick(self): """Reaktion auf Klick in Tabelle""" self.dlg.cb_selActive.setChecked(True) self.countselection() def selActiveClick(self): """Reagiert auf Checkbox zur Aktivierung der Auswahl""" # Checkbox hat den Status nach dem Klick if self.dlg.cb_selActive.isChecked(): # Nix tun ... logger.debug('\nChecked = True') else: # Auswahl deaktivieren und Liste zurücksetzen anz = self.dlg.tw_selAbflparamTeilgeb.rowCount() range = QTableWidgetSelectionRange(0, 0, anz - 1, 4) self.dlg.tw_selAbflparamTeilgeb.setRangeSelected(range, False) logger.debug('\nChecked = False\nQWidget: anzahl = {}'.format(anz)) # Anzahl in der Anzeige aktualisieren self.countselection() def countselection(self): """Zählt nach Änderung der Auswahlen in den Listen im Formular die Anzahl der betroffenen TEZG-Flächen""" liste_selAbflparamTeilgeb = self.listselectedTabitems( self.dlg.tw_selAbflparamTeilgeb) # logger.debug(u'QKan.createunbeffl.application.countselection (1)\nlen(liste_selAbflparamTeilgeb) = {}'.format(len(liste_selAbflparamTeilgeb))) # logger.debug(u'QKan.createunbeffl.application.countselection (2)\nliste_selAbflparamTeilgeb = {}'.format(str(liste_selAbflparamTeilgeb))) # Aufbereiten für SQL-Abfrage # Unterschiedliches Vorgehen, je nachdem ob mindestens eine oder keine Zeile # ausgewählt wurde # if len(liste_selAbflparamTeilgeb) == 0: # anzahl = sum([int(attr[-2]) for attr in self.listetezg]) # else: # anzahl = sum([int(attr[-2]) for attr in liste_selAbflparamTeilgeb]) # Vorbereitung des Auswahlkriteriums für die SQL-Abfrage: Kombination aus abflussparameter und teilgebiet # Dieser Block ist identisch in k_unbef und in application enthalten if len(liste_selAbflparamTeilgeb) == 0: auswahl = u'' elif len(liste_selAbflparamTeilgeb) == 1: auswahl = u' AND' elif len(liste_selAbflparamTeilgeb) >= 2: auswahl = u' AND (' else: fehlermeldung(u"Interner Fehler", u"Fehler in Fallunterscheidung!") return False # Anfang SQL-Krierien zur Auswahl der tezg-Flächen first = True for attr in liste_selAbflparamTeilgeb: if attr[4] == u'None' or attr[1] == u'None': fehlermeldung( u'Datenfehler: ', u'In den ausgewählten Daten sind noch Datenfelder nicht definiert ("NULL").' ) return False if first: first = False auswahl += u""" (tezg.abflussparameter = '{abflussparameter}' AND tezg.teilgebiet = '{teilgebiet}')""".format( abflussparameter=attr[0], teilgebiet=attr[1]) else: auswahl += u""" OR\n (tezg.abflussparameter = '{abflussparameter}' AND tezg.teilgebiet = '{teilgebiet}')""".format( abflussparameter=attr[0], teilgebiet=attr[1]) if len(liste_selAbflparamTeilgeb) >= 2: auswahl += u")" # Ende SQL-Krierien zur Auswahl der tezg-Flächen # Ende SQL-Krierien zur Auswahl der tezg-Flächen # Trick: Der Zusatz "WHERE 1" dient nur dazu, dass der Block zur Zusammenstellung von 'auswahl' identisch mit dem # Block in 'k_unbef.py' bleiben kann... sql = u"""SELECT count(*) AS anz FROM tezg WHERE 1{auswahl} """.format(auswahl=auswahl) if not self.dbQK.sql(sql, u"QKan.CreateUnbefFlaechen (5)"): return False data = self.dbQK.fetchone() if not (data is None): self.dlg.lf_anzahl_tezg.setText(u'{}'.format(data[0])) else: self.dlg.lf_anzahl_tezg.setText(u'0') # ------------------------------------------------------------------------- # Funktion zur Zusammenstellung einer Auswahlliste für eine SQL-Abfrage def listselectedTabitems(self, tableWidget, nCols=5): """Erstellt eine Liste aus den in einem Auswahllisten-Widget angeklickten Objektnamen :param tableWidget: Tabelle zur Auswahl der Arten von Haltungsflächen. :type tableWidget: QTableWidget :param nCols: Anzahl Spalten des tableWidget-Elements :type nCols: integer :returns: Tuple mit ausgewählten Abflussparametern :rtype: tuple """ items = tableWidget.selectedItems() anz = len(items) nRows = anz // nCols if len(items) > nCols: # mehr als eine Zeile ausgewählt if tableWidget.row(items[1]) == 1: # Elemente wurden spaltenweise übergeben liste = [[el.text() for el in items][i:anz:nRows] for i in range(nRows)] else: # Elemente wurden zeilenweise übergeben liste = [[el.text() for el in items][i:i + 5] for i in range(0, anz, 5)] else: # Elemente wurden zeilenweise übergeben oder Liste ist leer liste = [[el.text() for el in items][i:i + 5] for i in range(0, anz, 5)] return liste # ------------------------------------------------------------------------------------------------------------ # Vorbereiten und Öffnen des Formulars def run(self): """Run method that performs all the real work""" database_QKan, epsg = get_database_QKan() if not database_QKan: fehlermeldung( u"Fehler in CreateUnbefFl", u"database_QKan konnte nicht aus den Layern ermittelt werden. Abbruch!" ) logger.error( u"CreateUnbefFl: database_QKan konnte nicht aus den Layern ermittelt werden. Abbruch!" ) return False # Abfragen der Tabelle tezg nach verwendeten Abflussparametern self.dbQK = DBConnection( dbname=database_QKan ) # Datenbankobjekt der QKan-Datenbank zum Lesen if self.dbQK is None: fehlermeldung( u"Fehler in QKan_CreateUnbefFl", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format( database_QKan)) iface.messageBar().pushMessage(u"Fehler in QKan_Import_from_HE", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format( \ database_QKan), level=QgsMessageBar.CRITICAL) return None # Kontrolle, ob in Tabelle "abflussparameter" ein Datensatz für unbefestigte Flächen vorhanden ist # (Standard: apnam = '$Default_Unbef') sql = u"""SELECT apnam FROM abflussparameter WHERE bodenklasse IS NOT NULL AND trim(bodenklasse) <> ''""" if not self.dbQK.sql(sql, u'createunbeffl.run (1)'): return False data = self.dbQK.fetchone() if data is None: if autokorrektur: daten = [ u"'$Default_Unbef', u'von QKan ergänzt', 0.5, 0.5, 2, 5, 0, 0, 'LehmLoess', '13.01.2011 08:44:50'" ] for ds in daten: sql = u"""INSERT INTO abflussparameter ( 'apnam', 'kommentar', 'anfangsabflussbeiwert', 'endabflussbeiwert', 'benetzungsverlust', 'muldenverlust', 'benetzung_startwert', 'mulden_startwert', 'bodenklasse', 'createdat') Values ({})""".format(ds) if not self.dbQK.sql(sql, u'createunbeffl.run (2)'): return False else: fehlermeldung( u'Datenfehler: ', u'Bitte ergänzen Sie in der Tabelle "abflussparameter" einen Datensatz für unbefestigte Flächen ("bodenklasse" darf nicht leer oder NULL sein)' ) # # Kontrolle, ob noch Flächen in Tabelle "tezg" ohne Zuordnung zu einem Abflussparameter oder zu einem # # Abflussparameter, bei dem keine Bodenklasse definiert ist (Kennzeichen für undurchlässige Flächen). # sql = u"""SELECT te.abflussparameter, te.teilgebiet, count(*) AS anz # FROM tezg AS te # LEFT JOIN abflussparameter AS ap # ON te.abflussparameter = ap.apnam # WHERE ap.bodenklasse IS NULL # GROUP BY abflussparameter, teilgebiet""" # if not self.dbQK.sql(sql, u'createunbeffl.run (3)'): # return False # data = self.dbQK.fetchall() # if len(data) > 0: # liste = [u'{}\t{}\t{}'.format(el1, el2, el3) for el1, el2, el3 in data] # liste.insert(0, u'\nAbflussparameter\tTeilgebiet\tAnzahl') # fehlermeldung(u'In Tabelle "tezg" fehlen Abflussparameter oder gehören zu befestigten Flächen (Bodenklasse = NULL):\n', # u'\n'.join(liste)) # return False sql = u"""SELECT te.abflussparameter, te.teilgebiet, bk.bknam, count(*) AS anz, CASE WHEN te.abflussparameter ISNULL THEN 'Fehler: Kein Abflussparameter angegeben' ELSE CASE WHEN bk.infiltrationsrateanfang ISNULL THEN 'Fehler: Keine Bodenklasse angegeben' WHEN bk.infiltrationsrateanfang < 0.00001 THEN 'Fehler: undurchlässige Bodenart' ELSE '' END END AS status FROM tezg AS te LEFT JOIN abflussparameter AS ap ON te.abflussparameter = ap.apnam LEFT JOIN bodenklassen AS bk ON bk.bknam = ap.bodenklasse GROUP BY abflussparameter, teilgebiet""" if not self.dbQK.sql(sql, u'createunbeffl.run (4)'): return None self.listetezg = self.dbQK.fetchall() nzeilen = len(self.listetezg) self.dlg.tw_selAbflparamTeilgeb.setRowCount(nzeilen) self.dlg.tw_selAbflparamTeilgeb.setHorizontalHeaderLabels([ u"Abflussparameter", u"Teilgebiet", u"Bodenklasse", u"Anzahl", u"Anmerkungen" ]) self.dlg.tw_selAbflparamTeilgeb.setColumnWidth( 0, 144) # 17 Pixel für Rand und Nummernspalte (und je Spalte?) self.dlg.tw_selAbflparamTeilgeb.setColumnWidth(1, 140) self.dlg.tw_selAbflparamTeilgeb.setColumnWidth(2, 90) self.dlg.tw_selAbflparamTeilgeb.setColumnWidth(3, 50) self.dlg.tw_selAbflparamTeilgeb.setColumnWidth(4, 200) for i, elem in enumerate(self.listetezg): for j, item in enumerate(elem): cell = u'{}'.format(elem[j]) self.dlg.tw_selAbflparamTeilgeb.setItem( i, j, QTableWidgetItem(cell)) self.dlg.tw_selAbflparamTeilgeb.setRowHeight(i, 20) # config in Dialog übernehmen # Autokorrektur if 'autokorrektur' in self.config: autokorrektur = self.config['autokorrektur'] else: autokorrektur = True self.dlg.cb_autokorrektur.setChecked(autokorrektur) self.countselection() # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() logger.debug('\n\nresult = {}'.format(repr(result))) # See if OK was pressed if result: # Do something useful here - delete the line containing pass and # substitute with your code. # pass # Start der Verarbeitung liste_selAbflparamTeilgeb = self.listselectedTabitems( self.dlg.tw_selAbflparamTeilgeb) logger.debug(u'\nliste_selAbflparamTeilgeb (1): {}'.format( liste_selAbflparamTeilgeb)) autokorrektur = self.dlg.cb_autokorrektur.isChecked() self.config['autokorrektur'] = autokorrektur with open(self.configfil, 'w') as fileconfig: fileconfig.write(json.dumps(self.config)) createUnbefFlaechen(self.dbQK, liste_selAbflparamTeilgeb, autokorrektur)
class ExportToKP: """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ self.templatepath = os.path.join(pluginDirectory('qkan'), u"database/templates") # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join( self.plugin_dir, 'i18n', 'ExportToKP_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlg = ExportToKPDialog() # Anfang Eigene Funktionen ------------------------------------------------- # (jh, 08.02.2017) logger.info('\n\nQKan_ExportKP initialisiert...') # -------------------------------------------------------------------------- # Pfad zum Arbeitsverzeichnis sicherstellen wordir = os.path.join(site.getuserbase(), 'qkan') if not os.path.isdir(wordir): os.makedirs(wordir) # -------------------------------------------------------------------------- # Konfigurationsdatei qkan.json lesen # self.configfil = os.path.join(wordir, 'qkan.json') if os.path.exists(self.configfil): with open(self.configfil, 'r') as fileconfig: self.config = json.loads(fileconfig.read()) else: self.config['dynafile'] = '' # Vorlagedatenbank nur für den Fall, dass der Anwender keine eigene Vorlage erstellen will self.config['template_dyna'] = os.path.join(os.path.dirname(__file__), "templates", "dyna.ein") self.config['database_QKan'] = '' with open(self.configfil, 'w') as fileconfig: fileconfig.write(json.dumps(self.config)) # Standard für Suchverzeichnis festlegen project = QgsProject.instance() self.default_dir = os.path.dirname(project.fileName()) # Formularereignisse anbinden ---------------------------------------------- self.dlg.pb_select_KP_dest.clicked.connect(self.selectFile_kpDB_dest) self.dlg.pb_select_KP_template.clicked.connect(self.selectFile_kpDB_template) self.dlg.lw_teilgebiete.itemClicked.connect(self.lw_teilgebieteClick) self.dlg.cb_selActive.stateChanged.connect(self.selActiveClick) self.dlg.button_box.helpRequested.connect(self.helpClick) self.dlg.pb_selectQKanDB.clicked.connect(self.selectFile_QKanDB) # Ende Eigene Funktionen --------------------------------------------------- # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('ExportToKP', message) def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/qkan/exportdyna/res/icon_qk2kp.png' Dummy.instance.add_action(icon_path, text=self.tr(u'Export in DYNA-Datei...'), callback=self.run, parent=self.iface.mainWindow()) def unload(self): pass # Anfang Eigene Funktionen ------------------------------------------------- # (jh, 08.02.2017) def selectFile_kpDB_dest(self): """Zu erstellende DYNA-Datei eingeben""" filename = QFileDialog.getSaveFileName(self.dlg, "Dateinamen der zu schreibenden DYNA-Datei eingeben", self.default_dir, "*.ein") # if os.path.dirname(filename) != '': # os.chdir(os.path.dirname(filename)) self.dlg.tf_KP_dest.setText(filename) def selectFile_kpDB_template(self): """Vorlage-DYNA-Datei auswaehlen.""" filename = QFileDialog.getOpenFileName(self.dlg, u"Vorlage-DYNA-Datei auswählen", self.default_dir, "*.ein") # if os.path.dirname(filename) != '': # os.chdir(os.path.dirname(filename)) self.dlg.tf_KP_template.setText(filename) def selectFile_QKanDB(self): """Datenbankverbindung zur QKan-Datenbank (SpatiLite) auswaehlen.""" filename = QFileDialog.getOpenFileName(self.dlg, u"QKan-Datenbank auswählen", self.default_dir, "*.sqlite") # if os.path.dirname(filename) != '': # os.chdir(os.path.dirname(filename)) self.dlg.tf_QKanDB.setText(filename) # ------------------------------------------------------------------------- # Formularfunktionen def helpClick(self): """Reaktion auf Klick auf Help-Schaltfläche""" helpfile = os.path.join(self.plugin_dir, '..\doc', 'exportdyna.html') os.startfile(helpfile) def lw_teilgebieteClick(self): """Reaktion auf Klick in Tabelle""" self.dlg.cb_selActive.setChecked(True) self.countselection() def selActiveClick(self): """Reagiert auf Checkbox zur Aktivierung der Auswahl""" # Checkbox hat den Status nach dem Klick if self.dlg.cb_selActive.isChecked(): # Nix tun ... logger.debug('\nChecked = True') else: # Auswahl deaktivieren und Liste zurücksetzen anz = self.dlg.lw_teilgebiete.count() for i in range(anz): item = self.dlg.lw_teilgebiete.item(i) self.dlg.lw_teilgebiete.setItemSelected(item, False) # Anzahl in der Anzeige aktualisieren self.countselection() def countselection(self): """Zählt nach Änderung der Auswahlen in den Listen im Formular die Anzahl der betroffenen Flächen und Haltungen""" liste_teilgebiete = self.listselecteditems(self.dlg.lw_teilgebiete) # Zu berücksichtigende Flächen zählen auswahl = '' if len(liste_teilgebiete) != 0: auswahl = u" WHERE flaechen.teilgebiet in ('{}')".format("', '".join(liste_teilgebiete)) sql = u"""SELECT count(*) AS anzahl FROM flaechen{auswahl}""".format(auswahl=auswahl) if not self.dbQK.sql(sql, u"QKan_ExportDYNA.application.countselection (1)"): return False daten = self.dbQK.fetchone() if not (daten is None): self.dlg.lf_anzahl_flaechen.setText(str(daten[0])) else: self.dlg.lf_anzahl_flaechen.setText('0') # Zu berücksichtigende Schächte zählen auswahl = '' if len(liste_teilgebiete) != 0: auswahl = u" WHERE schaechte.teilgebiet in ('{}')".format("', '".join(liste_teilgebiete)) sql = u"""SELECT count(*) AS anzahl FROM schaechte{auswahl}""".format(auswahl=auswahl) if not self.dbQK.sql(sql, u"QKan_ExportDYNA.application.countselection (2) "): return False daten = self.dbQK.fetchone() if not (daten is None): self.dlg.lf_anzahl_schaechte.setText(str(daten[0])) else: self.dlg.lf_anzahl_schaechte.setText('0') # Zu berücksichtigende Haltungen zählen auswahl = '' if len(liste_teilgebiete) != 0: auswahl = u" WHERE haltungen.teilgebiet in ('{}')".format("', '".join(liste_teilgebiete)) sql = u"""SELECT count(*) AS anzahl FROM haltungen{auswahl}""".format(auswahl=auswahl) if not self.dbQK.sql(sql, u"QKan_ExportDYNA.application.countselection (3) "): return False daten = self.dbQK.fetchone() if not (daten is None): self.dlg.lf_anzahl_haltungen.setText(str(daten[0])) else: self.dlg.lf_anzahl_haltungen.setText('0') # ------------------------------------------------------------------------- # Funktion zur Zusammenstellung einer Auswahlliste für eine SQL-Abfrage def listselecteditems(self, listWidget): """Erstellt eine Liste aus den in einem Auswahllisten-Widget angeklickten Objektnamen :param listWidget: String for translation. :type listWidget: QListWidgetItem :returns: Tuple containing selected teilgebiete :rtype: tuple """ items = listWidget.selectedItems() liste = [] for elem in items: liste.append(elem.text()) return liste # Ende Eigene Funktionen --------------------------------------------------- def run(self): """Run method that performs all the real work""" # show the dialog # Check, ob die relevanten Layer nicht editable sind. if len({'flaechen', 'haltungen', 'linkfl', 'tezg', 'schaechte'} & get_editable_layers()) > 0: iface.messageBar().pushMessage(u"Bedienerfehler: ", u'Die zu verarbeitenden Layer dürfen nicht im Status "bearbeitbar" sein. Abbruch!', level=QgsMessageBar.CRITICAL) return False if 'dynafile' in self.config: dynafile = self.config['dynafile'] else: dynafile = '' self.dlg.tf_KP_dest.setText(dynafile) if 'template_dyna' in self.config: template_dyna = self.config['template_dyna'] else: template_dyna = '' self.dlg.tf_KP_template.setText(template_dyna) if 'datenbanktyp' in self.config: datenbanktyp = self.config['datenbanktyp'] else: datenbanktyp = 'spatialite' pass # Es gibt noch keine Wahlmöglichkeit # Übernahme der Quelldatenbank: # Wenn ein Projekt geladen ist, wird die Quelldatenbank daraus übernommen. # Wenn dies nicht der Fall ist, wird die Quelldatenbank aus der # json-Datei übernommen. database_QKan = '' database_QKan, epsg = get_database_QKan() if not database_QKan: if 'database_QKan' in self.config: database_QKan = self.config['database_QKan'] else: database_QKan = '' self.dlg.tf_QKanDB.setText(database_QKan) # Datenbankverbindung für Abfragen if database_QKan != '': # Nur wenn schon eine Projekt geladen oder eine QKan-Datenbank ausgewählt self.dbQK = DBConnection(dbname=database_QKan) # Datenbankobjekt der QKan-Datenbank zum Lesen if self.dbQK is None: fehlermeldung("Fehler in QKan_CreateUnbefFl", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format(database_QKan)) iface.messageBar().pushMessage("Fehler in QKan_Import_from_HE", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format( \ database_QKan), level=QgsMessageBar.CRITICAL) return None # Check, ob alle Teilgebiete in Flächen, Schächten und Haltungen auch in Tabelle "teilgebiete" enthalten sql = u"""INSERT INTO teilgebiete (tgnam) SELECT teilgebiet FROM flaechen WHERE teilgebiet IS NOT NULL AND teilgebiet NOT IN (SELECT tgnam FROM teilgebiete) GROUP BY teilgebiet""" if not self.dbQK.sql(sql, u"QKan_ExportDYNA.application.run (1) "): return False sql = u"""INSERT INTO teilgebiete (tgnam) SELECT teilgebiet FROM haltungen WHERE teilgebiet IS NOT NULL AND teilgebiet NOT IN (SELECT tgnam FROM teilgebiete) GROUP BY teilgebiet""" if not self.dbQK.sql(sql, u"QKan_ExportDYNA.application.run (2) "): return False sql = u"""INSERT INTO teilgebiete (tgnam) SELECT teilgebiet FROM schaechte WHERE teilgebiet IS NOT NULL AND teilgebiet NOT IN (SELECT tgnam FROM teilgebiete) GROUP BY teilgebiet""" if not self.dbQK.sql(sql, u"QKan_ExportDYNA.application.run (3) "): return False self.dbQK.commit() # Anlegen der Tabelle zur Auswahl der Teilgebiete # Zunächst wird die Liste der beim letzten Mal gewählten Teilgebiete aus config gelesen liste_teilgebiete = [] if 'liste_teilgebiete' in self.config: liste_teilgebiete = self.config['liste_teilgebiete'] # Abfragen der Tabelle teilgebiete nach Teilgebieten sql = 'SELECT "tgnam" FROM "teilgebiete" GROUP BY "tgnam"' if not self.dbQK.sql(sql, u"QKan_ExportDYNA.application.run (4) "): return False daten = self.dbQK.fetchall() self.dlg.lw_teilgebiete.clear() for ielem, elem in enumerate(daten): self.dlg.lw_teilgebiete.addItem(QListWidgetItem(elem[0])) try: if elem[0] in liste_teilgebiete: self.dlg.lw_teilgebiete.setCurrentRow(ielem) except BaseException as err: fehlermeldung(u'QKan_ExportDYNA (6), Fehler in elem = {}\n'.format(elem), repr(err)) # if len(daten) == 1: # self.dlg.lw_teilgebiete.setCurrentRow(0) # Ereignis bei Auswahländerung in Liste Teilgebiete self.countselection() # Autokorrektur if 'autokorrektur' in self.config: autokorrektur = self.config['autokorrektur'] else: autokorrektur = True self.dlg.cb_autokorrektur.setChecked(autokorrektur) if 'autonummerierung_dyna' in self.config: autonummerierung_dyna = self.config['autonummerierung_dyna'] else: autonummerierung_dyna = False self.dlg.cb_autonummerierung_dyna.setChecked(autonummerierung_dyna) # Festlegung des Fangradius # Kann über Menü "Optionen" eingegeben werden if 'fangradius' in self.config: fangradius = self.config['fangradius'] else: fangradius = u'0.1' # Mindestflächengröße # Kann über Menü "Optionen" eingegeben werden if 'mindestflaeche' in self.config: mindestflaeche = self.config['mindestflaeche'] else: mindestflaeche = u'0.5' # Maximalzahl Schleifendurchläufe if 'max_loops' in self.config: max_loops = self.config['max_loops'] else: max_loops = 1000 # Optionen zur Berechnung der befestigten Flächen if 'dynabef_choice' in self.config: dynabef_choice = self.config['dynabef_choice'] else: dynabef_choice = u'flaechen' if dynabef_choice == u'flaechen': self.dlg.rb_flaechen.setChecked(True) elif dynabef_choice == u'tezg': self.dlg.rb_tezg.setChecked(True) # Optionen zur Zuordnung des Profilschlüssels if 'dynaprof_choice' in self.config: dynaprof_choice = self.config['dynaprof_choice'] else: dynaprof_choice = u'profilname' if dynaprof_choice == u'profilname': self.dlg.rb_profnam.setChecked(True) elif dynaprof_choice == u'profilkey': self.dlg.rb_profkey.setChecked(True) # Formular anzeigen self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: # Abrufen der ausgewählten Elemente in beiden Listen liste_teilgebiete = self.listselecteditems(self.dlg.lw_teilgebiete) # Eingaben aus Formular übernehmen database_QKan = self.dlg.tf_QKanDB.text() dynafile = self.dlg.tf_KP_dest.text() template_dyna = self.dlg.tf_KP_template.text() autokorrektur = self.dlg.cb_autokorrektur.isChecked() autonummerierung_dyna = self.dlg.cb_autonummerierung_dyna.isChecked() if self.dlg.rb_flaechen.isChecked(): dynabef_choice = u'flaechen' elif self.dlg.rb_tezg.isChecked(): dynabef_choice = u'tezg' else: fehlermeldung(u"exportdyna.application.run", u"Fehlerhafte Option: \ndynabef_choice = {}".format(repr(dynabef_choice))) if self.dlg.rb_profnam.isChecked(): dynaprof_choice = u'profilname' elif self.dlg.rb_profkey.isChecked(): dynaprof_choice = u'profilkey' else: fehlermeldung(u"exportdyna.application.run", u"Fehlerhafte Option: \ndynaprof_choice = {}".format(repr(dynaprof_choice))) # Konfigurationsdaten schreiben self.config['dynafile'] = dynafile self.config['template_dyna'] = template_dyna self.config['database_QKan'] = database_QKan self.config['liste_teilgebiete'] = liste_teilgebiete self.config['autokorrektur'] = autokorrektur self.config['autonummerierung_dyna'] = autonummerierung_dyna self.config['fangradius'] = fangradius self.config['mindestflaeche'] = mindestflaeche self.config['max_loops'] = max_loops self.config['dynabef_choice'] = dynabef_choice self.config['dynaprof_choice'] = dynaprof_choice with open(self.configfil, 'w') as fileconfig: # logger.debug(u"Config-Dictionary: {}".format(self.config)) fileconfig.write(json.dumps(self.config)) exportKanaldaten(iface, dynafile, template_dyna, self.dbQK, dynabef_choice, dynaprof_choice, liste_teilgebiete, autokorrektur, autonummerierung_dyna, fangradius, mindestflaeche, max_loops, datenbanktyp)
class QKanTools: """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join( self.plugin_dir, 'i18n', 'Flaechenzuordnungen_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlgpr = QgsadaptDialog() self.dlgop = QKanOptionsDialog() self.dlgro = RunoffParamsDialog() # Anfang Eigene Funktionen ------------------------------------------------- # (jh, 12.06.2017) logger.info(u'\n\nQKan_Tools initialisiert...') # -------------------------------------------------------------------------- # Pfad zum Arbeitsverzeichnis sicherstellen wordir = os.path.join(site.getuserbase(), 'qkan') if not os.path.isdir(wordir): os.makedirs(wordir) # -------------------------------------------------------------------------------------------------- # Konfigurationsdatei qkan.json lesen # self.configfil = os.path.join(wordir, 'qkan.json') if os.path.exists(self.configfil): with open(self.configfil, 'r') as fileconfig: self.config = json.loads(fileconfig.read()) else: self.config = {'epsg': '25832'} # Projektionssystem with open(self.configfil, 'w') as fileconfig: fileconfig.write(json.dumps(self.config)) # Formularereignisse anbinden ---------------------------------------------- # Formular dlgpr self.dlgpr.pb_selectProjectFile.clicked.connect(self.dlgpr_selectFileProjectfile) self.dlgpr.pb_selectQKanDB.clicked.connect(self.dlgpr_selectFile_qkanDB) self.dlgpr.pb_selectProjectTemplate.clicked.connect(self.dlgpr_selectFileProjectTemplate) # Formular dlgop self.dlgop.pb_fangradiusDefault.clicked.connect(self.dlgop_fangradiusDefault) self.dlgop.pb_mindestflaecheDefault.clicked.connect(self.dlgop_mindestflaecheDefault) self.dlgop.pb_max_loopsDefault.clicked.connect(self.dlgop_maxLoopsDefault) self.dlgop.pb_selectKBS.clicked.connect(self.dlgop_selectKBS) # Formular dlgro self.dlgro.lw_teilgebiete.itemClicked.connect(self.dlgro_lwTeilgebieteClick) self.dlgro.lw_abflussparameter.itemClicked.connect(self.dlgro_lwAbflussparamsClick) self.dlgro.cb_selTgbActive.stateChanged.connect(self.dlgro_selTgbActiveClick) self.dlgro.cb_selParActive.stateChanged.connect(self.dlgro_selParActiveClick) self.dlgro.button_box.helpRequested.connect(self.dlgro_helpClick) self.dlgro.pb_selectQKanDB.clicked.connect(self.dlgro_selectFile_qkanDB) # Ende Eigene Funktionen --------------------------------------------------- # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('Flaechenzuordnungen', message) def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_qgsadapt_path = ':/plugins/qkan/tools/res/icon_qgsadapt.png' Dummy.instance.add_action( icon_qgsadapt_path, text=self.tr(u'Projektdatei auf bestehende QKan-Datenbank übertragen'), callback=self.run_qgsadapt, parent=self.iface.mainWindow()) icon_qkanoptions_path = ':/plugins/qkan/tools/res/icon_qkanoptions.png' Dummy.instance.add_action( icon_qkanoptions_path, text=self.tr(u'Allgemeine Optionen'), callback=self.run_qkanoptions, parent=self.iface.mainWindow()) icon_runoffparams_path = ':/plugins/qkan/tools/res/icon_runoffparams.png' Dummy.instance.add_action( icon_runoffparams_path, text=self.tr(u'Oberflächenabflussparameter eintragen'), callback=self.run_runoffparams, parent=self.iface.mainWindow()) def unload(self): pass # ----------------------------------------------------------------------------------------------------- # Erstellen einer Projektdatei aus einer Vorlage # 1. Formularfunktionen def dlgpr_selectFileProjectfile(self): """Zu erstellende Projektdatei festlegen""" filename = QFileDialog.getSaveFileName(self.dlgpr, "Dateinamen der zu erstellenden Projektdatei eingeben", self.default_dir, "*.qgs") # logger.info('Dateiname wurde erkannt zu:\n{}'.format(filename)) if os.path.dirname(filename) != '': os.chdir(os.path.dirname(filename)) self.dlgpr.tf_projectFile.setText(filename) def dlgpr_selectFile_qkanDB(self): """Anzubindende QKan-Datenbank festlegen""" filename = QFileDialog.getOpenFileName(self.dlgpr, "QKan-Datenbank auswählen", self.default_dir, "*.sqlite") if os.path.dirname(filename) != '': os.chdir(os.path.dirname(filename)) self.dlgpr.tf_qkanDB.setText(filename) def dlgpr_selectFileProjectTemplate(self): """Vorlage-Projektdatei auswählen""" self.setPathToTemplateDir = self.dlgpr.cb_setPathToTemplateDir.isChecked() if self.setPathToTemplateDir: self.templateDir = os.path.join(pluginDirectory('qkan'), u"database/templates") else: try: self.templateDir = os.path.dirname(self.database_QKan) except: logger.error('Programmfehler in tools.run_qgsadapt:\nPfad konnte nicht auf ' + \ 'database_QKan gesetzt werden.\n database_QKan = {}'.format( self.database_QKan)) self.templateDir = '' filename = QFileDialog.getOpenFileName(self.dlgpr, "Vorlage für zu erstellende Projektdatei auswählen", self.templateDir, "*.qgs") if os.path.dirname(filename) != '': os.chdir(os.path.dirname(filename)) self.dlgpr.tf_projectTemplate.setText(filename) # ----------------------------------------------------------------------------------------------------- # 2. Aufruf des Formulars def run_qgsadapt(self): '''Erstellen einer Projektdatei aus einer Vorlage''' # Formularfelder setzen ------------------------------------------------------------------------- # Formularfeld Datenbank # Falls eine Datenbank angebunden ist, wird diese zunächst in das Formular eingetragen. self.database_QKan, epsg = get_database_QKan(silent = True) if self.database_QKan: self.default_dir = os.path.dirname(self.database_QKan) # bereits geladene QKan-Datenbank übernehmen elif 'database_QKan' in self.config: self.database_QKan = self.config['database_QKan'] self.dlgpr.tf_qkanDB.setText(self.database_QKan) self.default_dir = os.path.dirname(self.database_QKan) else: self.database_QKan = '' self.default_dir = '.' self.dlgpr.tf_qkanDB.setText(self.database_QKan) # Formularfeld Vorlagedatei if 'projectTemplate' in self.config: projectTemplate = self.config['projectTemplate'] else: projectTemplate = '' # Formularfeld Projektdatei if 'projectfile' in self.config: projectfile = self.config['projectfile'] else: projectfile = '' # Option: Suchpfad für Vorlagedatei auf template-Verzeichnis setzen if 'setPathToTemplateDir' in self.config: self.setPathToTemplateDir = self.config['setPathToTemplateDir'] else: self.setPathToTemplateDir = True self.dlgpr.cb_setPathToTemplateDir.setChecked(self.setPathToTemplateDir) # Option: QKan-Datenbank aktualisieren if 'qkanDBUpdate' in self.config: qkanDBUpdate = self.config['qkanDBUpdate'] else: qkanDBUpdate = True self.dlgpr.cb_qkanDBUpdate.setChecked(qkanDBUpdate) # show the dialog self.dlgpr.show() # Run the dialog event loop result = self.dlgpr.exec_() # See if OK was pressed if result: # Inhalte aus Formular lesen -------------------------------------------------------------- projectTemplate = self.dlgpr.tf_projectTemplate.text() self.database_QKan = self.dlgpr.tf_qkanDB.text() projectfile = self.dlgpr.tf_projectFile.text() self.setPathToTemplateDir = self.dlgpr.cb_setPathToTemplateDir.isChecked() qkanDBUpdate = self.dlgpr.cb_qkanDBUpdate.isChecked() # Konfigurationsdaten schreiben ----------------------------------------------------------- self.config['projectTemplate'] = projectTemplate self.config['database_QKan'] = self.database_QKan self.config['projectfile'] = projectfile self.config['setPathToTemplateDir'] = self.setPathToTemplateDir self.config['qkanDBUpdate'] = qkanDBUpdate with open(self.configfil, 'w') as fileconfig: fileconfig.write(json.dumps(self.config)) qgsadapt(projectTemplate, self.database_QKan, epsg, projectfile, self.setPathToTemplateDir, u'SpatiaLite') # ---------------------------------------------------------------------------------------------------- # Allgemeine QKan-Optionen bearbeiten # 1. Formularfunktionen def dlgop_selectKBS(self): """KBS auswählen. Setzt das KBS für die weiteren Funktionen :returns: void """ projSelector = QgsGenericProjectionSelector() projSelector.exec_() erg = projSelector.selectedAuthId() if len(erg.split(u':')) == 2: self.dlgop.tf_epsg.setText(erg.split(u':')[1]) else: self.dlgop.tf_epsg.setText(erg) def dlgop_fangradiusDefault(self): self.dlgop.tf_fangradius.setText('0.1') def dlgop_mindestflaecheDefault(self): self.dlgop.tf_mindestflaeche.setText('0.5') def dlgop_maxLoopsDefault(self): self.dlgop.tf_max_loops.setText('1000') # ----------------------------------------------------------------------------------------- # 2. Aufruf des Formulars def run_qkanoptions(self): '''Bearbeitung allgemeiner QKan-Optionen''' # Formularfelder setzen ------------------------------------------------------------------------- # Fangradius für Anfang der Anbindungslinie if 'fangradius' in self.config: fangradius = self.config['fangradius'] else: fangradius = u'0.1' self.dlgop.tf_fangradius.setText(str(fangradius)) # Mindestflächengröße if 'mindestflaeche' in self.config: mindestflaeche = self.config['mindestflaeche'] else: mindestflaeche = u'0.5' self.dlgop.tf_mindestflaeche.setText(str(mindestflaeche)) # Maximalzahl Schleifendurchläufe if 'max_loops' in self.config: max_loops = self.config['max_loops'] else: max_loops = '1000' self.dlgop.tf_max_loops.setText(str(max_loops)) # Optionen zum Typ der QKan-Datenbank if 'datenbanktyp' in self.config: datenbanktyp = self.config['datenbanktyp'] else: datenbanktyp = u'spatialite' if datenbanktyp == u'spatialite': self.dlgop.rb_spatialite.setChecked(True) # elif datenbanktyp == u'postgis': # self.dlgop.rb_postgis.setChecked(True) if 'epsg' in self.config: self.epsg = self.config['epsg'] else: self.epsg = u'25832' self.dlgop.tf_epsg.setText(self.epsg) # show the dialog self.dlgop.show() # Run the dialog event loop result = self.dlgop.exec_() # See if OK was pressed if result: # Inhalte aus Formular lesen -------------------------------------------------------------- fangradius = self.dlgop.tf_fangradius.text() mindestflaeche = self.dlgop.tf_mindestflaeche.text() max_loops = self.dlgop.tf_max_loops.text() if self.dlgop.rb_spatialite.isChecked(): datenbanktyp = u'spatialite' # elif self.dlgop.rb_postgis.isChecked(): # datenbanktyp = u'postgis' else: fehlermeldung(u"tools.application.run", u"Fehlerhafte Option: \ndatenbanktyp = {}".format(repr(datenbanktyp))) epsg = self.dlgop.tf_epsg.text() self.config['fangradius'] = fangradius self.config['mindestflaeche'] = mindestflaeche self.config['max_loops'] = max_loops self.config['datenbanktyp'] = datenbanktyp self.config['epsg'] = epsg with open(self.configfil, 'w') as fileconfig: # logger.debug(u"Config-Dictionary: {}".format(self.config)) fileconfig.write(json.dumps(self.config)) # ---------------------------------------------------------------------------------------------------- # Oberflächenabflussparameter in QKan-Tabellen eintragen, ggfs. nur für ausgewählte Teilgebiete # 1. Formularfunktionen def dlgro_selectFile_qkanDB(self): """Datenbankverbindung zur QKan-Datenbank (SpatiLite) auswaehlen.""" filename = QFileDialog.getOpenFileName(self.dlgro, u"QKan-Datenbank auswählen", self.default_dir, "*.sqlite") # if os.path.dirname(filename) != '': # os.chdir(os.path.dirname(filename)) self.dlgro.tf_QKanDB.setText(filename) def dlgro_helpClick(self): """Reaktion auf Klick auf Help-Schaltfläche""" helpfile = os.path.join(self.plugin_dir, '../doc/sphinx/build/html/Qkan_Formulare.html#berechnung-von-oberflachenabflussparametern') webbrowser.open_new_tab(helpfile) def dlgro_lwTeilgebieteClick(self): """Reaktion auf Klick in Tabelle""" self.dlgro.cb_selTgbActive.setChecked(True) self.dlgro_countselection() def dlgro_lwAbflussparamsClick(self): """Reaktion auf Klick in Tabelle""" self.dlgro.cb_selParActive.setChecked(True) self.dlgro_countselection() def dlgro_selTgbActiveClick(self): """Reagiert auf Checkbox zur Aktivierung der Auswahl""" # Checkbox hat den Status nach dem Klick if self.dlgro.cb_selTgbActive.isChecked(): # Nix tun ... logger.debug('\nChecked = True') else: # Auswahl deaktivieren und Liste zurücksetzen anz = self.dlgro.lw_teilgebiete.count() for i in range(anz): item = self.dlgro.lw_teilgebiete.item(i) self.dlgro.lw_teilgebiete.setItemSelected(item, False) # Anzahl in der Anzeige aktualisieren self.dlgro_countselection() def dlgro_selParActiveClick(self): """Reagiert auf Checkbox zur Aktivierung der Auswahl""" # Checkbox hat den Status nach dem Klick if self.dlgro.cb_selParActive.isChecked(): # Nix tun ... logger.debug('\nChecked = True') else: # Auswahl deaktivieren und Liste zurücksetzen anz = self.dlgro.lw_abflussparameter.count() for i in range(anz): item = self.dlgro.lw_abflussparameter.item(i) self.dlgro.lw_abflussparameter.setItemSelected(item, False) # Anzahl in der Anzeige aktualisieren self.dlgro_countselection() def dlgro_countselection(self): """Zählt nach Änderung der Auswahlen in den Listen im Formular die Anzahl der betroffenen Flächen und Haltungen""" liste_teilgebiete = self.dlgro_listselecteditems(self.dlgro.lw_teilgebiete) liste_abflussparameter = self.dlgro_listselecteditems(self.dlgro.lw_abflussparameter) # Auswahl der zu bearbeitenden Flächen auswahl = sqlconditions('WHERE', ('teilgebiet', 'abflussparameter'), (liste_teilgebiete, liste_abflussparameter)) sql = u"""SELECT count(*) AS anzahl FROM flaechen{auswahl}""".format(auswahl=auswahl) if not self.dbQK.sql(sql, u"QKan_Tools.application.dlgro_countselection (1)"): return False daten = self.dbQK.fetchone() if not (daten is None): self.dlgro.lf_anzahl_flaechen.setText(str(daten[0])) else: self.dlgro.lf_anzahl_flaechen.setText('0') # ------------------------------------------------------------------------- # Funktion zur Zusammenstellung einer Auswahlliste für eine SQL-Abfrage def dlgro_listselecteditems(self, listWidget): """Erstellt eine Liste aus den in einem Auswahllisten-Widget angeklickten Objektnamen :param listWidget: String for translation. :type listWidget: QListWidgetItem :returns: Tuple containing selected teilgebiete :rtype: tuple """ items = listWidget.selectedItems() liste = [] for elem in items: liste.append(elem.text()) return liste def run_runoffparams(self): """Berechnen und Eintragen der Oberflächenabflussparameter in die Tabelle flaechen""" # Check, ob die relevanten Layer nicht editable sind. if len({'flaechen'} & get_editable_layers()) > 0: iface.messageBar().pushMessage(u"Bedienerfehler: ", u'Die zu verarbeitenden Layer dürfen nicht im Status "bearbeitbar" sein. Abbruch!', level=QgsMessageBar.CRITICAL) return False # Übernahme der Quelldatenbank: # Wenn ein Projekt geladen ist, wird die Quelldatenbank daraus übernommen. # Wenn dies nicht der Fall ist, wird die Quelldatenbank aus der # json-Datei übernommen. database_QKan = '' database_QKan, epsg = get_database_QKan() if not database_QKan: if 'database_QKan' in self.config: database_QKan = self.config['database_QKan'] else: database_QKan = '' self.dlgro.tf_QKanDB.setText(database_QKan) # Datenbankverbindung für Abfragen if database_QKan != '': self.dbQK = DBConnection(dbname=database_QKan) # Datenbankobjekt der QKan-Datenbank zum Lesen if self.dbQK is None: fehlermeldung("Fehler in tools.runoffparams", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format(database_QKan)) iface.messageBar().pushMessage("Fehler in tools.runoffparams", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format( \ database_QKan), level=QgsMessageBar.CRITICAL) return None # Check, ob alle Teilgebiete in Flächen auch in Tabelle "teilgebiete" enthalten sql = u"""INSERT INTO teilgebiete (tgnam) SELECT teilgebiet FROM flaechen WHERE teilgebiet IS NOT NULL AND teilgebiet NOT IN (SELECT tgnam FROM teilgebiete) GROUP BY teilgebiet""" if not self.dbQK.sql(sql, u"QKan_Tools.application.run (1) "): return False # Check, ob alle Abflussparameter in Flächen auch in Tabelle "abflussparameter" enthalten sql = u"""INSERT INTO abflussparameter (apnam) SELECT abflussparameter FROM flaechen WHERE abflussparameter IS NOT NULL AND abflussparameter NOT IN (SELECT apnam FROM abflussparameter) GROUP BY abflussparameter""" if not self.dbQK.sql(sql, u"QKan_Tools.application.run (2) "): return False self.dbQK.commit() # Anlegen der Tabelle zur Auswahl der Teilgebiete # Zunächst wird die Liste der beim letzten Mal gewählten Teilgebiete aus config gelesen liste_teilgebiete = [] if 'liste_teilgebiete' in self.config: liste_teilgebiete = self.config['liste_teilgebiete'] # Abfragen der Tabelle teilgebiete nach Teilgebieten sql = '''SELECT "tgnam" FROM "teilgebiete" GROUP BY "tgnam"''' if not self.dbQK.sql(sql, u"QKan_Tools.application.run (4) "): return False daten = self.dbQK.fetchall() self.dlgro.lw_teilgebiete.clear() for ielem, elem in enumerate(daten): self.dlgro.lw_teilgebiete.addItem(QListWidgetItem(elem[0])) try: if elem[0] in liste_teilgebiete: self.dlgro.lw_teilgebiete.setCurrentRow(ielem) except BaseException as err: fehlermeldung(u'QKan_Tools (6), Fehler in elem = {}\n'.format(elem), repr(err)) # if len(daten) == 1: # self.dlgro.lw_teilgebiete.setCurrentRow(0) # Anlegen der Tabelle zur Auswahl der Abflussparameter # Zunächst wird die Liste der beim letzten Mal gewählten Abflussparameter aus config gelesen liste_abflussparameter = [] if 'liste_abflussparameter' in self.config: liste_abflussparameter = self.config['liste_abflussparameter'] # Abfragen der Tabelle abflussparameter nach Abflussparametern sql = '''SELECT "apnam" FROM "abflussparameter" GROUP BY "apnam"''' if not self.dbQK.sql(sql, u"QKan_Tools.application.run (4) "): return False daten = self.dbQK.fetchall() self.dlgro.lw_abflussparameter.clear() for ielem, elem in enumerate(daten): self.dlgro.lw_abflussparameter.addItem(QListWidgetItem(elem[0])) try: if elem[0] in liste_abflussparameter: self.dlgro.lw_abflussparameter.setCurrentRow(ielem) except BaseException as err: fehlermeldung(u'QKan_Tools (6), Fehler in elem = {}\n'.format(elem), repr(err)) # if len(daten) == 1: # self.dlgro.lw_abflussparameter.setCurrentRow(0) self.dlgro_countselection() # Optionen zur Berechnung der befestigten Flächen if 'runoffparamstype_choice' in self.config: runoffparamstype_choice = self.config['runoffparamstype_choice'] else: runoffparamstype_choice = u'itwh' if runoffparamstype_choice == u'itwh': self.dlgro.rb_runoffparamsitwh.setChecked(True) elif runoffparamstype_choice == u'dyna': self.dlgro.rb_runoffparamsdyna.setChecked(True) if 'datenbanktyp' in self.config: datenbanktyp = self.config['datenbanktyp'] else: datenbanktyp = 'spatialite' # Formular anzeigen self.dlgro.show() # Run the dialog event loop result = self.dlgro.exec_() # See if OK was pressed if result: # Abrufen der ausgewählten Elemente in den Listen liste_teilgebiete = self.dlgro_listselecteditems(self.dlgro.lw_teilgebiete) liste_abflussparameter = self.dlgro_listselecteditems(self.dlgro.lw_abflussparameter) # Eingaben aus Formular übernehmen database_QKan = self.dlgro.tf_QKanDB.text() if self.dlgro.rb_runoffparamsitwh.isChecked(): runoffparamstype_choice = u'itwh' elif self.dlgro.rb_runoffparamsdyna.isChecked(): runoffparamstype_choice = u'dyna' else: fehlermeldung(u"tools.runoffparams.run_runoffparams", u"Fehlerhafte Option: \nrunoffparamstype_choice = {}".format(repr(runoffparamstype_choice))) # Konfigurationsdaten schreiben self.config['database_QKan'] = database_QKan self.config['liste_teilgebiete'] = liste_teilgebiete self.config['liste_abflussparameter'] = liste_abflussparameter self.config['runoffparamstype_choice'] = runoffparamstype_choice with open(self.configfil, 'w') as fileconfig: # logger.debug(u"Config-Dictionary: {}".format(self.config)) fileconfig.write(json.dumps(self.config)) setRunoffparams(self.dbQK, runoffparamstype_choice, liste_teilgebiete, liste_abflussparameter, datenbanktyp)
class LinkFl: """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join( self.plugin_dir, 'i18n', 'Flaechenzuordnungen_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlg_at = AssigntgebDialog() self.dlg_cl = CreatelineflDialog() self.dlg_sw = CreatelineswDialog() self.dlg_ul = UpdateLinksDialog() self.dlg_mg = ManagegroupsDialog() # Anfang Eigene Funktionen ------------------------------------------------- # (jh, 12.06.2017) logger.info(u'\n\nQKan_LinkFlaechen initialisiert...') # -------------------------------------------------------------------------- # Pfad zum Arbeitsverzeichnis sicherstellen wordir = os.path.join(site.getuserbase(), 'qkan') if not os.path.isdir(wordir): os.makedirs(wordir) # -------------------------------------------------------------------------------------------------- # Konfigurationsdatei qkan.json lesen # self.configfil = os.path.join(wordir, 'qkan.json') if os.path.exists(self.configfil): with open(self.configfil, 'r') as fileconfig: self.config = json.loads(fileconfig.read()) else: self.config = {'epsg': '25832'} # Projektionssystem self.config['autokorrektur'] = False self.config['suchradius'] = u'50' self.config['mindestflaeche'] = u'0.5' self.config['bezug_abstand'] = 'kante' with open(self.configfil, 'w') as fileconfig: fileconfig.write(json.dumps(self.config)) # Formularereignisse anbinden ---------------------------------------------- # Dialog dlg_cl self.dlg_cl.lw_flaechen_abflussparam.itemClicked.connect(self.cl_lw_flaechen_abflussparamClick) self.dlg_cl.lw_hal_entw.itemClicked.connect(self.cl_lw_hal_entwClick) self.dlg_cl.lw_teilgebiete.itemClicked.connect(self.cl_lw_teilgebieteClick) self.dlg_cl.cb_selFlActive.stateChanged.connect(self.cl_selFlActiveClick) self.dlg_cl.cb_selHalActive.stateChanged.connect(self.cl_selHalActiveClick) self.dlg_cl.cb_selTgbActive.stateChanged.connect(self.cl_selTgbActiveClick) self.dlg_cl.button_box.helpRequested.connect(self.cl_helpClick) # Dialog dlg_sw self.dlg_sw.lw_hal_entw.itemClicked.connect(self.sw_lw_hal_entwClick) self.dlg_sw.lw_teilgebiete.itemClicked.connect(self.sw_lw_teilgebieteClick) self.dlg_sw.cb_selHalActive.stateChanged.connect(self.sw_selHalActiveClick) self.dlg_sw.cb_selTgbActive.stateChanged.connect(self.sw_selTgbActiveClick) self.dlg_sw.button_box.helpRequested.connect(self.sw_helpClick) # Dialog dlg_at self.dlg_at.rb_within.clicked.connect(self.select_within) self.dlg_at.rb_overlaps.clicked.connect(self.select_overlaps) # Dialog dlg_mg self.dlg_mg.lw_gruppen.itemClicked.connect(self.listGroupAttr) self.dlg_mg.pb_storegroup.clicked.connect(self.storegrouptgb) self.dlg_mg.pb_reloadgroup.clicked.connect(self.reloadgrouptgb) # Ende Eigene Funktionen --------------------------------------------------- # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('Flaechenzuordnungen', message) def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_assigntgeb_path = ':/plugins/qkan/linkflaechen/res/icon_assigntgeb.png' Dummy.instance.add_action( icon_assigntgeb_path, text=self.tr(u'Alle Elemente des Entwässerungsnetzes zu Teilgebiet zuordnen'), callback=self.run_assigntgeb, parent=self.iface.mainWindow()) icon_createlinefl_path = ':/plugins/qkan/linkflaechen/res/icon_createlinefl.png' Dummy.instance.add_action( icon_createlinefl_path, text=self.tr(u'Erzeuge Verknüpfungslinien von Flaechen zu Haltungen'), callback=self.run_createlinefl, parent=self.iface.mainWindow()) icon_createlinesw_path = ':/plugins/qkan/linkflaechen/res/icon_createlinesw.png' Dummy.instance.add_action( icon_createlinesw_path, text=self.tr(u'Erzeuge Verknüpfungslinien von Direkteinleitungen zu Haltungen'), callback=self.run_createlinesw, parent=self.iface.mainWindow()) icon_updatelinks_path = ':/plugins/qkan/linkflaechen/res/icon_updatelinks.png' Dummy.instance.add_action( icon_updatelinks_path, text=self.tr(u'Verknüpfungen bereinigen'), callback=self.run_updatelinks, parent=self.iface.mainWindow()) icon_managegroups_path = ':/plugins/qkan/linkflaechen/res/icon_managegroups.png' Dummy.instance.add_action( icon_managegroups_path, text=self.tr(u'Teilgebietszuordnungen als Gruppen verwalten'), callback=self.run_managegroups, parent=self.iface.mainWindow()) def unload(self): pass # ------------------------------------------------------------------------- # Formularfunktionen linkfl def cl_helpClick(self): """Reaktion auf Klick auf Help-Schaltfläche""" helpfile = os.path.join(self.plugin_dir, '../doc/sphinx/build/html/Qkan_Formulare.html#automatisches-erzeugen-von-flachenanbindungen') webbrowser.open_new_tab(helpfile) def cl_lw_flaechen_abflussparamClick(self): """Reaktion auf Klick in Tabelle""" self.dlg_cl.cb_selFlActive.setChecked(True) self.countselectionfl() def cl_lw_hal_entwClick(self): """Reaktion auf Klick in Tabelle""" self.dlg_cl.cb_selHalActive.setChecked(True) self.countselectionfl() def cl_lw_teilgebieteClick(self): """Reaktion auf Klick in Tabelle""" self.dlg_cl.cb_selTgbActive.setChecked(True) self.countselectionfl() def cl_selFlActiveClick(self): """Reagiert auf Checkbox zur Aktivierung der Auswahl""" # Checkbox hat den Status nach dem Klick if self.dlg_cl.cb_selFlActive.isChecked(): # Nix tun ... pass else: # Auswahl deaktivieren und Liste zurücksetzen anz = self.dlg_cl.lw_flaechen_abflussparam.count() for i in range(anz): item = self.dlg_cl.lw_flaechen_abflussparam.item(i) self.dlg_cl.lw_flaechen_abflussparam.setItemSelected(item, False) # Anzahl in der Anzeige aktualisieren self.countselectionfl() def cl_selHalActiveClick(self): """Reagiert auf Checkbox zur Aktivierung der Auswahl""" # Checkbox hat den Status nach dem Klick if self.dlg_cl.cb_selHalActive.isChecked(): # Nix tun ... pass else: # Auswahl deaktivieren und Liste zurücksetzen anz = self.dlg_cl.lw_hal_entw.count() for i in range(anz): item = self.dlg_cl.lw_hal_entw.item(i) self.dlg_cl.lw_hal_entw.setItemSelected(item, False) # Anzahl in der Anzeige aktualisieren self.countselectionfl() def cl_selTgbActiveClick(self): """Reagiert auf Checkbox zur Aktivierung der Auswahl""" # Checkbox hat den Status nach dem Klick if self.dlg_cl.cb_selTgbActive.isChecked(): # Nix tun ... pass else: # Auswahl deaktivieren und Liste zurücksetzen anz = self.dlg_cl.lw_teilgebiete.count() for i in range(anz): item = self.dlg_cl.lw_teilgebiete.item(i) self.dlg_cl.lw_teilgebiete.setItemSelected(item, False) # Anzahl in der Anzeige aktualisieren self.countselectionfl() def countselectionfl(self): """Zählt nach Änderung der Auswahlen in den Listen im Formular die Anzahl der betroffenen Flächen und Haltungen""" liste_flaechen_abflussparam = self.listselecteditems(self.dlg_cl.lw_flaechen_abflussparam) liste_hal_entw = self.listselecteditems(self.dlg_cl.lw_hal_entw) liste_teilgebiete = self.listselecteditems(self.dlg_cl.lw_teilgebiete) # Aufbereiten für SQL-Abfrage # Zu berücksichtigende ganze Flächen zählen if len(liste_flaechen_abflussparam) == 0: # Keine Auswahl. Soll eigentlich nicht vorkommen, funktioniert aber... auswahl = u'' logger.debug(u'liste_flaechen_abflussparam:\n{}'.format(liste_flaechen_abflussparam)) else: auswahl = u" AND flaechen.abflussparameter in ('{}')".format(u"', '".join(liste_flaechen_abflussparam)) if len(liste_teilgebiete) != 0: auswahl += u" and flaechen.teilgebiet in ('{}')".format(u"', '".join(liste_teilgebiete)) sql = u"""SELECT count(*) AS anzahl FROM flaechen WHERE (aufteilen <> 'ja' OR aufteilen IS NULL){auswahl}""".format(auswahl=auswahl) if not self.dbQK.sql(sql, u"QKan_LinkFlaechen.countselectionfl (1)"): return False daten = self.dbQK.fetchone() if not (daten is None): self.dlg_cl.lf_anzahl_flaechen.setText(str(daten[0])) else: self.dlg_cl.lf_anzahl_flaechen.setText(u'0') # Zu berücksichtigende zu verschneidende Flächen zählen sql = u"""SELECT count(*) AS anzahl FROM flaechen WHERE aufteilen = 'ja'{auswahl}""".format(auswahl=auswahl) logger.debug(u'sql Flaechen zu verschneiden:\n{}'.format(sql)) if not self.dbQK.sql(sql, u"QKan_LinkFlaechen.countselectionfl (2)"): return False daten = self.dbQK.fetchone() if not (daten is None): self.dlg_cl.lf_anzahl_flaechsec.setText(str(daten[0])) else: self.dlg_cl.lf_anzahl_flaechsec.setText(u'0') # Zu berücksichtigende Haltungen zählen if len(liste_hal_entw) == 0: auswahl = u'' else: auswahl = u" WHERE haltungen.entwart in ('{}')".format(u"', '".join(liste_hal_entw)) if len(liste_teilgebiete) != 0: if auswahl == u'': auswahl = u" WHERE haltungen.teilgebiet in ('{}')".format(u"', '".join(liste_teilgebiete)) else: auswahl += u" and haltungen.teilgebiet in ('{}')".format(u"', '".join(liste_teilgebiete)) sql = u"""SELECT count(*) AS anzahl FROM haltungen{auswahl}""".format(auswahl=auswahl) if not self.dbQK.sql(sql, u"QKan_LinkFlaechen.countselectionfl (3)"): return False daten = self.dbQK.fetchone() if not (daten is None): self.dlg_cl.lf_anzahl_haltungen.setText(str(daten[0])) else: self.dlg_cl.lf_anzahl_haltungen.setText(u'0') # ------------------------------------------------------------------------- # Formularfunktionen linksw def sw_helpClick(self): """Reaktion auf Klick auf Help-Schaltfläche""" helpfile = os.path.join(self.plugin_dir, '../doc/sphinx/build/html/Qkan_Formulare.html#automatisches-erzeugen-von-anbindungen-von-einzeleinleitern') webbrowser.open_new_tab(helpfile) def sw_lw_hal_entwClick(self): """Reaktion auf Klick in Tabelle""" self.dlg_sw.cb_selHalActive.setChecked(True) self.countselectionsw() def sw_lw_teilgebieteClick(self): """Reaktion auf Klick in Tabelle""" self.dlg_sw.cb_selTgbActive.setChecked(True) self.countselectionsw() def sw_selHalActiveClick(self): """Reagiert auf Checkbox zur Aktivierung der Auswahl""" # Checkbox hat den Status nach dem Klick if self.dlg_sw.cb_selHalActive.isChecked(): # Nix tun ... pass else: # Auswahl deaktivieren und Liste zurücksetzen anz = self.dlg_sw.lw_hal_entw.count() for i in range(anz): item = self.dlg_sw.lw_hal_entw.item(i) self.dlg_sw.lw_hal_entw.setItemSelected(item, False) # Anzahl in der Anzeige aktualisieren self.countselectionsw() def sw_selTgbActiveClick(self): """Reagiert auf Checkbox zur Aktivierung der Auswahl""" # Checkbox hat den Status nach dem Klick if self.dlg_sw.cb_selTgbActive.isChecked(): # Nix tun ... pass else: # Auswahl deaktivieren und Liste zurücksetzen anz = self.dlg_sw.lw_teilgebiete.count() for i in range(anz): item = self.dlg_sw.lw_teilgebiete.item(i) self.dlg_sw.lw_teilgebiete.setItemSelected(item, False) # Anzahl in der Anzeige aktualisieren self.countselectionsw() def countselectionsw(self): """Zählt nach Änderung der Auswahlen in den Listen im Formular die Anzahl der betroffenen Haltungen""" liste_hal_entw = self.listselecteditems(self.dlg_sw.lw_hal_entw) liste_teilgebiete = self.listselecteditems(self.dlg_sw.lw_teilgebiete) # Aufbereiten für SQL-Abfrage # Zu berücksichtigende Haltungen zählen if len(liste_hal_entw) == 0: auswahl = u'' else: auswahl = u" WHERE haltungen.entwart in ('{}')".format(u"', '".join(liste_hal_entw)) if len(liste_teilgebiete) != 0: if auswahl == u'': auswahl = u" WHERE haltungen.teilgebiet in ('{}')".format(u"', '".join(liste_teilgebiete)) else: auswahl += u" and haltungen.teilgebiet in ('{}')".format(u"', '".join(liste_teilgebiete)) sql = u"""SELECT count(*) AS anzahl FROM haltungen{auswahl}""".format(auswahl=auswahl) if not self.dbQK.sql(sql, u"QKan_LinkFlaechen.countselectionsw (1)"): return False daten = self.dbQK.fetchone() if not (daten is None): self.dlg_sw.lf_anzahl_haltungen.setText(str(daten[0])) else: self.dlg_sw.lf_anzahl_haltungen.setText(u'0') # Zu berücksichtigende Direkteinleitungen zählen if len(liste_teilgebiete) != 0: auswahl = u" WHERE einleit.teilgebiet in ('{}')".format(u"', '".join(liste_teilgebiete)) else: auswahl = u'' sql = u"""SELECT count(*) AS anzahl FROM einleit{auswahl}""".format(auswahl=auswahl) if not self.dbQK.sql(sql, u"QKan_LinkFlaechen.countselectionsw (2)"): return False daten = self.dbQK.fetchone() if not (daten is None): self.dlg_sw.lf_anzahl_einleit.setText(str(daten[0])) else: self.dlg_sw.lf_anzahl_einleit.setText(u'0') # ------------------------------------------------------------------------- # Funktion zur Zusammenstellung einer Auswahlliste für eine SQL-Abfrage def listselecteditems(self, listWidget): """Erstellt eine Liste aus den in einem Auswahllisten-Widget angeklickten Objektnamen :param listWidget: String for translation. :type listWidget: QListWidgetItem :returns: Tuple containing selected teilgebiete :rtype: tuple """ items = listWidget.selectedItems() liste = [] for elem in items: liste.append(elem.text()) return liste # ---------------------------------------------------------------------------- # Funktion zum Auflisten der Gruppen def showgroups(self): """Abfragen der Tabelle gruppen nach verwendeten vorhandenen Gruppen""" sql = u"""SELECT grnam FROM gruppen GROUP BY grnam""" if not self.dbQK.sql(sql, u"QKan_LinkFlaechen.showgroups (1)"): return False daten = self.dbQK.fetchall() self.dlg_mg.lw_gruppen.clear() for ielem, elem in enumerate(daten): if elem[0] is not None: self.dlg_mg.lw_gruppen.addItem(QListWidgetItem(elem[0])) # ---------------------------------------------------------------------------- # Funktion zum Abfragen der zugeordneten Teilgebiete, betroffenen Tabellen und # Anzahl für eine ausgewählte Gruppe def listGroupAttr(self): # Angeklickte Gruppe aus QListWidget gr = self.listselecteditems(self.dlg_mg.lw_gruppen) if len(gr) > 0: self.gruppe = self.listselecteditems(self.dlg_mg.lw_gruppen)[0] # Im Formular gesetzt: selectionMode = SingleSelection sql = u""" SELECT teilgebiet, tabelle, printf('%i',count(*)) AS Anzahl FROM gruppen WHERE grnam = '{gruppe}' GROUP BY tabelle, teilgebiet ORDER BY tabelle, teilgebiet """.format(gruppe=self.gruppe) if not self.dbQK.sql(sql, u"QKan_LinkFlaechen.listGroupAttr (1)"): return False daten = self.dbQK.fetchall() logger.debug(u'\ndaten: {}'.format(str(daten))) # debug nzeilen = len(daten) self.dlg_mg.tw_gruppenattr.setRowCount(nzeilen) # self.dlg_mg.tw_gruppenattr.setHorizontalHeaderLabels([u"Teilgebiet", u"Tabelle", u"Anzahl"]) self.dlg_mg.tw_gruppenattr.setColumnWidth(0, 174) # 17 Pixel für Rand und Nummernspalte (und je Spalte?) self.dlg_mg.tw_gruppenattr.setColumnWidth(1, 80) self.dlg_mg.tw_gruppenattr.setColumnWidth(2, 50) for i, elem in enumerate(daten): for j, item in enumerate(elem): self.dlg_mg.tw_gruppenattr.setItem(i, j, QTableWidgetItem(elem[j])) self.dlg_mg.tw_gruppenattr.setRowHeight(i, 20) def reloadgrouptgb(self): reloadgroup(self.dbQK, self.gruppe, dbtyp = u'SpatiaLite') iface.messageBar().pushMessage(u"Fertig!", u'Teilgebiete wurden geladen!', level=QgsMessageBar.INFO) def storegrouptgb(self): neuegruppe = self.dlg_mg.tf_newgroup.text() if neuegruppe != u'' and neuegruppe is not None: kommentar = self.dlg_mg.tf_kommentar.toPlainText() if kommentar is None: kommentar = u'' storegroup(self.dbQK, neuegruppe, kommentar, dbtyp = u'SpatiaLite') self.showgroups() iface.messageBar().pushMessage(u"Fertig!", u'Teilgebiete wurden gespeichert', level=QgsMessageBar.INFO) # ------------------------------------------------------------------------- # Öffnen des Formulars zur Erstellung der Verknüpfungen def run_createlinefl(self): """Run method that performs all the real work""" # Check, ob die relevanten Layer nicht editable sind. if len({u'flaechen', u'haltungen', u'linkfl'} & get_editable_layers()) > 0: iface.messageBar().pushMessage(u"Bedienerfehler: ", u'Die zu verarbeitenden Layer dürfen nicht im Status "bearbeitbar" sein. Abbruch!', level=QgsMessageBar.CRITICAL) return False database_QKan = u'' database_QKan, epsg = get_database_QKan() if not database_QKan: fehlermeldung(u"Fehler in k_link", u"database_QKan konnte nicht aus den Layern ermittelt werden. Abbruch!") logger.error(u"k_link: database_QKan konnte nicht aus den Layern ermittelt werden. Abbruch!") return False # Datenbankverbindung für Abfragen self.dbQK = DBConnection(dbname=database_QKan) # Datenbankobjekt der QKan-Datenbank zum Lesen if self.dbQK is None: fehlermeldung(u"Fehler in LinkFl.run_createlinefl", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format(database_QKan)) iface.messageBar().pushMessage(u"Fehler in LinkFl.run_createlinefl", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format( \ database_QKan), level=QgsMessageBar.CRITICAL) return None # Check, ob alle Teilgebiete in Flächen und Haltungen auch in Tabelle "teilgebiete" enthalten sql = u"""INSERT INTO teilgebiete (tgnam) SELECT teilgebiet FROM flaechen WHERE teilgebiet IS NOT NULL AND teilgebiet <> '' AND teilgebiet NOT IN (SELECT tgnam FROM teilgebiete) GROUP BY teilgebiet""" if not self.dbQK.sql(sql, u"QKan_LinkFlaechen (1)"): return False sql = u"""INSERT INTO teilgebiete (tgnam) SELECT teilgebiet FROM haltungen WHERE teilgebiet IS NOT NULL AND teilgebiet <> '' AND teilgebiet NOT IN (SELECT tgnam FROM teilgebiete) GROUP BY teilgebiet""" if not self.dbQK.sql(sql, u"QKan_LinkFlaechen (1)"): return False self.dbQK.commit() # Abfragen der Tabelle flaechen nach verwendeten Abflussparametern sql = u'SELECT abflussparameter FROM flaechen GROUP BY abflussparameter' if not self.dbQK.sql(sql, u"QKan_LinkFlaechen.run_createlinefl (1)"): return False daten = self.dbQK.fetchall() # logger.debug(u'\ndaten: {}'.format(str(daten))) # debug self.dlg_cl.lw_flaechen_abflussparam.clear() for ielem, elem in enumerate(daten): if elem[0] is not None: self.dlg_cl.lw_flaechen_abflussparam.addItem(QListWidgetItem(elem[0])) if 'liste_flaechen_abflussparam' in self.config: try: if elem[0] in self.config['liste_flaechen_abflussparam']: self.dlg_cl.lw_flaechen_abflussparam.setCurrentRow(ielem) self.dlg_cl.cb_selFlActive.setChecked(True) # Auswahlcheckbox aktivieren except BaseException as err: del self.dbQK # logger.debug(u'\nelem: {}'.format(str(elem))) # debug # if len(daten) == 1: # self.dlg_cl.lw_flaechen_abflussparam.setCurrentRow(0) # Abfragen der Tabelle haltungen nach vorhandenen Entwässerungsarten sql = u'SELECT "entwart" FROM "haltungen" GROUP BY "entwart"' if not self.dbQK.sql(sql, u"QKan_LinkFlaechen.run_createlinefl (2)"): return False daten = self.dbQK.fetchall() self.dlg_cl.lw_hal_entw.clear() for ielem, elem in enumerate(daten): if elem[0] is not None: self.dlg_cl.lw_hal_entw.addItem(QListWidgetItem(elem[0])) if 'liste_hal_entw' in self.config: if elem[0] in self.config['liste_hal_entw']: self.dlg_cl.lw_hal_entw.setCurrentRow(ielem) self.dlg_cl.cb_selHalActive.setChecked(True) # Auswahlcheckbox aktivieren # if len(daten) == 1: # self.dlg_cl.lw_hal_entw.setCurrentRow(0) # Abfragen der Tabelle teilgebiete nach Teilgebieten sql = u'SELECT "tgnam" FROM "teilgebiete" GROUP BY "tgnam"' if not self.dbQK.sql(sql, u"QKan_LinkFlaechen.run_createlinefl (3)"): return False daten = self.dbQK.fetchall() self.dlg_cl.lw_teilgebiete.clear() for ielem, elem in enumerate(daten): if elem[0] is not None: self.dlg_cl.lw_teilgebiete.addItem(QListWidgetItem(elem[0])) if 'liste_teilgebiete' in self.config: if elem[0] in self.config['liste_teilgebiete']: self.dlg_cl.lw_teilgebiete.setCurrentRow(ielem) self.dlg_cl.cb_selTgbActive.setChecked(True) # Auswahlcheckbox aktivieren # if len(daten) == 1: # self.dlg_cl.lw_teilgebiete.setCurrentRow(0) # config in Dialog übernehmen # Autokorrektur if 'autokorrektur' in self.config: autokorrektur = self.config['autokorrektur'] else: autokorrektur = True self.dlg_cl.cb_autokorrektur.setChecked(autokorrektur) # Verbindungslinien nur innerhalb tezg if 'linksw_in_tezg' in self.config: linksw_in_tezg = self.config['linksw_in_tezg'] else: linksw_in_tezg = True self.dlg_cl.cb_linkswInTezg.setChecked(linksw_in_tezg) # Suchradius if 'suchradius' in self.config: suchradius = self.config['suchradius'] else: suchradius = u'50' self.dlg_cl.tf_suchradius.setText(str(suchradius)) # Mindestflächengröße if 'mindestflaeche' in self.config: mindestflaeche = self.config['mindestflaeche'] else: mindestflaeche = u'0.5' # Fangradius für Anfang der Anbindungslinie # Kann über Menü "Optionen" eingegeben werden if 'fangradius' in self.config: fangradius = self.config['fangradius'] else: fangradius = u'0.1' # Festlegung, ob sich der Abstand auf die Flächenkante oder deren Mittelpunkt bezieht if 'bezug_abstand' in self.config: bezug_abstand = self.config['bezug_abstand'] else: bezug_abstand = 'kante' if bezug_abstand == 'kante': self.dlg_cl.rb_abstandkante.setChecked(True) elif bezug_abstand == 'mittelpunkt': self.dlg_cl.rb_abstandmittelpunkt.setChecked(True) else: fehlermeldung(u"Fehler im Programmcode", u"Nicht definierte Option") return False self.countselectionfl() # show the dialog self.dlg_cl.show() # Run the dialog event loop result = self.dlg_cl.exec_() # See if OK was pressed if result: # Do something useful here - delete the line containing pass and # substitute with your code. # pass # Start der Verarbeitung # Abrufen der ausgewählten Elemente in beiden Listen liste_flaechen_abflussparam = self.listselecteditems(self.dlg_cl.lw_flaechen_abflussparam) liste_hal_entw = self.listselecteditems(self.dlg_cl.lw_hal_entw) liste_teilgebiete = self.listselecteditems(self.dlg_cl.lw_teilgebiete) suchradius = self.dlg_cl.tf_suchradius.text() if self.dlg_cl.rb_abstandkante.isChecked(): bezug_abstand = 'kante' elif self.dlg_cl.rb_abstandmittelpunkt.isChecked(): bezug_abstand = 'mittelpunkt' else: fehlermeldung(u"Fehler im Programmcode", u"Nicht definierte Option") return False autokorrektur = self.dlg_cl.cb_autokorrektur.isChecked() linksw_in_tezg = self.dlg_cl.cb_linkswInTezg.isChecked() # if len(liste_flaechen_abflussparam) == 0 or len(liste_hal_entw) == 0: # iface.messageBar().pushMessage(u"Bedienerfehler: ", # u'Bitte in beiden Tabellen mindestens ein Element auswählen!', # level=QgsMessageBar.CRITICAL) # self.run_createlinefl() # Konfigurationsdaten schreiben self.config['suchradius'] = suchradius self.config['fangradius'] = fangradius self.config['mindestflaeche'] = mindestflaeche self.config['bezug_abstand'] = bezug_abstand self.config['liste_hal_entw'] = liste_hal_entw self.config['liste_flaechen_abflussparam'] = liste_flaechen_abflussparam self.config['liste_teilgebiete'] = liste_teilgebiete self.config['epsg'] = epsg self.config['autokorrektur'] = autokorrektur self.config['linksw_in_tezg'] = linksw_in_tezg with open(self.configfil, 'w') as fileconfig: fileconfig.write(json.dumps(self.config)) # Start der Verarbeitung createlinkfl(self.dbQK, liste_flaechen_abflussparam, liste_hal_entw, liste_teilgebiete, linksw_in_tezg, autokorrektur, suchradius, mindestflaeche, fangradius, bezug_abstand, epsg) # Einfügen der Verbindungslinien in die Layerliste, wenn nicht schon geladen layers = iface.legendInterface().layers() if u'Anbindungen Flächen' not in [lay.name() for lay in layers]: # layers wurde oben erstellt uri = QgsDataSourceURI() uri.setDatabase(database_QKan) uri.setDataSource(u'', u'linkfl', u'glink') vlayer = QgsVectorLayer(uri.uri(), u'Anbindungen Flächen', u'spatialite') QgsMapLayerRegistry.instance().addMapLayer(vlayer) # -------------------------------------------------------------------------- # Datenbankverbindungen schliessen del self.dbQK # ------------------------------------------------------------------------- # Öffnen des Formulars zur Erstellung der Verknüpfungen def run_createlinesw(self): """Run method that performs all the real work""" # Check, ob die relevanten Layer nicht editable sind. if len({u'einleit', u'haltungen', u'linksw'} & get_editable_layers()) > 0: iface.messageBar().pushMessage(u"Bedienerfehler: ", u'Die zu verarbeitenden Layer dürfen nicht im Status "bearbeitbar" sein. Abbruch!', level=QgsMessageBar.CRITICAL) return False database_QKan = u'' database_QKan, epsg = get_database_QKan() if not database_QKan: fehlermeldung(u"Fehler in LinkFl.run_createlinesw", u"database_QKan konnte nicht aus den Layern ermittelt werden. Abbruch!") logger.error(u"LinkFl.run_createlinesw: database_QKan konnte nicht aus den Layern ermittelt werden. Abbruch!") return False # Datenbankverbindung für Abfragen self.dbQK = DBConnection(dbname=database_QKan) # Datenbankobjekt der QKan-Datenbank zum Lesen if self.dbQK is None: fehlermeldung(u"Fehler in LinkFl.run_createlinesw", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format(database_QKan)) iface.messageBar().pushMessage(u"Fehler in LinkFl.run_createlinesw", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format( \ database_QKan), level=QgsMessageBar.CRITICAL) return None # Check, ob alle Teilgebiete in Flächen und Haltungen auch in Tabelle "teilgebiete" enthalten sql = u"""INSERT INTO teilgebiete (tgnam) SELECT teilgebiet FROM einleit WHERE teilgebiet IS NOT NULL AND teilgebiet <> '' AND teilgebiet NOT IN (SELECT tgnam FROM teilgebiete) GROUP BY teilgebiet""" if not self.dbQK.sql(sql, u"LinkFl.run_createlinesw (1)"): return False sql = u"""INSERT INTO teilgebiete (tgnam) SELECT teilgebiet FROM haltungen WHERE teilgebiet IS NOT NULL AND teilgebiet <> '' AND teilgebiet NOT IN (SELECT tgnam FROM teilgebiete) GROUP BY teilgebiet""" if not self.dbQK.sql(sql, u"LinkFl.run_createlinesw (2)"): return False self.dbQK.commit() # Abfragen der Tabelle haltungen nach vorhandenen Entwässerungsarten sql = u'SELECT "entwart" FROM "haltungen" GROUP BY "entwart"' if not self.dbQK.sql(sql, u"QKan_LinkFlaechen.run_createlinesw (1)"): return False daten = self.dbQK.fetchall() self.dlg_sw.lw_hal_entw.clear() for ielem, elem in enumerate(daten): if elem[0] is not None: self.dlg_sw.lw_hal_entw.addItem(QListWidgetItem(elem[0])) if 'liste_hal_entw' in self.config: if elem[0] in self.config['liste_hal_entw']: self.dlg_sw.lw_hal_entw.setCurrentRow(ielem) self.dlg_sw.cb_selHalActive.setChecked(True) # Auswahlcheckbox aktivieren # if len(daten) == 1: # self.dlg_sw.lw_hal_entw.setCurrentRow(0) # Abfragen der Tabelle teilgebiete nach Teilgebieten sql = u'SELECT "tgnam" FROM "teilgebiete" GROUP BY "tgnam"' if not self.dbQK.sql(sql, u"QKan_LinkFlaechen.run_createlinesw (2)"): return False daten = self.dbQK.fetchall() self.dlg_sw.lw_teilgebiete.clear() for ielem, elem in enumerate(daten): if elem[0] is not None: self.dlg_sw.lw_teilgebiete.addItem(QListWidgetItem(elem[0])) if 'liste_teilgebiete' in self.config: if elem[0] in self.config['liste_teilgebiete']: self.dlg_sw.lw_teilgebiete.setCurrentRow(ielem) self.dlg_sw.cb_selTgbActive.setChecked(True) # Auswahlcheckbox aktivieren # if len(daten) == 1: # self.dlg_sw.lw_teilgebiete.setCurrentRow(0) # config in Dialog übernehmen # Suchradius if 'suchradius' in self.config: suchradius = self.config['suchradius'] else: suchradius = u'50' self.dlg_sw.tf_suchradius.setText(str(suchradius)) # Haltungen direkt in einleit eintragen. Es kann wegen der längeren Zeitdauer sinnvoll # sein, dies erst am Schluss der Bearbeitung in einem eigenen Vorgang zu machen. self.countselectionsw() # show the dialog self.dlg_sw.show() # Run the dialog event loop result = self.dlg_sw.exec_() # See if OK was pressed if result: # Do something useful here - delete the line containing pass and # substitute with your code. # pass # Start der Verarbeitung # Inhalte aus Formular lesen suchradius = self.dlg_sw.tf_suchradius.text() # Abrufen der ausgewählten Elemente in beiden Listen liste_hal_entw = self.listselecteditems(self.dlg_sw.lw_hal_entw) liste_teilgebiete = self.listselecteditems(self.dlg_sw.lw_teilgebiete) # Konfigurationsdaten schreiben self.config['suchradius'] = suchradius self.config['liste_hal_entw'] = liste_hal_entw self.config['liste_teilgebiete'] = liste_teilgebiete self.config['epsg'] = epsg with open(self.configfil, 'w') as fileconfig: fileconfig.write(json.dumps(self.config)) # Start der Verarbeitung createlinksw(self.dbQK, liste_teilgebiete, suchradius, epsg) # Einfügen der Verbindungslinien in die Layerliste, wenn nicht schon geladen layers = iface.legendInterface().layers() if u'Anbindungen Direkteinleitungen' not in [lay.name() for lay in layers]: # layers wurde oben erstellt uri = QgsDataSourceURI() uri.setDatabase(database_QKan) uri.setDataSource(u'', u'linksw', u'glink') vlayer = QgsVectorLayer(uri.uri(), u'Anbindungen Direkteinleitungen', u'spatialite') QgsMapLayerRegistry.instance().addMapLayer(vlayer) # -------------------------------------------------------------------------- # Datenbankverbindungen schliessen del self.dbQK # Zuordnen der Haltungs- etc. -objekte zu (ausgewählten) Teilgebieten # Hilfsfunktionen def enable_bufferradius(self, onoff=True): """Aktiviert/Deaktiviert die Eingabe der Pufferbreite abhängig von der Auswahloption""" self.dlg_at.lb_bufferradius.setEnabled(onoff) self.dlg_at.tf_bufferradius.setEnabled(onoff) self.dlg_at.unit_bufferradius.setEnabled(onoff) def select_within(self): """Aktiviert die Eingabe der Pufferbreite""" self.enable_bufferradius(True) def select_overlaps(self): """Deaktiviert die Eingabe der Pufferbreite""" self.enable_bufferradius(False) # ------------------------------------------------------------------------- # Öffnen des Formulars def run_assigntgeb(self): """Öffnen des Formulars zur Zuordnung von Teilgebieten auf Haltungen und Flächen""" # Check, ob die relevanten Layer nicht editable sind. if len({u'flaechen', u'haltungen', u'linkfl', u'linksw', u'tezg', u'einleit'} & get_editable_layers()) > 0: iface.messageBar().pushMessage(u"Bedienerfehler: ", u'Die zu verarbeitenden Layer dürfen nicht im Status "bearbeitbar" sein. Abbruch!', level=QgsMessageBar.CRITICAL) return False database_QKan = u'' database_QKan, epsg = get_database_QKan() if not database_QKan: fehlermeldung(u"Fehler in k_link", u"database_QKan konnte nicht aus den Layern ermittelt werden. Abbruch!") logger.error(u"k_link: database_QKan konnte nicht aus den Layern ermittelt werden. Abbruch!") return False # Datenbankverbindung für Abfragen self.dbQK = DBConnection(dbname=database_QKan) # Datenbankobjekt der QKan-Datenbank zum Lesen if self.dbQK is None: fehlermeldung(u"Fehler in LinkFl.run_assigntgeb", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format(database_QKan)) iface.messageBar().pushMessage(u"Fehler in LinkFl.run_assigntgeb", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format( \ database_QKan), level=QgsMessageBar.CRITICAL) return None # config in Dialog übernehmen # Autokorrektur if 'autokorrektur' in self.config: autokorrektur = self.config['autokorrektur'] else: autokorrektur = True self.dlg_at.cb_autokorrektur.setChecked(autokorrektur) # Abfragen der Tabelle teilgebiete nach Teilgebieten sql = u'SELECT "tgnam" FROM "teilgebiete" GROUP BY "tgnam"' if not self.dbQK.sql(sql, u"QKan_LinkFlaechen.run_assigntgeb (1)"): return False daten = self.dbQK.fetchall() self.dlg_at.lw_teilgebiete.clear() for ielem, elem in enumerate(daten): if elem[0] is not None: self.dlg_at.lw_teilgebiete.addItem(QListWidgetItem(elem[0])) if 'liste_teilgebiete' in self.config: if elem[0] in self.config['liste_teilgebiete']: self.dlg_at.lw_teilgebiete.setCurrentRow(ielem) # Festlegung, ob die Auswahl nur Objekte innerhalb oder aller überlappenden berücksichtigt if 'auswahltyp' in self.config: auswahltyp = self.config['auswahltyp'] else: auswahltyp = u'within' if auswahltyp == u'within': self.dlg_at.rb_within.setChecked(True) self.enable_bufferradius(True) elif auswahltyp == u'overlaps': self.dlg_at.rb_overlaps.setChecked(True) self.enable_bufferradius(False) else: fehlermeldung(u"Fehler im Programmcode (3)", u"Nicht definierte Option") return False # Festlegung des Pufferradius if 'bufferradius' in self.config: bufferradius = self.config['bufferradius'] else: bufferradius = u'0' self.dlg_at.tf_bufferradius.setText(bufferradius) # show the dialog self.dlg_at.show() # Run the dialog event loop result = self.dlg_at.exec_() # See if OK was pressed if result: # Inhalte aus Formular lesen liste_teilgebiete = self.listselecteditems(self.dlg_at.lw_teilgebiete) if self.dlg_at.rb_within.isChecked(): auswahltyp = u'within' elif self.dlg_at.rb_overlaps.isChecked(): auswahltyp = u'overlaps' else: fehlermeldung(u"Fehler im Programmcode (4)", u"Nicht definierte Option") return False autokorrektur = self.dlg_at.cb_autokorrektur.isChecked() bufferradius = self.dlg_at.tf_bufferradius.text() # config schreiben self.config['liste_teilgebiete'] = liste_teilgebiete self.config['auswahltyp'] = auswahltyp self.config['epsg'] = epsg self.config['bufferradius'] = bufferradius self.config['autokorrektur'] = autokorrektur with open(self.configfil, 'w') as fileconfig: fileconfig.write(json.dumps(self.config)) # Start der Verarbeitung assigntgeb(self.dbQK, auswahltyp, liste_teilgebiete, [u'haltungen', u'flaechen', u'schaechte', u'einleit', u'tezg', u'linksw', u'linkfl'], autokorrektur, bufferradius) # -------------------------------------------------------------------------- # Datenbankverbindungen schliessen del self.dbQK # ---------------------------------------------------------------------------------------------- # Laden und Speichern von Teilgebietszuordnungen als Gruppe def run_managegroups(self): """Speichern und Wiederherstellen von Teilgebietszuordnungen als Gruppe""" # Check, ob die relevanten Layer nicht editable sind. if len({u'flaechen', u'haltungen', u'schaechte', u'linksw', u'einleit', u'linkfl', u'teilgebiete', u'tezg'} & get_editable_layers()) > 0: iface.messageBar().pushMessage(u"Bedienerfehler: ", u'Die zu verarbeitenden Layer dürfen nicht im Status "bearbeitbar" sein. Abbruch!', level=QgsMessageBar.CRITICAL) return False database_QKan = u'' database_QKan, epsg = get_database_QKan() if not database_QKan: fehlermeldung(u"Fehler in LinkFl.run_managegroups", u"database_QKan konnte nicht aus den Layern ermittelt werden. Abbruch!") logger.error(u"CreateUnbefFl: database_QKan konnte nicht aus den Layern ermittelt werden. Abbruch!") return False self.dbQK = DBConnection(dbname=database_QKan) # Datenbankobjekt der QKan-Datenbank zum Lesen if self.dbQK is None: fehlermeldung(u"Fehler in LinkFl.run_managegroups", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format(database_QKan)) iface.messageBar().pushMessage(u"Fehler in LinkFl.run_managegroups", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format( \ database_QKan), level=QgsMessageBar.CRITICAL) return None self.showgroups() self.dlg_mg.lw_gruppen.setCurrentRow(0) # Anzeige initialisieren self.listGroupAttr() # show the dialog self.dlg_mg.show() # Run the dialog event loop result = self.dlg_mg.exec_() # See if OK was pressed if result: # Do something useful here - delete the line containing pass and # substitute with your code. pass # Start der Verarbeitung # Nur Formular schließen # ---------------------------------------------------------------------------------------------- # Datenbankverbindungen schliessen del self.dbQK # ---------------------------------------------------------------------------------------------- # Logischen Cache der Verknüpfungen aktualisieren def run_updatelinks(self): '''Aktualisieren des logischen Verknüpfungscaches in linkfl und linksw''' # Check, ob die relevanten Layer nicht editable sind. if len({u'flaechen', u'haltungen', u'linkfl', u'linksw', u'tezg', u'einleit'} & get_editable_layers()) > 0: iface.messageBar().pushMessage(u"Bedienerfehler: ", u'Die zu verarbeitenden Layer dürfen nicht im Status "bearbeitbar" sein. Abbruch!', level=QgsMessageBar.CRITICAL) return False database_QKan = u'' database_QKan, epsg = get_database_QKan() if not database_QKan: fehlermeldung(u"Fehler in k_link", u"database_QKan konnte nicht aus den Layern ermittelt werden. Abbruch!") logger.error(u"k_link: database_QKan konnte nicht aus den Layern ermittelt werden. Abbruch!") return False # Datenbankverbindung für Abfragen self.dbQK = DBConnection(dbname=database_QKan) # Datenbankobjekt der QKan-Datenbank zum Lesen if self.dbQK is None: fehlermeldung(u"Fehler in LinkFl.run_assigntgeb", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format(database_QKan)) iface.messageBar().pushMessage(u"Fehler in LinkFl.run_assigntgeb", u'QKan-Datenbank {:s} wurde nicht gefunden!\nAbbruch!'.format( \ database_QKan), level=QgsMessageBar.CRITICAL) return False self.dlg_ul.tf_qkDB.setText(database_QKan) # Festlegung des Fangradius # Kann über Menü "Optionen" eingegeben werden if 'fangradius' in self.config: fangradius = self.config['fangradius'] else: fangradius = u'0.1' # Löschen von Flächenverknüpfungen ohne Linienobjekt if 'deletelinkflGeomNone' in self.config: deletelinkflGeomNone = self.config['deletelinkflGeomNone'] else: deletelinkflGeomNone = True self.dlg_ul.cb_deleteGeomNone.setChecked(deletelinkflGeomNone) # show the dialog self.dlg_ul.show() # Run the dialog event loop result = self.dlg_ul.exec_() # See if OK was pressed if result: # Inhalte aus Formular lesen deletelinkflGeomNone = self.dlg_ul.cb_deleteGeomNone.isChecked() # config schreiben self.config['deletelinkflGeomNone'] = deletelinkflGeomNone self.config['fangradius'] = fangradius with open(self.configfil, 'w') as fileconfig: fileconfig.write(json.dumps(self.config)) # Start der Verarbeitung if self.dlg_ul.cb_linkfl.isChecked(): updatelinkfl(self.dbQK, fangradius, deletelinkflGeomNone) if self.dlg_ul.cb_linksw.isChecked(): updatelinksw(self.dbQK, fangradius, deletelinkflGeomNone) # ---------------------------------------------------------------------------------------------- # Datenbankverbindungen schliessen del self.dbQK
class ExportToHE: """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ self.templatepath = os.path.join(pluginDirectory('qkan'), u"templates") # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join( self.plugin_dir, 'i18n', 'ExportToHE_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlg = ExportToHEDialog() # Anfang Eigene Funktionen ------------------------------------------------- # (jh, 08.02.2017) logger.info('\n\nQKan_ExportHE initialisiert...') # -------------------------------------------------------------------------- # Pfad zum Arbeitsverzeichnis sicherstellen wordir = os.path.join(site.getuserbase(), 'qkan') if not os.path.isdir(wordir): os.makedirs(wordir) # -------------------------------------------------------------------------- # Konfigurationsdatei qkan.json lesen # self.configfil = os.path.join(wordir, 'qkan.json') if os.path.exists(self.configfil): with open(self.configfil, 'r') as fileconfig: self.config = json.loads(fileconfig.read()) else: self.config['database_HE'] = '' # Vorlagedatenbank nur für den Fall, dass der Anwender keine eigene Vorlage erstellen will self.config['dbtemplate_HE'] = os.path.join(os.path.dirname(__file__), "templates", "itwh.idbf") self.config['database_QKan'] = '' with open(self.configfil, 'w') as fileconfig: fileconfig.write(json.dumps(self.config)) # Standard für Suchverzeichnis festlegen project = QgsProject.instance() self.default_dir = os.path.dirname(project.fileName()) if 'database_QKan' in self.config: database_QKan = self.config['database_QKan'] else: database_QKan = '' self.dlg.tf_QKanDB.setText(database_QKan) self.dlg.pb_selectQKanDB.clicked.connect(self.selectFile_QKanDB) if 'database_HE' in self.config: database_HE = self.config['database_HE'] else: database_HE = '' self.dlg.tf_heDB_dest.setText(database_HE) self.dlg.pb_selectHeDB_dest.clicked.connect(self.selectFile_HeDB_dest) if 'dbtemplate_HE' in self.config: dbtemplate_HE = self.config['dbtemplate_HE'] else: dbtemplate_HE = '' self.dlg.tf_heDB_template.setText(dbtemplate_HE) self.dlg.pb_selectHeDB_template.clicked.connect(self.selectFile_HeDB_template) self.dlg.pb_selectHeDB_emptytemplate.clicked.connect(self.selectFile_HeDB_emptytemplate) if 'datenbanktyp' in self.config: datenbanktyp = self.config['datenbanktyp'] else: datenbanktyp = 'spatialite' pass # Es gibt noch keine Wahlmöglichkeit # Auswahl der zu exportierenden Tabellen ---------------------------------------------- # Eigene Funktion für die zahlreichen Checkboxen def cb_set(name, cbox, default): if name in self.config: checked = self.config[name] else: checked = default cbox.setChecked(checked) return checked export_schaechte = cb_set('export_schaechte', self.dlg.cb_export_schaechte, True) export_auslaesse = cb_set('export_auslaesse', self.dlg.cb_export_auslaesse, True) export_speicher = cb_set('export_speicher', self.dlg.cb_export_speicher, True) export_haltungen = cb_set('export_haltungen', self.dlg.cb_export_haltungen, True) export_pumpen = cb_set('export_pumpen', self.dlg.cb_export_pumpen, False) export_wehre = cb_set('export_wehre', self.dlg.cb_export_wehre, False) export_flaechenrw = cb_set('export_flaechenrw', self.dlg.cb_export_flaechenrw, True) export_einleitdirekt = cb_set('export_einleitdirekt', self.dlg.cb_export_einleitdirekt, True) export_aussengebiete = cb_set('export_aussengebiete', self.dlg.cb_export_aussengebiete, True) export_abflussparameter = cb_set('export_abflussparameter', self.dlg.cb_export_abflussparameter, True) export_regenschreiber = cb_set('export_regenschreiber', self.dlg.cb_export_regenschreiber, False) export_rohrprofile = cb_set('export_rohrprofile', self.dlg.cb_export_rohrprofile, False) export_speicherkennlinien = cb_set('export_speicherkennlinien', self.dlg.cb_export_speicherkennlinien, False) export_bodenklassen = cb_set('export_bodenklassen', self.dlg.cb_export_bodenklassen, False) modify_schaechte = cb_set('modify_schaechte', self.dlg.cb_modify_schaechte, False) modify_auslaesse = cb_set('modify_auslaesse', self.dlg.cb_modify_auslaesse, False) modify_speicher = cb_set('modify_speicher', self.dlg.cb_modify_speicher, False) modify_haltungen = cb_set('modify_haltungen', self.dlg.cb_modify_haltungen, False) modify_pumpen = cb_set('modify_pumpen', self.dlg.cb_modify_pumpen, False) modify_wehre = cb_set('modify_wehre', self.dlg.cb_modify_wehre, False) modify_flaechenrw = cb_set('modify_flaechenrw', self.dlg.cb_modify_flaechenrw, False) modify_einleitdirekt = cb_set('modify_einleitdirekt', self.dlg.cb_modify_einleitdirekt, False) modify_aussengebiete = cb_set('modify_aussengebiete', self.dlg.cb_modify_aussengebiete, False) modify_abflussparameter = cb_set('modify_abflussparameter', self.dlg.cb_modify_abflussparameter, False) modify_regenschreiber = cb_set('modify_regenschreiber', self.dlg.cb_modify_regenschreiber, False) modify_rohrprofile = cb_set('modify_rohrprofile', self.dlg.cb_modify_rohrprofile, False) modify_speicherkennlinien = cb_set('modify_speicherkennlinien', self.dlg.cb_modify_speicherkennlinien, False) modify_bodenklassen = cb_set('modify_bodenklassen', self.dlg.cb_modify_bodenklassen, False) combine_flaechenrw = cb_set('combine_flaechenrw', self.dlg.cb_combine_flaechenrw, True) combine_einleitdirekt = cb_set('combine_einleitdirekt', self.dlg.cb_combine_einleitdirekt, True) # Formularereignisse anbinden ---------------------------------------------- self.dlg.pb_exportall.clicked.connect(self.exportall) self.dlg.pb_modifyall.clicked.connect(self.modifyall) self.dlg.pb_exportnone.clicked.connect(self.exportnone) self.dlg.pb_modifynone.clicked.connect(self.modifynone) self.dlg.lw_teilgebiete.itemClicked.connect(self.countselection) self.dlg.lw_teilgebiete.itemClicked.connect(self.lw_teilgebieteClick) self.dlg.cb_selActive.stateChanged.connect(self.selActiveClick) self.dlg.button_box.helpRequested.connect(self.helpClick) # Ende Eigene Funktionen --------------------------------------------------- # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('ExportToHE', message) def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/qkan/exporthe/icon_qk2he.png' Dummy.instance.add_action(icon_path, text=self.tr(u'Export to Hystem-Extran'), callback=self.run, parent=self.iface.mainWindow()) def unload(self): pass # Anfang Eigene Funktionen ------------------------------------------------- # (jh, 08.02.2017) def selectFile_HeDB_dest(self): """Datenbankverbindung zur HE-Datenbank (Firebird) auswaehlen und gegebenenfalls die Zieldatenbank erstellen, aber noch nicht verbinden.""" filename = QFileDialog.getSaveFileName(self.dlg, "Dateinamen der Ziel-HE-Datenbank eingeben", self.default_dir, "*.idbf") # if os.path.dirname(filename) != '': # os.chdir(os.path.dirname(filename)) self.dlg.tf_heDB_dest.setText(filename) def selectFile_HeDB_template(self): """Vorlage-HE-Datenbank (Firebird) auswaehlen.""" filename = QFileDialog.getOpenFileName(self.dlg, u"Vorlage-HE-Datenbank auswählen", self.default_dir, "*.idbf") # if os.path.dirname(filename) != '': # os.chdir(os.path.dirname(filename)) self.dlg.tf_heDB_template.setText(filename) def selectFile_HeDB_emptytemplate(self): """Vorlage-HE-Datenbank (Firebird) auswaehlen.""" filename = QFileDialog.getOpenFileName(self.dlg, u"Leere Vorlage-HE-Datenbank auswählen", self.templatepath, "*.idbf") # if os.path.dirname(filename) != '': # os.chdir(os.path.dirname(filename)) self.dlg.tf_heDB_template.setText(filename) def selectFile_QKanDB(self): """Datenbankverbindung zur QKan-Datenbank (SpatiLite) auswaehlen.""" filename = QFileDialog.getOpenFileName(self.dlg, u"QKan-Datenbank auswählen", self.default_dir, "*.sqlite") # if os.path.dirname(filename) != '': # os.chdir(os.path.dirname(filename)) self.dlg.tf_QKanDB.setText(filename) def exportall(self): """Aktiviert alle Checkboxen zm Export""" self.dlg.cb_export_schaechte.setChecked(True) self.dlg.cb_export_auslaesse.setChecked(True) self.dlg.cb_export_speicher.setChecked(True) self.dlg.cb_export_haltungen.setChecked(True) self.dlg.cb_export_pumpen.setChecked(True) self.dlg.cb_export_wehre.setChecked(True) self.dlg.cb_export_flaechenrw.setChecked(True) self.dlg.cb_export_einleitdirekt.setChecked(True) self.dlg.cb_export_aussengebiete.setChecked(True) self.dlg.cb_export_abflussparameter.setChecked(True) self.dlg.cb_export_regenschreiber.setChecked(True) self.dlg.cb_export_rohrprofile.setChecked(True) self.dlg.cb_export_speicherkennlinien.setChecked(True) self.dlg.cb_export_bodenklassen.setChecked(True) def modifyall(self): """Aktiviert alle Checkboxen zm Ändern""" self.dlg.cb_modify_schaechte.setChecked(True) self.dlg.cb_modify_auslaesse.setChecked(True) self.dlg.cb_modify_speicher.setChecked(True) self.dlg.cb_modify_haltungen.setChecked(True) self.dlg.cb_modify_pumpen.setChecked(True) self.dlg.cb_modify_wehre.setChecked(True) self.dlg.cb_modify_flaechenrw.setChecked(True) self.dlg.cb_modify_einleitdirekt.setChecked(True) self.dlg.cb_modify_aussengebiete.setChecked(True) self.dlg.cb_modify_abflussparameter.setChecked(True) self.dlg.cb_modify_regenschreiber.setChecked(True) self.dlg.cb_modify_rohrprofile.setChecked(True) self.dlg.cb_modify_speicherkennlinien.setChecked(True) self.dlg.cb_modify_bodenklassen.setChecked(True) def exportnone(self): """Deaktiviert alle Checkboxen zm Export""" self.dlg.cb_export_schaechte.setChecked(False) self.dlg.cb_export_auslaesse.setChecked(False) self.dlg.cb_export_speicher.setChecked(False) self.dlg.cb_export_haltungen.setChecked(False) self.dlg.cb_export_pumpen.setChecked(False) self.dlg.cb_export_wehre.setChecked(False) self.dlg.cb_export_flaechenrw.setChecked(False) self.dlg.cb_export_einleitdirekt.setChecked(False) self.dlg.cb_export_aussengebiete.setChecked(False) self.dlg.cb_export_abflussparameter.setChecked(False) self.dlg.cb_export_regenschreiber.setChecked(False) self.dlg.cb_export_rohrprofile.setChecked(False) self.dlg.cb_export_speicherkennlinien.setChecked(False) self.dlg.cb_export_bodenklassen.setChecked(False) def modifynone(self): """Deaktiviert alle Checkboxen zm Ändern""" self.dlg.cb_modify_schaechte.setChecked(False) self.dlg.cb_modify_auslaesse.setChecked(False) self.dlg.cb_modify_speicher.setChecked(False) self.dlg.cb_modify_haltungen.setChecked(False) self.dlg.cb_modify_pumpen.setChecked(False) self.dlg.cb_modify_wehre.setChecked(False) self.dlg.cb_modify_flaechenrw.setChecked(False) self.dlg.cb_modify_einleitdirekt.setChecked(False) self.dlg.cb_modify_aussengebiete.setChecked(False) self.dlg.cb_modify_abflussparameter.setChecked(False) self.dlg.cb_modify_regenschreiber.setChecked(False) self.dlg.cb_modify_rohrprofile.setChecked(False) self.dlg.cb_modify_speicherkennlinien.setChecked(False) self.dlg.cb_modify_bodenklassen.setChecked(False) # ------------------------------------------------------------------------- # Formularfunktionen def helpClick(self): """Reaktion auf Klick auf Help-Schaltfläche""" helpfile = os.path.join(self.plugin_dir, '..\doc', 'exporthe.html') os.startfile(helpfile) def lw_teilgebieteClick(self): """Reaktion auf Klick in Tabelle""" self.dlg.cb_selActive.setChecked(True) self.countselection() def selActiveClick(self): """Reagiert auf Checkbox zur Aktivierung der Auswahl""" # Checkbox hat den Status nach dem Klick if self.dlg.cb_selActive.isChecked(): # Nix tun ... logger.debug('\nChecked = True') else: # Auswahl deaktivieren und Liste zurücksetzen anz = self.dlg.lw_teilgebiete.count() for i in range(anz): item = self.dlg.lw_teilgebiete.item(i) self.dlg.lw_teilgebiete.setItemSelected(item, False) # Anzahl in der Anzeige aktualisieren self.countselection() def countselection(self): """Zählt nach Änderung der Auswahlen in den Listen im Formular die Anzahl der betroffenen Flächen und Haltungen""" liste_teilgebiete = self.listselecteditems(self.dlg.lw_teilgebiete) # Zu berücksichtigende Flächen zählen auswahl = '' if len(liste_teilgebiete) != 0: auswahl = u" WHERE flaechen.teilgebiet in ('{}')".format("', '".join(liste_teilgebiete)) sql = u"""SELECT count(*) AS anzahl FROM flaechen{auswahl}""".format(auswahl=auswahl) if not self.dbQK.sql(sql, u"QKan_ExportHE.application.countselection (1)"): return False daten = self.dbQK.fetchone() if not (daten is None): self.dlg.lf_anzahl_flaechen.setText(str(daten[0])) else: self.dlg.lf_anzahl_flaechen.setText('0') # Zu berücksichtigende Schächte zählen auswahl = '' if len(liste_teilgebiete) != 0: auswahl = u" WHERE schaechte.teilgebiet in ('{}')".format("', '".join(liste_teilgebiete)) sql = u"""SELECT count(*) AS anzahl FROM schaechte{auswahl}""".format(auswahl=auswahl) if not self.dbQK.sql(sql, u"QKan_ExportHE.application.countselection (2) "): return False daten = self.dbQK.fetchone() if not (daten is None): self.dlg.lf_anzahl_schaechte.setText(str(daten[0])) else: self.dlg.lf_anzahl_schaechte.setText('0') # Zu berücksichtigende Haltungen zählen auswahl = '' if len(liste_teilgebiete) != 0: auswahl = u" WHERE haltungen.teilgebiet in ('{}')".format("', '".join(liste_teilgebiete)) sql = u"""SELECT count(*) AS anzahl FROM haltungen{auswahl}""".format(auswahl=auswahl) if not self.dbQK.sql(sql, u"QKan_ExportHE.application.countselection (3) "): return False daten = self.dbQK.fetchone() if not (daten is None): self.dlg.lf_anzahl_haltungen.setText(str(daten[0])) else: self.dlg.lf_anzahl_haltungen.setText('0') # ------------------------------------------------------------------------- # Funktion zur Zusammenstellung einer Auswahlliste für eine SQL-Abfrage def listselecteditems(self, listWidget): """Erstellt eine Liste aus den in einem Auswahllisten-Widget angeklickten Objektnamen :param listWidget: String for translation. :type listWidget: QListWidget :returns: Tuple containing selected teilgebiete :rtype: tuple """ items = listWidget.selectedItems() liste = [] for elem in items: liste.append(elem.text()) return liste # Ende Eigene Funktionen --------------------------------------------------- def run(self): """Run method that performs all the real work""" # show the dialog # Check, ob die relevanten Layer nicht editable sind. if len({'flaechen', 'haltungen', 'linkfl', 'tezg', 'schaechte'} & get_editable_layers()) > 0: iface.messageBar().pushMessage(u"Bedienerfehler: ", u'Die zu verarbeitenden Layer dürfen nicht im Status "bearbeitbar" sein. Abbruch!', level=QgsMessageBar.CRITICAL) return False # Übernahme der Quelldatenbank: # Wenn ein Projekt geladen ist, wird die Quelldatenbank daraus übernommen. # Wenn dies nicht der Fall ist, wird die Quelldatenbank aus der # json-Datei übernommen. database_QKan = '' database_QKan, epsg = get_database_QKan() if not database_QKan: fehlermeldung(u"Fehler in k_link", u"database_QKan konnte nicht aus den Layern ermittelt werden. Abbruch!") logger.error("k_link: database_QKan konnte nicht aus den Layern ermittelt werden. Abbruch!") return False if database_QKan != '': self.dlg.tf_QKanDB.setText(database_QKan) # Datenbankverbindung für Abfragen self.dbQK = DBConnection(dbname=database_QKan) # Datenbankobjekt der QKan-Datenbank zum Lesen if not self.dbQK.connected: logger.error(u"Fehler in exportdyna.application:\n", u'QKan-Datenbank {:s} wurde nicht gefunden oder war nicht aktuell!\nAbbruch!'.format(database_QKan)) return None # Check, ob alle Teilgebiete in Flächen, Schächten und Haltungen auch in Tabelle "teilgebiete" enthalten sql = u"""INSERT INTO teilgebiete (tgnam) SELECT teilgebiet FROM flaechen WHERE teilgebiet IS NOT NULL AND teilgebiet NOT IN (SELECT tgnam FROM teilgebiete) GROUP BY teilgebiet""" if not self.dbQK.sql(sql, u"QKan_ExportHE.application.run (1) "): return False sql = u"""INSERT INTO teilgebiete (tgnam) SELECT teilgebiet FROM haltungen WHERE teilgebiet IS NOT NULL AND teilgebiet NOT IN (SELECT tgnam FROM teilgebiete) GROUP BY teilgebiet""" if not self.dbQK.sql(sql, u"QKan_ExportHE.application.run (2) "): return False sql = u"""INSERT INTO teilgebiete (tgnam) SELECT teilgebiet FROM schaechte WHERE teilgebiet IS NOT NULL AND teilgebiet NOT IN (SELECT tgnam FROM teilgebiete) GROUP BY teilgebiet""" if not self.dbQK.sql(sql, u"QKan_ExportHE.application.run (3) "): return False self.dbQK.commit() # Anlegen der Tabelle zur Auswahl der Teilgebiete # Zunächst wird die Liste der beim letzten Mal gewählten Teilgebiete aus config gelesen liste_teilgebiete = [] if 'liste_teilgebiete' in self.config: liste_teilgebiete = self.config['liste_teilgebiete'] # Abfragen der Tabelle teilgebiete nach Teilgebieten sql = 'SELECT "tgnam" FROM "teilgebiete" GROUP BY "tgnam"' if not self.dbQK.sql(sql, u"QKan_ExportHE.application.run (4) "): return False daten = self.dbQK.fetchall() self.dlg.lw_teilgebiete.clear() for ielem, elem in enumerate(daten): self.dlg.lw_teilgebiete.addItem(QListWidgetItem(elem[0])) try: if elem[0] in liste_teilgebiete: self.dlg.lw_teilgebiete.setCurrentRow(ielem) except BaseException as err: fehlermeldung(u'QKan_ExportHE (6), Fehler in elem = {}\n'.format(elem), repr(err)) # if len(daten) == 1: # self.dlg.lw_teilgebiete.setCurrentRow(0) # Ereignis bei Auswahländerung in Liste Teilgebiete self.countselection() # Autokorrektur if 'autokorrektur' in self.config: autokorrektur = self.config['autokorrektur'] else: autokorrektur = True self.dlg.cb_autokorrektur.setChecked(autokorrektur) # Festlegung des Fangradius # Kann über Menü "Optionen" eingegeben werden if 'fangradius' in self.config: fangradius = self.config['fangradius'] else: fangradius = u'0.1' # Haltungsflächen (tezg) berücksichtigen if 'mit_verschneidung' in self.config: mit_verschneidung = self.config['mit_verschneidung'] else: mit_verschneidung = True self.dlg.cb_regardTezg.setChecked(mit_verschneidung) # Mindestflächengröße # Kann über Menü "Optionen" eingegeben werden if 'mindestflaeche' in self.config: mindestflaeche = self.config['mindestflaeche'] else: mindestflaeche = u'0.5' self.countselection() # Formular anzeigen self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: # Abrufen der ausgewählten Elemente in beiden Listen liste_teilgebiete = self.listselecteditems(self.dlg.lw_teilgebiete) # Eingaben aus Formular übernehmen database_QKan = self.dlg.tf_QKanDB.text() database_HE = self.dlg.tf_heDB_dest.text() dbtemplate_HE = self.dlg.tf_heDB_template.text() datenbanktyp = 'spatialite' autokorrektur = self.dlg.cb_autokorrektur.isChecked() mit_verschneidung = self.dlg.cb_regardTezg.isChecked() check_export = {} check_export['export_schaechte'] = self.dlg.cb_export_schaechte.isChecked() check_export['export_auslaesse'] = self.dlg.cb_export_auslaesse.isChecked() check_export['export_speicher'] = self.dlg.cb_export_speicher.isChecked() check_export['export_haltungen'] = self.dlg.cb_export_haltungen.isChecked() check_export['export_pumpen'] = self.dlg.cb_export_pumpen.isChecked() check_export['export_wehre'] = self.dlg.cb_export_wehre.isChecked() check_export['export_flaechenrw'] = self.dlg.cb_export_flaechenrw.isChecked() check_export['export_einleitdirekt'] = self.dlg.cb_export_einleitdirekt.isChecked() check_export['export_aussengebiete'] = self.dlg.cb_export_aussengebiete.isChecked() check_export['export_abflussparameter'] = self.dlg.cb_export_abflussparameter.isChecked() check_export['export_regenschreiber'] = self.dlg.cb_export_regenschreiber.isChecked() check_export['export_rohrprofile'] = self.dlg.cb_export_rohrprofile.isChecked() check_export['export_speicherkennlinien'] = self.dlg.cb_export_speicherkennlinien.isChecked() check_export['export_bodenklassen'] = self.dlg.cb_export_bodenklassen.isChecked() check_export['modify_schaechte'] = self.dlg.cb_modify_schaechte.isChecked() check_export['modify_auslaesse'] = self.dlg.cb_modify_auslaesse.isChecked() check_export['modify_speicher'] = self.dlg.cb_modify_speicher.isChecked() check_export['modify_haltungen'] = self.dlg.cb_modify_haltungen.isChecked() check_export['modify_pumpen'] = self.dlg.cb_modify_pumpen.isChecked() check_export['modify_wehre'] = self.dlg.cb_modify_wehre.isChecked() check_export['modify_flaechenrw'] = self.dlg.cb_modify_flaechenrw.isChecked() check_export['modify_einleitdirekt'] = self.dlg.cb_modify_einleitdirekt.isChecked() check_export['modify_aussengebiete'] = self.dlg.cb_modify_aussengebiete.isChecked() check_export['modify_abflussparameter'] = self.dlg.cb_modify_abflussparameter.isChecked() check_export['modify_regenschreiber'] = self.dlg.cb_modify_regenschreiber.isChecked() check_export['modify_rohrprofile'] = self.dlg.cb_modify_rohrprofile.isChecked() check_export['modify_speicherkennlinien'] = self.dlg.cb_modify_speicherkennlinien.isChecked() check_export['modify_bodenklassen'] = self.dlg.cb_modify_bodenklassen.isChecked() check_export['combine_flaechenrw'] = self.dlg.cb_combine_flaechenrw.isChecked() check_export['combine_einleitdirekt'] = self.dlg.cb_combine_einleitdirekt.isChecked() # Konfigurationsdaten schreiben self.config['database_HE'] = database_HE self.config['dbtemplate_HE'] = dbtemplate_HE self.config['database_QKan'] = database_QKan self.config['datenbanktyp'] = datenbanktyp self.config['liste_teilgebiete'] = liste_teilgebiete self.config['autokorrektur'] = autokorrektur self.config['fangradius'] = fangradius self.config['mit_verschneidung'] = mit_verschneidung self.config['mindestflaeche'] = mindestflaeche for el in check_export: self.config[el] = check_export[el] with open(self.configfil, 'w') as fileconfig: # logger.debug(u"Config-Dictionary: {}".format(self.config)) fileconfig.write(json.dumps(self.config)) exportKanaldaten(iface, database_HE, dbtemplate_HE, self.dbQK, liste_teilgebiete, autokorrektur, fangradius, mindestflaeche, mit_verschneidung, datenbanktyp, check_export)
class Navigator: def __init__(self, dbname: str): """ Constructor :param dbname: Entspricht dem Datei-Pfad zur SpatiaLite-Datenbank. """ self.__dbname = dbname self.__error_msg = "" self.db = DBConnection(dbname) if not self.db.connected: main_logger.error( ( "Fehler in navigation:\n" + "QKan-Datenbank {:s} wurde nicht gefunden oder war nicht aktuell!\nAbbruch!" ).format(dbname) ) raise Exception() # TODO: ??? self.log = logging.getLogger("QKan.navigation.Navigator") def calculate_route_schacht( self, nodes: List[str] ) -> Optional[Dict[str, Union[List[str], Dict[str, Union[str, float]]]]]: """ * Wird ausgeführt, wenn eine Route zwischen Schächten gefunden werden soll. * Berechnet die Route aus Start- und Endpunkt, prüft am Ende, ob alle anderen Schächte innerhalb der berechneten Route liegen. * Benötigt mindestens zwei Schächte :param nodes: Entspricht einer Liste von den selektierten Schacht-Namen aus QGIS. :return: Gibt ein Routen-Objekt zurück mit allen Haltungen und Schächten """ self.log.debug("Übergebene Schächte:\t{}".format(nodes)) endpoint = nodes[0] startpoint = nodes[0] statement = """ SELECT sohlhoehe FROM schaechte WHERE schnam="{}" """ self.db.sql(statement.format(nodes[0])) (min_value,) = self.db.fetchone() max_value = min_value for n in nodes: self.db.sql(statement.format(n)) (value,) = self.db.fetchone() if value < min_value: min_value = value endpoint = n elif value > max_value: max_value = value startpoint = n self.log.info("Start- und Endpunkt wurden gesetzt") self.log.debug("Startpunkt:\t{}\nEndpunkt:\t{}".format(startpoint, endpoint)) nodes.remove(startpoint) nodes.remove(endpoint) self.log.debug(u"Zusätzliche Punkte:\t{}".format(nodes)) return self.__calculate_route_schacht( startpoint, endpoint, additional_points=nodes ) def __calculate_route_schacht( self, startpoint: str, endpoint: str, additional_points: List[str] ) -> Optional[Dict[str, Union[List[str], Dict[str, Union[str, float]]]]]: """ Berechnet die Schächte und Haltungen, die zwischen einem Start- und Endpunkt liegen. * Start- und Endhöhe müssen nicht in der richtigen Reihenfolge übergeben werden. * Zusätzliche Punkte müssen nur übergeben werden, wenn der Endpunkt über mehrere Wege zu erreichen ist. :param startpoint: Entspricht dem Schacht-Namen aus QGIS. :param endpoint: Entspricht dem Schacht-Namen aus QGIS. :param additional_points: Entspricht einer Liste von Schacht-Namen, die zusätzlich ausgewählt wurden. :return: Gibt ein Routen-Objekt zurück, bestehend aus allen Haltungen und Schächten """ statement = u""" SELECT name FROM (SELECT haltnam AS name, schoben FROM haltungen UNION SELECT wnam AS name, schoben FROM wehre UNION SELECT pnam AS name, schoben FROM pumpen) WHERE schoben ="{}" """ self.db.sql(statement.format(startpoint)) start_haltungen = [h[0] for h in self.db.fetchall()] self.log.debug(u"Start-Haltungen:\t{}".format(start_haltungen)) statement_2 = u""" SELECT name FROM (SELECT haltnam AS name, schunten FROM haltungen UNION SELECT wnam AS name, schunten FROM wehre UNION SELECT pnam AS name, schunten FROM pumpen) WHERE schunten ="{}" """ self.db.sql(statement_2.format(endpoint)) end_haltungen = [h[0] for h in self.db.fetchall()] self.log.debug(u"End-Haltungen:\t{}".format(end_haltungen)) nodes = [] if len(additional_points) > 0: for p in additional_points: self.db.sql(statement.format(p)) nodes.append([h[0] for h in self.db.fetchall()]) permutations = cast(List[List[float]], itertools.product(*nodes)) permutations = [list(p) for p in permutations] possibilities = 0 route = None self.log.debug(u"Zusätzliche Haltungen:\t{}".format(nodes)) self.log.info(u"Alle nötigen Haltungen gesetzt") for start_haltung in start_haltungen: for end_haltung in end_haltungen: for permutation in permutations: _nodes = list(set([start_haltung, end_haltung] + list(permutation))) self.log.debug(u"Aktuelle Haltungen:\t{}".format(_nodes)) _route = self.calculate_route_haltung(_nodes) if _route: self.log.info(u"Aktuelle Route ist valide") possibilities += 1 if possibilities > 1: self.log.error( u"Zu viele Möglichkeiten zwischen Start- und End-Haltung." ) self.__error_msg = ( u"Zu viele Möglichkeiten. Bitte wählen Sie einen Wegpunkt auf" u" dem kritischen Pfad!" ) return None route = _route return route def calculate_route_haltung( self, nodes: List[str] ) -> Optional[Dict[str, Union[List[str], Dict[str, Union[str, float]]]]]: """ Berechnet eine Route zwischen mehreren Haltungen. :param nodes: Alle selektierten Haltungs-Namen aus QGIS :return: Gibt eine Routen-Objekt mit allen Haltungen und Schächten zurück """ if len(nodes) == 1: routes = [nodes] else: tasks = Tasks(self.__dbname, nodes) self.log.info(u"Tasks wurden initialisiert") routes = tasks.start() self.log.info(u"Alle möglichen Routen ({}) berechnet".format(len(routes))) if len(routes) == 1: self.log.info(u"Eine einzige mögliche Route gefunden") return self.__fetch_data(routes[0]) elif len(routes) == 0: self.log.error(u"Keine Route gefunden. Pfad ist fehlerhaft!") self.__error_msg = u"Übergebener Pfad ist fehlerhaft." return None else: self.log.error( u"Es gibt {} mögliche Routen. Der Pfad muss spezifiziert werden".format( len(routes) ) ) self.__error_msg = ( u"Mehrere Möglichkeiten ({}) den Endpunkt zu erreichen. " u"Bitte spezifizieren Sie die Route." ).format(len(routes)) return None def __fetch_data( self, haltungen: List[str] ) -> Dict[str, Union[List[str], Dict[str, Union[str, float]]]]: """ Fragt die Datenbank nach den benötigten Attributen ab und speichert sie in einem Dictionary. Das Dictionary hat folgende Struktur: *{haltungen:[haltungsnamen], schaechte:[schachtnamen], schachtinfo:{schachtname: {sohlhoehe:float, deckelhoehe:float} }, haltunginfo:{haltungsname: {schachtoben: schachtname, schachtunten: schachtname, laenge: float, sohlhoeheoben: float, sohlhoeheunten: float, querschnitt: float} } } :param haltungen: Liste aller Haltungs-Namen aus QGIS :return: Gibt ein Routen-Objekt zurück. """ statement = u""" SELECT schoben FROM (SELECT haltnam AS name, schoben FROM haltungen UNION SELECT wnam AS name, schoben FROM wehre UNION SELECT pnam AS name, schoben FROM pumpen) WHERE name = "{}" """ schaechte = [] self.log.debug(u"Haltungen:\t{}".format(haltungen)) self.db.sql(statement.format(haltungen[0])) schaechte.append(self.db.fetchone()[0]) statement = u""" SELECT schunten FROM (SELECT haltnam AS name, schunten FROM haltungen UNION SELECT wnam AS name, schunten FROM wehre UNION SELECT pnam AS name, schunten FROM pumpen) WHERE name = "{}" """ for h in haltungen: self.db.sql(statement.format(h)) schaechte.append(self.db.fetchone()[0]) self.log.debug(u"Schächte:\t{}".format(schaechte)) route = {"haltungen": haltungen, "schaechte": schaechte} rinfo = self.get_info(route) rval: Dict[str, Union[List[str], Dict[str, Union[str, float]]]] = { "haltungen": haltungen, "schaechte": schaechte, "schachtinfo": rinfo[0], "haltunginfo": rinfo[1], } self.log.info("Route wurde erfolgreich erstellt!") return rval def get_info(self, route: Dict[str, List[str]]) -> Tuple[Dict, Dict]: """ Methode muss überschrieben werden bei Verwendung dieses Moduls :param route: Die Haltungen und Schächte in einem Dictionary :type route: dict :return Gibt zwei Dictionaries mit zusätzlichen Informationen aus der Datenbank zurück :rtype: dict, dict """ def get_error_msg(self) -> str: """ Getter der Error-Message. :return: Gibt die Error-Message zurück """ return self.__error_msg
class Worker(QtCore.QRunnable): def __init__(self, dbname: str, startpoint: str, nodes: List[str], parent: "Tasks"): """ Constructor :param dbname:Entspricht dem SpatiaLite-Datenbank-Pfad :param startpoint:Haltungs-Name des Startpunktes :param nodes: Liste alle Haltungs-Namen, die in der Route vorkommen müssen :param parent: Verweis auf die Task-Klasse, damit die Ergebnisse gespeichert werden können """ super(Worker, self).__init__() self.__startpoint = startpoint self.__nodes = nodes self.__db = DBConnection(dbname) if not self.__db.connected: main_logger.error( ( "Fehler in navigation:\n" + "QKan-Datenbank {:s} wurde nicht gefunden oder war nicht aktuell!\nAbbruch!" ).format(dbname) ) raise Exception() # TODO: ??? self.__parent = parent def run(self) -> None: """ Berechnet alle Routen zwischen einem Startpunkt und allen anderen Punkten """ routes = self.__get_routes(self.__startpoint) for route in routes: self.__parent.results.append(route) def __get_routes(self, startpoint: str) -> List[List[str]]: """ Berechnet rekursiv alle Routen von einem Startpunkt bis zum Endpunkt (Keine weitere Haltung verfügbar) Außerdem wird abgebrochen, wenn alle Punkte in der Route vorkommen. :param startpoint: Entspricht dem Haltungs-Namen des Startpunkts aus QGIS :return: Gibt eine Liste von allen möglichen Routen zurück """ results: List[List[str]] = [] self.__get_routes_recursive([startpoint], results) return results def __get_routes_recursive( self, haltungen: List[str], results: List[List[str]] ) -> Optional[List[str]]: """ Berechnet alle möglichen Routen rekursiv :param haltungen: Eine Liste der bisherigen Route :type haltungen: list :param results: Eine Liste aller bisher errechneten Routen :type results: list """ if set(haltungen).issuperset(set(self.__nodes)): return haltungen statement = """SELECT name FROM (SELECT haltnam AS name, schoben FROM haltungen UNION SELECT wnam AS name, schoben FROM wehre UNION SELECT pnam AS name, schoben FROM pumpen) WHERE schoben = (SELECT schunten FROM (SELECT haltnam AS name, schunten FROM haltungen UNION SELECT wnam AS name, schunten FROM wehre UNION SELECT pnam AS name, schunten FROM pumpen) WHERE name = "{}") """ self.__db.sql(statement.format(haltungen[-1])) next_haltungen = self.__db.fetchall() for (option,) in next_haltungen: h_copy = list(haltungen) h_copy.append(option) res = self.__get_routes_recursive(h_copy, results) if res is not None: results.append(res) return None
class Worker(QtCore.QRunnable): def __init__(self, dbname, startpoint, nodes, parent): """ Constructor :param dbname:Entspricht dem SpatiaLite-Datenbank-Pfad :type dbname: str :param startpoint:Haltungs-Name des Startpunktes :type startpoint: str :param nodes: Liste alle Haltungs-Namen, die in der Route vorkommen müssen :type nodes: list :param parent: Verweis auf die Task-Klasse, damit die Ergebnisse gespeichert werden können :type parent: Tasks """ super(Worker, self).__init__() self.__startpoint = startpoint self.__nodes = nodes self.__db = DBConnection(dbname) self.__parent = parent def run(self): """ Berechnet alle Routen zwischen einem Startpunkt und allen anderen Punkten """ routes = self.__get_routes(self.__startpoint) for route in routes: self.__parent.results.append(route) def __get_routes(self, startpoint): """ Berechnet rekursiv alle Routen von einem Startpunkt bis zum Endpunkt (Keine weitere Haltung verfügbar) Außerdem wird abgebrochen, wenn alle Punkte in der Route vorkommen. :param startpoint: Entspricht dem Haltungs-Namen des Startpunkts aus QGis :type startpoint: str :return: Gibt eine Liste von allen möglichen Routen zurück :rtype: list """ results = [] self.__get_routes_recursive([startpoint], results) return results def __get_routes_recursive(self, haltungen, results): """ Berechnet alle möglichen Routen rekursiv :param haltungen: Eine Liste der bisherigen Route :type haltungen: list :param results: Eine Liste aller bisher errechneten Routen :type results: list """ if set(haltungen).issuperset(set(self.__nodes)): return haltungen statement = u"""SELECT name FROM (SELECT haltnam AS name, schoben FROM haltungen UNION SELECT wnam AS name, schoben FROM wehre UNION SELECT pnam AS name, schoben FROM pumpen) WHERE schoben = (SELECT schunten FROM (SELECT haltnam AS name, schunten FROM haltungen UNION SELECT wnam AS name, schunten FROM wehre UNION SELECT pnam AS name, schunten FROM pumpen) WHERE name = "{}") """ self.__db.sql(statement.format(haltungen[-1])) next_haltungen = self.__db.fetchall() if len(next_haltungen) == 0: return for option, in next_haltungen: hCopy = list(haltungen) hCopy.append(option) res = self.__get_routes_recursive(hCopy, results) if res is not None: results.append(res)