Esempio n. 1
0
 def importLayer(self):
     params = [
         Parameter("layer", "Layer to add", "", VECTOR, ""),
         Parameter("message", "Commit message", "", STRING, "")
     ]
     ret = openParametersDialog(params, "Add layer")
     if ret is not None:
         if ret["layer"] is None:
             return
         if isGeogigLayer(ret["layer"]):
             raise GeogigError("Selected layer is already a Geogig layer")
         if GEOGIGID_FIELD in [
                 f.name().lower() for f in ret["layer"].fields()
         ]:
             raise GeogigError("Selected layer has a 'geogigid' field")
         msg = ret["message"] or "Added layer '{}'".format(
             ret["layer"].name())
         self.server.addLayer(self.user, self.repo, ret["layer"], "master",
                              msg)
         saveStyleFromQgisLayer(ret["layer"], self.server, self.user,
                                self.repo)
         self.refreshContent()
         iface.messageBar().pushMessage("Add layer",
                                        "Layer correctly imported",
                                        level=Qgis.Info,
                                        duration=5)
def onLayersLoaded(layers):
    global _geogigLayers
    for layer in layers:
        if GeogigLiveLayer.GEOGIG_URL in layer.customPropertyKeys(): #geogig layer that is part of a project
            geogigLayer = addGeogigLayerFromLayer(layer)
            if geogigLayer:
                _geogigLayers.append(geogigLayer)
                if not geogigLayer.isValid():
                    item = QgsProject.instance().layerTreeRoot().findLayer(geogigLayer.layer.id())
                    item.setItemVisibilityCheckedRecursive(False)
                    raise GeogigError("Could not populate layer with Geogig server data")
        else: #let's see if it's a geogig layer in a geopackage file
            path = geogig.geopkgtools.simplifyGeoPKGFname(layer.source())
            if path.endswith("gpkg"):
                url = geogig.geopkgtools.getMetadataValue(path, GeogigLiveLayer.GEOGIG_URL)
                if url is not None:
                    rect = layer.extent()
                    extent = [rect.xMinimum(), rect.yMinimum(), rect.xMaximum(), rect.yMaximum()]
                    layer.setCustomProperty(GeogigLiveLayer.GEOGIG_URL, url)
                    layer.setCustomProperty(GeogigLiveLayer.GEOGIG_USER, geogig.geopkgtools.getMetadataValue(path, GeogigLiveLayer.GEOGIG_USER))
                    layer.setCustomProperty(GeogigLiveLayer.GEOGIG_REPO, geogig.geopkgtools.getMetadataValue(path, GeogigLiveLayer.GEOGIG_REPO))
                    layer.setCustomProperty(GeogigLiveLayer.GEOGIG_LAYER, geogig.geopkgtools.getMetadataValue(path, GeogigLiveLayer.GEOGIG_LAYER))
                    layer.setCustomProperty(GeogigLiveLayer.GEOGIG_COMMITID, geogig.geopkgtools.getMetadataValue(path, GeogigLiveLayer.GEOGIG_COMMITID))
                    layer.setCustomProperty(GeogigLiveLayer.GEOGIG_EXTENT, extent)
                    layer.setCustomProperty(GeogigLiveLayer.GEOGIG_LAYERCLASS, GeogigGpkgLayer.__name__)
                    geogigLayer = addGeogigLayerFromLayer(layer)
                    if geogigLayer:
                        _geogigLayers.append(geogigLayer)
                        if not geogigLayer.isValid():
                            item = QgsProject.instance().layerTreeRoot().findLayer(geogigLayer.layer.id())
                            item.setItemVisibilityCheckedRecursive(False)
                            raise GeogigError("Could not populate layer with Geogig server data")
    def __init__(self, geogiglayer, fid):
        super(VersionViewerDialog, self).__init__(iface.mainWindow())
        self.geogiglayer = geogiglayer
        self.fid = fid
        self.layer = None
        self.setupUi(self)

        self.listWidget.itemClicked.connect(self.commitClicked)

        horizontalLayout = QHBoxLayout()
        horizontalLayout.setSpacing(0)
        horizontalLayout.setMargin(0)
        self.mapCanvas = QgsMapCanvas()
        self.mapCanvas.setCanvasColor(Qt.white)
        horizontalLayout.addWidget(self.mapCanvas)
        self.mapWidget.setLayout(horizontalLayout)
        self.panTool = QgsMapToolPan(self.mapCanvas)
        self.mapCanvas.setMapTool(self.panTool)

        path = geogiglayer.layername + "/" + fid
        ids, commits = geogiglayer.server.log(geogiglayer.user,
                                              geogiglayer.repo, "master", path)
        if commits:
            for commit in commits.values():
                item = CommitListItem(commit, geogiglayer, fid)
                self.listWidget.addItem(item)
        else:
            raise GeogigError("The selected feature is not versioned yet")
