class GeometryDiffViewerDialog(QDialog):
    def __init__(self, geoms, crs, parent=None):
        super(GeometryDiffViewerDialog, self).__init__(parent)
        self.geoms = geoms
        self.crs = crs
        self.initGui()

    def initGui(self):
        layout = QVBoxLayout()
        self.tab = QTabWidget()
        self.table = QTableView()

        self.setLayout(layout)
        self.canvas = QgsMapCanvas()
        self.canvas.setCanvasColor(Qt.white)
        settings = QSettings()
        self.canvas.enableAntiAliasing(
            settings.value("/qgis/enable_anti_aliasing", False, type=bool))
        self.canvas.useImageToRender(
            settings.value("/qgis/use_qimage_to_render", False, type=bool))
        self.canvas.mapSettings().setDestinationCrs(self.crs)
        action = settings.value("/qgis/wheel_action", 0, type=float)
        zoomFactor = settings.value("/qgis/zoom_factor", 2, type=float)
        self.canvas.setWheelAction(QgsMapCanvas.WheelAction(action),
                                   zoomFactor)
        self.panTool = QgsMapToolPan(self.canvas)
        self.canvas.setMapTool(self.panTool)

        execute(self.createLayers)

        model = GeomDiffTableModel(self.data)
        self.table.setModel(model)
        self.table.resizeColumnsToContents()
        self.table.resizeRowsToContents()
        self.tab.addTab(self.canvas, "Map view")
        self.tab.addTab(self.table, "Table view")
        layout.addWidget(self.tab)

        self.resize(600, 500)
        self.setWindowTitle("Geometry comparison")

    def createLayers(self):
        textGeometries = []
        for geom in self.geoms:
            text = geom.exportToWkt()
            valid = " -1234567890.,"
            text = "".join([c for c in text if c in valid])
            textGeometries.append(text.split(","))
        lines = difflib.Differ().compare(textGeometries[0], textGeometries[1])
        self.data = []
        for line in lines:
            if line.startswith("+"):
                self.data.append([None, line[2:]])
            if line.startswith("-"):
                self.data.append([line[2:], None])
            if line.startswith(" "):
                self.data.append([line[2:], line[2:]])
        types = [("LineString", lineBeforeStyle, lineAfterStyle),
                 ("Polygon", polygonBeforeStyle, polygonAfterStyle)]
        layers = []
        extent = self.geoms[0].boundingBox()
        for i, geom in enumerate(self.geoms):
            geomtype = types[int(geom.type() - 1)][0]
            style = types[int(geom.type() - 1)][i + 1]
            layer = loadLayerNoCrsDialog(
                geomtype + "?crs=" + self.crs.authid(), "layer", "memory")
            pr = layer.dataProvider()
            feat = QgsFeature()
            feat.setGeometry(geom)
            pr.addFeatures([feat])
            layer.loadNamedStyle(style)
            layer.updateExtents()
            layers.append(layer)
            QgsMapLayerRegistry.instance().addMapLayer(layer, False)
            extent.combineExtentWith(geom.boundingBox())

        layer = loadLayerNoCrsDialog(
            "Point?crs=%s&field=changetype:string" % self.crs.authid(),
            "points", "memory")
        pr = layer.dataProvider()
        feats = []
        for coords in self.data:
            coord = coords[0] or coords[1]
            feat = QgsFeature()
            x, y = coord.strip().split(" ")
            x, y = (float(x), float(y))
            pt = QgsGeometry.fromPoint(QgsPoint(x, y))
            feat.setGeometry(pt)
            if coords[0] is None:
                changetype = "A"
            elif coords[1] is None:
                changetype = "R"
            else:
                changetype = "U"
            feat.setAttributes([changetype])
            feats.append(feat)

        pr.addFeatures(feats)
        layer.loadNamedStyle(pointsStyle)
        QgsMapLayerRegistry.instance().addMapLayer(layer, False)
        layers.append(layer)

        self.mapLayers = [QgsMapCanvasLayer(lay) for lay in layers]
        self.canvas.setLayerSet(self.mapLayers)
        self.canvas.setExtent(extent)
        self.canvas.refresh()

    def reject(self):
        QDialog.reject(self)
