def localChanges(self, layer): filename, layername = namesFromLayer(layer) con = sqlite3.connect(filename) cursor = con.cursor() attributes = [v[1] for v in cursor.execute("PRAGMA table_info('%s');" % layername)] attrnames = [a for a in attributes if a != "fid"] cursor.execute("SELECT * FROM %s_audit;" % layername) changes = cursor.fetchall() changesdict = {} tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) commitid = cursor.execute("SELECT commit_id FROM geogig_audited_tables WHERE table_name='%s';" % layername).fetchone()[0] geomField = cursor.execute("SELECT column_name FROM gpkg_geometry_columns WHERE table_name='%s';" % layername).fetchone()[0] for c in changes: featurechanges = {} path = str(c[attributes.index("fid")]) for attr in attrnames: if c[-1] == LOCAL_FEATURE_REMOVED: value = None else: if attr != geomField: value = c[attributes.index(attr)] else: request = QgsFeatureRequest().setFilterExpression("fid=%s" % path) features = list(layer.getFeatures(request)) if len(features) == 0: continue value = features[0].geometry().exportToWkt().upper() featurechanges[attr] = value path = geogigFidFromGpkgFid(tracking, path) changesdict[path] = LocalDiff(layername, path, repo, featurechanges, commitid, c[-1]) return changesdict
def revertChange(layer): if hasLocalChanges(layer): QMessageBox.warning(config.iface.mainWindow(), 'Cannot revert commit', "The layer has local changes.\n" "Revert local changes before reverting a previous commit.", QMessageBox.Ok) return tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) filename, layername = namesFromLayer(layer) from geogig.gui.dialogs.historyviewer import HistoryViewerDialog dlg = HistoryViewerDialog(repo, layername) dlg.exec_() if dlg.ref is not None: #TODO check that selected commit is in history line commit = Commit.fromref(repo, dlg.ref) # check if we are reverting commit which adds layer to the repo if commit.addsLayer(): QMessageBox.warning(config.iface.mainWindow(), 'Cannot revert commit', "Commits which add layer to the repository can not " "be reverted. Use GeoGig Navigator to remove layer " "from branch.") return applyLayerChanges(repo, layer, commit.commitid, commit.parent.commitid, False) layer.reload() layer.triggerRepaint() config.iface.messageBar().pushMessage("GeoGig", "Commit changes have been reverted in local layer", level=QgsMessageBar.INFO, duration=5) commitdialog.suggestedMessage = "Reverted changes from commit %s [%s] " % (commit.commitid, commit.message)
def addInfoActions(layer): commitId = getCommitId(layer) tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) _infoActions[layer.id()] = [] try: commit = Commit.fromref(repo, commitId) messageAction = QAction( "Message: '%s'" % commit.message.splitlines()[0], config.iface.legendInterface()) f = messageAction.font() f.setBold(True) messageAction.setFont(f) config.iface.legendInterface().addLegendLayerAction( messageAction, u"GeoGig", u"id1", QgsMapLayer.VectorLayer, False) config.iface.legendInterface().addLegendLayerActionForLayer( messageAction, layer) _infoActions[layer.id()].append(messageAction) except Exception, e: QgsMessageLog.logMessage( "Cannot connect to server when creating GeoGig layer context:\n %s" % str(e), level=QgsMessageLog.WARNING) messageAction = QAction("Error: Cannot connect with repository", config.iface.legendInterface()) f = messageAction.font() f.setBold(True) messageAction.setFont(f) config.iface.legendInterface().addLegendLayerAction( messageAction, u"GeoGig", u"id1", QgsMapLayer.VectorLayer, False) config.iface.legendInterface().addLegendLayerActionForLayer( messageAction, layer) _infoActions[layer.id()].append(messageAction) return False
def changeVersion(layer): if hasLocalChanges(layer): QMessageBox.warning(config.iface.mainWindow(), 'Cannot change commit', "The layer has local changes that would be overwritten. " "Either sync layer with branch or revert local changes " "before changing commit.", QMessageBox.Ok) else: tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) dlg = HistoryViewerDialog(repo, tracking.layername) dlg.exec_() if dlg.ref is not None: layers = repo.trees(dlg.ref) if tracking.layername not in layers: QMessageBox.warning(config.iface.mainWindow(), 'Cannot change commit', "The selected commit does not contain the specified layer.", QMessageBox.Ok) else: repo.checkoutlayer(tracking.geopkg, tracking.layername, None, dlg.ref) config.iface.messageBar().pushMessage("GeoGig", "Layer has been updated to commit %s" % dlg.ref, level=QgsMessageBar.INFO, duration=5) layer.reload() layer.triggerRepaint() repoWatcher.layerUpdated.emit(layer) repoWatcher.repoChanged.emit(repo)
def localChanges(self, layer): filename, layername = namesFromLayer(layer) con = sqlite3.connect(filename) cursor = con.cursor() attributes = [v[1] for v in cursor.execute("PRAGMA table_info('%s');" % layername)] attrnames = [a for a in attributes if a != "fid"] cursor.execute("SELECT * FROM %s_audit;" % layername) changes = cursor.fetchall() changesdict = {} tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) commitid = cursor.execute("SELECT commit_id FROM geogig_audited_tables WHERE table_name='%s';" % layername).fetchone()[0] geomField = cursor.execute("SELECT column_name FROM gpkg_geometry_columns WHERE table_name='%s';" % layername).fetchone()[0] for c in changes: featurechanges = {} path = str(c[attributes.index("fid")]) for attr in attrnames: if c[-1] == LOCAL_FEATURE_REMOVED: value = None else: if attr != geomField: value = c[attributes.index(attr)] else: request = QgsFeatureRequest().setFilterExpression("fid=%s" % path) features = list(layer.getFeatures(request)) if len(features) == 0: continue value = features[0].geometry().exportToWkt().upper() featurechanges[attr] = value path = geogigFidFromGpkgFid(tracking, path) changesdict[path] = LocalDiff(layername, path, repo, featurechanges, commitid, c[-1]) return changesdict
def canvasPressEvent(self, e): layer = config.iface.activeLayer() if layer is None or not isinstance(layer, QgsVectorLayer): config.iface.messageBar().pushMessage("No layer selected or the current active layer is not a valid vector layer", level = QgsMessageBar.WARNING, duration = 4) return if not layertracking.isTracked(layer): config.iface.messageBar().pushMessage("The current active layer is not being tracked as part of a GeoGig repo", level = QgsMessageBar.WARNING, duration = 4) return trackedlayer = layertracking.getTrackingInfo(layer) point = self.toMapCoordinates(e.pos()) searchRadius = self.canvas().extent().width() * .01; r = QgsRectangle() r.setXMinimum(point.x() - searchRadius); r.setXMaximum(point.x() + searchRadius); r.setYMinimum(point.y() - searchRadius); r.setYMaximum(point.y() + searchRadius); r = self.toLayerCoordinates(layer, r); fit = layer.getFeatures(QgsFeatureRequest().setFilterRect(r).setFlags(QgsFeatureRequest.ExactIntersect)); fid = None try: feature = fit.next() try: fid = unicode(feature["geogigid"]) except: pass except StopIteration, e: return
def changeVersion(layer): if hasLocalChanges(layer): QMessageBox.warning( config.iface.mainWindow(), 'Cannot change version', "There are local changes that would be overwritten.\n" "Revert them before changing version.", QMessageBox.Ok) else: tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) dlg = HistoryViewerDialog(repo, tracking.layername) dlg.exec_() if dlg.ref is not None: layers = repo.trees(dlg.ref) if tracking.layername not in layers: QMessageBox.warning( config.iface.mainWindow(), 'Cannot change version', "The selected version does not contain the specified layer.", QMessageBox.Ok) else: repo.checkoutlayer(tracking.geopkg, tracking.layername, None, dlg.ref) config.iface.messageBar().pushMessage( "GeoGig", "Layer has been updated to version %s" % dlg.ref, level=QgsMessageBar.INFO, duration=5) layer.reload() layer.triggerRepaint() repoWatcher.layerUpdated.emit(layer) repoWatcher.repoChanged.emit(repo)
def _checkLayerNotInRepo(): layer = layerFromName("points") tracking = getTrackingInfo(layer) assert tracking is None connector = PyQtConnectorDecorator() connector.checkIsAlive() repo = Repository(os.path.join(_tempReposPath, "repos", "pointsrepo"), connector) layers = [tree.path for tree in repo.trees] assert "points" not in layers
def _checkLayerInRepo(): layer = layerFromName("points") tracking = getTrackingInfo(layer) assert tracking is not None connector = PyQtConnectorDecorator() connector.checkIsAlive() repo = Repository(tracking.repoFolder, connector) layers = [tree.path for tree in repo.trees] assert "points" in layers removeTrackedLayer(layer)
def changeVersion(self, repo, layer, commit): if hasLocalChanges(layer): QMessageBox.warning(config.iface.mainWindow(), 'Cannot switch to this commit', "There are local changes that would be overwritten.\n" "Revert them before retrying this operation.", QMessageBox.Ok) else: tracking = getTrackingInfo(layer) repo.checkoutlayer(tracking.geopkg, tracking.layername, None, commit) config.iface.messageBar().pushMessage("GeoGig", "Layer has been updated to commit %s" % commit, level=QgsMessageBar.INFO, duration=5) layer.reload() layer.triggerRepaint() repoWatcher.layerUpdated.emit(layer)
def revertLocalChanges(layer): if hasLocalChanges(layer): tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) commitid = getCommitId(layer) repo.checkoutlayer(tracking.geopkg, tracking.layername, None, commitid) config.iface.messageBar().pushMessage("GeoGig", "Local changes have been discarded", level=QgsMessageBar.INFO, duration=5) layer.reload() layer.triggerRepaint() else: config.iface.messageBar().pushMessage("GeoGig", "No local changes were found", level=QgsMessageBar.INFO, duration=5)
def revertLocalChanges(layer): if hasLocalChanges(layer): tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) commitid = getCommitId(layer) repo.checkoutlayer(tracking.geopkg, tracking.layername, None, commitid) config.iface.messageBar().pushMessage( "GeoGig", "Local changes have been discarded", level=QgsMessageBar.INFO, duration=5) layer.reload() layer.triggerRepaint() else: config.iface.messageBar().pushMessage("GeoGig", "No local changes were found", level=QgsMessageBar.INFO, duration=5)
def changeVersion(self, repo, layer, commit): if hasLocalChanges(layer): QMessageBox.warning( config.iface.mainWindow(), 'Cannot switch to this commit', "There are local changes that would be overwritten.\n" "Revert them before retrying this operation.", QMessageBox.Ok) else: tracking = getTrackingInfo(layer) repo.checkoutlayer(tracking.geopkg, tracking.layername, None, commit) config.iface.messageBar().pushMessage( "GeoGig", "Layer has been updated to commit %s" % commit, level=QgsMessageBar.INFO, duration=5) layer.reload() layer.triggerRepaint() repoWatcher.layerUpdated.emit(layer)
def canvasPressEvent(self, e): layer = config.iface.activeLayer() if layer is None or not isinstance(layer, QgsVectorLayer): config.iface.messageBar().pushMessage("No layer selected or the current active layer is not a valid vector layer", level = QgsMessageBar.WARNING, duration = 5) return if not layertracking.isRepoLayer(layer): config.iface.messageBar().pushMessage("The current active layer is not being tracked as part of a GeoGig repo", level = QgsMessageBar.WARNING, duration = 5) return trackedlayer = layertracking.getTrackingInfo(layer) point = self.toMapCoordinates(e.pos()) searchRadius = self.canvas().extent().width() * .01; r = QgsRectangle() r.setXMinimum(point.x() - searchRadius); r.setXMaximum(point.x() + searchRadius); r.setYMinimum(point.y() - searchRadius); r.setYMaximum(point.y() + searchRadius); r = self.toLayerCoordinates(layer, r); fit = layer.getFeatures(QgsFeatureRequest().setFilterRect(r).setFlags(QgsFeatureRequest.ExactIntersect)); fid = None try: feature = next(fit) fid = feature.id() fid = geogigFidFromGpkgFid(trackedlayer, fid) if fid is None: return except StopIteration as e: return repo = Repository(trackedlayer.repoUrl) menu = QMenu() versionsAction = QAction("Show all versions of this feature...", None) versionsAction.triggered.connect(lambda: self.versions(repo, trackedlayer.layername, fid)) menu.addAction(versionsAction) blameAction = QAction("Show authorship...", None) blameAction.triggered.connect(lambda: self.blame(repo, trackedlayer.layername, fid)) menu.addAction(blameAction) point = config.iface.mapCanvas().mapToGlobal(e.pos()) menu.exec_(point)
def revertChange(layer): tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) currentCommitId = getCommitId(layer) filename, layername = namesFromLayer(layer) dlg = CommitSelectDialog(repo, currentCommitId, layername) dlg.exec_() if dlg.ref is not None: #TODO check that selected commit is in history line applyLayerChanges(repo, layer, dlg.ref.commitid, dlg.ref.parent.commitid, False) layer.reload() layer.triggerRepaint() config.iface.messageBar().pushMessage( "GeoGig", "Version changes have been reverted in local layer", level=QgsMessageBar.INFO, duration=5) commitdialog.suggestedMessage = "Reverted changes from version %s [%s] " % ( dlg.ref.commitid, dlg.ref.message)
def addInfoActions(layer): commitId = getCommitId(layer) tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) layer.infoActions = [] try: commit = Commit.fromref(repo, commitId) messageAction = QAction( "Message: '%s'" % commit.message.splitlines()[0], config.iface.legendInterface()) f = messageAction.font() f.setBold(True) messageAction.setFont(f) config.iface.legendInterface().addLegendLayerAction( messageAction, u"GeoGig", u"id1", QgsMapLayer.VectorLayer, False) config.iface.legendInterface().addLegendLayerActionForLayer( messageAction, layer) layer.infoActions.append(messageAction) except: messageAction = QAction("Error: Cannot connect with repository", config.iface.legendInterface()) f = messageAction.font() f.setBold(True) messageAction.setFont(f) config.iface.legendInterface().addLegendLayerAction( messageAction, u"GeoGig", u"id1", QgsMapLayer.VectorLayer, False) config.iface.legendInterface().addLegendLayerActionForLayer( messageAction, layer) layer.infoActions.append(messageAction) return False shaAction = QAction("Version ID: %s" % commitId, config.iface.legendInterface()) f = shaAction.font() f.setBold(True) shaAction.setFont(f) config.iface.legendInterface().addLegendLayerAction( shaAction, u"GeoGig", u"id1", QgsMapLayer.VectorLayer, False) config.iface.legendInterface().addLegendLayerActionForLayer( shaAction, layer) layer.infoActions.append(shaAction) return True
def revertChange(layer): if hasLocalChanges(layer): QMessageBox.warning( config.iface.mainWindow(), 'Cannot revert commit', "The layer has local changes.\n" "Revert local changes before reverting a previous commit.", QMessageBox.Ok) return tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) filename, layername = namesFromLayer(layer) from geogig.gui.dialogs.historyviewer import HistoryViewerDialog dlg = HistoryViewerDialog(repo, layername) dlg.exec_() if dlg.ref is not None: #TODO check that selected commit is in history line commit = Commit.fromref(repo, dlg.ref) # check if we are reverting commit which adds layer to the repo if commit.addsLayer(): QMessageBox.warning( config.iface.mainWindow(), 'Cannot revert commit', "Commits which add layer to the repository can not " "be reverted. Use GeoGig Navigator to remove layer " "from branch.") return applyLayerChanges(repo, layer, commit.commitid, commit.parent.commitid, False) layer.reload() layer.triggerRepaint() config.iface.messageBar().pushMessage( "GeoGig", "Commit changes have been reverted in local layer", level=QgsMessageBar.INFO, duration=5) commitdialog.suggestedMessage = "Reverted changes from commit %s [%s] " % ( commit.commitid, commit.message)
def canvasPressEvent(self, e): layer = config.iface.activeLayer() if layer is None or not isinstance(layer, QgsVectorLayer): config.iface.messageBar().pushMessage( "No layer selected or the current active layer is not a valid vector layer", level=QgsMessageBar.WARNING, duration=4) return if not layertracking.isTracked(layer): config.iface.messageBar().pushMessage( "The current active layer is not being tracked as part of a GeoGig repo", level=QgsMessageBar.WARNING, duration=4) return trackedlayer = layertracking.getTrackingInfo(layer) point = self.toMapCoordinates(e.pos()) searchRadius = self.canvas().extent().width() * .01 r = QgsRectangle() r.setXMinimum(point.x() - searchRadius) r.setXMaximum(point.x() + searchRadius) r.setYMinimum(point.y() - searchRadius) r.setYMaximum(point.y() + searchRadius) r = self.toLayerCoordinates(layer, r) fit = layer.getFeatures(QgsFeatureRequest().setFilterRect(r).setFlags( QgsFeatureRequest.ExactIntersect)) fid = None try: feature = fit.next() try: fid = unicode(feature["geogigid"]) except: pass except StopIteration, e: return
def addInfoActions(layer): commitId = getCommitId(layer) tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) _infoActions[layer.id()] = [] try: commit = Commit.fromref(repo, commitId) messageAction = QAction("Message: '%s'" % commit.message.splitlines()[0], config.iface.legendInterface()) f = messageAction.font(); f.setBold(True); messageAction.setFont(f); config.iface.legendInterface().addLegendLayerAction(messageAction, u"GeoGig", u"id1", QgsMapLayer.VectorLayer, False) config.iface.legendInterface().addLegendLayerActionForLayer(messageAction, layer) _infoActions[layer.id()].append(messageAction) except Exception, e: QgsMessageLog.logMessage("Cannot connect to server when creating GeoGig layer context:\n %s" % str(e), level=QgsMessageLog.WARNING) messageAction = QAction("Error: Cannot connect with repository", config.iface.legendInterface()) f = messageAction.font(); f.setBold(True); messageAction.setFont(f); config.iface.legendInterface().addLegendLayerAction(messageAction, u"GeoGig", u"id1", QgsMapLayer.VectorLayer, False) config.iface.legendInterface().addLegendLayerActionForLayer(messageAction, layer) _infoActions[layer.id()].append(messageAction) return False
def syncLayer(layer): tracking = getTrackingInfo(layer) repo = Repository(tracking.repoUrl) filename, layername = namesFromLayer(layer) con = sqlite3.connect(filename) cursor = con.cursor() cursor.execute("SELECT * FROM %s_audit;" % layername) changes = bool(cursor.fetchall()) cursor.close() con.close() if changes: con = sqlite3.connect(filename) cursor = con.cursor() beforeAttrs = set(v[1] for v in cursor.execute("PRAGMA table_info('%s');" % layername)) afterAttrs = set( v[1] for v in cursor.execute("PRAGMA table_info('%s_audit');" % layername) if v[1] not in ["audit_timestamp", "audit_op"]) cursor.close() con.close() if beforeAttrs != afterAttrs: ret = QMessageBox.warning( iface.mainWindow(), "Cannot commit changes to repository", "The structure of attributes table has been modified.\n" "This type of change is not supported by GeoGig.", QMessageBox.Yes) return user, email = config.getUserInfo() if user is None: return dlg = CommitDialog(repo, layername) dlg.exec_() if dlg.branch is None: return if dlg.branch not in repo.branches(): commitId = getCommitId(layer) repo.createbranch(commitId, dlg.branch) mergeCommitId, importCommitId, conflicts, featureIds = repo.importgeopkg( layer, dlg.branch, dlg.message, user, email, True) if conflicts: ret = QMessageBox.warning( iface.mainWindow(), "Error while syncing", "There are conflicts between local and remote changes.\n" "Do you want to continue and fix them?", QMessageBox.Yes | QMessageBox.No) if ret == QMessageBox.No: repo.closeTransaction(conflicts[0].transactionId) return solved, resolvedConflicts = solveConflicts(conflicts) if not solved: repo.closeTransaction(conflicts[0].transactionId) return for conflict, resolution in zip(conflicts, list(resolvedConflicts.values())): if resolution == ConflictDialog.LOCAL: conflict.resolveWithLocalVersion() elif resolution == ConflictDialog.REMOTE: conflict.resolveWithRemoteVersion() elif resolution == ConflictDialog.DELETE: conflict.resolveDeletingFeature() else: conflict.resolveWithNewFeature(resolution) repo.commitAndCloseMergeAndTransaction(user, email, "Resolved merge conflicts", conflicts[0].transactionId) updateFeatureIds(repo, layer, featureIds) try: applyLayerChanges(repo, layer, importCommitId, mergeCommitId) except: QgsMessageLog.logMessage( "Database locked while syncing. Using full layer checkout instead", level=QgsMessageLog.CRITICAL) repo.checkoutlayer(tracking.geopkg, layername, None, mergeCommitId) commitdialog.suggestedMessage = "" else: branches = [] for branch in repo.branches(): trees = repo.trees(branch) if layername in trees: branches.append(branch) branch, ok = QInputDialog.getItem(iface.mainWindow(), "Sync", "Select branch to update from", branches, 0, False) if not ok: return commitId = getCommitId(layer) headCommitId = repo.revparse(branch) applyLayerChanges(repo, layer, commitId, headCommitId) layer.reload() layer.triggerRepaint() repoWatcher.repoChanged.emit(repo) iface.messageBar().pushMessage("GeoGig", "Layer has been correctly synchronized", level=QgsMessageBar.INFO, duration=5) repoWatcher.layerUpdated.emit(layer)