Exemple #1
0
    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()
Exemple #2
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 APISSystemTableEditor(QDialog, FORM_CLASS):
    def __init__(self, dbm, parent=None):
        """Constructor."""
        self.dbm = dbm
        super(APISSystemTableEditor, self).__init__(parent)

        self.table = None
        self.model = None
        self.insertQuery = None
        self.updateQuery = None
        self.deleteQuery = None
        self.inputDialog = None

        self.setupUi(self)

        self.uiEditBtn.setEnabled(False)
        self.uiRemoveBtn.setEnabled(False)

        self.rejected.connect(self.onClose)

        self.setupTable()

    def setupTable(self):
        self.uiSystemTableV.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.uiSystemTableV.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.uiSystemTableV.resizeColumnsToContents()
        self.uiSystemTableV.resizeRowsToContents()
        self.uiSystemTableV.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)

    def onSelectionChanged(self):
        if self.uiSystemTableV.selectionModel().hasSelection():
            self.uiEditBtn.setEnabled(True)
            self.uiRemoveBtn.setEnabled(True)
        else:
            self.uiEditBtn.setEnabled(False)
            self.uiRemoveBtn.setEnabled(False)

    def loadTable(self, table):
        # check if table in db
        if not DbHasTable(self.dbm.db, table):
            return False

        self.table = table
        self.dbm.createTriggerForSystemTable(table)
        # TODO: if returns FALSE then deactivate editing Capabilites + Wanring

        self.uiSysTableLbl.setText(self.table)

        self.model = QSqlRelationalTableModel(self, self.dbm.db)
        self.model.setTable(table)
        self.model.select()
        #rc = self.model.rowCount()
        while (self.model.canFetchMore()):
            self.model.fetchMore()
            #rc = self.model.rowCount()

        self.uiSystemTableV.setModel(self.model)
        self.uiSystemTableV.selectionModel().selectionChanged.connect(
            self.onSelectionChanged)
        self.onSelectionChanged()

        # dummyRecord holds field structure!
        dummyRecord = self.model.record()
        editors = []
        for fIdx in range(dummyRecord.count()):
            field = dummyRecord.field(fIdx)
            if field.name() != "ogc_fid":
                editors.append({
                    'name': field.name(),
                    'type': field.type(),
                    'lineEdit': QLineEdit(),
                    'default': None
                })

        # init input dialog
        self.inputDialog = APISInputDialog(editors, dummyRecord, parent=self)
        self.uiAddBtn.clicked.connect(self.addRecord)
        self.uiEditBtn.clicked.connect(
            self.editRecord
        )  # in EditMode: load current Value; try to update (but with trigger: only possible to update if not in use!!!)
        self.uiRemoveBtn.clicked.connect(self.removeRecord)
        return True

    def addRecord(self):
        if self.inputDialog.exec_():
            rec = self.inputDialog.getRecord()
            if not rec.isEmpty():
                res = self.model.insertRowIntoTable(rec)
                if res:
                    self.model.select()
                    self.dbm.dbRequiresUpdate = True
                else:
                    QMessageBox.warning(
                        self, "DB Fehler",
                        "Der folgende Fehler ist aufgetreten: {}".format(
                            self.model.lastError().text()))
        else:
            pass
        self.inputDialog.resetEditors()

    def editRecord(self):
        recIdx = self.uiSystemTableV.selectionModel().currentIndex().row()
        # Get current Record for index
        currRec = self.model.record(recIdx)
        # Set current Record in Dialog
        self.inputDialog.setEditors(currRec)
        if self.inputDialog.exec_():
            data = self.inputDialog.getData()
            # QMessageBox.information(None, "edited record", f"{data}")
            for key in data:
                currRec.setValue(key, data[key])
            if not currRec.isEmpty():
                res = self.model.updateRowInTable(recIdx, currRec)
                if res:
                    self.model.select()
                    self.dbm.dbRequiresUpdate = True
                else:
                    QMessageBox.warning(
                        self, "DB Fehler",
                        "Der folgende Fehler ist aufgetreten: {}".format(
                            self.model.lastError().text()))
        self.inputDialog.resetEditors()

    def removeRecord(self):
        #Check if one really wants to remove the entry!
        # Abfrage wirklich löschen
        header = u"Eintrag löschen"
        question = u"Möchten Sie den Eintrag wirklich aus der Datenbank löschen?"
        result = QMessageBox.question(self, header, question,
                                      QMessageBox.Yes | QMessageBox.No,
                                      QMessageBox.Yes)
        if result == QMessageBox.Yes:
            recIdx = self.uiSystemTableV.selectionModel().currentIndex().row()
            # QMessageBox.information(self, "Information", f"Current Idx {recIdx}")
            res = self.model.removeRow(recIdx)
            if res:
                self.model.select()
                self.dbm.dbRequiresUpdate = True
            else:
                QMessageBox.warning(
                    self, "DB Fehler",
                    "Der folgende Fehler ist aufgetreten: {}".format(
                        self.model.lastError().text()))

    def onClose(self):
        '''
        Run some actions when
        the user closes the dialog
        '''
        self.uiAddBtn.clicked.disconnect(self.addRecord)
        self.uiEditBtn.clicked.disconnect(self.editRecord)
        self.uiRemoveBtn.clicked.disconnect(self.removeRecord)
        self.inputDialog.deleteLater()
