class ParentMapTool(QgsMapTool):
    def __init__(self, iface, settings, action, index_action):
        """ Class constructor """

        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        self.settings = settings
        self.show_help = bool(int(self.settings.value('status/show_help', 1)))
        self.index_action = index_action
        self.layer_arc = None
        self.layer_connec = None
        self.layer_node = None

        self.layer_arc_man = None
        self.layer_connec_man = None
        self.layer_node_man = None
        self.layer_gully_man = None

        self.schema_name = None
        self.controller = None
        self.dao = None

        # Call superclass constructor and set current action
        QgsMapTool.__init__(self, self.canvas)
        self.setAction(action)

        # Snapper
        self.snapper_manager = SnappingConfigManager(self.iface)
        self.snapper = QgsMapCanvasSnapper(self.canvas)

        # Change map tool cursor
        self.cursor = QCursor()
        self.cursor.setShape(Qt.CrossCursor)

        # Get default cursor
        self.std_cursor = self.parent().cursor()

        # Set default vertex marker
        color = QColor(255, 100, 255)
        self.vertex_marker = QgsVertexMarker(self.canvas)
        self.vertex_marker.setIconType(QgsVertexMarker.ICON_CIRCLE)
        self.vertex_marker.setColor(color)
        self.vertex_marker.setIconSize(15)
        self.vertex_marker.setPenWidth(3)

        # Set default rubber band
        color_selection = QColor(254, 178, 76, 63)
        self.rubber_band = QgsRubberBand(self.canvas, QGis.Polygon)
        self.rubber_band.setColor(color)
        self.rubber_band.setFillColor(color_selection)
        self.rubber_band.setWidth(1)
        self.reset()

        self.force_active_layer = True

        # Set default encoding
        reload(sys)
        sys.setdefaultencoding('utf-8')  #@UndefinedVariable

    def get_cursor_multiple_selection(self):
        """ Set cursor for multiple selection """

        path_folder = os.path.join(os.path.dirname(__file__), os.pardir)
        path_cursor = os.path.join(path_folder, 'icons', '201.png')
        if os.path.exists(path_cursor):
            cursor = QCursor(QPixmap(path_cursor))
        else:
            cursor = QCursor(Qt.ArrowCursor)

        return cursor

    def set_layers(self,
                   layer_arc_man,
                   layer_connec_man,
                   layer_node_man,
                   layer_gully_man=None):
        """ Sets layers involved in Map Tools functions
            Sets Snapper Manager """
        self.layer_arc_man = layer_arc_man
        self.layer_connec_man = layer_connec_man
        self.layer_node_man = layer_node_man
        self.layer_gully_man = layer_gully_man
        self.snapper_manager.set_layers(layer_arc_man, layer_connec_man,
                                        layer_node_man, layer_gully_man)

    def set_controller(self, controller):
        self.controller = controller
        self.schema_name = controller.schema_name
        self.plugin_dir = self.controller.plugin_dir
        self.snapper_manager.controller = controller

    def deactivate(self):

        # Uncheck button
        self.action().setChecked(False)

        # Restore previous snapping
        self.snapper_manager.recover_snapping_options()

        # Recover cursor
        self.canvas.setCursor(self.std_cursor)

        # Remove highlight
        self.vertex_marker.hide()

    def set_icon(self, widget, icon):
        """ Set @icon to selected @widget """

        # Get icons folder
        icons_folder = os.path.join(self.plugin_dir, 'icons')
        icon_path = os.path.join(icons_folder, str(icon) + ".png")
        if os.path.exists(icon_path):
            widget.setIcon(QIcon(icon_path))
        else:
            self.controller.log_info("File not found", parameter=icon_path)

    def set_action_pan(self):
        """ Set action 'Pan' """
        try:
            self.iface.actionPan().trigger()
        except Exception:
            pass

    def reset(self):

        # Graphic elements
        self.rubber_band.reset(QGis.Polygon)

        # Selection
        self.snapped_feat = None

    def cancel_map_tool(self):
        """ Executed if user press right button or escape key """

        # Reset rubber band
        self.reset()

        # Deactivate map tool
        self.deactivate()
        self.set_action_pan()

    def remove_markers(self):
        """ Remove previous markers """

        vertex_items = [
            i for i in self.canvas.scene().items()
            if issubclass(type(i), QgsVertexMarker)
        ]
        for ver in vertex_items:
            if ver in self.canvas.scene().items():
                self.canvas.scene().removeItem(ver)

    def refresh_map_canvas(self):
        """ Refresh all layers present in map canvas """

        self.canvas.refreshAllLayers()
        for layer_refresh in self.canvas.layers():
            layer_refresh.triggerRepaint()

    def open_dialog(self,
                    dlg=None,
                    dlg_name=None,
                    maximize_button=True,
                    stay_on_top=True):
        """ Open dialog """

        if dlg is None or type(dlg) is bool:
            dlg = self.dlg

        # Manage i18n of the dialog
        if dlg_name:
            self.controller.manage_translation(dlg_name, dlg)

        # Manage stay on top and maximize button
        if maximize_button and stay_on_top:
            dlg.setWindowFlags(Qt.WindowMinimizeButtonHint
                               | Qt.WindowMaximizeButtonHint
                               | Qt.WindowStaysOnTopHint)
        elif not maximize_button and stay_on_top:
            dlg.setWindowFlags(Qt.WindowMinimizeButtonHint
                               | Qt.WindowStaysOnTopHint)
        elif maximize_button and not stay_on_top:
            dlg.setWindowFlags(Qt.WindowMaximizeButtonHint)

        # Open dialog
        dlg.open()

    def close_dialog(self, dlg=None, set_action_pan=True):
        """ Close dialog """

        if dlg is None or type(dlg) is bool:
            dlg = self.dlg
        try:
            self.save_settings(dlg)
            dlg.close()
            if set_action_pan:
                map_tool = self.canvas.mapTool()
                # If selected map tool is from the plugin, set 'Pan' as current one
                if map_tool.toolName() == '':
                    self.set_action_pan()
        except AttributeError:
            pass

    def load_settings(self, dialog=None):
        """ Load QGIS settings related with dialog position and size """

        if dialog is None:
            dialog = self.dlg

        try:
            width = self.controller.plugin_settings_value(
                dialog.objectName() + "_width", dialog.width())
            height = self.controller.plugin_settings_value(
                dialog.objectName() + "_height", dialog.height())
            x = self.controller.plugin_settings_value(dialog.objectName() +
                                                      "_x")
            y = self.controller.plugin_settings_value(dialog.objectName() +
                                                      "_y")
            if int(x) < 0 or int(y) < 0:
                dialog.resize(int(width), int(height))
            else:
                dialog.setGeometry(int(x), int(y), int(width), int(height))
        except:
            pass

    def save_settings(self, dialog=None):
        """ Save QGIS settings related with dialog position and size """

        if dialog is None:
            dialog = self.dlg

        try:
            self.controller.plugin_settings_set_value(
                dialog.objectName() + "_width", dialog.width())
            self.controller.plugin_settings_set_value(
                dialog.objectName() + "_height", dialog.height())
            self.controller.plugin_settings_set_value(
                dialog.objectName() + "_x",
                dialog.pos().x())
            self.controller.plugin_settings_set_value(
                dialog.objectName() + "_y",
                dialog.pos().y())
        except:
            pass

    def check_expression(self, expr_filter, log_info=False):
        """ Check if expression filter @expr is valid """

        if log_info:
            self.controller.log_info(expr_filter)
        expr = QgsExpression(expr_filter)
        if expr.hasParserError():
            message = "Expression Error"
            self.controller.log_warning(message, parameter=expr_filter)
            return (False, expr)
        return (True, expr)

    def canvasMoveEvent(self, event):

        # Make sure active layer is always 'v_edit_node'
        cur_layer = self.iface.activeLayer()
        if cur_layer != self.layer_node and self.force_active_layer:
            self.iface.setActiveLayer(self.layer_node)

        # Hide highlight
        self.vertex_marker.hide()

        try:
            # Get current mouse coordinates
            x = event.pos().x()
            y = event.pos().y()
            event_point = QPoint(x, y)
        except (TypeError, KeyError):
            self.iface.actionPan().trigger()
            return

        # Snapping
        (retval,
         result) = self.snapper.snapToCurrentLayer(event_point,
                                                   2)  # @UnusedVariable

        # That's the snapped features
        if result:
            # Get the point and add marker on it
            point = QgsPoint(result[0].snappedVertex)
            self.vertex_marker.setCenter(point)
            self.vertex_marker.show()
class CaptureCoordinateToolUpdate(QgsMapTool):
    def __init__(self, canvas, annotation=None):
        self.canvas = canvas
        #         self.tableView = tableView
        #         self.standardItemModel = standardItemModel
        #         self.txtXCoord = txtXCoord
        #         self.txtYCoord = txtYCoord
        QgsMapToolEmitPoint.__init__(self, self.canvas)
        self.annotation = annotation
        self.mSnapper = QgsMapCanvasSnapper(canvas)
        self.rubberBand = QgsRubberBand(canvas, QGis.Point)
        self.rubberBand.setColor(Qt.red)
        self.rubberBand.setWidth(10)
        self.rubberBandClick = QgsRubberBand(canvas, QGis.Point)
        self.rubberBandClick.setColor(Qt.green)
        self.rubberBandClick.setWidth(3)
        self.obstaclesLayerList = QgisHelper.getSurfaceLayers(
            SurfaceTypes.Obstacles)
        self.demLayerList = QgisHelper.getSurfaceLayers(SurfaceTypes.DEM)
        #         lblDoc = QTextDocument(label)
        #         self.annotation.setDocument(lblDoc)
        #         self.annotation.setFrameBackgroundColor(QColor(0,0,0,0))
        #         self.annotation.setFrameSize( QSizeF( 30, 20 ) )

        self.reset()

    def reset(self):
        self.Point = None
#     def canvasPressEvent(self, e):

    def canvasReleaseEvent(self, e):
        pointBackground = e.pos()
        #         self.Point = QgisHelper.snapPoint(e.pos(), self.mSnapper, define._canvas)
        self.Point, self.pointID, self.layer = self.snapPoint(e.pos())
        self.selectedLayerFromSnapPoint = None
        resultValueList = []
        if self.annotation is not None:
            self.annotation.setMapPosition(self.Point)
            self.annotation.show()
        else:
            self.rubberBandClick.reset(QGis.Point)
            #         snapPoint = QgisHelper.snapPoint(e.pos(), self.mSnapper, define._canvas, True)

            self.rubberBandClick.addPoint(self.Point)
            self.rubberBandClick.show()
        self.selectedLayerFromSnapPoint = define._canvas.currentLayer()
        # if self.obstaclesLayerList != None:
        #     for obstacleLayer in self.obstaclesLayerList:
        #         if self.layer == None:
        #             break
        #         if obstacleLayer.name() == self.layer.name():
        #             self.selectedLayerFromSnapPoint = self.layer
        #             break
        if self.selectedLayerFromSnapPoint != None and isinstance(
                self.selectedLayerFromSnapPoint,
                QgsVectorLayer) and self.pointID != None:
            # if self.pointID == None:
            #     resultValueList.append("Background")
            #
            #     resultValueList.append(str(self.Point.x()))
            #     resultValueList.append(str(self.Point.y()))
            #     resultValueList.append("0.0")
            # else:
            dataProvider = self.selectedLayerFromSnapPoint.dataProvider()
            featureIter = dataProvider.getFeatures(
                QgsFeatureRequest(self.pointID))
            feature = None
            for feature0 in featureIter:
                feature = feature0

            idx = self.selectedLayerFromSnapPoint.fieldNameIndex('Name')
            if not idx == -1:
                idValue = feature.attributes()[idx]
                resultValueList.append(idValue.toString())
            else:
                resultValueList.append("")
