Exemplo n.º 1
0
class APISFilm(QDialog, FORM_CLASS):

    FIRST, PREV, NEXT, LAST = range(4)
    OBLIQUE, VERTICAL = range(2)

    def __init__(self, iface, dbm, imageRegistry, apisLayer, parent=None):
        """Constructor."""
        super(APISFilm, self).__init__(parent)

        self.iface = iface
        self.dbm = dbm
        self.imageRegistry = imageRegistry
        self.apisLayer = apisLayer

        self.parent = parent

        self.setupUi(self)

        # Initial window size/pos last saved. Use default values for first time
        if GetWindowSize("film"):
            self.resize(GetWindowSize("film"))
        if GetWindowPos("film"):
            self.move(GetWindowPos("film"))

        self.printingOptionsDlg = None

        self.settings = QSettings(QSettings().value("APIS/config_ini"), QSettings.IniFormat)

        self.editMode = False
        self.addMode = False
        self.initalLoad = True

        #self.uiInitalEntryQgsDate.setCalendarPopup(False)
        #self.uiLastChangesQgsDate.setCalendarPopup(False)

        # Signals/Slot Connections
        self.rejected.connect(self.onReject)
        self.uiOkBtn.clicked.connect(self.onAccept)
        self.uiCancelBtn.clicked.connect(self.cancelEdit)
        self.uiSaveBtn.clicked.connect(self.saveEdits)

        self.uiFilmSelectionBtn.clicked.connect(self.openFilmSelectionDialog)

        self.uiNewFilmBtn.clicked.connect(self.openNewFilmDialog)
        self.uiSearchFilmBtn.clicked.connect(self.openSearchFilmDialog)
        self.uiEditWeatherBtn.clicked.connect(self.openEditWeatherDialog)

        self.uiExportPdfBtn.clicked.connect(self.exportDetailsPdf)

        self.uiShowFlightPathBtn.clicked.connect(lambda: self.openFlightPathDialog([self.uiCurrentFilmNumberEdit.text()]))

        # For LaLe Mode
        if self.settings.value("APIS/disable_site_and_findspot", "0") != "1":
            self.uiListSitesOfFilmBtn.setEnabled(True)
            self.uiListSitesOfFilmBtn.clicked.connect(self.openSiteSelectionListDialog)
        else:
            self.uiListSitesOfFilmBtn.setEnabled(False)

        self.uiListImagesOfFilmBtn.clicked.connect(self.openImageSelectionListDialog)
        self.uiExtractGpsFromImagesBtn.clicked.connect(self.extractGpsFromImages)

        self.uiWeatherCodeEdit.textChanged.connect(self.generateWeatherCode)
        self.uiFilmModeCombo.currentIndexChanged.connect(self.onFilmModeChanged)

        self.uiEditProjectTableBtn.clicked.connect(lambda: self.openSystemTableEditorDialog("projekt", self.uiProjectSelectionCombo))
        self.uiEditCopyrightTableBtn.clicked.connect(lambda: self.openSystemTableEditorDialog("copyright", self.uiCopyrightCombo))
        # self.uiEditProjectTableBtn.clicked.connect(lambda: VersionToCome())
        # self.uiEditCopyrightTableBtn.clicked.connect(lambda: VersionToCome())

        # init Project Btn
        self.uiAddProjectBtn.clicked.connect(self.addProject)
        self.uiRemoveProjectBtn.clicked.connect(self.removeProject)

        # Setup Sub-Dialogs
        self.filmSelectionDlg = APISFilmNumberSelection(self)
        self.newFilmDlg = APISFilmNew(parent=self)
        self.searchFilmDlg = APISFilmSearch(self.dbm, self)  # (self.iface, self.dbm)
        self.editWeatherDlg = APISWeather(self.iface, self.dbm, self)
        self.flightPathDlg = APISFlightPath(self.iface, self.dbm, self.apisLayer, self)
        self.siteSelectionListDlg = APISSiteSelectionList(self.iface, self.dbm, self.imageRegistry, self.apisLayer, self)
        self.imageSelectionListDlg = APISImageSelectionList(self.iface, self.dbm, self.imageRegistry,  self.apisLayer, parent=self)
        self.systemTableEditorDlg = None

        # Setup film model
        self.model = QSqlRelationalTableModel(self, self.dbm.db)
        self.model.setTable("film")
        self.model.select()

        while (self.model.canFetchMore()):
            self.model.fetchMore()

        self.setupMapper()
        self.setupComboBox(self.uiProjectSelectionCombo, "projekt", 0, None)

        self.setupComboBox(self.newFilmDlg.uiProducerCombo, "hersteller", 2, None)

        self.setupNavigation()

        self.mapper.toFirst()

        self.initalLoad = False

    def setupMapper(self):
        self.mapper = QDataWidgetMapper(self)

        self.mapper.currentIndexChanged.connect(self.onCurrentIndexChanged)

        self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
        self.mapper.setItemDelegate(FilmDelegate())

        self.mapper.setModel(self.model)

        self.mandatoryEditors = [self.uiImageCountEdit, self.uiCameraCombo, self.uiFilmMakeCombo, self.uiFilmModeCombo]
        self.disableEditorsIfOblique = [self.uiCameraNumberEdit, self.uiCalibratedFocalLengthEdit]
        # LineEdits & PlainTextEdits
        self.intValidator = QIntValidator()
        self.doubleValidator = QDoubleValidator()
        self.lineEditMaps = {
            "filmnummer": {
                "editor": self.uiCurrentFilmNumberEdit
            },
            "hersteller": {
                "editor": self.uiProducerEdit
            },
            "anzahl_bilder": {
                "editor": self.uiImageCountEdit,
                "validator": self.intValidator
            },
            "militaernummer": {
                "editor": self.uiMilitaryNumberEdit
            },
            "militaernummer_alt": {
                "editor": self.uiOldMilitaryNumberEdit
            },
            "form1": {
                "editor": self.uiFormat1Edit
            },
            "form2": {
                "editor": self.uiFormat2Edit
            },
            "kalibrierungsnummer": {
                "editor": self.uiCameraNumberEdit
            },
            "kammerkonstante": {
                "editor": self.uiCalibratedFocalLengthEdit,
                "validator": self.doubleValidator
            },
            "kassettennummer": {
                "editor": self.uiCassetteEdit
            },
            "art_ausarbeitung": {
                "editor": self.uiFilmMakeEdit
            },
            "fotograf": {
                "editor": self.uiPhotographerEdit
            },
            "pilot": {
                "editor": self.uiPilotEdit
            },
            "flugzeug": {
                "editor": self.uiAirplaneEdit
            },
            "abflug_flughafen": {
                "editor": self.uiDepartureAirportEdit
            },
            "ankunft_flughafen": {
                "editor": self.uiArrivalAirportEdit
            },
            "flugzeit": {
                "editor": self.uiFlightDurationEdit
            },
            "wetter": {
                "editor": self.uiWeatherCodeEdit
            },
            "kommentar": {
                "editor": self.uiCommentsPTxt
            }
        }
        for key, item in self.lineEditMaps.items():
            self.mapper.addMapping(item["editor"], self.model.fieldIndex(key))
            if "validator" in item:
                item["editor"].setValidator(item["validator"])
            #item["editor"].textChanged.connect(partial(self.onLineEditChanged, item["editor"]))
            item["editor"].textChanged.connect(self.onLineEditChanged)
        #Text
        #self.mapper.addMapping(self.uiCommentsPTxt, self.model.fieldIndex("kommentar"))

        # Date and Times
        self.mapper.addMapping(self.uiFlightDate, self.model.fieldIndex("flugdatum"))
        #self.mapper.addMapping(self.uiFlightQgsDate, self.model.fieldIndex("flugdatum"))
        self.mapper.addMapping(self.uiInitalEntryDate, self.model.fieldIndex("datum_ersteintrag"))
        #self.mapper.addMapping(self.uiInitalEntryQgsDate, self.model.fieldIndex("datum_ersteintrag"))
        self.mapper.addMapping(self.uiLastChangesDate, self.model.fieldIndex("datum_aenderung"))
        #self.mapper.addMapping(self.uiLastChangesQgsDate, self.model.fieldIndex("datum_aenderung"))

        self.mapper.addMapping(self.uiDepartureTime, self.model.fieldIndex("abflug_zeit"))
        self.mapper.addMapping(self.uiArrivalTime, self.model.fieldIndex("ankunft_zeit"))
        self.uiDepartureTime.timeChanged.connect(self.onFlightTimeChanged)
        self.uiArrivalTime.timeChanged.connect(self.onFlightTimeChanged)

        # ComboBox without Model
        self.mapper.addMapping(self.uiFilmModeCombo, self.model.fieldIndex("weise"))
        self.uiFilmModeCombo.editTextChanged.connect(self.onLineEditChanged)
        completer = QCompleter(self.uiFilmModeCombo.model())
        self.uiFilmModeCombo.setCompleter(completer)
        self.uiFilmModeCombo.lineEdit().setValidator(InListValidator([self.uiFilmModeCombo.itemText(i) for i in range(self.uiFilmModeCombo.count())], self.uiFilmModeCombo.lineEdit(), None, self))

        # ComboBox with Model
        self.comboBoxMaps = {
            "archiv": {
                "editor": self.uiArchiveCombo,
                "table": "hersteller",
                "modelcolumn": 2,
                "depend": None
            },
            "kamera": {
                "editor": self.uiCameraCombo,
                "table": "kamera",
                "modelcolumn": 0,
                "depend": [{"form1": self.uiFormat1Edit}, {"form2": self.uiFormat2Edit}]
            },
            "filmfabrikat": {
                "editor": self.uiFilmMakeCombo,
                "table": "film_fabrikat",
                "modelcolumn": 0,
                "depend": [{"art": self.uiFilmMakeEdit}]
            },
            "target": {
                "editor": self.uiTargetCombo,
                "table": "target",
                "modelcolumn": 0,
                "depend": None
            },
            "copyright": {
                "editor": self.uiCopyrightCombo,
                "table": "copyright",
                "modelcolumn": 0,
                "depend": None
            }
        }
        for key, item in self.comboBoxMaps.items():
            self.mapper.addMapping(item["editor"], self.model.fieldIndex(key))
            self.setupComboBox(item["editor"], item["table"], item["modelcolumn"], item["depend"])
            item["editor"].editTextChanged.connect(self.onLineEditChanged)

        self.mapper.addMapping(self.uiProjectList, self.model.fieldIndex("projekt"))

    def fixComboBoxDropDownListSizeAdjustemnt(self, cb):
        scroll = 0 if cb.count() <= cb.maxVisibleItems() else QApplication.style().pixelMetric(QStyle.PM_ScrollBarExtent)
        iconWidth = cb.iconSize().width()
        max = 0

        for i in range(cb.count()):
            width = cb.view().fontMetrics().width(cb.itemText(i))
            if max < width:
                max = width

        QMessageBox.information(self, "info", "scroll: {0}, max: {1}, icon: {2}".format(scroll, max, iconWidth))

        #cb.view().setMinimumWidth(scroll + max)

    def setupComboBox(self, editor, table, modelColumn, depend):
        model = QSqlRelationalTableModel(self, self.dbm.db)
        model.setTable(table)
        model.removeColumn(0)
        model.select()

        tv = QTableView()
        editor.setView(tv)

        tv.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        tv.setSelectionMode(QAbstractItemView.SingleSelection)
        tv.setSelectionBehavior(QAbstractItemView.SelectRows)
        tv.setAutoScroll(False)

        editor.setModel(model)

        editor.setModelColumn(modelColumn)
        editor.setInsertPolicy(QComboBox.NoInsert)

        tv.resizeColumnsToContents()
        tv.resizeRowsToContents()
        tv.verticalHeader().setVisible(False)
        tv.horizontalHeader().setVisible(True)
        #tv.setMinimumWidth(tv.horizontalHeader().length())
        tv.horizontalHeader().setStretchLastSection(True)
        #tv.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        tv.resizeColumnsToContents()
        scroll = 0 if editor.count() <= editor.maxVisibleItems() else QApplication.style().pixelMetric(QStyle.PM_ScrollBarExtent)
        tv.setMinimumWidth(tv.horizontalHeader().length() + scroll)
        #self.fixComboBoxDropDownListSizeAdjustemnt(editor)

        #editor.resize(tv.horizontalHeader().sizeHint())

        completer = QCompleter(editor.model())
        editor.setCompleter(completer)
        #editor.setAutoCompletion(True)
        editor.lineEdit().setValidator(InListValidator([editor.itemText(i) for i in range(editor.count())], editor.lineEdit(), depend, self))

        if depend:
            editor.currentIndexChanged.connect(partial(self.updateDepends, editor, depend))

    def updateDepends(self, editor, depend):
        for dep in depend:
            for key, value in dep.items():
                idx = editor.model().createIndex(editor.currentIndex(), editor.model().fieldIndex(key))
                value.setText(str(editor.model().data(idx)))
                #QMessageBox.warning(None, "Test", str(idx))

    def setupNavigation(self):
        self.uiFirstFilmBtn.clicked.connect(partial(self.loadRecordByNavigation, APISFilm.FIRST))
        self.uiPreviousFilmBtn.clicked.connect(partial(self.loadRecordByNavigation, APISFilm.PREV))
        self.uiNextFilmBtn.clicked.connect(partial(self.loadRecordByNavigation, APISFilm.NEXT))
        self.uiLastFilmBtn.clicked.connect(partial(self.loadRecordByNavigation, APISFilm.LAST))

        self.uiTotalFilmCountLbl.setText(str(self.model.rowCount()))
        self.intRecordValidator = QIntValidator(1, self.model.rowCount())
        self.uiCurrentFilmCountEdit.setValidator(self.intRecordValidator)
        self.uiCurrentFilmCountEdit.setText(str(self.mapper.currentIndex() + 1))
        self.uiCurrentFilmCountEdit.editingFinished.connect(lambda: self.loadRecordById(int(self.uiCurrentFilmCountEdit.text()) - 1))
        # QMessageBox.warning(None, "Test", str(self.mapper.itemDelegate()))

    def enableItemsInLayout(self, layout, enable):
        for i in range(layout.count()):
            if layout.itemAt(i).widget():
                layout.itemAt(i).widget().setEnabled(enable)

    def loadRecordByNavigation(self, mode):
        #self.mapper.submit()
        #self.submitChanges()
        self.initalLoad = True
        if mode == APISFilm.FIRST:
            self.mapper.toFirst()
        elif mode == APISFilm.PREV:
            self.mapper.toPrevious()
        elif mode == APISFilm.NEXT:
            self.mapper.toNext()
        elif mode == APISFilm.LAST:
            self.mapper.toLast()
        self.initalLoad = False

    def loadRecordById(self, id):
        #self.submitChanges
        self.initalLoad = True
        self.mapper.setCurrentIndex(id)
        self.initalLoad = False

    def loadRecordByKeyAttribute(self, attribute, value):
        #self.model.setFilter(attribute + " = '" + value + "'")
        #self.model.select()
        # self.mapper.toFirst()

        query = QSqlQuery(self.dbm.db)
        #qryStr = "select {0} from film where {0} = '{1}' limit 1".format(attribute, value)
        #qryStr = "SELECT rowid FROM film WHERE {0} = '{1}' limit 1".format(attribute, value)
        qryStr = "SELECT" \
                 "  (SELECT COUNT(*)" \
                 "       FROM film AS t2" \
                 "       WHERE t2.rowid < t1.rowid" \
                 "      ) + (" \
                 "         SELECT COUNT(*)" \
                 "         FROM film AS t3" \
                 "        WHERE t3.rowid = t1.rowid AND t3.rowid < t1.rowid" \
                 "      ) AS rowNum" \
                 "   FROM film AS t1" \
                 "   WHERE {0} = '{1}'" \
                 "   ORDER BY t1.rowid ASC".format(attribute, value)

        query.exec_(qryStr)

        #QMessageBox.warning(None, "Test", str(query.size()) + ',' + str(query.numRowsAffected()))

        query.first()
        fn = query.value(0)

        if fn is not None:
            self.loadRecordById(fn)
            return True
        else:
            # Film does not exist
            QMessageBox.warning(None, "Film Nummer", str("Der Film mit der Nummer {0} existiert nicht!".format(value)))
            return False

        #self.model.setFilter('')
        #self.model.select()
        #while (self.model.canFetchMore()):
            #self.model.fetchMore()

    def submitChanges(self):
        self.mapper.submit()

    def onCurrentIndexChanged(self):
        self.uiCurrentFilmCountEdit.setText(str(self.mapper.currentIndex() + 1))
        self.onFilmModeChanged()

    def onFlightTimeChanged(self):
        dTime = self.uiDepartureTime.time()
        aTime = self.uiArrivalTime.time()
        flightDuration = dTime.secsTo(aTime)
        self.uiFlightDurationEdit.setText(str(flightDuration / 60))

    def disableIfOblique(self, isOblique):
        for editor in self.disableEditorsIfOblique:
            editor.setDisabled(isOblique)

    def onFilmModeChanged(self):
        if self.uiFilmModeCombo.currentText() == u'schräg':
            self.disableIfOblique(True)
        else:
            self.disableIfOblique(False)

    def onLineEditChanged(self):
        sender = self.sender()
        if not self.editMode and not self.initalLoad:
            self.startEditMode()
        if not self.initalLoad:
            sender.setStyleSheet("{0} {{background-color: rgb(153, 204, 255);}}".format(sender.metaObject().className()))
            self.editorsEdited.append(sender)

    def onComboBoxChanged(self, editor):
        pass

    def addProject(self):
        editor = self.uiProjectList
        value = self.uiProjectSelectionCombo.currentText()
        notInList = True
        for row in range(editor.count()):
            if value == editor.item(row).data(0):
                notInList = False
                break
        if notInList:
            editor.addItem(value)
            editor.sortItems()
            if not self.editMode and not self.initalLoad:
                self.startEditMode()
            if not self.initalLoad:
                editor.setStyleSheet("{0} {{background-color: rgb(153, 204, 255);}}".format(editor.metaObject().className()))
                self.editorsEdited.append(editor)

    def removeProject(self):
        editor = self.uiProjectList
        editor.takeItem(self.uiProjectList.currentRow())
        if not self.editMode and not self.initalLoad:
            self.startEditMode()
        if not self.initalLoad:
            editor.setStyleSheet("{0} {{background-color: rgb(153, 204, 255);}}".format(editor.metaObject().className()))
            self.editorsEdited.append(editor)

    def onAccept(self):
        '''
        Check DB
        Save options when pressing OK button
        Update Plugin Status
        '''
        self.accept()

    def onReject(self):
        '''
        Run some actions when
        the user closes the dialog
        '''
        if self.editMode:
            res = self.cancelEdit()
            if res:
                self.close()
            else:
                self.show()
        else:
            self.close()

    def closeEvent(self, e):
        # Write window size and position to QSettings
        if self.editMode:
            self.onReject()
        else:
            SetWindowSizeAndPos("film", self.size(), self.pos())
            e.accept()

    def extractGpsFromImages(self):
        key = self.uiCurrentFilmNumberEdit.text()
        e2p = Exif2Points(self.iface, key)
        layer = e2p.run()
        if layer:
            self.apisLayer.requestShapeFile(layer, groupName="Flugwege", addToCanvas=True)

    def exportDetailsPdf(self):
        if self.printingOptionsDlg is None:
            self.printingOptionsDlg = APISPrintingOptions(self)
            self.printingOptionsDlg.setWindowTitle("Druck Optionen: Film")
            self.printingOptionsDlg.configure(False, False, visPersonalDataChk=True)

        self.printingOptionsDlg.show()

        if self.printingOptionsDlg.exec_():
            printPersonalData = self.printingOptionsDlg.printPersonalData()
            APISPrinterQueue([{'type': APISTemplatePrinter.FILM, 'idList': [self.uiCurrentFilmNumberEdit.text()], 'options': {'personalData': printPersonalData}}],
                             OutputMode.MergeNone,
                             openFile=self.printingOptionsDlg.uiOpenFilesChk.isChecked(),
                             openFolder=self.printingOptionsDlg.uiOpenFolderChk.isChecked(),
                             dbm=self.dbm,
                             parent=self)

    def openSearchFilmDialog(self):
        """Run method that performs all the real work"""
        # show the dialog
        self.searchFilmDlg.show()
        #self.filmSelectionDlg.uiFilmNumberEdit.setFocus()
        # Run the dialog event loop and See if OK was pressed
        if self.searchFilmDlg.exec_():
            # QMessageBox.warning(None, "FilmNumber", self.searchFilmDlg.generateSearchQuery())

            model = QSqlRelationalTableModel(self, self.dbm.db)
            model.setTable("film")
            searchMode, searchFilter = self.searchFilmDlg.generateSearchFilter()
            # QMessageBox.information(self, "info", searchFilter)

            model.setFilter(searchFilter)
            model.select()
            rc = model.rowCount()
            while (model.canFetchMore()):
                model.fetchMore()
                rc = model.rowCount()

            query = QSqlQuery(self.dbm.db)
            searchQuery = "select filmnummer, substr(filmnummer, 3, 8) as 'ohne_hersteller', flugdatum, anzahl_bilder, weise, art_ausarbeitung, militaernummer, militaernummer_alt from film where {0}".format(searchFilter)
            query.exec_(searchQuery)
            querySize = 0
            while(query.next()):
                querySize += 1
            query.seek(-1)
            # if model.rowCount():
            if querySize > 0:
                # open film selection list dialog
                searchListDlg = APISFilmSelectionList(self.iface, model, self.dbm, self.imageRegistry, parent=self)
                searchListDlg.uiFilmCountLbl.setText(str(rc))
                searchListDlg.uiFilmCountDescriptionLbl.setText(u"Film gefunden" if model.rowCount() == 1 else u"Filme gefunden")
                searchListDlg.uiFilmSearchModeLbl.setText(searchMode)
                res = searchListDlg.loadFilmListBySqlQuery(query)
                if res and searchListDlg.exec_():
                    #QMessageBox.warning(None, "FilmNumber", unicode(searchListDlg.filmNumberToLoad))
                    self.loadRecordByKeyAttribute("filmnummer", searchListDlg.filmNumberToLoad)
            else:
                QMessageBox.warning(self, u"Film Suche", u"Keine Ergebnisse mit den angegebenen Suchkriterien.")
                self.openSearchFilmDialog()

            #QMessageBox.warning(None, "FilmNumber", u"{0}, rows: {1}".format(self.searchFilmDlg.generateSearchQuery(), model.rowCount()))

            # Get Search String/Query
            #if not self.loadRecordByKeyAttribute("filmnummer", self.filmSelectionDlg.filmNumber()):
                #self.openFilmSelectionDialog()

    def openFilmSelectionDialog(self):
        """Run method that performs all the real work"""
        self.filmSelectionDlg.show()
        self.filmSelectionDlg.uiFilmNumberEdit.setFocus()
        if self.filmSelectionDlg.exec_():
            if not self.loadRecordByKeyAttribute("filmnummer", self.filmSelectionDlg.filmNumber()):
                self.openFilmSelectionDialog()

    def openNewFilmDialog(self):
        """Run method that performs all the real work"""
        self.newFilmDlg.show()
        if self.newFilmDlg.exec_():
            self.addNewFilm(self.newFilmDlg.flightDate(), self.newFilmDlg.useLastEntry(), self.newFilmDlg.producer(), self.newFilmDlg.producerCode())

    def openEditWeatherDialog(self):
        self.editWeatherDlg.setWeatherCode(self.uiWeatherCodeEdit.text())
        self.editWeatherDlg.show()

        if self.editWeatherDlg.exec_():
            self.uiWeatherCodeEdit.setText(self.editWeatherDlg.weatherCode())
            #self.uiWeatherPTxt.setPlainText(self.editWeatherDlg.weatherDescription())

    def generateWeatherCode(self):
        weatherDescription = self._generateWeatherCode(self.uiWeatherCodeEdit.text())
        self.uiWeatherPTxt.setPlainText(weatherDescription)

    def _generateWeatherCode(self, weatherCode):
        categories = ["Low Cloud Amount", "Visibility Kilometres", "Low Cloud Height", "Weather", "Remarks Mission", "Remarks Weather"]
        query = QSqlQuery(self.dbm.db)
        pos = 0
        help = 0
        weatherDescription = ""
        for c in weatherCode:
            qryStr = "select description from wetter where category = '{0}' and code = '{1}' limit 1".format(categories[pos - help], c)
            query.exec_(qryStr)
            query.first()
            fn = query.value(0)
            if pos <= 5:
                weatherDescription += categories[pos] + ': ' + fn
                if pos < 5:
                    weatherDescription += '\n'
            else:
                weatherDescription += '; ' + fn

            if pos >= 5:
                help += 1
            pos += 1
        return weatherDescription

    def openSystemTableEditorDialog(self, table, updateEditor):
        if self.dbm:
            self.systemTableEditorDlg = APISAdvancedInputDialog(self.dbm, table, False, parent=self)

            if self.systemTableEditorDlg.tableExists:
                if self.systemTableEditorDlg.exec_():
                    # See if OK was pressed
                    # rec = self.systemTableEditorDlg.getRecord()
                    # Update updateEditor
                    # self.setupComboBox(self.uiProjectSelectionCombo, "projekt", 0, None)
                    self.updateComboBox(updateEditor)

            else:
                QMessageBox.warning(self, "Tabelle nicht vorhanden", "Die Tabelle {0} ist in der APIS Datenbank nicht vorhanden".format(table))

        else:
            QMessageBox.warning(self, "Warning Database", "Die APIS Datenbank konnte nicht gefunden werden.")

    def updateComboBox(self, updateEditor):
        updateEditor.model().select()
        tv = updateEditor.view()
        tv.resizeRowsToContents()
        tv.resizeColumnsToContents()
        scroll = 0 if updateEditor.count() <= updateEditor.maxVisibleItems() else QApplication.style().pixelMetric(
            QStyle.PM_ScrollBarExtent)
        tv.setMinimumWidth(tv.horizontalHeader().length() + scroll)
        updateEditor.setCurrentIndex(updateEditor.count() - 1)
        if updateEditor.validator():
            updateEditor.lineEdit().setValidator(
                InListValidator([updateEditor.itemText(i) for i in range(updateEditor.count())],
                                updateEditor.lineEdit(), None, self))

    def openFlightPathDialog(self, filmList, toClose=None):
        self.flightPathDlg.viewFilms(filmList)  # DEBUG
        self.flightPathDlg.show()

        if self.flightPathDlg.exec_():
            #TODO load Data in TOC, Close Windows
            if toClose:
                toClose.close()
            self.close()

    def openSiteSelectionListDialog(self):
        if self.uiFilmModeCombo.currentIndex() == APISFilm.VERTICAL:
            fromTable = "luftbild_senk_fp"
        elif self.uiFilmModeCombo.currentIndex() == APISFilm.OBLIQUE:
            fromTable = "luftbild_schraeg_fp"

        query = QSqlQuery(self.dbm.db)
        query.prepare("SELECT fundortnummer, flurname, katastralgemeinde, fundgewinnung, sicherheit FROM fundort WHERE fundortnummer IN (SELECT DISTINCT fo.fundortnummer FROM fundort fo, {0} WHERE fo.geometry IS NOT NULL AND {0}.geometry IS NOT NULL AND {0}.filmnummer = '{1}' AND Intersects({0}.geometry, fo.geometry) AND fo.ROWID IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'fundort' AND search_frame = {0}.geometry)) ORDER BY katastralgemeindenummer, land, fundortnummer_nn".format(fromTable, self.uiCurrentFilmNumberEdit.text()))
        query.exec_()
        info = u"gefunden, die vom Film {0} abgedeckt/geschnitten werden.".format(self.uiCurrentFilmNumberEdit.text())
        res = self.siteSelectionListDlg.loadSiteListBySpatialQuery(query, info)
        if res:
            self.siteSelectionListDlg.show()
            if self.siteSelectionListDlg.exec_():
                pass

    def openImageSelectionListDialog(self):
        if self.uiFilmModeCombo.currentIndex() == APISFilm.VERTICAL:
            fromTable = 'luftbild_senk_cp'
            spatialIndicator = 'massstab'
        elif self.uiFilmModeCombo.currentIndex() == APISFilm.OBLIQUE:
            fromTable = 'luftbild_schraeg_cp'
            spatialIndicator = 'radius'

        query = QSqlQuery(self.dbm.db)
        query.prepare("SELECT cp.bildnummer AS bildnummer, cp.filmnummer AS filmnummer, cp.{2} AS mst_radius, f.weise AS weise, f.art_ausarbeitung AS art FROM {0} AS cp, film AS f WHERE cp.filmnummer = '{1}' AND f.filmnummer = '{1}'".format(fromTable, self.uiCurrentFilmNumberEdit.text(), spatialIndicator))
        query.exec_()
        res = self.imageSelectionListDlg.loadImageListBySqlQuery(query)
        if res:
            self.imageSelectionListDlg.show()
            if self.imageSelectionListDlg.exec_():
                pass

    def addNewFilm(self, flightDate, useLastEntry, producer, producerCode):
        self.initalLoad = True
        self.addMode = True
        self.startEditMode()
        row = self.model.rowCount()
        self.mapper.submit()
        while (self.model.canFetchMore()):
            self.model.fetchMore()

        self.model.insertRow(row)

        if useLastEntry:
            #copy last row
            for c in range(1, self.model.columnCount()):
                value = self.model.data(self.model.createIndex(row - 1, c))
                self.model.setData(self.model.createIndex(row, c), value)
                editor = self.mapper.mappedWidgetAt(c)

                if editor and not (value == 'NULL' or value == ''):
                    cName = editor.metaObject().className()
                    if (cName == "QLineEdit" or cName == "QDateEdit") and editor.isReadOnly():
                        pass
                    else:
                        editor.setStyleSheet("{0} {{background-color: rgb(153, 204, 255);}}".format(editor.metaObject().className()))
                        self.editorsEdited.append(editor)

        self.mapper.setCurrentIndex(row)

        self.uiTotalFilmCountLbl.setText(str(self.model.rowCount()))
        self.uiFlightDate.setDate(flightDate)
        #self.uiFlightQgsDate.setDate(flightDate)
        self.uiProducerEdit.setText(producer)
        self.uiArchiveCombo.lineEdit().setText(producer)
        if not useLastEntry:
            self.uiWeatherCodeEdit.setText("9990X")

        #now = QDateTime.currentDateTime()
        now = QDate.currentDate()
        self.uiInitalEntryDate.setDate(now)
        #self.uiInitalEntryQgsDate.setDateTime(now)
        self.uiLastChangesDate.setDate(now)
        #self.uiLastChangesQgsDate.setDateTime(now)
        self.uiFilmModeCombo.setEnabled(True)

        #Filmnummer
        hh = producerCode
        yyyy = flightDate.toString("yyyy")
        mm = flightDate.toString("MM")

        query = QSqlQuery(self.dbm.db)
        qryStr = "select max(filmnummer_nn) from film where filmnummer_hh_jjjj_mm = '{0}{1}{2}' limit 1".format(hh, yyyy, mm)
        query.exec_(qryStr)
        query.first()
        fn = query.value(0)

        if isinstance(fn, int):
            nn = str(fn + 1).zfill(2)
        else:
            nn = "01"
        self.uiCurrentFilmNumberEdit.setText("{0}{1}{2}{3}".format(hh, yyyy, mm, nn))

        self.initalLoad = False

    def removeNewFilm(self):
        self.initalLoad = True
        row = self.mapper.currentIndex()
        self.model.removeRow(row)
        self.model.submitAll()
        while (self.model.canFetchMore()):
            self.model.fetchMore()
        self.uiTotalFilmCountLbl.setText(str(self.model.rowCount()))
        self.mapper.toLast()
        self.initalLoad = False

    def saveEdits(self):
        # Check Mandatory fields
        flag = False
        for mEditor in self.mandatoryEditors:
            cName = mEditor.metaObject().className()
            if cName == 'QLineEdit':
                value = mEditor.text()
            elif cName == 'QComboBox':
                value = mEditor.lineEdit().text()
            if value.strip() == "":
                flag = True
                mEditor.setStyleSheet("{0} {{background-color: rgb(240, 160, 160);}}".format(cName))
                if mEditor not in self.editorsEdited:
                    self.editorsEdited.append(mEditor)
            else:
                if mEditor in self.editorsEdited:
                    mEditor.setStyleSheet("{0} {{background-color: rgb(153, 204, 255);}}".format(cName))
                #else:
                    #mEditor.setStyleSheet("")
        if flag:
            QMessageBox.warning(self, self.tr(u"Benötigte Felder Ausfüllen"), self.tr(u"Füllen Sie bitte alle Felder aus, die mit * gekennzeichnet sind."))
            return False

        #saveToModel
        currIdx = self.mapper.currentIndex()
        #now = QDateTime.currentDateTime()
        now = QDate.currentDate()
        self.uiLastChangesDate.setDate(now)
        #self.uiLastChangesQgsDate.setDateTime(now)

        res = self.mapper.submit()

        if not res:
            sqlError = self.mapper.model().lastError()
            QMessageBox.information(self, "Submit", u"Error: {0}, {1}".format(res, sqlError.text()))

        while (self.model.canFetchMore()):
            self.model.fetchMore()

        self.mapper.setCurrentIndex(currIdx)
        self.endEditMode()
        return True

    def cancelEdit(self):
        if self.editMode:
            result = QMessageBox.question(self,
                                          self.tr(u"Änderungen wurden vorgenommen!"),
                                          self.tr(u"Möchten Sie die Änerungen speichern?"),
                                          QMessageBox.Yes | QMessageBox.No,
                                          QMessageBox.Yes)

            #save or not save
            if result == QMessageBox.Yes:
                res = self.saveEdits()
                if res:
                    return True
                else:
                    return False
            elif result == QMessageBox.No:
                if self.addMode:
                    self.removeNewFilm()

                self.mapper.setCurrentIndex(self.mapper.currentIndex())
                self.endEditMode()
                return True

    def startEditMode(self):
        self.editMode = True
        self.enableItemsInLayout(self.uiTopHorizontalLayout, False)
        self.enableItemsInLayout(self.uiBottomHorizontalLayout, False)
        self.uiOkBtn.setEnabled(False)
        self.uiSaveBtn.setEnabled(True)
        self.uiCancelBtn.setEnabled(True)
        self.editorsEdited = []

    def endEditMode(self):
        self.editMode = False
        self.addMode = False
        self.enableItemsInLayout(self.uiTopHorizontalLayout, True)
        self.enableItemsInLayout(self.uiBottomHorizontalLayout, True)
        self.uiOkBtn.setEnabled(True)
        self.uiSaveBtn.setEnabled(False)
        self.uiCancelBtn.setEnabled(False)
        for editor in self.editorsEdited:
            cName = editor.metaObject().className()
            if (cName == "QLineEdit" or cName == "QDateEdit") and editor.isReadOnly():
                editor.setStyleSheet("{0} {{background-color: rgb(218, 218, 218);}}".format(cName))
            else:
                editor.setStyleSheet("")
        self.editorsEdited = []

        self.uiFilmModeCombo.setEnabled(False)

    def showEvent(self, evnt):
        # QMessageBox.information(self, "info", "db requires update: {0}".format(self.dbm.dbRequiresUpdate))

        if self.dbm.dbRequiresUpdate:
            self.initalLoad = True
            for editor in [self.uiArchiveCombo, self.uiCameraCombo, self.uiFilmMakeCombo, self.uiCopyrightCombo, self.uiProjectSelectionCombo, self.newFilmDlg.uiProducerCombo]:
                self.updateComboBox(editor)
            currIdx = self.mapper.currentIndex()
            self.model.select()
            while (self.model.canFetchMore()):
                self.model.fetchMore()
            self.mapper.setCurrentIndex(currIdx)
            self.dbm.dbRequiresUpdate = False
            self.initalLoad = False