class APISAdvancedInputDialog(QDialog):
    def __init__(self,
                 dbm,
                 tableName,
                 showEntriesCombo,
                 modelColumnName=None,
                 excludeEntries=None,
                 parent=None):
        super(APISAdvancedInputDialog, self).__init__(parent)

        self.dbm = dbm
        self.tableName = tableName
        self.modelColumnName = modelColumnName
        self.showEntriesCombo = showEntriesCombo
        self.excludeEntries = excludeEntries

        self.valueToBeAdded = None
        self.editors = None
        self.record = None
        self.tableExists = False

        if self.prepairEditorsAndRecord():
            self.setupForm()
        else:
            pass
            # something went wrong preping

    def prepairEditorsAndRecord(self):
        if not DbHasTable(self.dbm.db, self.tableName):
            return False

        self.tableExists = True

        self.model = QSqlRelationalTableModel(self, self.dbm.db)
        self.model.setTable(self.tableName)
        self.model.select()
        while (self.model.canFetchMore()):
            self.model.fetchMore()

        self.record = self.model.record()
        self.editors = []
        for fIdx in range(self.record.count()):
            field = self.record.field(fIdx)
            if field.name() != "ogc_fid":
                self.editors.append({
                    'name': field.name(),
                    'type': field.type(),
                    'lineEdit': QLineEdit()
                })

        return True

    def setupForm(self):
        layout = QFormLayout()

        if self.showEntriesCombo:
            self.uiAvailableEntriesCombo = QComboBox()
            # populate (but exlude if exclude has elements)

            if self.excludeEntries and len(self.excludeEntries) > 0:
                self.model.setFilter("{0} NOT IN ({1})".format(
                    self.modelColumnName,
                    ",".join("'{0}'".format(i) for i in self.excludeEntries)))
                # QMessageBox.information(self, "info", "{0} NOT IN ({1})".format(self.modelColumnName, ",".join("'{0}'".format(i) for i in self.excludeEntries)))
                # self.model.select()
            self.model.removeColumn(0)
            self.setupComboBox(self.uiAvailableEntriesCombo,
                               self.model.fieldIndex(self.modelColumnName))
            layout.addRow(self.uiAvailableEntriesCombo)

            self.uiAddBtn = QPushButton("Hinzufügen")
            if self.uiAvailableEntriesCombo.count() < 1:
                self.uiAddBtn.setEnabled(False)
            self.uiAddBtn.clicked.connect(self.addInputToSelection)
            layout.addRow(self.uiAddBtn)

        for editor in self.editors:
            # QMessageBox.information(self, "info", "{}".format((editor["name"])))
            if editor["name"] != "ogc_fid":
                label = QLabel(editor["name"])
                # QMessageBox.information(None, "info", "{}".format(editor["type"]))
                if editor["type"] == QVariant.Int:
                    intVal = QIntValidator()
                    intVal.setBottom(0)
                    editor['lineEdit'].setValidator(intVal)
                layout.addRow(label, editor['lineEdit'])
                editor['lineEdit'].textEdited.connect(self.onTextEdited)

        self.uiSubmitBtn = QPushButton("Speichern")
        self.uiSubmitBtn.setEnabled(False)
        self.uiSubmitBtn.clicked.connect(self.saveInputAsQSqlRecord)
        layout.addRow(self.uiSubmitBtn)
        self.setLayout(layout)
        self.setWindowTitle("APIS Input Dialog")
        self.adjustSize()

    def onTextEdited(self, text):
        for editor in self.editors:
            if len(editor['lineEdit'].text().replace(" ", "")) == 0:
                self.uiSubmitBtn.setEnabled(False)
                return
        self.uiSubmitBtn.setEnabled(True)

    def addInputToSelection(self):
        self.setValueToBeAdded(self.uiAvailableEntriesCombo.currentText())
        self.accept()

    def setValueToBeAdded(self, value):
        self.valueToBeAdded = value

    def getValueToBeAdded(self):
        return self.valueToBeAdded

    def saveInputAsQSqlRecord(self):
        for editor in self.editors:
            self.record.setValue(editor["name"], editor['lineEdit'].text())
        if not self.record.isEmpty():
            result = self.model.insertRowIntoTable(self.record)
            if result:
                self.setValueToBeAdded(
                    self.record.field(self.modelColumnName).value())
                self.accept()
            else:
                QMessageBox.warning(
                    self, "DB Fehler",
                    "Der folgende Feheler ist aufgetreten: {}".format(
                        self.model.lastError().text()))
                self.reject()
        else:
            self.reject()

    def setupComboBox(self, editor, modelColumn):
        tv = QTableView()
        editor.setView(tv)

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

        editor.setModel(self.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)