#             itemList.append(QStandardItem(idValue.toString()))

            resultValueList.append(str(self.Point.x()))
            resultValueList.append(str(self.Point.y()))

            idx = self.selectedLayerFromSnapPoint.fieldNameIndex('Altitude')
            if not idx == -1:
                altitudeValue = feature.attributes()[idx]
                resultValueList.append(altitudeValue.toString())
            else:
                resultValueList.append("0.0")

        else:

            if self.Point != None:
                identifyResult = None
                idValue = "Background"
                if self.demLayerList != None:

                    for demLayer in self.demLayerList:
                        identifyResults = demLayer.dataProvider().identify(
                            self.Point, QgsRaster.IdentifyFormatValue)
                        identifyResult = identifyResults.results()
                if identifyResult != None and identifyResult[1].toString(
                ) != "":
                    idValue = "DEM"

                resultValueList.append(idValue)
                resultValueList.append(str(self.Point.x()))
                resultValueList.append(str(self.Point.y()))
                if identifyResult != None and identifyResult[1].toString(
                ) != "":
                    resultValueList.append(identifyResult[1].toString())
                else:
                    resultValueList.append("0")
        self.emit(SIGNAL("resultPointValueList"), resultValueList)

    def canvasMoveEvent(self, e):
        if define._snapping == False:
            return
        self.rubberBand.reset(QGis.Point)
        #         snapPoint = QgisHelper.snapPoint(e.pos(), self.mSnapper, define._canvas, True)
        snapPoint, snapPointID, layer = self.snapPoint(e.pos(), True)
        if snapPoint == None:
            return
        self.rubberBand.addPoint(snapPoint)
        self.rubberBand.show()
#         print snapPointID

    def snapPoint(self, p, bNone=False):
        if define._snapping == False:
            return (
                define._canvas.getCoordinateTransform().toMapCoordinates(p),
                None, None)
        snappingResults = self.mSnapper.snapToCurrentLayer(
            p, QgsSnapper.SnapToVertex)
        if (snappingResults[0] != 0 or len(snappingResults[1]) < 1):

            if bNone:
                return (None, None, None)
            else:
                return (define._canvas.getCoordinateTransform().
                        toMapCoordinates(p), None, None)
        else:
            return (snappingResults[1][0].snappedVertex,
                    snappingResults[1][0].snappedAtGeometry,
                    snappingResults[1][0].layer)

    def deactivate(self):
        self.rubberBand.reset(QGis.Point)
        QgsMapTool.deactivate(self)
        self.emit(SIGNAL("deactivated()"))