def addGeogigLayer(server, user, repo, layername, commitid, live, parent = None):
    if live:
        layer = GeogigLiveLayer(server, user, repo, layername, commitid)
    else:
        parent = parent or iface.mainWindow()
        if parent == iface:
            parent = iface.mainWindow()
        dlg = ExtentDialog(parent)
        dlg.exec_()
        if dlg.ok:
            extent = dlg.extent
            if extent is not None:
                extentRect = QgsRectangle(extent[0],extent[1],
                                      extent[2],extent[3])
                projectCrs = QgsProject.instance().crs()
                layerCrs = server.layerCrs(user, repo, layername, commitid)
                extentRect = xform(extentRect, projectCrs,layerCrs)
                extent = [extentRect.xMinimum(),extentRect.yMinimum(),
                          extentRect.xMaximum(), extentRect.yMaximum()]
            layer = GeogigGpkgLayer(server, user, repo, layername, commitid, extent=extent)
        else:
            return False # no action - they said "cancel"
    _geogigLayers.append(layer)
    if live and not layer.isValid(): # layer will not be valid/invalid until downloaded -- will do check then
        raise GeogigError("Could not populate layer with Geogig server data. See log for details", "Error connecting to server")
    return True
    def saveChanges(self):
        changesFile = self._changesFile()
        if changesFile is None:
            if self.hasLocalChanges():
                raise GeogigError(
                    "Cannot save local changes. Project must be saved first.")
            else:
                return
        deletedGigIds = self.deletedFeatures
        modifiedFeatures = list(self.layer.getFeatures(self.modifiedFeatures))
        addedFeatures = list(self.layer.getFeatures(self.addedFeatures))

        if self.hasLocalChanges():
            with open(changesFile, "wb") as f:
                f.write(struct.pack(
                    'i', len(deletedGigIds)))  # write int - # of deleted
                for gigid in deletedGigIds:
                    s = gigid.encode()
                    f.write(struct.pack('i', len(s)))  #len
                    f.write(s)
                f.write(struct.pack(
                    'i', len(modifiedFeatures)))  # write int - # of mod
                if len(modifiedFeatures) > 0:
                    writer = FeatureWriter(modifiedFeatures)
                    f.write(writer.asBytes())
                    f.write(bytes([0]))  # separator
                f.write(struct.pack(
                    'i', len(addedFeatures)))  # write int - # of mod
                if len(addedFeatures) > 0:
                    writer = FeatureWriter(addedFeatures)
                    f.write(writer.asBytes())
        elif os.path.exists(changesFile):
            os.remove(changesFile)
Esempio n. 6
0
 def createRepo(self, user, repo):
     user = cleanseUserName(user)
     repo = cleanseRepoName(repo)
     repos = self.reposForUser(user)
     if repo in [r["identity"] for r in repos]:
         raise GeogigError("A repository with that name already exists for the specified user") 
     self.connector.post("repos/{}/{}".format(user, repo),json={})
     self.repoCreated.emit(user, repo)
Esempio n. 7
0
 def _diffPR(self, user, repo, layerName, prID):
     user = cleanseUserName(user)
     repo = cleanseRepoName(repo)
     prID = cleansePRId(prID)
     layerName = cleanseLayerName(layerName)
     q = QueryForLayerProto(self.connector)
     try:
         return q.queryDiffPR(user, repo, layerName, prID)
     except HTTPError as ee:
         raise
     except Exception as e:
         raise GeogigError("Error getting diff from server", str(e))
Esempio n. 8
0
    def forkRepo(self, user, repo, name):
        user = cleanseUserName(user)
        repo = cleanseRepoName(repo)
        name = cleanseRepoName(name)

        repos = self.reposForUser(self.connector.user)
        if name in [r["identity"] for r in repos]:
            raise GeogigError("A repository with that name already exists for the current user")                
        query = {"forkName": name}
        taskId = self.connector.post("repos/{}/{}/forks".format(user, repo), params=query)["id"]
        self.waitForTask(taskId, "Forking repository")
        self.repoForked.emit(user, repo, name)
Esempio n. 9
0
 def checkCanCommit(self):
     if self.server.connector.user != self.user:
         raise GeogigError("You logged in with a different user. Features were not commited and will be kept in the Geogig edit buffer")
     try:
         headid = self.server.commitidForBranch(self.user, self.repo, "master")
     except GeogigAuthException:
         raise GeogigError("You are not logged in. Features were not commited and will be kept in the Geogig edit buffer")
     except GeogigError:
         raise GeogigError("Cannot connect to server. Features were not commited and will be kept in the Geogig edit buffer")
     if self.commitid=="HEAD":
         return # by definition, up to date
     if headid != self.commitid:
         filteredIds = [f[GEOGIGID_FIELD] for f in self.layer.getFeatures(QgsFeatureRequest(self.modifiedFeatures))]
         filteredIds.extend(self.deletedFeatures)
         featureFilter = {"featureIds": filteredIds}
         diff = self.server.diff(self.user, self.repo, self.layername,
                          headid, self.commitid, featureFilter)
         if diff:
             conflicts = solveConflicts(self, diff)
             if not conflicts:
                 raise GeogigError("Conflicts were not solved. Features were not commited to the repo.")