Exemple #5
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(700, 600)
        MainWindow.setMinimumSize(QtCore.QSize(700, 600))
        MainWindow.setMaximumSize(QtCore.QSize(700, 600))
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.btn_call = QtWidgets.QPushButton(self.centralwidget)
        self.btn_call.setGeometry(QtCore.QRect(558, 480, 131, 71))
        self.btn_call.setObjectName("btn_call")
        font = QtGui.QFont()
        font.setPointSize(11)
        self.btn_call.setFont(font)
        self.btn_add = QtWidgets.QPushButton(self.centralwidget)
        self.btn_add.setGeometry(QtCore.QRect(10, 480, 89, 71))
        self.btn_add.setStyleSheet("")
        self.btn_add.setObjectName("btn_add")
        font = QtGui.QFont()
        font.setPointSize(11)
        self.btn_add.setFont(font)
        self.btn_delete = QtWidgets.QPushButton(self.centralwidget)
        self.btn_delete.setGeometry(QtCore.QRect(120, 480, 89, 71))
        self.btn_delete.setObjectName("btn_delete")
        font = QtGui.QFont()
        font.setPointSize(11)
        self.btn_delete.setFont(font)
        self.btn_search = QtWidgets.QPushButton(self.centralwidget)
        self.btn_search.setGeometry(QtCore.QRect(230, 480, 89, 71))
        self.btn_search.setObjectName("btn_search")
        font = QtGui.QFont()
        font.setPointSize(11)
        self.btn_search.setFont(font)
        self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit.setGeometry(QtCore.QRect(10, 434, 311, 31))
        font = QtGui.QFont()
        font.setPointSize(14)
        self.lineEdit.setFont(font)
        self.lineEdit.setObjectName("lineEdit")
        self.comboBox = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox.setGeometry(QtCore.QRect(335, 434, 121, 31))
        self.comboBox.setObjectName("comboBox")
        font = QtGui.QFont()
        font.setPointSize(11)
        self.comboBox.setFont(font)
        self.tableView = QtWidgets.QTableView(self.centralwidget)
        self.tableView.setGeometry(QtCore.QRect(10, 10, 681, 411))
        self.tableView.setObjectName("tableView")
        font = QtGui.QFont()
        font.setPointSize(11)
        self.tableView.setFont(font)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 700, 22))
        self.menubar.setObjectName("menubar")
        self.menuSetting = QtWidgets.QMenu(self.menubar)
        self.menuSetting.setObjectName("menuSetting")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.action_Invite_window = QtWidgets.QAction(MainWindow)
        self.action_Invite_window.setObjectName("action_Invite_window")
        # self.actionPlace_windows = QtWidgets.QAction(MainWindow)
        # self.actionPlace_windows.setObjectName("actionPlace_windows")
        self.actionini_py = QtWidgets.QAction(MainWindow)
        self.actionini_py.setObjectName("actionini_py")
        self.actionDestination = QtWidgets.QAction(MainWindow)
        self.actionDestination.setObjectName("actionDestination")
        self.actionDrop_tablel = QtWidgets.QAction(MainWindow)
        self.actionDrop_tablel.setObjectName("actionDrop_tablel")
        self.menuSetting.addAction(self.action_Invite_window)
        # self.menuSetting.addAction(self.actionPlace_windows)
        self.menuSetting.addAction(self.actionDestination)
        self.menuSetting.addAction(self.actionDrop_tablel)
        self.menuSetting.addSeparator()
        self.menuSetting.addAction(self.actionini_py)
        self.menubar.addAction(self.menuSetting.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        # เรียกฟังชั่นเพื่อโหลด model ลง table
        self.loadData()

        self.btn_add.clicked.connect(self.insertData)
        self.btn_delete.clicked.connect(self.deleteData)
        self.btn_call.clicked.connect(self.speak)
        self.btn_search.clicked.connect(self.searchData)
        self.actionDestination.triggered.connect(self.show_desDialog)

    def show_desDialog(self):
        self.desDialog.show()

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Simple Queue"))
        self.btn_call.setWhatsThis(
            _translate(
                "MainWindow",
                "<html><head/><body><p>คลิ๊กเพื่อเรียกคิวที่เลือกจากตารางคิว</p></body></html>"
            ))
        self.btn_call.setText(_translate("MainWindow", "เรียกคิว"))
        self.btn_add.setWhatsThis(
            _translate(
                "MainWindow",
                "<html><head/><body><p>คลิ๊กเพื่อเปิดเมนูการเพิ่มคิวด้วยตัวเอง</p></body></html>"
            ))
        self.btn_add.setText(_translate("MainWindow", "เพิ่มคิว"))
        self.btn_delete.setWhatsThis(
            _translate(
                "MainWindow",
                "<html><head/><body><p>คลิ๊กเพื่อลบคิวที่ป้อนค่าผิดออกจากตารางคิว</p></body></html>"
            ))
        self.btn_delete.setText(_translate("MainWindow", "ลบคิว"))
        self.btn_search.setWhatsThis(
            _translate(
                "MainWindow",
                "<html><head/><body><p>คลิ๊กเพื่อโหลดตารางคิวใหม่</p></body></html>"
            ))
        self.btn_search.setText(_translate("MainWindow", "ค้นหาคิว"))
        self.menuSetting.setTitle(_translate("MainWindow", "ตั้งค่า"))
        self.action_Invite_window.setText(
            _translate("MainWindow", "Call sentence setting"))
        #self.actionPlace_windows.setText(_translate("MainWindow", "Place sentence"))
        self.actionini_py.setText(_translate("MainWindow", "ini.py"))
        self.actionDestination.setText(
            _translate("MainWindow", "Destination setting"))
        self.actionDrop_tablel.setText(_translate("MainWindow", "Drop tablel"))

    def loadData(self):
        self.lineEdit.clear()
        self.lineEdit.setFocus()

        # สร้าง model เรียก data จาก database
        # ใช้ QSqlRelationalTableModel สำหรับตารางที่มีคีย์นอก
        self.model = QSqlRelationalTableModel()
        self.model.setTable('queue')
        self.model.setEditStrategy(QSqlTableModel.OnFieldChange)
        self.model.setHeaderData(0, Qt.Horizontal, 'ID')
        self.model.setHeaderData(1, Qt.Horizontal, "รายชื่อ")
        self.model.setHeaderData(2, Qt.Horizontal, "เวลาเพิ่มคิว")
        self.model.setHeaderData(3, Qt.Horizontal, "เวลาเรียกคิว")
        self.model.setHeaderData(4, Qt.Horizontal, "สถาณะคิว")
        self.model.setHeaderData(5, Qt.Horizontal, "ปลายทาง")
        self.model.setHeaderData(6, Qt.Horizontal, "Option")

        # ให้ column#5 เป็นคีย์นอกดึงตารางนอกมาแสดง
        self.model.setRelation(
            5, QSqlRelation("destination", "des_id", "des_name"))

        # เรียกใช้ model เรียกใช้ได้จากทุกที่ใน class ไม่ต้องเรียก loadData()
        self.model.select()

        # ให้ tableView เลือก data จาก model ไปแสดง
        self.tableView.setModel(self.model)
        self.tableView.setItemDelegate(QSqlRelationalDelegate(self.tableView))
        self.tableView.setColumnHidden(0, True)
        self.tableView.setCornerButtonEnabled(False)
        self.tableView.setSortingEnabled(True)
        self.tableView.setColumnWidth(1, 210)

        # เรียก fetchData เพื่อ fetch data เข้ามาใน model ให้หมด
        self.fetchData()

        # เมื่อ click ให้เลือกทั้งแถว
        self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)

        # สร้าง model เรียกตาราง destination แล้วยัดเข้า combobox
        self.desModel = QSqlQueryModel()
        selectQuery = QSqlQuery()
        selectQuery.prepare('SELECT des_name FROM destination')
        # print('QUERY = ' + str(selectQuery.lastQuery()))
        if selectQuery.exec():
            self.desModel.setQuery(selectQuery)
            # print('SELECT des_name COMPLETE')
            self.comboBox.setModel(self.desModel)
        else:
            print('SELECT FALSE = ' + selectQuery.lastError().text())

        # สร้าง obj ของ destination setting ไว้รอเรียก
        self.desDialog = QtWidgets.QDialog()
        self.ui = destination2.Ui_Dialog()
        self.ui.setupUi(self.desDialog)

        self.tableView.selectRow(0)

    def insertData(self):
        q_number = self.lineEdit.text()
        q_localtime = time.localtime()
        q_enter_time = time.strftime("%H:%M:%S", q_localtime)

        # q_number ต้องไม่ใช่ค่าเว้นวรรค และ ต้องไม่ใช่ค่าว่าง
        if not q_number.isspace() and q_number != '':

            # เรียก getDestination_id เพื่อหาค่า des_id เพื่อใช้ในคำสั่ง sql INSERT
            des_id = self.getDestination_id()
            try:
                insertQuery = QSqlQuery()
                insertQuery.prepare(
                    "INSERT INTO queue " + "(q_number,q_enter_time,des_id) " +
                    "VALUES " + f"('{q_number}','{q_enter_time}',{des_id})")
                print('Query = ' + insertQuery.lastQuery())

                if insertQuery.exec():
                    print('INSERT COMPLETE')
                    self.loadData()
                else:
                    print('INSERT FALSE = ' + insertQuery.lastError().text())

            except (Error) as e:
                print(
                    str(time.strftime("%H:%M:%S : ", time.localtime())) +
                    'ERROR :' + str(e))
        else:
            self.showDialog('กรุณากรอกหมายเลขที่จะเพิ่มก่อน')

    def getDestination_id(self):
        # สร้างมาเพื่อให้ return ค่า des_id ในตาราง destination กลับไป
        temp = self.comboBox.currentText()
        desModel = QSqlQueryModel()
        selectQuery = QSqlQuery()
        selectQuery.prepare('SELECT des_id,des_name From destination')
        if selectQuery.exec():
            desModel.setQuery(selectQuery)
            for i in range(desModel.rowCount()):
                if temp == desModel.index(i, 1).data():
                    return desModel.index(i, 0).data()
                else:
                    pass
        else:
            print('SELECT FALSE = ' + selectQuery.lastError().text())

    def insertDev(self):
        j = 10
        for i in range(50):
            q_number = random.randint(0, 100000)
            q_enter_time = f'18:{j}:00'
            des_id = 4
            insertQuery = QSqlQuery()
            insertQuery.prepare("INSERT INTO queue " +
                                "(q_number,q_enter_time,des_id) " + "VALUES " +
                                f"('{q_number}','{q_enter_time}',{des_id})")
            insertQuery.exec()
            self.model.select()
            j += 1
        print('insertDEV complete')

    def searchData(self):
        self.fetchData()
        q_number = self.lineEdit.text()
        totleRow = self.tableView.model().rowCount()
        foundStatus = False

        # q_number ต้องไม่ใช่ค่าเว้นวรรค และ ต้องไม่ใช่ค่าว่าง
        if not q_number.isspace() and q_number != '':
            i = 0
            for i in range(totleRow):

                # เก็บค่า q_number จาก tableView
                s_number = self.tableView.model().data(
                    self.tableView.model().index(i, 1))

                # เทียบค่า q_number ของ lineEdit กับ tableView
                if q_number == s_number:
                    # print('found this number.')
                    foundStatus = True
                    break
                else:
                    foundStatus = False

            if foundStatus == True:
                self.tableView.selectRow(i)
            else:
                self.showDialog('ค้นหมายเลข ' + q_number + ' ไม่พบ')

        else:
            self.showDialog('กรุณากรอกหมายเลขที่จะค้นก่อน')

    def deleteData(self):
        try:
            # เก็บค่า text จาก column
            current_row = self.tableView.selectedIndexes()
            current_itemUse = current_row[0]
            q_number = self.tableView.model().data(
                self.tableView.model().index(current_itemUse.row(), 1))
        except:
            self.showDialog('กรุณาเลือกหมายเลขที่จะลบก่อน')
            return

        if q_number == None:
            self.showDialog('เกิดข้อผิดพลาดระหว่างการลบ')
            self.model.select()
            return

        # ยืนยันการลบด้วย code 1024
        temp = self.confDelete(q_number)
        if temp == 1024:
            current_item = self.tableView.selectedIndexes()
            for index in current_item:
                self.model.removeRow(index.row())
            self.model.select()
            print('Record deleted.')
            self.showDialog('ลบหมายเลขแล้ว')
        else:
            print('User cancel delete this record.')

    def confDelete(self, q_number):
        # สร้าง dialog เพื่อยืนยันการลบ และ return code ยืนยันการลบด้วย code 1024
        confMsg = QtWidgets.QMessageBox()
        confMsg.setIcon(QtWidgets.QMessageBox.Critical)
        confMsg.setText('ยืนยันที่จะลบหมายเลข : ' + q_number)
        confMsg.setWindowTitle('แจ้งเตือนการลบ')
        confMsg.setStandardButtons(QtWidgets.QMessageBox.Ok
                                   | QtWidgets.QMessageBox.Cancel)
        reval = confMsg.exec_()
        return (reval)

    def btn_delClicked(self):
        button = QtGui.QGuiApplication.focusObject()
        index = self.tableView.indexAt(button.pos())
        if index.isValid():
            print(index.row(), index.column())

    def showDialog(self, message):
        msg = QtWidgets.QMessageBox()
        msg.setWindowTitle('แจ้งเตือน')
        msg.setIcon(QtWidgets.QMessageBox.Information)
        msg.setText(
            # message + str(time.strftime(" @ %H:%M:%S ", time.localtime())))
            message)
        msg.exec_()

    def speak(self):
        try:
            # เก็บค่า text จาก column
            current_row = self.tableView.selectedIndexes()
            current_inUse = current_row[0]
            q_numberText = self.tableView.model().data(
                self.tableView.model().index(current_inUse.row(), 1))
            des_idText = self.tableView.model().data(
                self.tableView.model().index(current_inUse.row(), 5))
        except:
            self.showDialog('กรุณาเลือกหมายเลขที่จะเรียกก่อน')
            return

        # ยืนยันการเรียกด้วย code 1024
        temp = self.confSpeak(q_numberText)
        q_localtime = time.localtime()
        q_call_time = time.strftime("%H:%M:%S", q_localtime)
        if temp == 1024:
            # pyttsx3 engine
            # engine = pyttsx3.init()
            # """ RATE"""
            # rate = engine.getProperty('rate')
            # #print (rate)
            # engine.setProperty('rate', 100)
            # """VOLUME"""
            # volume = engine.getProperty('volume')
            # #print (volume)
            # engine.setProperty('volume',1.0)
            # """VOICE"""
            # voices = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\TTS_THAI'
            # engine.setProperty('voice',voices)
            # engine.say('ขอเชิญหมายเลข' + q_numberText + 'ที่ช่อง' + des_idText + 'นะครับ')
            # print('result = :'+ q_numberText)
            # engine.runAndWait()
            # engine.stop()

            # gTTS engine
            speech_text = 'ขอเชิญคุณ ' + q_numberText + ' ที่ช่อง ' + des_idText + ' ค่ะ'
            tts = gTTS(speech_text, lang='th')
            tts.save('temp.mp3')
            speech_file = pyglet.media.load('temp.mp3', streaming=False)
            speech_file.play()
            sleep(speech_file.duration)  # prevent from killing
            os.remove('temp.mp3')  # remove temperory file

            try:
                insertQuery = QSqlQuery()
                insertQuery.prepare("UPDATE queue SET q_call_time = " +
                                    f"'{q_call_time}'" +
                                    " , q_call_status = 1 WHERE q_number = " +
                                    f"'{q_numberText}'")
                print('Query after speek ' + insertQuery.lastQuery())
                if insertQuery.exec():
                    print('UPDATE COMPLETE')
                    self.loadData()
                else:
                    print('UPDATE FALSE = ' + insertQuery.lastError().text())
            except (Error) as e:
                print('ERROR : ' + str(e))

        else:
            print('User decided cancel call.')

    def confSpeak(self, q_numberText):
        # สร้าง dialog เพื่อยืนยันการเรียกและ return code ยืนยันการเรียกด้วย code 1024
        confMsg = QtWidgets.QMessageBox()
        confMsg.setIcon(QtWidgets.QMessageBox.Warning)
        confMsg.setText('ยืนยันที่จะเรียกหมายเลข : ' + q_numberText)
        confMsg.setWindowTitle('แจ้งเตือน')
        confMsg.setStandardButtons(QtWidgets.QMessageBox.Ok
                                   | QtWidgets.QMessageBox.Cancel)
        reval = confMsg.exec_()
        return (reval)

    def fetchData(self):
        self.model.select()
        # fetch ข้อมูลจากตารางออกมาให้หมด มีผลตอนใช้ search
        while self.model.canFetchMore() == True:
            self.model.fetchMore()
        print('rowCoundt = ' + str(self.model.rowCount()))
        self.tableView.scrollToBottom()
