# -*- coding: utf-8 -*-
"""

/***************************************************************************
 GRMDialog
                                 A QGIS plugin
 GRM
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                             -------------------
        begin                : 2019-12-18
        git sha              : $Format:%H$
        copyright            : (C) 2019 by KICT/Hermesys
        email                : shpark@hermesys.co.kr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""

import os

from qgis.PyQt import QtGui, QtWidgets, uic
from qgis.PyQt import QtWidgets
from qgis.core import *
from qgis.gui import *
from PyQt5 import uic
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import *
from .css import *

from .XMLCheck import xmls
from .lib.Util import *
from .lib.Get_Set import *
from .lib.xmltodict import *
from .plugin.grid_layer import get_point_layer
from .plugin.flow_layer import get_flow_layer
import xml.etree.ElementTree as ET
from .AddFlowControl_dialog import AddFlowControl

#2020-05-12 박: dll 변경으로 바뀜 기존 .net framwork 에서 C++ DLL 로 변경
from .lib.GRM_DLL import *
from .lib.Raster import *
import shutil

_GSC=set_Controls()
_XmlCheck = xmls()
FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(__file__), 'GRM_dialog_base.ui'))
class GRMDialog(QtWidgets.QMainWindow, FORM_CLASS):
    closeDialogEvent = pyqtSignal()
    
    def __init__(self,_xmltodict={}, _WatchPointCount=0,_SubWatershedCount=0,_GreenAmptCount=0,_SoilDepthCount=0,_LandCoverCount=0,_FlowControlCount=0,_ChannelSettingsCount=0,parent=None):
        super(GRMDialog, self).__init__(parent)
        self.setupUi(self)
        self._StreamWSID=[]
        self._wsinfo=None
        self._Flowcontrolgrid_flag = False

        self._xmltodict=_xmltodict
        self._WatchPointCount= _WatchPointCount
        self._SubWatershedCount= _SubWatershedCount
        self._GreenAmptCount=_GreenAmptCount
        self._SoilDepthCount = _SoilDepthCount
        self._LandCoverCount = _LandCoverCount
        self._FlowControlCount = _FlowControlCount
        self._ChannelSettingsCount=_ChannelSettingsCount
        self._Flowcontrolgrid_flag = True
#         self.Apply_Flag=False #20220106 동 : watershed parameter 기능에서 필요 없는듯 하여 주석 처리
        self.canvasRubberBand = []
        
        #2019-12-20 박: 동희 개발 2줄 탭 
        self.qTabBar()
        self.firstTab.currentChanged.connect(lambda: self.connectionTabBar("first"))
        self.secondTab.currentChanged.connect(lambda: self.connectionTabBar("second"))

        #2020-01-20 박: 프로젝트 데이터 초기 셋팅
        self.Set_ProjectDataInit()

        #2020-01-09 박: 스타일 적용
        self.setStyleSheet(css_sheet)
        self.groupBox_2.setStyleSheet("QGroupBox{padding-top:15px;margin-top:-15px;}")
        self.groupBox_6.setStyleSheet("QGroupBox{padding-top:15px;margin-top:-15px;}")

        #2020-01-09 박:캔버스 툴 버튼 아이콘 셋팅
        self.Set_Canvas_Tool_Icon()


        #2020-01-20 박:캔버스에 레이어 올리기
        self.Set_Canvas_Layer_default()

        # 시뮬레이션 탭 기능 기본값 셋팅
        self.Set_simulation_tab_default()
        # default 설정이지만 프로그램 흐름상 나중에 처리 해야 하는 목록
        # Watchpoint 체크박스 선택 상태로 처리
        self.chkWatch_Point.setChecked(True)
        self.chkFlowContorGird.setChecked(True)

        self.watchpoint()

        self.click_FlowContorGird()

        # WatchPoint 탭 기능 기본값 셋팅
        # 프로젝트 파일을 읽고 테이블에 셋팅(watch point)
        self.Set_Wathpoint_tab_default()

        # Channel CS 탭 기능 기본값 셋팅
        self.Set_ChannelCS_tab_default()

        # Watershed 탭 기능 기본값 셋팅
        # 데이터 값들이 다 들어 오지 않았음 확인 해야 함
        self.Set_Watershed_Parameter_tab_default()

        # Flow Control 탭 기능 기본값 셋팅
        self.Set_FlowControl_tab_default()

        #2020-01-20 박: dockwidget 창 분리 비활성화
        self.dockDisableButton()
        
        _GSC.GlobalLabel(self.lblColRow)

        # Cell info Flow 텍스트 박스에 값 셋팅에 사용 하기 위해 유틸에 텍스트 박스 넘김
        _GSC.GlobalControl(self.txtCellCount,self.txtCelltype,self.txtStreamValue,self.txtFD,self.txtFA,self.txtSlope,self.txtWatershedID)

        # Cell info Land cover
        _GSC.GlobalControl_Landcover(self.txtLandGridValue, self.txtLandType, self.txtRoughness, self.txtratio)

        # Cell info Depth
        _GSC.GlobalControl_Depth(self.txtDepthValue,self.txtSoilDepthClass, self.txtSoilDepth)


        # Cell info Texture
        _GSC.GlobalControl_texture(self.txtTextureGridValue, self.txtSoilTexture, self.txtPorosity, self.txtEffectivePorosity, self.txtSuctionhead,self.txtcondcutivity)

        _GSC.set_GreenAmptCount(self._GreenAmptCount)
        _GSC.set_SoilDepthCount(self._SoilDepthCount)
        _GSC.set_LandCoverCount(self._LandCoverCount)
        _GSC.set_xmltodict(self._xmltodict)
        
        self.dataTimeFormat = self.chkStartingTime.isChecked()
        
        #2020-01-20 박: 캔버스 툴 셋팅
        self.Set_Cavas_tool_btn()
        
        self.btnStart_Simulation.clicked.connect(self.Click_StartSimulation)
        self.btnSaveproject.clicked.connect(lambda: self.SaveProject(True))
        self.btnViewResult.clicked.connect(self.Open_ViewResult)
        self.btnClose.clicked.connect(self.Close_Form)
    
    def Click_StartSimulation(self):
        #값 변경 테스트 용 WatershedFile 파일 경로를 바꿈
        GRMCore_exe = os.path.dirname(os.path.realpath(__file__)) + "\DLL\GRM.exe"
        self.SaveProject(False)
        
        option = "/a " if self.chkAutoROM.isChecked() else ""
        arg = f'"{GRMCore_exe}" {option}"{self.ProjectFile}"'
        
        result=Execute(arg)
        
        msg = "Simulation completed"
        if result!=1:
            msg = "Simulation was stopped."
            
        MsInfo(msg)

    def qTabBar(self):
        self.firstTab = QTabBar()
        self.secondTab = QTabBar()
        layout = QGridLayout()
        baseLayout = self.centralwidget.layout()
        
        self.firstTab.addTab("");        
        self.firstTab.addTab("Simulation");        
        self.firstTab.addTab("Watch points");        
        self.firstTab.addTab("Channel cross section");   

        self.secondTab.addTab("");        
        self.secondTab.addTab("Flow control");        
        self.secondTab.addTab("Watershed parameters");        
        self.secondTab.addTab("Cell Info.");                  
        
        self.firstTab.setExpanding(False) #창 넓이에 맞춰 늘어나지 않음
        self.secondTab.setExpanding(False)
        style = "QTabBar::tab:first{ max-width: 0px; } QTabBar::tab:first:selected{ border: 0px; }"
        self.firstTab.setStyleSheet(style)
        self.secondTab.setStyleSheet(style)
        self.firstTab.setDrawBase(False) # 탭 하단에 선을 표시하지 않음
        
        #layout 세팅
        #r, c, rspan, cspan
        layout.addWidget(self.firstTab, 0, 0, 1, 2)
        layout.addWidget(self.secondTab, 1, 0, 1, 2)
        layout.addWidget(self.stackedWidget, 2, 0, 1, 2)
        layout.setSpacing(0) 
        self.gridLayout_10.setSpacing(0)
        self.centralwidget.setLayout(layout)
        baseLayout.addLayout(layout, 0, 0, 2, 2)        
        baseLayout.addWidget(self.btnStart_Simulation, 2, 0)
        baseLayout.addWidget(self.btnSaveproject, 2, 1)
        baseLayout.addWidget(self.btnViewResult, 3, 0)
        baseLayout.addWidget(self.btnClose, 3, 1)
        baseLayout.addWidget(self.mapcanvas, 1, 2, 3, 2)

        self.firstTab.setCurrentIndex(1)
        
    def Set_ProjectDataInit(self):
        # 그리드 라인 에 사용될 변수
        ## 글로벌 변수로 지정 해서 사용 하면 화면을 닫았다가 다시 켜면 값이 남아 있어서 그리드 라인이 안그려짐
        self.grid_line = {}

        # direction 그리때 사용 변수
        ## 글로벌 변수로 지정 해서 사용 하면 화면을 닫았다가 다시 켜면 값이 남아 있어서 디렉션이 안그려짐
        self.flow_direction = {}

        # 프로젝트 파일 경로 변수 셋팅
        self.ProjectFile = self._xmltodict['GRMProject']['ProjectSettings']['ProjectFile']

        # watershed Layer file 경로 변수
        self.LayerPath = self._xmltodict['GRMProject']['ProjectSettings']['DomainFile']

        # simulation Tab 변수
        self.RainfallInterval = self._xmltodict['GRMProject']['ProjectSettings']['RainfallInterval']
        self.ComputationalTimeStep = self._xmltodict['GRMProject']['ProjectSettings']['ComputationalTimeStep']
        self.MaxDegreeOfParallelism= self._xmltodict['GRMProject']['ProjectSettings']['MaxDegreeOfParallelism']

        self.SimulationDuration = self._xmltodict['GRMProject']['ProjectSettings']['SimulationDuration']
        self.OutputTimeStep = self._xmltodict['GRMProject']['ProjectSettings']['OutputTimeStep']
        self.SimulateInfiltration = self._xmltodict['GRMProject']['ProjectSettings']['SimulateInfiltration']
        self.SimulateSubsurfaceFlow = self._xmltodict['GRMProject']['ProjectSettings']['SimulateSubsurfaceFlow']
        self.SimulateBaseFlow = self._xmltodict['GRMProject']['ProjectSettings']['SimulateBaseFlow']
        self.SimulateFlowControl = self._xmltodict['GRMProject']['ProjectSettings']['SimulateFlowControl']

        self.IsFixedTimeStep = self._xmltodict['GRMProject']['ProjectSettings']['IsFixedTimeStep']

        self.SimulStartingTime = self._xmltodict['GRMProject']['ProjectSettings']['SimulStartingTime']

        self.WatershedFile = self._xmltodict['GRMProject']['ProjectSettings']['DomainFile']
        self.SlopeFile = self._xmltodict['GRMProject']['ProjectSettings']['SlopeFile']
        self.FlowDirectionFile = self._xmltodict['GRMProject']['ProjectSettings']['FlowDirectionFile']
        self.FlowAccumFile = self._xmltodict['GRMProject']['ProjectSettings']['FlowAccumFile']
        self.StreamFile = self._xmltodict['GRMProject']['ProjectSettings']['StreamFile']
        self.ChannelWidthFile = self._xmltodict['GRMProject']['ProjectSettings']['ChannelWidthFile']
        self.LandCoverFile = self._xmltodict['GRMProject']['ProjectSettings']['LandCoverFile']
        self.SoilTextureFile = self._xmltodict['GRMProject']['ProjectSettings']['SoilTextureFile']

        self.SoilDepthFile = self._xmltodict['GRMProject']['ProjectSettings']['SoilDepthFile']
        self.InitialChannelFlowFile = self._xmltodict['GRMProject']['ProjectSettings']['InitialChannelFlowFile']
        self.InitialSoilSaturationRatioFile = self._xmltodict['GRMProject']['ProjectSettings'][
            'InitialSoilSaturationRatioFile']

        self.MakeIMGFile = self._xmltodict['GRMProject']['ProjectSettings']['MakeIMGFile']
        self.MakeASCFile = self._xmltodict['GRMProject']['ProjectSettings']['MakeASCFile']
        self.MakeSoilSaturationDistFile = self._xmltodict['GRMProject']['ProjectSettings']['MakeSoilSaturationDistFile']
        self.MakeRfDistFile = self._xmltodict['GRMProject']['ProjectSettings']['MakeRfDistFile']
        self.MakeRFaccDistFile = self._xmltodict['GRMProject']['ProjectSettings']['MakeRFaccDistFile']
        self.MakeFlowDistFile = self._xmltodict['GRMProject']['ProjectSettings']['MakeFlowDistFile']
        self.PrintOption = self._xmltodict['GRMProject']['ProjectSettings']['PrintOption']
        self.WriteLog = self._xmltodict['GRMProject']['ProjectSettings']['WriteLog']


        if self.InitialChannelFlowFile == None:
            self.InitialChannelFlowFile = ""
        if self.InitialSoilSaturationRatioFile == None:
            self.InitialSoilSaturationRatioFile = ""
        if self.ChannelWidthFile == None:
            self.ChannelWidthFile=""
        
        # Core DLL 연동 작업 선행 처리
        FDType = self._xmltodict['GRMProject']['ProjectSettings']['FlowDirectionType']

        #2020-05-12 박: 추가 된 기능  (dll에 정보 넘겨주고 값 받기)
        self._wsinfo = grmWSinfo(FDType,self.WatershedFile, self.SlopeFile, self.FlowDirectionFile, self.FlowAccumFile,
                                    self.StreamFile, self.LandCoverFile, self.SoilTextureFile, self.SoilDepthFile,
                                    self.InitialSoilSaturationRatioFile, self.InitialChannelFlowFile,self.ChannelWidthFile)
        _GSC.set_wsinfo(self._wsinfo)
        self.GridCellSize=self._wsinfo.cellSize

        # 임시 리스트를 만들어서 데이터를 받고 받은 데이터를 _StreamWSID 에 셋팅
        try:
            self._StreamWSID=[]
            WSIDs=[]
            WSIDs=self._wsinfo.mostDownStreamWSIDs
            for i in range(self._wsinfo.mostDownStreamWSCount):
                if WSIDs[i] is not None:
                    self._StreamWSID.append(str(WSIDs[i]))
        except Exception as e:
            MsInfo(e)

        #2020-05-13 박: 지금 함수가 확인이 안되서 임시로 주석 처리 
        self.Set_Wathpoint_default_value()

        # ChannelWidth tab 변수
        self.WSID=[]
        self.CrossSectionType=[] 
        self.SingleCSChannelWidthType=[]
        self.ChannelWidthEQc=[]
        self.ChannelWidthEQd=[]
        self.ChannelWidthEQe=[]
        self.ChannelWidthMostDownStream=[]
        self.LowerRegionHeight=[]
        self.LowerRegionBaseWidth=[]
        self.UpperRegionBaseWidth=[]
        self.CompoundCSChannelWidthLimit=[]
        self.BankSideSlopeRight=[]
        self.BankSideSlopeLeft=[]
        
        channelDic = {
            "CrossSectionType" : ["CSSingle", self.CrossSectionType], 
            "SingleCSChannelWidthType" : ["CWGeneration", self.SingleCSChannelWidthType], 
            "ChannelWidthEQc" : ["1.698", self.ChannelWidthEQc], 
            "ChannelWidthEQd" : ["0.318", self.ChannelWidthEQd],
            "ChannelWidthEQe" : ["0.5", self.ChannelWidthEQe],
            "ChannelWidthMostDownStream" : [str(self.GridCellSize), self.ChannelWidthMostDownStream],
            "LowerRegionHeight" : ["0", self.LowerRegionHeight],
            "LowerRegionBaseWidth" : ["0", self.LowerRegionBaseWidth],
            "UpperRegionBaseWidth" : ["0", self.UpperRegionBaseWidth],
            "CompoundCSChannelWidthLimit" : ["0", self.CompoundCSChannelWidthLimit],
            "BankSideSlopeRight" : ["1.5", self.BankSideSlopeRight],
            "BankSideSlopeLeft" : ["1.5", self.BankSideSlopeLeft]
        }
        
        if self._ChannelSettingsCount==0: 
            self.lisw_WSID.clear()
            #2020-05-25 박: New 프로젝트 시행시에 값을 받아 오는 부분이 없어서 추가 
            self._ChannelSettingsCount=len(self._StreamWSID)
            if self._ChannelSettingsCount>0:
                DictoXml = unparse(self._xmltodict)
                ET.register_namespace('', "http://tempuri.org/GRMProject.xsd")
                xmltree = ET.ElementTree(ET.fromstring(DictoXml))
                root = xmltree.getroot()
                for i in range(len(self._StreamWSID)):
                    child = ET.Element("ChannelSettings")
                    root.append(child)
                    
                    ChannelWSID = ET.Element("WSID")
                    ChannelWSID.text = str(self._StreamWSID[i])
                    child.append(ChannelWSID)

                    self.WSID.append(str(self._StreamWSID[i]))
                    item1 = QListWidgetItem(str(self._StreamWSID[i]))
                    self.lisw_WSID.addItem(item1)
                    
                    for k in channelDic.keys():
                        ele = ET.Element(k)
                        ele.text = channelDic[k][0]
                        child.append(ele)
                        channelDic[k][1].append(channelDic[k][0])
 
                xmltree_string = ET.tostring(xmltree.getroot())
                docs = dict(parse(xmltree_string))
                self._xmltodict.clear()
                self._xmltodict.update(docs)

        elif self._ChannelSettingsCount==1:
            self.lisw_WSID.clear()
            result =self._xmltodict['GRMProject']['ChannelSettings']['WSID']
            self.WSID.append(self._xmltodict['GRMProject']['ChannelSettings']['WSID'])
            item1 = QListWidgetItem(str(self.WSID[0]))
            self.lisw_WSID.addItem(item1)
            
            for k in channelDic:
                value = self._xmltodict['GRMProject']['ChannelSettings'][k]
                if k=="ChannelWidthMostDownStream" and not str(value).strip():
                    value = str(int(self.GridCellSize))
                channelDic[k][1].append(value)
            
            self._ChannelSettingsCount=1

        elif self._ChannelSettingsCount>1:
            self.lisw_WSID.clear()
            i=0
            for flowitem in self._xmltodict['GRMProject']['ChannelSettings']:
                self.WSID.append(str(flowitem['WSID']))
                item1 = QListWidgetItem(str(self.WSID[i]))
                self.lisw_WSID.addItem(item1)
                self.CrossSectionType.append(str(flowitem['CrossSectionType']))
                self.SingleCSChannelWidthType.append(str(flowitem['SingleCSChannelWidthType']))
                self.ChannelWidthEQc.append(str(flowitem['ChannelWidthEQc']))
                self.ChannelWidthEQd.append(str(flowitem['ChannelWidthEQd']))
                self.ChannelWidthEQe.append(str(flowitem['ChannelWidthEQe']))

                DSValue = str(flowitem['ChannelWidthMostDownStream'])
                if str(DSValue).strip():
                    self.ChannelWidthMostDownStream.append(DSValue)
                else: 
                    self.ChannelWidthMostDownStream.append(str(int(self.GridCellSize)))

                self.LowerRegionHeight.append(str(flowitem['LowerRegionHeight']))
                self.LowerRegionBaseWidth.append(str(flowitem['LowerRegionBaseWidth']))
                self.UpperRegionBaseWidth.append(str(flowitem['UpperRegionBaseWidth']))
                self.CompoundCSChannelWidthLimit.append(str(flowitem['CompoundCSChannelWidthLimit']))
                self.BankSideSlopeRight.append(str(flowitem['BankSideSlopeRight']))
                self.BankSideSlopeLeft.append(str(flowitem['BankSideSlopeLeft']))
                i=i+1
            self._ChannelSettingsCount=i
        
        self.flowEle = [
            'Name', 'ColX', 'RowY', 'DT', 'ControlType', 
            'FlowDataFile','IniStorage', 'MaxStorage','NormalHighStorage', 'RestrictedStorage',
            'RestrictedPeriod_Start','RestrictedPeriod_End', 'ROType', 'ROConstQ', 'ROConstQDuration'
        ]

    def SetMostDownStream(self,id):
        try:
            # 만약에 Cell size 값이 없으면 레이어에서 값을 받음
            if self.GridCellSize is None:
                self.GridCellSize = str(self._xsize) if self._xsize else "0"
            Allsize = self.GridCellSize 

            IniSaturation = "0.9"
            MinSlopeOF = "0.0001"
            MinSlopeChBed = "0.0001"
            intAll = float(Allsize)
#             if intAll > 0:
#                 MinChBaseWidth = intAll / 10
            MinChBaseWidth = intAll / 10 if intAll>0 else 0
            IniFlow = "0"
            ChRoughness = "0.045"
            DryStreamOrder = "0"
            CalCoefLCRoughness = "1"
            CalCoefSoilDepth = "1"
            CalCoefPorosity = "1"
            CalCoefWFSuctionHead = "1"
            CalCoefHydraulicK = "1"
            UnsturatedType =1
            CoefUnsatruatedk = "0.2"
            self._wsinfo.setOneSWSParsAndUpdateAllSWSUsingNetwork(int(id), 	                    #int wsid,
                                                                  float(IniSaturation), 	    #double iniSat,
                                                                  float(MinSlopeOF),	        #double minSlopeLandSurface,
                                                                  int(UnsturatedType),	        #int unSKType,
                                                                  float(CoefUnsatruatedk),	    #double coefUnsK,
                                                                  float(MinSlopeChBed),	        #double minSlopeChannel, 
                                                                  float(MinChBaseWidth),	    #double minChannelBaseWidth, 
                                                                  float(ChRoughness),	        #double roughnessChannel,
                                                                  int(DryStreamOrder), 	        #int dryStreamOrder, 
                                                                  float(CalCoefLCRoughness),	#double ccLCRoughness,
                                                                  float(CalCoefSoilDepth), 	    #double ccSoilDepth, 
                                                                  float(CalCoefPorosity), 	    #double ccPorosity, 
                                                                  float(CalCoefWFSuctionHead),	#double ccWFSuctionHead,
                                                                  float(CalCoefHydraulicK),	    #double ccSoilHydraulicCond, 
                                                                  0)	                        #double iniFlow = 0)
        except Exception as e:
            MsError(e)


    def dockDisableButton(self):
        dockList = self.stackedWidget.findChildren(QDockWidget)
        for dock in dockList:
            dock.setFeatures(QDockWidget.NoDockWidgetFeatures)


    def connectionTabBar(self, type):
        f = self.firstTab.currentIndex()
        s = self.secondTab.currentIndex()
        index = 0
        
        if type=="second" and s>0:
            self.firstTab.setCurrentIndex(0)
            self.secondTab.setCurrentIndex(s)
            index = s+(self.firstTab.count()-2)
        elif type=="first" and f>0:
            self.secondTab.setCurrentIndex(0)
            self.firstTab.setCurrentIndex(f)
            index = f-1
        
        self.stackedWidget.setCurrentIndex(index)

    # canvas 버튼 아이콘 이미지 설정
    def Set_Canvas_Tool_Icon(self):
        root=os.path.dirname(os.path.abspath(__file__))+"\image"
        ZoomExtent = root + "\ZoomExtent.png"
        Zoomin = root + "\ZoomIn.png"
        ZoomOut = root + "\ZoomOut.png"
        Pan = root + "\Pan.png"
        Zoomnext = root + "\Zoomnext.png"
        ZoomPrevious = root + "\ZoomPrevious.png"
        SelectGrid = root + "\SelectGrid.png"
        MoveTo = root + "\MoveTo.png"

        self.btnZoomExtent.setIcon(QtGui.QIcon(ZoomExtent))
        self.btnZoomExtent.setIconSize(QtCore.QSize(200, 200))

        self.btnZoomIn.setIcon(QtGui.QIcon(Zoomin))
        self.btnZoomOut.setIcon(QtGui.QIcon(ZoomOut))
        self.btnPan.setIcon(QtGui.QIcon(Pan))
        self.btnZoomnext.setIcon(QtGui.QIcon(Zoomnext))
        self.btnZoomprevious.setIcon(QtGui.QIcon(ZoomPrevious))
        self.btnSelectgrid.setIcon(QtGui.QIcon(SelectGrid))
        self.btnMoveto.setIcon(QtGui.QIcon(MoveTo))

    # 캔버스 툴 기능 연동
    def Set_Cavas_tool_btn(self):
        self.tool = CanvasTool(self.mapcanvas)

        # ZoomExtent
        self.btnZoomExtent.clicked.connect(self.tool.ZoomtoExtent)

        # Zoom Next
        self.btnZoomnext.clicked.connect(self.tool.ZoomtoNextExtent)

        # Zoom Previous
        self.btnZoomprevious.clicked.connect(self.tool.ZoomtoPrevious)

        # Zoom In
        self.btnZoomIn.clicked.connect(self.tool.canvas_zoomIn)

        # Zoom Out
        self.btnZoomOut.clicked.connect(self.tool.canvas_zoomOut)

        # Pan
        self.btnPan.clicked.connect(self.tool.canvas_pan)

        # Moveto
        self.btnMoveto.clicked.connect(self.aboutApp)

        # # Selectgrid
        self.btnSelectgrid.clicked.connect(self.identify)

        # Watch_Point 기본 설정은 체크
        self.chkWatch_Point.stateChanged.connect(self.watchpoint)

        # chkFC
        self.chkFlowContorGird.stateChanged.connect(self.click_FlowContorGird)

        # 체크 박스 눌렀을때 캔버스에 그리드 라인 추가 함수
        self.show_grid_line.clicked.connect(self.show_hide_grid_line)

        # 캔버스에 Flow direction
        self.show_flow_direction.clicked.connect(self.show_hide_flow_direction)

    # 캔버스에 레이어 올리기
    def Set_Canvas_Layer_default(self):
        # canvase 레이어 올리기
        if self.LayerPath is not None:
            convert_shape_path =self.LayerPath.upper().replace(".ASC","_temp_convert_file.SHP")
            flag_WSID_Shape=AscToShape(self.LayerPath,convert_shape_path)
            Wsid_shape_style_path_ori = os.path.dirname(os.path.realpath(__file__)) + "\DLL\Label_Style.qml"

#             self.layer = QgsRasterLayer(self.LayerPath, "FA", "gdal")
            self.layer = QgsRasterLayer(self.LayerPath, "WSFAlayerload", "gdal") 
            self.Wsid_label_shape = QgsVectorLayer(convert_shape_path, "WSID_label" )
            self.Wsid_label_shape.loadNamedStyle(Wsid_shape_style_path_ori)
            # 캔버스의 기본 정보를 Global에 대입 다른 클래스에서 사용
            _layer = self.layer
            self.Set_Global_CanvaseValue()

            """#2017.11..1 원 :
                문제1. 상기 ASC가 투영 좌표계 레이어인데. 경위도로 오인 지정되어 있었슴. 이는 PRJ 파일 만듧면 해결됨.
                문제2 .그리고 canvas 는 직접 setDestinationCrs 해야 좌표계가 지정됨. https://issues.qgis.org/issues/9772 """

            self.mapcanvas.setDestinationCrs(self.layer.crs())
            QgsProject.instance().addMapLayer(self.layer, False)
            self.mapcanvas.setExtent(self.layer.extent())
            self.mapcanvas.setLayers([self.layer,self.Wsid_label_shape])
    

    # 레이어 기본 값을 Global 로 지정해서 정의
    def Set_Global_CanvaseValue(self):
        self._width = self.layer.width()
        self._height = self.layer.height()
        self._xsize = self.layer.rasterUnitsPerPixelX()
        self._ysize = self.layer.rasterUnitsPerPixelY()
        self._extent = self.layer.extent()
        self._ymax = self._extent.yMaximum()
        self._ymin = self._extent.yMinimum()
        self._xmax = self._extent.xMaximum()
        self._xmin = self._extent.xMinimum()

     # def 연동 함수
    def Open_ViewResult(self):
        self.disCharge = self._xmltodict['GRMProject']['ProjectSettings']['ProjectFile']
        disCharge_path = os.path.splitext(os.path.basename(self.disCharge))[0]
        self.disCharge = self.disCharge.replace(disCharge_path+".gmp",disCharge_path+"Discharge.out")
        Opewn_ViewFile(self.disCharge)


 # ----------------- 2017-10-24_오전 박 simulation 탭 텍스트 박스 셋팅 -----------------------------
    def Set_simulation_tab_default(self):
        # 프린트 옵션 콤보 박스 셋팅
        combolist = ('All','DischargeFile','DischargeFileQ','AllQ')
        self.cmbPrint.addItems(combolist)
        index = self.cmbPrint.findText(self.PrintOption, QtCore.Qt.MatchFixedString)
        if index >= 0:
            self.cmbPrint.setCurrentIndex(index)

        self.cmbPrint.currentIndexChanged.connect(self.printcombo)
        self.spTimeStep_min_2.valueChanged.connect(self.SPvaluechange)

        self.chkParallel.stateChanged.connect(self.Check_Parallel)
        self.Check_Parallel()

        self.chkFlowControl.toggled.connect(self.Check_Flow)
        self.Check_Flow(False)

        self.chkmakeimage.setChecked(False)
        if self.MakeIMGFile.upper() == 'TRUE':
            self.chkmakeimage.setChecked(True)

        self.chkmakeASC.setChecked(False)
        if self.MakeASCFile.upper() == 'TRUE':
            self.chkmakeASC.setChecked(True)

        self.chksoiSaturation.setChecked(False)
        if self.MakeSoilSaturationDistFile.upper() == 'TRUE':
            self.chksoiSaturation.setChecked(True)

        self.chkrfDistFile.setChecked(False)
        if self.MakeRfDistFile.upper() == 'TRUE':
            self.chkrfDistFile.setChecked(True)

        self.chkrfaacDistfile.setChecked(False)
        if self.MakeRFaccDistFile.upper() == 'TRUE':
            self.chkrfaacDistfile.setChecked(True)

        self.chkdischarge.setChecked(False)
        if self.MakeFlowDistFile.upper() == 'TRUE':
            self.chkdischarge.setChecked(True)

        self.chklog.setChecked(False)
        if self.WriteLog.upper() == 'TRUE':
            self.chklog.setChecked(True)

        if self.SimulStartingTime =="0" :
            now = QtCore.QDateTime.currentDateTime()
            self.dateTimeEdit.setDateTime(now)
            self.chkStartingTime.setChecked(False)
            self.dateTimeEdit.setEnabled(False)
            self.dataTimeFormat = False
        else:
            self.chkStartingTime.setChecked(True)
            self.dateTimeEdit.setEnabled(True)
            dateTime = QDateTime.fromString(self.SimulStartingTime,"yyyy-MM-dd hh:mm")
            self.dateTimeEdit.setDateTime(dateTime)
            self.dataTimeFormat = True

        self.chkParallel.setChecked(False)
        if int(self.MaxDegreeOfParallelism)>0:
            self.chkParallel.setChecked(True)

        if self.ComputationalTimeStep is not None :
            intvalue = int(self.ComputationalTimeStep)
            self.spTimeStep_min.setValue(intvalue)
        else:
            if self._xsize<=200:
                value =3
            elif self._xsize>200:
                value = 5
            self.spTimeStep_min.setValue(value)


        if self.MaxDegreeOfParallelism is not None :
            intvalue = int(self.MaxDegreeOfParallelism)
            self.spTimeStep_min_2.setValue(intvalue)
     
        self.txtOutput_time_step.setText(str(self.RainfallInterval))
        if self.OutputTimeStep is not None and self.OutputTimeStep!="":
            self.txtOutput_time_step.setText(str(self.OutputTimeStep))

        self.txtSimulation_duration.setText("")
        if self.SimulationDuration is not None:
            self.txtSimulation_duration.setText(self.SimulationDuration)

        if self.OutputTimeStep is not None:
            self.txtOutput_time_step.setText(self.OutputTimeStep)

        # 체크 박스 셋팅 (프로젝트 파일에서 체크 값 받아서 셋팅)
        self.chkInfiltration.setChecked(True)
        if self.SimulateInfiltration and self.SimulateInfiltration.upper() != "TRUE":
            self.chkInfiltration.setChecked(False)

        self.chkSubsurfaceFlow.setChecked(True)
        if self.SimulateSubsurfaceFlow and self.SimulateSubsurfaceFlow.upper() != "TRUE":
            self.chkSubsurfaceFlow.setChecked(False)

        self.chkBaseFlow.setChecked(True)
        if self.SimulateBaseFlow and self.SimulateBaseFlow.upper() != "TRUE":
            self.chkBaseFlow.setChecked(False)

        if self.SimulateFlowControl is not None:
            if self.SimulateFlowControl.upper() == "TRUE":
                self.chkFlowControl.setChecked(True)
                
        self.chkStartingTime.stateChanged.connect(self.Check_StartingTime)

        self.chkmakeimage.stateChanged.connect(self.MakeASC_IMAGE)
        self.chkmakeASC.stateChanged.connect(self.MakeASC_IMAGE)
        self.MakeASC_IMAGE()

        if self.IsFixedTimeStep.upper() == "TRUE":
            self.chkfixeTimeStep.setChecked(True)

    def printcombo(self):
        if self.cmbPrint.currentText()=="All":
            self.chkmakeimage.setEnabled(True)
            self.chkmakeASC.setEnabled(True)
            self.MakeASC_IMAGE()
        else:
            self.chkmakeimage.setEnabled(False)
            self.chkmakeASC.setEnabled(False)
            self.chksoiSaturation.setEnabled(False)
            self.chkrfDistFile.setEnabled(False)
            self.chkrfaacDistfile.setEnabled(False)
            self.chkdischarge.setEnabled(False)

    def SPvaluechange(self):
        value=self.spTimeStep_min_2.text()
        if value =="0":
            MsError(" Input 0 can not be input. ")
            
    def Check_Parallel(self):
        flag = self.chkParallel.isChecked()
        self.spTimeStep_min_2.setEnabled(flag)
    
    def Check_Flow(self, flag):
        self.chkAutoROM.setEnabled(flag)
        self.chkAutoROM.setChecked(False)

    def Check_StartingTime(self):
        flag = self.chkStartingTime.isChecked()
        self.dateTimeEdit.setEnabled(flag)
        self.dataTimeFormat = flag
            
    def MakeASC_IMAGE(self):
        flag = self.chkmakeimage.isChecked() or self.chkmakeASC.isChecked()
        self.chksoiSaturation.setEnabled(flag)
        self.chkrfDistFile.setEnabled(flag)
        self.chkrfaacDistfile.setEnabled(flag)
        self.chkdischarge.setEnabled(flag)

 # ======================WatchPoint Tab Table Setting and btn event =========================
    def Set_Wathpoint_tab_default(self):
        try:
            # 테이블 상에 선택된 열을 위로 올림
            self.btnMoveup.clicked.connect(self.MoveUp)


            # 테이블 상에 선택된 열을 아래로 내림
            self.btnMovedown.clicked.connect(self.MoveDown)


            # 테이블 상에 선택된 열을 삭제
            self.btnRemove.clicked.connect(self.ReMove)


            # 테이블 셀값을 변경 불가능 하게 설정
            self.tbList.setEditTriggers(QAbstractItemView.NoEditTriggers)

            # color picker 이벤트
            self.btnColorPicker.clicked.connect(lambda: self.color_picker(self.btnColorPicker))
            self.btnColorPicker_3.clicked.connect(lambda: self.color_picker(self.btnColorPicker_3))

            #2017/11/22-------------------
            #테이블 셀 값 선택한 값의 위치로 view 이동