class DrawProfiles(ParentMapTool):
    """ Button 43: Draw_profiles """
    def __init__(self, iface, settings, action, index_action):
        """ Class constructor """

        # Call ParentMapTool constructor
        super(DrawProfiles, self).__init__(iface, settings, action,
                                           index_action)

        self.list_of_selected_nodes = []
        self.nodes = []

    def activate(self):

        # Get version of pgRouting
        sql = "SELECT version FROM pgr_version()"
        row = self.controller.get_row(sql)
        if not row:
            message = "Error getting pgRouting version"
            self.controller.show_warning(message)
            return
        self.version = str(row[0][:1])

        self.dlg = DrawProfile()
        utils_giswater.setDialog(self.dlg)
        self.dlg.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.set_icon(self.dlg.btn_add_start_point, "111")
        self.set_icon(self.dlg.btn_add_end_point, "111")
        self.set_icon(self.dlg.btn_add_arc, "111")
        self.set_icon(self.dlg.btn_delete_arc, "112")
        self.dlg.findChild(QPushButton, "btn_add_start_point").clicked.connect(
            self.activate_snapping_node1)
        self.dlg.findChild(QPushButton, "btn_add_end_point").clicked.connect(
            self.activate_snapping_node2)

        self.btn_save_profile = self.dlg.findChild(QPushButton,
                                                   "btn_save_profile")
        self.btn_save_profile.clicked.connect(self.save_profile)
        self.btn_load_profile = self.dlg.findChild(QPushButton,
                                                   "btn_load_profile")
        self.btn_load_profile.clicked.connect(self.load_profile)

        self.profile_id = self.dlg.findChild(QLineEdit, "profile_id")
        self.widget_start_point = self.dlg.findChild(QLineEdit, "start_point")
        self.widget_end_point = self.dlg.findChild(QLineEdit, "end_point")

        self.group_pointers_node = []
        self.group_layers_node = [
            "Junction", "Valve", "Reduction", "Tank", "Meter", "Manhole",
            "Source", "Hydrant", "Pump", "Filter", "Waterwell", "Register",
            "Netwjoin"
        ]
        for layername in self.group_layers_node:
            layer = QgsMapLayerRegistry.instance().mapLayersByName(layername)
            if layer:
                self.group_pointers_node.append(layer[0])

        self.group_pointers_arc = []
        self.group_layers_arc = ["Conduit", "Siphon", "Varc", "Waccel"]
        for layername in self.group_layers_arc:
            layer = QgsMapLayerRegistry.instance().mapLayersByName(layername)
            if layer:
                self.group_pointers_arc.append(layer[0])

        self.nodes = []
        self.list_of_selected_nodes = []

        self.dlg.open()

    def save_profile(self):

        profile_id = self.profile_id.text()
        start_point = self.widget_start_point.text()
        end_point = self.widget_end_point.text()

        # Check if all data are entered
        if profile_id == '' or start_point == '' or end_point == '':
            self.controller.show_info_box("Some of data is missing", "Info")
            return

        # Check if id of profile already exists in DB
        sql = ("SELECT DISTINCT(profile_id)"
               " FROM " + self.schema_name + ".anl_arc_profile_value"
               " WHERE profile_id = '" + profile_id + "'")
        row = self.controller.get_row(sql)
        if row:
            self.controller.show_warning(
                "Selected 'profile_id' already exist in database",
                parameter=profile_id)
            return

        list_arc = []
        n = self.tbl_list_arc.count()
        for i in range(n):
            list_arc.append(str(self.tbl_list_arc.item(i).text()))

        for i in range(n):
            sql = "INSERT INTO " + self.schema_name + ".anl_arc_profile_value (profile_id, arc_id, start_point, end_point) "
            sql += " VALUES ('" + profile_id + "', '" + list_arc[
                i] + "', '" + start_point + "', '" + end_point + "')"
            status = self.controller.execute_sql(sql)
            if not status:
                message = "Error inserting profile table, you need to review data"
                self.controller.show_warning(message)
                return

        # Show message to user
        message = "Values has been updated"
        self.controller.show_info(message)
        self.deactivate()

    def load_profile(self):

        self.dlg_load = LoadProfiles()
        utils_giswater.setDialog(self.dlg_load)

        btn_open = self.dlg_load.findChild(QPushButton, "btn_open")
        btn_open.clicked.connect(self.open_profile)

        self.tbl_profiles = self.dlg_load.findChild(QListWidget,
                                                    "tbl_profiles")
        sql = "SELECT DISTINCT(profile_id) FROM " + self.schema_name + ".anl_arc_profile_value"
        rows = self.controller.get_rows(sql)
        if rows:
            for row in rows:
                item_arc = QListWidgetItem(str(row[0]))
                self.tbl_profiles.addItem(item_arc)

        self.dlg_load.open()
        self.dlg.close()
        self.deactivate()

    def open_profile(self):

        # Selected item from list
        selected_profile = self.tbl_profiles.currentItem().text()

        # Get data from DB for selected item| profile_id, start_point, end_point
        sql = "SELECT start_point, end_point"
        sql += " FROM " + self.schema_name + ".anl_arc_profile_value"
        sql += " WHERE profile_id = '" + selected_profile + "'"
        row = self.controller.get_row(sql)
        if not row:
            return

        start_point = row['start_point']
        end_point = row['end_point']

        # Fill widgets of form draw_profile | profile_id, start_point, end_point
        self.widget_start_point.setText(str(start_point))
        self.widget_end_point.setText(str(end_point))

        profile_id = self.dlg.findChild(QLineEdit, "profile_id")
        profile_id.setText(str(selected_profile))

        # Call dijkstra to set new list of arcs and list of nodes
        self.shortest_path(str(start_point), str(end_point))

        self.dlg_load.close()
        self.dlg.open()

    def activate_snapping_node1(self):

        # Create the appropriate map tool and connect the gotPoint() signal.
        self.emit_point = QgsMapToolEmitPoint(self.canvas)
        self.canvas.setMapTool(self.emit_point)
        self.snapper = QgsMapCanvasSnapper(self.canvas)

        # Get layer 'v_edit_node'
        layer = self.controller.get_layer_by_tablename("v_edit_node",
                                                       log_info=True)
        if layer:
            self.layer_valve_analytics = layer
            self.canvas.connect(self.canvas,
                                SIGNAL("xyCoordinates(const QgsPoint&)"),
                                self.mouse_move)
            self.emit_point.canvasClicked.connect(self.snapping_node1)

    def activate_snapping_node2(self):

        # Create the appropriate map tool and connect the gotPoint() signal.
        self.emit_point = QgsMapToolEmitPoint(self.canvas)
        self.canvas.setMapTool(self.emit_point)
        self.snapper = QgsMapCanvasSnapper(self.canvas)

        # Get layer 'v_edit_node'
        layer = self.controller.get_layer_by_tablename("v_edit_node",
                                                       log_info=True)
        if layer:
            self.layer_valve_analytics = layer
            self.canvas.connect(self.canvas,
                                SIGNAL("xyCoordinates(const QgsPoint&)"),
                                self.mouse_move)
            self.emit_point.canvasClicked.connect(self.snapping_node2)

    def mouse_move(self, p):

        map_point = self.canvas.getCoordinateTransform().transform(p)
        x = map_point.x()
        y = map_point.y()
        eventPoint = QPoint(x, y)

        # Snapping
        (retval,
         result) = self.snapper.snapToCurrentLayer(eventPoint,
                                                   2)  # @UnusedVariable

        # That's the snapped features
        if result:
            for snapped_point in result:
                viewname = self.controller.get_layer_source_table_name(
                    snapped_point.layer)
                if viewname == 'v_edit_node':
                    point = QgsPoint(snapped_point.snappedVertex)
                    # Add marker
                    self.vertex_marker.setCenter(point)
                    self.vertex_marker.show()
        else:
            self.vertex_marker.hide()

    def snapping_node1(self, point, btn):  # @UnusedVariable

        map_point = self.canvas.getCoordinateTransform().transform(point)
        x = map_point.x()
        y = map_point.y()
        event_point = QPoint(x, y)

        # Snapping
        (retval, result) = self.snapper.snapToBackgroundLayers(
            event_point)  # @UnusedVariable

        # That's the snapped point
        if result:
            # Check feature
            for snapped_point in result:
                element_type = snapped_point.layer.name()
                if element_type in self.group_layers_node:
                    # Get the point
                    point = QgsPoint(snapped_point.snappedVertex)
                    snapp_feature = next(
                        snapped_point.layer.getFeatures(
                            QgsFeatureRequest().setFilterFid(
                                snapped_point.snappedAtGeometry)))
                    element_id = snapp_feature.attribute('node_id')
                    self.element_id = str(element_id)
                    # Leave selection
                    snapped_point.layer.select(
                        [snapped_point.snappedAtGeometry])
                    self.widget_start_point.setText(str(element_id))

        node_start = str(self.widget_start_point.text())
        node_end = str(self.widget_end_point.text())
        if node_start != '' and node_end != '':
            self.shortest_path(str(node_start), str(node_end))

    def snapping_node2(self, point, btn):  # @UnusedVariable

        map_point = self.canvas.getCoordinateTransform().transform(point)
        x = map_point.x()
        y = map_point.y()
        event_point = QPoint(x, y)

        # Snapping
        (retval, result) = self.snapper.snapToBackgroundLayers(
            event_point)  # @UnusedVariable

        # That's the snapped point
        if result:
            # Check feature
            for snap_point in result:
                element_type = snap_point.layer.name()
                if element_type in self.group_layers_node:
                    # Get the point
                    point = QgsPoint(snap_point.snappedVertex)
                    snapp_feature = next(
                        snap_point.layer.getFeatures(
                            QgsFeatureRequest().setFilterFid(
                                snap_point.snappedAtGeometry)))
                    element_id = snapp_feature.attribute('node_id')
                    self.element_id = str(element_id)
                    # Leave selection
                    snap_point.layer.select([snap_point.snappedAtGeometry])
                    self.widget_end_point.setText(str(element_id))

        node_start = str(self.widget_start_point.text())
        node_end = str(self.widget_end_point.text())
        if node_start != '' and node_end != '':
            self.shortest_path(str(node_start), str(node_end))

    def paint_event(self, arc_id, node_id):
        """ Parent function - Draw profiles """

        # Clear plot
        plt.gcf().clear()

        # arc_id ,node_id list of nodes and arc form dijkstra algoritam
        self.set_parameters(arc_id, node_id)
        self.fill_memory()
        self.set_table_parameters()

        # Start drawing
        # Draw first | start node
        # Function self.draw_first_node(start_point, top_elev, ymax, z1, z2, cat_geom1, geom1)
        self.draw_first_node(self.memory[0][0], self.memory[0][1],
                             self.memory[0][2], self.memory[0][3],
                             self.memory[0][4], self.memory[0][5],
                             self.memory[0][6], 0)

        # Draw nodes between first and last node
        # Function self.draw_nodes(start_point, top_elev, ymax, z1, z2, cat_geom1, geom1, index)
        for i in range(1, self.n - 1):
            self.draw_nodes(self.memory[i][0], self.memory[i][1],
                            self.memory[i][2], self.memory[i][3],
                            self.memory[i][4], self.memory[i][5],
                            self.memory[i][6], i, self.memory[i - 1][4],
                            self.memory[i - 1][5])
            self.draw_arc()
            self.draw_ground()

        # Draw last node
        self.draw_last_node(
            self.memory[self.n - 1][0], self.memory[self.n - 1][1],
            self.memory[self.n - 1][2], self.memory[self.n - 1][3],
            self.memory[self.n - 1][4], self.memory[self.n - 1][5],
            self.memory[self.n - 1][6], self.n - 1, self.memory[self.n - 2][4],
            self.memory[self.n - 2][5])
        self.draw_arc()
        self.draw_ground()

        self.draw_table_horizontals()
        self.set_properties()

        self.draw_coordinates()
        self.draw_grid()

        # Maximeze window ( after drawing )
        mng = plt.get_current_fig_manager()
        mng.window.showMaximized()
        plt.show()

        # Action on resizing window
        self.fig1.canvas.mpl_connect('resize_event', self.on_resize)

    def set_properties(self):
        """ Set properties of main window """

        # Set window name
        self.win = plt.gcf()
        self.win.canvas.set_window_title('Draw Profile')

        # Hide axes
        self.axes = plt.gca()
        self.axes.set_axis_off()

        # Set background color of window
        self.fig1 = plt.figure(1)
        self.rect = self.fig1.patch
        self.rect.set_facecolor('white')

        # Set axes
        x_min = round(self.memory[0][0] - self.fix_x -
                      self.fix_x * Decimal(0.15))
        x_max = round(self.memory[self.n - 1][0] + self.fix_x +
                      self.fix_x * Decimal(0.15))
        self.axes.set_xlim([x_min, x_max])

        # Set y-axes
        y_min = round(self.min_top_elev - self.z -
                      self.height_row * Decimal(1.5))
        y_max = round(self.max_top_elev + self.height_row * Decimal(1.5))
        self.axes.set_ylim([y_min, y_max])

    def set_parameters(self, arc_id, node_id):
        """ Get and calculate parameters and values for drawing """

        self.list_of_selected_arcs = arc_id
        self.list_of_selected_nodes = node_id

        self.gis_length = [0]
        self.start_point = [0]
        self.arc_id = []

        # Get arcs between nodes (on shortest path)
        self.n = len(self.list_of_selected_nodes)

        # Get length (gis_length) of arcs and save them in separate list ( self.gis_length )
        for arc_id in self.list_of_selected_arcs:
            # Get gis_length from v_edit_arc
            sql = "SELECT gis_length"
            sql += " FROM " + self.schema_name + ".v_edit_arc"
            sql += " WHERE arc_id = '" + str(arc_id) + "'"
            row = self.controller.get_row(sql)
            if row:
                self.gis_length.append(row[0])

        # Calculate start_point (coordinates) of drawing for each node
        n = len(self.gis_length)
        for i in range(1, n):
            x = self.start_point[i - 1] + self.gis_length[i]
            self.start_point.append(x)
            i = i + 1

    def fill_memory(self):
        """ Get parameters from data base. Fill self.memory with parameters postgres """

        self.memory = []

        i = 0
        # Get parameters and fill the memory
        for node_id in self.node_id:
            # self.parameters : list of parameters for one node
            # self.parameters [start_point, top_elev, y_max,z1, z2, cat_geom1, geom1, slope, elev1, elev2,y1 ,y2, node_id, elev]
            parameters = [
                self.start_point[i], None, None, None, None, None, None, None,
                None, None, None, None, None, None
            ]
            # Get data top_elev ,y_max, elev, nodecat_id from v_edit_node
            # change elev to sys_elev
            sql = "SELECT top_elev, ymax, sys_elev, nodecat_id"
            sql += " FROM  " + self.schema_name + ".v_edit_node"
            sql += " WHERE node_id = '" + str(node_id) + "'"
            row = self.controller.get_row(sql)
            if row:
                parameters[1] = row[0]
                parameters[2] = row[1]
                parameters[13] = row[2]
                nodecat_id = row[3]

            # Get data z1, z2 ,cat_geom1 ,elev1 ,elev2 , y1 ,y2 ,slope from v_edit_arc
            # Change to elevmax1 and elevmax2
            sql = "SELECT z1, z2, cat_geom1, sys_elev1, sys_elev2, y1, y2, slope"
            sql += " FROM " + self.schema_name + ".v_edit_arc"
            sql += " WHERE node_1 = '" + str(
                node_id) + "' OR node_2 = '" + str(node_id) + "'"
            row = self.controller.get_row(sql)
            if row:
                parameters[3] = row[0]
                parameters[4] = row[1]
                parameters[5] = row[2]
                parameters[8] = row[3]
                parameters[9] = row[4]
                parameters[10] = row[5]
                parameters[11] = row[6]
                parameters[7] = row[7]

            # Geom1 from cat_node
            sql = "SELECT geom1"
            sql += " FROM " + self.schema_name + ".cat_node"
            sql += " WHERE id = '" + str(nodecat_id) + "'"
            row = self.controller.get_row(sql)
            if row:
                parameters[6] = row[0]

            # Set node_id in memory
            parameters[12] = node_id

            # Check if we have all data for drawing
            if None in parameters:
                message = "Some parameters are missing for node:"
                self.controller.show_info_box(message, "Info", node_id)
                parameters = []
                return

            self.memory.append(parameters)
            i = i + 1

    def draw_first_node(self, start_point, top_elev, ymax, z1, z2, cat_geom1,
                        geom1, indx):  #@UnusedVariable
        """ Draw first node """

        # Draw first node
        x = [0, -(geom1), -(geom1), (geom1), (geom1)]
        y = [
            top_elev, top_elev, top_elev - ymax, top_elev - ymax,
            top_elev - ymax + z1
        ]

        x1 = [geom1, geom1, 0]
        y1 = [top_elev - ymax + z1 + cat_geom1, top_elev, top_elev]
        plt.plot(x, y, 'black', zorder=100)
        plt.plot(x1, y1, 'black', zorder=100)
        plt.show()

        self.first_top_x = 0
        self.first_top_y = top_elev

        # Draw fixed part of table
        self.draw_fix_table(start_point)

    def draw_fix_table(self, start_point):
        """ Draw fixed part of table """

        # DRAW TABLE - FIXED PART
        # Draw fixed part of table
        self.draw_marks(0)

        # Vertical line [-1,0]
        x = [
            start_point - self.fix_x * Decimal(0.2),
            start_point - self.fix_x * Decimal(0.2)
        ]
        y = [
            self.min_top_elev - 1 * self.height_row,
            self.min_top_elev - 6 * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)

        # Vertical line [-2,0]
        x = [
            start_point - self.fix_x * Decimal(0.75),
            start_point - self.fix_x * Decimal(0.75)
        ]
        y = [
            self.min_top_elev - 2 * self.height_row,
            self.min_top_elev - 5 * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)

        # Vertical line [-3,0]
        x = [start_point - self.fix_x, start_point - self.fix_x]
        y = [
            self.min_top_elev - 1 * self.height_row,
            self.min_top_elev - 6 * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)

        # Fill the fixed part of table with data - draw text
        # Called just with first node
        self.data_fix_table(start_point)

    def draw_marks(self, start_point):
        """ Draw marks for each node """

        # Vertical line [0,0]
        x = [start_point, start_point]
        y = [
            self.min_top_elev - 1 * self.height_row, self.min_top_elev -
            2 * self.height_row - Decimal(0.1) * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)

        # Vertical lines [0,0] - marks
        x = [start_point, start_point]
        y = [
            self.min_top_elev - Decimal(2.9) * self.height_row,
            self.min_top_elev - Decimal(3.1) * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)

        x = [start_point, start_point]
        y = [
            self.min_top_elev - Decimal(3.9) * self.height_row,
            self.min_top_elev - Decimal(4.1) * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)

        x = [start_point, start_point]
        y = [
            self.min_top_elev - Decimal(4.9) * self.height_row,
            self.min_top_elev - Decimal(5.1) * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)

        x = [start_point, start_point]
        y = [
            self.min_top_elev - Decimal(5.9) * self.height_row,
            self.min_top_elev - Decimal(6.1) * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)

    def data_fix_table(self, start_point):  #@UnusedVariable
        """ FILL THE FIXED PART OF TABLE WITH DATA - DRAW TEXT """

        c = (self.fix_x - self.fix_x * Decimal(0.2)) / 2
        plt.text(-(c + self.fix_x * Decimal(0.2)),
                 self.min_top_elev - 1 * self.height_row -
                 Decimal(0.45) * self.height_row,
                 'DIAMETER',
                 fontsize=7.5,
                 horizontalalignment='center')

        plt.text(-(c + self.fix_x * Decimal(0.2)),
                 self.min_top_elev - 1 * self.height_row -
                 Decimal(0.80) * self.height_row,
                 'SLP. / LEN.',
                 fontsize=7.5,
                 horizontalalignment='center')

        c = (self.fix_x * Decimal(0.25)) / 2
        plt.text(-(c + self.fix_x * Decimal(0.74)),
                 self.min_top_elev - Decimal(2) * self.height_row -
                 self.height_row * 3 / 2,
                 'ORDINATES',
                 fontsize=7.5,
                 rotation='vertical',
                 horizontalalignment='center',
                 verticalalignment='center')

        plt.text(-self.fix_x * Decimal(0.70),
                 self.min_top_elev - Decimal(2.05) * self.height_row -
                 self.height_row / 2,
                 'TOP ELEV',
                 fontsize=7.5,
                 verticalalignment='center')
        plt.text(-self.fix_x * Decimal(0.70),
                 self.min_top_elev - Decimal(3.05) * self.height_row -
                 self.height_row / 2,
                 'Y MAX',
                 fontsize=7.5,
                 verticalalignment='center')
        plt.text(-self.fix_x * Decimal(0.70),
                 self.min_top_elev - Decimal(4.05) * self.height_row -
                 self.height_row / 2,
                 'ELEV',
                 fontsize=7.5,
                 verticalalignment='center')

        c = (self.fix_x - self.fix_x * Decimal(0.2)) / 2
        plt.text(-(c + self.fix_x * Decimal(0.2)),
                 self.min_top_elev -
                 Decimal(self.height_row * 5 + self.height_row / 2),
                 'NODE ID',
                 fontsize=7.5,
                 horizontalalignment='center',
                 verticalalignment='center')

        # Fill table with values
        self.fill_data(0, 0)

    def draw_nodes(self, start_point, top_elev, ymax, z1, z2, cat_geom1, geom1,
                   indx, z22, cat2):  #@UnusedVariable
        """ Draw nodes between first and last node """

        ytop1 = ymax - z1 - cat_geom1
        # cat_geom_1 from node before
        ytop2 = ymax - z22 - cat2

        x = [start_point, start_point - (geom1), start_point - (geom1)]
        y = [top_elev, top_elev, top_elev - ymax + z22 + cat2]
        x1 = [
            start_point - (geom1), start_point - (geom1),
            start_point + (geom1), start_point + (geom1)
        ]
        y1 = [
            top_elev - ymax + z22, top_elev - ymax, top_elev - ymax,
            top_elev - ymax + z1
        ]
        x2 = [start_point + (geom1), start_point + (geom1), start_point]
        y2 = [top_elev - ytop1, top_elev, top_elev]

        plt.plot(x, y, 'black', zorder=100)
        plt.plot(x1, y1, 'black', zorder=100)
        plt.plot(x2, y2, 'black', zorder=100)
        plt.show()

        # index -1 for node before
        self.x = self.memory[indx - 1][6] + self.memory[indx - 1][0]
        self.y = self.memory[indx - 1][1] - self.memory[
            indx - 1][2] + self.memory[indx - 1][3] + self.memory[indx - 1][5]
        self.x1 = self.memory[indx - 1][6] + self.memory[indx - 1][0]
        self.y1 = self.y1 = self.memory[indx - 1][1] - self.memory[
            indx - 1][2] + self.memory[indx - 1][3]
        self.x2 = (start_point - (geom1))
        self.y2 = top_elev - ytop2
        self.x3 = (start_point - (geom1))
        self.y3 = top_elev - ymax + z22

        self.node_top_x = start_point
        self.node_top_y = top_elev

        self.first_top_x = self.memory[indx - 1][0]
        self.first_top_y = self.memory[indx - 1][1]

        # DRAW TABLE-MARKS
        self.draw_marks(start_point)

        # Fill table
        self.fill_data(start_point, indx)

    def fill_data(self, start_point, indx):

        # Fill top_elevation and node_id for all nodes
        # Fill top_elevation
        plt.annotate(' ' + '\n' + str(round(self.memory[indx][1], 2)) + '\n' +
                     ' ',
                     xy=(Decimal(start_point), self.min_top_elev -
                         Decimal(self.height_row * 2 + self.height_row / 2)),
                     fontsize=7.5,
                     rotation='vertical',
                     horizontalalignment='center',
                     verticalalignment='center')

        # Draw node_id
        plt.text(0 + start_point,
                 self.min_top_elev -
                 Decimal(self.height_row * 5 + self.height_row / 2),
                 self.memory[indx][12],
                 fontsize=7.5,
                 horizontalalignment='center',
                 verticalalignment='center')

        # Fill y_max and alevation
        # 1st node : y_max,y2 and top_elev, elev2
        if indx == 0:
            # Fill y_max
            plt.annotate(
                ' ' + '\n' + str(round(self.memory[0][2], 2)) + '\n' +
                str(round(self.memory[0][10], 2)),
                xy=(Decimal(0 + start_point), self.min_top_elev -
                    Decimal(self.height_row * 3 + self.height_row / 2)),
                fontsize=7.5,
                rotation='vertical',
                horizontalalignment='center',
                verticalalignment='center')

            # Fill elevation
            plt.annotate(
                ' ' + '\n' + str(round(self.memory[0][13], 2)) + '\n' +
                str(round(self.memory[0][8], 2)),
                xy=(Decimal(0 + start_point), self.min_top_elev -
                    Decimal(self.height_row * 4 + self.height_row / 2)),
                fontsize=7.5,
                rotation='vertical',
                horizontalalignment='center',
                verticalalignment='center')

        # Last node : y_max,y1 and top_elev, elev1
        elif (indx == self.n - 1):
            # Fill y_max
            plt.annotate(
                str(round(self.memory[indx - 1][11], 2)) + '\n' +
                str(round(self.memory[indx][2], 2)) + '\n' + ' ',
                xy=(Decimal(0 + start_point), self.min_top_elev -
                    Decimal(self.height_row * 3 + self.height_row / 2)),
                fontsize=7.5,
                rotation='vertical',
                horizontalalignment='center',
                verticalalignment='center')

            # Fill elevation
            plt.annotate(
                str(round(self.memory[indx - 1][9], 2)) + '\n' +
                str(round(self.memory[indx][13], 2)) + '\n' + ' ',
                xy=(Decimal(0 + start_point), self.min_top_elev -
                    Decimal(self.height_row * 4 + self.height_row / 2)),
                fontsize=7.5,
                rotation='vertical',
                horizontalalignment='center',
                verticalalignment='center')
        # Nodes between 1st and last node : y_max,y1,y2 and top_elev, elev1, elev2
        else:
            # Fill y_max
            plt.annotate(
                str(round(self.memory[indx - 1][11], 2)) + '\n' +
                str(round(self.memory[indx][2], 2)) + '\n' +
                str(round(self.memory[indx][10], 2)),
                xy=(Decimal(0 + start_point), self.min_top_elev -
                    Decimal(self.height_row * 3 + self.height_row / 2)),
                fontsize=7.5,
                rotation='vertical',
                horizontalalignment='center',
                verticalalignment='center')

            # Fill elevation
            plt.annotate(
                str(round(self.memory[indx - 1][9], 2)) + '\n' +
                str(round(self.memory[indx][13], 2)) + '\n' +
                str(round(self.memory[indx][8], 2)),
                xy=(Decimal(0 + start_point), self.min_top_elev -
                    Decimal(self.height_row * 4 + self.height_row / 2)),
                fontsize=7.5,
                rotation='vertical',
                horizontalalignment='center',
                verticalalignment='center')

        # Fill diameter and slope / length for all nodes except last node
        if (indx != self.n - 1):
            # Draw diameter
            center = self.gis_length[indx + 1] / 2
            plt.text(center + start_point,
                     self.min_top_elev - 1 * self.height_row -
                     Decimal(0.45) * self.height_row,
                     round(self.memory[indx][5], 2),
                     fontsize=7.5,
                     horizontalalignment='center'
                     )  # PUT IN THE MIDDLE PARAMETRIZATION
            # Draw slope / length
            slope = str(round((self.memory[indx][7] * 100), 2))
            length = str(round(self.gis_length[indx + 1], 2))

            plt.text(center + start_point,
                     self.min_top_elev - 1 * self.height_row -
                     Decimal(0.8) * self.height_row,
                     slope + '%/' + length,
                     fontsize=7.5,
                     horizontalalignment='center'
                     )  # PUT IN THE MIDDLE PARAMETRIZATION

    def draw_last_node(self, start_point, top_elev, ymax, z1, z2, cat_geom1,
                       geom1, indx, z22, cat2):  #@UnusedVariable

        x = [start_point, start_point - (geom1), start_point - (geom1)]
        y = [top_elev, top_elev, top_elev - ymax + z22 + cat2]
        x1 = [
            start_point - geom1, start_point - geom1, start_point + geom1,
            start_point + geom1, start_point
        ]
        y1 = [
            top_elev - ymax + z2, top_elev - ymax, top_elev - ymax, top_elev,
            top_elev
        ]

        plt.plot(x, y, 'black', zorder=100)
        plt.plot(x1, y1, 'black', zorder=100)
        plt.show()

        self.x = self.memory[indx - 1][6] + self.memory[indx - 1][0]
        self.y = self.memory[indx - 1][1] - self.memory[
            indx - 1][2] + self.memory[indx - 1][3] + self.memory[indx - 1][5]
        self.x1 = self.memory[indx - 1][6] + self.memory[indx - 1][0]
        self.y1 = self.y1 = self.memory[indx - 1][1] - self.memory[
            indx - 1][2] + self.memory[indx - 1][3]

        ytop2 = ymax - z22 - cat2
        self.x2 = (start_point - (geom1))
        self.y2 = top_elev - ytop2
        self.x3 = (start_point - (geom1))
        self.y3 = top_elev - ymax + z22

        self.first_top_x = self.memory[indx - 1][0]
        self.first_top_y = self.memory[indx - 1][1]

        self.node_top_x = start_point
        self.node_top_y = top_elev

        # DRAW TABLE
        # DRAW TABLE-MARKS
        self.draw_marks(start_point)
        # Fill table
        self.fill_data(start_point, indx)

    def set_table_parameters(self):

        # Search y coordinate min_top_elev ( top_elev- ymax)
        self.min_top_elev = self.memory[0][1] - self.memory[0][2]
        for i in range(1, self.n):
            if (self.memory[i][1] - self.memory[i][2]) < self.min_top_elev:
                self.min_top_elev = self.memory[i][1] - self.memory[i][2]
        # Search y coordinate max_top_elev
        self.max_top_elev = self.memory[0][1]
        for i in range(1, self.n):
            if (self.memory[i][1]) > self.max_top_elev:
                self.max_top_elev = self.memory[i][1]

        # Calculating dimensions of x-fixed part of table
        self.fix_x = Decimal(0.1 / (1 - 0.1)) * self.memory[self.n - 1][0]

        # Calculating dimensions of y-fixed part of table
        # Height y = height of table + height of graph
        self.z = self.max_top_elev - self.min_top_elev
        self.height_row = (self.z * Decimal(0.97)) / Decimal(5)

        # Height of graph + table
        self.height_y = self.z * 2

    def draw_table_horizontals(self):

        self.set_table_parameters()

        # DRAWING TABLE
        # Nacrtat horizontale
        x = [self.memory[self.n - 1][0], self.memory[0][0] - self.fix_x]
        y = [
            self.min_top_elev - self.height_row,
            self.min_top_elev - self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)

        x = [self.memory[self.n - 1][0], self.memory[0][0] - self.fix_x]
        y = [
            self.min_top_elev - 2 * self.height_row,
            self.min_top_elev - 2 * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)

        # horizontale krace
        x = [
            self.memory[self.n - 1][0],
            self.memory[0][0] - self.fix_x * Decimal(0.75)
        ]
        y = [
            self.min_top_elev - 3 * self.height_row,
            self.min_top_elev - 3 * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)
        x = [
            self.memory[self.n - 1][0],
            self.memory[0][0] - self.fix_x * Decimal(0.75)
        ]
        y = [
            self.min_top_elev - 4 * self.height_row,
            self.min_top_elev - 4 * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)
        # zadnje dvije linije
        x = [self.memory[self.n - 1][0], self.memory[0][0] - self.fix_x]
        y = [
            self.min_top_elev - 5 * self.height_row,
            self.min_top_elev - 5 * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)
        x = [self.memory[self.n - 1][0], self.memory[0][0] - self.fix_x]
        y = [
            self.min_top_elev - 6 * self.height_row,
            self.min_top_elev - 6 * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)

    def on_resize(self, event):
        """ TODO """
        pass
        # Clear the entire current figure
        #plt.clf()
        #self.paint_event()
        #plt.rcParams['xtick.labelsize'] = 2
        #plt.rcParams.update({'font-size':22})
        #plt.draw()
        #res.remove()

    def check_colision(self, gis_length, pix):
        """ TODO: Checking colision just for text """

        axes = plt.gca()
        [x, y] = axes.transData.transform([(0, 1), (1, 0)])

        # available_length in pixels
        available_length = 2500

        # gis_lenght in pixels, x[0]-pixels by unit
        gis_length_pix = Decimal(gis_length) * Decimal(x[0])

        # if colision return 1
        if gis_length_pix > available_length:
            return 1
        #if no colision return 0
        else:
            return 0

    def draw_coordinates(self):

        start_point = self.memory[self.n - 1][0]
        geom1 = self.memory[self.n - 1][6]
        # Draw coocrinates
        x = [0, 0]
        y = [
            self.min_top_elev - 1 * self.height_row,
            self.max_top_elev + 1 * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)
        x = [start_point, start_point]
        y = [
            self.min_top_elev - 1 * self.height_row,
            self.max_top_elev + 1 * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)
        x = [0, start_point]
        y = [
            self.max_top_elev + 1 * self.height_row,
            self.max_top_elev + 1 * self.height_row
        ]
        plt.plot(x, y, 'black', zorder=100)

        # Values left y_ordinate_max
        plt.text(0 - geom1 * Decimal(1.5),
                 self.max_top_elev + self.height_row,
                 str(round(self.max_top_elev + self.height_row, 2)),
                 fontsize=7.5,
                 horizontalalignment='right',
                 verticalalignment='center')

        # Loop till self.max_top_elev + height_row
        y = int(math.ceil(self.min_top_elev - 1 * self.height_row))
        x = int(math.floor(self.max_top_elev))
        if x % 2 == 0:
            x = x + 2
        else:
            x = x + 1

        for i in range(y, x):
            if i % 2 == 0:
                x1 = [0, start_point]
                y1 = [i, i]
            else:
                i = i + 1
                x1 = [0, start_point]
                y1 = [i, i]
            plt.plot(x1, y1, 'lightgray', zorder=1)
            # Values left y_ordinate_all
            plt.text(0 - geom1 * Decimal(1.5),
                     i,
                     str(i),
                     fontsize=7.5,
                     horizontalalignment='right',
                     verticalalignment='center')

    def draw_grid(self):

        # Values right y_ordinate_max
        start_point = self.memory[self.n - 1][0]
        geom1 = self.memory[self.n - 1][6]
        plt.annotate('P.C. ' +
                     str(round(self.min_top_elev - 1 * self.height_row, 2)) +
                     '\n' + ' ',
                     xy=(0 - geom1 * Decimal(1.5),
                         self.min_top_elev - 1 * self.height_row),
                     fontsize=7.5,
                     horizontalalignment='right',
                     verticalalignment='center')

        # Values right x_ordinate_min
        plt.annotate('0' + '\n' + ' ',
                     xy=(0, self.max_top_elev + 1 * self.height_row),
                     fontsize=7.5,
                     horizontalalignment='center')

        # Values right x_ordinate_max
        plt.annotate(str(round(start_point, 2)) + '\n' + ' ',
                     xy=(start_point, self.max_top_elev + 1 * self.height_row),
                     fontsize=7.5,
                     horizontalalignment='center')

        # Loop from 0 to start_point(of last node)
        x = int(math.floor(start_point))
        # First after 0 (first is drawn ,start from i(0)+1)
        for i in range(50, x, 50):
            x1 = [i, i]
            y1 = [
                self.min_top_elev - 1 * self.height_row,
                self.max_top_elev + 1 * self.height_row
            ]
            plt.plot(x1, y1, 'lightgray', zorder=1)
            # values left y_ordinate_all
            plt.text(0 - geom1 * Decimal(1.5),
                     i,
                     str(i),
                     fontsize=7.5,
                     horizontalalignment='right',
                     verticalalignment='center')
            plt.text(start_point + geom1 * Decimal(1.5),
                     i,
                     str(i),
                     fontsize=7.5,
                     horizontalalignment='left',
                     verticalalignment='center')
            # values right x_ordinate_all
            plt.annotate(str(i) + '\n' + ' ',
                         xy=(i, self.max_top_elev + 1 * self.height_row),
                         fontsize=7.5,
                         horizontalalignment='center')

    def draw_arc(self):

        x = [self.x, self.x2]
        y = [self.y, self.y2]
        x1 = [self.x1, self.x3]
        y1 = [self.y1, self.y3]
        plt.plot(x, y, 'black', zorder=100)
        plt.plot(x1, y1, 'black', zorder=100)

    def draw_ground(self):

        # Green triangle
        plt.plot(self.first_top_x, self.first_top_y, 'g^', linewidth=3.5)
        plt.plot(self.node_top_x, self.node_top_y, 'g^', linewidth=3.5)
        x = [self.first_top_x, self.node_top_x]
        y = [self.first_top_y, self.node_top_y]
        plt.plot(x, y, 'green', linestyle='dashed')

    def shortest_path(self, start_point, end_point):
        """ Calculating shortest path using dijkstra algorithm """

        args = []
        start_point_id = start_point
        end_point_id = end_point

        args.append(start_point_id)
        args.append(end_point_id)

        self.rnode_id = []
        self.rarc_id = []

        rstart_point = None
        sql = "SELECT rid"
        sql += " FROM " + self.schema_name + ".v_anl_pgrouting_node"
        sql += " WHERE node_id = '" + start_point + "'"
        row = self.controller.get_row(sql)
        if row:
            rstart_point = int(row[0])

        rend_point = None
        sql = "SELECT rid"
        sql += " FROM " + self.schema_name + ".v_anl_pgrouting_node"
        sql += " WHERE node_id = '" + end_point + "'"
        row = self.controller.get_row(sql)
        if row:
            rend_point = int(row[0])

        # Check starting and end points
        if rstart_point is None or rend_point is None:
            message = "Start point or end point not found"
            self.controller.show_warning(message)
            return

        # Clear list of arcs and nodes - preparing for new profile
        sql = "SELECT * FROM public.pgr_dijkstra('SELECT id::integer, source, target, cost"
        sql += " FROM " + self.schema_name + ".v_anl_pgrouting_arc', " + str(
            rstart_point) + ", " + str(rend_point) + ", false"
        if self.version == '2':
            sql += ", false"
        elif self.version == '3':
            pass
        else:
            message = "You need to upgrade your version of pg_routing!"
            self.controller.show_info(message)
            return
        sql += ")"

        rows = self.controller.get_rows(sql)
        for i in range(0, len(rows)):
            if self.version == '2':
                self.rnode_id.append(str(rows[i][1]))
                self.rarc_id.append(str(rows[i][2]))
            elif self.version == '3':
                self.rnode_id.append(str(rows[i][2]))
                self.rarc_id.append(str(rows[i][3]))

        self.rarc_id.pop()
        self.arc_id = []
        self.node_id = []

        for n in range(0, len(self.rarc_id)):
            # convert arc_ids
            sql = "SELECT arc_id"
            sql += " FROM " + self.schema_name + ".v_anl_pgrouting_arc"
            sql += " WHERE id = '" + str(self.rarc_id[n]) + "'"
            row = self.controller.get_row(sql)
            if row:
                self.arc_id.append(str(row[0]))

        for m in range(0, len(self.rnode_id)):
            # convert node_ids
            sql = "SELECT node_id"
            sql += " FROM " + self.schema_name + ".v_anl_pgrouting_node"
            sql += " WHERE rid = '" + str(self.rnode_id[m]) + "'"
            row = self.controller.get_row(sql)
            if row:
                self.node_id.append(str(row[0]))

        # Select arcs of the shortest path
        if rows:
            # Build an expression to select them
            aux = "\"arc_id\" IN ("
            for i in range(len(self.arc_id)):
                aux += "'" + str(self.arc_id[i]) + "', "
            aux = aux[:-2] + ")"
            expr = QgsExpression(aux)
            if expr.hasParserError():
                message = "Expression Error: " + str(expr.parserErrorString())
                self.controller.show_warning(message)
                return

            # Loop which is pasing trough all layer of arc_group searching for feature
            for layer_arc in self.group_pointers_arc:
                it = layer_arc.getFeatures(QgsFeatureRequest(expr))

                # Build a list of feature id's from the previous result
                id_list = [i.id() for i in it]

                # Select features with these id's
                layer_arc.selectByIds(id_list)

        # Select nodes of shortest path
        aux = "\"node_id\" IN ("
        for i in range(len(self.node_id)):
            aux += "'" + str(self.node_id[i]) + "', "
        aux = aux[:-2] + ")"
        expr = QgsExpression(aux)
        if expr.hasParserError():
            message = "Expression Error: " + str(expr.parserErrorString())
            self.controller.show_warning(message)
            return

        # Loop which is pasing trough all layers of node_group searching for feature
        for layer_node in self.group_pointers_node:

            it = layer_node.getFeatures(QgsFeatureRequest(expr))

            # Build a list of feature id's from the previous result
            self.id_list = [i.id() for i in it]

            # Select features with these id's
            layer_node.selectByIds(self.id_list)

            if self.id_list != []:
                layer = layer_node
                center_widget = self.id_list[0]

        # Center profile (first node)
        canvas = self.iface.mapCanvas()
        layer.selectByIds([center_widget])
        canvas.zoomToSelected(layer)

        self.tbl_list_arc = self.dlg.findChild(QListWidget, "tbl_list_arc")
        list_arc = []

        # Clear list
        self.tbl_list_arc.clear()

        for i in range(len(self.arc_id)):
            item_arc = QListWidgetItem(self.arc_id[i])
            self.tbl_list_arc.addItem(item_arc)
            list_arc.append(self.arc_id[i])

        self.dlg.findChild(QPushButton, "btn_draw").clicked.connect(
            partial(self.paint_event, self.arc_id, self.node_id))
        self.dlg.findChild(QPushButton, "btn_clear_profile").clicked.connect(
            self.clear_profile)

    def clear_profile(self):

        # Clear list of nodes and arcs
        self.list_of_selected_nodes = []
        self.list_of_selected_arcs = []
        self.nodes = []
        self.arcs = []

        start_point = self.dlg.findChild(QLineEdit, "start_point")
        start_point.clear()
        end_point = self.dlg.findChild(QLineEdit, "end_point")
        end_point.clear()

        profile_id = self.dlg.findChild(QLineEdit, "profile_id")
        profile_id.clear()

        # Get data from DB for selected item| tbl_list_arc
        tbl_list_arc = self.dlg.findChild(QListWidget, "tbl_list_arc")
        tbl_list_arc.clear()

        # Clear selection
        can = self.iface.mapCanvas()
        for layer in can.layers():
            layer.removeSelection()
        can.refresh()

        self.deactivate()