Exemple #2
0
class FreezeTableWidget(QTableView):

    def __init__(
            self, table_data, headers, parent=None, *args
    ):
        """
        Creates two QTableViews one of which is a frozen table while the
        other one can scroll behind it.
        :param table_data: The data that goes into the tables
        :type table_data: List
        :param headers: The header data of the tables.
        :type headers: List
        :param parent: The parent of the QTableView
        :type parent: QWidget
        :param args:
        :type args:
        """
        QTableView.__init__(self, parent)
        # set the table model
        self.table_model = BaseSTDMTableModel(
            table_data, headers, parent
        )
        # set the proxy model
        proxy_model = QSortFilterProxyModel(self)
        proxy_model.setSourceModel(self.table_model)
        # Assign a data model for TableView
        self.setModel(self.table_model)
        # frozen_table_view - first column
        self.frozen_table_view = QTableView(self)
        # Set the model for the widget, fixed column
        self.frozen_table_view.setModel(self.table_model)
        # Hide row headers
        self.frozen_table_view.verticalHeader().hide()
        # Widget does not accept focus
        self.frozen_table_view.setFocusPolicy(
            Qt.StrongFocus | Qt.TabFocus | Qt.ClickFocus
        )
        # The user can not resize columns
        self.frozen_table_view.horizontalHeader(). \
            setSectionResizeMode(QHeaderView.Fixed)
        self.frozen_table_view.setObjectName('frozen_table')
        self.setSelectionMode(QAbstractItemView.NoSelection)
        # Remove the scroll bar
        self.frozen_table_view.setHorizontalScrollBarPolicy(
            Qt.ScrollBarAlwaysOff
        )
        self.frozen_table_view.setVerticalScrollBarPolicy(
            Qt.ScrollBarAlwaysOff
        )
        # Puts more widgets to the foreground
        self.viewport().stackUnder(self.frozen_table_view)
        # # Log in to edit mode - even with one click
        # Set the properties of the column headings
        hh = self.horizontalHeader()
        # Text alignment centered
        hh.setDefaultAlignment(Qt.AlignCenter)

        self.set_column_width()
        # Set properties header lines
        vh = self.verticalHeader()
        vh.setDefaultSectionSize(25)  # height lines
        # text alignment centered
        vh.setDefaultAlignment(Qt.AlignCenter)
        vh.setVisible(True)
        # Height of rows - as in the main widget
        self.frozen_table_view.verticalHeader(). \
            setDefaultSectionSize(
            vh.defaultSectionSize()
        )
        # Show frozen table view
        self.frozen_table_view.show()
        # Set the size of him like the main

        self.setHorizontalScrollMode(
            QAbstractItemView.ScrollPerPixel
        )
        self.setVerticalScrollMode(
            QAbstractItemView.ScrollPerPixel
        )
        self.frozen_table_view.setVerticalScrollMode(
            QAbstractItemView.ScrollPerPixel
        )
        ## select the first column (STR Type)
        self.frozen_table_view.selectColumn(0)

        self.frozen_table_view.setEditTriggers(
            QAbstractItemView.AllEditTriggers
        )
        self.set_size()
        self.signals()

    def set_size(self):
        """
        Sets the size and size policy of the tables.
        :return:
        :rtype:
        """
        size_policy = QSizePolicy(
            QSizePolicy.Fixed, QSizePolicy.Fixed
        )
        size_policy.setHorizontalStretch(0)
        size_policy.setVerticalStretch(0)
        size_policy.setHeightForWidth(
            self.sizePolicy().hasHeightForWidth()
        )
        self.setSizePolicy(size_policy)
        self.setMinimumSize(QSize(55, 75))
        self.setMaximumSize(QSize(5550, 5555))
        self.SelectionMode(
            QAbstractItemView.SelectColumns
        )
        # set column width to fit contents
        self.frozen_table_view.resizeColumnsToContents()
        # set row height
        self.frozen_table_view.resizeRowsToContents()

    def signals(self):
        """
        Connects signals of the tables.
        """
        # Connect the headers and scrollbars of
        # both tableviews together
        self.horizontalHeader().sectionResized.connect(
            self.update_section_width
        )
        self.verticalHeader().sectionResized.connect(
            self.update_section_height
        )
        self.frozen_table_view.verticalScrollBar().valueChanged.connect(
            self.verticalScrollBar().setValue
        )
        self.verticalScrollBar().valueChanged.connect(
            self.frozen_table_view.verticalScrollBar().setValue
        )

    def set_column_width(self):
        """
        Sets the column width of the frozen QTableView.
        """
        # Set the width of columns
        columns_count = self.table_model.columnCount(self)
        for col in range(columns_count):
            if col == 0:
                # Set the size
                self.horizontalHeader().resizeSection(
                    col, 60
                )
                # Fix width
                self.horizontalHeader().setSectionResizeMode(
                    col, QHeaderView.Fixed
                )
                # Width of a fixed column - as in the main widget
                self.frozen_table_view.setColumnWidth(
                    col, self.columnWidth(col)
                )
            elif col == 1:
                self.horizontalHeader().resizeSection(
                    col, 150
                )
                self.horizontalHeader().setSectionResizeMode(
                    col, QHeaderView.Fixed
                )
                self.frozen_table_view.setColumnWidth(
                    col, self.columnWidth(col)
                )
            else:
                self.horizontalHeader().resizeSection(
                    col, 150
                )
                # Hide unnecessary columns in the
                # widget fixed columns
                self.frozen_table_view.setColumnHidden(
                    col, True
                )

    def add_widgets(self, spatial_unit, insert_row):
        """
        Adds widget into the frozen table.
        :param str_type_id: The STR type id of the tenure type combobox
        :type str_type_id: Integer
        :param insert_row: The row number the widgets to be added.
        :type insert_row: Integer
        """
        delegate = STRTypeDelegate(spatial_unit)
        # Set delegate to add combobox under
        # social tenure type column
        self.frozen_table_view.setItemDelegate(
            delegate
        )
        self.frozen_table_view.setItemDelegateForColumn(
            0, delegate
        )
        index = self.frozen_table_view.model().index(
            insert_row, 0, QModelIndex()
        )
        self.frozen_table_view.model().setData(
            index, '', Qt.EditRole
        )

        self.frozen_table_view.openPersistentEditor(
            self.frozen_table_view.model().index(insert_row, 0)
        )
        self.frozen_table_view.openPersistentEditor(
            self.frozen_table_view.model().index(insert_row, 1)
        )

    def update_section_width(
            self, logicalIndex, oldSize, newSize
    ):
        """
        Updates frozen table column width and geometry.
        :param logicalIndex: The section's logical number
        :type logicalIndex: Integer
        :param oldSize: The old size of the section
        :type oldSize: Integer
        :param newSize: The new size of the section
        :type newSize: Integer
        """
        if logicalIndex == 0 or logicalIndex == 1:
            self.frozen_table_view.setColumnWidth(
                logicalIndex, newSize
            )
            self.update_frozen_table_geometry()

    def update_section_height(
            self, logicalIndex, oldSize, newSize
    ):
        """
        Updates frozen table column height.
        :param logicalIndex: The section's logical number
        :type logicalIndex: Integer
        :param oldSize: The old size of the section
        :type oldSize: Integer
        :param newSize: The new size of the section
        :type newSize: Integer
        """
        self.frozen_table_view.setRowHeight(
            logicalIndex, newSize
        )

    def resizeEvent(self, event):
        """
        Handles the resize event of the frozen table view.
        It updates the frozen table view geometry on resize of table.
        :param event: The event
        :type event: QEvent
        """
        QTableView.resizeEvent(self, event)
        try:
            self.update_frozen_table_geometry()
        except DummyException as log:
            LOGGER.debug(str(log))

    def scrollTo(self, index, hint):
        """
        Scrolls the view if necessary to ensure that the item at index is
        visible. The view will try to position the item according to the
        given hint.
        :param index: The scroll index
        :type index: QModelIndex
        :param hint: The scroll hint
        :type hint: Integer
        """
        if index.column() > 1:
            QTableView.scrollTo(self, index, hint)

    def update_frozen_table_geometry(self):
        """
        Updates the frozen table view geometry.
        """
        if self.verticalHeader().isVisible():
            self.frozen_table_view.setGeometry(
                self.verticalHeader().width() +
                self.frameWidth(),
                self.frameWidth(),
                self.columnWidth(0) + self.columnWidth(1),
                self.viewport().height() +
                self.horizontalHeader().height()
            )
        else:
            self.frozen_table_view.setGeometry(
                self.frameWidth(),
                self.frameWidth(),
                self.columnWidth(0) + self.columnWidth(1),
                self.viewport().height() +
                self.horizontalHeader().height()
            )

    def move_cursor(self, cursor_action, modifiers):
        """
        Override function for correct left to scroll the keyboard.
        Returns a QModelIndex object pointing to the next object in the
        table view, based on the given cursorAction and keyboard modifiers
        specified by modifiers.
        :param cursor_action: The cursor action
        :type cursor_action: Integer
        :param modifiers: Qt.KeyboardModifier value.
        :type modifiers: Object
        :return: The current cursor position.
        :rtype: QModelIndex
        """
        current = QTableView.move_cursor(
            self, cursor_action, modifiers
        )
        if cursor_action == self.MoveLeft and current.column() > 1 and \
                self.visualRect(current).topLeft().x() < \
                (self.frozen_table_view.columnWidth(0) +
                 self.frozen_table_view.columnWidth(1)):
            new_value = self.horizontalScrollBar().value() + \
                        self.visualRect(current).topLeft().x() - \
                        (self.frozen_table_view.columnWidth(0) +
                         self.frozen_table_view.columnWidth(1))
            self.horizontalScrollBar().setValue(new_value)
        return current