class RectangleMapTool(QgsMapToolEmitPoint):
    def __init__(self, iface, dbm, imageRegistry, apisLayer):
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        self.dbm = dbm
        self.imageRegistry = imageRegistry
        self.apisLayer = apisLayer

        QgsMapToolEmitPoint.__init__(self, self.canvas)

        self.rubberBand = QgsRubberBand(self.canvas,
                                        QgsWkbTypes.PolygonGeometry)
        self.rubberBand.setColor(QColor(255, 128, 0, 255))
        self.rubberBand.setFillColor(QColor(255, 128, 0, 128))
        self.rubberBand.setWidth(1)

        self.topic = 'image'  # 'image', 'site', 'findspot'

        self.reset()

        self.imageSelectionListDlg = APISImageSelectionList(
            self.iface,
            self.dbm,
            self.imageRegistry,
            self.apisLayer,
            parent=self.iface.mainWindow())
        self.siteSelectionListDlg = APISSiteSelectionList(
            self.iface,
            self.dbm,
            self.imageRegistry,
            self.apisLayer,
            parent=self.iface.mainWindow())
        self.findspotSelectionListDlg = APISFindspotSelectionList(
            self.iface,
            self.dbm,
            self.imageRegistry,
            self.apisLayer,
            parent=self.iface.mainWindow())

        self.worker = None

    def setTopic(self, topic):
        self.topic = topic

    def deactivate(self):
        super(RectangleMapTool, self).deactivate()
        self.deactivated.emit()

    def activate(self):
        self.canvas.setCursor(
            QgsApplication.getThemeCursor(QgsApplication.Cursor.Select))

    def reset(self):
        self.startPoint = self.endPoint = None
        self.isEmittingPoint = False
        self.rubberBand.reset(QgsWkbTypes.PolygonGeometry)

    def canvasPressEvent(self, e):
        self.startPoint = self.toMapCoordinates(e.pos())
        self.endPoint = self.startPoint
        self.isEmittingPoint = True
        self.showRect(self.startPoint, self.endPoint)

    def canvasReleaseEvent(self, e):
        self.isEmittingPoint = False
        r = self.rectangle()

        #QMessageBox.warning(None, "Bild", u"Punkt: {0}".format(epsg))

        srcCrs = self.canvas.mapSettings().destinationCrs()
        destCrs = QgsCoordinateReferenceSystem(
            4312, QgsCoordinateReferenceSystem.EpsgCrsId)
        ct = QgsCoordinateTransform(srcCrs, destCrs, QgsProject.instance())
        if r is None:
            #QMessageBox.warning(None, "Bild", u"Punkt: {0}".format(self.endPoint.wellKnownText()))

            p = QgsGeometry.fromPointXY(self.endPoint)
            p.transform(ct)
            #QMessageBox.warning(None, "Bild", u"Punkt: {0}".format(self.endPoint.x()))
            #self.openImageSelectionListDialogByLocation(p.asWkt(8))
            self.startWorker(p.asWkt(8))

        else:
            #.warning(None, "Bild", u"Rechteck: {0}, {1}, {2}, {3}".format(r.xMinimum(), r.yMinimum(), r.xMaximum(), r.yMaximum()))

            r2 = QgsGeometry.fromRect(r)
            r2.transform(ct)
            #QMessageBox.warning(None, "Bild", u"Polygon: {0}".format(r2.asoWkt(8)))
            #self.openImageSelectionListDialogByLocation(r2.asoWkt(8))
            self.startWorker(r2.asWkt(8))
            #print "Rectangle:", r.xMinimum(), r.yMinimum(), r.xMaximum(), r.yMaximum()

    def openImageSelectionListDialogByLocation(self, query):
        # progressMessageBar = self.iface.messageBar().createMessage("Luftbilder werden gesucht")
        # progress = QProgressBar()
        # progress.setMinimum(0)
        # progress.setMaximum(0)
        # progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter)
        # progressMessageBar.layout().addWidget(progress)
        # self.iface.messageBar().pushWidget(progressMessageBar, self.iface.messageBar().INFO)

        res = self.imageSelectionListDlg.loadImageListBySqlQuery(query)
        if res:
            self.imageSelectionListDlg.show()
            if self.imageSelectionListDlg.exec_():
                pass

        self.rubberBand.hide()

    def openSiteSelectionListDialogByLocation(self, query):
        info = u"gefunden für den ausgewählten Bereich."
        res = self.siteSelectionListDlg.loadSiteListBySpatialQuery(query, info)
        if res:
            self.siteSelectionListDlg.show()
            if self.siteSelectionListDlg.exec_():
                pass

        self.rubberBand.hide()

    def openFindspotSelectionListDialogByLocation(self, query):
        info = u"gefunden für den ausgewählten Bereich."
        res = self.findspotSelectionListDlg.loadFindspotListBySpatialQuery(
            query, info)
        if res:
            self.findspotSelectionListDlg.show()
            #if self.findspotSelectionListDlg.exec_():
            #    pass

        self.rubberBand.hide()

    def canvasMoveEvent(self, e):
        if not self.isEmittingPoint:
            return

        self.endPoint = self.toMapCoordinates(e.pos())
        self.showRect(self.startPoint, self.endPoint)

    def showRect(self, startPoint, endPoint):
        self.rubberBand.reset(QgsWkbTypes.PolygonGeometry)
        if startPoint.x() == endPoint.x() or startPoint.y() == endPoint.y():
            return

        point1 = QgsPointXY(startPoint.x(), startPoint.y())
        point2 = QgsPointXY(startPoint.x(), endPoint.y())
        point3 = QgsPointXY(endPoint.x(), endPoint.y())
        point4 = QgsPointXY(endPoint.x(), startPoint.y())

        self.rubberBand.addPoint(point1, False)
        self.rubberBand.addPoint(point2, False)
        self.rubberBand.addPoint(point3, False)
        self.rubberBand.addPoint(point4, True)  # true to update canvas
        self.rubberBand.show()

    def rectangle(self):
        if self.startPoint is None or self.endPoint is None:
            return None
        elif self.startPoint.x() == self.endPoint.x() or self.startPoint.y(
        ) == self.endPoint.y():
            return None

        return QgsRectangle(self.startPoint, self.endPoint)

    def startWorker(self, geometry):
        # create a new worker instance

        if self.worker is None:

            worker = Worker(self.dbm, geometry, self.topic)

            # configure the QgsMessageBar
            messageBar = self.iface.messageBar().createMessage(
                u'Räumliche Suche wird durchgeführt ...', )
            progressBar = QProgressBar()
            progressBar.setMinimum(0)
            progressBar.setMaximum(0)
            progressBar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
            cancelButton = QPushButton()
            cancelButton.setText('Cancel')
            cancelButton.clicked.connect(self.killWorker)
            messageBar.layout().addWidget(progressBar)
            self.progressBar = progressBar
            messageBar.layout().addWidget(cancelButton)
            self.iface.messageBar().pushWidget(messageBar, Qgis.Info)
            self.messageBar = messageBar

            # start the worker in a new thread
            thread = QThread(self)
            worker.moveToThread(thread)
            worker.finished.connect(self.workerFinished)
            worker.error.connect(self.workerError)
            #worker.progress.connect(progressBar.setValue)
            thread.started.connect(worker.run)
            thread.start()
            self.thread = thread
            self.worker = worker

    def killWorker(self):
        self.worker.kill()
        self.progressBar.setMaximum(100)
        self.progressBar.setValue(100)

    def workerFinished(self, query, topic):
        # clean up the worker and thread
        self.worker.deleteLater()
        self.thread.quit()
        self.thread.wait()
        self.thread.deleteLater()
        # remove widget from message bar
        self.iface.messageBar().popWidget(self.messageBar)
        if query is not None:
            # report the result
            #query = result
            if not self.worker.killed:
                if topic == 'image':
                    self.openImageSelectionListDialogByLocation(query)
                elif topic == 'site':
                    self.openSiteSelectionListDialogByLocation(query)
                elif topic == 'findspot':
                    self.openFindspotSelectionListDialogByLocation(query)
            else:
                self.rubberBand.hide()
            #self.iface.messageBar().pushMessage('Result')
        else:
            # notify the user that something went wrong
            self.iface.messageBar().pushMessage(
                'Something went wrong! See the message log for more information.',
                level=Qgis.Critical,
                duration=3)

        self.worker = None

    def workerError(self, e, exception_string):
        QgsMessageLog.logMessage(
            'APIS Search Worker thread raised an exception:\n'.format(
                exception_string),
            tag='APIS',
            level=Qgis.Critical)
