Example #1
0
    def __init__(self, parent, repo):
        QtGui.QDialog.__init__(self, parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
        self.solved = False
        self.repo = repo
        self.ui = Ui_ConflictDialog()
        self.ui.setupUi(self)

        self.setWindowFlags(self.windowFlags() |
                              QtCore.Qt.WindowSystemMenuHint |
                              QtCore.Qt.WindowMinMaxButtonsHint)

        self.ui.buttonBox.rejected.connect(self.closePressed)
        self.ui.zoomButton.clicked.connect(self.zoomToFullExtent)
        self.ui.solveButton.clicked.connect(self.solve)
        self.ui.conflictsTree.itemClicked.connect(self.treeItemClicked)
        self.ui.attributesTable.cellClicked.connect(self.cellClicked)
        self.ui.solveAllOursButton.clicked.connect(self.solveOurs)
        self.ui.solveAllTheirsButton.clicked.connect(self.solveTheirs)
        self.ui.baseMapCombo.currentIndexChanged.connect(self.baseMapChanged)

        def refreshMap():
            self.showGeoms()
        self.ui.showTheirsCheck.stateChanged.connect(refreshMap)
        self.ui.showOursCheck.stateChanged.connect(refreshMap)

        self.lastSelectedItem = None
        self.currentPath = None
        self.theirsLayer = None
        self.oursLayer = None
        self.baseLayer = None

        settings = QtCore.QSettings()
        horizontalLayout = QtGui.QHBoxLayout()
        horizontalLayout.setSpacing(0)
        horizontalLayout.setMargin(0)
        self.mapCanvas = QgsMapCanvas()
        self.mapCanvas.setCanvasColor(QtCore.Qt.white)
        self.mapCanvas.enableAntiAliasing(settings.value("/qgis/enable_anti_aliasing", False, type = bool))
        self.mapCanvas.useImageToRender(settings.value("/qgis/use_qimage_to_render", False, type = bool))
        self.mapCanvas.mapRenderer().setProjectionsEnabled(True)
        action = settings.value("/qgis/wheel_action", 0, type = float)
        zoomFactor = settings.value("/qgis/zoom_factor", 2, type = float)
        self.mapCanvas.setWheelAction(QgsMapCanvas.WheelAction(action), zoomFactor)
        horizontalLayout.addWidget(self.mapCanvas)
        self.ui.canvasWidget.setLayout(horizontalLayout)
        self.panTool = QgsMapToolPan(self.mapCanvas)
        self.mapCanvas.setMapTool(self.panTool)

        self.fillConflictsTree()
Example #2
0
class ConflictDialog(QtGui.QDialog):

    def __init__(self, parent, repo):
        QtGui.QDialog.__init__(self, parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint)
        self.solved = False
        self.repo = repo
        self.ui = Ui_ConflictDialog()
        self.ui.setupUi(self)

        self.setWindowFlags(self.windowFlags() |
                              QtCore.Qt.WindowSystemMenuHint |
                              QtCore.Qt.WindowMinMaxButtonsHint)

        self.ui.buttonBox.rejected.connect(self.closePressed)
        self.ui.zoomButton.clicked.connect(self.zoomToFullExtent)
        self.ui.solveButton.clicked.connect(self.solve)
        self.ui.conflictsTree.itemClicked.connect(self.treeItemClicked)
        self.ui.attributesTable.cellClicked.connect(self.cellClicked)
        self.ui.solveAllOursButton.clicked.connect(self.solveOurs)
        self.ui.solveAllTheirsButton.clicked.connect(self.solveTheirs)
        self.ui.baseMapCombo.currentIndexChanged.connect(self.baseMapChanged)

        def refreshMap():
            self.showGeoms()
        self.ui.showTheirsCheck.stateChanged.connect(refreshMap)
        self.ui.showOursCheck.stateChanged.connect(refreshMap)

        self.lastSelectedItem = None
        self.currentPath = None
        self.theirsLayer = None
        self.oursLayer = None
        self.baseLayer = None

        settings = QtCore.QSettings()
        horizontalLayout = QtGui.QHBoxLayout()
        horizontalLayout.setSpacing(0)
        horizontalLayout.setMargin(0)
        self.mapCanvas = QgsMapCanvas()
        self.mapCanvas.setCanvasColor(QtCore.Qt.white)
        self.mapCanvas.enableAntiAliasing(settings.value("/qgis/enable_anti_aliasing", False, type = bool))
        self.mapCanvas.useImageToRender(settings.value("/qgis/use_qimage_to_render", False, type = bool))
        self.mapCanvas.mapRenderer().setProjectionsEnabled(True)
        action = settings.value("/qgis/wheel_action", 0, type = float)
        zoomFactor = settings.value("/qgis/zoom_factor", 2, type = float)
        self.mapCanvas.setWheelAction(QgsMapCanvas.WheelAction(action), zoomFactor)
        horizontalLayout.addWidget(self.mapCanvas)
        self.ui.canvasWidget.setLayout(horizontalLayout)
        self.panTool = QgsMapToolPan(self.mapCanvas)
        self.mapCanvas.setMapTool(self.panTool)

        self.fillConflictsTree()

    def fillConflictsTree(self):
        conflicts = self.repo.conflicts()
        self.paths = {}
        for path, c in conflicts.iteritems():
            tree = os.path.dirname(path)
            if tree not in self.paths:
                item = QtGui.QTreeWidgetItem([tree])
                item.setIcon(0, layerIcon)
                self.ui.conflictsTree.addTopLevelItem(item)
                self.paths[tree] = item
            conflictItem = ConflictItem(path, c)
            self.paths[tree].addChild(conflictItem)

    def cellClicked(self, row, col):
        if col > 1:
            return
        value = self.ui.attributesTable.item(row, col).value
        geoms = (self.oursgeom, self.theirsgeom)
        self.ui.attributesTable.setItem(row, 3, ValueItem(value, False, geoms));
        self.ui.attributesTable.item(row, 0).setBackgroundColor(QtCore.Qt.white);
        self.ui.attributesTable.item(row, 1).setBackgroundColor(QtCore.Qt.white);
        attrib = self.ui.attributesTable.item(row, 2).text()
        if attrib in self.conflicted:
            self.conflicted.remove(attrib)
        self.updateSolveButton()

    def baseMapChanged(self, idx):
        if idx == BASEMAP_OSM:
            baseLayerFile = os.path.join(os.path.dirname(__file__),
                                         os.pardir, os.pardir, "resources", "osm.xml")
        elif idx == BASEMAP_GOOGLE:
            baseLayerFile = os.path.join(os.path.dirname(__file__),
                                         os.pardir, os.pardir, "resources", "gmaps.xml")
        else:
            self.baseLayer = None
            self.showGeoms()
            return

        if self.baseLayer is not None:
            QgsMapLayerRegistry.instance().removeMapLayer(self.baseLayer.id())
            self.baseLayer = None
        baseLayer = QgsRasterLayer(baseLayerFile, "base", "gdal")
        if baseLayer.isValid():
            self.baseLayer = baseLayer
            QgsMapLayerRegistry.instance().addMapLayer(self.baseLayer, False)
        else:
            _logger.debug("Could not load base layer")

        self.showGeoms()

    def treeItemClicked(self):
        item = self.ui.conflictsTree.selectedItems()[0]
        if self.lastSelectedItem == item:
            return
        self.lastSelectedItem = item
        if isinstance(item, ConflictItem):
            self.currentPath = item.path
            self.updateCurrentPath(item.versions)

    def updateCurrentPath(self, versions):
        self.cleanCanvas()
        self.showFeatureAttributes(versions)
        self.createLayers()
        self.showGeoms()
        self.zoomToFullExtent()

    def zoomToFullExtent(self):
        layers = [lay.extent() for lay in self.mapCanvas.layers() if lay.type() == lay.VectorLayer]
        if layers:
            ext = layers[0]
            for layer in  layers[1:]:
                ext.combineExtentWith(layer)
            self.mapCanvas.setExtent(ext)
            self.mapCanvas.refresh()

    def cleanCanvas(self):
        self.mapCanvas.setLayerSet([])
        layers = [self.oursLayer, self.theirsLayer, self.baseLayer]
        for layer in layers:
            if layer is not None:
                QgsMapLayerRegistry.instance().removeMapLayer(layer.id())
        self.oursLayer = None
        self.theirsLayer = None
        self.baseLayer = None


    def solveTheirs(self):
        ret = QtGui.QMessageBox.warning(self, "Solve conflict",
                                "Are you sure you want to solve all conflicts using the 'To merge' version?",
                                QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
                                QtGui.QMessageBox.Yes);
        if ret == QtGui.QMessageBox.Yes:
            self.repo.solveconflicts(self.repo.conflicts().keys(), geogig.THEIRS)
            self.solved = True
            self.close()

    def solveOurs(self):
        ret = QtGui.QMessageBox.warning(self, "Solve conflict",
            "Are you sure you want to solve all conflict using the 'Local' version?",
            QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
            QtGui.QMessageBox.Yes);
        if ret == QtGui.QMessageBox.Yes:
            self.repo.solveconflicts(self.repo.conflicts().keys(), geogig.OURS)
            self.solved = True
            self.close()

    def solve(self):
        attribs = {}
        for i in xrange(self.ui.attributesTable.rowCount()):
            value = self.ui.attributesTable.item(i, 3).value
            name = unicode(self.ui.attributesTable.item(i, 2).text())
            attribs[name] = value
        attribs['geogigid'] = os.path.basename(self.currentPath)
        self.repo.solveconflict(self.currentPath, attribs)
        parent = self.lastSelectedItem.parent()
        parent.removeChild(self.lastSelectedItem)
        if parent.childCount() == 0:
            self.ui.conflictsTree.invisibleRootItem().removeChild(parent)
            self.solved = True
        self.lastSelectedItem = None
        self.ui.attributesTable.setRowCount(0)
        self.cleanCanvas()
        self.ui.solveButton.setEnabled(False)


    def updateSolveButton(self):
        self.ui.solveButton.setEnabled(len(self.conflicted) == 0)

    def showFeatureAttributes(self, versions):
        self.oursgeom = None
        self.theirsgeom = None
        geoms = (self.oursgeom, self.theirsgeom)
        self.conflicted = []
        allAttribs = set()
        for v in versions:
            for a in v.attributes:
                if a.lower() != "geogigid":
                    allAttribs.add(a)

        self.ui.attributesTable.setRowCount(len(allAttribs))

        for idx, name in enumerate(allAttribs):
            values = [v.attributes.get(name, None) for v in versions]
            font = QtGui.QFont()
            font.setBold(True)
            font.setWeight(75)
            item = QtGui.QTableWidgetItem(name)
            item.setFont(font)
            self.ui.attributesTable.setItem(idx, 2, item);

            self.ui.attributesTable.setItem(idx, 3, ValueItem(None, False));

            if isinstance(values[0], Geometry):
                self.oursgeom = values[1]
                self.theirsgeom = values[2]
                geoms = (self.oursgeom, self.theirsgeom)

            ok = values[0] == values[1] or values[1] == values[2] or values[0] == values[2]

            for i, v in enumerate(values[1:]):
                self.ui.attributesTable.setItem(idx, i, ValueItem(v, not ok, geoms));

            if not ok:
                self.conflicted.append(name)
            else:
                self.ui.attributesTable.setItem(idx, 3, ValueItem(values[1], False, geoms));

        self.ui.attributesTable.resizeRowsToContents()
        self.ui.attributesTable.horizontalHeader().setMinimumSectionSize(150)
        self.ui.attributesTable.horizontalHeader().setStretchLastSection(True)

    def createLayers(self):
        types = [("Point", ptOursStyle, ptTheirsStyle),
                  ("LineString", lineOursStyle, lineTheirsStyle),
                  ("Polygon", polygonOursStyle, polygonTheirsStyle)]
        if self.oursgeom is not None:
            qgsgeom = QgsGeometry.fromWkt(self.oursgeom.geom)
            geomtype = types[int(qgsgeom.type())][0]
            if self.oursgeom.crs is not None:
                targetCrs = self.mapCanvas.mapRenderer().destinationCrs()
                crsTransform = QgsCoordinateTransform(QgsCoordinateReferenceSystem(self.oursgeom.crs), targetCrs)
                qgsgeom.transform(crsTransform)
            style = types[int(qgsgeom.type())][1]
            self.oursLayer = loadLayerNoCrsDialog(geomtype + "?crs=EPSG:4326", "ours", "memory")
            pr = self.oursLayer.dataProvider()
            feat = QgsFeature()
            feat.setGeometry(qgsgeom)
            pr.addFeatures([feat])
            self.oursLayer.loadNamedStyle(style)
            self.oursLayer.updateExtents()
            #this is to correct a problem with memory layers in qgis 2.2
            self.oursLayer.selectAll()
            self.oursLayer.setExtent(self.oursLayer.boundingBoxOfSelected())
            self.oursLayer.invertSelection()
            QgsMapLayerRegistry.instance().addMapLayer(self.oursLayer, False)
        else:
            self.oursLayer = None
        if self.theirsgeom is not None:
            qgsgeom = QgsGeometry.fromWkt(self.theirsgeom.geom)
            geomtype = types[int(qgsgeom.type())][0]
            if self.theirsgeom.crs is not None:
                targetCrs = self.mapCanvas.mapRenderer().destinationCrs()
                crsTransform = QgsCoordinateTransform(QgsCoordinateReferenceSystem(self.theirsgeom.crs), targetCrs)
                qgsgeom.transform(crsTransform)
            style = types[int(qgsgeom.type())][2]
            self.theirsLayer = loadLayerNoCrsDialog(geomtype + "?crs=EPSG:4326", "theirs", "memory")
            pr = self.theirsLayer.dataProvider()
            feat = QgsFeature()
            feat.setGeometry(qgsgeom)
            pr.addFeatures([feat])
            self.theirsLayer.loadNamedStyle(style)
            self.theirsLayer.updateExtents()
            #this is to correct a problem with memory layers in qgis 2.2
            self.theirsLayer.selectAll()
            self.theirsLayer.setExtent(self.theirsLayer.boundingBoxOfSelected())
            self.theirsLayer.invertSelection()
            QgsMapLayerRegistry.instance().addMapLayer(self.theirsLayer, False)
        else:
            self.theirsLayer = None

    def showGeoms(self):
        checks = [self.ui.showOursCheck, self.ui.showTheirsCheck]
        layers = [self.oursLayer, self.theirsLayer]
        toShow = []
        for lay, chk in zip(layers, checks):
            if lay is not None and chk.isChecked():
                toShow.append(lay)
        if len(toShow) > 0 and self.baseLayer is not None:
            toShow.append(self.baseLayer)
        self.mapCanvas.setRenderFlag(False)
        self.mapCanvas.setLayerSet([QgsMapCanvasLayer(layer) for layer in toShow])
        self.mapCanvas.setRenderFlag(True)


    def closePressed(self):
        self.cleanCanvas()
        self.close()