class LandmarkToolbox(QDockWidget, Ui_DockWidget): landmarkMessage = pyqtSignal(unicode, int) def __init__(self, iface): QDockWidget.__init__(self) self.setupUi(self) self.iface = iface self.canvas = self.iface.mapCanvas() self.geoCrs = QgsCoordinateReferenceSystem(4326) self.btnAddPhoto.setIcon(QIcon(':/icons/camera.svg')) self.txtPhotoComment.setPlaceholderText(self.tr('Comment')) self.cmbLayers.setFilters(QgsMapLayerProxyModel.VectorLayer) self.db = QSqlDatabase.addDatabase('QPSQL') self.landmarkId = None self.photoId = None self.highlight = None self.model = QStandardItemModel() self.lstPhotos.setModel(self.model) self.btnUpdateLandmark.clicked.connect(self.saveLandmark) self.btnDeleteLandmark.clicked.connect(self.deleteLandmark) self.btnAddPhoto.clicked.connect(self.addPhoto) self.btnUpdatePhoto.clicked.connect(self.savePhoto) self.btnDeletePhoto.clicked.connect(self.removePhoto) self.lstPhotos.selectionModel().selectionChanged.connect( self.photoSelected) self.lstPhotos.doubleClicked.connect(self.showPhoto) self._enableOrDisableButtons() self.ToggleToolbox() def ToggleToolbox(self): layer_list = self.canvas.layers() if not layer_list: self.hide() return elif len(layer_list) == 0: self.hide() return self.setVisible(not self.isVisible()) def getLandmarkID(self): #ランドマークがなかった時の処理 return self.landmarkId def openDatabase(self): if self.db.isValid(): settings = QSettings('MatsueGkukan', 'Gkukandb') dbHostName = settings.value('hostname') dbDatabaseName = settings.value('databasename') dbUserName = settings.value('username') dbPassword = settings.value('dbpassword') self.db.setHostName(dbHostName) self.db.setDatabaseName(dbDatabaseName) self.db.setUserName(dbUserName) self.db.setPassword(dbPassword) if not self.db.open(): self.GKukanMusiumMessage.emit( self.tr('Can not open GKukanMusium database'), QgsMessageBar.WARNING) return False self.query = QSqlQuery(self.db) return True else: settings = QSettings('MatsueGkukan', 'Gkukandb') dbHostName = settings.value('hostname') dbDatabaseName = settings.value('databasename') dbUserName = settings.value('username') dbPassword = settings.value('dbpassword') self.db.removeDatabase(dbDatabaseName) del self.db self.db = None self.db = QSqlDatabase.addDatabase('QPSQL') self.db.setHostName(dbHostName) self.db.setDatabaseName(dbDatabaseName) self.db.setUserName(dbUserName) self.db.setPassword(dbPassword) if not self.db.open(): self.GKukanMusiumMessage.emit( self.tr('Can not open GKukanMusium database'), QgsMessageBar.WARNING) return False self.query = QSqlQuery(self.db) return True return False def GetPhotoFolderPath(self): if not self.openDatabase(): return False if self.query.exec_(u'select * from m_folder'): self.query.first() self.folderpath = self.query.value(2) self.thumbpath = os.path.join(self.folderpath, 'thumb') ret = self.folderpath else: ret = '' self.db.close() return ret def landmarkSelected(self, infos): self.info = infos[0] ft = self.info[1] self.landmarkId = ft['id'] self.leLandmarkTitle.setText(ft['title'] if ft['title'] else '') self.spnLandmarkClass.setValue( ft['icon_type'] if ft['icon_type'] != None else 0) self._highlightLandmark() self.populatePhotos() self._enableOrDisableButtons() def populatePhotos(self, index=0): self.model.clear() QApplication.setOverrideCursor(Qt.WaitCursor) # photos is a list of tuples (id, title, imagepath) photos = self._photosOfLandmark() for i in photos: tp = os.path.join(self.thumbpath, str(i[0])) + '.png' img = self.thumbnailPhoto(i[2], tp) icon = QIcon(img) title = i[1] if i[1] else '<unnamed photo> %s' % i[0] item = QStandardItem(title) item.setIcon(icon) item.setData(i[0], Qt.UserRole) item.setToolTip(title) self.model.appendRow(item) lastIdx = self.model.indexFromItem(item) idx = self.model.createIndex(0, 0) if self.model.rowCount() > 0: if index == -1: idx = lastIdx elif index > 0: idx = self.model.createIndex(index, 0) self.lstPhotos.selectionModel().select(idx, QItemSelectionModel.Select) else: self._clearForm() QApplication.restoreOverrideCursor() def thumbnailPhoto(self, imagePath, tp): if os.path.exists(tp): return QPixmap(tp) else: if os.path.exists(os.path.dirname(tp)) == False: os.mkdir(os.path.dirname(tp)) pixmap = QPixmap(imagePath).scaled(800, 600).scaled( 75, 50, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) a = pixmap.save(tp, 'PNG') return pixmap def showPhoto(self, index): if not self.openDatabase(): return item = self.lstPhotos.model().itemFromIndex(index) self.query.prepare( 'SELECT filename ,ST_X(geom),ST_Y(geom),geom FROM t_photo WHERE p_id=?;' ) self.query.addBindValue(item.data(Qt.UserRole)) if self.query.exec_(): self.query.first() path = os.path.join(self.folderpath, self.query.value(0)) if self.query.value( 3) <> '010100000000000000000000000000000000000000': lon = self.query.value(1) lat = self.query.value(2) point = self._transformPoint(QgsPoint(lon, lat)) self.canvas.freeze(True) self.canvas.setCenter(point) self.canvas.freeze(False) self.canvas.refresh() dlg = ViewPhotoDialog(path) dlg.exec_() else: a = self.query.lastError().text() self.db.close() def saveLandmark(self): layer = self.info[0] fid = self.info[1].id() idxTitle = layer.fieldNameIndex('title') idxClassification = layer.fieldNameIndex('icon_type') attrs = {idxTitle: self.leLandmarkTitle.text(),\ idxClassification: self.spnLandmarkClass.value() } layer.dataProvider().changeAttributeValues({fid: attrs}) layer.reload() layer.triggerRepaint() self.landmarkMessage.emit(self.tr('Landmark updated.'), QgsMessageBar.INFO) def deleteLandmark(self): layer = self.info[0] fid = self.info[1].id() layer.dataProvider().deleteFeatures([fid]) layer.reload() layer.triggerRepaint() self._clearAllFields() self.landmarkMessage.emit(self.tr('Landmark deleted.'), QgsMessageBar.INFO) def addPhoto(self): if self.landmarkId is not None: settings = QSettings('MatsueGkukan', 'Gkukandb') lastDir = settings.value('lastPhotoDir', '.') fileName = QFileDialog.getOpenFileName(self, self.tr('Select photo'), lastDir, self._createFilter()) if fileName == '': return settings.setValue('lastPhotoDir', QFileInfo(fileName).absoluteDir().absolutePath()) projectPath = self.GetPhotoFolderPath() + os.sep photoPath = os.path.basename(fileName) photoDate = self._photoDate(fileName).toString('yyyy-MM-dd') if not self.openDatabase(): return self.query.prepare( 'INSERT INTO t_photo("cdate", "filename", "landmark_id",lon,lat,angle,geomtype,geom) VALUES(?, ?, ?,?,?,?,?,?);' ) self.query.addBindValue(photoDate) self.query.addBindValue(photoPath) self.query.addBindValue(self.landmarkId) self.query.addBindValue(0) self.query.addBindValue(0) self.query.addBindValue(0) self.query.addBindValue(0) self.query.addBindValue( '010100000000000000000000000000000000000000') if self.query.exec_(): self._copyPhotoToFolder(fileName, self.landmarkId) self.populatePhotos(-1) else: a = self.query.lastError().text() self.db.close() else: self.landmarkMessage.emit( self.tr('Select landmark before adding a photo.'), QgsMessageBar.WARNING) def savePhoto(self): if not self.openDatabase(): return self.query.prepare( 'UPDATE t_photo SET film_no=?, keywords=?, keyword1=?, keyword2=?, keyword3=?, notes=?, mdate=?, registrant=?, comment=?, reference=?, angle=? WHERE p_id=?;' ) self.query.addBindValue(self.lePhotoTitle.text()) self.query.addBindValue(self.leKeywords.text()) self.query.addBindValue(self.leKeyword1.text()) self.query.addBindValue(self.leKeyword2.text()) self.query.addBindValue(self.leKeyword3.text()) self.query.addBindValue(self.txtPhotoComment.toPlainText()) self.query.addBindValue( self.edPhotoDate.dateTime().toString('yyyy-MM-dd')) self.query.addBindValue(self.leRegistrant.text()) self.query.addBindValue(self.leComment.text()) self.query.addBindValue(self.lerRference.text()) self.query.addBindValue(self.spnPhotoAngle.value()) self.query.addBindValue(self.photoId) if self.query.exec_(): self.landmarkMessage.emit(self.tr('Photo updated.'), QgsMessageBar.INFO) self.populatePhotos(self.lstPhotos.currentIndex().row()) else: a = self.query.lastError().text() self.db.close() def removePhoto(self): if not self.openDatabase(): return self.query.prepare('DELETE FROM t_photo WHERE "p_id"=?;') self.query.addBindValue(self.photoId) if self.query.exec_(): self.db.close() self._removePhotofromFolder() self.populatePhotos() def photoSelected(self, current, previous): if not self.openDatabase(): return idx = current.indexes()[0] item = self.lstPhotos.model().itemFromIndex(idx) self.photoId = item.data(Qt.UserRole) self.query.prepare( 'SELECT film_no, filename, keywords, keyword1, keyword2, keyword3, notes, mdate, registrant, comment, reference, angle FROM t_photo WHERE p_id=?;' ) self.query.addBindValue(self.photoId) if self.query.exec_(): self.query.first() self.filename = self.query.value(1) self.lePhotoTitle.setText( self.query.value(0) if self.query.value(0) else '') self.txtPhotoComment.setPlainText( self.query.value(6) if self.query.value(6) else '') self.leKeywords.setText( self.query.value(2) if self.query.value(2) else '') self.leKeyword1.setText( self.query.value(3) if self.query.value(3) else '') self.leKeyword2.setText( self.query.value(4) if self.query.value(4) else '') self.leKeyword3.setText( self.query.value(5) if self.query.value(5) else '') self.leRegistrant.setText( self.query.value(8) if self.query.value(8) else '') self.leComment.setText( self.query.value(9) if self.query.value(9) else '') self.lerRference.setText( self.query.value(10) if self.query.value(10) else '') self.spnPhotoAngle.setValue( int(self.query.value(11)) if self.query.value(11) else 0) self.edPhotoDate.setDateTime( self.query.value(7) if self.query.value(7) else QDateTime. currentDateTime()) self._enableOrDisableButtons() self.db.close() def _photosOfLandmark(self): projectPath = self.GetPhotoFolderPath() if not self.openDatabase(): return photos = [] self.query.prepare( 'SELECT "p_id", "keywords", "filename" FROM t_photo WHERE "landmark_id"=? ORDER BY "p_id";' ) self.query.addBindValue(self.landmarkId) if self.query.exec_(): while self.query.next(): photos.append((self.query.value(0), self.query.value(1), os.path.join(projectPath, self.query.value(2)))) self.db.close() return photos def _createFilter(self): formats = '' for f in QImageReader.supportedImageFormats(): f = unicode(f) if f == 'svg': continue formats += '*.{} *.{} '.format(f.lower(), f.upper()) return self.tr('Image files (%s);;All files (*.*)' % formats[:-1]) def _clearForm(self): self.lePhotoTitle.clear() self.txtPhotoComment.clear() self.leKeyword1.clear() self.leKeyword2.clear() self.leKeyword3.clear() self.leRegistrant.clear() self.leComment.clear() self.lerRference.clear() self.photoId = None self.landmarkId = None def _enableOrDisableButtons(self): if self.landmarkId is None: self.btnAddPhoto.setEnabled(False) else: self.btnAddPhoto.setEnabled(True) if self.photoId is None: self.btnDeletePhoto.setEnabled(False) self.btnUpdatePhoto.setEnabled(False) else: self.btnDeletePhoto.setEnabled(True) self.btnUpdatePhoto.setEnabled(True) def _highlightLandmark(self): self._clearHighlight() self.highlight = QgsHighlight(self.canvas, self.info[1].geometry(), self.info[0]) settings = QSettings() color = QColor( settings.value('/Map/highlight/color', QGis.DEFAULT_HIGHLIGHT_COLOR.name())) alpha = settings.value('/Map/highlight/colorAlpha', QGis.DEFAULT_HIGHLIGHT_COLOR.alpha(), type=int) buffer = settings.value('/Map/highlight/buffer', QGis.DEFAULT_HIGHLIGHT_BUFFER_MM, type=float) minWidth = settings.value('/Map/highlight/minWidth', QGis.DEFAULT_HIGHLIGHT_MIN_WIDTH_MM, type=float) self.highlight.setColor(color) color.setAlpha(alpha) self.highlight.setFillColor(color) self.highlight.setBuffer(buffer) self.highlight.setMinWidth(minWidth) self.highlight.show() def _photoDate(self, path): with open(path, 'rb') as imgFile: tags = exifread.process_file(imgFile, details=False) if 'EXIF GPS GPSDate' in tags: return QDateTime.fromString(tags['EXIF GPS GPSDate'].values, 'yyyy:MM:dd') else: return QDateTime.currentDateTime() def _clearHighlight(self): if hasattr(self, 'highlight'): del self.highlight self.highlight = None def _clearAllFields(self): self.leLandmarkTitle.clear() self.spnLandmarkClass.clear() self._clearHighlight() self._clearForm() self.model.clear() def _copyPhotoToFolder(self, path, landmark_id): projectPath = self.GetPhotoFolderPath() dst = os.path.join(projectPath, os.path.basename(path)) shutil.copy2(path, dst) def _removePhotofromFolder(self, path, landmark_id): projectPath = self.GetPhotoFolderPath() dst = os.path.join(projectPath, path) os.remove(dst) def _transformPoint(self, pnt): crsDest = self.canvas.mapSettings().destinationCrs() xform = QgsCoordinateTransform(self.geoCrs, crsDest) p2 = xform.transform(pnt) return p2