class GeometryDiffViewerDialog(QDialog):

    def __init__(self, geoms, crs, parent = None):
        super(GeometryDiffViewerDialog, self).__init__(parent)
        self.geoms = geoms
        self.crs = crs
        self.initGui()

    def initGui(self):
        layout = QVBoxLayout()
        self.tab = QTabWidget()
        self.table = QTableView()

        self.setLayout(layout)
        self.canvas = QgsMapCanvas()
        self.canvas.setCanvasColor(Qt.white)
        settings = QSettings()
        self.canvas.enableAntiAliasing(settings.value("/qgis/enable_anti_aliasing", False, type = bool))
        self.canvas.useImageToRender(settings.value("/qgis/use_qimage_to_render", False, type = bool))
        self.canvas.mapSettings().setDestinationCrs(self.crs)
        action = settings.value("/qgis/wheel_action", 0, type = float)
        zoomFactor = settings.value("/qgis/zoom_factor", 2, type = float)
        self.canvas.setWheelAction(QgsMapCanvas.WheelAction(action), zoomFactor)
        self.panTool = QgsMapToolPan(self.canvas)
        self.canvas.setMapTool(self.panTool)

        execute(self.createLayers)

        model = GeomDiffTableModel(self.data)
        self.table.setModel(model)
        self.table.resizeColumnsToContents()
        self.table.resizeRowsToContents()
        self.tab.addTab(self.canvas, "Map view")
        self.tab.addTab(self.table, "Table view")
        layout.addWidget(self.tab)

        self.resize(600, 500)
        self.setWindowTitle("Geometry comparison")


    def createLayers(self):
        textGeometries = []
        for geom in self.geoms:
            text = geom.exportToWkt()
            valid = " -1234567890.,"
            text = "".join([c for c in text if c in valid])
            textGeometries.append(text.split(","))
        lines = difflib.Differ().compare(textGeometries[0], textGeometries[1])
        self.data = []
        for line in lines:
            if line.startswith("+"):
                self.data.append([None, line[2:]])
            if line.startswith("-"):
                self.data.append([line[2:], None])
            if line.startswith(" "):
                self.data.append([line[2:], line[2:]])
        types = [("LineString", lineBeforeStyle, lineAfterStyle),
                  ("Polygon", polygonBeforeStyle, polygonAfterStyle)]
        layers = []
        extent = self.geoms[0].boundingBox()
        for i, geom in enumerate(self.geoms):
            geomtype = types[int(geom.type() - 1)][0]
            style = types[int(geom.type() - 1)][i + 1]
            layer = loadLayerNoCrsDialog(geomtype + "?crs=" + self.crs.authid(), "layer", "memory")
            pr = layer.dataProvider()
            feat = QgsFeature()
            feat.setGeometry(geom)
            pr.addFeatures([feat])
            layer.loadNamedStyle(style)
            layer.updateExtents()
            layers.append(layer)
            QgsMapLayerRegistry.instance().addMapLayer(layer, False)
            extent.combineExtentWith(geom.boundingBox())

        layer = loadLayerNoCrsDialog("Point?crs=%s&field=changetype:string" % self.crs.authid(), "points", "memory")
        pr = layer.dataProvider()
        feats = []
        for coords in self.data:
            coord = coords[0] or coords[1]
            feat = QgsFeature()
            x, y = coord.strip().split(" ")
            x, y = (float(x), float(y))
            pt = QgsGeometry.fromPoint(QgsPoint(x, y))
            feat.setGeometry(pt)
            if coords[0] is None:
                changetype = "A"
            elif coords[1] is None:
                changetype = "R"
            else:
                changetype = "U"
            feat.setAttributes([changetype])
            feats.append(feat)

        pr.addFeatures(feats)
        layer.loadNamedStyle(pointsStyle)
        QgsMapLayerRegistry.instance().addMapLayer(layer, False)
        layers.append(layer)

        self.mapLayers = [QgsMapCanvasLayer(lay) for lay in layers]
        self.canvas.setLayerSet(self.mapLayers)
        self.canvas.setExtent(extent)
        self.canvas.refresh()

    def reject(self):
        QDialog.reject(self)