def __init__(self): super(NavigatorDialog, self).__init__(None) self.currentRepo = None self.reposItem = None self.setupUi(self) self.repoTree.setContextMenuPolicy(Qt.CustomContextMenu) self.repoTree.setSelectionBehavior(QAbstractItemView.SelectRows) self.repoTree.itemSelectionChanged.connect(self.selectionChanged) self.repoTree.customContextMenuRequested.connect(self.showPopupMenu) self.comboEndpoint.currentIndexChanged.connect(self.fillTree) self.btnAddServer.setIcon(icon("add-server.svg")) self.btnEditServer.setIcon(icon("edit-server.svg")) self.btnDeleteServer.setIcon(icon("delete-server.svg")) self.btnAddRepo.setIcon(icon("add-repository.svg")) self.btnRefresh.setIcon(icon("refresh.svg")) self.btnAddServer.clicked.connect(self.addGeoGigServer) self.btnEditServer.clicked.connect(self.editGeoGigServer) self.btnDeleteServer.clicked.connect(self.deleteGeoGigServer) self.btnAddRepo.clicked.connect(self.createRepo) self.btnRefresh.clicked.connect(self.fillTree) self._enableOrDisableButtons() if qtVersion < 5: self.repoTree.header().setResizeMode(0, QHeaderView.Stretch) self.repoTree.header().setResizeMode(1, QHeaderView.ResizeToContents) self.versionsTree = HistoryViewer() layout = QVBoxLayout() layout.addWidget(QLabel("Repository history")) layout.addWidget(self.versionsTree) self.versionsWidget.setLayout(layout) def _repoChanged(repo): if self.currentRepo is not None and repo.url == self.currentRepo.url: self.updateCurrentRepo(repo, True) for i in range(self.repoTree.topLevelItemCount()): item = self.repoTree.topLevelItem(i) if item.repo == repo: item.refreshContent() repoWatcher.repoChanged.connect(_repoChanged) self.updateNavigator() self.repoTree.itemExpanded.connect(self._itemExpanded)
def __init__(self): super(NavigatorDialog, self).__init__(None) self.currentRepo = None self.reposItem = None self.setupUi(self) self.repoTree.setContextMenuPolicy(Qt.CustomContextMenu) self.repoTree.setSelectionBehavior(QAbstractItemView.SelectRows) self.repoTree.itemSelectionChanged.connect(self.selectionChanged) self.repoTree.customContextMenuRequested.connect(self.showPopupMenu) self.comboEndpoint.currentIndexChanged.connect(self.fillTree) self.btnAddServer.setIcon(icon("add-server.svg")) self.btnEditServer.setIcon(icon("edit-server.svg")) self.btnDeleteServer.setIcon(icon("delete-server.svg")) self.btnAddRepo.setIcon(icon("add-repository.svg")) self.btnRefresh.setIcon(icon("refresh.svg")) self.btnAddServer.clicked.connect(self.addGeoGigServer) self.btnEditServer.clicked.connect(self.editGeoGigServer) self.btnDeleteServer.clicked.connect(self.deleteGeoGigServer) self.btnAddRepo.clicked.connect(self.createRepo) self.btnRefresh.clicked.connect(self.fillTree) self.btnRefresh.clicked.connect(self.refreshTree) self._enableOrDisableButtons() if qtVersion < 5: self.repoTree.header().setResizeMode(0, QHeaderView.Stretch) self.repoTree.header().setResizeMode(1, QHeaderView.ResizeToContents) self.versionsTree = HistoryViewer() layout = QVBoxLayout() layout.addWidget(QLabel("Repository history")) layout.addWidget(self.versionsTree) self.versionsWidget.setLayout(layout) def _repoChanged(repo): if self.currentRepo is not None and repo.url == self.currentRepo.url: self.updateCurrentRepo(repo, True) for i in range(self.repoTree.topLevelItemCount()): item = self.repoTree.topLevelItem(i) if item.repo == repo: item.refreshContent() repoWatcher.repoChanged.connect(_repoChanged) self.updateNavigator() self.repoTree.itemExpanded.connect(self._itemExpanded)
def __init__(self): QtGui.QDialog.__init__(self, config.iface.mainWindow(), QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint) self.currentRepo = None self.currentRepoName = None self.privateVersioReposItem = None self.sharedVersioReposItem = None self.reposItem = None self.localOnlyVersioReposItem = None self.ui = Ui_NavigatorDialog() self.ui.setupUi(self) self.ui.filterBox.adjustSize() tabHeight = self.ui.filterBox.height() + self.ui.filterBox.parent().layout().spacing() self.ui.tabWidget.setStyleSheet("QTabWidget::pane {border: 0;} QTabBar::tab { height: %ipx}" % tabHeight); self.ui.newRepoButton.clicked.connect(self.newRepo) self.ui.openButton.clicked.connect(self.openRepo) self.ui.filterBox.textChanged.connect(self.filterRepos) self.ui.repoTree.itemClicked.connect(self.treeItemClicked) self.ui.filterButton.clicked.connect(self.showFilterPopup) self.ui.clearFilterButton.clicked.connect(self.clearFilter) self.ui.tabWidget.currentChanged.connect(self.tabChanged) self.ui.repoTree.customContextMenuRequested.connect(self.showRepoTreePopupMenu) self.ui.repoDescription.setOpenLinks(False) self.connect(self.ui.repoDescription, QtCore.SIGNAL("anchorClicked(const QUrl&)"), self.descriptionLinkClicked) self.ui.repoTree.setFocusPolicy(QtCore.Qt.NoFocus) with open(resourceFile("repodescription.css")) as f: sheet = "".join(f.readlines()) self.ui.repoDescription.document().setDefaultStyleSheet(sheet) self.ui.repoTree.header().setResizeMode(0, QtGui.QHeaderView.Stretch) self.ui.repoTree.header().setResizeMode(1, QtGui.QHeaderView.ResizeToContents) self.statusWidget = StatusWidget() layout = QtGui.QVBoxLayout() layout.setSpacing(0) layout.setMargin(0) layout.addWidget(self.statusWidget) self.ui.statusWidget.setLayout(layout) self.versionsTree = HistoryViewer() layout = QtGui.QVBoxLayout() layout.setSpacing(0) layout.setMargin(0) layout.addWidget(self.versionsTree) self.ui.versionsWidget.setLayout(layout) self.ui.tabWidget.setCornerWidget(self.ui.filterWidget) self.ui.clearFilterButton.setEnabled(False) self.versionsTree.headChanged.connect(self.updateBranchLabel) self.versionsTree.repoChanged.connect(self.statusWidget.updateLabelText) self.statusWidget.repoChanged.connect(self.versionsTree.updateCurrentBranchItem) self.lastSelectedRepoItem = None self.fillTree() self.updateCurrentRepo(None, None) self.layersFilterDialog = None self.repoLayers = []
class NavigatorDialog(QtGui.QDialog): def __init__(self): QtGui.QDialog.__init__(self, config.iface.mainWindow(), QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint) self.currentRepo = None self.currentRepoName = None self.privateVersioReposItem = None self.sharedVersioReposItem = None self.reposItem = None self.localOnlyVersioReposItem = None self.ui = Ui_NavigatorDialog() self.ui.setupUi(self) self.ui.filterBox.adjustSize() tabHeight = self.ui.filterBox.height() + self.ui.filterBox.parent().layout().spacing() self.ui.tabWidget.setStyleSheet("QTabWidget::pane {border: 0;} QTabBar::tab { height: %ipx}" % tabHeight); self.ui.newRepoButton.clicked.connect(self.newRepo) self.ui.openButton.clicked.connect(self.openRepo) self.ui.filterBox.textChanged.connect(self.filterRepos) self.ui.repoTree.itemClicked.connect(self.treeItemClicked) self.ui.filterButton.clicked.connect(self.showFilterPopup) self.ui.clearFilterButton.clicked.connect(self.clearFilter) self.ui.tabWidget.currentChanged.connect(self.tabChanged) self.ui.repoTree.customContextMenuRequested.connect(self.showRepoTreePopupMenu) self.ui.repoDescription.setOpenLinks(False) self.connect(self.ui.repoDescription, QtCore.SIGNAL("anchorClicked(const QUrl&)"), self.descriptionLinkClicked) self.ui.repoTree.setFocusPolicy(QtCore.Qt.NoFocus) with open(resourceFile("repodescription.css")) as f: sheet = "".join(f.readlines()) self.ui.repoDescription.document().setDefaultStyleSheet(sheet) self.ui.repoTree.header().setResizeMode(0, QtGui.QHeaderView.Stretch) self.ui.repoTree.header().setResizeMode(1, QtGui.QHeaderView.ResizeToContents) self.statusWidget = StatusWidget() layout = QtGui.QVBoxLayout() layout.setSpacing(0) layout.setMargin(0) layout.addWidget(self.statusWidget) self.ui.statusWidget.setLayout(layout) self.versionsTree = HistoryViewer() layout = QtGui.QVBoxLayout() layout.setSpacing(0) layout.setMargin(0) layout.addWidget(self.versionsTree) self.ui.versionsWidget.setLayout(layout) self.ui.tabWidget.setCornerWidget(self.ui.filterWidget) self.ui.clearFilterButton.setEnabled(False) self.versionsTree.headChanged.connect(self.updateBranchLabel) self.versionsTree.repoChanged.connect(self.statusWidget.updateLabelText) self.statusWidget.repoChanged.connect(self.versionsTree.updateCurrentBranchItem) self.lastSelectedRepoItem = None self.fillTree() self.updateCurrentRepo(None, None) self.layersFilterDialog = None self.repoLayers = [] def descriptionLinkClicked(self, url): url = url.toString() if url == "title": text, ok = QtGui.QInputDialog.getText(self, 'Title', 'Enter the new repository title:', text = self.currentRepo.title) if ok: self.currentRepo.title = text self.ui.repoDescription.setText(self.currentRepo.fullDescription) self.lastSelectedRepoItem.refreshTitle() def fillTree(self): self.updateCurrentRepo(None, None) self.ui.repoTree.clear() self.reposItem = None self.privateVersioReposItem = None self.sharedVersioReposItem = None self.localOnlyVersioReposItem = None self.downloadedPublicVersioReposItem = 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.ui.repoTree.addTopLevelItem(self.reposItem) self.filterRepos() self.reposItem.setExpanded(True) self.ui.repoTree.sortItems(0, QtCore.Qt.AscendingOrder) def showFilterPopup(self): if self.layersFilterDialog is None: self.layersFilterDialog = LayersFilterDialog(self.repoLayers, self.ui.filterButton, self) self.layersFilterDialog.filterLayersChanged.connect(self.filterLayersChanged) self.layersFilterDialog.filterTextChanged.connect(self.filterTextChanged) self.layersFilterDialog.setFilterLayers(self.versionsTree.filterLayers) self.layersFilterDialog.setFilterText(self.versionsTree.filterText) self.layersFilterDialog.show() def clearFilter(self): self.versionsTree.filterLayers = None self.versionsTree.filterText = "" self.ui.clearFilterButton.setEnabled(False) def tabChanged(self, i): self.ui.filterButton.setVisible(i != 0) def filterLayersChanged(self): enabled = self.layersFilterDialog.filterText.strip() != "" or self.versionsTree.filterLayers is not None self.ui.clearFilterButton.setEnabled(enabled) self.versionsTree.filterLayers = self.layersFilterDialog.filterLayers def filterTextChanged(self): enabled = self.layersFilterDialog.filterText.strip() != "" or self.versionsTree.filterLayers is not None self.ui.clearFilterButton.setEnabled(enabled) self.versionsTree.filterText = self.layersFilterDialog.filterText def showHistoryTab(self): self.ui.historyTabButton.setAutoRaise(False) self.ui.descriptionTabButton.setAutoRaise(True) self.ui.versionsWidget.setVisible(True) self.ui.repoDescription.setVisible(False) self.ui.filterButton.setVisible(True) self.ui.filterButton.setEnabled(len(self.repoLayers) != 0) def showDescriptionTab(self): self.ui.historyTabButton.setAutoRaise(True) self.ui.descriptionTabButton.setAutoRaise(False) self.ui.versionsWidget.setVisible(False) self.ui.repoDescription.setVisible(True) self.ui.filterButton.setVisible(False) def showRepoTreePopupMenu(self, point): item = self.ui.repoTree.selectedItems()[0] if isinstance(item, RepoItem): menu = QtGui.QMenu() addAction = QtGui.QAction(addIcon, "Add layer to repository...", None) addAction.triggered.connect(self.addLayer) menu.addAction(addAction) addMultipleAction = QtGui.QAction(addIcon, "Add multiple snapshots of a layer to repository...", None) addMultipleAction.triggered.connect(self.batchImport) menu.addAction(addMultipleAction) deleteAction = QtGui.QAction(deleteIcon, "Delete this repository", None) deleteAction.triggered.connect(lambda: self.deleteRepo(item)) menu.addAction(deleteAction) deleteAction = QtGui.QAction(deleteIcon, "Delete this repository", None) deleteAction.triggered.connect(lambda: self.deleteRepo(item)) menu.addAction(deleteAction) syncAction = QtGui.QAction(syncIcon, "Open Sync dialog for this repository...", None) syncAction.triggered.connect(lambda: self.syncRepo(item)) menu.addAction(syncAction) point = self.ui.repoTree.mapToGlobal(point) menu.exec_(point) def syncRepo(self, item): dlg = SyncDialog(item.repo.repo(), item.repo.title) dlg.exec_() if dlg.conflicts: self.statusWidget.updateLabelText() if dlg.pulled: updateTrackedLayers(item.repo.repo()) self.versionsTree.updateCurrentBranchItem self.statusWidget.updateLabelText() elif dlg.pushed: self.statusWidget.updateLabelText() def batchImport(self): dlg = BatchImportDialog(self, repo = self.currentRepo.repo()) dlg.exec_() if dlg.ok: self.versionsTree.updateCurrentBranchItem() self.statusWidget.updateLabelText() def addLayer(self): layers = [layer for layer in getVectorLayers() if layer.source().lower().endswith("shp") and not isTracked(layer)] if layers: dlg = ImportDialog(self, repo = self.currentRepo.repo()) dlg.exec_() if dlg.ok: self.versionsTree.updateCurrentBranchItem() self.statusWidget.updateLabelText() else: QtGui.QMessageBox.warning(self, 'Cannot add layer', "No suitable layers can be found in your current QGIS project.\n" "Open the layers in QGIS before trying to add them.", QtGui.QMessageBox.Ok) 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 openRepo(self, ref): exportFullRepo(self.currentRepo.repo()) loadRepoExportedLayers(self.currentRepo.repo()) config.iface.messageBar().pushMessage("Repository layers correctly added to QGIS project", level = QgsMessageBar.INFO, duration = 4) def filterRepos(self): text = self.ui.filterBox.text().strip() for i in xrange(self.ui.repoTree.topLevelItemCount()): parent = self.ui.repoTree.topLevelItem(i) for j in xrange(parent.childCount()): item = parent.child(j) itemText = item.text(0) item.setHidden(text != "" and text not in itemText) def treeItemClicked(self, item, i): if self.lastSelectedRepoItem == item: return self.lastSelectedRepoItem = item if isinstance(item, RepoItem): self.updateCurrentRepo(item.repo, item.text(0)) else: self.updateCurrentRepo(None, None) url = QtCore.QUrl.fromLocalFile(resourceFile("localrepos_offline.html")) self.ui.repoDescription.setSource(url) def updateCurrentRepo(self, repo, name): def _update(): if repo != self.currentRepo: self.ui.tabWidget.setCurrentIndex(0) self.ui.filterButton.setVisible(self.ui.tabWidget.currentIndex() != 0) self.ui.tabWidget.setTabEnabled(1, False) if repo is None: self.currentRepo = None self.currentRepoName = None self.ui.repoDescription.setText("") self.lastSelectedRepoItem = None self.ui.openButton.setVisible(False) self.ui.repoWidget.setVisible(False) self.ui.downloadButton.setVisible(False) self.ui.placeholderWidget.setVisible(True) else: self.currentRepo = repo self.currentRepoName = name self.ui.repoDescription.setText(repo.fullDescription) self.versionsTree.updateContent(repo.repo()) self.ui.openButton.setVisible(True) self.ui.downloadButton.setVisible(False) self.updateBranchLabel() self.ui.repoWidget.setVisible(True) self.ui.placeholderWidget.setVisible(False) 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.ui.tabWidget.setTabEnabled(1, True) self.statusWidget.updateRepository(repo) self.ui.downloadButton.setFixedHeight(self.ui.statusWidget.height()) self.ui.repoWidget.setFixedHeight(self.ui.statusWidget.height()) self.ui.placeholderWidget.setFixedHeight(self.ui.statusWidget.height()) try: self.ui.repoTree.setSelectionMode(QtGui.QAbstractItemView.NoSelection) self.ui.repoTree.blockSignals(True) execute(_update) finally: self.ui.repoTree.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) self.ui.repoTree.blockSignals(False) def updateBranchLabel(self): self.ui.branchLabel.setText("The current branch is <b>%s</b>" % self.versionsTree.head) self.ui.repoDescription.setText(self.currentRepo.fullDescription) 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
class NavigatorDialog(BASE, WIDGET): def __init__(self): super(NavigatorDialog, self).__init__(None) self.currentRepo = None self.reposItem = None self.setupUi(self) self.repoTree.setContextMenuPolicy(Qt.CustomContextMenu) self.repoTree.setSelectionBehavior(QAbstractItemView.SelectRows) self.repoTree.itemSelectionChanged.connect(self.selectionChanged) self.repoTree.customContextMenuRequested.connect(self.showPopupMenu) self.comboEndpoint.currentIndexChanged.connect(self.fillTree) self.btnAddServer.setIcon(icon("add-server.svg")) self.btnEditServer.setIcon(icon("edit-server.svg")) self.btnDeleteServer.setIcon(icon("delete-server.svg")) self.btnAddRepo.setIcon(icon("add-repository.svg")) self.btnRefresh.setIcon(icon("refresh.svg")) self.btnAddServer.clicked.connect(self.addGeoGigServer) self.btnEditServer.clicked.connect(self.editGeoGigServer) self.btnDeleteServer.clicked.connect(self.deleteGeoGigServer) self.btnAddRepo.clicked.connect(self.createRepo) self.btnRefresh.clicked.connect(self.fillTree) self.btnRefresh.clicked.connect(self.refreshTree) self._enableOrDisableButtons() if qtVersion < 5: self.repoTree.header().setResizeMode(0, QHeaderView.Stretch) self.repoTree.header().setResizeMode(1, QHeaderView.ResizeToContents) self.versionsTree = HistoryViewer() layout = QVBoxLayout() layout.addWidget(QLabel("Repository history")) layout.addWidget(self.versionsTree) self.versionsWidget.setLayout(layout) def _repoChanged(repo): if self.currentRepo is not None and repo.url == self.currentRepo.url: self.updateCurrentRepo(repo, True) for i in range(self.repoTree.topLevelItemCount()): item = self.repoTree.topLevelItem(i) if item.repo == repo: item.refreshContent() repoWatcher.repoChanged.connect(_repoChanged) self.updateNavigator() self.repoTree.itemExpanded.connect(self._itemExpanded) def showPopupMenu(self, point): item = self.repoTree.currentItem() self.menu = item.menu() point = self.repoTree.mapToGlobal(point) self.menu.popup(point) def updateNavigator(self): self.fillCombo() self.updateCurrentRepo(None) #self.checkButtons() def _itemExpanded(self, item): if item is not None and isinstance(item, (RepoItem, BranchItem)): item.populate() def _checkoutLayer(self, layername, bbox): checkoutLayer(self.currentRepo, layername, bbox) def fillCombo(self): self.comboEndpoint.clear() groups = repository.repoEndpoints.keys() #groups.insert(0, "Select a GeoGig server") self.comboEndpoint.addItems(groups) def refreshTree(self): groupName = self.comboEndpoint.currentText() repository.refreshEndpoint(groupName) self.fillTree() def fillTree(self): groupName = self.comboEndpoint.currentText() #repository.refreshEndpoint(groupName) self.btnAddRepo.setEnabled(groupName in repository.availableRepoEndpoints) self.updateCurrentRepo(None) self.repoTree.clear() groupRepos = repository.endpointRepos(groupName) for repo in groupRepos: try: item = RepoItem(self, self.repoTree, repo) self.repoTree.addTopLevelItem(item) except: #TODO: inform of failed repos pass self.repoTree.sortItems(0, Qt.AscendingOrder) def selectionChanged(self): items = self.repoTree.selectedItems() if items: self.updateCurrentRepo(items[0].repo) else: self.updateCurrentRepo(None) def updateCurrentRepo(self, repo, force=False): if repo == self.currentRepo and not force: return def _update(): self.currentRepo = repo self.versionsTree.updateContent(repo) try: self.repoTree.setSelectionMode(QAbstractItemView.NoSelection) self.repoTree.blockSignals(True) execute(_update) finally: self.repoTree.setSelectionMode(QAbstractItemView.SingleSelection) self.repoTree.blockSignals(False) def createRepo(self): name, ok = QInputDialog.getText(self, 'Create repository', 'Enter the repository name:') if ok: group = self.comboEndpoint.currentText() 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, self.repoTree, repo) addRepo(repo) self.repoTree.addTopLevelItem(item) config.iface.messageBar().pushMessage("Create repository", "Repository correctly created", level=QgsMessageBar.INFO, duration=5) def editGeoGigServer(self): group = self.comboEndpoint.currentText() dlg = GeoGigServerDialog(repository.repoEndpoints[group], group) dlg.setWindowTitle("Edit GeoGig server") dlg.exec_() if dlg.title is not None: removeRepoEndpoint(group) self.comboEndpoint.removeItem(self.comboEndpoint.currentIndex()) self._addGeoGigServer(dlg.title, dlg.url) def deleteGeoGigServer(self): group = self.comboEndpoint.currentText() res = QMessageBox.question(None, "Delete server?", "Are you sure you want to remove the " "'{}' GeoGig server from the list?".format(group), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if res == QMessageBox.Yes: removeRepoEndpoint(group) self.comboEndpoint.removeItem(self.comboEndpoint.currentIndex()) self.fillTree() self._enableOrDisableButtons() def addGeoGigServer(self): dlg = GeoGigServerDialog() dlg.exec_() if dlg.title is not None: self._addGeoGigServer(dlg.title, dlg.url) self._enableOrDisableButtons() def _addGeoGigServer(self, title, url): try: repos = addRepoEndpoint(url, title) if not repos: msg = "No repositories found at the specified server" QMessageBox.warning(self, 'Add repositories', "No repositories found at the specified server", QMessageBox.Ok) except Exception as e: msg = "No geogig server found at the specified url. %s" QgsMessageLog.logMessage(msg % e, level=QgsMessageLog.CRITICAL) QMessageBox.warning(self, 'Add repositories', msg % "See the logs for details.", QMessageBox.Ok) self.comboEndpoint.addItem(title) self.comboEndpoint.setCurrentIndex(self.comboEndpoint.count() - 1) def _enableOrDisableButtons(self): self.btnEditServer.setEnabled(len(repository.repoEndpoints) > 0) self.btnDeleteServer.setEnabled(len(repository.repoEndpoints) > 0)
def __init__(self): super(NavigatorDialog, self).__init__(None) self.currentRepo = None self.currentRepoName = None self.reposItem = None self.setupUi(self) self.setAllowedAreas(QtCore.Qt.RightDockWidgetArea | QtCore.Qt.LeftDockWidgetArea) self.filterBox.adjustSize() tabHeight = self.filterBox.height() + self.filterBox.parent().layout().spacing() self.tabWidget.setStyleSheet("QTabWidget::pane {border: 0;} QTabBar::tab { height: %ipx}" % tabHeight); self.newRepoButton.clicked.connect(self.newRepo) self.openButton.clicked.connect(self.openRepo) self.filterBox.textChanged.connect(self.filterRepos) self.repoTree.itemClicked.connect(self.treeItemClicked) self.filterButton.clicked.connect(self.showFilterPopup) self.clearFilterButton.clicked.connect(self.clearFilter) self.tabWidget.currentChanged.connect(self.tabChanged) self.repoTree.customContextMenuRequested.connect(self.showRepoTreePopupMenu) self.repoDescription.setOpenLinks(False) self.repoDescription.anchorClicked.connect(self.descriptionLinkClicked) self.repoTree.setFocusPolicy(QtCore.Qt.NoFocus) with open(resourceFile("repodescription.css")) as f: sheet = "".join(f.readlines()) self.repoDescription.document().setDefaultStyleSheet(sheet) self.repoTree.header().setResizeMode(0, QtGui.QHeaderView.Stretch) self.repoTree.header().setResizeMode(1, QtGui.QHeaderView.ResizeToContents) self.statusWidget = StatusWidget() layout = QtGui.QVBoxLayout() layout.setSpacing(0) layout.setMargin(0) layout.addWidget(self.statusWidget) self.repoWidget.setLayout(layout) self.versionsTree = HistoryViewer() layout = QtGui.QVBoxLayout() layout.setSpacing(0) layout.setMargin(0) layout.addWidget(self.versionsTree) self.versionsWidget.setLayout(layout) self.tabWidget.setCornerWidget(self.filterWidget) self.clearFilterButton.setEnabled(False) self.versionsTree.headChanged.connect(self.statusWidget.updateLabelText) self.versionsTree.repoChanged.connect(self.statusWidget.updateLabelText) self.statusWidget.repoChanged.connect(self.versionsTree.updateCurrentBranchItem) self.lastSelectedRepoItem = None def _updateDescription(repo): if self.currentRepo is not None and repo.url == self.currentRepo.repo().url: self.updateCurrentRepoDescription() self.versionsTree.updateCurrentBranchItem() self.statusWidget.updateLabelText() repoWatcher.repoChanged.connect(_updateDescription) self.updateNavigator()
class NavigatorDialog(BASE, WIDGET): def __init__(self): super(NavigatorDialog, self).__init__(None) self.currentRepo = None self.currentRepoName = None self.reposItem = None self.setupUi(self) self.setAllowedAreas(QtCore.Qt.RightDockWidgetArea | QtCore.Qt.LeftDockWidgetArea) self.filterBox.adjustSize() tabHeight = self.filterBox.height() + self.filterBox.parent().layout().spacing() self.tabWidget.setStyleSheet("QTabWidget::pane {border: 0;} QTabBar::tab { height: %ipx}" % tabHeight); self.newRepoButton.clicked.connect(self.newRepo) self.openButton.clicked.connect(self.openRepo) self.filterBox.textChanged.connect(self.filterRepos) self.repoTree.itemClicked.connect(self.treeItemClicked) self.filterButton.clicked.connect(self.showFilterPopup) self.clearFilterButton.clicked.connect(self.clearFilter) self.tabWidget.currentChanged.connect(self.tabChanged) self.repoTree.customContextMenuRequested.connect(self.showRepoTreePopupMenu) self.repoDescription.setOpenLinks(False) self.repoDescription.anchorClicked.connect(self.descriptionLinkClicked) self.repoTree.setFocusPolicy(QtCore.Qt.NoFocus) with open(resourceFile("repodescription.css")) as f: sheet = "".join(f.readlines()) self.repoDescription.document().setDefaultStyleSheet(sheet) self.repoTree.header().setResizeMode(0, QtGui.QHeaderView.Stretch) self.repoTree.header().setResizeMode(1, QtGui.QHeaderView.ResizeToContents) self.statusWidget = StatusWidget() layout = QtGui.QVBoxLayout() layout.setSpacing(0) layout.setMargin(0) layout.addWidget(self.statusWidget) self.repoWidget.setLayout(layout) self.versionsTree = HistoryViewer() layout = QtGui.QVBoxLayout() layout.setSpacing(0) layout.setMargin(0) layout.addWidget(self.versionsTree) self.versionsWidget.setLayout(layout) self.tabWidget.setCornerWidget(self.filterWidget) self.clearFilterButton.setEnabled(False) self.versionsTree.headChanged.connect(self.statusWidget.updateLabelText) self.versionsTree.repoChanged.connect(self.statusWidget.updateLabelText) self.statusWidget.repoChanged.connect(self.versionsTree.updateCurrentBranchItem) self.lastSelectedRepoItem = None def _updateDescription(repo): if self.currentRepo is not None and repo.url == self.currentRepo.repo().url: self.updateCurrentRepoDescription() self.versionsTree.updateCurrentBranchItem() self.statusWidget.updateLabelText() repoWatcher.repoChanged.connect(_updateDescription) self.updateNavigator() def updateNavigator(self): self.fillTree() self.updateCurrentRepo(None, None) self.layersFilterDialog = None self.repoLayers = [] def descriptionLinkClicked(self, url): url = url.toString() if url == "title": text, ok = QtGui.QInputDialog.getText(self, 'Title', 'Enter the new repository title:', text = self.currentRepo.title) if ok: self.currentRepo.title = text self.updateCurrentRepoDescription() self.lastSelectedRepoItem.refreshTitle() def updateCurrentRepoDescription(self): self.repoDescription.setText(self.currentRepo.fullDescription) 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 showFilterPopup(self): if self.layersFilterDialog is None: self.layersFilterDialog = LayersFilterDialog(self.repoLayers, self.filterButton, self) self.layersFilterDialog.filterLayersChanged.connect(self.filterLayersChanged) self.layersFilterDialog.filterTextChanged.connect(self.filterTextChanged) self.layersFilterDialog.setFilterLayers(self.versionsTree.filterLayers) self.layersFilterDialog.setFilterText(self.versionsTree.filterText) self.layersFilterDialog.show() def clearFilter(self): self.versionsTree.filterLayers = None self.versionsTree.filterText = "" self.clearFilterButton.setEnabled(False) def tabChanged(self, i): self.filterWidget.setVisible(i != 0) def filterLayersChanged(self): enabled = self.layersFilterDialog.filterText.strip() != "" or self.versionsTree.filterLayers is not None self.clearFilterButton.setEnabled(enabled) self.versionsTree.filterLayers = self.layersFilterDialog.filterLayers def filterTextChanged(self): enabled = self.layersFilterDialog.filterText.strip() != "" or self.versionsTree.filterLayers is not None self.clearFilterButton.setEnabled(enabled) self.versionsTree.filterText = self.layersFilterDialog.filterText def showHistoryTab(self): self.historyTabButton.setAutoRaise(False) self.descriptionTabButton.setAutoRaise(True) self.versionsWidget.setVisible(True) self.repoDescription.setVisible(False) self.filterWidget.setVisible(True) self.filterButton.setEnabled(len(self.repoLayers) != 0) def showDescriptionTab(self): self.historyTabButton.setAutoRaise(True) self.descriptionTabButton.setAutoRaise(False) self.versionsWidget.setVisible(False) self.repoDescription.setVisible(True) self.filterWidget.setVisible(False) def showRepoTreePopupMenu(self, point): item = self.repoTree.selectedItems()[0] if isinstance(item, RepoItem): menu = QtGui.QMenu() addAction = QtGui.QAction(addIcon, "Add layer to repository...", None) addAction.triggered.connect(self.addLayer) menu.addAction(addAction) addMultipleAction = QtGui.QAction(addIcon, "Add multiple snapshots of a layer to repository...", None) addMultipleAction.triggered.connect(self.batchImport) menu.addAction(addMultipleAction) deleteAction = QtGui.QAction(deleteIcon, "Delete this repository", None) deleteAction.triggered.connect(lambda: self.deleteRepo(item)) menu.addAction(deleteAction) deleteAction = QtGui.QAction(deleteIcon, "Delete this repository", None) deleteAction.triggered.connect(lambda: self.deleteRepo(item)) menu.addAction(deleteAction) syncAction = QtGui.QAction(syncIcon, "Open Sync dialog for this repository...", None) syncAction.triggered.connect(lambda: self.syncRepo(item)) menu.addAction(syncAction) point = self.repoTree.mapToGlobal(point) menu.exec_(point) def syncRepo(self, item): dlg = SyncDialog(item.repo.repo(), item.repo.title) dlg.exec_() if dlg.conflicts: self.statusWidget.updateLabelText() if dlg.pulled: updateTrackedLayers(item.repo.repo()) self.versionsTree.updateCurrentBranchItem() self.statusWidget.updateLabelText() elif dlg.pushed: self.statusWidget.updateLabelText() self.updateCurrentRepoDescription() def batchImport(self): dlg = BatchImportDialog(self, repo = self.currentRepo.repo()) dlg.exec_() if dlg.ok: self.versionsTree.updateCurrentBranchItem() self.statusWidget.updateLabelText() self.updateCurrentRepoDescription() def addLayer(self): layers = [layer for layer in getVectorLayers() if layer.source().lower().endswith("shp") and not isTracked(layer)] if layers: dlg = ImportDialog(self, repo = self.currentRepo.repo()) dlg.exec_() if dlg.ok: self.versionsTree.updateCurrentBranchItem() self.statusWidget.updateLabelText() self.updateCurrentRepoDescription() setAsTracked(dlg.layer) else: QtGui.QMessageBox.warning(self, 'Cannot add layer', "No suitable layers can be found in your current QGIS project.\n" "Open the layers in QGIS before trying to add them.", QtGui.QMessageBox.Ok) 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 self.lastSelectedRepoItem.parent().removeChild(self.lastSelectedRepoItem) self.updateCurrentRepo(None, None) tracked = getTrackedPathsForRepo(item.repo.repo()) layers = getVectorLayers() for layer in layers: if layer.source() in tracked: setAsUntracked(layer) 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 openRepo(self, ref): exportFullRepo(self.currentRepo.repo()) loadRepoExportedLayers(self.currentRepo.repo()) config.iface.messageBar().pushMessage("Repository layers correctly added to QGIS project", level = QgsMessageBar.INFO, duration = 4) def filterRepos(self): text = self.filterBox.text().strip() for i in xrange(self.repoTree.topLevelItemCount()): parent = self.repoTree.topLevelItem(i) for j in xrange(parent.childCount()): item = parent.child(j) itemText = item.text(0) item.setHidden(text != "" and text not in itemText) def treeItemClicked(self, item, i): if self.lastSelectedRepoItem == item: return self.lastSelectedRepoItem = item if isinstance(item, RepoItem): self.updateCurrentRepo(item.repo, item.text(0)) else: self.updateCurrentRepo(None, None) url = QtCore.QUrl.fromLocalFile(resourceFile("localrepos_offline.html")) self.repoDescription.setSource(url) 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 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 __init__(self): super(NavigatorDialog, self).__init__(None) self.currentRepo = None self.reposItem = None self.setupUi(self) self.filterWidget.hide() self.leFilter.setPlaceholderText( self.tr("Type here to filter repositories...")) self.actionAddGeoGigServer.setIcon(icon('geogig_server.svg')) self.actionCreateRepository.setIcon(icon('new-repo.png')) self.actionAddLayer.setIcon(icon('layer_group.svg')) self.actionManageRemotes.setIcon(icon('geogig.png')) self.actionEdit.setIcon(icon('edit.svg')) self.actionRefresh.setIcon( QgsApplication.getThemeIcon('/mActionDraw.svg')) self.actionShowFilter.setIcon( QgsApplication.getThemeIcon('/mActionFilter2.svg')) self.actionDelete.setIcon( QgsApplication.getThemeIcon('/mActionDeleteSelected.svg')) self.actionHelp.setIcon( QgsApplication.getThemeIcon('/mActionHelpContents.svg')) self.actionPull.setIcon(icon('pull.svg')) self.actionPush.setIcon(icon('push.svg')) self.actionAddGeoGigServer.triggered.connect(self.addGeoGigServer) self.actionCreateRepository.triggered.connect(self.createRepo) self.actionAddLayer.triggered.connect(self.addLayer) self.actionEdit.triggered.connect(self.editGeoGigServer) self.actionRefresh.triggered.connect(self.updateNavigator) self.actionShowFilter.triggered.connect(self.showFilterWidget) self.actionDelete.triggered.connect(self.deleteCurrentElement) self.actionHelp.triggered.connect(self.openHelp) self.actionManageRemotes.triggered.connect(self.manageRemotes) self.actionPull.triggered.connect(self.pull) self.actionPush.triggered.connect(self.push) self.leFilter.returnPressed.connect(self.filterRepos) self.leFilter.cleared.connect(self.filterRepos) self.leFilter.textChanged.connect(self.filterRepos) self.repoTree.itemSelectionChanged.connect(self.selectionChanged) self.repoDescription.anchorClicked.connect(self.descriptionLinkClicked) self.repoDescription.setOpenLinks(False) self.repoTree.setFocusPolicy(Qt.NoFocus) with open(resourceFile("repodescription.css")) as f: sheet = "".join(f.readlines()) self.repoDescription.document().setDefaultStyleSheet(sheet) if qtVersion < 5: self.repoTree.header().setResizeMode(0, QHeaderView.Stretch) self.repoTree.header().setResizeMode(1, QHeaderView.ResizeToContents) self.versionsTree = HistoryViewer() layout = QVBoxLayout() layout.setSpacing(0) layout.setMargin(0) layout.addWidget(self.versionsTree) self.versionsWidget.setLayout(layout) def _repoChanged(repo): if self.currentRepo is not None and repo.url == self.currentRepo.url: self.updateCurrentRepo(repo) for i in range(self.reposItem.childCount()): item = self.reposItem.child(i) for j in range(item.childCount()): subitem = item.child(j) if subitem.repo == repo: subitem.refreshContent() repoWatcher.repoChanged.connect(_repoChanged) self.updateNavigator() self.repoTree.itemExpanded.connect(self._itemExpanded)
class NavigatorDialog(BASE, WIDGET): def __init__(self): super(NavigatorDialog, self).__init__(None) self.currentRepo = None self.reposItem = None self.setupUi(self) self.filterWidget.hide() self.leFilter.setPlaceholderText( self.tr("Type here to filter repositories...")) self.actionAddGeoGigServer.setIcon(icon('geogig_server.svg')) self.actionCreateRepository.setIcon(icon('new-repo.png')) self.actionAddLayer.setIcon(icon('layer_group.svg')) self.actionManageRemotes.setIcon(icon('geogig.png')) self.actionEdit.setIcon(icon('edit.svg')) self.actionRefresh.setIcon( QgsApplication.getThemeIcon('/mActionDraw.svg')) self.actionShowFilter.setIcon( QgsApplication.getThemeIcon('/mActionFilter2.svg')) self.actionDelete.setIcon( QgsApplication.getThemeIcon('/mActionDeleteSelected.svg')) self.actionHelp.setIcon( QgsApplication.getThemeIcon('/mActionHelpContents.svg')) self.actionPull.setIcon(icon('pull.svg')) self.actionPush.setIcon(icon('push.svg')) self.actionAddGeoGigServer.triggered.connect(self.addGeoGigServer) self.actionCreateRepository.triggered.connect(self.createRepo) self.actionAddLayer.triggered.connect(self.addLayer) self.actionEdit.triggered.connect(self.editGeoGigServer) self.actionRefresh.triggered.connect(self.updateNavigator) self.actionShowFilter.triggered.connect(self.showFilterWidget) self.actionDelete.triggered.connect(self.deleteCurrentElement) self.actionHelp.triggered.connect(self.openHelp) self.actionManageRemotes.triggered.connect(self.manageRemotes) self.actionPull.triggered.connect(self.pull) self.actionPush.triggered.connect(self.push) self.leFilter.returnPressed.connect(self.filterRepos) self.leFilter.cleared.connect(self.filterRepos) self.leFilter.textChanged.connect(self.filterRepos) self.repoTree.itemSelectionChanged.connect(self.selectionChanged) self.repoDescription.anchorClicked.connect(self.descriptionLinkClicked) self.repoDescription.setOpenLinks(False) self.repoTree.setFocusPolicy(Qt.NoFocus) with open(resourceFile("repodescription.css")) as f: sheet = "".join(f.readlines()) self.repoDescription.document().setDefaultStyleSheet(sheet) if qtVersion < 5: self.repoTree.header().setResizeMode(0, QHeaderView.Stretch) self.repoTree.header().setResizeMode(1, QHeaderView.ResizeToContents) self.versionsTree = HistoryViewer() layout = QVBoxLayout() layout.setSpacing(0) layout.setMargin(0) layout.addWidget(self.versionsTree) self.versionsWidget.setLayout(layout) def _repoChanged(repo): if self.currentRepo is not None and repo.url == self.currentRepo.url: self.updateCurrentRepo(repo) for i in range(self.reposItem.childCount()): item = self.reposItem.child(i) for j in range(item.childCount()): subitem = item.child(j) if subitem.repo == repo: subitem.refreshContent() repoWatcher.repoChanged.connect(_repoChanged) self.updateNavigator() self.repoTree.itemExpanded.connect(self._itemExpanded) def descriptionLinkClicked(self, url): url = url.toString() if url.startswith("checkout"): layernames = url[url.find(":") + 1:].split(",") for layername in layernames: if layername: try: self._checkoutLayer(layername, None) except HasLocalChangesError: QMessageBox.warning( config.iface.mainWindow(), 'Cannot change version', "There are local changes that would be overwritten.\n" "Revert them before changing version.", QMessageBox.Ok) def updateNavigator(self): readRepos() self.fillTree() self.updateCurrentRepo(None) self.checkButtons() def _itemExpanded(self, item): if item is not None and isinstance(item, (RepoItem, BranchItem)): item.populate() def _removeLayer(self, layeritem): user, email = config.getUserInfo() if user is None: return self.currentRepo.removetree(layeritem.layer, user, email, layeritem.branch) config.iface.messageBar().pushMessage( "Layer correctly removed from repository", level=QgsMessageBar.INFO, duration=5) layer = getProjectLayerForGeoGigLayer(self.currentRepo.url, layeritem.layer) if layer: branches = self.currentRepo.branches() layerInRepo = False for branch in branches: layers = self.currentRepo.trees(branch) if layeritem.layer in layers: layerInRepo = True break if not layerInRepo: setAsNonRepoLayer(layer) tracking = getTrackingInfoForGeogigLayer( self.currentRepo.url, layeritem.layer) if tracking: removeTrackedLayer(tracking.source) #TODO remove triggers from layer repoWatcher.repoChanged.emit(self.currentRepo) def _checkoutLayer(self, layername, bbox): checkoutLayer(self.currentRepo, layername, bbox) def fillTree(self): self.updateCurrentRepo(None) self.repoTree.clear() self.reposItem = None repos = repository.repos self.reposItem = RepositoriesItem() self.reposItem.setIcon(0, repoIcon) groupedRepos = defaultdict(list) for repo in repos: groupedRepos[repo.group].append(repo) for groupName in repository.repoEndpoints: groupRepos = groupedRepos.get(groupName, []) groupItem = GroupItem(groupName) for repo in groupRepos: try: item = RepoItem(self.repoTree, repo) groupItem.addChild(item) except: #TODO: inform of failed repos pass self.reposItem.addChild(groupItem) self.repoTree.addTopLevelItem(self.reposItem) if self.reposItem.childCount(): self.filterRepos() self.reposItem.setExpanded(True) for i in range(self.reposItem.childCount()): self.reposItem.child(i).setExpanded(True) #self.repoTree.expandAll() self.repoTree.sortItems(0, Qt.AscendingOrder) def showHistoryTab(self): self.historyTabButton.setAutoRaise(False) self.descriptionTabButton.setAutoRaise(True) self.versionsWidget.setVisible(True) self.repoDescription.setVisible(False) def showDescriptionTab(self): self.historyTabButton.setAutoRaise(True) self.descriptionTabButton.setAutoRaise(False) self.versionsWidget.setVisible(False) self.repoDescription.setVisible(True) def addLayer(self): layers = [ layer for layer in getVectorLayers() if layer.source().lower().split("|")[0].split(".")[-1] in ["gpkg", "geopkg"] and not isRepoLayer(layer) ] if layers: dlg = ImportDialog(self, repo=self.currentRepo) dlg.exec_() if dlg.ok: #self.versionsTree.updateCurrentBranchItem() setAsRepoLayer(dlg.layer) repoWatcher.repoChanged.emit(self.currentRepo) else: QMessageBox.warning( self, 'Cannot add layer', "No suitable layers can be found in your current QGIS project.\n" "Only Geopackage layers that do not already belong to a repository can be added.", QMessageBox.Ok) 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 _removeRepoEndpoint(self, item): parent = item.parent() parent.removeChild(item) removeRepoEndpoint(item.text(0)) def filterRepos(self): text = self.leFilter.text().strip() for i in range(self.repoTree.topLevelItemCount()): parent = self.repoTree.topLevelItem(i) for j in range(parent.childCount()): item = parent.child(j) itemText = item.text(0) item.setHidden(text != "" and text not in itemText) def selectionChanged(self): self.checkButtons() items = self.repoTree.selectedItems() if items: item = items[0] try: if isinstance(item, (GroupItem, RepositoriesItem)): self.updateCurrentRepo(None) url = QUrl.fromLocalFile( resourceFile("localrepos_offline.html")) self.repoDescription.setSource(url) else: if item.repo != self.currentRepo: self.updateCurrentRepo(item.repo) except Exception as e: msg = "An error occurred while fetching repository data! %s" QgsMessageLog.logMessage(msg % e, level=QgsMessageLog.CRITICAL) QMessageBox.warning(self, 'Add repositories', msg % "See the logs for details.", QMessageBox.Ok) else: self.updateCurrentRepo(None) 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 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 editGeoGigServer(self): item = self.repoTree.selectedItems()[0] dlg = GeoGigServerDialog(repository.repoEndpoints[item.name], item.name) dlg.exec_() if dlg.title is not None: self._removeRepoEndpoint(item) self._addGeoGigServer(dlg.title, dlg.url) def addGeoGigServer(self): dlg = GeoGigServerDialog() dlg.exec_() if dlg.title is not None: self._addGeoGigServer(dlg.title, dlg.url) def _addGeoGigServer(self, title, url): try: repos = addRepoEndpoint(url, title) if not repos: msg = "No repositories found at the specified server" QMessageBox.warning( self, 'Add repositories', "No repositories found at the specified server", QMessageBox.Ok) groupItem = GroupItem(title) else: groupItem = GroupItem(title) for repo in repos: item = RepoItem(self.repoTree, repo) groupItem.addChild(item) except Exception as e: msg = "No geogig server found at the specified url. %s" QgsMessageLog.logMessage(msg % e, level=QgsMessageLog.CRITICAL) QMessageBox.warning(self, 'Add repositories', msg % "See the logs for details.", QMessageBox.Ok) groupItem = GroupItem(title) self.reposItem.addChild(groupItem) self.reposItem.setExpanded(True) self.repoTree.sortItems(0, Qt.AscendingOrder) def showFilterWidget(self, visible): self.filterWidget.setVisible(visible) if not visible: self.leFilter.setText("") self.filterRepos() else: self.leFilter.setFocus() def checkButtons(self): self.actionCreateRepository.setEnabled(False) self.actionRefresh.setEnabled(False) self.actionDelete.setEnabled(False) self.actionEdit.setEnabled(False) self.actionPush.setEnabled(False) self.actionPull.setEnabled(False) self.actionManageRemotes.setEnabled(False) if len(self.repoTree.selectedItems()) == 0: return item = self.repoTree.selectedItems()[0] if isinstance(item, RepositoriesItem): self.actionRefresh.setEnabled(True) elif isinstance(item, GroupItem): self.actionEdit.setEnabled(True) if item.isRepoAvailable: self.actionCreateRepository.setEnabled(True) self.actionDelete.setEnabled(True) elif isinstance(item, BranchItem): self.actionDelete.setEnabled(item.parent().childCount() > 1 and item.branch != "master") elif isinstance(item, RepoItem): self.actionDelete.setEnabled(True) self.actionManageRemotes.setEnabled(True) self.actionPush.setEnabled(True) self.actionPull.setEnabled(True) else: self.actionDelete.setEnabled(True) def openHelp(self): webbrowser.open('file://{}'.format( os.path.join(pluginPath, 'docs', 'html', 'index.html'))) def manageRemotes(self): dlg = RemotesDialog(iface.mainWindow(), self.currentRepo) dlg.exec_() 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 push(self): dlg = RemoteRefDialog(self.currentRepo) dlg.exec_() if dlg.remote is not None: try: self.currentRepo.push(dlg.remote, dlg.branch) config.iface.messageBar().pushMessage( "Changes have been correctly pushed to remote", level=QgsMessageBar.INFO, duration=5) except CannotPushException: config.iface.messageBar().pushMessage( "Changes could not be pushed to remote. Make sure you have pulled changed from the remote first.", level=QgsMessageBar.WARNING, duration=5)