#             self.btnGrid.clicked.connect(self.GoToGrid)
            self.btnGrid.clicked.connect(lambda: self.btnGotoGrid(self.tbList))

            # 테이블 셀값을 변경 가능하게 설정 ----> 색상값 변경임 잘못된 구현 변경 해야함
            self.btnEdit.clicked.connect(self.Edit)

            self.btnAddSelectCell.clicked.connect(self.Add_Selected_Cell)

            # 최하류 셀 넣기
            self.btnAddMostDown.clicked.connect(self.Add_MostDown_Stream)

            # 각각의 컬럼에 갑셋팅(xml 상에 'ObTSId', 'ObTSLegend', 'ObTSMissingCount' 항목의 값이 없음
            self.Watchpoint_TableCreate(len(self.Name))
            self.Watchpoint_Table_Insert()
        except Exception as wa:
            MsError(wa)

    def MoveUp(self):
        row = self.tbList.currentRow()
        column = self.tbList.currentColumn()
        if row > 0:
            self.tbList.insertRow(row - 1)
            for i in range(self.tbList.columnCount()):
                self.tbList.setItem(row - 1, i, self.tbList.takeItem(row + 1, i))
                self.tbList.setCurrentCell(row - 1, column)
            self.tbList.removeRow(row + 1)

    def MoveDown(self):
        row = self.tbList.currentRow()
        column = self.tbList.currentColumn()
        if row>=0:
            if row < self.tbList.rowCount() - 1:
                self.tbList.insertRow(row + 2)
                for i in range(self.tbList.columnCount()):
                    self.tbList.setItem(row + 2, i, self.tbList.takeItem(row, i))
                    self.tbList.setCurrentCell(row + 2, column)
                self.tbList.removeRow(row)


    def check_add_watchpoint(self,x,y,name):
        rowCount = self.tbList.rowCount()
        self.RetBool= True
        for row in range(0, rowCount):
            Names = self.tbList.item(row,0).text()
            X = self.tbList.item(row, 1).text()
            Y = self.tbList.item(row, 2).text()
            if (X==str(x) and Y==str(y) ) or name==Names :
                self.RetBool= False
        return self.RetBool

    def ReMove(self):
        row = self.tbList.currentIndex().row()
        mess="Are you sure you want to delete the selected items?"
        result=QMessageBox.question(None, "Watershed Setup",mess,QMessageBox.Yes, QMessageBox.No)
        if result == QMessageBox.Yes:
            self.tbList.removeRow(row)

        self.post_grid_remove2()
        if self.chkFlowContorGird.isChecked():
            self.FlowContorGird_paint()
        if self.chkWatch_Point.isChecked():
            if self.tbList.rowCount()!=0:
                self.watchpoint_paint()
    
    def btnGotoGrid(self, tbl):
        row = tbl.currentRow()
        if row>-1:
            ColX = int(tbl.item(row, 1).text())
            RowY = int(tbl.item(row, 2).text())
            
            self.post_grid_remove()
            self.mapcanvas.refresh()
            self.scale_changed_mapcanvas()
            self.row_cols_grid(ColX, RowY, None)
            self.tool.scale_changed_disconnect()
        else:
            MsInfo("Check! select row")

    def CheckTableValue(self,x,y):
        rowCount = self.tbList.rowCount()
        self.RetBool= True
        for row in range(0, rowCount):
            X = self.tbList.item(row, 1).text()
            Y = self.tbList.item(row, 2).text()
            if X==str(x) and Y==str(y) :
                self.RetBool= False
        return self.RetBool

    # 에디트 클릭시에 선택된 Row 의 name 변경
    def Edit(self):
        # 현재 선택된 Row
        row=self.tbList.currentRow()

        if row>-1:
            cell = self.tbList.item(row, 0).text()
            # 다이얼 로그 출력하여 사용자가 셀값 제정의
            #text, ok = QtGui.QInputDialog.getText(self, 'Input Dialog','Enter name:',QLineEdit.Normal,cell)
            text, ok = QInputDialog.getText(self, 'Input Dialog','Enter name:',QLineEdit.Normal,cell)
            if ok:
                item = QTableWidgetItem(str(text))  # create a new Item
                self.tbList.setItem(row, 0, item)
        else:
            MsInfo("check! select Row")

    #2017 -12-15 박: 추가 버튼 눌렀을때 Watchpoint table 에 데이터 추가 하기
    def Add_Selected_Cell(self):
        try:
            if self.tool._FXCOL !=0 and self.tool._FYROW!=0:
                rowCount = self.tbList.rowCount()
                if rowCount >0:
                    text, ok = QInputDialog.getText(self, 'Input Dialog','Enter name:',QLineEdit.Normal,"")
                    if text.strip()!="":
                        if self.check_add_watchpoint(self.tool._YROW,self.tool._XCOL,text):
                            self.tbList.insertRow(rowCount)
                            self.tbList.setItem(rowCount, 0, QTableWidgetItem(text))
                            self.tbList.setItem(rowCount, 1, QTableWidgetItem(str(self.tool._FYROW)))
                            self.tbList.setItem(rowCount, 2, QTableWidgetItem(str(self.tool._FXCOL)))
                            self.ColX.append(self.tool._FXCOL)
                            self.RowY.append(self.tool._FYROW)
                            if self.chkWatch_Point.isChecked():
                                self.row_cols_grid(self.tool._FYROW, self.tool._FXCOL, "watchpoint")
                        else:
                            MsInfo( " Name or watchpoint is required. ")
                    else:
                        MsInfo(" Name is required. ")
                else:
                    text, ok = QInputDialog.getText(self, 'Input Dialog','Enter name:',QLineEdit.Normal,"")
                    if text.strip() != "":
                        self.tbList.insertRow(0)
                        self.tbList.setItem(rowCount, 0, QTableWidgetItem(text))
                        self.tbList.setItem(0, 1, QTableWidgetItem(str(self.tool._FYROW)))
                        self.tbList.setItem(0, 2, QTableWidgetItem(str(self.tool._FXCOL)))
                        self.ColX.append(self.tool._FXCOL)
                        self.RowY.append(self.tool._FYROW)
                        if self.chkWatch_Point.isChecked():
                            self.row_cols_grid(self.tool._FYROW, self.tool._FXCOL, "watchpoint")
                    else:
                        MsInfo( " Name is required. ")
        except Exception as e:
            MsError(e)

    def Add_MostDown_Stream(self):
        if len(self._StreamWSID)==1:
            x = self._wsinfo.facMaxCellxCol
            y = self._wsinfo.facMaxCellyRow

            rowCount = self.tbList.rowCount()
            if self.CheckTableValue(x,y):
                self.tbList.insertRow(rowCount)
                text, ok = QInputDialog.getText(self, 'Input Dialog', 'Enter name:', QLineEdit.Normal, "")
                self.tbList.setItem(rowCount, 0, QTableWidgetItem(text))
                self.tbList.setItem(rowCount, 1, QTableWidgetItem(str(x)))
                self.tbList.setItem(rowCount, 2, QTableWidgetItem(str(y)))
                self.row_cols_grid(x, y, "watchpoint")
                for id in range (len(self._StreamWSID)):
                    self.SetMostDownStream(self._StreamWSID[id])
            else:
                MsInfo(" The most downstream value already exists. ")
        else:
            # 최박사님이 문구 주실거임
            # 2018-07-24 박: 최하류 유역이 1개일때만 자동 추가 2개 이상일때는 추가하지 않고 문구로 대체함
            MsInfo( " The number of most down stream cells are more than 1." + "\r\n" +  " Add most down stream cells manually. ")

    def Watchpoint_TableCreate(self,Row):
        self.tbList.setColumnCount(3)
        self.tbList.setRowCount(Row)
        self.tbList.setHorizontalHeaderLabels( ['Name','ColX', 'RowY'])
        #테이블 넓이 에 맞게 Name 항목 넓이 지정 
        self.tbList.setColumnWidth(0,176)
        
 # watchpoint datault 값을 변수에 저장
    def Set_Wathpoint_default_value(self):
        self.Name = []
        self.ColX = []
        self.RowY = []
        if self._WatchPointCount== 0:
            # Dll 에서 X,Y 값을 넣었을때 받는 값

            #2020-05-19 박: 기존에서 함수명 변경됨
            x = self._wsinfo.facMaxCellxCol
            y = self._wsinfo.facMaxCellyRow

            # 2018-07-24 박: 처음 로드시 최하류 셀이 1개이면 추가함 그이상이면 추가하지 안음
            if self._wsinfo.mostDownStreamWSCount==1:
                names = "MD"
                self.Name.append(names)
                self.ColX.append(str(x))
                self.RowY.append(str(y))
                # New Project 일때 프로그램 최하류 정보를 Dll에 넣음

                for id in range (self._wsinfo.mostDownStreamWSCount):
                    self.SetMostDownStream(self._StreamWSID[id])

        elif self._WatchPointCount>1:
            for flowitem in self._xmltodict['GRMProject']['WatchPoints']:
                self.ColX.append(str(flowitem['ColX']))
                self.RowY.append(str(flowitem['RowY']))
                self.Name.append(flowitem['Name'])

        elif  self._WatchPointCount==1:
            self.ColX.append(str(self._xmltodict['GRMProject']['WatchPoints']['ColX']))
            self.RowY.append(str(self._xmltodict['GRMProject']['WatchPoints']['RowY']))
            self.Name.append(str(self._xmltodict['GRMProject']['WatchPoints']['Name']))

    def Watchpoint_Table_Insert(self):
        if len(self.Name) >0:
            for i in range(0, len(self.Name)):
                # 사용자에게 CVID 표출 안함
                self.tbList.setItem(i, 0, QTableWidgetItem(self.Name[i]))
                self.tbList.setItem(i, 1, QTableWidgetItem(self.ColX[i]))
                self.tbList.setItem(i, 2, QTableWidgetItem(self.RowY[i]))

    # 색상 변경 Picker -- 2017/09/07  조가 주석달음
    def color_picker(self, bttom): #, type
        color = QColorDialog.getColor()
        bttom.setStyleSheet("background-color:" + str(color.name()) + ";");

        self.post_grid_remove2()
        self.watchpoint()
        self.click_FlowContorGird()
            

    # watchpoint RubberBand 제거
    def post_grid_remove2(self):
        for v in self.canvasRubberBand:
#         for v in self.mapcanvas.scene().items():
            if issubclass(type(v), QgsRubberBand) == True:
                self.mapcanvas.scene().removeItem(v)

    def watchpoint(self):

        if self.chkWatch_Point.isChecked():
            self.watchpoint_paint()
        else:
            # 지우기
            self.post_grid_remove2()
            if self.chkFlowContorGird.isChecked():
                self.FlowContorGird_paint()


    def watchpoint_paint(self):
        try:
            if len(self.ColX)>0 and len(self.RowY)>0:
                if self.tbList.rowCount()>0:
                    for i in range(0,self.tbList.rowCount()):
                        x=self.tbList.item(i, 1).text()
                        y=self.tbList.item(i, 2).text()
                        self.row_cols_grid(int(x),int(y),"watchpoint")

                else:
                    for i in range(0,len(self.ColX)):
                        self.row_cols_grid(int(self.ColX[i]),int(self.RowY[i]),"watchpoint")
        except Exception as e :
            MsError(e)
            
    #1. row/cols로 마커
    def row_cols_grid(self,row,column,type):
        if str(row)!="" and str(column)!="":
            row = int(row)
            column=int(column)
            if row < 0 or column < 0 or self._height<=column or self._width <= row:
                row = "out of extent"
                column="out of extent"
                MsInfo("{0}, {1}".format(str(row),str(column)))
            else:
                if type == "watchpoint":
                    Cell_X_Center2 = self._xmin + self._xsize/2 + self._xsize * (row)
                    Cell_Y_Center2 =  self._ymax -  self._ysize/2 -  self._ysize * (column)
                    if Cell_X_Center2<= self._xmax or self._xmin<=Cell_X_Center2 or Cell_Y_Center2<=self._ymax or self._ymin<=Cell_Y_Center2:
                        self.draw_grid2(Cell_X_Center2, Cell_Y_Center2,self.btnColorPicker)

                else:
                    self.lblColRow.setText("xCol, yRow:" + str(row) + " , " + str(column))
                    self.tool.Cell_X_Center = self._xmin+ self._xsize/2 + self._xsize * (row)
                    self.tool.Cell_Y_Center =  self._ymax -  self._ysize/2 -  self._ysize * (column)
                    if self.tool.Cell_X_Center<= self._xmax or self.xmin<=self.tool.Cell_X_Center or self.tool.Cell_Y_Center<=self._ymax or self._ymin<=self.tool.Cell_Y_Center:
                        oldExtent = self.mapcanvas.extent()

                        x1n = self.tool.Cell_X_Center - oldExtent.width()/2.0
                        x2n = self.tool.Cell_X_Center + oldExtent.width()/2.0
                        y1n = self.tool.Cell_Y_Center - oldExtent.height()/2.0
                        y2n = self.tool.Cell_Y_Center + oldExtent.height()/2.0

                        self.mapcanvas.setExtent(QgsRectangle(x1n, y2n, x2n, y1n))
                        self.draw_grid(self.tool.Cell_X_Center, self.tool.Cell_Y_Center)
        else:
            MsError("There is a problem with the text value.")
            return
              
    # Watch point 그림을 Rubberbanc로 처리 함
    def draw_grid2(self,x,y,btn):
        r = QgsRubberBand(self.mapcanvas, True)
        size=self._xsize/2

        points = [[QgsPointXY(x - size, y + size), QgsPointXY(x - size, y - size), QgsPointXY(x + size, y - size),QgsPointXY(x + size, y + size)]]

        r.setToGeometry(QgsGeometry.fromPolygonXY(points), None)
        r.setColor(QColor(btn.palette().button().color()))
        r.setWidth(2)
        
        self.canvasRubberBand.append(r)

    def click_FlowContorGird(self):
        if self.chkFlowContorGird.isChecked():
            self.FlowContorGird_paint()
        else:
            # 지우기
            self.post_grid_remove2()
            if self.chkWatch_Point.isChecked():
                self.watchpoint_paint()

    def FlowContorGird_paint(self):
        counts = self.tlbFlowControl.rowCount()
        for i in range(0,counts):
            xvalue = self._xmin + self._xsize / 2 + self._xsize * (int(self.tlbFlowControl.item(i, 1).text()))
            yvalue = self._ymax - self._ysize / 2 - self._ysize * (int(self.tlbFlowControl.item(i, 2).text()))
            self.draw_grid2(xvalue,yvalue,self.btnColorPicker_3)

    # 그리드 라인 함수
    def show_hide_grid_line(self):
        if self.show_grid_line.isChecked():
            self.add_grid_layer()
        else:
            self.remove_grid_layer()

    def remove_grid_layer(self):
        self.grid_line.setOpacity(0)
        self.mapcanvas.refresh()

    # 플로우 디렉션
    def show_hide_flow_direction(self):
        if self.show_flow_direction.isChecked():
            self.show_flow_directions()
        else:
            self.hide_flow_direction()


    def add_grid_layer(self):
        names = [layer.name() for layer in QgsProject.instance().mapLayers().values()]
        if names.count("grid_line")>0:
            self.grid_line.setOpacity(1)
            self.mapcanvas.refresh()
            if names.count("flow_layer")>0:
                #self.mapcanvas.setLayers([self.flow_direction_layer,self.grid_line,self.layer])
                self.mapcanvas.setLayers([self.flow_direction,self.grid_line,self.layer,self.Wsid_label_shape])
        else:
            self.grid_line = get_point_layer(self.layer, self.mapcanvas)
            QgsProject.instance().addMapLayer(self.grid_line, False)
            self.layer.extent().combineExtentWith(self.grid_line.extent())
            self.mapcanvas.setExtent(self.mapcanvas.extent())

            # ========= 2017/11/10 : 기본적으로 Grid line 단일 체크시 Grid line 만 표현,flow direction 체크 시 flow direction 함께 표시
            self.mapcanvas.setLayers([self.grid_line,self.layer,self.Wsid_label_shape])

            if self.flow_direction:
                self.mapcanvas.setLayers([self.flow_direction,self.grid_line,self.layer,self.Wsid_label_shape])
      
    def show_flow_directions(self):
        names = [layer.name() for layer in QgsProject.instance().mapLayers().values()]
        if names.count("flow_layer")>0:
            self.flow_direction.setOpacity(1)
            self.mapcanvas.refresh()
        else:
            FD = self._xmltodict['GRMProject']['ProjectSettings']['FlowDirectionFile']
            ST = self._xmltodict['GRMProject']['ProjectSettings']['StreamFile']
            self.layer2 = QgsRasterLayer(FD, "FD", "gdal")
            self.layer3 = QgsRasterLayer(ST, "ST", "gdal")

            strFDType = self._xmltodict['GRMProject']['ProjectSettings']['FlowDirectionType']
            self.flow_direction = get_flow_layer(self.layer2, self.mapcanvas, self.layer3,strFDType,self.GridCellSize)


            #  신규 소스
            QgsProject.instance().addMapLayer(self.flow_direction, False)
            self.layer.extent().combineExtentWith(self.flow_direction.extent())

            # ========= 2017/11/10 : 기본적으로 flow direction 단일 체크시 다음 flow direction 만 표현,Grid line 체크 시 grid line 함께 표시
            self.mapcanvas.setLayers([self.flow_direction,self.layer,self.Wsid_label_shape])
            if names.count("grid_line")>0:
                self.mapcanvas.setLayers([self.grid_line,self.flow_direction,self.layer,self.Wsid_label_shape])
            # ========= 2017/11/10 : 기본적으로 flow direction 단일 체크시 다음 flow direction 만 표현,Grid line 체크 시 grid line 함께 표시
            
 # Qdilog 창에 Qtablewidget 셋팅
    def aboutApp(self):
        website = "http://code.google.com/p/comictagger"
        msgBox = QMessageBox()
        msgBox.setWindowTitle(self.tr("Move to grid"))
        msgBox.setTextFormat(QtCore.Qt.RichText)

        msgBox.setText("<pre></pre>")
        self.addGroupWidget(msgBox)
        ret=msgBox.exec_()

    #Create TableWidget
    def addGroupWidget (self, parentItem) :
        #라디오 버튼, move to grid, xCol No, yRow No
        self.rdo_xColyRowNo = QRadioButton("xCol No, yRow No", parentItem)
        self.rdo_xy = QRadioButton("x, y", parentItem)

        #텍스트 박스
        self.txt_xColyRowNo_1 = QLineEdit(parentItem)
        self.txt_xColyRowNo_2 = QLineEdit(parentItem)
        self.txt_xy1 = QLineEdit(parentItem)
        self.txt_xy2 = QLineEdit(parentItem)
        self.btn_Cancel = QPushButton(parentItem)
        self.btn_Cancel.setText("Cancel")


        self.btn_OK = QPushButton(parentItem)
        self.btn_OK.setText("OK")
        #위치 정의 setGeometry(x,y,w,h)
        layout = parentItem.layout()
        
        layout.addWidget(self.rdo_xColyRowNo, 0, 0)
        layout.addWidget(self.rdo_xy, 1, 0)
        layout.addWidget(self.txt_xColyRowNo_1, 0, 1)
        layout.addWidget(self.txt_xColyRowNo_2, 0, 2)
        layout.addWidget(self.txt_xy1, 1, 1)
        layout.addWidget(self.txt_xy2, 1, 2)

        layout.addWidget(self.btn_Cancel, 2, 2)
        layout.addWidget(self.btn_OK, 2, 1)

        self.txt_xColyRowNo_1.setMaximumWidth(100);
        self.txt_xColyRowNo_2.setMaximumWidth(100);
        self.txt_xy1.setFixedWidth(100);
        self.txt_xy2.setFixedWidth(100);

        #버튼별 이벤트
        #1. rdo_xColyRowNo가 체크 시 그 외 비활성화
        self.rdo_xColyRowNo.setChecked(True)
        self.rdo_xy.setChecked(False)
        self.txt_xy1.setDisabled(True)
        self.txt_xy2.setDisabled(True)
        #라디오 버튼 이벤트, 함수는 나중에 수정 바람... 2017/10/19 Cho
        self.rdo_xColyRowNo.clicked.connect(self.disableFunction)
        self.rdo_xy.clicked.connect(self.disableFunction)
        self.btn_OK.clicked.connect(self.OK_Click)
        self.btn_Cancel.clicked.connect(lambda: self.Cancel_Click(parentItem))


    def Cancel_Click(self,parentItem):
        parentItem.close()

    # 폼 종료
    def Close_Form(self):
        self.close()


    def closeEvent(self, event):
        del self._wsinfo
        self.Clear_Canvas()
        self.closeDialogEvent.emit()
      
    def SaveProject(self, flag=False):
        self.InputDictionary()
        DictoXml = unparse(self._xmltodict)
        fw = open(self.ProjectFile, 'w+')
        fw.write(DictoXml)
        fw.close()

        #2020-02-10 박: XML 체크할때 Landcover 데이터를 배열에 받아서 반환 함 
        _XmlCheck.Check_Gmp_xml(self.ProjectFile)
        self._LandCoverCount =_XmlCheck._LandCoverCount
        self._GreenAmptCount =_XmlCheck._GreenAmptCount
        self._SoilDepthCount =_XmlCheck._SoilDepthCount
        self._WatchPointCount = _XmlCheck._WatchPointCount
        self._SubWatershedCount=_XmlCheck._SubWatershedCount
        self._FlowControlCount = _XmlCheck._FlowControlCount
        self._ChannelSettingsCount=_XmlCheck._ChannelSettingsCount
        if flag:
            MsInfo( '[' + self.ProjectFile + ']' + ' was saved. ')

    def InputDictionary(self):
        try:
            # =========================simulation tab ===================================
            self._xmltodict['GRMProject']['ProjectSettings']['ComputationalTimeStep'] = self.spTimeStep_min.text()
            if self.chkStartingTime.isChecked():
                DateTime = self.dateTimeEdit.dateTime().toString("yyyy-MM-dd hh:mm")
                self._xmltodict['GRMProject']['ProjectSettings']['SimulStartingTime'] = DateTime
            else:
                self._xmltodict['GRMProject']['ProjectSettings']['SimulStartingTime'] = "0"

            if self.chkParallel.isChecked():
                self._xmltodict['GRMProject']['ProjectSettings']['MaxDegreeOfParallelism'] =self.spTimeStep_min_2.text()

            else:
                self._xmltodict['GRMProject']['ProjectSettings']['MaxDegreeOfParallelism'] ="-1"

            self._xmltodict['GRMProject']['ProjectSettings']['OutputTimeStep'] = self.txtOutput_time_step.text()
            self._xmltodict['GRMProject']['ProjectSettings']['SimulationDuration'] = self.txtSimulation_duration.text()
            self._xmltodict['GRMProject']['ProjectSettings']['OutputTimeStep'] = self.txtOutput_time_step.text()

            projectTagDic = {
                'SimulateInfiltration' : self.chkInfiltration,
                'SimulateSubsurfaceFlow' : self.chkSubsurfaceFlow,
                'SimulateBaseFlow' : self.chkBaseFlow,
                'SimulateFlowControl' : self.chkFlowControl,
                'MakeIMGFile' : self.chkmakeimage,
                'MakeASCFile' : self.chkmakeASC,
                'MakeSoilSaturationDistFile' : self.chksoiSaturation,
                'MakeRfDistFile' : self.chkrfDistFile,
                'MakeRFaccDistFile' : self.chkrfaacDistfile,
                'MakeFlowDistFile' : self.chkdischarge,
                'WriteLog' : self.chklog,
                'IsFixedTimeStep' : self.chkfixeTimeStep
            }
            
            for k in projectTagDic.keys():
                self._xmltodict['GRMProject']['ProjectSettings'][k] = str(projectTagDic[k].isChecked()).lower() #'true' or 'false'

            self._xmltodict['GRMProject']['ProjectSettings']['PrintOption'] =self.cmbPrint.currentText()

            # =========================simulation tab end ===============================================

            # =========================Watch Point tab===================================================
            #     GRM._WatchPointCount