Esempio n. 10
0
    def diff(self,
             user,
             repo,
             layer,
             refspec,
             oldRef,
             featureFilter=None,
             returnAsIterator=False,
             oldRefUser=None,
             oldRefRepoName=None):
        user = cleanseUserName(user)
        repo = cleanseRepoName(repo)
        layer = cleanseLayerName(layer)
        refspec = cleanseRefSpec(refspec)
        oldRef = cleanseRefSpec(oldRef)
        q = QueryForLayerProto(self.connector)
        try:
            return q.queryDiff(user,
                               repo,
                               layer,
                               refspec,
                               oldRef,
                               featureFilter,
                               returnAsIterator=returnAsIterator,
                               oldRefUser=oldRefUser,
                               oldRefRepoName=oldRefRepoName)
        except:
            try:
                #might be a deleted layer. We try to compute the diff in reversed order of commits
                if oldRefRepoName is None:
                    diff = q.queryDiff(user, repo, layer, oldRef, refspec,
                                       featureFilter)
                else:
                    diff = q.queryDiff(oldRefUser,
                                       oldRefRepoName,
                                       layer,
                                       oldRef,
                                       refspec,
                                       featureFilter,
                                       oldRefUser=user,
                                       oldRefRepoName=repo)

                def invert(d):
                    d['geogig.changeType'] = 2
                    d['old'] = d['new']
                    d['new'] = None
                    return d

                inverted = [invert(d) for d in diff]
                return inverted
            except Exception as e:
                raise GeogigError("Error getting diff from server", str(e))
Esempio n. 11
0
 def syncBranch(self,
                user,
                repo,
                parentUser,
                parentRepo,
                transactionid,
                branch="master",
                parentBranch="master",
                commitMessage=""):
     user = cleanseUserName(user)
     repo = cleanseRepoName(repo)
     parentUser = cleanseUserName(parentUser)
     parentRepo = cleanseRepoName(parentRepo)
     branch = cleanseBranchName(branch)
     parentBranch = cleanseBranchName(parentBranch)
     transactionid = cleanseTransactionId(transactionid)
     headers = {"geogig-transaction-id": transactionid}
     pullArgs = {
         "remote_repo_owner": parentUser,
         "remote_repo_name": parentRepo,
         "remote_repo_head": parentBranch,
         "commit_message": commitMessage
     }
     ret = self.connector.post("repos/{}/{}/branches/{}/sync".format(
         user, repo, branch),
                               json=pullArgs,
                               headers=headers)
     taskId = ret["id"]
     ret = self.waitForTask(taskId, "Processing changes in server")
     layers = self.layers(user, repo)
     q = QueryForLayerProto(self.connector)
     result = {}
     conflictsFound = False
     for layerName in layers:
         try:
             conflicts = q.queryConflict(user, repo, layerName,
                                         transactionid)
             conflicts2 = {}
             if conflicts:
                 conflictsFound = True
             for conflict in conflicts:
                 conflicts2[conflict["ID"]] = {}
                 conflicts2[conflict["ID"]]["origin"] = conflict["ancestor"]
                 conflicts2[conflict["ID"]]["local"] = conflict["theirs"]
                 conflicts2[conflict["ID"]]["remote"] = conflict["ours"]
             result[layerName] = conflicts2
         except Exception as e:
             raise GeogigError("Error getting diff from server", str(e))
     if conflictsFound:
         return result
     return []
Esempio n. 12
0
    def addNewServer(self):
        params = [
            Parameter("url", "URL", "", STRING, "http://localhost:8181"),
            Parameter("name", "Name", "", STRING, "")
        ]

        urls = []
        for i in range(self.childCount()):
            serverItem = self.child(i)
            urls.append(serverItem.url)
        ret = openParametersDialog(params, "New server")
        if ret is not None:
            url = ret["url"]
            url = url + "/" if not url.endswith("/") else url
            if url in urls:
                raise GeogigError("A server item with that url already exists")
            item = ServerItem(url, ret["name"])
            self.addChild(item)
            servers = _servers()
            servers[ret["name"]] = url
            _saveServers(servers)
Esempio n. 13
0
 def populate(self):
     try:
         preloadedData = RepoDataPreloader(self.server).data
         self.usersItem = UsersItem(self.server,
                                    preloadedData=preloadedData)
         self.addChild(self.usersItem)
     except ConnectionError:
         raise GeogigError(
             "Connection error. Server not available or might not be a GeoGig server."
         )
     try:
         self.myUserItem = UserItem(
             self.connector.user,
             self.server,
             preloadedData=preloadedData["userRepos"][self.connector.user])
         self.myUserItem.setText(0, "My repos")
         self.myUserItem.setIcon(0, repoIcon)
         self.addChild(self.myUserItem)
         self.myUserItem.setExpanded(True)
     except:
         pass
     self.setExpanded(True)