Пример #1
0
class QvCrearMapetaConBotones(QWidget):
    '''
    Pongo botones para:\n
      Poner un circulo con ruberband\n
      Guardar la ruberband
    '''

    Sig_MapetaTemporal = pyqtSignal('QString ')

    def __init__(self, canvas, pare=None):
        '''
        '''
        self.canvas = canvas
        if self.canvas.rotation() != 0:
            self.canvas.setRotation(0)

        QWidget.__init__(self)
        self.dadesdir = configuracioQvista.dadesdir
        self.setParent(pare)
        self.pare = pare
        self.existeCirculo = False

        #defino botones y las funciones de su click
        self.botoponerCirculo = QPushButton("Posar circle")
        self.botoponerCirculo.setToolTip('Color perimetre')
        self.botoponerCirculo.clicked.connect(self.ponerCirculo)
        self.botoponerCirculo.setFixedWidth(120)

        self.botoEnvMap = QPushButton('Enviar a mapeta')
        self.botoEnvMap.setToolTip('Color perimetre')
        self.botoEnvMap.clicked.connect(self.EnvMap)
        self.botoEnvMap.setFixedWidth(120)

        self.botoActualizar = QPushButton("Actualizar")
        self.botoEnvMap.setToolTip('Color perimetre')
        self.botoActualizar.clicked.connect(self.actualizar)
        self.botoActualizar.setFixedWidth(120)

        self.botoColor = QPushButton('Sel·lecc. color')
        self.botoColor.setToolTip('Color perimetre')
        self.botoColor.clicked.connect(self.showDialogColor)
        self.botoColor.setFixedWidth(120)

        self.botoCargar = QPushButton('Cargar')
        self.botoCargar.setToolTip('Color perimetre')
        self.botoCargar.clicked.connect(self.Cargar)
        self.botoCargar.setFixedWidth(120)

        self.botoSalvar = QPushButton('Salvar')
        self.botoSalvar.setToolTip('Color perimetre')
        self.botoSalvar.clicked.connect(self.Salvar)
        self.botoSalvar.setFixedWidth(120)

        self.label = QLabel(self)  #para el pixmap

        # self.label.setDragEnabled(True)      no va!!!

        self.color = QColor(121, 144, 155)
        self.xmax_ymax = QLabel(" ", self)
        self.xmin_ymin = QLabel(" ", self)

        self.spinBox = QSpinBox(self)
        self.spinBox.setFixedWidth(60)
        self.spinBox.setRange(50, 600)
        self.spinBox.setSingleStep(20)
        self.spinBox.setValue(200)
        self.lado = self.spinBox.value()
        self.spinBox.valueChanged.connect(self.tamanyoLadoCirculo)

        spacerItem = QSpacerItem(0, 0, QSizePolicy.Expanding,
                                 QSizePolicy.Minimum)
        self.layH1 = QHBoxLayout()
        self.layH1.addWidget(self.botoponerCirculo)

        self.layH1.addWidget(self.botoEnvMap)

        self.layH1.addItem(spacerItem)

        self.layH2 = QHBoxLayout()
        self.layH2.addWidget(self.botoActualizar)
        self.layH2.addWidget(self.botoColor)
        self.layH2.addItem(spacerItem)

        self.layH3 = QHBoxLayout()
        self.layH3.addWidget(self.botoCargar)
        self.layH3.addWidget(self.botoSalvar)
        self.layH3.addItem(spacerItem)

        self.layH4 = QHBoxLayout()
        self.layH4.addWidget(self.xmax_ymax)
        self.layH4.addItem(spacerItem)

        self.layH5 = QHBoxLayout()
        self.layH5.addWidget(self.xmin_ymin)
        self.layH5.addItem(spacerItem)

        self.layH6 = QHBoxLayout()
        self.layH6.addWidget(self.spinBox)
        self.layH6.addItem(spacerItem)

        self.layH7 = QHBoxLayout()
        self.layH7.addWidget(self.label)
        self.layH7.addItem(spacerItem)

        spacerItem2 = QSpacerItem(0, 0, QSizePolicy.Ignored,
                                  QSizePolicy.Expanding)
        self.layV1 = QVBoxLayout()
        self.layV1.addLayout(self.layH1)
        self.layV1.addLayout(self.layH2)
        self.layV1.addLayout(self.layH3)
        self.layV1.addLayout(self.layH4)
        self.layV1.addLayout(self.layH5)
        self.layV1.addLayout(self.layH6)
        self.layV1.addItem(spacerItem2)
        self.layV1.addLayout(self.layH7)
        self.setLayout(self.layV1)

    def EnvMap(self):

        try:
            self.Sig_MapetaTemporal.emit(self.colocoCirculo.fileName)
        except Exception as ee:
            self.actualizar()
            fic_tmp = os.path.join(self.tempdir, "temporal2.png")
            self.Sig_MapetaTemporal.emit(fic_tmp)

    def tamanyoLadoCirculo(self):
        '''
        lado me gusta mas que spinB...value
        '''
        self.lado = self.spinBox.value()

    def hacer5(self):
        self.tempdir = configuracioQvista.tempdir
        fic_tmp = os.path.join(self.tempdir, "temporal.png")
        self.pixmap = QPixmap(fic_tmp)
        # self.pixmap=self.canvas.grab() # no acaba de ir bien, me carga en pixmap tambien el circulo pintado
        # tamaño del pixmap
        hp = self.pixmap.height()  # alto imagen
        wp = self.pixmap.width()  # ancho imagen salvada
        # radio.
        if hp < wp:
            self.rP = hp / 2
        else:
            self.rP = wp / 2

        self.xcP = wp / 2
        self.ycP = hp / 2
        # self.rP = math.sqrt(math.pow((self.xcP-self.xrP), 2) + math.pow((self.ycP-self.yrP), 2))  # radio pantalla
        pcX = self.xcP - self.rP
        pcY = self.ycP - self.rP  # punto inicio crop
        self.an = 2 * self.rP
        self.al = self.an  # an, ancho para crop   al, alto para crop
        # escala= self.rP /self.rM                                                   # escala, como relacion de radiopantalla a radiomundo
        # pmin= QPoint();
        # pmin.setX(pcX);
        # pmin.setY(pcY+self.al);
        # self.Pmin = self.toMapCoordinates(pmin)
        # pmax= QPoint();
        # pmax.setX(pcX+self.an);
        # pmax.setY(pcY);
        # self.Pmax = self.toMapCoordinates(pmax)

        # calculo area de recorte para hacer el crop
        rect = QRect(pcX, pcY, self.an, self.al)
        # hago crop
        cropped_pixmap = self.pixmap.copy(rect)

        # escalo el pixmap al tamaño que quiero
        self.scaled_pixmap = cropped_pixmap.scaled(
            self.lado, self.lado, Qt.KeepAspectRatioByExpanding,
            Qt.SmoothTransformation)
        # de pixmap a image
        image = QImage(self.scaled_pixmap.toImage())
        image = image.convertToFormat(QImage.Format_ARGB32)

        # preparo imagen de salida transparente y del tamaño del de entrada....
        out_img = QImage(image.width(), image.width(), QImage.Format_ARGB32)
        out_img.fill(Qt.transparent)

        # Create a texture brush and paint a circle with the original image onto
        # the output image: Chapeau!!
        brush = QBrush(image)  # Create texture brush
        painter = QPainter(out_img)  # Paint the output image
        painter.setBrush(brush)  # Use the image texture brush
        # painter.setPen(Qt.NoPen)     # Don't draw an outline
        # pen= QPen(QColor(121,144,155),  1, Qt.SolidLine)    #qVista claro
        pen = QPen(self.color, 1, Qt.SolidLine)  #qVista claro
        painter.setPen(pen)
        painter.setRenderHint(QPainter.Antialiasing, True)  # Use AA
        painter.drawEllipse(0, 0, image.width(),
                            image.width())  # Actually draw the circle
        painter.end()  # We are done (segfault if you forget this)

        # de out_img a pixmap
        self.scaled_pixmap = QPixmap.fromImage(out_img)

        # muestro ese pixmap en label...
        self.label.setPixmap(self.scaled_pixmap)

        # y lo salvo como temporal2
        fic_tmp = os.path.join(self.tempdir, "temporal2.png")
        self.fileName = fic_tmp

        if self.fileName:
            # Guardo el pixmap como png
            self.scaled_pixmap.save(self.fileName)
            # Calculo info para el PQW
            # rango mundo x e y

            xdist = self.xmax - self.xmin
            ydist = self.ymax - self.ymin
            # ancho y alto de la imagen
            iheight = self.scaled_pixmap.height()
            iwidth = self.scaled_pixmap.width()

            # Preparo nombre del PGW
            split_nombre = os.path.splitext(self.fileName)
            filenamePgw = split_nombre[0] + ".pgw"

            # Escribo PGW
            wld = open(filenamePgw, "w")
            wld.writelines("%s\n" % (xdist / iwidth))
            wld.writelines("0.0\n")
            wld.writelines("0.0\n")
            wld.writelines("%s\n" % (ydist / iheight))
            wld.writelines("%s\n" % self.xmin)
            wld.writelines("%s\n" % self.ymin)
            wld.close

        # #  muestro datos de georeferenciacion
        # literal= "xmin,ymin=" + str(round(self.Pmin.x(),3)) +"  "+ str(round(self.Pmin.y(),3))
        # self.parent.xmin_ymin.setText(literal)
        # literal= "xmax,ymax=" + str(round(self.Pmax.x(),3)) +"  "+ str(round(self.Pmax.y(),3))
        # self.parent.xmax_ymax.setText(literal)

        try:
            self.reset()
        except:
            pass

    def actualizar(self):
        try:
            self.colocoCirculo.saveCanvas1()
        except Exception as ee:
            print("Desde carga Aun no implementado")
            self.hacer5()

            pass

    def ponerCirculo(self):
        '''
        Dibujo circulo, dinamicamente
        '''

        if self.canvas.rotation() != 0:
            self.canvas.setRotation(0)

        self.label.setPixmap(QPixmap())
        numeroSegmentsCercle = 360
        lado = self.lado
        # if not self.existeCirculo:
        #     self.colocoCirculo= QvColocacionCirculo(self.canvas,  numeroSegmentsCercle,self,lado)
        #     self.existeCirculo=True
        #     self.canvas.setMapTool(self.colocoCirculo)

        # reseterar circulo
        try:
            self.colocoCirculo.rubberband.reset(True)
        except:
            pass

        self.colocoCirculo = QvColocacionCirculo(self.canvas,
                                                 numeroSegmentsCercle, self,
                                                 lado)
        self.existeCirculo = True
        self.canvas.setMapTool(self.colocoCirculo)

    def showDialogColor(self):
        d_color = QColorDialog()

        col = d_color.getColor()
        if col.isValid():
            self.color = col

    def Cargar(self):
        '''
        Leo PNG y PGW
        '''
        dialegObertura = QFileDialog()
        dialegObertura.setDirectoryUrl(QUrl(self.dadesdir))

        # Images (*.png );;World files (*.pgw)
        self.fileName,_ = dialegObertura.getOpenFileName(parent=self,\
                                                        caption= 'Cargar mapeta',\
                                                        directory='',
                                                        filter="World files(*.pgw);;Images(*.png);;Tot(*.*)")
        if self.fileName:
            split_nombre = os.path.splitext(self.fileName)
            filenamePGW = split_nombre[0] + ".pgw"
            filenamePNG = split_nombre[0] + ".png"
            datos_mapeta = self.CalcularPNGyRangoMapeta(filenamePNG)

            pixmap = QPixmap(filenamePNG)
            self.label.setPixmap(pixmap)

            literal = "xmin,ymin=" + str(round(
                datos_mapeta[1], 3)) + "  " + str(round(datos_mapeta[2], 3))
            self.xmin_ymin.setText(literal)
            literal = "xmax,ymax=" + str(round(
                datos_mapeta[3], 3)) + "  " + str(round(datos_mapeta[4], 3))
            self.xmax_ymax.setText(literal)
            self.spinBox.setValue(datos_mapeta[5])

            self.xmin = datos_mapeta[1]
            self.ymin = datos_mapeta[2]
            self.xmax = datos_mapeta[3]
            self.ymax = datos_mapeta[4]
            pass
            #  TODO: Actualizar variables necesarias para poder hacer recalculos
            self.rang = QgsRectangle(self.xmin, self.ymin, self.xmax,
                                     self.ymax)
            self.canvas.setExtent(self.rang)

    def CalcularPNGyRangoMapeta(self, ficheroEnviado):
        '''
        Hay 2 ficheros complementarios: PNG y PGW. (PNG la imagen, 
        PGW su georeferenciacio,  en esta versión referida a un mapeta sin 
        rotación). La funcion recibe un fichero (cualquiera de los dos) y 
        busca su complementario. 
        Con ambos calcula y la anchura y altura del PNG, y su rango.
        '''
        split_nombre = os.path.splitext(ficheroEnviado)
        ficheroPNG = split_nombre[0] + ".png"
        ficheroPGW = split_nombre[0] + ".pgw"

        pixmap = QPixmap(ficheroPNG)
        heigthPNG = pixmap.height()
        widthPNG = pixmap.width()

        try:
            if not os.path.exists(ficheroPGW):
                print("PNG sin PGW")
                return

            wld = open(ficheroPGW, "r")
            A = float(wld.readlines(1)[0])
            D = float(wld.readlines(2)[0])
            B = float(wld.readlines(3)[0])
            E = float(wld.readlines(4)[0])
            C = float(wld.readlines(5)[0])
            F = float(wld.readlines(6)[0])
            wld.close
            x = heigthPNG
            y = widthPNG
            x1 = A * x + B * y + C
            y1 = D * x + E * y + F
            xmin = C
            ymin = F
            xmax = x1
            ymax = y1
            return ficheroPNG, xmin, ymin, xmax, ymax, widthPNG, heigthPNG

        except:
            print("problemas PGW")

    def Salvar(self):
        '''
        Escribo PNG y PGW
        '''
        dialegObertura = QFileDialog()
        dialegObertura.setDirectoryUrl(QUrl(self.dadesdir))
        self.fileName, _ = dialegObertura.getSaveFileName(
            self, 'Guardar mapeta', '', 'PNG(*.png)')
        if self.fileName:
            # Guardo el pixmap como png
            self.colocoCirculo.scaled_pixmap.save(self.fileName)
            # Calculo info para el PQW
            # rango mundo x e y
            xdist = self.colocoCirculo.Pmax.x() - self.colocoCirculo.Pmin.x()
            ydist = self.colocoCirculo.Pmax.y() - self.colocoCirculo.Pmin.y()

            # ancho y alto de la imagen
            iheight = self.colocoCirculo.scaled_pixmap.height()
            iwidth = self.colocoCirculo.scaled_pixmap.width()

            # Preparo nombre del PGW
            split_nombre = os.path.splitext(self.fileName)
            filenamePgw = split_nombre[0] + ".pgw"

            # Escribo PGW
            wld = open(filenamePgw, "w")
            wld.writelines("%s\n" % (xdist / iwidth))
            wld.writelines("0.0\n")
            wld.writelines("0.0\n")
            wld.writelines("%s\n" % (ydist / iheight))
            wld.writelines("%s\n" % self.colocoCirculo.Pmin.x())
            wld.writelines("%s\n" % self.colocoCirculo.Pmin.y())
            wld.close

    def closeEvent(self, event):
        close = QMessageBox()
        close.setText("You sure?")
        close.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel)
        close = close.exec()

        if close == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()