#             if self._WatchPointCount > 0:
            try:
                #2021.12.07 동 : watchpoint, subwatershed 태그는 Set_ProjectDataInit 함수에서 초기값 세팅을 안해주기 때문에 
                # 프로젝트 오픈후 처음으로 run dialog를 실행 시켰을 때 self._WatchPointCount..등 값이 무조건 0 값으로 표기됨. 
                # 그래서  값이 중복되서 저장되는 현상이 있어 keyerror가 발생하지 않는한, 무조건 적으로 지우도록 변경
                del self._xmltodict['GRMProject']['WatchPoints']
            except KeyError:
                pass
            self._WatchPointCount = self.tbList.rowCount()

            DictoXml = unparse(self._xmltodict)
            ET.register_namespace('', "http://tempuri.org/GRMProject.xsd")
            xmltree = ET.ElementTree(ET.fromstring(DictoXml))
            root = xmltree.getroot()

            wcount = self.tbList.rowCount()
            self._WatchPointCount = wcount
            for row in range(0, wcount):
                child = ET.Element("WatchPoints")
                root.append(child)

                WathchName = ET.Element("Name")
                WathchName.text = self.tbList.item(row, 0).text()
                child.append(WathchName)

                WathchColX = ET.Element("ColX")
                WathchColX.text = self.tbList.item(row, 1).text()
                child.append(WathchColX)

                WathchRowY = ET.Element("RowY")
                WathchRowY.text = self.tbList.item(row, 2).text()
                child.append(WathchRowY)
            xmltree_string = ET.tostring(xmltree.getroot())
            docs = dict(parse(xmltree_string))
            self._xmltodict.clear()
            self._xmltodict.update(docs)

            # =========================Wahch Point tab end===============================================

            # =========================Channel CS tab====================================================
            #2020-04-28 박: 이부분이 따로 떨어져서 xml 생성됨 그래서 주석 처리로 변경 하고 XML 부분 수정으로 소스 수정
            if self._ChannelSettingsCount>0:
                del self._xmltodict['GRMProject']['ChannelSettings']

            DictoXml = unparse(self._xmltodict)
            ET.register_namespace('', "http://tempuri.org/GRMProject.xsd")
            xmltree = ET.ElementTree(ET.fromstring(DictoXml))
            root = xmltree.getroot()
            self._ChannelSettingsCount = len(self._StreamWSID)
            
            for index in range(0, self._ChannelSettingsCount):
                child = ET.Element("ChannelSettings")
                root.append(child)

                WSID = ET.Element("WSID")
                WSID.text = str(self._StreamWSID[index])
                child.append(WSID)

                CrossSectionType = ET.Element("CrossSectionType")
                if self.CrossSectionType[index]== "CSCOMPOUND":
                    CrossSectionType.text ="CSCompound"
                elif self.CrossSectionType[index]== "CSSINGLE":
                    CrossSectionType.text ="CSSingle"
                else:
                    CrossSectionType.text ="CSSingle"
                child.append(CrossSectionType)

                SingleCSChannelWidthType = ET.Element("SingleCSChannelWidthType")
                if self.SingleCSChannelWidthType[index].upper()=="CWGENERATION":
                    SingleCSChannelWidthType.text = "CWGeneration"
                elif self.SingleCSChannelWidthType[index].upper()=="CWEQUATION":
                    SingleCSChannelWidthType.text = "CWEquation"
                else:
                    SingleCSChannelWidthType.text = "CWGeneration"

                child.append(SingleCSChannelWidthType)
            
                ChannelWidthEQc = ET.Element("ChannelWidthEQc")
                ChannelWidthEQc.text = str(self.ChannelWidthEQc[index])
                child.append(ChannelWidthEQc)

                ChannelWidthEQd = ET.Element("ChannelWidthEQd")
                ChannelWidthEQd.text = str(self.ChannelWidthEQd[index])
                child.append(ChannelWidthEQd)

                ChannelWidthEQe = ET.Element("ChannelWidthEQe")
                ChannelWidthEQe.text = str(self.ChannelWidthEQe[index])
                child.append(ChannelWidthEQe)
        
                ChannelWidthMostDownStream = ET.Element("ChannelWidthMostDownStream")
                ChannelWidthMostDownStream.text = str(self.ChannelWidthMostDownStream[index])
                child.append(ChannelWidthMostDownStream)

                LowerRegionHeight = ET.Element("LowerRegionHeight")
                LowerRegionHeight.text = str(self.LowerRegionHeight[index])
                child.append(LowerRegionHeight)
        
                LowerRegionBaseWidth = ET.Element("LowerRegionBaseWidth")
                LowerRegionBaseWidth.text = str(self.LowerRegionBaseWidth[index])
                child.append(LowerRegionBaseWidth)

                UpperRegionBaseWidth = ET.Element("UpperRegionBaseWidth")
                UpperRegionBaseWidth.text = str(self.UpperRegionBaseWidth[index])
                child.append(UpperRegionBaseWidth)
        
                CompoundCSChannelWidthLimit = ET.Element("CompoundCSChannelWidthLimit")
                CompoundCSChannelWidthLimit.text = str(self.CompoundCSChannelWidthLimit[index])
                child.append(CompoundCSChannelWidthLimit)

                BankSideSlopeRight = ET.Element("BankSideSlopeRight")
                BankSideSlopeRight.text = str(self.BankSideSlopeRight[index])
                child.append(BankSideSlopeRight)
            
            
                BankSideSlopeLeft = ET.Element("BankSideSlopeLeft")
                BankSideSlopeLeft.text = str(self.BankSideSlopeLeft[index])
                child.append(BankSideSlopeLeft)
        

            xmltree_string = ET.tostring(xmltree.getroot())
            docs = dict(parse(xmltree_string))
            self._xmltodict.clear()
            self._xmltodict.update(docs)

            # =========================Channel CS tab end================================================
            # =========================Flow Control Tab==================================================
            self.UpdateFlowControl()
            
            # =========================Flow Control Tab end ==================================================
            # ========================= Watershed tab ========================================================