Exemple #6
0
class APISSharding(QDialog, FORM_CLASS):

    shardingEditsSaved = pyqtSignal(bool)

    def __init__(self, iface, dbm, parent=None):
        """Constructor."""
        super(APISSharding, self).__init__(parent)
        self.iface = iface
        self.dbm = dbm
        self.setupUi(self)

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

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

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

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

        mViewPictures = QMenu()
        aViewPicturesPreview = mViewPictures.addAction(
            QIcon(
                os.path.join(QSettings().value("APIS/plugin_dir"), 'ui',
                             'icons', 'image.png')), "in Vorschau")
        aViewPicturesPreview.triggered.connect(self.viewPictures)
        aViewPicturesFolder = mViewPictures.addAction(
            QIcon(
                os.path.join(QSettings().value("APIS/plugin_dir"), 'ui',
                             'icons', 'image.png')), "in Ordner")
        aViewPicturesFolder.triggered.connect(self.openPictures)
        self.uiViewPicturesTBtn.setMenu(mViewPictures)
        self.uiViewPicturesTBtn.clicked.connect(
            self.uiViewPicturesTBtn.showMenu)

        mViewSketches = QMenu()
        aViewSketchesPreview = mViewSketches.addAction(
            QIcon(
                os.path.join(QSettings().value("APIS/plugin_dir"), 'ui',
                             'icons', 'sketch.png')), "in Vorschau")
        aViewSketchesPreview.triggered.connect(self.viewSketches)
        aViewSketchesFolder = mViewSketches.addAction(
            QIcon(
                os.path.join(QSettings().value("APIS/plugin_dir"), 'ui',
                             'icons', 'sketch.png')), "in Ordner")
        aViewSketchesFolder.triggered.connect(self.openSketches)
        self.uiViewSketchesTBtn.setMenu(mViewSketches)
        self.uiViewSketchesTBtn.clicked.connect(
            self.uiViewSketchesTBtn.showMenu)

        self.initalLoad = False

    def openSharding(self, siteNumber, shardingNumber):
        self.initalLoad = True
        self.siteNumber = siteNumber
        self.shardingNumber = shardingNumber

        #QMessageBox.warning(None, self.tr(u"Neu"), self.tr(u"{0}, {1}".format(siteNumber, shardingNumber)))

        # Setup sharding model
        self.model = QSqlRelationalTableModel(self, self.dbm.db)
        self.model.setTable("begehung")
        self.model.setFilter("fundortnummer='{0}' AND begehung='{1}'".format(
            self.siteNumber, self.shardingNumber))
        res = self.model.select()
        self.setupMapper()
        self.mapper.toFirst()
        self.setKgNameAndCode()

        self.initalLoad = False

    def setKgNameAndCode(self):
        query = QSqlQuery(self.dbm.db)
        qryStr = u"select CASE WHEN katastralgemeinde IS NULL AND katastralgemeindenummer IS NULL THEN '--' ELSE katastralgemeindenummer || ' - ' || katastralgemeinde END AS kg FROM fundort WHERE fundortnummer = '{0}'".format(
            self.siteNumber)
        query.exec_(qryStr)
        query.first()
        self.uiCadastralCommunityEdit.setText(query.value(0))

    def setupMapper(self):
        self.mapper = QDataWidgetMapper(self)
        self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
        self.mapper.setItemDelegate(ShardingDelegate())

        self.mapper.setModel(self.model)

        self.mandatoryEditors = [self.uiShardingDate]

        # LineEdits & PlainTextEdits
        self.intValidator = QIntValidator()
        self.doubleValidator = QDoubleValidator()

        self.lineEditMaps = {
            "fundortnummer": {
                "editor": self.uiSiteNumberEdit
            },
            "begehung": {
                "editor": self.uiShardingNumberEdit
            },
            "name": {
                "editor": self.uiNameEdit
            },
            "parzelle": {
                "editor": self.uiPlotPTxt
            },
            "sichtbarkeit": {
                "editor": self.uiVisibilityEdit
            },
            "verbleib": {
                "editor": self.uiWhereaboutsEdit
            },
            "funde": {
                "editor": self.uiFindsPTxt
            },
            "morphologie": {
                "editor": self.uiMorphologyPTxt
            },
            "sonstiges": {
                "editor": self.uiMiscellaneousPTxt
            }
        }
        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)

        # Date and Times
        self.mapper.addMapping(self.uiShardingDate,
                               self.model.fieldIndex("datum"))

        # ComboBox without Model
        self.mapper.addMapping(self.uiShardingTypeCombo,
                               self.model.fieldIndex("begehtyp"))
        self.uiShardingTypeCombo.editTextChanged.connect(
            self.onLineEditChanged)
        # FIXME Pyqt5 AutoCompletion
        #self.uiShardingTypeCombo.setAutoCompletion(True)
        self.uiShardingTypeCombo.lineEdit().setValidator(
            InListValidator([
                self.uiShardingTypeCombo.itemText(i)
                for i in range(self.uiShardingTypeCombo.count())
            ], self.uiShardingTypeCombo.lineEdit(), None, self))

        # ComboBox without Model
        self.mapper.addMapping(self.uiConditionPlantCoverCombo,
                               self.model.fieldIndex("zustand_bewuchs"))
        self.uiConditionPlantCoverCombo.editTextChanged.connect(
            self.onLineEditChanged)
        # FIXME Pyqt5 AutoCompletion
        #self.uiConditionPlantCoverCombo.setAutoCompletion(True)
        self.uiConditionPlantCoverCombo.lineEdit().setValidator(
            InListValidator([
                self.uiConditionPlantCoverCombo.itemText(i)
                for i in range(self.uiConditionPlantCoverCombo.count())
            ], self.uiConditionPlantCoverCombo.lineEdit(), None, self))

        # ComboBox without Model
        self.mapper.addMapping(self.uiConditionLightCombo,
                               self.model.fieldIndex("zustand_licht"))
        self.uiConditionLightCombo.editTextChanged.connect(
            self.onLineEditChanged)
        # FIXME Pyqt5 AutoCompletion
        #self.uiConditionLightCombo.setAutoCompletion(True)
        self.uiConditionLightCombo.lineEdit().setValidator(
            InListValidator([
                self.uiConditionLightCombo.itemText(i)
                for i in range(self.uiConditionLightCombo.count())
            ], self.uiConditionLightCombo.lineEdit(), None, self))

        # ComboBox without Model
        self.mapper.addMapping(self.uiConditionSoilCombo,
                               self.model.fieldIndex("zustand_boden"))
        self.uiConditionSoilCombo.editTextChanged.connect(
            self.onLineEditChanged)
        # FIXME Pyqt5 AutoCompletion
        #self.uiConditionSoilCombo.setAutoCompletion(True)
        self.uiConditionSoilCombo.lineEdit().setValidator(
            InListValidator([
                self.uiConditionSoilCombo.itemText(i)
                for i in range(self.uiConditionSoilCombo.count())
            ], self.uiConditionSoilCombo.lineEdit(), None, self))

        # ComboBox without Model
        self.mapper.addMapping(self.uiConditionMoistureCombo,
                               self.model.fieldIndex("zustand_feuchtigkeit"))
        self.uiConditionMoistureCombo.editTextChanged.connect(
            self.onLineEditChanged)
        # FIXME Pyqt5 AutoCompletion
        #self.uiConditionMoistureCombo.setAutoCompletion(True)
        self.uiConditionMoistureCombo.lineEdit().setValidator(
            InListValidator([
                self.uiConditionMoistureCombo.itemText(i)
                for i in range(self.uiConditionMoistureCombo.count())
            ], self.uiConditionMoistureCombo.lineEdit(), None, self))

        # ComboBox without Model
        self.mapper.addMapping(self.uiConditionRainCombo,
                               self.model.fieldIndex("zustand_abgeregnet"))
        self.uiConditionRainCombo.editTextChanged.connect(
            self.onLineEditChanged)
        # FIXME Pyqt5 AutoCompletion
        #self.uiConditionRainCombo.setAutoCompletion(True)
        self.uiConditionRainCombo.lineEdit().setValidator(
            InListValidator([
                self.uiConditionRainCombo.itemText(i)
                for i in range(self.uiConditionRainCombo.count())
            ], self.uiConditionRainCombo.lineEdit(), None, self))

    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 onAccept(self):
        '''
        Check DB
        Save options when pressing OK button
        Update Plugin Status
        '''
        # Save Settings
        SetWindowSize("sharding", self.size())
        self.accept()

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

    def addNewSharding(self, siteNumber):
        self.initalLoad = True
        self.siteNumber = siteNumber

        # get new sharding number
        query = QSqlQuery(self.dbm.db)
        qryStr = "SELECT CASE WHEN max(begehung) IS NULL THEN 1 ELSE max(begehung)+1 END begehungNeu FROM begehung WHERE fundortnummer='{0}'".format(
            self.siteNumber)
        query.exec_(qryStr)
        query.first()
        self.shardingNumber = query.value(0)

        self.model = QSqlRelationalTableModel(self, self.dbm.db)
        self.model.setTable("begehung")
        self.model.setFilter("fundortnummer='{0}'".format(self.siteNumber))
        res = self.model.select()
        #self.model.submitAll()
        while (self.model.canFetchMore()):
            self.model.fetchMore()

        row = self.model.rowCount()
        #QMessageBox.information(None, "begehung", "{0}".format(row))
        self.model.insertRow(row)

        #QMessageBox.information(None, "begehung", "{0}".format(self.model.rowCount()))

        self.setupMapper()
        self.mapper.toLast()

        self.addMode = True
        self.startEditMode()

        # self.mapper.submit()

        # self.model.insertRow(row)
        # self.mapper.setCurrentIndex(row)

        self.uiSiteNumberEdit.setText(self.siteNumber)
        self.uiShardingNumberEdit.setText(str(self.shardingNumber))
        now = QDate.currentDate()
        self.uiShardingDate.setDate(now)

        self.setKgNameAndCode()

        #QMessageBox.warning(None, self.tr(u"Neu"), self.tr(u"{0}, {1}".format(siteNumber,nn)))

        self.initalLoad = False

    def removeNewSharding(self):
        self.initalLoad = True
        row = self.mapper.currentIndex()
        self.model.removeRow(row + 1)
        self.model.submitAll()
        while (self.model.canFetchMore()):
            self.model.fetchMore()
        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 == 'QDateEdit':
                value = mEditor.date().toString("yyyy-MM-dd")
            elif cName == 'QLineEdit':
                value = mEditor.text()
            elif cName == 'QComboBox':
                if mEditor.isEditable():
                    value = mEditor.lineEdit().text()
                else:
                    if mEditor.currentIndex == -1:
                        value = ''
                    else:
                        value = '1'
            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()
        #QMessageBox.information(None, "begehung", "{0}".format(currIdx))
        #now = QDate.currentDate()
        #self.uiLastChangesDate.setDate(now)
        self.mapper.submit()

        self.mapper.setCurrentIndex(currIdx)

        # emit signal
        self.shardingEditsSaved.emit(True)

        self.endEditMode()
        return True

    def cancelEdit(self):
        currIdx = self.mapper.currentIndex()
        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.close()
                    self.done(1)
                    self.removeNewSharding()
                    self.endEditMode()

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

    def startEditMode(self):
        self.editMode = True
        self.uiOkBtn.setEnabled(False)
        self.uiSaveBtn.setEnabled(True)
        self.uiCancelBtn.setEnabled(True)
        self.editorsEdited = []
        self.uiShardingDate.setReadOnly(not self.addMode)
        if self.uiShardingDate.isReadOnly():
            self.uiShardingDate.setStyleSheet(
                "background-color: rgb(218, 218, 218);")
        else:
            self.uiShardingDate.setStyleSheet("")

    def endEditMode(self):
        self.editMode = False
        self.addMode = False
        self.uiOkBtn.setEnabled(True)
        self.uiSaveBtn.setEnabled(False)
        self.uiCancelBtn.setEnabled(False)
        self.uiShardingDate.setReadOnly(not self.addMode)
        self.uiShardingDate.setStyleSheet(
            "background-color: rgb(218, 218, 218);")
        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 = []

    def viewPictures(self):
        dirName = self.settings.value("APIS/insp_image_dir")
        folderNameType = self.settings.value("APIS/insp_image_foto_dir")
        folderNameSite = self.getFolderNameSite(self.siteNumber)
        path = dirName + u'\\' + folderNameSite + u'\\' + folderNameType

        self.loadInImageViewer(path)

    def openPictures(self):
        dirName = self.settings.value("APIS/insp_image_dir")
        folderNameType = self.settings.value("APIS/insp_image_foto_dir")
        folderNameSite = self.getFolderNameSite(self.siteNumber)
        path = dirName + u'\\' + folderNameSite + u'\\' + folderNameType

        if not OpenFileOrFolder(path):
            QMessageBox.information(
                self, u"Begehung",
                u"Das Verzeichnis '{0}' wurde nicht gefunden.".format(path))

    def viewSketches(self):
        dirName = self.settings.value("APIS/insp_image_dir")
        folderNameType = self.settings.value("APIS/insp_image_sketch_dir")
        folderNameSite = self.getFolderNameSite(self.siteNumber)
        path = dirName + u'\\' + folderNameSite + u'\\' + folderNameType

        self.loadInImageViewer(path)

    def openSketches(self):
        dirName = self.settings.value("APIS/insp_image_dir")
        folderNameType = self.settings.value("APIS/insp_image_sketch_dir")
        folderNameSite = self.getFolderNameSite(self.siteNumber)
        path = dirName + u'\\' + folderNameSite + u'\\' + folderNameType

        if not OpenFileOrFolder(path):
            QMessageBox.information(
                None, u"Begehung",
                u"Das Verzeichnis '{0}' wurde nicht gefunden.".format(path))

    def getFolderNameSite(self, siteNumber):
        query = QSqlQuery(self.dbm.db)
        #qryStr = u"SELECT trim(katastralgemeinde) || ' ' || trim(katastralgemeindenummer) || '.' || substr('000' || fundortnummer_nn_legacy, -3, 3) AS folderName FROM fundort f WHERE f.fundortnummer='{0}'".format(siteNumber)
        query.prepare(
            u"SELECT land || '\\'  || CASE WHEN land = 'AUT' THEN replace(replace(replace(replace(lower(trim(katastralgemeinde)), '.',''), '-', ' '), '(', ''), ')', '') || ' ' ELSE '' END || substr('000000' || fundortnummer_nn, -6, 6) AS folderName FROM fundort f WHERE f.fundortnummer='{0}'"
            .format(siteNumber))
        query.exec_()
        query.first()
        return query.value(0)

    def loadInImageViewer(self, path):
        dir = QDir(path)
        if dir.exists():
            entryList = dir.entryList(['*.jpg'], QDir.Files)
            if len(entryList) > 0:
                # load in thumb viewer
                # QMessageBox.information(None, u"Begehung", u",".join(entryList))
                imagePathList = []
                for image in entryList:
                    imagePathList.append(path + u'\\' + image)

                widget = APISThumbViewer()
                widget.load(imagePathList)
                widget.show()
                if widget.exec_():
                    pass
                    # app.exec_()
            else:
                QMessageBox.information(
                    self, u"Begehung",
                    u"Es wurden keine Dateien [*.jpg] für diesen Fundort gefunden."
                )
        else:
            QMessageBox.information(
                self, u"Begehung",
                u"Das Verzeichnis '{0}' wurde nicht gefunden.".format(path))