Exemple #4
0
class MultipleSnapping(QgsMapTool):

    canvasClicked = pyqtSignal()

    def __init__(self, iface, controller, group):
        """ Class constructor """

        self.group_layers = group
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        # Call superclass constructor and set current action
        QgsMapTool.__init__(self, self.canvas)

        self.controller = controller
        self.rubber_band = QgsRubberBand(self.canvas, QGis.Polygon)
        mFillColor = QColor(254, 178, 76, 63)
        self.rubber_band.setColor(mFillColor)
        self.rubber_band.setWidth(1)
        self.reset()
        self.snapper = QgsMapCanvasSnapper(self.canvas)
        self.selected_features = []

        # Vertex marker
        self.vertex_marker = QgsVertexMarker(self.canvas)
        self.vertex_marker.setColor(QColor(255, 0, 255))
        self.vertex_marker.setIconSize(11)
        self.vertex_marker.setIconType(
            QgsVertexMarker.ICON_CROSS)  # or ICON_CROSS, ICON_X, ICON_BOX
        self.vertex_marker.setPenWidth(3)

    def reset(self):
        self.start_point = self.end_point = None
        self.is_emitting_point = False
        self.rubber_band.reset(QGis.Polygon)

    def canvasPressEvent(self, e):

        if e.button() == Qt.LeftButton:
            self.start_point = self.toMapCoordinates(e.pos())
            self.end_point = self.start_point
            self.is_emitting_point = True
            self.show_rect(self.start_point, self.end_point)

    def canvasReleaseEvent(self, e):

        self.is_emitting_point = False
        r = self.rectangle()

        # Use CTRL button to unselect features
        key = QApplication.keyboardModifiers()

        number_features = 0
        if e.button() == Qt.LeftButton:
            for layer in self.group_pointers:
                # Check number of selections
                #number_features = layer.selectedFeatureCount()
                if r is not None:
                    # Selection by rectange
                    lRect = self.canvas.mapSettings().mapToLayerCoordinates(
                        layer, r)
                    layer.select(lRect,
                                 True)  # True for leave previous selection
                    # if CTRL pressed : unselect features
                    if key == Qt.ControlModifier:
                        layer.selectByRect(lRect, layer.RemoveFromSelection)
                else:
                    # Selection one by one
                    x = e.pos().x()
                    y = e.pos().y()
                    eventPoint = QPoint(x, y)
                    (retval,
                     result) = self.snapper.snapToBackgroundLayers(eventPoint)
                    if result:
                        # Check feature
                        for snap_point in result:
                            # Get the point
                            #point = QgsPoint(snap_point.snappedVertex)
                            snapp_feat = next(
                                snap_point.layer.getFeatures(
                                    QgsFeatureRequest().setFilterFid(
                                        snap_point.snappedAtGeometry)))
                            # LEAVE SELECTION
                            snap_point.layer.select(
                                [snap_point.snappedAtGeometry])

            self.rubber_band.hide()

    def canvasMoveEvent(self, e):

        if not self.is_emitting_point:
            return
        self.end_point = self.toMapCoordinates(e.pos())
        self.show_rect(self.start_point, self.end_point)

    def show_rect(self, start_point, end_point):

        self.rubber_band.reset(QGis.Polygon)
        if start_point.x() == end_point.x() or start_point.y() == end_point.y(
        ):
            return
        point1 = QgsPoint(start_point.x(), start_point.y())
        point2 = QgsPoint(start_point.x(), end_point.y())
        point3 = QgsPoint(end_point.x(), end_point.y())
        point4 = QgsPoint(end_point.x(), start_point.y())

        self.rubber_band.addPoint(point1, False)
        self.rubber_band.addPoint(point2, False)
        self.rubber_band.addPoint(point3, False)
        self.rubber_band.addPoint(point4, True)  # true to update canvas
        self.rubber_band.show()

    def rectangle(self):

        if self.start_point is None or self.end_point is None:
            return None
        elif self.start_point.x() == self.end_point.x() or self.start_point.y(
        ) == self.end_point.y():
            return None

        return QgsRectangle(self.start_point, self.end_point)

    def deactivate(self):
        self.rubber_band.hide()
        QgsMapTool.deactivate(self)

    def activate(self):

        self.group_layers = ["Wjoin", "Fountain", "Greentap", "Tap"]
        self.group_pointers = []
        for layer_name in self.group_layers:
            layer = QgsMapLayerRegistry.instance().mapLayersByName(layer_name)
            if layer:
                layer = layer[0]
                self.group_pointers.append(layer)

        # Set active layer
        self.layer_connec = None
        self.layer_connec = QgsMapLayerRegistry.instance().mapLayersByName(
            "Edit connec")[0]
        self.iface.setActiveLayer(self.layer_connec)

        self.canvas.connect(self.canvas,
                            SIGNAL("xyCoordinates(const QgsPoint&)"),
                            self.mouse_move)

    def mouse_move(self, p):

        map_point = self.canvas.getCoordinateTransform().transform(p)
        x = map_point.x()
        y = map_point.y()
        event_point = QPoint(x, y)

        # Snapping
        (retval,
         result) = self.snapper.snapToCurrentLayer(event_point,
                                                   2)  # @UnusedVariable

        # That's the snapped point
        if result:
            # Check feature
            for snapPoint in result:
                #self.controller.log_info(str(snapPoint))
                if snapPoint.layer.name() == 'Edit connec':
                    point = QgsPoint(snapPoint.snappedVertex)
                    # Add marker
                    self.vertex_marker.setCenter(point)
                    self.vertex_marker.show()
        else:
            self.vertex_marker.hide()