#             if self._SubWatershedCount>0:
            try:
                del self._xmltodict['GRMProject']['SubWatershedSettings']
            except KeyError:
                pass
            
            DictoXml = unparse(self._xmltodict)
            ET.register_namespace('', "http://tempuri.org/GRMProject.xsd")
            xmltree = ET.ElementTree(ET.fromstring(DictoXml))
            root = xmltree.getroot()
            self._SubWatershedCount = self.cb_selectws.count()
            scount = self.cb_selectws.count()

            for row in range(0, scount):
                selectWS=self.cb_selectws.itemText(row)

                child = ET.Element("SubWatershedSettings")
                root.append(child)

                ID = ET.Element("ID")
                ID.text = selectWS
                child.append(ID)

                IniSaturation = ET.Element("IniSaturation")
                IniSaturation.text = str(self._wsinfo.subwatershedPars(int(selectWS)).iniSaturation)
                child.append(IniSaturation)

                MinSlopeOF = ET.Element("MinSlopeOF")
                MinSlopeOF.text = str(self._wsinfo.subwatershedPars(int(selectWS)).minSlopeOF)
                child.append(MinSlopeOF)

                UnsaturatedKType=ET.Element('UnsaturatedKType')
                UnsaturatedKType_int=str(self._wsinfo.subwatershedPars(int(selectWS)).unSatKType)
                UnsturatedType="Linear" #2021.12.06 동  : 1 or default 값은 Linear
                if UnsaturatedKType_int=="0":
                    UnsturatedType="Constant"
                elif UnsaturatedKType_int=="2":
                     UnsturatedType="Exponential"

                UnsaturatedKType.text = UnsturatedType
                child.append(UnsaturatedKType)


                CoefUnsaturatedK=ET.Element('CoefUnsaturatedK')
                CoefUnsaturatedK.text = str(self._wsinfo.subwatershedPars(int(selectWS)).coefUnsaturatedK)
                child.append(CoefUnsaturatedK)

                MinSlopeChBed = ET.Element("MinSlopeChBed")
                MinSlopeChBed.text = str(self._wsinfo.subwatershedPars(int(selectWS)).minSlopeChBed)
                child.append(MinSlopeChBed)

                MinChBaseWidth = ET.Element("MinChBaseWidth")
                MinChBaseWidth.text = str(self._wsinfo.subwatershedPars(int(selectWS)).minChBaseWidth)
                child.append(MinChBaseWidth)

                ChRoughness = ET.Element("ChRoughness")
                ChRoughness.text = str(self._wsinfo.subwatershedPars(int(selectWS)).chRoughness)
                child.append(ChRoughness)

                DryStreamOrder = ET.Element("DryStreamOrder")
                DryStreamOrder.text =  str(self._wsinfo.subwatershedPars(int(selectWS)).dryStreamOrder)
                child.append(DryStreamOrder)

                IniFlow = ET.Element("IniFlow")
                IniFlow.text = "0"
                if self._wsinfo.subwatershedPars(int(selectWS)).iniFlow is not None:
                    IniFlow.text = str(self._wsinfo.subwatershedPars(int(selectWS)).iniFlow)
                child.append(IniFlow)

                CalCoefLCRoughness = ET.Element("CalCoefLCRoughness")
                CalCoefLCRoughness.text =  str(self._wsinfo.subwatershedPars(int(selectWS)).ccLCRoughness)
                child.append(CalCoefLCRoughness)

                CalCoefPorosity = ET.Element("CalCoefPorosity")
                CalCoefPorosity.text =str(self._wsinfo.subwatershedPars(int(selectWS)).ccPorosity)
                child.append(CalCoefPorosity)

                CalCoefWFSuctionHead = ET.Element("CalCoefWFSuctionHead")
                CalCoefWFSuctionHead.text = str(self._wsinfo.subwatershedPars(int(selectWS)).ccWFSuctionHead)
                child.append(CalCoefWFSuctionHead)

                CalCoefHydraulicK = ET.Element("CalCoefHydraulicK")
                CalCoefHydraulicK.text = str(self._wsinfo.subwatershedPars(int(selectWS)).ccHydraulicK)
                child.append(CalCoefHydraulicK)

                CalCoefSoilDepth = ET.Element("CalCoefSoilDepth")
                CalCoefSoilDepth.text = str(self._wsinfo.subwatershedPars(int(selectWS)).ccSoilDepth) 
                child.append(CalCoefSoilDepth)

                UserSet = ET.Element("UserSet")
                UserSet_value = str(self._wsinfo.subwatershedPars(int(selectWS)).userSet)
                UserSet.text = "False"
                if UserSet_value=="1":
                    UserSet.text = "True"
                
                child.append(UserSet)

            xmltree_string = ET.tostring(xmltree.getroot())
            docs = dict(parse(xmltree_string))
            self._xmltodict.clear()
            self._xmltodict.update(docs)

        except Exception as e : 
            MsError(e)

    def Clear_Canvas(self):
        try:
            #레이어가 자꾸 잡혀 있어서 프로세스가 사용중으로 나옴 그래서 레이어 삭제 기능 추가해서 넣음
            layers = self.mapcanvas.layers()
            for l in layers:
                QgsProject.instance().removeMapLayer(l.id())
            self.mapcanvas.clearCache()
#             self.AddLayerQGIS()
            
        except Exception as e:
            pass
        

    def AddLayerQGIS(self):
        # dictionary 값을 받아서 레이어 목록을 Qgis 에 올림
        proTag = ['DomainFile', 'SlopeFile', 'FlowDirectionFile', 'FlowAccumFile'
                  'StreamFile', 'LandCoverFile', 'SoilDepthFile', 'SoilTextureFile']
        
        for t in proTag:
            if self._xmltodict['GRMProject']['ProjectSettings'][t] is not None:
                self.AddlayerQGIS(self._xmltodict['GRMProject']['ProjectSettings'][t])


    # gis에 올리기
    def AddlayerQGIS(self, path):
        try:
            if (os.path.isfile(path)):
                fileInfo = QFileInfo(path)
                baseName = fileInfo.baseName()
                layer=QgsRasterLayer(path, baseName, "gdal")
                QgsProject.instance().addMapLayer(layer)
        except Exception as e:
            MsInfo(e)

    def OK_Click(self):
        self.post_grid_remove()
        self.rdo_selection()
        self.mapcanvas.refresh()
        self.scale_changed_mapcanvas()
        self.tool.scale_changed_disconnect()

    #scale에 따라 Marker 크기 변화 --  Canvastool class 별개 함수
    def scale_changed_mapcanvas(self):
        try:
            #connect 중복 연결 방지 
            self.mapcanvas.scaleChanged.disconnect(self.scale_change_vertexMarker)
        except TypeError:
            pass
        self.mapcanvas.scaleChanged.connect(self.scale_change_vertexMarker)

    def scale_change_vertexMarker(self):
        self.post_grid_remove()
        try:
            if self.tool.Cell_X_Center is not None or self.tool.Cell_Y_Center is not None:
                self.draw_grid(self.tool.Cell_X_Center,self.tool.Cell_Y_Center)
        except AttributeError:
            pass

     # ================== 2017/11/6 조
    def post_grid_remove(self):
        for v in self.mapcanvas.scene().items():
            if issubclass(type(v), QgsVertexMarker):
                self.mapcanvas.scene().removeItem(v)

    def rdo_selection(self):
        #col, row 입력
        if self.rdo_xColyRowNo.isChecked():
            self.tool._FXCOL = int(self.txt_xColyRowNo_2.text())
            self.tool._FYROW = int(self.txt_xColyRowNo_1.text())
            self.tool._XCOL = int(self.txt_xColyRowNo_2.text())
            self.tool._YROW = int(self.txt_xColyRowNo_1.text())

            gird=self.row_cols_grid(self.txt_xColyRowNo_1.text(),self.txt_xColyRowNo_2.text(),None)
        #xy 입력
        elif self.rdo_xy.isChecked():
            self.xy_grid(self.layer,self.txt_xy1.text(),self.txt_xy2.text())
            x = self.txt_xy1.text()
            y =self.txt_xy2.text()

    def identify(self):
        # 캔버스 휠까지 처리 됨
        self.mapcanvas.setCursor(QtGui.QCursor(Qt.ArrowCursor))
        
        self.tool.scale_changed()
        self.mapcanvas.setMapTool(self.tool)


    def disableFunction(self):
        flag = self.rdo_xColyRowNo.isChecked()
        self.txt_xColyRowNo_1.setDisabled(not flag)
        self.txt_xColyRowNo_2.setDisabled(not flag)
        self.txt_xy1.setDisabled(flag)
        self.txt_xy2.setDisabled(flag)

     #grid 그리기
    def draw_grid(self,x,y):
        marker = QgsVertexMarker(self.mapcanvas)
        marker.setCenter(QgsPointXY(float(x), float(y)))

        marker.setColor(QColor(255, 0, 0))
        scale = self.mapcanvas.scale()
        # 사이즈 조절함. 가능한 맞게 조정함
        map_width = self.mapcanvas.extent().xMaximum() - self.mapcanvas.extent().xMinimum()
        size = (self._xsize / 150.0) * 100000 / map_width
        marker.setIconSize(size)
        marker.setIconType(QgsVertexMarker.ICON_BOX)
        marker.setPenWidth(1)
        return marker

    def hide_flow_direction(self):
        self.flow_direction.setOpacity(0)
        self.mapcanvas.refresh()