class HistoryTree(QTreeWidget):

    historyChanged = pyqtSignal()

    def __init__(self, parent):
        # import pydevd
        # pydevd.settrace('localhost', port=65432, stdoutToServer=True, stderrToServer=True,
        #                 trace_only_current_thread=False, overwrite_prev_trace=True, patch_multiprocessing=True,
        #                 suspend=False)
        super(HistoryTree, self).__init__()
        self.repo = None
        self.layername = None
        self.selecting = False
        self.parent = parent
        self.showPopup = True
        self.initGui()

    # override the default autoscroll behavior
    #  this will not move the horizontal position of the scroll bar during a scroll-to
    # ie. when you click on a cell, it will bring that into view (if its large, it will change the x scroll)
    # this is very anoying
    def scrollTo(self, index, hint):
        oldH = self.horizontalScrollBar().value() # remember current horizontal value
        super().scrollTo(index, hint) # call default implementation
        self.horizontalScrollBar().setValue(oldH) # reset to old value

    def initGui(self):
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.header().setStretchLastSection(True)
        self.setAlternatingRowColors(True)
        self.setHeaderLabels(["Graph", "Description", "Author", "Date", "CommitID"])
        if self.showPopup:
            self.customContextMenuRequested.connect(self._showPopupMenu)
            self.setSelectionMode(QAbstractItemView.ExtendedSelection)

    def exportVersion(self, layer, commitid, live):
        from geogig.layers import addGeogigLayer
        addGeogigLayer(self.server, self.user, self.repo, layer, commitid, live, self)
        currentWindow().messageBar().pushMessage("Layer", "Layer was correctly added to QGIS project",
                                                level=Qgis.Info, duration=5)
        
    def _showPopupMenu(self, point):
        point = self.mapToGlobal(point)
        self.showPopupMenu(point)

    def showPopupMenu(self, point):
        selected = self.selectedItems()
        if selected and len(selected)==1:
            item = self.currentItem()
            layers = self.server.layers(self.user, self.repo, item.commit.commitid)
            exportVersionActions = []
            for layer in layers:
                exportVersionActions.append(QAction(resetIcon, "Add '%s' layer to QGIS from this commit (geopackage)" % layer, None))
                exportVersionActions[-1].triggered.connect(partial(self.exportVersion, layer, item.commit.commitid, False))
                exportVersionActions.append(QAction(resetIcon, "Add '%s' layer to QGIS from this commit (live link)" % layer, None))
                exportVersionActions[-1].triggered.connect(partial(self.exportVersion, layer, item.commit.commitid, True))
            menu = QMenu()

            revertAction = QAction("Revert changes introduced by this commit...", None)
            revertAction.triggered.connect(lambda: self.revert(item.commit.commitid))
            menu.addAction(revertAction)
            resetAction = QAction("Reset repository to this commit...", None)
            resetAction.triggered.connect(lambda: self.resetToCommit(item.commit.commitid))
            menu.addAction(resetAction)
            menu.addSeparator()
            exportDiffAction =  QAction(resetIcon, "Add DIFF layers to QGIS for this commit", None)
            exportDiffAction.triggered.connect(partial(self.exportDiff, item, None,self.layername))
            menu.addAction(exportDiffAction)
            if exportVersionActions:
                menu.addSeparator()
                for action in exportVersionActions:
                    menu.addAction(action)
            menu.exec_(point)
        if selected and len(selected) == 2:
            item0 = selected[0]
            item1 = selected[1]

            exportDiffAction =  QAction(resetIcon, "Add DIFF layers to QGIS for these commits", None)
            exportDiffAction.triggered.connect(partial(self.exportDiff, item0,  item1,self.layername))
            menu = QMenu()
            menu.addAction(exportDiffAction)
            menu.exec_(point)

    def exportDiff(self, item0, item1, layer=None):
        row0 = self.indexFromItem(item0).row()
        row1 = self.indexFromItem(item1).row() if item1 is not None else (row0 + 1)
        commitA = item0.commit.commitid
        commitB = item1.commit.commitid if item1 is not None else commitA + "~1"
        if item1 is None and len(item0.commit.parentIds) ==0:
            commitB = "0000000"
        if row0 > row1:
            commitB, commitA = commitA, commitB

        diffexporter = DiffGeoPKGMultiLayer(self.server,
                            self.user,
                            self.repo,
                            commitA,
                            commitB, layer=layer)
        diffexporter.addToProject()
        currentWindow().messageBar().pushMessage("Layers", "DIFF layers were correctly added to QGIS project",
                                                level=Qgis.Info, duration=5)

    def revert(self, commitid):
        lastCommit = self.graph.commits[0].commitid
        self.server.revert(self.user, self.repo, "master", commitid)
        commits, commitsDict = self.server.log(self.user, self.repo, "master")        
        if commits[0] == lastCommit:
            QMessageBox.warning(self, "Revert", "Commit could not be reverted")
        else:
            self.historyChanged.emit()

    def resetToCommit(self, commitid):
        self.server.reset(self.user, self.repo, "master", commitid)
        self.historyChanged.emit()      
        
    COMMIT_GRAPH_HEIGHT = 20
    COLUMN_SEPARATION = 20
    COMMIT_GRAPH_WIDTH = 300
    RADIUS = 5
    PEN_WIDTH = 4

    COLORS = [QColor(Qt.red),
              QColor(Qt.green),
              QColor(Qt.blue),
              QColor(Qt.black),
              QColor(255,166,0),
              QColor(Qt.darkGreen),
              QColor(Qt.darkBlue),
              QColor(Qt.cyan),
              QColor(Qt.magenta)]

    def createGraphImage(self):
        self.image = QPixmap(self.COMMIT_GRAPH_WIDTH, 1000).toImage()
        qp = QPainter(self.image)
        qp.fillRect(QRectF(0, 0, self.COMMIT_GRAPH_WIDTH, 1000), Qt.white);
        #qp.begin(self.image)
        self.drawLines(qp)
        qp.end()

    def drawLines(self, painter):
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setRenderHint(QPainter.HighQualityAntialiasing)
        self.linked = []
        self.columnColor = {}
        self.lastColor = -1
        def linkCommit(commit):
            for parent in commit.getParentsIfAvailable():
                try:
                    self.drawLine(painter, commit, parent)
                    if parent.commitid not in self.linked:
                        linkCommit(parent)
                except:
                    continue

        if self.graph.commits:
            linkCommit(self.graph.commits[0])

        y = len(self.graph.commits) * self.COLUMN_SEPARATION
        x = self.RADIUS * 3
        painter.setPen(self.COLORS[0])
        painter.setBrush(self.COLORS[0])
        painter.drawEllipse(QPoint(x, y), self.RADIUS, self.RADIUS)

    def drawLine(self, painter, commit, parent):
        commitRow = self.graph.commitRows[commit.commitid]
        commitCol = self.graph.commitColumns[commit.commitid]
        parentRow = self.graph.commitRows[parent.commitid]
        parentCol = self.graph.commitColumns[parent.commitid]
        commitX = self.RADIUS * 3 + commitCol * self.COLUMN_SEPARATION
        parentX = self.RADIUS * 3 + parentCol * self.COLUMN_SEPARATION
        commitY = commitRow * self.COMMIT_GRAPH_HEIGHT
        parentY = parentRow * self.COMMIT_GRAPH_HEIGHT
        color = self._columnColor(parentCol)

        if parent is not None and self.graph.isFauxLink(parent.commitid, commit.commitid)\
                and len(parent.childrenIds)>1:
            # draw a faux line
            path = QPainterPath()
            path.moveTo(parentX, parentY)
            path.lineTo(commitX , commitY)

            color = QColor(255,160,255)
            pen = QPen()
            pen.setWidth(2)
            pen.setBrush(color)
            pen.setStyle(Qt.DashLine)
            painter.setPen(pen)
            painter.drawPath(path)

            # draw arrow
            # draw arrow
            ARROW_POINT_SIZE = 9
            painter.setPen(color)
            painter.setBrush(color)
            line = QLineF(commitX , commitY, parentX, parentY)

            angle = math.acos(line.dx() / line.length())
            if line.dy() >= 0:
                angle = 2.0 * math.pi - angle

            sourcePoint = QPointF(commitX,commitY)
            sourceArrowP1 = sourcePoint + QPointF(math.sin(angle + math.pi / 3) * ARROW_POINT_SIZE,
                                                       math.cos(angle + math.pi / 3) * ARROW_POINT_SIZE)
            sourceArrowP2 = sourcePoint + QPointF(math.sin(angle + math.pi - math.pi / 3) * ARROW_POINT_SIZE,
                                                       math.cos(angle + math.pi - math.pi / 3) * ARROW_POINT_SIZE)
            arrow = QPolygonF([line.p1(), sourceArrowP1, sourceArrowP2])
            painter.drawPolygon(arrow)
            return

        path = QPainterPath()
        painter.setBrush(color)
        painter.setPen(color)

        if parentCol != commitCol:
            if parent.isFork() and commit.getParents()[0].commitid == parent.commitid:
                path.moveTo(commitX, commitY)
                path.lineTo(commitX, parentY)
                if parentX<commitX:
                    path.lineTo(parentX + self.RADIUS + 1, parentY)
                else:
                    path.lineTo(parentX - self.RADIUS, parentY)
                color = self._columnColor(commitCol)
            else:
                path2 = QPainterPath()
                path2.moveTo(commitX + self.RADIUS + 1, commitY)
                path2.lineTo(commitX + self.RADIUS + self.COLUMN_SEPARATION / 2, commitY + self.COLUMN_SEPARATION / 3)
                path2.lineTo(commitX + self.RADIUS + self.COLUMN_SEPARATION / 2, commitY - self.COLUMN_SEPARATION / 3)
                path2.lineTo(commitX + + self.RADIUS + 1, commitY)
                painter.setBrush(color)
                painter.setPen(color)
                painter.drawPath(path2)
                path.moveTo(commitX + self.RADIUS + self.COLUMN_SEPARATION / 2, commitY)
                path.lineTo(parentX, commitY)
                path.lineTo(parentX, parentY)

            if parent.isFork():
                if commitCol in self.columnColor.keys():
                    del self.columnColor[commitCol]
  
        else:
            path.moveTo(commitX, commitY)
            path.lineTo(parentX, parentY)

        pen = QPen(color, self.PEN_WIDTH, Qt.SolidLine, Qt.FlatCap, Qt.RoundJoin)
        painter.strokePath(path, pen)

        if not commit.commitid in self.linked:
            y = commitRow * self.COLUMN_SEPARATION
            x = self.RADIUS * 3 + commitCol * self.COLUMN_SEPARATION
            painter.setPen(color)
            painter.setBrush(color)
            painter.drawEllipse(QPoint(x, y), self.RADIUS, self.RADIUS)
            self.linked.append(commit.commitid)

    def _columnColor(self, column):
        if column in self.columnColor:
            color = self.columnColor[column]
        elif column == 0:
            self.lastColor += 1
            color = self.COLORS[0]
            self.columnColor[column] = color
        else:
            self.lastColor += 1
            color = self.COLORS[(self.lastColor % (len(self.COLORS)-1)) + 1]
            self.columnColor[column] = color
        return color

    def graphSlice(self, row, width):
        return self.image.copy(0, (row - .5) * self.COMMIT_GRAPH_HEIGHT,
                               width, self.COMMIT_GRAPH_HEIGHT)

    def updateContent(self, server, user, repo, graph, layername = None):
        self.server = server
        self.user = user
        self.repo = repo
        self.layername = layername
        self.graph = graph
        self.clear()
        self._updateContent()
        if graph.commits:
            self.setCurrentItem(self.topLevelItem(0))

    def _updateContent(self):
        if not self.graph:
            return
        self.createGraphImage()
        self.clear()

        if self.graph.commitColumns:
            width = self.COLUMN_SEPARATION * (max(self.graph.commitColumns.values()) + 1) + self.RADIUS +10
        else:
            width = self.COLUMN_SEPARATION

        for i, commit in enumerate(self.graph.commits):
            item = CommitTreeItem(commit, self)
            self.addTopLevelItem(item)
            img =self.graphSlice(i + 1, width)
            w = GraphWidget(img)
            w.setFixedHeight(self.COMMIT_GRAPH_HEIGHT)
            w.setFixedWidth(self.COMMIT_GRAPH_WIDTH )
            self.setItemWidget(item, 0, w)
            self.setColumnWidth(0, self.COMMIT_GRAPH_WIDTH)

        for i in range(1, 4):
            self.resizeColumnToContents(i)

        self.expandAll()

        self.header().resizeSection(0, width +20)