Exemplo n.º 3
0
class APISSearch(QDockWidget, FORM_CLASS):
    def __init__(self, iface, dbm, imageRegistry, apisLayer, parent=None):
        """Constructor."""
        super(APISSearch, self).__init__(parent)

        self.iface = iface
        self.dbm = dbm
        self.imageRegistry = imageRegistry
        self.apisLayer = apisLayer

        self.setupUi(self)

        self.settings = QSettings(QSettings().value("APIS/config_ini"),
                                  QSettings.IniFormat)

        self.iface.addDockWidget(Qt.RightDockWidgetArea, self)
        self.hide()

        self.visibilityChanged.connect(self.onVisibilityChanged)

        #For Lale Mode
        if self.settings.value("APIS/disable_site_and_findspot", "0") != "1":
            self.uiSearchTab.setTabEnabled(1, True)
            self.uiSearchSiteRBtn.setEnabled(True)
            self.uiSearchFindspotRBtn.setEnabled(True)
        else:
            self.uiSearchTab.setCurrentIndex(0)
            self.uiSearchTab.setTabEnabled(1, False)
            self.uiSearchImageRBtn.setChecked(True)
            self.uiSearchSiteRBtn.setEnabled(False)
            self.uiSearchFindspotRBtn.setEnabled(False)

        # Spatial Search

        self.searchTargetBGrp = QButtonGroup(self)
        self.searchTargetBGrp.addButton(self.uiSearchImageRBtn)
        self.searchTargetBGrp.addButton(self.uiSearchSiteRBtn)
        self.searchTargetBGrp.addButton(self.uiSearchFindspotRBtn)
        self.uiSearchImageRBtn.setChecked(True)

        self.spatialSearchModeBGrp = QButtonGroup(self)
        self.spatialSearchModeBGrp.addButton(self.uiSearchModeIntersectsRBtn)
        self.spatialSearchModeBGrp.addButton(self.uiSearchModeCoversRBtn)
        self.uiSearchModeIntersectsRBtn.setChecked(True)

        self.spatialSearchTool = RectangleMapTool(self.iface, self.dbm,
                                                  self.imageRegistry,
                                                  self.apisLayer)
        #self.spatialSearchTool.setCursor(Qt.CrossCursor)
        self.spatialSearchTool.setButton(self.uiSpatialSearchBtn)
        self.uiSpatialSearchBtn.setCheckable(True)
        self.uiSpatialSearchBtn.toggled.connect(self.toggleSpatialSearch)

        self.uiSearchByMapLayerCombo.setFilters(
            QgsMapLayerProxyModel.HasGeometry)
        self.uiFilterByMapLayerCombo.setFilters(
            QgsMapLayerProxyModel.HasGeometry)
        self.uiSearchByMapLayerBtn.clicked.connect(
            self.spatialSearchByMapLayer)

        self.uiSearchImageRBtn.toggled.connect(self.setSearchTopic)
        self.uiSearchSiteRBtn.toggled.connect(self.setSearchTopic)
        self.uiSearchFindspotRBtn.toggled.connect(self.setSearchTopic)

        self.setupSearchComboBox(
            self.uiSearchByCadastralCommunityCombo, "katastralgemeinden",
            "katastralgemeindenummer, katastralgemeindename",
            "katastralgemeindenummer, katastralgemeindename", 1)
        self.uiSearchByCadastralCommunityCombo.currentIndexChanged.connect(
            self.joinRowValues)
        self.uiSearchByCadastralCommunityBtn.clicked.connect(
            self.spatialSearchByCadastralCommunity)
        self.uiSearchByCadastralCommunityCombo.lineEdit(
        ).returnPressed.connect(self.spatialSearchByCadastralCommunity)

        self.setupSearchComboBox(self.uiSearchByCountryCombo, "osm_boundaries",
                                 "code, name", "code", 1)
        self.uiSearchByCountryCombo.currentIndexChanged.connect(
            self.joinRowValues)

        # Attributive Search

        # Fundort

        self.setupSearchComboBox(self.uiSearchSiteNumberCombo, "fundort",
                                 "fundortnummer", "land, fundortnummer_nn")
        self.setupSearchComboBox(self.uiSearchFilmNumberCombo, "film",
                                 "filmnummer", "filmnummer")
        self.setupSearchComboBox(self.uiSearchProjectNameCombo, "fundort",
                                 "filmnummer_projekt", "filmnummer_projekt")

        self.uiSearchSiteNumberBtn.clicked.connect(
            self.attributeSearchSiteBySiteNumber)
        self.uiSearchSiteNumberCombo.lineEdit().returnPressed.connect(
            self.attributeSearchSiteBySiteNumber)

        self.uiSearchFilmNumberBtn.clicked.connect(
            self.attributeSearchSiteByFilmNumber)
        self.uiSearchFilmNumberCombo.lineEdit().returnPressed.connect(
            self.attributeSearchSiteByFilmNumber)

        self.uiSearchYearBtn.clicked.connect(
            self.attributeSearchSiteByFilmsOfYear)
        self.uiSearchYearDate.lineEdit().returnPressed.connect(
            self.attributeSearchSiteByFilmsOfYear)

        self.uiSearchProjectNameBtn.clicked.connect(
            self.attributeSearchSiteByProjectName)
        self.uiSearchProjectNameCombo.lineEdit().returnPressed.connect(
            self.attributeSearchSiteByProjectName)

        # Fundstelle

        self.uiSearchFindspotBtn.setEnabled(True)
        self.uiSearchFindspotBtn.clicked.connect(self.attributeSearchFindspot)

        # Datierung

        self.uiPeriodChk.setCheckState(Qt.Unchecked)
        self.uiPeriodDetailsChk.setCheckState(Qt.Unchecked)

        self.uiPeriodDetailsChk.setEnabled(False)

        self.uiPeriodCombo.setEnabled(False)
        self.uiPeriodDetailsCombo.setEnabled(False)

        self.uiPeriodChk.stateChanged.connect(self.onPeriodChkChanged)
        self.uiPeriodDetailsChk.stateChanged.connect(
            self.onPeriodDetailsChkChanged)

        self.uiTimeCombo.currentIndexChanged.connect(self.loadPeriodContent)
        self.uiPeriodCombo.currentIndexChanged.connect(
            self.loadPeriodDetailsContent)
        #self.uiPeriodDetailsCombo.currentIndexChanged.connect(False)

        self.setupSearchComboBox(self.uiTimeCombo, "zeit", "zeit", "zeit")

        # Kultur

        self.setupSearchComboBox(self.uiCultureCombo, "kultur", "name", "name")

        # Befundart
        self.setupSearchComboBox(self.uiFindTypeCombo, "befundart",
                                 "befundart", "befundart")
        self.uiFindTypeCombo.currentIndexChanged.connect(
            self.loadFindTypeDtailsContent)

        self.uiFindTypeDetailsChk.setCheckState(Qt.Unchecked)
        self.uiFindTypeDetailsCombo.setEnabled(False)
        self.uiFindTypeDetailsChk.stateChanged.connect(
            self.onFindTypeDetailsChkChanged)

    def loadPeriodContent(self, idx):
        time = self.uiTimeCombo.currentText()
        self.setupSearchComboBoxByQuery(
            self.uiPeriodCombo,
            u"SELECT DISTINCT periode FROM zeit WHERE zeit ='{0}'".format(
                time))

    def loadPeriodDetailsContent(self, idx):
        time = self.uiTimeCombo.currentText()
        period = self.uiPeriodCombo.currentText()
        self.setupSearchComboBoxByQuery(
            self.uiPeriodDetailsCombo,
            u"SELECT DISTINCT periode_detail FROM zeit WHERE zeit = '{0}' AND periode = '{1}'"
            .format(time, period))

    def loadFindTypeDtailsContent(self, idx):
        findType = self.uiFindTypeCombo.currentText()
        self.setupSearchComboBoxByQuery(
            self.uiFindTypeDetailsCombo,
            u"SELECT DISTINCT befundart_detail FROM befundart WHERE befundart ='{0}'"
            .format(findType))

    def onPeriodChkChanged(self, state):
        if state:
            self.uiPeriodCombo.setEnabled(True)
            self.uiPeriodDetailsChk.setEnabled(True)
        else:
            self.uiPeriodCombo.setEnabled(False)
            self.uiPeriodDetailsChk.setCheckState(Qt.Unchecked)
            self.uiPeriodDetailsChk.setEnabled(False)

    def onPeriodDetailsChkChanged(self, state):
        if state:
            self.uiPeriodDetailsCombo.setEnabled(True)
        else:
            self.uiPeriodDetailsCombo.setEnabled(False)

    def onFindTypeDetailsChkChanged(self, state):
        if state:
            self.uiFindTypeDetailsCombo.setEnabled(True)
        else:
            self.uiFindTypeDetailsCombo.setEnabled(False)

    def setSearchTopic(self):
        if self.uiSearchImageRBtn.isChecked():
            self.spatialSearchTool.setTopic('image')
        elif self.uiSearchSiteRBtn.isChecked():
            self.spatialSearchTool.setTopic('site')
        elif self.uiSearchFindspotRBtn.isChecked():
            self.spatialSearchTool.setTopic('findspot')

    def toggleSpatialSearch(self, isChecked):
        if isChecked:
            self.iface.mapCanvas().setMapTool(self.spatialSearchTool)
            self.iface.messageBar().pushMessage(
                u"APIS räumliche Suche",
                u"Klicken Sie auf die Karte oder ziehen Sie ein Rechteck auf, um in der ausgewählten Kategorie zu suchen!",
                level=Qgis.Info)
        else:
            self.iface.mapCanvas().unsetMapTool(self.spatialSearchTool)
            self.iface.actionPan().trigger()
            self.iface.messageBar().clearWidgets()

    def spatialSearchByMapLayer(self):
        if self.uiSpatialSearchBtn.isChecked():
            self.uiSpatialSearchBtn.toggle()
        if self.uiSearchByMapLayerCombo.count() < 1:
            return
        vlayer = self.uiSearchByMapLayerCombo.currentLayer()
        selection = vlayer.selectedFeatures()
        if len(selection) > 0:

            i = 0
            for feature in selection:
                if i == 0:
                    searchGeometry = QgsGeometry.fromWkt(
                        feature.geometry().asWkt())
                    searchGeometry.convertToMultiType()
                else:
                    searchGeometry.addPartGeometry(feature.geometry())
                i += 1
                #searchGeometry = searchGeometry.combine(feature.geometry())

            srcCrs = vlayer.crs()
            destCrs = QgsCoordinateReferenceSystem(
                4312, QgsCoordinateReferenceSystem.EpsgCrsId)
            ct = QgsCoordinateTransform(srcCrs, destCrs, QgsProject.instance())
            searchGeometry.transform(ct)

            #QMessageBox.warning(None, "WKT", "{0}".format(searchGeometry.geometry().partCount()))

            epsg = 4312
            query = QSqlQuery(self.dbm.db)
            if self.uiSearchModeCoversRBtn.isChecked():
                mode = "Covers"
            else:
                mode = "Intersects"

            if self.uiSearchImageRBtn.isChecked():
                # LuftbildSuche
                query.prepare(
                    "SELECT cp.bildnummer AS bildnummer, cp.filmnummer AS filmnummer, cp.radius AS mst_radius, f.weise AS weise, f.art_ausarbeitung AS art FROM film AS f, luftbild_schraeg_cp AS cp WHERE f.filmnummer = cp.filmnummer AND cp.bildnummer IN (SELECT fp.bildnummer FROM luftbild_schraeg_fp AS fp WHERE NOT IsEmpty(fp.geometry) AND {2}(GeomFromText('{0}',{1}), fp.geometry) AND rowid IN (SELECT rowid FROM SpatialIndex WHERE f_table_name = 'luftbild_schraeg_fp' AND search_frame = GeomFromText('{0}',{1}) )) UNION ALL SELECT  cp_s.bildnummer AS bildnummer, cp_S.filmnummer AS filmnummer, cp_s.massstab, f_s.weise, f_s.art_ausarbeitung FROM film AS f_s, luftbild_senk_cp AS cp_s WHERE f_s.filmnummer = cp_s.filmnummer AND cp_s.bildnummer IN (SELECT fp_s.bildnummer FROM luftbild_senk_fp AS fp_s WHERE NOT IsEmpty(fp_s.geometry) AND {2}(GeomFromText('{0}',{1}), fp_s.geometry) AND rowid IN (SELECT rowid FROM SpatialIndex WHERE f_table_name = 'luftbild_senk_fp' AND search_frame = GeomFromText('{0}',{1}) ) ) ORDER BY filmnummer, bildnummer"
                    .format(searchGeometry.asWkt(), epsg, mode))
                query.exec_()
                self.imageSelectionListDlg = APISImageSelectionList(
                    self.iface,
                    self.dbm,
                    self.imageRegistry,
                    self.apisLayer,
                    parent=self.iface.mainWindow())
                res = self.imageSelectionListDlg.loadImageListBySqlQuery(query)
                if res:
                    self.imageSelectionListDlg.show()
                    if self.imageSelectionListDlg.exec_():
                        pass

            elif self.uiSearchSiteRBtn.isChecked():
                # Fundortsuche
                query.prepare(
                    "SELECT fundortnummer, flurname, katastralgemeinde, fundgewinnung, sicherheit FROM fundort WHERE fundortnummer IN (SELECT DISTINCT fo.fundortnummer FROM fundort fo WHERE NOT IsEmpty(fo.geometry) AND NOT IsEmpty(GeomFromText('{0}',{1})) AND {2}(GeomFromText('{0}',{1}), fo.geometry) AND fo.ROWID IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'fundort' AND search_frame = GeomFromText('{0}',{1}) ) ) ORDER BY katastralgemeindenummer, land, fundortnummer_nn"
                    .format(searchGeometry.asWkt(), epsg, mode))
                query.exec_()
                self.siteSelectionListDlg = APISSiteSelectionList(
                    self.iface, self.dbm, self.imageRegistry, self.apisLayer,
                    self.iface.mainWindow())
                info = u"gefunden, die von den selektierten Features aus dem Layer '{0}' abgedeckt/geschnitten werden.".format(
                    vlayer.name())
                res = self.siteSelectionListDlg.loadSiteListBySpatialQuery(
                    query, info)
                if res:
                    self.siteSelectionListDlg.show()
                    if self.siteSelectionListDlg.exec_():
                        pass

            elif self.uiSearchFindspotRBtn.isChecked():
                #Fundstellensuche
                query.prepare(
                    "SELECT fs.fundortnummer, fs.fundstellenummer, fo.katastralgemeinde, datierung_zeitstufe, datierung_periode, datierung_periode_detail, befundart, befundart_detail, fs.sicherheit, kultur FROM fundstelle fs, fundort fo WHERE fs.fundortnummer = fo.fundortnummer AND (fs.fundortnummer || '.' || fs.fundstellenummer) IN (SELECT DISTINCT (fst.fundortnummer || '.' || fst.fundstellenummer) AS fsn FROM fundstelle fst WHERE NOT IsEmpty(fst.geometry) AND NOT IsEmpty(GeomFromText('{0}',{1})) AND {2}(GeomFromText('{0}', {1}), fst.geometry) AND fst.ROWID IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'fundstelle' AND search_frame = GeomFromText('{0}', {1}))) ORDER BY fo.katastralgemeindenummer, fo.land, fo.fundortnummer_nn, fs.fundstellenummer"
                    .format(searchGeometry.asWkt(), epsg, mode))

                query.exec_()
                self.findspotSelectionListDlg = APISFindspotSelectionList(
                    self.iface,
                    self.dbm,
                    self.imageRegistry,
                    self.apisLayer,
                    parent=self.iface.mainWindow())
                res = self.findspotSelectionListDlg.loadFindspotListBySpatialQuery(
                    query)
                if res:
                    self.findspotSelectionListDlg.show()
                    #if self.findspotSelectionListDlg.exec_():
                    #    pass

            #QMessageBox.warning(None, "Query", "Query finished")

        else:
            self.iface.messageBar().pushMessage(
                u"Error",
                u"Bitte selektieren sie zumindest ein Feature im Layer {0} für die Suche!"
                .format(vlayer.name()),
                level=Qgis.Warning,
                duration=5)

    def spatialSearchByCadastralCommunity(self):
        if self.uiSpatialSearchBtn.isChecked():
            self.uiSpatialSearchBtn.toggle()

        searchValue = self.uiSearchByCadastralCommunityCombo.lineEdit().text()
        searchValues = [
            sV.strip().replace("'", "").replace("\"", "")
            for sV in searchValue.split(",")
            if len(sV.strip().replace("'", "").replace("\"", "")) > 0
        ]
        if len(searchValues) < 1:
            return
        likeSearch = False
        if len(searchValues) == 1:
            likeSearch = True
        searchValuesStr = u"'"
        searchValuesStr += u"', '".join(searchValues)
        searchValuesStr += u"'"
        #if searchValuesStr
        #QMessageBox.warning(None, self.tr(u"Katastralgemeinde"), u"{0}".format(searchValuesStr))

        epsg = 4312
        query = QSqlQuery(self.dbm.db)

        if likeSearch:
            ccSearchStr = u"SELECT Transform(kg.geometry, {1}) as geometry FROM katastralgemeinden kg WHERE kg.katastralgemeindenummer LIKE '{0}' OR kg.katastralgemeindename LIKE '{0}' AND NOT IsEmpty(kg.geometry)".format(
                searchValuesStr.replace("'", "%"), epsg)
        else:
            ccSearchStr = u"SELECT Transform(kg.geometry, {1}) as geometry FROM katastralgemeinden kg WHERE kg.katastralgemeindenummer IN ({0}) OR kg.katastralgemeindename IN ({0}) AND NOT IsEmpty(kg.geometry)".format(
                searchValuesStr, epsg)

        #QMessageBox.warning(None, self.tr(u"Katastralgemeinde"), u"{0}".format(ccSearchStr))

        if self.uiSearchImageRBtn.isChecked():
            # LuftbildSuche
            query.prepare(
                u"SELECT cp.bildnummer AS bildnummer, cp.filmnummer AS filmnummer, cp.radius AS mst_radius, f.weise AS weise, f.art_ausarbeitung AS art FROM film f, luftbild_schraeg_cp cp WHERE f.filmnummer = cp.filmnummer AND cp.bildnummer IN (SELECT fp.bildnummer FROM luftbild_schraeg_fp fp, ({0}) cc WHERE NOT IsEmpty(fp.geometry) AND Intersects(cc.geometry, fp.geometry) AND fp.rowid IN (SELECT rowid FROM SpatialIndex WHERE f_table_name = 'luftbild_schraeg_fp' AND search_frame = cc.geometry )) UNION ALL SELECT  cp_s.bildnummer AS bildnummer, cp_S.filmnummer AS filmnummer, cp_s.massstab, f_s.weise, f_s.art_ausarbeitung FROM film f_s, luftbild_senk_cp cp_s WHERE f_s.filmnummer = cp_s.filmnummer AND cp_s.bildnummer IN (SELECT fp_s.bildnummer FROM luftbild_senk_fp fp_s, ({0}) cc WHERE NOT IsEmpty(fp_s.geometry) AND Intersects(cc.geometry, fp_s.geometry) AND fp_s.rowid IN (SELECT rowid FROM SpatialIndex WHERE f_table_name = 'luftbild_senk_fp' AND search_frame = cc.geometry ) ) ORDER BY filmnummer, bildnummer"
                .format(ccSearchStr))
            query.exec_()
            self.imageSelectionListDlg = APISImageSelectionList(
                self.iface, self.dbm, self.imageRegistry, self.apisLayer)
            res = self.imageSelectionListDlg.loadImageListBySqlQuery(query)
            if res:
                self.imageSelectionListDlg.show()
                if self.imageSelectionListDlg.exec_():
                    pass
        elif self.uiSearchSiteRBtn.isChecked():
            # Fundortsuche
            # old query (pnt/pol)
            # qryStr = "SELECT fundortnummer, flurname, katastralgemeinde, fundgewinnung, sicherheit FROM fundort_pnt WHERE fundort_pnt.fundortnummer IN (SELECT DISTINCT fundort_pol.fundortnummer FROM fundort_pol WHERE NOT IsEmpty(fundort_pol.geometry) AND NOT IsEmpty(GeomFromText('{0}',{1})) AND Intersects(GeomFromText('{0}',{1}), fundort_pol.geometry) AND fundort_pol.ROWID IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'fundort_pol' AND search_frame = GeomFromText('{0}',{1}) ) ) ORDER BY SUBSTR(fundortnummer, 0, 3), CAST(SUBSTR(fundortnummer, 5) AS INTEGER)".format(searchGeometry.asWkt(), epsg)
            query.prepare(
                u"SELECT fundortnummer, flurname, katastralgemeinde, fundgewinnung, sicherheit FROM fundort WHERE fundortnummer IN (SELECT DISTINCT fo.fundortnummer FROM fundort fo, ({0}) cc WHERE NOT IsEmpty(fo.geometry) AND Intersects(cc.geometry, fo.geometry) AND fo.ROWID IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'fundort' AND search_frame = cc.geometry ) ) ORDER BY katastralgemeindenummer, land, fundortnummer_nn"
                .format(ccSearchStr))
            query.exec_()
            self.siteSelectionListDlg = APISSiteSelectionList(
                self.iface, self.dbm, self.imageRegistry, self.apisLayer,
                self.iface.mainWindow())
            #info = u"gefunden, die von den selektierten Features aus dem Layer '{0}' abgedeckt/geschnitten werden.".format(vlayer.name())
            res = self.siteSelectionListDlg.loadSiteListBySpatialQuery(query)
            if res:
                self.siteSelectionListDlg.show()
                if self.siteSelectionListDlg.exec_():
                    pass

        elif self.uiSearchFindspotRBtn.isChecked():
            #Fundstellen
            query.prepare(
                u"SELECT fs.fundortnummer, fs.fundstellenummer, fo.katastralgemeinde, datierung_zeitstufe, datierung_periode, datierung_periode_detail, befundart, befundart_detail, fs.sicherheit, kultur FROM fundstelle fs, fundort fo WHERE fs.fundortnummer = fo.fundortnummer AND (fs.fundortnummer || '.' || fs.fundstellenummer) IN (SELECT DISTINCT (fst.fundortnummer || '.' || fst.fundstellenummer) AS fsn FROM fundstelle fst, ({0}) cc WHERE NOT IsEmpty(fst.geometry) AND Intersects(cc.geometry, fst.geometry) AND fst.ROWID IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'fundstelle' AND search_frame = cc.geometry)) ORDER BY fo.katastralgemeindenummer, fo.land, fo.fundortnummer_nn, fs.fundstellenummer"
                .format(ccSearchStr))
            query.exec_()
            self.findspotSelectionListDlg = APISFindspotSelectionList(
                self.iface,
                self.dbm,
                self.imageRegistry,
                self.apisLayer,
                parent=self.iface.mainWindow())
            res = self.findspotSelectionListDlg.loadFindspotListBySpatialQuery(
                query)
            if res:
                self.findspotSelectionListDlg.show()
                #if self.findspotSelectionListDlg.exec_():
                #    pass

    def attributeSearchSiteBySiteNumber(self):
        # Fundortsuche
        siteNumberSearchValue = self.uiSearchSiteNumberCombo.lineEdit().text()
        searchValues = [
            sV.strip().replace("'", "").replace("\"", "")
            for sV in siteNumberSearchValue.split(",")
            if len(sV.strip().replace("'", "").replace("\"", "")) > 0
        ]
        if len(searchValues) < 1:
            return
        likeSearch = False
        if len(searchValues) == 1:
            # has Quotes
            if len(siteNumberSearchValue
                   ) > 1 and siteNumberSearchValue.startswith(
                       "'") or siteNumberSearchValue.startswith(
                           "\"") and siteNumberSearchValue.endswith(
                               "'") or siteNumberSearchValue.endswith("\""):
                likeSearch = False
            else:
                likeSearch = True

        searchValuesStr = u", ".join(u"'{0}'".format(sV)
                                     for sV in searchValues)
        #QMessageBox.warning(None, self.tr(u"Fundorte"), u"{0}, {1}".format(likeSearch, searchValuesStr))

        query = QSqlQuery(self.dbm.db)
        if likeSearch:
            query.prepare(
                u"SELECT fundortnummer, flurname, katastralgemeinde, fundgewinnung, sicherheit FROM fundort WHERE fundortnummer LIKE '{0}' ORDER BY katastralgemeindenummer, land, fundortnummer_nn"
                .format(searchValuesStr.replace("'", "%")))
        else:
            query.prepare(
                u"SELECT fundortnummer, flurname, katastralgemeinde, fundgewinnung, sicherheit FROM fundort WHERE fundortnummer IN ({0}) ORDER BY katastralgemeindenummer, land, fundortnummer_nn"
                .format(searchValuesStr))

        # qryStr = "select cp.bildnummer as bildnummer, cp.filmnummer as filmnummer, cp.radius as mst_radius, f.weise as weise, f.art_ausarbeitung as art from film as f, luftbild_schraeg_cp AS cp WHERE f.filmnummer = cp.filmnummer AND cp.bildnummer IN (SELECT fp.bildnummer FROM luftbild_schraeg_fp AS fp WHERE NOT IsEmpty(fp.geometry) AND Intersects(GeomFromText('{0}',{1}), fp.geometry) AND rowid IN (SELECT rowid FROM SpatialIndex WHERE f_table_name = 'luftbild_schraeg_fp' AND search_frame = GeomFromText('{0}',{1}) )) UNION ALL SELECT  cp_s.bildnummer AS bildnummer, cp_S.filmnummer AS filmnummer, cp_s.massstab, f_s.weise, f_s.art_ausarbeitung FROM film AS f_s, luftbild_senk_cp AS cp_s WHERE f_s.filmnummer = cp_s.filmnummer AND cp_s.bildnummer IN (SELECT fp_s.bildnummer FROM luftbild_senk_fp AS fp_s WHERE NOT IsEmpty(fp_s.geometry) AND Intersects(GeomFromText('{0}',{1}), fp_s.geometry) AND rowid IN (SELECT rowid FROM SpatialIndex WHERE f_table_name = 'luftbild_senk_fp' AND search_frame = GeomFromText('{0}',{1}) ) ) ORDER BY filmnummer, bildnummer".format(searchGeometry.asWkt(), epsg)
        query.exec_()
        self.siteSelectionListDlg = APISSiteSelectionList(
            self.iface, self.dbm, self.imageRegistry, self.apisLayer,
            self.iface.mainWindow())
        info = u"gefunden, deren Fundortnummer die Suche '{0}' enthält.".format(
            siteNumberSearchValue)
        res = self.siteSelectionListDlg.loadSiteListBySpatialQuery(query, info)
        if res:
            self.siteSelectionListDlg.show()
            if self.siteSelectionListDlg.exec_():
                pass

    def attributeSearchSiteByFilmNumber(self):
        #Fundortsuche
        filmNumber = self.uiSearchFilmNumberCombo.lineEdit().text()
        filmType = self.isFilm(filmNumber)

        if filmType == u"senk.":
            fromTable = "luftbild_senk_fp"
        elif filmType == u"schräg":
            fromTable = "luftbild_schraeg_fp"
        else:
            QMessageBox.warning(
                None, self.tr(u"Film Nummer"),
                u"Es gibt keinen Film mit der Filmnummer {0}.".format(
                    filmNumber))
            return

        query = QSqlQuery(self.dbm.db)
        query.prepare(
            "SELECT fundortnummer, flurname, katastralgemeinde, fundgewinnung, sicherheit FROM fundort WHERE fundortnummer IN (SELECT DISTINCT fo.fundortnummer FROM fundort fo, {0} WHERE fo.geometry IS NOT NULL AND {0}.geometry IS NOT NULL AND {0}.filmnummer = '{1}' AND Intersects({0}.geometry, fo.geometry) AND fo.ROWID IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'fundort' AND search_frame = {0}.geometry)) ORDER BY katastralgemeindenummer, land, fundortnummer_nn"
            .format(fromTable, filmNumber))
        query.exec_()
        self.siteSelectionListDlg = APISSiteSelectionList(
            self.iface, self.dbm, self.imageRegistry, self.apisLayer,
            self.iface.mainWindow())
        info = u"gefunden, die vom Film {0} abgedeckt/geschnitten werden.".format(
            filmNumber)
        res = self.siteSelectionListDlg.loadSiteListBySpatialQuery(query, info)
        if res:
            self.siteSelectionListDlg.show()
            if self.siteSelectionListDlg.exec_():
                pass

    def attributeSearchSiteByFilmsOfYear(self):
        year = self.uiSearchYearDate.date().toString('yyyy')

        query = QSqlQuery(self.dbm.db)
        query.prepare(
            "SELECT fundortnummer, flurname, katastralgemeinde, fundgewinnung, sicherheit FROM fundort WHERE fundortnummer IN (SELECT DISTINCT fo.fundortnummer FROM fundort fo, (SELECT filmnummer, geometry FROM luftbild_schraeg_fp WHERE NOT IsEmpty(luftbild_schraeg_fp.geometry) AND substr(luftbild_schraeg_fp.filmnummer, 3, 4) = '{0}' UNION ALL SELECT filmnummer, geometry FROM luftbild_senk_fp WHERE NOT IsEmpty(luftbild_senk_fp.geometry) AND substr(luftbild_senk_fp.filmnummer, 3, 4) = '{0}') luftbild WHERE NOT IsEmpty(fo.geometry) AND Intersects(luftbild.geometry, fo.geometry) AND fo.ROWID IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'fundort' AND search_frame = luftbild.geometry)) ORDER BY katastralgemeindenummer, land, fundortnummer_nn"
            .format(year))

        query.exec_()
        self.siteSelectionListDlg = APISSiteSelectionList(
            self.iface, self.dbm, self.imageRegistry, self.apisLayer,
            self.iface.mainWindow())
        info = u"gefunden, die von Filmen aus dem Jahr {0} abgedeckt/geschnitten werden.".format(
            year)
        res = self.siteSelectionListDlg.loadSiteListBySpatialQuery(query, info)
        if res:
            self.siteSelectionListDlg.show()
            if self.siteSelectionListDlg.exec_():
                pass

    def attributeSearchSiteByProjectName(self):
        # Fundortsuche
        projectNameSearchValue = self.uiSearchProjectNameCombo.lineEdit().text(
        )
        query = QSqlQuery(self.dbm.db)
        query.prepare(
            "SELECT fundortnummer, flurname, katastralgemeinde, fundgewinnung, sicherheit FROM fundort WHERE filmnummer_projekt LIKE '%{0}%' ORDER BY katastralgemeindenummer, land, fundortnummer_nn"
            .format(projectNameSearchValue))
        query.exec_()
        self.siteSelectionListDlg = APISSiteSelectionList(
            self.iface, self.dbm, self.imageRegistry, self.apisLayer,
            self.iface.mainWindow())
        info = u"gefunden, deren Projektbezeichnung die Suche '{0}' enthält.".format(
            projectNameSearchValue)
        res = self.siteSelectionListDlg.loadSiteListBySpatialQuery(query, info)
        if res:
            self.siteSelectionListDlg.show()
            if self.siteSelectionListDlg.exec_():
                pass

    def attributeSearchFindspot(self):
        query = QSqlQuery(self.dbm.db)
        #query.prepare("SELECT fs.fundortnummer, fs.fundstellenummer, fo.katastralgemeinde, datierung, befundart, befundart_detail, fs.sicherheit, kultur FROM fundstelle fs, fundort fo WHERE fs.fundortnummer = fo.fundortnummer AND (fs.fundortnummer || '.' || fs.fundstellenummer) IN (SELECT DISTINCT (fst.fundortnummer || '.' || fst.fundstellenummer) AS fsn FROM fundstelle fst WHERE NOT IsEmpty(fst.geometry) AND NOT IsEmpty(GeomFromText('{0}',{1})) AND Intersects(GeomFromText('{0}', {1}), fst.geometry) AND fst.ROWID IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'fundstelle' AND search_frame = GeomFromText('{0}', {1}))) ORDER BY fo.katastralgemeindenummer, fo.land, fo.fundortnummer_nn, fs.fundstellenummer".format(searchGeometry.asWkt(), epsg))
        # query.prepare("SELECT fundortnummer, fundstellenummer, datierung, befundart, befundart_detail, sicherheit, kultur FROM fundstelle WHERE (fundortnummer || '.' || fundstellenummer) as id1 IN (SELECT DISTINCT (fs.fundortnummer || '.' || fs.fundstellenummer) as id2 FROM fundstelle fs WHERE NOT IsEmpty(fs.geometry) AND NOT IsEmpty(GeomFromText('{0}',{1})) AND Intersects(GeomFromText('{0}',{1}), fs.geometry) AND fs.ROWID IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'fundstelle' AND search_frame = GeomFromText('{0}',{1}) ) )".format(searchGeometry.asWkt(), epsg))

        info = "gefunden"
        whereClause = []
        whereClause.append(u"fs.fundortnummer = fo.fundortnummer")
        if self.uiDatingGrp.isChecked(
        ) and self.uiTimeCombo.currentIndex() >= 0:
            #whereClause.append(u"substr(datierung, 1, pos1-1) = '{0}'".format(self.uiTimeCombo.currentText()))  # zeit
            whereClause.append(u"datierung_zeitstufe = '{0}'".format(
                self.uiTimeCombo.currentText()))
            info += " | Zeitstufe='{0}'".format(self.uiTimeCombo.currentText())
            if self.uiPeriodChk.isChecked(
            ) and self.uiPeriodCombo.currentIndex() >= 0:
                #whereClause.append(u"substr(datierung, pos1+1, pos2-1) = '{0}'".format(self.uiPeriodCombo.currentText()))  # periode
                whereClause.append(u"datierung_periode = '{0}'".format(
                    self.uiPeriodCombo.currentText()))
                info += ", Periode='{0}'".format(
                    self.uiPeriodCombo.currentText())
                if self.uiPeriodDetailsChk.isChecked(
                ) and self.uiPeriodDetailsCombo.currentIndex() >= 0:
                    #whereClause.append(u"substr(datierung, pos1+pos2+1, pos3-1) = '{0}'".format(self.uiPeriodDetailsCombo.currentText()))  # periode_detail
                    whereClause.append(
                        u"datierung_periode_detail = '{0}'".format(
                            self.uiPeriodDetailsCombo.currentText()))
                    info += ", Detail='{0}'".format(
                        self.uiPeriodDetailsCombo.currentText())
        if self.uiCultureGrp.isChecked(
        ) and self.uiCultureCombo.currentIndex() >= 0:
            whereClause.append(u"kultur = '{0}'".format(
                self.uiCultureCombo.currentText()))  # kultur
            info += " | Kultur='{0}'".format(self.uiCultureCombo.currentText())
        if self.uiFindTypeGrp.isChecked(
        ) and self.uiFindTypeCombo.currentIndex() >= 0:
            whereClause.append(u"befundart = '{0}'".format(
                self.uiFindTypeCombo.currentText()))  # befundart
            info += " | Befundart='{0}'".format(
                self.uiFindTypeCombo.currentText())
            if self.uiFindTypeDetailsChk.isChecked(
            ) and self.uiFindTypeDetailsCombo.currentIndex() >= 0:
                whereClause.append(u"instr(befundart_detail, '{0}')".format(
                    self.uiFindTypeDetailsCombo.currentText())
                                   )  # befundart_detail; je befundart_detail
                info += ", Detail='{0}'".format(
                    self.uiFindTypeDetailsCombo.currentText())
        if self.uiSpatialFilterGrp.isChecked(
        ) and self.uiFilterByMapLayerCombo.count(
        ) > 0 and self.uiFilterByMapLayerCombo.currentIndex() >= 0:
            #QMessageBox.warning(None, self.tr(u"findspot search"), u"{0}".format("Spatial Filter Activ"))
            vlayer = self.uiFilterByMapLayerCombo.currentLayer()
            selection = vlayer.selectedFeatures()
            if len(selection) > 0:
                i = 0
                for feature in selection:
                    if i == 0:
                        searchGeometry = QgsGeometry.fromWkt(
                            feature.geometry().asWkt())
                        searchGeometry.convertToMultiType()
                    else:
                        searchGeometry.addPartGeometry(feature.geometry())
                    i += 1
                    # searchGeometry = searchGeometry.combine(feature.geometry())

                srcCrs = vlayer.crs()
                destCrs = QgsCoordinateReferenceSystem(
                    4312, QgsCoordinateReferenceSystem.EpsgCrsId)
                ct = QgsCoordinateTransform(srcCrs, destCrs,
                                            QgsProject.instance())
                searchGeometry.transform(ct)
                whereClause.append(
                    u"(fs.fundortnummer || '.' || fs.fundstellenummer) IN (SELECT DISTINCT (fst.fundortnummer || '.' || fst.fundstellenummer) AS fsn FROM fundstelle fst WHERE NOT IsEmpty(fst.geometry) AND NOT IsEmpty(GeomFromText('{0}',{1})) AND Intersects(GeomFromText('{0}', {1}), fst.geometry) AND fst.ROWID IN (SELECT ROWID FROM SpatialIndex WHERE f_table_name = 'fundstelle' AND search_frame = GeomFromText('{0}', {1})))"
                    .format(searchGeometry.asWkt(), 4312))
                info += " | Räumlicher Filter Selektion in '{0}'".format(
                    vlayer.name())
        #whereClause.append("")  # spatial

        whereStr = u" AND ".join(whereClause)

        #qryStr = u"SELECT fundortnummer, fundstellenummer, datierung_zeitstufe, datierung_periode, datierung_periode_detail, befundart, befundart_detail, sicherheit, kultur FROM (SELECT *, instr(datierung,',') AS pos1, instr(substr(datierung, instr(datierung,',')+1), ',') AS pos2, instr(substr(datierung, instr(datierung,',')+instr(substr(datierung, instr(datierung,',')+1), ',')+1),  ',') AS pos3 FROM fundstelle) WHERE {0}".format(whereStr)
        #qryStr = u"SELECT fundortnummer, fundstellenummer, datierung_zeitstufe, datierung_periode, datierung_periode_detail, befundart, befundart_detail, sicherheit, kultur FROM fundstelle WHERE {0}".format(whereStr)
        qryStr = u"SELECT fs.fundortnummer, fs.fundstellenummer, fo.katastralgemeinde, datierung_zeitstufe, datierung_periode, datierung_periode_detail, befundart, befundart_detail, fs.sicherheit, kultur FROM fundstelle fs, fundort fo WHERE {0} ORDER BY fo.land, fo.katastralgemeindenummer, fo.fundortnummer_nn, fs.fundstellenummer".format(
            whereStr)

        # QMessageBox.warning(None, self.tr(u"findspot search"), u"{0}".format(qryStr))

        # return
        query.prepare(qryStr)
        query.exec_()
        self.findspotSelectionListDlg = APISFindspotSelectionList(
            self.iface,
            self.dbm,
            self.imageRegistry,
            self.apisLayer,
            parent=self.iface.mainWindow())
        res = self.findspotSelectionListDlg.loadFindspotListBySpatialQuery(
            query, info)
        if res:
            self.findspotSelectionListDlg.show()
            # if self.findspotSelectionListDlg.exec_():
            #    pass

    def isFilm(self, filmNumber):
        # check if filmNumber is a filmNumber in film Table
        query = QSqlQuery(self.dbm.db)
        query.prepare("SELECT weise FROM film WHERE filmnummer = '{0}'".format(
            filmNumber))
        query.exec_()
        query.first()
        return query.value(0)

    def setupSearchComboBox(self, editor, table, column, order, modelcolumn=0):
        model = QSqlQueryModel(self)
        model.setQuery(
            "SELECT DISTINCT {0} FROM {1} ORDER BY {2}".format(
                column, table, order), self.dbm.db)

        tv = QTableView()
        editor.setView(tv)

        tv.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        tv.setSelectionMode(QAbstractItemView.SingleSelection)
        tv.setSelectionBehavior(QAbstractItemView.SelectRows)
        tv.setAutoScroll(False)

        editor.setModel(model)

        editor.setModelColumn(modelcolumn)
        editor.setInsertPolicy(QComboBox.NoInsert)

        tv.resizeColumnsToContents()
        tv.resizeRowsToContents()
        tv.verticalHeader().setVisible(False)
        tv.horizontalHeader().setVisible(True)
        # tv.setMinimumWidth(tv.horizontalHeader().length())
        tv.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        # FIXME PyQt5 AutoCompletion
        #editor.setAutoCompletion(True)
        editor.setCurrentIndex(-1)

    def setupSearchComboBoxByQuery(self, editor, query, modelcolumn=0):
        model = QSqlQueryModel(self)
        model.setQuery(query, self.dbm.db)

        tv = QTableView()
        editor.setView(tv)

        tv.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        #tv.setSelectionMode(QAbstractItemView.MultiSelection)
        tv.setSelectionMode(QAbstractItemView.SingleSelection)
        tv.setSelectionBehavior(QAbstractItemView.SelectRows)
        tv.setAutoScroll(False)

        editor.setModel(model)

        editor.setModelColumn(modelcolumn)
        editor.setInsertPolicy(QComboBox.NoInsert)

        tv.resizeColumnsToContents()
        tv.resizeRowsToContents()
        tv.verticalHeader().setVisible(False)
        tv.horizontalHeader().setVisible(True)
        # tv.setMinimumWidth(tv.horizontalHeader().length())
        tv.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        # FIXME PyQt5 AutoCompletion
        #editor.setAutoCompletion(True)
        editor.setCurrentIndex(-1)

    def onVisibilityChanged(self, isVisible):
        #QMessageBox.warning(None, self.tr(u"SearchDialog Visibility"), u"Visibility Search Dialog: {0}".format(visibility))
        if not isVisible:
            if self.uiSpatialSearchBtn.isChecked():
                self.uiSpatialSearchBtn.toggle()

    def joinRowValues(self, row):
        editor = self.sender()
        #QMessageBox.warning(None, self.tr(u"Katastralgemeinde"), u"{0}".format(editor))
        record = editor.model().record(row)
        values = []
        for i in range(record.count()):
            values.append(record.value(i))
        editor.lineEdit().setText(", ".join(values))