# ----------------- Channel CS 탭 텍스트 박스 셋팅 -----------------------------
    def Set_ChannelCS_tab_default(self):
        CrossSectionType=self.CrossSectionType[0].upper()
        SingleCSChannelWidthType=self.SingleCSChannelWidthType[0].upper()

        if CrossSectionType=="CSSINGLE":
            self.chk_compound.setChecked(False)
        elif CrossSectionType == "CSCOMPOUND":
            self.chk_compound.setChecked(True)


        if SingleCSChannelWidthType=="CWGENERATION":
                self.rdo_generateCh.setChecked(True)
        elif SingleCSChannelWidthType=="CWEQUATION":
            self.rdo_useCh.setChecked(True)
        else:
            self.rdo_generateCh.setChecked(True)

        self.txt_c.setText(self.ChannelWidthEQc[0])
        self.txt_d.setText(self.ChannelWidthEQd[0])
        self.txt_e.setText(self.ChannelWidthEQe[0])
        self.txt_douwnstream.setText(self.ChannelWidthMostDownStream[0])
        self.txtLower_Region_Height.setText(self.LowerRegionHeight[0])
        self.txtLower_Region_Base_Width.setText(self.LowerRegionBaseWidth[0])
        self.txtUpper_Region_Base_Width.setText(self.UpperRegionBaseWidth[0])
        self.txtCompound_CSChannel_Width_Limit.setText(self.CompoundCSChannelWidthLimit[0])
        self.txtRight_bank.setText(self.BankSideSlopeRight[0])
        self.txtLeft_bank.setText(self.BankSideSlopeLeft[0])

        self.txt_douwnstream.setDisabled(True)
        self.ChannelCS_rdo_able()

        self.chk_compound.clicked.connect(self.ChannelCS_rdo_able)

        self.rdo_useCh.clicked.connect(self.ChannelCS_rdo_able)
        self.rdo_generateCh.clicked.connect(self.ChannelCS_rdo_able)
        self.lisw_WSID.clicked.connect(self.ListView_WSID)
        self.lisw_WSID.currentItemChanged.connect(self.key_events)

        self.btn_Apply_WSID_value.clicked.connect(self.set_WSID_value_change)


    def key_events(self):
        try:
            index=self.lisw_WSID.currentRow()
            CrossSectionType=self.CrossSectionType[index].upper()
            SingleCSChannelWidthType=self.SingleCSChannelWidthType[index].upper()
            if SingleCSChannelWidthType=="CWGENERATION":
                self.rdo_generateCh.setChecked(True)
            elif SingleCSChannelWidthType=="CWEQUATION":
                self.rdo_useCh.setChecked(True)
            else:
                self.rdo_generateCh.setChecked(True)
            if CrossSectionType=="CSSINGLE":
                self.chk_compound.setChecked(False)
            elif CrossSectionType == "CSCOMPOUND":
                self.chk_compound.setChecked(True)
            else:
                self.chk_compound.setChecked(False)


            self.txt_c.setText(self.ChannelWidthEQc[index])
            self.txt_d.setText(self.ChannelWidthEQd[index])
            self.txt_e.setText(self.ChannelWidthEQe[index])
            self.txt_douwnstream.setText(self.ChannelWidthMostDownStream[index])
            self.txtLower_Region_Height.setText(self.LowerRegionHeight[index])
            self.txtLower_Region_Base_Width.setText(self.LowerRegionBaseWidth[index])
            self.txtUpper_Region_Base_Width.setText(self.UpperRegionBaseWidth[index])
            self.txtCompound_CSChannel_Width_Limit.setText(self.CompoundCSChannelWidthLimit[index])
            self.txtRight_bank.setText(self.BankSideSlopeRight[index])
            self.txtLeft_bank.setText(self.BankSideSlopeLeft[index])

            self.txt_douwnstream.setDisabled(True)
            self.ChannelCS_rdo_able()

        except Exception as e:
            MsError(e)


    #2020-07-09 박: WSID 별 값수정 후 적용 하기 버튼 이벤트
    def set_WSID_value_change(self):
        try:
            if self.lisw_WSID.currentItem():
                select_item=self.lisw_WSID.currentItem().text()
                
                #2020-07-16 박:기능 변경 
                for i in range(self._ChannelSettingsCount):
                    if (str(self._StreamWSID[i]) == str(select_item)):
                        self.ChannelWidthEQc[i] = self.txt_c.text()
                        self.ChannelWidthEQd[i] = self.txt_d.text()
                        self.ChannelWidthEQe[i] = self.txt_e.text()
                        self.ChannelWidthMostDownStream[i] = self.txt_douwnstream.text()
                        self.LowerRegionHeight[i] = self.txtLower_Region_Height.text()
                        self.LowerRegionBaseWidth[i] = self.txtLower_Region_Base_Width.text()
                        self.UpperRegionBaseWidth[i] = self.txtUpper_Region_Base_Width.text()
                        self.CompoundCSChannelWidthLimit[i] = self.txtCompound_CSChannel_Width_Limit.text()
                        self.BankSideSlopeRight[i] = self.txtRight_bank.text()
                        self.BankSideSlopeLeft[i] = self.txtLeft_bank.text()
                   
                        if self.rdo_generateCh.isChecked():
                            self.SingleCSChannelWidthType[i]="CWGENERATION"
                        elif self.rdo_useCh.isChecked():
                            self.SingleCSChannelWidthType[i]="CWEQUATION"

                        self.CrossSectionType[i]="CSSingle"
                        if self.chk_compound.isChecked():
                            self.CrossSectionType[i]="CSCOMPOUND"
                            
                MsInfo("Channel setting was updated.")
                
            else:
                MsInfo("Select WSID ")
        except Exception as e:
            MsError(e)

    def ListView_WSID(self, index):
        try:
            CrossSectionType=self.CrossSectionType[index.row()].upper()
            SingleCSChannelWidthType=self.SingleCSChannelWidthType[index.row()].upper()
            if SingleCSChannelWidthType=="CWGENERATION":
                self.rdo_generateCh.setChecked(True)
            elif SingleCSChannelWidthType=="CWEQUATION":
                self.rdo_useCh.setChecked(True)
            else:
                self.rdo_generateCh.setChecked(True)
            if CrossSectionType=="CSSINGLE":
                self.chk_compound.setChecked(False)
            elif CrossSectionType == "CSCOMPOUND":
                self.chk_compound.setChecked(True)
            else:
                self.chk_compound.setChecked(False)

            self.txt_c.setText(self.ChannelWidthEQc[index.row()])
            self.txt_d.setText(self.ChannelWidthEQd[index.row()])
            self.txt_e.setText(self.ChannelWidthEQe[index.row()])
            self.txt_douwnstream.setText(self.ChannelWidthMostDownStream[index.row()])
            self.txtLower_Region_Height.setText(self.LowerRegionHeight[index.row()])
            self.txtLower_Region_Base_Width.setText(self.LowerRegionBaseWidth[index.row()])
            self.txtUpper_Region_Base_Width.setText(self.UpperRegionBaseWidth[index.row()])
            self.txtCompound_CSChannel_Width_Limit.setText(self.CompoundCSChannelWidthLimit[index.row()])
            self.txtRight_bank.setText(self.BankSideSlopeRight[index.row()])
            self.txtLeft_bank.setText(self.BankSideSlopeLeft[index.row()])

            self.txt_douwnstream.setDisabled(True)
            self.ChannelCS_rdo_able()

        except Exception as e:
            MsError(e)

    # Channel CS  --2017/09/08 조
    # 라디오 버튼 클릭 시 활성/비활성 함수
    def ChannelCS_rdo_able(self):
        # 활성 상태
        self.row = self.lisw_WSID.currentRow() 

        # Use channel width equation 활성 상태인 경우
        if self.rdo_useCh.isChecked():
            #2020-04-28 박: 라디오 이벤트로 배열값 변경 처리
            self.txt_douwnstream.setDisabled(True)
            self.txt_c.setDisabled(False)
            self.txt_d.setDisabled(False)
            self.txt_e.setDisabled(False)

        # Use channel width equation 비활성 상태인 경우
        elif self.rdo_generateCh.isChecked():
            self.txt_douwnstream.setDisabled(False)
            self.txt_c.setDisabled(True)
            self.txt_d.setDisabled(True)
            self.txt_e.setDisabled(True)

        # single cross section 라디오 버튼이 비활성 상태 일 때
        if self.chk_compound.isChecked():
            self.groupBox_6.setDisabled(False)
        else:
            self.groupBox_6.setDisabled(True)

    # ----------------- 2017-10-24_오전 박 Watershed Parmeters 탭 텍스트 박스 셋팅 -----------------------------
    def Set_Watershed_Parameter_tab_default(self):
        # Select watershed 콥보 박스 셋팅
        self.Set_Watershed_combo()

        # 함수로 빼야함 급해서 그냥 넣음
        combolist = ['Constant', 'Linear', 'Exponential']
#         combolist = ('Linear','Exponential','Constant')
        self.cmbUnsturatedType.addItems(combolist)
        self.cmbUnsturatedType.currentIndexChanged.connect(self.chage_UnsturatedType)

        ## 최하류 셀값 설정정
        self.Set_MostDownStream()
        self.cb_selectws.currentIndexChanged.connect(self.SelectWsCombobox)
        
        #2020-05-19 박:콤보 박스 셋팅후 각각의 상류 하류 유역 정보가 설정 되지 않아서 호출
        self.SelectWsCombobox()

        self.btnApplyWS.clicked.connect(self.UserSet_Add)
        self.btnRemoveWS.clicked.connect(self.UserSet_remove)
        self.SetWatershedstream()
        #2020-05-19 박:콤보 박스 셋팅후 각각의 상류 하류 유역 정보가 설정 되지 않아서 호출
        self.SelectWsCombobox()


        # 콤보 박스에 유역 설정 하기
    def Set_Watershed_combo(self):
        WS_list = []
        wscount=self._wsinfo.WScount
        AllItem=self._wsinfo.WSIDsAll
        for i in range(wscount):
            WS_list.append(str(AllItem[i]))
        WS_list.sort()

        self.cb_selectws.clear()
        self.cb_selectws.addItems(WS_list)


    def Set_MostDownStream(self):
        if self._SubWatershedCount == 0:
            templist=[]
            if len(self._StreamWSID)>0:
                for id in range (len(self._StreamWSID)):
                    if str(self._StreamWSID[id]) not in templist:
                        self.SetMostDownStream(self._StreamWSID[id])
                        templist.append(str(self._StreamWSID[id]))

    def chage_UnsturatedType(self):
        self.selectText=self.cmbUnsturatedType.currentText()
        
        value = "0.1"
        if self.selectText=="Linear":
            value = "0.2"
        elif self.selectText=="Exponential":
            value = "6.4"
            
        self.txtCoefUnsatruatedk.setText(value)
        self.txtCoefUnsatruatedk.setEnabled(True)

    # 콤보박스 선택시 하류 유역과 상류 유역의 콤보박스에 값 셋팅
    def SelectWsCombobox(self):
        self.project_use_flag = False
        # 2018-01-29 박: Watershed parmeter 함수 호출
        # 하류 유역 정보 셋팅
        selectWS=""
        selectWS=self.cb_selectws.currentText()
        DownSW = []
        Dllresult_Down=self._wsinfo.downStreamWSIDs(int(selectWS))
        Dllresult_Down_count = self._wsinfo.downStreamWSCount(int(selectWS))

        for i in range (Dllresult_Down_count):
            DownSW.append(Dllresult_Down[i])

        if len(DownSW)>0:
            self.lisw_DownWS.clear()
            for i in range(len(DownSW)):
                if DownSW[i]>0:
                    item = QListWidgetItem(str(DownSW[i]))
                    self.lisw_DownWS.addItem(item)
        else:
            self.lisw_DownWS.clear()

        # 상류 유역 정보 셋팅
        UPSW = []
        Dllresult_UP = self._wsinfo.upStreamWSIDs(int(selectWS))
        Dllresult_UP_count = self._wsinfo.upStreamWSCount(int(selectWS))
        for i in range (Dllresult_UP_count):
            UPSW.append(Dllresult_UP[i])

        #UPSW.extend(Dllresult_UP)
        if len(UPSW)>0:
            self.lisw_UpWS.clear()
            for s in range(len(UPSW)):
                if UPSW[s]>0:
                    item1 = QListWidgetItem(str(UPSW[s]))
                    self.lisw_UpWS.addItem(item1)
        else:
            self.lisw_UpWS.clear()

        try:
            #global self._wsinfo
            # 콤보박스에서 받은 내용을 텍스트 박스에 넣는 방법
            iniSaturation = str(self._wsinfo.subwatershedPars(int(selectWS)).iniSaturation)
            minSlopeChBed = str(self._wsinfo.subwatershedPars(int(selectWS)).minSlopeChBed)
            minSlopeOF = str(self._wsinfo.subwatershedPars(int(selectWS)).minSlopeOF)

            # 2018-03-12 박: 화면 수정
            UKType = int(self._wsinfo.subwatershedPars(int(selectWS)).unSatKType)
            coefUK = str(self._wsinfo.subwatershedPars(int(selectWS)).coefUnsaturatedK)
            
            minChBaseWidth = str(self._wsinfo.subwatershedPars(int(selectWS)).minChBaseWidth)
            chRoughness = str(self._wsinfo.subwatershedPars(int(selectWS)).chRoughness)
            dryStreamOrder = str(self._wsinfo.subwatershedPars(int(selectWS)).dryStreamOrder)
            ccLCRoughness = str(self._wsinfo.subwatershedPars(int(selectWS)).ccLCRoughness)
            ccSoilDepth = str(self._wsinfo.subwatershedPars(int(selectWS)).ccSoilDepth)
            ccPorosity = str(self._wsinfo.subwatershedPars(int(selectWS)).ccPorosity)
            ccWFSuctionHead = str(self._wsinfo.subwatershedPars(int(selectWS)).ccWFSuctionHead)
            ccHydraulicK = str(self._wsinfo.subwatershedPars(int(selectWS)).ccHydraulicK)
            iniFlow = str(self._wsinfo.subwatershedPars(int(selectWS)).iniFlow)
            if iniFlow.upper() =="NONE":
                iniFlow ="0"
            self.txtIniSaturation.setText(iniSaturation)
            self.txtMinSlopeOF.setText(minSlopeOF)
            self.txtMinSlopeChBed.setText(minSlopeChBed)
            self.txtMinChBaseWidth.setText(str(minChBaseWidth))
            self.txtIniFlow.setText(str(iniFlow))
            self.txtChRoughness.setText(chRoughness)
            self.txtDryStreamOrder.setText(dryStreamOrder)
            self.txtCalCoefLCRoughness.setText(ccLCRoughness)
            self.txtCalCoefSoilDepth.setText(ccSoilDepth)
            self.txtCalCoefPorosity.setText(ccPorosity)
            self.txtCalCoefWFSuctionHead.setText(ccWFSuctionHead)
            self.txtCalCoefHydraulicK.setText(ccHydraulicK)
            
            self.txtCoefUnsatruatedk.setDisabled(bool(UKType<0 or UKType>2))
            UKType = UKType if 0 <= UKType and UKType < 3 else 1
            self.cmbUnsturatedType.setCurrentIndex(UKType)

            self.txtCoefUnsatruatedk.setText(coefUK)
            
        # 예외가 발생했을때 예외 값을 셋팅
        except Exception as e:
            self.txtIniSaturation.setText("0.9")
            self.txtMinSlopeOF.setText("0.0001")
            self.txtMinSlopeChBed.setText("0.0001")

            intAll = float(self.GridCellSize)
            if intAll>0:
                cal_MinChBaseWidth = intAll/10
            self.txtMinChBaseWidth.setText(str(cal_MinChBaseWidth))
            self.txtIniFlow.setText("0")

            self.cmbUnsturatedType.setCurrentIndex(0)
            self.txtCoefUnsatruatedk.setText('0.2')

            self.txtChRoughness.setText("0.045")
            self.txtDryStreamOrder.setText("0")
            self.txtCalCoefLCRoughness.setText("1")
            self.txtCalCoefSoilDepth.setText("1")
            self.txtCalCoefPorosity.setText("1")
            self.txtCalCoefWFSuctionHead.setText("1")
            self.txtCalCoefHydraulicK.setText("1")
            item1 = QListWidgetItem(str(self._StreamWSID))
            self.lisw_UserSet.addItem(item1)

    def UserSet_Add(self):
        id = int(self.cb_selectws.currentText())
        items = self.lisw_UserSet.findItems(str(id), Qt.MatchExactly)
        if len(items) ==0:
            item1 = QListWidgetItem(str(id))
            self.lisw_UserSet.addItem(item1)

        IniSaturation = self.txtIniSaturation.text()
        MinSlopeOF = self.txtMinSlopeOF.text()
        MinSlopeChBed = self.txtMinSlopeChBed.text()
        IniFlow = self.txtIniFlow.text()

        UnsaturatedKType_int = self.cmbUnsturatedType.currentIndex()

        CoefUnsatruatedk = self.txtCoefUnsatruatedk.text()
        ChRoughness = self.txtChRoughness.text()
        DryStreamOrder = self.txtDryStreamOrder.text()
        CalCoefLCRoughness = self.txtCalCoefLCRoughness.text()
        CalCoefSoilDepth = self.txtCalCoefSoilDepth.text()
        CalCoefPorosity = self.txtCalCoefPorosity.text()
        CalCoefWFSuctionHead = self.txtCalCoefWFSuctionHead.text()
        CalCoefHydraulicK = self.txtCalCoefHydraulicK.text()
        
        MinChBaseWidth = self.txtMinChBaseWidth.text()
        result=self._wsinfo.setOneSWSParsAndUpdateAllSWSUsingNetwork(id, float(IniSaturation), float(MinSlopeOF),int(UnsaturatedKType_int),float(CoefUnsatruatedk),
                                                               float(MinSlopeChBed), float(MinChBaseWidth),
                                                               float(ChRoughness), int(DryStreamOrder),
                                                               float(CalCoefLCRoughness),
                                                               float(CalCoefSoilDepth), float(CalCoefPorosity),
                                                               float(CalCoefWFSuctionHead),
                                                               float(CalCoefHydraulicK),float(IniFlow))
        if result:
            MsInfo("Apply parameter was completed")
        else:
            MsError("Apply parameter was not completed!")
            
    # 사용자 정의 제거 함수
    def UserSet_remove(self):
        id = self.cb_selectws.currentText()
        comboindex = self.cb_selectws.currentIndex()
                    
        if id in self._StreamWSID:
            MsError("Most downstream watershed parameters can not be removed.")
            
        else:
            result=self._wsinfo.removeUserParametersSetting(int(id))
            items = self.lisw_UserSet.findItems(id, Qt.MatchFixedString)
            
            if result and items:
                index = self.lisw_UserSet.row(items[0])
                self.lisw_UserSet.takeItem(index)            
                MsInfo("Remove parameter was completed")        
                
                # 변경된 값을 다시 표출하기. 
                self.SelectWsCombobox()

    def SetWatershedstream(self):
        self.ID = []; self.IniSaturation=[];self.MinSlopeOF=[];self.MinSlopeChBed=[]
        self.MinChBaseWidth=[]; self.ChRoughness=[]; self.DryStreamOrder=[]; self.IniFlow=[]
        self.CalCoefLCRoughness=[]; self.CalCoefPorosity=[]; self.CalCoefWFSuctionHead=[]; self.CalCoefHydraulicK=[]
        self.CalCoefSoilDepth=[];self.UserSet =[]
        self.UnsaturatedKType=[];self.CoefUnsaturatedK=[]
        doc = ET.parse(self.ProjectFile)
        root = doc.getroot()
        # 최하류 유역 Id 값
        try:
            if self._SubWatershedCount == 0:
                intAll = float(self.GridCellSize)
                cal_MinChBaseWidth=0

                if intAll > 0:
                    cal_MinChBaseWidth = intAll / 10
                
                for id in self._StreamWSID:
                    self._wsinfo.setOneSWSParsAndUpdateAllSWSUsingNetwork(
                        int(id), 1, 0.0001, 1, 0.2,
                        0.0001, float(cal_MinChBaseWidth), 0.045, 0, 1,
                        1, 1, 1, 1, 0
                    )
                
                    item1 = QListWidgetItem(str(id))
                    self.lisw_UserSet.addItem(item1)
                    
                return 
                
            xmltoDict = self._xmltodict['GRMProject']['SubWatershedSettings']
            if self._SubWatershedCount==1:
                xmltoDict = [xmltoDict]
            
            for i, watershed in enumerate(xmltoDict):
                self.ID.append(str(watershed['ID']))
                self.IniSaturation.append(watershed['IniSaturation'])
                self.MinSlopeOF.append(watershed['MinSlopeOF'])
                self.MinSlopeChBed.append(watershed['MinSlopeChBed'])
                self.MinChBaseWidth.append(watershed['MinChBaseWidth'])
                self.ChRoughness.append(watershed['ChRoughness'])
                self.DryStreamOrder.append(watershed['DryStreamOrder'])
                self.IniFlow.append(watershed['IniFlow'])

                self.CoefUnsaturatedK.append(watershed['CoefUnsaturatedK'])
                self.CalCoefLCRoughness.append(watershed['CalCoefLCRoughness'])
                self.CalCoefPorosity.append(watershed['CalCoefPorosity'])
                self.CalCoefWFSuctionHead.append(watershed['CalCoefWFSuctionHead'])
                self.CalCoefHydraulicK.append(watershed['CalCoefHydraulicK'])
                self.CalCoefSoilDepth.append(watershed['CalCoefSoilDepth'])
                usersetString = watershed['UserSet']
                self.UserSet.append(usersetString)

                self.UnsaturatedKType.append(watershed['UnsaturatedKType'])
                UnsaturatedKType_int=0
                #2020-05-19 박: 기능 추가
                UnsaturatedKType = self.UnsaturatedKType[i]
                if UnsaturatedKType=="Constant":
                    UnsaturatedKType_int=0
                elif UnsaturatedKType=="Linear":
                    UnsaturatedKType_int=1
                elif UnsaturatedKType=="Exponential":
                    UnsaturatedKType_int=2
                
                #2022.02.09 동 : Userset은 UI에서 사용자가 값을 변경하거나, mostdownstream 값일 경우에 True 값이 적용됨. 
                # Open project시, gmp 파일에 있는 값을 그대로 UI에 출력해야 하나, False인 값들은 dll에서 받아오는 값과 동일해야 정상. 
                # 아니라면 데이터 파일을 의심하거나, gmp 파일의 오류를 의심해야함. 
                if usersetString.upper() == "TRUE" or str(self.ID[i]) in self._StreamWSID:
                    self._wsinfo.setOneSWSParsAndUpdateAllSWSUsingNetwork(int(self.ID[i]),
                                                                           float(self.IniSaturation[i]),
                                                                           float(self.MinSlopeOF[i]),
                                                                           int(UnsaturatedKType_int),
                                                                           float(self.CoefUnsaturatedK[i]),
                                                                           float(self.MinSlopeChBed[i]),
                                                                           float(self.MinChBaseWidth[i]),
                                                                           float(self.ChRoughness[i]),
                                                                           int(self.DryStreamOrder[i]),
                                                                           float(self.CalCoefLCRoughness[i]),
                                                                           float(self.CalCoefSoilDepth[i]),
                                                                           float(self.CalCoefPorosity[i]),
                                                                           float(self.CalCoefWFSuctionHead[i]),
                                                                           float(self.CalCoefHydraulicK[i]),
                                                                           float(self.IniFlow[i]))

                    item1 = QListWidgetItem(str(self.ID[i]))
                    self.lisw_UserSet.addItem(item1)
                    
        except Exception as esd:
            MsError(esd)

    def SetMostDownStream_combobox(self):
        count = self.cb_selectws.count()
        for i in range(0, count):
            selectWS=self.cb_selectws.itemText(i)

            # 2018-07-24 박: 기존 소스
            # 목록중에 최하류 셀값 자동으로 선택하게 하는 기능
            # 그래서 리스트 목록중에 0번째 있는 목록을 자동으로 선택하게 하였음
            if str(selectWS) ==str(self._StreamWSID[0]):
                self.cb_selectws.setCurrentIndex(i)
                return


 # ============================ Flow Control 탭 시작 ===============================================
    def Set_FlowControl_tab_default(self):
        try:
            # 테이블 셀값을 변경 불가능 하게 설정
            self.tlbFlowControl.setEditTriggers(QAbstractItemView.NoEditTriggers)
            # 테이블에 초기 셋팅
            self.FlowControlTableSetting()
            # 테이블에 값 셋팅후 화면에 점 표시
            self.FlowContorGird_paint()
            self.btnFlowControl_AddCell.clicked.connect(self.FlowControlAddCell)
            self.btnFWCEdit.clicked.connect(self.FlowControlEdit)
            self.tlbFlowControl.itemClicked.connect(self.tlbFlowControl_clik_enent)
            self.btnFlowRemove.clicked.connect(self.RemoveTalbeRow)