Exemple #5
0
class Dimensions(ParentDialog):
    def __init__(self, dialog, layer, feature):
        """ Constructor class """
        super(Dimensions, self).__init__(dialog, layer, feature)
        self.init_config_form()
        if dialog.parent():
            dialog.parent().setFixedSize(320, 410)

    def init_config_form(self):
        ''' Custom form initial configuration '''

        # Set snapping
        self.canvas = self.iface.mapCanvas()
        self.emit_point = QgsMapToolEmitPoint(self.canvas)
        self.canvas.setMapTool(self.emit_point)
        self.snapper = QgsMapCanvasSnapper(self.canvas)

        # Vertex marker
        self.vertex_marker = QgsVertexMarker(self.canvas)
        self.vertex_marker.setColor(QColor(255, 0, 255))
        self.vertex_marker.setIconSize(11)
        self.vertex_marker.setIconType(
            QgsVertexMarker.ICON_CROSS)  # or ICON_CROSS, ICON_X, ICON_BOX
        self.vertex_marker.setPenWidth(3)

        btn_orientation = self.dialog.findChild(QPushButton, "btn_orientation")
        btn_orientation.clicked.connect(self.orientation)
        self.set_icon(btn_orientation, "133")
        btn_snapping = self.dialog.findChild(QPushButton, "btn_snapping")
        btn_snapping.clicked.connect(self.snapping)
        self.set_icon(btn_snapping, "129")

        # Set layers dimensions, node and connec
        self.layer_dimensions = self.controller.get_layer_by_tablename(
            "v_edit_dimensions")
        self.layer_node = self.controller.get_layer_by_tablename("v_edit_node")
        self.layer_connec = self.controller.get_layer_by_tablename(
            "v_edit_connec")

        self.create_map_tips()

    def orientation(self):

        # Disconnect previous snapping
        QObject.disconnect(
            self.emit_point,
            SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"),
            self.click_button_snapping)
        self.emit_point.canvasClicked.connect(self.click_button_orientation)

    def snapping(self):

        # Disconnect previous snapping
        QObject.disconnect(
            self.emit_point,
            SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"),
            self.click_button_orientation)

        # Track mouse movement
        # Set active layer
        self.iface.setActiveLayer(self.layer_node)
        self.canvas.connect(self.canvas,
                            SIGNAL("xyCoordinates(const QgsPoint&)"),
                            self.mouse_move)

        # Snapping
        QObject.connect(
            self.emit_point,
            SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"),
            self.click_button_snapping)

    def mouse_move(self, p):

        map_point = self.canvas.getCoordinateTransform().transform(p)
        x = map_point.x()
        y = map_point.y()
        eventPoint = QPoint(x, y)

        # Snapping
        (retval,
         result) = self.snapper.snapToCurrentLayer(eventPoint,
                                                   2)  # @UnusedVariable

        # That's the snapped point
        if result:
            # Check feature
            for snapPoint in result:
                # TODO: connec layers
                if snapPoint.layer == self.layer_node:
                    point = QgsPoint(snapPoint.snappedVertex)
                    # Add marker
                    self.vertex_marker.setCenter(point)
                    self.vertex_marker.show()
        else:
            self.vertex_marker.hide()

    def click_button_orientation(self, point):  #@UnusedVariable

        if not self.layer_dimensions:
            return

        self.x_symbol = self.dialog.findChild(QLineEdit, "x_symbol")
        self.x_symbol.setText(str(point.x()))
        self.y_symbol = self.dialog.findChild(QLineEdit, "y_symbol")
        self.y_symbol.setText(str(point.y()))

    def click_button_snapping(self, point, btn):  #@UnusedVariable

        # Disconnect mouse movement
        self.vertex_marker.hide()
        self.canvas.disconnect(self.canvas,
                               SIGNAL("xyCoordinates(const QgsPoint&)"),
                               self.mouse_move)

        if not self.layer_dimensions:
            return

        layer = self.layer_dimensions
        self.iface.setActiveLayer(layer)
        layer.startEditing()

        # TODO:
        node_group = [
            "Junction", "Valve", "Reduction", "Tank", "Meter", "Manhole",
            "Source", "Hydrant", "Wtp", "Netsamplepoint", "Netelement",
            "Flexunion", "Expantank", "Netwjoin", "Register", "Pump",
            "Waterwell", "Filter"
        ]

        snapper = QgsMapCanvasSnapper(self.canvas)
        map_point = self.canvas.getCoordinateTransform().transform(point)
        x = map_point.x()
        y = map_point.y()
        event_point = QPoint(x, y)

        # Snapping
        (retval, result) = snapper.snapToBackgroundLayers(
            event_point)  # @UnusedVariable

        # That's the snapped point
        if result <> []:

            # Check feature
            for snap_point in result:

                element_type = snap_point.layer.name()
                if element_type in node_group:
                    feat_type = 'node'
                else:
                    continue

                # Get the point
                point = QgsPoint(snap_point.snappedVertex)
                snapp_feature = next(
                    snap_point.layer.getFeatures(
                        QgsFeatureRequest().setFilterFid(
                            snap_point.snappedAtGeometry)))
                element_id = snapp_feature.attribute(feat_type + '_id')

                # Leave selection
                snap_point.layer.select([snap_point.snappedAtGeometry])

                # Get depth of the feature
                if self.project_type == 'ws':
                    fieldname = "depth"
                elif self.project_type == 'ud' and feat_type == 'node':
                    fieldname = "ymax"
                elif self.project_type == 'ud' and feat_type == 'connec':
                    fieldname = "connec_depth"

                sql = "SELECT " + fieldname
                sql += " FROM " + self.schema_name + "." + feat_type
                sql += " WHERE " + feat_type + "_id = '" + element_id + "'"
                row = self.controller.get_row(sql)
                if not row:
                    return

                utils_giswater.setText("depth", row[0])
                utils_giswater.setText("feature_id", element_id)
                utils_giswater.setText("feature_type", element_type)

    def create_map_tips(self):
        ''' Create MapTips on the map '''

        self.timer_map_tips = QTimer(self.canvas)
        self.map_tip_node = QgsMapTip()
        self.map_tip_connec = QgsMapTip()
        self.canvas.connect(self.canvas,
                            SIGNAL("xyCoordinates(const QgsPoint&)"),
                            self.map_tip_changed)
        self.canvas.connect(self.timer_map_tips, SIGNAL("timeout()"),
                            self.show_map_tip)

        self.timer_map_tips_clear = QTimer(self.canvas)
        self.canvas.connect(self.timer_map_tips_clear, SIGNAL("timeout()"),
                            self.clear_map_tip)

    def map_tip_changed(self, p):
        """ SLOT. Initialize the Timer to show MapTips on the map """

        if self.canvas.underMouse():
            self.last_map_position = QgsPoint(p.x(), p.y())
            self.map_tip_node.clear(self.canvas)
            self.map_tip_connec.clear(self.canvas)
            self.timer_map_tips.start(100)

    def show_map_tip(self):
        """ SLOT. Show MapTips on the map """

        self.timer_map_tips.stop()
        if self.canvas.underMouse():
            point_qgs = self.last_map_position
            point_qt = self.canvas.mouseLastXY()
            if self.layer_node:
                self.map_tip_node.showMapTip(self.layer_node, point_qgs,
                                             point_qt, self.canvas)
            if self.layer_connec:
                self.map_tip_connec.showMapTip(self.layer_connec, point_qgs,
                                               point_qt, self.canvas)
            self.timer_map_tips_clear.start(1000)

    def clear_map_tip(self):
        """ SLOT. Clear MapTips """

        self.timer_map_tips_clear.stop()
        self.map_tip_node.clear(self.canvas)
        self.map_tip_connec.clear(self.canvas)

    def reject_dialog(self):
        """ Reject dialog without saving """
        self.set_action_identify()
        try:
            self.timer_map_tips.timeout.disconnect()
            self.canvas.xyCoordinates.disconnect()
        except Exception:
            pass

    def save(self):
        """ Save feature """
        # Call parent method and 'reject_dialog'
        ParentDialog.save(self)
        self.reject_dialog()