Пример #3
0
class QvColocacionCirculo(QgsMapTool):
    """ Dibuixa un cercle i selecciona els elements."""
    def __init__(self, canvas, numeroSegmentsCercle, parent, lado):
        '''
        '''
        self.canvas = canvas
        self.parent = parent
        self.lado = lado
        self.tempdir = configuracioQvista.tempdir

        QgsMapTool.__init__(self, self.canvas)

        # clickable(self).connect(self.showText1)
        self.status = 0
        self.numeroSegmentsCercle = numeroSegmentsCercle

        self.rubberband = QgsRubberBand(self.canvas, True)
        self.rubberband.setColor(QColor("Blue"))
        self.rubberband.setWidth(1)
        self.rubberband.setIconSize(10)
        # self.overlap = False
        # self.radio  =0

    def canvasPressEvent(self, e):
        '''
        Data en canvas. Segun boton iz o derecho se que es modo win o no....
        Guardo el centro
        '''
        if self.canvas.rotation() != 0:
            self.canvas.setRotation(0)

        # self.parent.label.setPixmap(QPixmap())
        try:
            self.rubberband.reset(True)
        except:
            pass

        self.status = 1  #Estamos pintando circulo!!
        # self.centre  centro del circulo
        self.centre = self.toMapCoordinates(e.pos())
        self.centroEnPantalla = e.pos()
        return

    def canvasMoveEvent(self, e):
        '''
          Hay que pintar dinamicamente el circulo
        '''
        if self.status == 0:  # si no estoy en modo pintar circulo, no continuo
            return

        # guardo punto pantalla
        self.final = e.pos()
        # punto pantalla a mundo
        cp = self.toMapCoordinates(e.pos())

        # establezco color de rubberband
        self.rubberband.setColor(QColor("blue"))

        # dibujo el circulo
        self.rbcircle(self.rubberband, self.centre, cp,
                      self.numeroSegmentsCercle)
        # r = math.sqrt(self.centre.sqrDist(cp))
    def rbcircle(self, rb, center, edgePoint, segments):
        '''
        Calculo circulo y lo cargo en rubberband
        '''
        rd = math.sqrt(center.sqrDist(edgePoint))
        self.radio = rd

        rb.reset(True)
        pi = 3.1416
        llistaPunts = []
        theta = 1 * (2.0 * pi / segments)
        rb.addPoint(
            QgsPointXY(center.x() + 1 * math.cos(theta),
                       center.y() + 1 * math.sin(theta)))
        for itheta in range(segments + 1):
            theta = itheta * (2.0 * pi / segments)
            rb.addPoint(
                QgsPointXY(center.x() + rd * math.cos(theta),
                           center.y() + rd * math.sin(theta)))

    def pre_saveCanvas(self):
        self.canvas.mapCanvasRefreshed.disconnect(self.pre_saveCanvas)
        QTimer.singleShot(0, self.saveCanvas)

    def saveCanvas(self):
        fic_tmp = os.path.join(self.tempdir, "temporal.png")
        self.canvas.saveAsImage(fic_tmp)
        self.hacer4()

    def saveCanvas1(self):
        fic_tmp = os.path.join(self.tempdir, "temporal.png")
        self.canvas.saveAsImage(fic_tmp)
        self.hacer4()

    def hacer4(self):

        fic_tmp = os.path.join(self.tempdir, "temporal.png")
        self.pixmap = QPixmap(fic_tmp)
        # self.pixmap=self.canvas.grab() # no acaba de ir bien, me carga en pixmap tambien el circulo pintado
        # tamaño del pixmap
        hp = self.pixmap.height()  # alto imagen
        wp = self.pixmap.width()  # ancho imagen salvada
        # radio.
        if hp < wp:
            self.rP = hp / 2
        else:
            self.rP = wp / 2

        self.xcP = wp / 2
        self.ycP = hp / 2
        # self.rP = math.sqrt(math.pow((self.xcP-self.xrP), 2) + math.pow((self.ycP-self.yrP), 2))  # radio pantalla
        pcX = self.xcP - self.rP
        pcY = self.ycP - self.rP  # punto inicio crop
        self.an = 2 * self.rP
        self.al = self.an  # an, ancho para crop   al, alto para crop
        escala = self.rP / self.rM  # escala, como relacion de radiopantalla a radiomundo
        pmin = QPoint()
        pmin.setX(pcX)
        pmin.setY(pcY + self.al)
        self.Pmin = self.toMapCoordinates(pmin)
        pmax = QPoint()
        pmax.setX(pcX + self.an)
        pmax.setY(pcY)
        self.Pmax = self.toMapCoordinates(pmax)

        # calculo area de recorte para hacer el crop
        rect = QRect(pcX, pcY, self.an, self.al)
        # hago crop
        cropped_pixmap = self.pixmap.copy(rect)

        # escalo el pixmap al tamaño que quiero
        self.scaled_pixmap = cropped_pixmap.scaled(
            self.parent.lado, self.parent.lado, Qt.KeepAspectRatioByExpanding,
            Qt.SmoothTransformation)
        # de pixmap a image
        image = QImage(self.scaled_pixmap.toImage())
        image = image.convertToFormat(QImage.Format_ARGB32)

        # preparo imagen de salida transparente y del tamaño del de entrada....
        out_img = QImage(image.width(), image.width(), QImage.Format_ARGB32)
        out_img.fill(Qt.transparent)

        # Create a texture brush and paint a circle with the original image onto
        # the output image: Chapeau!!

        # pintamos circulo relleno de imagen
        painter = QPainter(out_img)  # Paint the output image
        brush = QBrush(image)  # Create texture brush
        painter.setBrush(
            brush)  # Use the image texture brush  (como se pintara el relleno)
        pen = QPen(self.parent.color, 1, Qt.SolidLine)  #qVista claro
        painter.setPen(pen)
        painter.setRenderHint(QPainter.Antialiasing, True)  # Use AA
        painter.drawEllipse(0, 0, image.width(),
                            image.width())  # Actually draw the circle
        painter.end()  # We are done (segfault if you forget this)

        # de out_img a pixmap
        self.scaled_pixmap = QPixmap.fromImage(out_img)

        # muestro ese pixmap en label...
        self.parent.label.setPixmap(self.scaled_pixmap)

        # y lo salvo como temporal2
        fic_tmp = os.path.join(self.tempdir, "temporal2.png")
        self.fileName = fic_tmp

        if self.fileName:
            # Guardo el pixmap como png
            self.scaled_pixmap.save(self.fileName)
            # Calculo info para el PQW
            # rango mundo x e y
            xdist = self.Pmax.x() - self.Pmin.x()
            ydist = self.Pmax.y() - self.Pmin.y()

            # ancho y alto de la imagen
            iheight = self.scaled_pixmap.height()
            iwidth = self.scaled_pixmap.width()

            # Preparo nombre del PGW
            split_nombre = os.path.splitext(self.fileName)
            filenamePgw = split_nombre[0] + ".pgw"

            # Escribo PGW
            wld = open(filenamePgw, "w")
            wld.writelines("%s\n" % (xdist / iwidth))
            wld.writelines("0.0\n")
            wld.writelines("0.0\n")
            wld.writelines("%s\n" % (ydist / iheight))
            wld.writelines("%s\n" % self.Pmin.x())
            wld.writelines("%s\n" % self.Pmin.y())
            wld.close

        #  muestro datos de georeferenciacion
        literal = "xmin,ymin=" + str(round(self.Pmin.x(), 3)) + "  " + str(
            round(self.Pmin.y(), 3))
        self.parent.xmin_ymin.setText(literal)
        literal = "xmax,ymax=" + str(round(self.Pmax.x(), 3)) + "  " + str(
            round(self.Pmax.y(), 3))
        self.parent.xmax_ymax.setText(literal)

        try:
            self.reset()
        except:
            pass

    def canvasReleaseEvent(self, e):
        '''
        Damos por dibujado el circulo al dejar de presionar el boton
        '''
        if self.status == 0:
            return

        # Calculo datos para el recorte
        self.xcM = self.centre.x()
        self.ycM = self.centre.y()  # Punto centro circulo Mundo
        self.xcP = self.centroEnPantalla.x()
        self.ycP = self.centroEnPantalla.y()  # Punto centro circulo Pantalla
        self.xrP = self.final.x()
        self.yrP = self.final.y()  # Punto radio Pantalla
        self.rM = self.radio

        # Calculo rango del circulo
        xmin = self.xcM - self.rM
        ymin = self.ycM - self.rM
        xmax = self.xcM + self.rM
        ymax = self.ycM + self.rM

        # Se lo paso al canvas para hacer zoom a esa zona
        self.rang = QgsRectangle(xmin, ymin, xmax, ymax)

        self.canvas.mapCanvasRefreshed.connect(self.pre_saveCanvas)
        self.canvas.setExtent(self.rang)
        self.canvas.refresh()

    def reset(self):
        '''
        '''
        self.status = 0
        self.rb.reset(True)

    def deactivate(self):
        '''
        '''
        pass