#             self.btnfcgotogrid.clicked.connect(self.btnFCGotoGrid)
            self.btnfcgotogrid.clicked.connect(lambda: self.btnGotoGrid(self.tlbFlowControl))
            
        except Exception as e:
            MsError(e)


    # Flow control 테이블 셋팅
    # 프로젝트 파일에서 데이터 값이 있으면 테이블에 값을 셋팅
    def FlowControlTableSetting(self):
        try:
            self.tlbFlowControl.setColumnCount(len(self.flowEle))
            self.tlbFlowControl.setHorizontalHeaderLabels(self.flowEle)
            self.tlbFlowControl.verticalHeader().hide()
            pro_file=self._xmltodict['GRMProject']['ProjectSettings']['ProjectFile']

            if self._Flowcontrolgrid_flag == False:
                self._FlowControlCount = self._FlowControlCount
            
            if self._FlowControlCount<1:
                return 
            
            flowGrid = self._xmltodict['GRMProject']['FlowControlGrid']
            if self._FlowControlCount == 1:
                flowGrid = [flowGrid]
                
            for i, flowItem in enumerate(flowGrid):
                self.tlbFlowControl.insertRow(i)
                for j, t in enumerate(self.flowEle):
                    s = ""
                    if (t in flowItem) and (flowItem[t]!="ReservoirOperation" or j!=5):
                        s = flowItem[t]
                    self.tlbFlowControl.setItem(i, j, QTableWidgetItem(s))
            
        except Exception as e: 
            MsError(e)

    # 사용자 추가 입력창 화면
    def FlowControlAddCell(self):
        if self.tool._FXCOL==0 and self.tool._FYROW==0 :
            self._FXCOL=0
            self._FYROW=0
            MsInfo(" No cells selected. ")
        else:
            self._FXCOL=self.tool._FXCOL
            self._FYROW=self.tool._FYROW
            self._AddFlowcontrol_Edit_or_Insert_type = "Insert"
            results = AddFlowControl(self._AddFlowcontrol_Edit_or_Insert_type, _DataTimeFormat=self.dataTimeFormat)
            results.exec_()

            self._AddFlowcontrolFilePath             =	results._AddFlowcontrolFilePath 
            self._AddFlowcontrolType                 =	results._AddFlowcontrolType 
            self._AddFlowcontrolTimeInterval         =	results._AddFlowcontrolTimeInterval 
            self._AddFlowcontrolName                 =	results._AddFlowcontrolName 
            self._AddFlowcontrol_Edit_or_Insert_type =	results._AddFlowcontrol_Edit_or_Insert_type 
            self._AddFlowcontrol_IniStorage          =	results._AddFlowcontrol_IniStorage 
            self._AddFlowcontrol_MaxStorage          =	results._AddFlowcontrol_MaxStorage
            self._AddNomalHighStorage                =  results._AddNomalHighStorage
            self._AddRestrictedStorage               =  results._AddRestrictedStorage
            self._AddRetiPeriodSt                    =  results._AddRetiPeriodSt
            self._AddRetiPeriodEd                    =  results._AddRetiPeriodEd
            self._AddFlowcontrol_ROType              =	results._AddFlowcontrol_ROType
            self._AddFlowcontrol_ROConstQ            =	results._AddFlowcontrol_ROConstQ
            self._AddFlowcontrol_ROConstQDuration    =  results._AddFlowcontrol_ROConstQDuration
            self._EditFlowFlowDataFile               =  results._EditFlowFlowDataFile 
            
            if self._Flowcontrolgrid_flag :
                if self._AddFlowcontrol_Edit_or_Insert_type=="Insert":
                    self.ADDFlowData()
                    self._Flowcontrolgrid_flag_Insert = False


    def ADDFlowData(self):
        try:
            counts=self.tlbFlowControl.rowCount()
            if self._FXCOL!=0 and self._FYROW!=0:
                self.tlbFlowControl.insertRow(counts)
                self.tlbFlowControl.setItem(counts,0, QTableWidgetItem(self._AddFlowcontrolName))
                self.tlbFlowControl.setItem(counts,1, QTableWidgetItem(str(self._FYROW)))
                self.tlbFlowControl.setItem(counts,2, QTableWidgetItem(str(self._FXCOL)))

                self._FXCOL=0
                self._FYROW=0
                self.tlbFlowControl.setItem(counts,3, QTableWidgetItem(self._AddFlowcontrolTimeInterval))
                self.tlbFlowControl.setItem(counts,4, QTableWidgetItem(self._AddFlowcontrolType))
                self.tlbFlowControl.setItem(counts,5, QTableWidgetItem(self._AddFlowcontrolFilePath))
                self.tlbFlowControl.setItem(counts,6, QTableWidgetItem(self._AddFlowcontrol_IniStorage))
                self.tlbFlowControl.setItem(counts,7, QTableWidgetItem(self._AddFlowcontrol_MaxStorage))
                self.tlbFlowControl.setItem(counts,8, QTableWidgetItem(self._AddNomalHighStorage))
                self.tlbFlowControl.setItem(counts,9, QTableWidgetItem(self._AddRestrictedStorage))
                self.tlbFlowControl.setItem(counts,10, QTableWidgetItem(self._AddRetiPeriodSt))
                self.tlbFlowControl.setItem(counts,11, QTableWidgetItem(self._AddRetiPeriodEd))
                self.tlbFlowControl.setItem(counts,12, QTableWidgetItem(self._AddFlowcontrol_ROType))
                self.tlbFlowControl.setItem(counts,13, QTableWidgetItem(self._AddFlowcontrol_ROConstQ))
                self.tlbFlowControl.setItem(counts,14, QTableWidgetItem(self._AddFlowcontrol_ROConstQDuration))

            self._Flowcontrolgrid_flag = True
            self.UpdateFlowControl()

            # 테이블에 값 셋팅후 화면에 점 표시
            if self.chkFlowContorGird.isChecked():
                self.FlowContorGird_paint()
        except Exception as e:
            MsError(e)

    def FlowControlEdit(self):
        self._FlowControlTable = self.tlbFlowControl
        row = self.tlbFlowControl.currentRow()
        self._EditFlowCurrentRow = row
        if row>-1:
            self._EditFlowName = self.tlbFlowControl.item(row, 0).text()
            self._EditFlowColX = self.tlbFlowControl.item(row, 1).text()
            self._EditFlowRowY = self.tlbFlowControl.item(row, 2).text()
            self._EditFlowDT = self.tlbFlowControl.item(row, 3).text()
            self._EditFlowControlType = self.tlbFlowControl.item(row, 4).text()
            self._EditFlowFlowDataFile = self.tlbFlowControl.item(row, 5).text()
            self._EditFlowIniStorage = self.tlbFlowControl.item(row, 6).text()
            self._EditFlowMaxStorage = self.tlbFlowControl.item(row, 7).text()
            self._EditNomalHighStorage = self.tlbFlowControl.item(row, 8).text()
            self._EditRestrictedStorage = self.tlbFlowControl.item(row, 9).text()
            self._EditRetiPeriodSt = self.tlbFlowControl.item(row, 10).text()
            self._EditRetiPeriodEd = self.tlbFlowControl.item(row, 11).text()
            self._EditFlowROType = self.tlbFlowControl.item(row, 12).text()
            self._EditFlowROConstQ = self.tlbFlowControl.item(row, 13).text()
            self._EditFlowROConstQDuration = self.tlbFlowControl.item(row, 14).text()

            self.flowEle
            self._AddFlowcontrol_Edit_or_Insert_type = "Edit"
            self._FlowControlCount=self._FlowControlCount
            results = AddFlowControl(
                self._AddFlowcontrol_Edit_or_Insert_type,
                self._EditFlowName,
                self._EditFlowDT,
                self._EditFlowControlType,
                self._EditFlowFlowDataFile,
                self._EditFlowIniStorage,
                self._EditFlowMaxStorage,
                self._EditNomalHighStorage,
                self._EditRestrictedStorage,
                self._EditRetiPeriodSt,
                self._EditRetiPeriodEd,
                self._EditFlowROType,
                self._EditFlowROConstQ,
                self._EditFlowROConstQDuration,
                self.dataTimeFormat)
            results.exec_()

            self._FlowControlTable.setItem(row, 0, QTableWidgetItem(results._EditFlowName))
            self._FlowControlTable.setItem(row, 3, QTableWidgetItem(results._EditFlowDT))
            self._FlowControlTable.setItem(row, 4, QTableWidgetItem(results._EditFlowControlType))
            self._FlowControlTable.setItem(row, 5, QTableWidgetItem(results._EditFlowFlowDataFile))
            self._FlowControlTable.setItem(row, 6, QTableWidgetItem(results._EditFlowIniStorage))
            self._FlowControlTable.setItem(row, 7, QTableWidgetItem(results._EditFlowMaxStorage))
            self._FlowControlTable.setItem(row, 8, QTableWidgetItem(results._EditNomalHighStorage))
            self._FlowControlTable.setItem(row, 9, QTableWidgetItem(results._EditRestrictedStorage))
            self._FlowControlTable.setItem(row, 10, QTableWidgetItem(results._EditRetiPeriodSt))
            self._FlowControlTable.setItem(row, 11, QTableWidgetItem(results._EditRetiPeriodEd))
            self._FlowControlTable.setItem(row, 12, QTableWidgetItem(results._EditFlowROType))
            self._FlowControlTable.setItem(row, 13, QTableWidgetItem(results._EditFlowROConstQ))
            self._FlowControlTable.setItem(row, 14, QTableWidgetItem(results._EditFlowROConstQDuration))
           
            self.UpdateFlowControl()
            
        else:
            MsInfo("Check! select row ")
    
    def UpdateFlowControl(self):
        # 딕셔너리 삭제
        if self._FlowControlCount>0:
            del self._xmltodict['GRMProject']['FlowControlGrid']
        DictoXml = unparse(self._xmltodict)

        ET.register_namespace('', "http://tempuri.org/GRMProject.xsd")
        xmltree = ET.ElementTree(ET.fromstring(DictoXml))
        root = xmltree.getroot()
        count = self.tlbFlowControl.rowCount()
        self._FlowControlCount = count
        
        for row in range(0, self._FlowControlCount):
            child = ET.Element("FlowControlGrid")
            root.append(child)
        
            for i in range(len(self.flowEle)):
                element = ET.Element(self.flowEle[i])
                item = self.tlbFlowControl.item(row, i)
                element.text = item.text() if item else ""
                child.append(element)
        
        xmltree_string = ET.tostring(xmltree.getroot())
        docs = dict(parse(xmltree_string))
        self._xmltodict.clear()
        self._xmltodict.update(docs)

            
    def tlbFlowControl_clik_enent(self):
        global _ClickX,_ClickY
        row=self.tlbFlowControl.currentRow()
        _ClickX = self.tlbFlowControl.item(row, 1).text()
        _ClickY = self.tlbFlowControl.item(row, 2).text()


    def RemoveTalbeRow(self):
        row = self.tlbFlowControl.currentIndex().row()
        # 선택된 Row 가 있을때
        if row > -1:
            mess = "Are you sure you want to delete the selected items?"
            result = QMessageBox.question(None, "Flow Control Grid", mess, QMessageBox.Yes, QMessageBox.No)
            if result == QMessageBox.Yes:
                # 사용자가 한번이라도 수정한 사항이 있으면 플래그값 True 로 변경하여 사용자 수정
                _Flowcontrolgrid_flag =True
                self.tlbFlowControl.removeRow(row)
                
                self.UpdateFlowControl()
                # 테이블에 값 셋팅후 화면에 점 표시

                self.post_grid_remove2()
                self.FlowContorGird_paint()
                if self.chkWatch_Point.isChecked():
                    self.watchpoint_paint()

    #2. xy좌표로
    def xy_grid(self,layer,xcoord,ycoord):
        try:
            xc=float(xcoord); yc=float(ycoord)
            row = int(((self._ymax - yc) / self._ysize))
            column = int(((xc - self._xmin) / self._xsize))
            self.lblColRow.setText("xCol, yRow:" + str(column) + " , " + str(row))
            if row < 0 or column < 0 or self._height<=column or self._width <= row :
                row = "out of extent"
                column="out of extent"
                MsInfo( "{0}, {1}".format(str(column), str(row)))
            else:
                self.tool.Cell_X_Center = self._xmin + self._xsize/2 + self._xsize * (column)
                self.tool.Cell_Y_Center = self._ymax -  self._ysize/2 -  self._ysize * (row) #(extent.yMinimum())
                if self.tool.Cell_X_Center<= self._xmax or self._xmin<=self.tool.Cell_X_Center or self.tool.Cell_Y_Center<=self._ymax or self._ymin<=self.tool.Cell_Y_Center:
                    self.draw_grid(self.tool.Cell_X_Center,self.tool.Cell_Y_Center)
        except Exception as e:
            MsError(e)

