def updateCurrentRepo(self, repo, name): def _update(): if repo != self.currentRepo: self.tabWidget.setCurrentIndex(0) self.filterWidget.setVisible(self.tabWidget.currentIndex() != 0) self.tabWidget.setTabEnabled(1, False) if repo is None: self.currentRepo = None self.currentRepoName = None self.repoDescription.setText("") self.lastSelectedRepoItem = None self.openButton.setEnabled(False) else: self.currentRepo = repo self.currentRepoName = name self.repoDescription.setText(repo.fullDescription) self.versionsTree.updateContent(repo.repo()) self.openButton.setEnabled(True) self.repoLayers = [tree.path for tree in self.currentRepo.repo().trees] self.versionsTree.filterLayers = None if self.layersFilterDialog is not None: self.layersFilterDialog.setLayers(self.repoLayers) self.tabWidget.setTabEnabled(1, True) self.statusWidget.updateRepository(repo) try: self.repoTree.setSelectionMode(QtGui.QAbstractItemView.NoSelection) self.repoTree.blockSignals(True) execute(_update) finally: self.repoTree.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) self.repoTree.blockSignals(False)
def computeLayerDiffs(self, layername): def _computeLayerDiff(): self.layers = self.allchanges[layername] self.createTableDataFromLayers() self.geogigidIdx = self.attribs.index("geogigid") self.changeTypeIdx = self.attribs.index("changetype") model = DiffTableModel(self.attribs, self.features) self.proxyModel = QtGui.QSortFilterProxyModel() self.proxyModel.setSourceModel(model) self.ui.attributesTable.setModel(self.proxyModel) self.ui.attributesTable.selectionModel().selectionChanged.connect(self.selectionChanged) self.ui.attributesTable.setColumnHidden(self.geogigidIdx, True) self.ui.attributesTable.resizeColumnsToContents() self.ui.attributesTable.setVisible(False) vporig = self.ui.attributesTable.viewport().geometry() vpnew = vporig vpnew.setWidth(10000) self.ui.attributesTable.viewport().setGeometry(vpnew) self.ui.attributesTable.resizeRowsToContents() self.ui.attributesTable.viewport().setGeometry(vporig) self.ui.attributesTable.setVisible(True) self.showLayers() execute(_computeLayerDiff)
def computeLayerDiffs(self, layername): def _computeLayerDiff(): self.layers = self.allchanges[layername] self.createTableDataFromLayers() self.geogigidIdx = self.attribs.index("geogigid") self.changeTypeIdx = self.attribs.index("changetype") model = DiffTableModel(self.attribs, self.features) self.proxyModel = QtGui.QSortFilterProxyModel(); self.proxyModel.setSourceModel(model) self.ui.attributesTable.setModel(self.proxyModel) self.ui.attributesTable.selectionModel().selectionChanged.connect(self.selectionChanged) self.ui.attributesTable.setColumnHidden(self.geogigidIdx, True) self.ui.attributesTable.resizeColumnsToContents() self.ui.attributesTable.setVisible(False) vporig = self.ui.attributesTable.viewport().geometry() vpnew = vporig; vpnew.setWidth(10000); self.ui.attributesTable.viewport().setGeometry(vpnew); self.ui.attributesTable.resizeRowsToContents() self.ui.attributesTable.viewport().setGeometry(vporig); self.ui.attributesTable.setVisible(True) self.showLayers() execute(_computeLayerDiff)
def __init__(self, repo, layer): self.repo = repo self.layer = layer self.ref = None QDialog.__init__(self, config.iface.mainWindow(), Qt.WindowSystemMenuHint | Qt.WindowTitleHint) execute(self.initGui)
def initGui(self): layout = QVBoxLayout() self.tab = QTabWidget() self.table = QTableView() self.setLayout(layout) self.canvas = QgsMapCanvas() self.canvas.setCanvasColor(Qt.white) settings = QSettings() self.canvas.enableAntiAliasing( settings.value("/qgis/enable_anti_aliasing", False, type=bool)) self.canvas.useImageToRender( settings.value("/qgis/use_qimage_to_render", False, type=bool)) self.canvas.mapSettings().setDestinationCrs(self.crs) action = settings.value("/qgis/wheel_action", 0, type=float) zoomFactor = settings.value("/qgis/zoom_factor", 2, type=float) self.canvas.setWheelAction(QgsMapCanvas.WheelAction(action), zoomFactor) self.panTool = QgsMapToolPan(self.canvas) self.canvas.setMapTool(self.panTool) execute(self.createLayers) model = GeomDiffTableModel(self.data) self.table.setModel(model) self.table.resizeColumnsToContents() self.table.resizeRowsToContents() self.tab.addTab(self.canvas, "Map view") self.tab.addTab(self.table, "Table view") layout.addWidget(self.tab) self.resize(600, 500) self.setWindowTitle("Geometry comparison")
def clone(url, dest, username = None, password = None): commands = ['clone', url, dest] if username is not None and password is not None: commands.extend(["--username", username, "--password", password]) port = config.getConfigValue(config.GENERAL, config.GATEWAY_PORT) setGatewayPort(port) try: execute(lambda: _runGateway(commands, os.path.dirname(__file__)), "Downloading repository data") except Py4JConnectionException: startGateway() execute(lambda: _runGateway(commands, os.path.dirname(__file__)), "Downloading repository data")
def fullDescription(self): def _prepareDescription(): footnote = "" try: ref = self.repo().head.ref footnote += ( "<p>Your current branch is set to <b>%s</b>. GeoGig will track and sync with this branch.</p>" % ref ) c = Commit.fromref(self.repo(), ref) epoch = time.mktime(c.committerdate.timetuple()) offset = datetime.fromtimestamp(epoch) - datetime.utcfromtimestamp(epoch) d = c.committerdate + offset lastDate = d.strftime("%b %d, %Y %I:%M%p") author = c.authorname lastVersion = "%s (%s by %s)" % (c.message.splitlines()[0], lastDate, author) except: lastVersion = "" with open(resourceFile("descriptiontemplate_edit.html")) as f: s = "".join(f.readlines()) s = s.replace("[NAME]", self.name) s = s.replace("[TITLE]", self.title) editIcon = os.path.dirname(__file__) + "/../ui/resources/pencil-icon.png" s = s.replace("[EDIT]", "<img src='" + editIcon + "'>") s = s.replace("[LAST_VERSION]", lastVersion) s = s.replace("[FOOTNOTE]", footnote) layers = "<dl>%s</dl>" % "".join(["<dd>%s</dd>" % tree.path for tree in self.repo().trees]) s = s.replace("[LAYERS]", layers) return s return execute(_prepareDescription)
def fullDescription(self): def _prepareDescription(): footnote = "" try: ref = self.repo().head.ref footnote += "<p>Your current branch is set to <b>%s</b>. GeoGig will track and sync with this branch.</p>" % ref c = Commit.fromref(self.repo(), ref) epoch = time.mktime(c.committerdate.timetuple()) offset = datetime.fromtimestamp( epoch) - datetime.utcfromtimestamp(epoch) d = c.committerdate + offset lastDate = d.strftime("%b %d, %Y %I:%M%p") author = c.authorname lastVersion = "%s (%s by %s)" % (c.message.splitlines()[0], lastDate, author) except: lastVersion = "" with open(resourceFile("descriptiontemplate_edit.html")) as f: s = "".join(f.readlines()) s = s.replace("[NAME]", self.name) s = s.replace("[TITLE]", self.title) editIcon = os.path.dirname( __file__) + "/../ui/resources/pencil-icon.png" s = s.replace("[EDIT]", "<img src='" + editIcon + "'>") s = s.replace("[LAST_VERSION]", lastVersion) s = s.replace("[FOOTNOTE]", footnote) layers = "<dl>%s</dl>" % "".join( ["<dd>%s</dd>" % tree.path for tree in self.repo().trees]) s = s.replace("[LAYERS]", layers) return s return (execute(_prepareDescription))
def addRepoEndpoint(url, title): global repoEndpoints global repos repoEndpoints[title] = url saveRepoEndpoints() _repos = execute(lambda: repositoriesFromUrl(url, title)) repos.extend(_repos) availableRepoEndpoints[title] = url return _repos
def deleteCurrentElement(self): if len(self.repoTree.selectedItems()) == 0: return item = self.repoTree.selectedItems()[0] if isinstance(item, RepoItem): ret = QMessageBox.warning( config.iface.mainWindow(), "Remove repository", "Are you sure you want to remove this repository and all the data in it?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if ret == QMessageBox.No: return tracked = getTrackedPathsForRepo(item.repo) item.repo.delete() removeRepo(item.repo) removeTrackedForRepo(item.repo) layers = getVectorLayers() for layer in layers: if formatSource(layer) in tracked: setAsNonRepoLayer(layer) parent = item.parent() parent.removeChild(item) self.updateCurrentRepo(None) elif isinstance(item, GroupItem): self._removeRepoEndpoint(item) elif isinstance(item, BranchItem): ret = QMessageBox.question( self, 'Delete branch', 'Are you sure you want to delete this branch?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if ret == QMessageBox.No: return item.repo.deletebranch(item.branch) repoWatcher.repoChanged.emit(item.repo) elif isinstance(item, LayerItem): ret = QMessageBox.question( self, 'Delete layer', 'Are you sure you want to delete this layer from the selected branch?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if ret == QMessageBox.No: return execute(lambda: self._removeLayer(item))
def fullDescription(self): def _prepareDescription(): try: c = self.log(limit=1)[0] epoch = time.mktime(c.committerdate.timetuple()) offset = datetime.fromtimestamp( epoch) - datetime.utcfromtimestamp(epoch) d = c.committerdate + offset lastDate = d.strftime("%b %d, %Y %I:%M%p") author = c.authorname lastVersion = "%s (%s by %s)" % (c.message.splitlines()[0], lastDate, author) except: lastVersion = "" with open(resourceFile("descriptiontemplate_edit.html")) as f: s = "".join(f.readlines()) s = s.replace("[TITLE]", self.title) s = s.replace("[URL]", self.url) s = s.replace("[LAST_VERSION]", lastVersion) layers = [] for tree in self.trees(): trackedlayer = getTrackingInfoForGeogigLayer(self.url, tree) if trackedlayer: filepath = trackedlayer.geopkg try: con = sqlite3.connect(trackedlayer.geopkg) cursor = con.cursor() cursor.execute( "SELECT commit_id FROM geogig_audited_tables WHERE table_name='%s';" % tree) commitid = cursor.fetchone()[0] cursor.close() con.close() current = commitid except: current = "Not available" else: filepath = "Not exported" current = "Not available" layer = ( "<li><b>%s <a href='checkout:%s'>[Add to QGIS]</a></b>" "<p><i>Filepath</i>: <b>%s</b></p><p><i>Current version</i>: <b>%s</b></p></li>" ) % (tree, tree, filepath, current) layers.append(layer) layers = "<ul>%s</ul>" % "".join(layers) s = s.replace("[LAYERS]", layers) s = s.replace("[LAYERNAMES]", ",".join(self.trees())) return s return (execute(_prepareDescription))
def deleteRepo(self, item): ret = QtGui.QMessageBox.warning(config.iface.mainWindow(), "Delete repository", "Are you sure you want to delete this repository?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes); if ret == QtGui.QMessageBox.No: return reponame = item.repo.name execute(lambda: deleteRepo(reponame)) self.lastSelectedRepoItem.parent().removeChild(self.lastSelectedRepoItem) if item.parent() == self.sharedVersioReposItem: self.lastSelectedRepoItem.setIcon(0, disabledRepoIcon) self.updateCurrentRepo(None, None) removeTrackedForRepo(item.repo.path) killGateway() try: shutil.rmtree(item.repo.repo().url) except: ret = QtGui.QMessageBox.warning(config.iface.mainWindow(), "Delete repository", "Local copy of repository could not be removed.\n" "It will have to be removed manually at the following path:\n" + item.repo.repo().url, QtGui.QMessageBox.Ok);
def updateCurrentRepo(self, repo): def _update(): if repo != self.currentRepo: self.tabWidget.setCurrentIndex(0) if repo is None: self.tabWidget.setTabEnabled(1, False) self.currentRepo = None self.repoDescription.setText("") else: self.currentRepo = repo self.repoDescription.setText(repo.fullDescription()) self.versionsTree.updateContent(repo) self.tabWidget.setTabEnabled(1, True) try: self.checkButtons() self.repoTree.setSelectionMode(QAbstractItemView.NoSelection) self.repoTree.blockSignals(True) execute(_update) finally: self.repoTree.setSelectionMode(QAbstractItemView.SingleSelection) self.repoTree.blockSignals(False)
def pull(self): dlg = RemoteRefDialog(self.currentRepo) dlg.exec_() if dlg.remote is not None: conflicts = execute( lambda: self.currentRepo.pull(dlg.remote, dlg.branch)) 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: self.currentRepo.closeTransaction( conflicts[0].transactionId) return dlg = ConflictDialog(conflicts) dlg.exec_() solved, resolvedConflicts = dlg.solved, dlg.resolvedConflicts if not solved: self.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) user, email = config.getUserInfo() if user is None: return self.currentRepo.commitAndCloseMergeAndTransaction( user, email, "Resolved merge conflicts", conflicts[0].transactionId) config.iface.messageBar().pushMessage( "Changes have been correctly pulled from remote", level=QgsMessageBar.INFO, duration=5) repoWatcher.repoChanged.emit(self.currentRepo) else: config.iface.messageBar().pushMessage( "Changes have been correctly pulled from remote", level=QgsMessageBar.INFO, duration=5) repoWatcher.repoChanged.emit(self.currentRepo)
def fillTree(self): self.updateCurrentRepo(None, None) self.repoTree.clear() self.reposItem = None repos = execute(localRepos) self.reposItem = OrderedParentItem("Local Repositories", 0) self.reposItem.setIcon(0, privateReposIcon) for repo in repos: item = RepoItem(repo) self.reposItem.addChild(item) if self.reposItem.childCount(): self.repoTree.addTopLevelItem(self.reposItem) self.filterRepos() self.reposItem.setExpanded(True) self.repoTree.sortItems(0, QtCore.Qt.AscendingOrder)
def computeDiffs(self): self.commit1 = self.commit1Panel.getRef() self.commit2 = self.commit2Panel.getRef() self.featuresTree.clear() changes = execute(lambda: self.repo.diff(self.commit1.commitid, self. commit2.commitid)) layerItems = {} layerSubItems = {} self.changes = {} for c in changes: self.changes[c.path] = c layername = c.path.split("/")[0] featureid = c.path.split("/")[-1] if layername not in layerItems: item = QTreeWidgetItem() item.setText(0, layername) item.setIcon(0, layerIcon) layerItems[layername] = item addedItem = QTreeWidgetItem() addedItem.setText(0, "Added") addedItem.setIcon(0, addedIcon) removedItem = QTreeWidgetItem() removedItem.setText(0, "Removed") removedItem.setIcon(0, removedIcon) modifiedItem = QTreeWidgetItem() modifiedItem.setText(0, "Modified") modifiedItem.setIcon(0, modifiedIcon) layerSubItems[layername] = { FEATURE_ADDED: addedItem, FEATURE_REMOVED: removedItem, FEATURE_MODIFIED: modifiedItem } item = FeatureItem(layername, featureid) layerSubItems[layername][c.changetype].addChild(item) for item in list(layerItems.values()): for i in [FEATURE_ADDED, FEATURE_REMOVED, FEATURE_MODIFIED]: item.addChild(layerSubItems[layername][i]) layerSubItems[layername][i].setText( 0, "%s [%i features]" % (layerSubItems[layername][i].text(0), layerSubItems[layername][i].childCount())) self.featuresTree.addTopLevelItem(item) self.attributesTable.clear() self.attributesTable.verticalHeader().hide() self.attributesTable.horizontalHeader().hide()
def readRepos(): global repos global repoEndpoints global availableRepoEndpoints repos = [] repoEndpoints = {} availableRepoEndpoints = {} filename = os.path.join(userFolder(), "repositories") if os.path.exists(filename): repoDescs = json.load(open(filename)) for r in repoDescs: repoEndpoints[r["title"]] = r["url"] try: _repos = execute( lambda: repositoriesFromUrl(r["url"], r["title"])) repos.extend(_repos) availableRepoEndpoints[r["title"]] = r["url"] except: pass
def newRepo(self, name = None): title, ok = QtGui.QInputDialog.getText(self, 'Name', 'Enter the new repository name:') if ok: try: repo = execute(lambda : createRepo(title)) item = RepoItem(RepositoryWrapper(repo.url)) except Exception, e: if "conflict" in unicode(e).lower(): text = "A repository with the specified name already exists" else: text = "There has been a problem while creating the repository\n" + unicode(e) QtGui.QMessageBox.warning(self, "Problem creating repository", text, QtGui.QMessageBox.Ok) return self.reposItem.addChild(item) self.repoTree.addTopLevelItem(self.reposItem) self.reposItem.setExpanded(True) self.repoTree.sortItems(0, QtCore.Qt.AscendingOrder) return repo
def createRepo(self): name, ok = QInputDialog.getText(self, 'Create repository', 'Enter the repository name:') if ok: groupItem = self.repoTree.selectedItems()[0] group = groupItem.text(0) url = repository.repoEndpoints[group] try: repo = execute(lambda: createRepoAtUrl(url, group, name)) except GeoGigException as e: config.iface.messageBar().pushMessage( "Error", str(e), level=QgsMessageBar.CRITICAL, duration=5) return item = RepoItem(self.repoTree, repo) addRepo(repo) groupItem.addChild(item) config.iface.messageBar().pushMessage( "Create repository", "Repository correctly created", level=QgsMessageBar.INFO, duration=5)
def newRepo(self, name = None): title, ok = QtGui.QInputDialog.getText(self, 'Name', 'Enter the new repository name:') if ok: try: repo = execute(lambda : createRepo(title)) item = RepoItem(RepositoryWrapper(repo.url)) except Exception, e: if "conflict" in unicode(e).lower(): text = "A repository with the specified name already exists" else: text = "There has been a problem while creating the repository\n" + unicode(e) QtGui.QMessageBox.warning(self, "Problem creating repository", text, QtGui.QMessageBox.Ok) return self.reposItem.addChild(item) self.ui.repoTree.addTopLevelItem(self.reposItem) self.reposItem.setExpanded(True) self.ui.repoTree.sortItems(0, QtCore.Qt.AscendingOrder) return repo
def startGateway(): _logger.debug("GeoGig gateway not started. Will try to start it") if not os.path.exists(geogigPath()): _logger.debug("GeoGig path (%s) does not exist. Cannot start gateway" % geogigPath()) return try: _logger.debug("Trying to start gateway at %s" % (geogigPath())) def _startGateway(): if jrePath(): os.environ["JAVA_HOME"] = jrePath() if os.name == "nt": os.environ["JAVACMD"] = os.path.join(jrePath(), "bin", "java") global _proc if os.name == 'nt': _proc = subprocess.Popen([os.path.join(geogigPath() , "geogig-gateway.bat")], shell = True) else: _proc = subprocess.Popen(os.path.join(geogigPath(), "geogig-gateway"), stdout = subprocess.PIPE, stdin = subprocess.PIPE) port = config.getConfigValue(config.GENERAL, config.GATEWAY_PORT) gateway = JavaGateway(GatewayClient(port = int(port))) success = False retries = int(config.getConfigValue(config.GENERAL, config.TIMEOUT)) for i in range(retries): try: gateway.entry_point.isGeoGigServer() success = True break except Exception, e: time.sleep(1) return success success = execute(_startGateway, "Starting local GeoGig engine") if success: _logger.debug("Gateway correctly started") else: raise Exception("Gateway not available")
def runDecorated(self, func, progressMessage = None): port = config.getConfigValue(config.GENERAL, config.GATEWAY_PORT) setGatewayPort(port) if not self._showProgress: progressMessage = None return execute(func, progressMessage)
def __init__(self, repo, layer): self.repo = repo self.layer = layer QtGui.QDialog.__init__(self, config.iface.mainWindow(), QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint) execute(self.initGui)
def _apicall(self, command, payload={}, transaction=False): return execute(lambda: self.__apicall(command, payload, transaction))
def geogigVersion(): try: from geogigpy.py4jconnector import geogigVersion as _geogigVersion return execute(_geogigVersion) except: return "Cannot resolve geogig version. Geogigpy version is too old"