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