class CanvasTool(QgsMapTool):
    def __init__(self, canvas):
        QgsMapTool.__init__(self, canvas)
        self.canvas = canvas
        self.layer = self.canvas.layers()[0]
        self._wsinfo=_GSC.get_wsinfo()
        self._GreenAmptCount=_GSC.get_GreenAmptCount()
        self._xmltodict = _GSC.get_xmltodict()
        self._SoilDepthCount=_GSC.get_SoilDepthCount()
        self._LandCoverCount =_GSC.get_LandCoverCount()
        self._FYROW =0
        self._YROW  =0
        self._FXCOL =0 
        self._XCOL  =0 

        self._width = self.layer.width()
        self._height = self.layer.height()
        self._xsize = self.layer.rasterUnitsPerPixelX()
        self._ysize = self.layer.rasterUnitsPerPixelY()
        self._extent = self.layer.extent()
        self._ymax = self._extent.yMaximum()
        self._ymin = self._extent.yMinimum()
        self._xmax = self._extent.xMaximum()
        self._xmin = self._extent.xMinimum()
        self.Cell_X_Center=0
        self.Cell_Y_Center=0

    def scale_changed(self):
        self.canvas.scaleChanged.connect(self.scale_change_marker)

    def scale_changed_disconnect(self):
        try:
            self.canvas.scaleChanged.disconnect(self.scale_change_marker)
        except:
            pass
        
     #canvas scale이 변화할 때  marker를 새로 그림
    def scale_change_marker(self):
        if self.Cell_X_Center!=0 and self.Cell_Y_Center!=0:
            self.post_vertex_remove()
            self.create_vertex(self.Cell_X_Center,self.Cell_Y_Center)

     #이전에 생성한 vertexMaker제거 함
    def post_vertex_remove(self):
        for v in self.canvas.scene().items():
            if issubclass(type(v), QgsVertexMarker):
                self.canvas.scene().removeItem(v)

    def create_vertex(self,x,y):
        marker = QgsVertexMarker(self.canvas)
        marker.setCenter(QgsPointXY(x, y))
        marker.setColor(QColor(255, 0, 0))
        width_Map = self.canvas.extent().xMaximum() - self.canvas.extent().xMinimum()
        Size_Marker = (self._xsize / 150.0) * 100000 / width_Map
        marker.setIconSize(Size_Marker)
        marker.setIconType(QgsVertexMarker.ICON_BOX)
        marker.setPenWidth(1)

    def getCVID(self, Rt, Ct):
        cvid_v = 0
        for c in range(self._width):
            for r in range(Ct):
                xxx = c * self._xsize + self._xmin
                yyy = self._ymax - r * self._ysize
                ident = self.layer.dataProvider().identify(QgsPointXY(xxx, yyy), QgsRaster.IdentifyFormatValue)
                
                #2020-01-28 박: 변경은 했으나 맞는지 확인이 안됨
                if ident.results()[1]!=None and ident.results()[1]>0:
                  cvid_v = (cvid_v+1 )

        cvid = 0
        for cs in range(Rt+ 1):
            for rs in range(Ct,Ct+1):
                xxx = cs * self._xsize + self._xmin
                yyy = self._ymax - rs * self._ysize
                ident = self.layer.dataProvider().identify(QgsPointXY(xxx, yyy), QgsRaster.IdentifyFormatValue)
                
                #2020-01-28 박: 변경은 했으나 맞는지 확인이 안됨
                if ident.results()[1]!=None and ident.results()[1]>0:
                    cvid = (cvid + 1)
        return cvid_v + cvid


     # 캔버스 클릭 이벤트 좌표 출력
    def canvasPressEvent(self, event):
        xx = event.pos().x()
        yy = event.pos().y()

        point = self.canvas.getCoordinateTransform().toMapCoordinates(xx,yy)
        if self.layer is not None:
            row ,column  = self.Point_To_RowColumn(point)
            _CVID = "Cvid: " + str(self.getCVID(row, column))
            self._XCOL =  column
            self._YROW = row

            self._FYROW =self._YROW
            self._FXCOL= self._XCOL
            text = "xCol, yRow: " + str(row) + " , " + str(column)

            #2020-01-28 박: 텍스트 박스 객체 넘기는게 되는지 모르겠음
            _GSC.GlobalLabel_SetText(text)

            self.Input_Cell_Value(row, column)
            if row < 0 or column < 0 or self._height<=column or self._width <= row :
                row = "out of extent"
                column="out of extent"

            else:
                self.Cell_X_Center = self._extent.xMinimum()+ self._xsize/2 + self._xsize * (row)
                self.Cell_Y_Center = self._ymax -  self._ysize/2 -  self._ysize * (column)

                FAc_ident = self.layer.dataProvider().identify(QgsPointXY(self.Cell_X_Center, self.Cell_Y_Center), QgsRaster.IdentifyFormatValue)
                cw_text = self.channel_width_cal(FAc_ident.results()[1])

                self._Cnavas_Click_X =self.Cell_X_Center; self._Cnavas_Click_Y =self.Cell_Y_Center
                if self.Cell_X_Center<= self._xmax or self._xmin<=self.Cell_X_Center or self.Cell_Y_Center<=self._ymax or self._ymin<=self.Cell_Y_Center:
                    self.post_vertex_remove()
                    self.create_vertex(self.Cell_X_Center,self.Cell_Y_Center)

        else:
            row = "no raster"
            column = "no raster"
            MsInfo("{0}, {1}".format(str(row),str(column)))


    def Input_Cell_Value(self,x,y):
        # Cell Info Flow 그룹 박스 데이터 내용
        CellCount = self._wsinfo.cellCountInWatershed
        CellType_Result=self._wsinfo.cellFlowTypeACell(x,y)
        Stream_Result = self._wsinfo.streamValue(x,y)
        FD_Result = self._wsinfo.flowDirection(x, y)
        FA_Result = self._wsinfo.flowAccumulation(x,y)
        Slop_Result = self._wsinfo.slope(x,y)
        watershed = self._wsinfo.watershedID(x,y)

        _GSC.GlobalControl_SetValue(str(CellCount),str(CellType_Result.decode("utf-8")),str(Stream_Result), FD_Result.decode("utf-8") , str(FA_Result), str(Slop_Result),str(watershed))

        Texture_Result=self._wsinfo.soilTextureValue(x,y)

        # Cell Info Depth 그룹 박스 테이터 내용
        Depth_Result = self._wsinfo.soilDepthValue(x,y)

        # Cell Info Landcover 그룹 박스 테이터 내용
        Landcover_Result = self._wsinfo.landCoverValue(x,y)


        # 메모리에서 불러오는 것으로 변경 해야함 우선은 진행
        if self._GreenAmptCount >1:
            for GreenAmpt in self._xmltodict['GRMProject']['GreenAmptParameter']:
                GridValue = GreenAmpt['GridValue']
                if str(Texture_Result) == GridValue:
                    GRMCode = GreenAmpt['GRMCode']
                    Porosity = GreenAmpt['Porosity']
                    EffectivePorosity = GreenAmpt['EffectivePorosity']
                    WFSoilSuctionHead = GreenAmpt['WFSoilSuctionHead']
                    HydraulicConductivity = GreenAmpt['HydraulicConductivity']
                    _GSC.GlobalControl_texture_SetValue(GridValue,GRMCode, Porosity, EffectivePorosity,WFSoilSuctionHead,HydraulicConductivity)
                    break
                elif Texture_Result is None or Texture_Result=="":
                    break
        elif self._GreenAmptCount ==1:
            GridValue = self._xmltodict['GRMProject']['GreenAmptParameter']['GridValue']
            if str(Texture_Result) == GridValue:
                GRMCode = self._xmltodict['GRMProject']['GreenAmptParameter']['GRMCode']
                Porosity = self._xmltodict['GRMProject']['GreenAmptParameter']['Porosity']
                EffectivePorosity = self._xmltodict['GRMProject']['GreenAmptParameter']['EffectivePorosity']
                WFSoilSuctionHead = self._xmltodict['GRMProject']['GreenAmptParameter']['WFSoilSuctionHead']
                HydraulicConductivity = self._xmltodict['GRMProject']['GreenAmptParameter']['HydraulicConductivity']
                _GSC.GlobalControl_texture_SetValue(GridValue, GRMCode, Porosity, EffectivePorosity, WFSoilSuctionHead,HydraulicConductivity)
        

        if self._SoilDepthCount>1:
            for SoilDepth in self._xmltodict['GRMProject']['SoilDepth']:
                GridValue = SoilDepth['GridValue']
                if str(Depth_Result) == GridValue:
                    GRMCode = SoilDepth['GRMCode']
                    #2020-05-27 박: 변경됨
                    SoilDepth=SoilDepth['SoilDepth_cm']
                    _GSC.GlobalControl_Depth_SetValue(GridValue, GRMCode, SoilDepth)
                    break
                elif Depth_Result is None or Depth_Result=="":
                    break

        elif self._SoilDepthCount==1:
            GridValue = self._xmltodict['GRMProject']['SoilDepth']['GridValue']
            if str(Depth_Result) == GridValue:
                GRMCode =  self._xmltodict['GRMProject']['SoilDepth']['GRMCode']
                SoilDepth =  self._xmltodict['GRMProject']['SoilDepth']['SoilDepth_cm']
                _GSC.GlobalControl_Depth_SetValue(GridValue, GRMCode, SoilDepth)

        if self._LandCoverCount>1:
            for LandCover in self._xmltodict['GRMProject']['LandCover']:
                GridValue = LandCover['GridValue']
                if str(Landcover_Result) == GridValue:
                    GRMCode = LandCover['GRMCode']
                    RoughnessCoefficient = LandCover['RoughnessCoefficient']
                    ImperviousRatio = LandCover['ImperviousRatio']
                    _GSC.GlobalControl_Landcover_SetValue(GridValue,GRMCode,RoughnessCoefficient,ImperviousRatio)
                    break
                elif Landcover_Result is None or Landcover_Result == "":
                    break

        elif self._LandCoverCount==1:
            GridValue = self._xmltodict['GRMProject']['LandCover']['GridValue']
            if str(Depth_Result) == GridValue:
                GRMCode = self._xmltodict['GRMProject']['LandCover']['GRMCode']
                RoughnessCoefficient = self._xmltodict['GRMProject']['LandCover']['RoughnessCoefficient']
                ImperviousRatio = self._xmltodict['GRMProject']['LandCover']['ImperviousRatio']
                _GSC.GlobalControl_Landcover_SetValue(GridValue, GRMCode, RoughnessCoefficient, ImperviousRatio)


    def Point_To_RowColumn(self,point):
        column = int(((self._ymax - point.y()) / self._ysize))
        row = int(((point.x() - self._xmin) / self._xsize))
        return row,column

    def canvasMoveEvent(self, event):
        x = event.pos().x()
        y = event.pos().y()
        point = self.canvas.getCoordinateTransform().toMapCoordinates(x, y)


    def canvasReleaseEvent(self, event):
        #Get the click
        x = event.pos().x()
        y = event.pos().y()
        point = self.canvas.getCoordinateTransform().toMapCoordinates(x, y)


    def activate(self):
        pass

    def deactivate(self):
        pass

    def isZoomTool(self):
        return False

    def isTransient(self):
        return False

    def isEditTool(self):
        return True

    # canvas event
    def ZoomtoExtent(self):
        self.canvas.zoomToFullExtent()
        self.canvas.refresh()

    def ZoomtoNextExtent(self):
        self.canvas.zoomToNextExtent()
        self.canvas.refresh()

    def ZoomtoPrevious(self):
        self.canvas.zoomToPreviousExtent()
        self.canvas.refresh()

    def canvas_zoomIn(self):
        actionZoomIn = QAction(self)
        self.toolZoomIn = QgsMapToolZoom(self.canvas, False)  # false = in
        self.toolZoomIn.setAction(actionZoomIn)
        self.canvas.setMapTool(self.toolZoomIn)
        self.canvas.refresh()

    def canvas_zoomOut(self):
        actionZoomOut = QAction(self)
        self.toolZoomOut = QgsMapToolZoom(self.canvas, True)  # True = out
        self.toolZoomOut.setAction(actionZoomOut)
        self.canvas.setMapTool(self.toolZoomOut)
        self.canvas.refresh()

    def canvas_pan(self):
        actionPan = QAction(self)
        self.toolPan = QgsMapToolPan(self.canvas)
        self.toolPan.setAction(actionPan)
        self.canvas.setMapTool(self.toolPan)
#
#     #2017/11/23----------------------
    def channel_width_cal(self,FAcvalue):
         #mw에서는 line edit 값을 바꿀 수 있고 그에 따라 결과 값이 바뀜. 일단 여기는 이렇세 처리함
        c = float(1.698)
        d = float(0.318)
        e = float(0.5)

        #FAc 는 cell 값, Slope는 gmp의 MinSlopeChBed 값임
        slope = float(0.0005)

        width = c * pow(( FAcvalue * (self._xsize * self._xsize / 1000000)) , d) / pow(slope, e)
        try:
            User_Cw = '%.3f'%width
        except Exception as e:
            return "0"
        return str(User_Cw)
