Exemple #1
0
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)
Exemple #2
0
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)
Exemple #3
0
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)
Exemple #4
0
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)
Exemple #6
0
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
Exemple #7
0
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
Exemple #8
0
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)