Exemple #6
0
class ManNodeDialog(ParentDialog):
    def __init__(self, dialog, layer, feature):
        """ Constructor class """

        self.layer = layer
        self.feature = feature
        self.geom_type = "node"
        self.field_id = "node_id"
        self.id = utils_giswater.getWidgetText(dialog, self.field_id, False)
        super(ManNodeDialog, self).__init__(dialog, layer, feature)
        self.init_config_form()
        self.dlg_is_destroyed = False
        #self.controller.manage_translation('ud_man_node', dialog)
        if dialog.parent():
            dialog.parent().setFixedSize(625, 660)

    def init_config_form(self):
        """ Custom form initial configuration """
        # Get last point clicked on canvas
        last_click = self.canvas.mouseLastXY()
        self.last_point = QgsMapToPixel.toMapCoordinates(
            self.canvas.getCoordinateTransform(), last_click.x(),
            last_click.y())

        # Define class variables
        self.filter = self.field_id + " = '" + str(self.id) + "'"
        emit_point = QgsMapToolEmitPoint(self.canvas)

        # Get user permisions
        role_basic = self.controller.check_role_user("role_basic")

        # Get widget controls
        self.tab_main = self.dialog.findChild(QTabWidget, "tab_main")
        self.tbl_element = self.dialog.findChild(QTableView, "tbl_element")
        self.tbl_document = self.dialog.findChild(QTableView, "tbl_document")
        self.tbl_event_element = self.dialog.findChild(QTableView,
                                                       "tbl_event_element")
        self.tbl_event = self.dialog.findChild(QTableView, "tbl_event_node")
        self.tbl_scada = self.dialog.findChild(QTableView, "tbl_scada")
        self.tbl_scada_value = self.dialog.findChild(QTableView,
                                                     "tbl_scada_value")
        self.tbl_costs = self.dialog.findChild(QTableView, "tbl_masterplan")
        self.nodecat_id = self.dialog.findChild(QLineEdit, 'nodecat_id')
        state_type = self.dialog.findChild(QComboBox, 'state_type')
        dma_id = self.dialog.findChild(QComboBox, 'dma_id')

        # Tables
        self.tbl_upstream = self.dialog.findChild(QTableView, "tbl_upstream")
        self.tbl_upstream.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tbl_downstream = self.dialog.findChild(QTableView,
                                                    "tbl_downstream")
        self.tbl_downstream.setSelectionBehavior(QAbstractItemView.SelectRows)

        self.dialog.findChild(QPushButton, "btn_catalog").clicked.connect(
            partial(self.catalog, self.dialog, 'ud', 'node'))

        # New Workcat
        # self.dialog.findChild(QPushButton, "btn_new_workcat").clicked.connect(partial(self.cf_new_workcat, self.dialog))

        self.tbl_upstream.doubleClicked.connect(
            partial(self.open_up_down_stream, self.tbl_upstream))
        self.tbl_downstream.doubleClicked.connect(
            partial(self.open_up_down_stream, self.tbl_downstream))

        feature = self.feature
        layer = self.iface.activeLayer()

        action_copypaste = self.dialog.findChild(QAction, "actionCopyPaste")
        layer.editingStarted.connect(
            partial(self.enabled_actions, action_copypaste, True))
        layer.editingStopped.connect(
            partial(self.enabled_actions, action_copypaste, False))
        action_rotation = self.dialog.findChild(QAction, "actionRotation")
        layer.editingStarted.connect(
            partial(self.enabled_actions, action_rotation, True))
        layer.editingStopped.connect(
            partial(self.enabled_actions, action_rotation, False))
        action_interpolate = self.dialog.findChild(QAction,
                                                   "actionInterpolate")
        layer.editingStarted.connect(
            partial(self.enabled_actions, action_interpolate, True))
        layer.editingStopped.connect(
            partial(self.enabled_actions, action_interpolate, False))
        self.dialog.destroyed.connect(partial(self.dlg_destroyed, layer=layer))
        # Toolbar actions
        action = self.dialog.findChild(QAction, "actionEnabled")
        self.dialog.findChild(QAction,
                              "actionCopyPaste").setEnabled(layer.isEditable())
        self.dialog.findChild(QAction,
                              "actionRotation").setEnabled(layer.isEditable())
        self.dialog.findChild(QAction, "actionInterpolate").setEnabled(
            layer.isEditable())
        self.dialog.findChild(QAction, "actionZoom").triggered.connect(
            partial(self.action_zoom_in, self.feature, self.canvas,
                    self.layer))
        self.dialog.findChild(QAction, "actionCentered").triggered.connect(
            partial(self.action_centered, self.feature, self.canvas,
                    self.layer))
        if not role_basic:
            action.setChecked(layer.isEditable())
            layer.editingStarted.connect(
                partial(self.check_actions, action, True))
            layer.editingStopped.connect(
                partial(self.check_actions, action, False))
            self.dialog.findChild(QAction, "actionEnabled").triggered.connect(
                partial(self.action_enabled, action, self.layer))
        else:
            action.setEnabled(False)
        self.dialog.findChild(QAction, "actionZoomOut").triggered.connect(
            partial(self.action_zoom_out, self.feature, self.canvas,
                    self.layer))
        self.dialog.findChild(QAction, "actionRotation").triggered.connect(
            self.action_rotation)
        self.dialog.findChild(QAction, "actionCopyPaste").triggered.connect(
            partial(self.action_copy_paste, self.geom_type))
        self.dialog.findChild(QAction, "actionLink").triggered.connect(
            partial(self.check_link, self.dialog, True))
        self.dialog.findChild(QAction, "actionHelp").triggered.connect(
            partial(self.action_help, 'ud', 'node'))
        self.dialog.findChild(QAction, "actionInterpolate").triggered.connect(
            partial(self.activate_snapping, emit_point))

        widget_ymax = self.dialog.findChild(QLineEdit, 'ymax')
        if widget_ymax is not None:
            widget_ymax.textChanged.connect(
                partial(self.compare_depth, widget_ymax, False))
            widget_ymax.lostFocus.connect(
                partial(self.compare_depth, widget_ymax, True))

        # Manage tab 'Scada'
        self.manage_tab_scada()

        # Check if exist URL from field 'link' in main tab
        self.check_link(self.dialog)

        # Check topology for new features
        continue_insert = True
        node_over_node = True
        check_topology_node = self.controller.plugin_settings_value(
            "check_topology_node", "0")
        check_topology_arc = self.controller.plugin_settings_value(
            "check_topology_arc", "0")

        # Check if feature has geometry object
        geometry = self.feature.geometry()
        if geometry:

            if self.id.upper() == 'NULL' and check_topology_node == "0":
                self.get_topology_parameters()
                (continue_insert, node_over_node) = self.check_topology_node()

            if continue_insert and not node_over_node:
                if self.id.upper() == 'NULL' and check_topology_arc == "0":
                    self.check_topology_arc()

            # Create thread
            thread1 = Thread(self, self.controller, 3)
            thread1.start()

        self.filter = "node_id = '" + str(self.id) + "'"
        table_name = self.controller.schema_name + ".v_ui_node_x_connection_upstream"
        self.fill_table(self.tbl_upstream, table_name, self.filter)
        self.set_configuration(self.tbl_upstream,
                               "v_ui_node_x_connection_upstream")

        table_name = self.controller.schema_name + ".v_ui_node_x_connection_downstream"
        self.fill_table(self.tbl_downstream, table_name, self.filter)
        self.set_configuration(self.tbl_downstream,
                               "v_ui_node_x_connection_downstream")

        # Manage tab signal
        self.tab_connections_loaded = False
        self.tab_element_loaded = False
        self.tab_document_loaded = False
        self.tab_om_loaded = False
        self.tab_scada_loaded = False
        self.tab_cost_loaded = False
        self.tab_custom_fields_loaded = False
        self.tab_main.currentChanged.connect(self.tab_activation)

        # Load default settings
        widget_id = self.dialog.findChild(QLineEdit, 'node_id')
        if utils_giswater.getWidgetText(self.dialog,
                                        widget_id).lower() == 'null':
            self.load_default(self.dialog, "node")
            self.load_type_default(self.dialog, "nodecat_id",
                                   "nodecat_vdefault")

        self.load_state_type(self.dialog, state_type, self.geom_type)
        self.load_dma(self.dialog, dma_id, self.geom_type)

    def compare_depth(self, widget_ymax, show_message):
        widget_ymax.setStyleSheet("border: 1px solid gray")
        node_id = utils_giswater.getWidgetText(self.dialog, 'node_id')
        ymax = utils_giswater.getWidgetText(self.dialog, widget_ymax)
        if ymax is None:
            return
        bad_alert = False
        sql = ("SELECT * from " + self.schema_name +
               ".v_ui_node_x_connection_upstream "
               " WHERE node_id = '" + str(node_id) + "'")
        rows = self.controller.get_rows(sql, log_sql=False)
        arcs_list = ""
        if len(rows) > 0:
            arcs_list += "Upstream: "
            for row in rows:
                if row['upstream_depth'] is not None:
                    if float(ymax) < float(row['upstream_depth']):
                        widget_ymax.setStyleSheet("border: 1px solid red")
                        arcs_list += str((row['feature_id'] + ", "))
                        bad_alert = True
        sql = ("SELECT * from " + self.schema_name +
               ".v_ui_node_x_connection_downstream "
               " WHERE node_id = '" + str(node_id) + "'")
        rows = self.controller.get_rows(sql, log_sql=False)
        if len(rows) > 0:
            arcs_list += "Downstream: "
            for row in rows:
                if row['downstream_depth'] is not None:
                    if float(ymax) < float(row['downstream_depth']):
                        widget_ymax.setStyleSheet("border: 1px solid red")
                        arcs_list += str((row['feature_id'] + ", "))
                        bad_alert = True
        if len(arcs_list) > 2:
            arcs_list = arcs_list[:-2]

        if show_message and bad_alert:
            msg = "The depth of this node is less than the arc/'s {}".format(
                arcs_list)
            # self.controller.show_info_box(text=msg, title="Info")
            msg_box = QMessageBox()
            msg_box.setIcon(3)
            msg_box.setWindowTitle("Warning")
            msg_box.setText(msg)
            msg_box.exec_()

    def activate_snapping(self, emit_point):
        # Set circle vertex marker
        color = QColor(255, 100, 255)
        self.vertex_marker = QgsVertexMarker(self.canvas)
        self.vertex_marker.setIconType(QgsVertexMarker.ICON_CIRCLE)
        self.vertex_marker.setColor(color)
        self.vertex_marker.setIconSize(15)
        self.vertex_marker.setPenWidth(3)

        self.node1 = None
        self.node2 = None
        self.canvas.setMapTool(emit_point)
        self.snapper = QgsMapCanvasSnapper(self.canvas)
        self.layer_node = self.controller.get_layer_by_tablename("v_edit_node")
        self.iface.setActiveLayer(self.layer_node)
        self.canvas.connect(self.canvas,
                            SIGNAL("xyCoordinates(const QgsPoint&)"),
                            self.mouse_move)
        emit_point.canvasClicked.connect(partial(self.snapping_node))

    def snapping_node(self, point, button):
        """ Get id of selected nodes (node1 and node2) """
        if button == 2:
            self.dlg_destroyed()
            return
        map_point = self.canvas.getCoordinateTransform().transform(point)
        x = map_point.x()
        y = map_point.y()
        event_point = QPoint(x, y)

        # Snapping
        (retval, result) = self.snapper.snapToBackgroundLayers(
            event_point)  # @UnusedVariable

        # That's the snapped point
        if result:
            # Check feature
            for snapped_point in result:
                if snapped_point.layer == self.layer_node:
                    # Get the point
                    snapp_feature = next(
                        snapped_point.layer.getFeatures(
                            QgsFeatureRequest().setFilterFid(
                                snapped_point.snappedAtGeometry)))
                    element_id = snapp_feature.attribute('node_id')

                    message = "Selected node"
                    if self.node1 is None:
                        self.node1 = str(element_id)
                        self.controller.show_message(message,
                                                     message_level=0,
                                                     duration=1,
                                                     parameter=self.node1)
                    elif self.node1 != str(element_id):
                        self.node2 = str(element_id)
                        self.controller.show_message(message,
                                                     message_level=0,
                                                     duration=1,
                                                     parameter=self.node2)

        if self.node1 is not None and self.node2 is not None:
            self.iface.actionPan().trigger()
            self.iface.setActiveLayer(self.layer)
            self.iface.mapCanvas().scene().removeItem(self.vertex_marker)
            sql = ("SELECT " + self.schema_name + ".gw_fct_node_interpolate('"
                   "" + str(self.last_point[0]) + "', '" +
                   str(self.last_point[1]) + "', '"
                   "" + str(self.node1) + "', '" + self.node2 + "')")
            row = self.controller.get_row(sql)
            if row:
                if 'elev' in row[0]:
                    utils_giswater.setWidgetText(self.dialog, 'elev',
                                                 row[0]['elev'])
                if 'top_elev' in row[0]:
                    utils_giswater.setWidgetText(self.dialog, 'top_elev',
                                                 row[0]['top_elev'])

    def mouse_move(self, p):
        map_point = self.canvas.getCoordinateTransform().transform(p)
        x = map_point.x()
        y = map_point.y()
        eventPoint = QPoint(x, y)

        # Snapping
        (retval,
         result) = self.snapper.snapToCurrentLayer(eventPoint,
                                                   2)  # @UnusedVariable

        # That's the snapped features
        if result:
            for snapped_point in result:
                if snapped_point.layer == self.layer_node:
                    point = QgsPoint(snapped_point.snappedVertex)
                    # Add marker
                    self.vertex_marker.setCenter(point)
                    self.vertex_marker.show()
        else:
            self.vertex_marker.hide()

    def open_up_down_stream(self, qtable):
        """ Open selected node from @qtable """

        selected_list = qtable.selectionModel().selectedRows()
        if len(selected_list) == 0:
            message = "Any record selected"
            self.controller.show_warning(message)
            return

        row = selected_list[0].row()
        feature_id = qtable.model().record(row).value("feature_id")
        featurecat_id = qtable.model().record(row).value("featurecat_id")

        # Get sys_feature_cat.id from cat_feature.id
        sql = ("SELECT sys_feature_cat.id FROM " +
               self.controller.schema_name + ".cat_feature"
               " INNER JOIN " + self.controller.schema_name +
               ".sys_feature_cat ON cat_feature.system_id = sys_feature_cat.id"
               " WHERE cat_feature.id = '" + featurecat_id + "'")
        row = self.controller.get_row(sql)
        if not row:
            return

        layer = self.get_layer(row[0])
        if layer:
            field_id = self.controller.get_layer_primary_key(layer)
            aux = "\"" + field_id + "\" = "
            aux += "'" + str(feature_id) + "'"
            expr = QgsExpression(aux)
            if expr.hasParserError():
                message = "Expression Error"
                self.controller.show_warning(
                    message, parameter=expr.parserErrorString())
                return

            it = layer.getFeatures(QgsFeatureRequest(expr))
            features = [i for i in it]
            if features != []:
                self.iface.openFeatureForm(layer, features[0])
        else:
            message = "Layer not found"
            self.controller.show_warning(message, parameter=row[0])

    def get_topology_parameters(self):
        """ Get parameters 'node_proximity' and 'node2arc' from config table """

        self.node_proximity = 0.1
        self.node2arc = 0.01
        sql = "SELECT node_proximity, node2arc FROM " + self.schema_name + ".config"
        row = self.controller.get_row(sql)
        if row:
            self.node_proximity = row['node_proximity']

    def check_topology_arc(self):
        """ Check topology: Inserted node is over an existing arc? """

        # Initialize plugin parameters
        self.controller.plugin_settings_set_value("check_topology_arc", "0")
        self.controller.plugin_settings_set_value("close_dlg", "0")

        # Get selected srid and coordinates. Set SQL to check topology
        srid = self.controller.plugin_settings_value('srid')
        point = self.feature.geometry().asPoint()
        node_geom = "ST_SetSRID(ST_Point(" + str(point.x()) + ", " + str(
            point.y()) + "), " + str(srid) + ")"

        sql = ("SELECT arc_id, state FROM " + self.schema_name + ".v_edit_arc"
               " WHERE ST_DWithin(" + node_geom + ", v_edit_arc.the_geom, " +
               str(self.node2arc) + ")"
               " ORDER BY ST_Distance(v_edit_arc.the_geom, " + node_geom + ")"
               " LIMIT 1")
        row = self.controller.get_row(sql)
        if row:
            sql = (
                "SELECT value FROM " + self.schema_name + ".config_param_user"
                " WHERE parameter = 'edit_arc_division_dsbl' AND cur_user = current_user"
            )
            row2 = self.controller.get_row(sql)
            if row2 and str(row2[0].lower()) == 'true':
                self.controller.plugin_settings_set_value(
                    "check_topology_arc", "1")
            else:
                msg = (
                    "We have detected you are trying to divide an arc with state "
                    + str(row['state']) + ""
                    "\nIt will destroy it. Would you like to continue?")
                answer = self.controller.ask_question(
                    msg, "Divide intersected arc?")
                if answer:
                    self.controller.plugin_settings_set_value(
                        "check_topology_arc", "1")
                else:
                    self.controller.plugin_settings_set_value("close_dlg", "1")

    def check_topology_node(self):
        """ Check topology: Inserted node is over an existing node? """

        node_over_node = False
        continue_insert = True

        # Initialize plugin parameters
        self.controller.plugin_settings_set_value("check_topology_node", "0")
        self.controller.plugin_settings_set_value("close_dlg", "0")

        # Get selected srid and coordinates. Set SQL to check topology
        srid = self.controller.plugin_settings_value('srid')
        point = self.feature.geometry().asPoint()
        node_geom = "ST_SetSRID(ST_Point(" + str(point.x()) + ", " + str(
            point.y()) + "), " + str(srid) + ")"

        sql = ("SELECT node_id, state FROM " + self.schema_name +
               ".v_edit_node"
               " WHERE ST_Intersects(ST_Buffer(" + node_geom + ", " +
               str(self.node_proximity) + "), the_geom)"
               " ORDER BY ST_Distance(" + node_geom + ", the_geom)"
               " LIMIT 1")
        row = self.controller.get_row(sql)
        if row:
            node_over_node = True
            msg = (
                "We have detected you are trying to insert one node over another node with state "
                + str(row['state']) + ""
                "\nRemember that:"
                "\n\nIn case of old or new node has state 0, you are allowed to insert new one, because state 0 has not topology rules."
                "\nIn the rest of cases, remember that the state topology rules of Giswater only enables one node with the same state at the same position."
                "\n\nWould you like to continue?")
            answer = self.controller.ask_question(msg,
                                                  "Insert node over node?")
            if answer:
                self.controller.plugin_settings_set_value(
                    "check_topology_node", "1")
            else:
                self.controller.plugin_settings_set_value("close_dlg", "1")
                continue_insert = False

        return continue_insert, node_over_node

    def action_rotation(self):

        # Set map tool emit point and signals
        self.emit_point = QgsMapToolEmitPoint(self.canvas)
        self.canvas.setMapTool(self.emit_point)
        self.snapper = QgsMapCanvasSnapper(self.canvas)
        self.canvas.xyCoordinates.connect(self.action_rotation_mouse_move)
        self.emit_point.canvasClicked.connect(
            self.action_rotation_canvas_clicked)

        # Store user snapping configuration
        self.snapper_manager = SnappingConfigManager(self.iface)
        self.snapper_manager.store_snapping_options()

        # Clear snapping
        self.snapper_manager.clear_snapping()

        # Set snapping
        layer = self.controller.get_layer_by_tablename("v_edit_arc")
        self.snapper_manager.snap_to_layer(layer)
        layer = self.controller.get_layer_by_tablename("v_edit_connec")
        self.snapper_manager.snap_to_layer(layer)
        layer = self.controller.get_layer_by_tablename("v_edit_node")
        self.snapper_manager.snap_to_layer(layer)

        # Set marker
        color = QColor(255, 100, 255)
        self.vertex_marker = QgsVertexMarker(self.canvas)
        self.vertex_marker.setIconType(QgsVertexMarker.ICON_CROSS)
        self.vertex_marker.setColor(color)
        self.vertex_marker.setIconSize(15)
        self.vertex_marker.setPenWidth(3)

    def action_rotation_mouse_move(self, point):
        """ Slot function when mouse is moved in the canvas. 
            Add marker if any feature is snapped 
        """

        # Hide marker and get coordinates
        self.vertex_marker.hide()
        map_point = self.canvas.getCoordinateTransform().transform(point)
        x = map_point.x()
        y = map_point.y()
        event_point = QPoint(x, y)

        # Snapping
        (retval, result) = self.snapper.snapToBackgroundLayers(
            event_point)  # @UnusedVariable

        if not result:
            return

        # Check snapped features
        for snapped_point in result:
            point = QgsPoint(snapped_point.snappedVertex)
            self.vertex_marker.setCenter(point)
            self.vertex_marker.show()
            break

    def action_rotation_canvas_clicked(self, point, btn):

        if btn == Qt.RightButton:
            self.disable_rotation()
            return

        viewname = self.controller.get_layer_source_table_name(self.layer)
        sql = ("SELECT ST_X(the_geom), ST_Y(the_geom)"
               " FROM " + self.schema_name + "." + viewname + ""
               " WHERE node_id = '" + self.id + "'")
        row = self.controller.get_row(sql)
        if row:
            existing_point_x = row[0]
            existing_point_y = row[1]

        sql = ("UPDATE " + self.schema_name + ".node"
               " SET hemisphere = (SELECT degrees(ST_Azimuth(ST_Point(" +
               str(existing_point_x) + ", " + str(existing_point_y) + "), "
               " ST_Point(" + str(point.x()) + ", " + str(point.y()) + "))))"
               " WHERE node_id = '" + str(self.id) + "'")
        status = self.controller.execute_sql(sql)
        if not status:
            self.disable_rotation()
            return

        sql = ("SELECT degrees(ST_Azimuth(ST_Point(" + str(existing_point_x) +
               ", " + str(existing_point_y) + "),"
               " ST_Point( " + str(point.x()) + ", " + str(point.y()) + ")))")
        row = self.controller.get_row(sql)
        if row:
            utils_giswater.setWidgetText(self.dialog, "hemisphere",
                                         str(row[0]))
            message = "Hemisphere of the node has been updated. Value is"
            self.controller.show_info(message, parameter=str(row[0]))

        self.disable_rotation()

    def disable_rotation(self):
        """ Disable actionRotation and set action 'Identify' """

        action_widget = self.dialog.findChild(QAction, "actionRotation")
        if action_widget:
            action_widget.setChecked(False)

        try:
            self.snapper_manager.recover_snapping_options()
            self.vertex_marker.hide()
            self.set_action_identify()
            self.canvas.xyCoordinates.disconnect()
            self.emit_point.canvasClicked.disconnect()
        except:
            pass

    def tab_activation(self):
        """ Call functions depend on tab selection """

        # Get index of selected tab
        index_tab = self.tab_main.currentIndex()

        # Tab 'Custom fields'
        if index_tab == 1 and not self.tab_custom_fields_loaded:
            self.tab_custom_fields_loaded = self.fill_tab_custom_fields()

        # Tab 'Connections'
        if index_tab == (
                2 - self.tabs_removed) and not self.tab_connections_loaded:
            self.fill_tab_connections()
            self.tab_connections_loaded = True

        # Tab 'Element'
        elif index_tab == (3 -
                           self.tabs_removed) and not self.tab_element_loaded:
            self.fill_tab_element()
            self.tab_element_loaded = True

        # Tab 'Document'
        elif index_tab == (4 -
                           self.tabs_removed) and not self.tab_document_loaded:
            self.fill_tab_document()
            self.tab_document_loaded = True

        # Tab 'O&M'
        elif index_tab == (5 - self.tabs_removed) and not self.tab_om_loaded:
            self.fill_tab_om()
            self.tab_om_loaded = True

        # Tab 'Scada'
        elif index_tab == (6 - self.tabs_removed - self.tab_scada_removed
                           ) and not self.tab_scada_loaded:
            self.fill_tab_scada()
            self.tab_scada_loaded = True

        # Tab 'Cost'
        elif index_tab == (7 - self.tabs_removed - self.tab_scada_removed
                           ) and not self.tab_cost_loaded:
            self.fill_tab_cost()
            self.tab_cost_loaded = True

    def fill_tab_connections(self):
        """ Fill tab 'Connections' """

        self.fill_tables(self.tbl_upstream, "v_ui_node_x_connection_upstream")
        self.fill_tables(self.tbl_downstream,
                         "v_ui_node_x_connection_downstream")

    def fill_tab_element(self):
        """ Fill tab 'Element' """

        table_element = "v_ui_element_x_node"
        self.fill_tbl_element_man(self.dialog, self.tbl_element, table_element,
                                  self.filter)
        self.set_configuration(self.tbl_element, table_element)

    def fill_tab_document(self):
        """ Fill tab 'Document' """

        table_document = "v_ui_doc_x_node"
        self.fill_tbl_document_man(self.dialog, self.tbl_document,
                                   table_document, self.filter)
        self.set_configuration(self.tbl_document, table_document)

    def fill_tab_om(self):
        """ Fill tab 'O&M' (event) """

        table_event_node = "v_ui_om_visit_x_node"
        self.fill_tbl_event(self.tbl_event,
                            self.schema_name + "." + table_event_node,
                            self.filter)
        self.tbl_event.doubleClicked.connect(self.open_visit_event)
        self.set_configuration(self.tbl_event, table_event_node)

    def fill_tab_scada(self):
        """ Fill tab 'Scada' """
        pass

    def fill_tab_cost(self):
        """ Fill tab 'Cost' """

        table_costs = "v_plan_node"
        self.fill_table(self.tbl_costs, self.schema_name + "." + table_costs,
                        self.filter)
        self.set_configuration(self.tbl_costs, table_costs)

    def fill_tab_custom_fields(self):
        """ Fill tab 'Custom fields' """

        node_type = self.dialog.findChild(QComboBox, "node_type")
        cat_feature_id = utils_giswater.getWidgetText(self.dialog, node_type)
        if cat_feature_id.lower() == "null":
            msg = "In order to manage custom fields, that field has to be set"
            self.controller.show_info(msg, parameter='node_type', duration=10)
            return False
        self.manage_custom_fields(cat_feature_id)
        return True