#---------------------------------------------------------------------------
# (c) Christophe MASSE 2013 - 2032
# revision code : 15-05-2024
# CLASS uiAutoLoaderRasterPlugin - AUTOLOADERRASTER PLUGIN
#---------------------------------------------------------------------------

from qgis.PyQt.QtCore import (QCoreApplication, QEvent, QFileInfo, QItemSelectionModel, QLocale, QObject, QSettings, QSize, QSizeF, Qt, QTimer, QTranslator)
from qgis.PyQt.QtWidgets import (QAbstractItemView, QAction, QActionGroup, QApplication, QButtonGroup, QCheckBox, QComboBox, QDialog, QDialogButtonBox, QDockWidget, QFileDialog,
                                 QGroupBox, QInputDialog, QLabel, QLineEdit, QListView, QListWidget, QListWidgetItem, QMdiSubWindow, QMenu, QMessageBox, QProgressBar, QProxyStyle,
                                 QPushButton, QSizePolicy, QSlider, QStyle, QTableView, QTabWidget, QTextEdit, QToolTip, QVBoxLayout, QWidgetAction)

from qgis.PyQt.QtGui import (QBrush, QColor, QCursor, QIcon, QImage, QKeySequence, QPainter, QPixmap, QStandardItem, QStandardItemModel, QTextDocument)
from qgis.PyQt.QtPrintSupport import (QPrintPreviewDialog, QPrinter)

from qgis.core import (QgsApplication, Qgis, QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsFeature, QgsFeatureRequest, QgsGeometry, QgsLayerTreeGroup, QgsLayerTreeLayer, 
                       QgsLayerTreeModel, QgsMapLayer, QgsPointXY, QgsProject, QgsRasterLayer, QgsRectangle, QgsSpatialIndex, QgsStyle, QgsVectorLayer)

from qgis.core import (QgsExpression, QgsExpressionContext, QgsExpressionContextScope, QgsMapLayerProxyModel)
from qgis.gui import (QgsColorButton, QgsColorWheel, QgsExpressionBuilderDialog, QgsMapLayerComboBox, QgsProjectionSelectionWidget, QgsRendererPropertiesDialog, QgsRendererRasterPropertiesWidget)

from qgis.gui import (QgsCollapsibleGroupBox, QgsLayerTreeMapCanvasBridge, QgsLayerTreeView, QgsMapCanvas, QgsMapCanvasItem, QgsMapTool, QgsMapToolPan,
                      QgsMapToolZoom, QgsRubberBand)
from qgis.utils import pluginMetadata

from os import walk
from os.path import (basename, dirname, exists, isfile, join, relpath, splitext) 
from xml.etree import ElementTree as etree

from autoLoaderRaster.ui_about import ui_About
from autoLoaderRaster.ui_autoLoaderRasterGrid import ui_gridRasterMaker
from autoLoaderRaster.ui_doubleFocusGlasses import uiDoubleFocusGlassesPlugin

from autoLoaderRaster.utils import (changeButtonIcon, cleanPath, cleanUri, dicoHasKey, fixeLabelsFileDialog, funnyPushButton, getExtension, getThemeIcon, iff, labeller,
                                    legendTreeWidget, makeListFormatsExtensions, myListWidget, myMenuStyle, myPushButton, prettifyXml, printerDlg, textEdit,
                                    translateMsg, windowIcon, wizardData, zoomNextExtent, zoomPreviousExtent) #NEW 3.6.4

from configparser import ConfigParser
from datetime import datetime as thedatetime
from math import pi,sin,cos,sqrt
from webbrowser import open as webbrowseropen

#NEW 3.4.0
from ast import literal_eval
from pathlib import Path as xPath

try: from osgeo import gdal
except : import gdal

import re
import shutil
import sys
import time

import urllib.parse as urlparse

if sys.version_info[:2] >= (3, 4): from importlib import reload
else: from imp import reload


#NEW 3.4.0
class myProxyStyle(QProxyStyle):
    pass
    def pixelMetric(self, QStyle_PixelMetric, option=None, widget=None):
        if QStyle_PixelMetric == QStyle.PixelMetric.PM_SmallIconSize: return  32 
        else : return QProxyStyle.pixelMetric(self, QStyle_PixelMetric, option, widget)

class autoLoaderRasterPlugin(object):
 
  def __init__(self, iface):
    self.name = "autoLoaderRasterPlugin"
    self.version = pluginMetadata(basename(dirname(__file__)),'version')
    self.dateVersion = pluginMetadata(basename(dirname(__file__)),'dateVersion')
    self.iface = iface
    self.canvas = self.iface.mapCanvas()
    self.settings = 'Plugin-autoLoaderRasterPlugin/'


    overrideLocale = QSettings().value("locale/overrideFlag", False)
    localeFullName = QLocale.system().name() if not overrideLocale else QSettings().value("locale/userLocale", "")
    self.localLangage = localeFullName[0:2]
    self.localePath = "%s/i18n/autoLoaderRaster_%s.qm" % (dirname(__file__), self.localLangage)
    self.localeFullName = localeFullName
    self.translator = QTranslator()

    if QFileInfo(self.localePath).exists():
       self.translator.load(self.localePath)
       QCoreApplication.installTranslator(self.translator)

    reload(sys)
    try : sys.setdefaultencoding('iso-8859-1')
    except : pass

    self.dlgAutoLoaderRasterPlugin = None

    self.imgNodeExpanded = getThemeIcon("nodes_expand.png").replace("\\","/")

    self.styleComboBox = """
      QComboBox { border-style: outset; border-radius: 3px; padding: 1px 18px 1px 3px;  }
      QComboBox:editable {  background-color: white;}
      QComboBox:!editable, QComboBox::drop-down:editable { background-color: rgba(255, 255, 255, 50); color : black; border-left-width: 1px; border-left-color: black; border-left-style: solid; border-top-right-radius: 3px; border-right-color: black;}
      QComboBox:!editable:on, QComboBox::drop-down:editable:on { background-color: rgba(75, 75, 75, 75); color : black;}
      QComboBox:on { padding-top: 3px; padding-left: 4px; }
      QComboBox::drop-down {subcontrol-origin: padding; subcontrol-position: top right; width: 15px; border-left-width: 1px; border-left-color: darkgray; border-left-style: solid; border-top-right-radius: 3px; border-bottom-right-radius: 3px;}
      QComboBox::down-arrow { image: url(%s); }
      QComboBox::down-arrow:on {top: 1px; left: 1px; }
    """ % self.imgNodeExpanded

    self.styleErrorComboBox = """
      QComboBox {  background-color: red; border-style: outset; border-radius: 3px; padding: 1px 18px 1px 3px;  }
      QComboBox::down-arrow { image: url(%s); }
      QComboBox::down-arrow:on {top: 1px; left: 1px; }
    """ % self.imgNodeExpanded

    self.setGrpRdi() 

  def setGrpRdi(self):
      s = QSettings()
      s.setValue("%sgrpRdi" % self.settings, "")

  def initGui(self):
    self.menu = QMenu(translateMsg("Dynamic grid raster loader"))
    self.menu.setObjectName("mautoLoaderRasterPlugin")
    self.menu.setIcon(QIcon(getThemeIcon("catchraster.png")))

    #NEW 3.4.0
    self.barInfo = self.iface.messageBar() 
    self.barInfo.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed)

    self.actionReloadGrids = QAction(QIcon(getThemeIcon("reload.png")), "%s" % translateMsg("Reload grid file"), self.iface.mainWindow())
    self.actionReloadGrids.setObjectName("actionReloadGrids")
    self.actionReloadGrids.setShortcut(QKeySequence("SHIFT+R"))

    self.actionCheckGrids = QAction(QIcon(getThemeIcon("checked.png")), "%s" % translateMsg("Check the grids"), self.iface.mainWindow())
    self.actionCheckGrids.setObjectName("actionCheckGrids")
    self.actionCheckGrids.setShortcut(QKeySequence("SHIFT+C"))

    #NEW 3.4.0
    self.actionParameters = QAction(QIcon(getThemeIcon("parameters_False.png")), "%s %s" % (translateMsg("Show"), translateMsg("the control panel")), self.iface.mainWindow())
    self.actionParameters.setObjectName("actionParameters")      

    icon = getThemeIcon("makegrid_off.png")
    self.actionMakeRasterGrid = QAction(QIcon(icon), "%s ..." % translateMsg("Tool to make grid with raster files"), self.iface.mainWindow())
    self.actionMakeRasterGrid.setObjectName("mActionMakeRasterGrid")    


    icon = getThemeIcon("uncheckdoubleglasses.png")
    self.actionDoubleGlasses = QAction(QIcon(icon), "%s" % translateMsg("Show or Hide double Focus Glasses"), self.iface.mainWindow())
    self.actionDoubleGlasses.setObjectName("mActionDoubleGlasses")
    self.actionDoubleGlasses.setCheckable(True)

    icon = getThemeIcon("services000.png")
    self.actionServices = QAction(QIcon(icon), "%s ..." % translateMsg("Services"),self.iface.mainWindow())
    self.actionServices.setObjectName("mActionServices")

    icon = getThemeIcon("help.png")
    self.actionHelp = QAction(QIcon(icon), "%s ..." % translateMsg("User guide"),self.iface.mainWindow())
    self.actionHelp.setToolTip("%s ..." % translateMsg("User guide"))
    self.actionHelp.setObjectName("mActionHelp")

    icon = getThemeIcon("about.png")
    self.actionAbout = QAction(QIcon(icon), "%s ..." % translateMsg("About"),self.iface.mainWindow())
    self.actionAbout.setToolTip("%s ..." % translateMsg("About"))
    self.actionAbout.setObjectName("mActionAbout")

    #NEW 3.4.0
    self.actionMakeRasterGrid.triggered.connect(self.getGridRasterMaker)
    self.actionHelp.triggered.connect(self.getHelp)
    self.actionAbout.triggered.connect(self.getAbout)

    self.menu.addAction(self.actionDoubleGlasses)
    self.menu.addAction(self.actionMakeRasterGrid)
    self.menu.addSeparator()
    #NEW 3.4.0
    self.menu.addAction(self.actionParameters)
    self.menu.addAction(self.actionHelp)
    self.menu.addAction(self.actionAbout)

    menuBar = self.iface.mainWindow().menuBar()
    menu = menuBar
    for child in menuBar.children():
        if child.objectName()== "mPluginMenu" :
           menu =  child
           break
    menu.addMenu(self.menu)

    self.toolBarName = translateMsg("Dynamic grid raster loader")
   
    self.wmsMenu = QMenu(menuBar)

    self.rootToolTipText = "%s : %s " % (translateMsg("Base layer"), translateMsg("WMS"))
    
    #NEW 3.4.0
    self.tabParams = 0
    self.style = myProxyStyle('Fusion')

    self.groupWmsActions = QActionGroup( self.iface.mainWindow())
    self.actionServicesWms = QAction(QIcon(getThemeIcon("wms.png")), "", self.iface.mainWindow())
    self.actionServicesWms.setObjectName("mActionToolsWms")
    
    self.dlgAutoLoaderRasterPlugin = uiAutoLoaderRasterPlugin(self, self.iface)
    self.dlgAutoLoaderRasterPlugin.hide()

    self.menuWmsServers = QMenu()
    self.menuWmsServers = self.getInfosInFile("%s/qml/wmsservers.xml" % dirname(__file__), self.menuWmsServers, self.dlgAutoLoaderRasterPlugin.getWmsService, None)  
 
    index = 0

    #NEW 3.4.0
    self.actionServicesWms.setMenu(self.menuWmsServers)
    
    self.toolBar = self.iface.addToolBar(self.toolBarName)
    
    self.actionUpdateLive = QAction(QIcon(getThemeIcon("uncheckliveupdate.png")), "%s" % translateMsg("Live update"), self.iface.mainWindow())
    self.actionUpdateLive.setCheckable(True)
    self.actionUpdateLive.setObjectName("mActionUpdateLive") 

    self.actionCheckVisibility = QAction(QIcon(getThemeIcon("uncheckvisibility.png")), "%s" % translateMsg("Dynamic management of visibility"), self.iface.mainWindow())
    self.actionCheckVisibility.setCheckable(True)
    self.actionCheckVisibility.setObjectName("mActionCheckVisibility")

    self.actionLinkMapCanvas = QAction(QIcon(getThemeIcon("unchecklinkmapcanvas.png")), "%s" % translateMsg("Link mapcanvas actions (zoom, pan)"), self.iface.mainWindow())
    self.actionLinkMapCanvas.setCheckable(True)
    self.actionLinkMapCanvas.setObjectName("mActionLinkMapCanvas")
    
    self.toolsHotLink = QMenu("%s" % translateMsg("Load a raster file"))

    dicoCtrls = {"actionToolHotLinkRaster" : ("selone.png", "Load a raster file"),
                 "actionToolHotLinkRasterRect" : ("selrect.png", "Selection with a rectangle"),
                 "actionToolHotLinkRasterFree" : ("selfree.png", "Selection with free hand"),
                 "actionToolHotLinkRasterPoly" : ("selpoly.png", "Selection with polygon"),
                 "actionToolHotLinkRasterCircleByCenter" : ("selcenter.png", "Selection with circle (center)"),
                 "actionToolHotLinkRasterCircleByRadius" : ("selradius.png", "Selection with circle (radius)")
                 }

    for key in dicoCtrls :
        icon = getThemeIcon(dicoCtrls[key][0])  
        text = translateMsg(dicoCtrls[key][1])
        action = QAction(QIcon(icon), text, self.toolsHotLink)
        action.setObjectName(key)
        self.toolsHotLink.addAction(action)
        action.triggered.connect(self.hotLinkRaster)
        setattr(self, key, action)
        if key in ("actionToolHotLinkRaster", "actionToolHotLinkRasterPoly") : self.toolsHotLink.addSeparator()
    
    self.toolHotLinkRaster = toolHotLink(self.dlgAutoLoaderRasterPlugin, self.canvas, False, False)
    self.toolHotLinkRemoveRaster = toolHotLink(self.dlgAutoLoaderRasterPlugin, self.canvas, False, True)
    
    self.toolHotLinkRasterRect = toolHotLinkRect(self.dlgAutoLoaderRasterPlugin, self.canvas, False)
    self.toolHotLinkRasterFree = toolHotLinkFree(self.dlgAutoLoaderRasterPlugin, self.canvas, False)
    self.toolHotLinkRasterPoly = toolHotLinkPoly(self.dlgAutoLoaderRasterPlugin, self.canvas, False)
    self.toolHotLinkRasterCircleByCenter = toolHotLinkCircleByCenter(self.dlgAutoLoaderRasterPlugin, self.canvas, False)
    self.toolHotLinkRasterCircleByRadius = toolHotLinkCircleByRadius(self.dlgAutoLoaderRasterPlugin, self.canvas, False)

    self.actionLoadExtent = QAction(QIcon(getThemeIcon("hotlinkextent.png")), "%s\n(SHIFT+E)" % translateMsg("Load the raster files for extent"), self.iface.mainWindow())
    self.actionLoadExtent.setObjectName("actionLoadExtent")
    self.actionLoadExtent.setShortcut(QKeySequence("SHIFT+E"))

    self.actionObjHotlink = QAction(QIcon(getThemeIcon("hotlinkselected.png")), "%s\n(SHIFT+S)" % translateMsg("Load the raster files for selected objects"), self.iface.mainWindow())
    self.actionObjHotlink.setObjectName("actionObjHotlink")
    self.actionObjHotlink.setShortcut(QKeySequence("SHIFT+S"))    

    self.actionCopyExtent = QAction(QIcon(getThemeIcon("copyrasterfiles.png")), "%s ..." % translateMsg("Copy the raster files for selection to a folder"), self.iface.mainWindow())
    self.actionCopyExtent.setObjectName("actionCopyExtent")    

    self.actionCleanGroup = QAction(QIcon(getThemeIcon("cleangroup.png")), translateMsg("Clean group"), self.iface.mainWindow())
    self.actionCleanGroup.setObjectName("actionCleanGroup")
    self.actionCleanGroup.setShortcut(QKeySequence("SHIFT+X"))

    self.actionCleanLayers = QAction(QIcon(getThemeIcon("cleanlayers.png")), "%s\n(CTRL+SHIFT+X)" % translateMsg("Remove layers"), self.iface.mainWindow())
    self.actionCleanLayers.setObjectName("actionCleanLayers")
    self.actionCleanLayers.setCheckable(True)
    self.actionCleanLayers.setWhatsThis("actionCleanLayers")
    self.actionCleanLayers.setShortcut(QKeySequence("CTRL+SHIFT+X"))
    self.actionCleanLayers.triggered.connect(self.updateToolRemove)    
    
    comboGridFiles = QWidgetAction(self.iface.mainWindow())
    comboGridFiles.setObjectName("mComboGridFiles")
    comboGridFiles.setDefaultWidget(self.dlgAutoLoaderRasterPlugin.listFiles)

    #NEW 3.4.0
    toolsGrid = QMenu("%s" % translateMsg("Actions"))
    
    self.actionZoomToGroup = QAction(QIcon(getThemeIcon("zoomtogroup.png")), translateMsg("Zoom to the group"), self.iface.mainWindow())
    self.actionZoomToGroup.setObjectName("actionZoomToGroup")
    self.actionZoomToGroup.setShortcut(QKeySequence("SHIFT+Z"))
    
    toolsGrid.addAction(self.actionZoomToGroup)
    toolsGrid.addSeparator()
    toolsGrid.addAction(self.actionCleanGroup)
    toolsGrid.addSeparator()
    toolsGrid.addAction(self.actionReloadGrids)
    toolsGrid.addAction(self.actionCheckGrids)

    self.actionGrid = QAction(QIcon(getThemeIcon("actions.png")), "", self.iface.mainWindow())
    self.actionGrid.setObjectName("mactionGrid")
    self.actionGrid.setToolTip(translateMsg("Actions"))
    self.actionGrid.setMenu(toolsGrid)

    self.actionDoubleGlasses.triggered.connect(self.dlgAutoLoaderRasterPlugin.getUpdateIcon)
    self.actionUpdateLive.triggered.connect(self.dlgAutoLoaderRasterPlugin.getUpdateIcon)
    self.actionCheckVisibility.triggered.connect(self.dlgAutoLoaderRasterPlugin.getUpdateIcon)

    self.actionLinkMapCanvas.triggered.connect(self.dlgAutoLoaderRasterPlugin.getUpdateIcon)
    self.actionZoomToGroup.triggered.connect(self.dlgAutoLoaderRasterPlugin.zoomToGroup)
    self.actionReloadGrids.triggered.connect(self.dlgAutoLoaderRasterPlugin.loadXmlGridFile)
    #NEW 3.4.0
    self.actionCheckGrids.triggered.connect(self.dlgAutoLoaderRasterPlugin.checkGridFiles)
    
    self.actionLoadExtent.triggered.connect(self.dlgAutoLoaderRasterPlugin.loadRasterForExtent)
    self.actionCopyExtent.triggered.connect(self.dlgAutoLoaderRasterPlugin.copyRasterForExtent)    
    self.actionCleanGroup.triggered.connect(self.dlgAutoLoaderRasterPlugin.cleanGroupRaster)
    self.actionObjHotlink.triggered.connect(self.dlgAutoLoaderRasterPlugin.loadForSelectedObj)

    services = QMenu(menuBar)
    
    services.addAction(self.actionUpdateLive)
    services.addAction(self.actionCheckVisibility)
    services.addAction(self.actionLinkMapCanvas)
    
    self.actionServices = QAction(QIcon(getThemeIcon("services.png")), "", self.iface.mainWindow())
    self.actionServices.setObjectName("mActionTools")
    self.actionServices.setToolTip(translateMsg("Services"))
    self.actionServices.setMenu(services)

    tools = QMenu(menuBar)
    #NEW 3.4.0
    tools.addAction(self.actionDoubleGlasses)
    tools.addAction(self.actionMakeRasterGrid)
    tools.addSeparator()
    tools.addAction(self.actionCopyExtent)

    self.actionParameters.triggered.connect(self.setOptions)
    
    self.actionTools = QAction(QIcon(getThemeIcon("tools.png")), "", self.iface.mainWindow())
    self.actionTools.setObjectName("mActionTools")
    self.actionTools.setToolTip(translateMsg("Tools"))
    self.actionTools.setMenu(tools)
    self.toolBar.addAction(self.actionCleanLayers)    
    self.toolBar.addAction(comboGridFiles)
    #NEW 3.4.0
    self.toolBar.addAction(self.actionGrid) 
    self.toolBar.addSeparator()
    self.toolBar.addAction(self.actionLoadExtent)
    self.toolBar.addAction(self.actionObjHotlink)

    self.actionToolsSel = QAction(QIcon(getThemeIcon("selone.png")), "", self.iface.mainWindow()) 
    self.actionToolsSel.setObjectName("mActionToolsSel")
    self.actionToolsSel.setCheckable(True)
    self.actionToolsSel.setChecked(False)
    self.actionToolsSel.setWhatsThis("actionToolHotLinkRaster")
    self.actionToolsSel.setToolTip(translateMsg("Selection's tools"))
    self.actionToolsSel.setMenu(self.toolsHotLink)
    self.actionToolsSel.triggered.connect(self.updateToolByAction)

    self.toolBar.addAction(self.actionServicesWms)
    self.toolBar.addAction(self.actionToolsSel)
    self.toolBar.addSeparator()
    self.toolBar.addAction(self.actionServices)
    self.toolBar.addAction(self.actionTools)   
    
    self.toolBar.addSeparator()
    #NEW 3.4.0
    self.toolBar.addAction(self.actionParameters)
    self.toolBar.addAction(self.actionHelp)
    self.toolBar.addAction(self.actionAbout)
    
    self.toolBar.setObjectName("mactionAutoLoaderRasterPluginToolBar")
    self.toolBar.setStyleSheet("QToolBar { border: 1px solid;    border-radius: 5px;   background-color: rgba(255, 255, 255, 210);}")

    self.canvas.mapToolSet.connect(self.updateToolChecked)
    self.canvas.setMapTool(QgsMapToolPan(self.canvas))

    self.actionCleanLayers.setChecked(False)
    self.actionToolsSel.setChecked(False)
    

  #NEW 3.4.0
  def parseFile(self, fileName):
      with open(fileName, 'r') as unknown_file:
           data = re.sub(r'\s+', '', unknown_file.read())
           if (re.match(r'^<.+>$', data)): return True
           else : return False
           
  def getInfosInFile(self, fileName, contextMenu, connectedSlot, treeWidgetObject):
      if not contextMenu : contextMenu = QMenu(); cond = False
      else : cond = True
      
      if exists(fileName):

           if treeWidgetObject :
              treeWidgetObject.setContext(0, getThemeIcon("wms.png"))
              treeWidgetObject.clear()
              treeWidgetObject.treeWidgetItemChanged(None, 0)
          

           if not self.parseFile(fileName) :
               msg = translateMsg("Invalid %s file") % fileName
               msgErr = translateMsg("Root autoLoaderRasterPlugin not found")
               self.barInfo.pushMessage(translateMsg("Warning"), "%s :<br>%s." % (msg, msgErr), Qgis.Warning, 3)
               return
            
           error = 0
           try:
               doc = etree.parse(fileName).getroot()
               if not doc.tag in ('ALR', 'alrPlugin', 'autoLoaderRasterPlugin') :
                  error, msg, msgErr = 1, translateMsg("Invalid %s file") % fileName, translateMsg("Root autoLoaderRasterPlugin not found")
           except (etree.ParseError, error):
               error, msg = 1, translateMsg("Cannot parse %s file") % fileName
           except (IOError, error):
               error, msg = 1, translateMsg("Cannot parse %s file") % fileName

           if error == 1:
               self.barInfo.pushMessage(translateMsg("Warning"), "%s :<br>%s." % (msg, msgErr), Qgis.Warning, 3)
               return

           isLocal = doc.attrib.get('local')
           if isLocal : isLocal = eval(isLocal)
           
           iconRessource = getThemeIcon("urlweb2.png").replace("\\", "/")        

           i = 0
           groupData = ""
           keys = ("labeluri", "uri", "paramuri")
           
           version = int(doc.attrib.get('version').split('.')[0])

           if version >= 3 :

               #NEW 3.4.0 
               text = translateMsg("None")
               action = QAction(QIcon(getThemeIcon("view_none_m.png")), '{:<45}'.format(text), contextMenu)
               contextMenu.addAction(action)
               action.triggered.connect(connectedSlot)
               
               for gridraster in doc.findall('groupData'):
                   labelGroupData = gridraster.attrib.get('labelGroupData')
                   iconGroupDataPath = join(dirname(__file__), "icons/%s" % gridraster.attrib.get('iconGroupData'))
                   iconGroupData = QIcon(iconGroupDataPath)

                   if labelGroupData != "" :
                      actionGroupData = QWidgetAction(contextMenu) 
                      button = QPushButton(labelGroupData)
                      button.setIcon(iconGroupData)
                      button.setStyleSheet("QPushButton { background-color : #C8C8C8; text-align: left; padding: 4 4 4 4px;}")

                      if cond : subMenu = QMenu(labelGroupData)
                      else : subMenu = contextMenu.addMenu(iconGroupData, labelGroupData)

                      dictValuesGroup = {}  
                      dictValuesGroup['labelGroupData'] = labelGroupData
                      dictValuesGroup['iconGroupData'] = gridraster.attrib.get('iconGroupData')

                      if treeWidgetObject :
                         if labelGroupData != "" : itemGroupData = treeWidgetObject.addItem([labelGroupData], "groupdata", -1, iconGroupData, "groupdata", None, dictValuesGroup)  

                      
                      data = []
                      try : data = gridraster.getchildren()
                      except : data = gridraster.findall('data')
                      
                      for child in data :
                          dictValues = {} 
                          for key in keys : dictValues[key] = child.attrib.get(key)
                          
                          key = child.attrib.get('uri')
                          text = child.attrib.get("labeluri")
                          action = QAction(QIcon(iconRessource), '{:<45}'.format(text), subMenu)
                          action.setWhatsThis(key)
                          action.setData(key)
                          subMenu.addAction(action)
                          #NEW 3.4.0 
                          action.triggered.connect(connectedSlot) 
                          setattr(self, text, action)

                          if treeWidgetObject : treeWidgetObject.addItem(['{:<100}'.format(text)], translateMsg("Value"), i, iconRessource, translateMsg("Value"), itemGroupData, dictValues)

                   contextMenu.addSeparator()
                   if cond :
                      actionGroupData.setDefaultWidget(button)            
                      contextMenu.addAction(actionGroupData)
                      subMenu.setStyle(self.style)
                      button.setMenu(subMenu)
                   
           else :

               dictValuesGroup = {}
               
               for gridraster in doc.findall('data'):
                   value = gridraster.attrib.get('uri')

                   dictValues = {} 
                   for key in keys : dictValues[key] = gridraster.attrib.get(key)
                   
                   if groupData != gridraster.attrib.get('groupData') :
                      if groupData != "" : contextMenu.addSeparator()
                      groupData = gridraster.attrib.get('groupData')
                      dictValuesGroup['labelGroupData'] = groupData
                      dictValuesGroup['iconGroupData'] = "group.png"

                      if groupData != "" :
                         if treeWidgetObject : itemGroupData = treeWidgetObject.addItem([groupData], "groupdata", -1, self.groupIcon, "groupdata", None, dictValuesGroup)
                   
                   test = exists(value) if isLocal else True
                   if test :
                      if isLocal :
                         sourceFile = QFileInfo(value)
                         if sourceFile.isFile():
                            iconMime = getThemeIcon("%s.png" % sourceFile.suffix().lower())
                            if exists(iconMime) : iconRessource = iconMime
                            else :   iconRessource = getThemeIcon("unknow.png")  
                         else : iconRessource = getThemeIcon("folder.png")


                      text = gridraster.attrib.get("labeluri")
                      if treeWidgetObject :
                         treeWidgetObject.addItem(['{:<100}'.format(text)], translateMsg("Value"), i, iconRessource, translateMsg("Value"), itemGroupData, dictValues)
                      
                      action = QAction(QIcon(iconRessource), '{:<45}'.format(text), contextMenu)
                      action.setWhatsThis(value)
                      contextMenu.addAction(action)
                      #NEW 3.4.0
                      action.triggered.connect(connectedSlot)
                      setattr(self, text, action)

      return contextMenu

  def updateToolChecked(self, oldTool, newTool):
      toRemove = None
      try : toRemove = self.canvas.mapTool().getRemove()
      except : pass
      if not toRemove :
         self.actionToolsSel.setChecked(False)
         self.actionCleanLayers.setChecked(False)
      else :
         if toRemove == True :
            self.actionToolsSel.setChecked(False)
            self.actionCleanLayers.setChecked(True)
         else :        
            self.actionToolsSel.setChecked(True)
            self.actionCleanLayers.setChecked(False)
         
  def updateToolByAction(self): self.updateTool(self.actionToolsSel.whatsThis(), None) 

  def updateToolRemove(self) :
      #TEST IF AUTOLOAD SERVICE ACTIVED      
      if self.actionUpdateLive.isChecked() : self.actionUpdateLive.setChecked(False); self.dlgAutoLoaderRasterPlugin.updateIcon(self.actionUpdateLive)
      self.canvas.setMapTool(self.toolHotLinkRemoveRaster)
      self.actionToolsSel.setChecked(False)   
      self.actionCleanLayers.setChecked(True)  
  
  def getGridRasterMaker(self): 
      changeButtonIcon(self, self.actionMakeRasterGrid,"makegrid_on.png", 24, 24); self.dialogGridRasterMaker = ui_gridRasterMaker(self.iface, self); self.dialogGridRasterMaker.exec(); changeButtonIcon(self, self.actionMakeRasterGrid, "makegrid_off.png", 24, 24);


  def hotLinkRaster(self):
      self.updateTool(self.iface.sender().objectName(), self.iface.sender())      
      self.actionToolsSel.setIcon(self.iface.sender().icon())
      self.actionToolsSel.setChecked(True)

  def updateTool(self, nameTool, obj):
      if nameTool == "actionToolHotLinkRaster" : self.canvas.setMapTool(self.toolHotLinkRaster)
      elif nameTool ==  "actionToolHotLinkRasterRect" : self.canvas.setMapTool(self.toolHotLinkRasterRect)
      elif nameTool ==  "actionToolHotLinkRasterFree" : self.canvas.setMapTool(self.toolHotLinkRasterFree)
      elif nameTool ==  "actionToolHotLinkRasterPoly" : self.canvas.setMapTool(self.toolHotLinkRasterPoly)
      elif nameTool ==  "actionToolHotLinkRasterCircleByCenter" : self.canvas.setMapTool(self.toolHotLinkRasterCircleByCenter)
      elif nameTool ==  "actionToolHotLinkRasterCircleByRadius" : self.canvas.setMapTool(self.toolHotLinkRasterCircleByRadius)

      if obj :
         self.actionToolsSel.setWhatsThis(nameTool)
         self.actionToolsSel.setIcon(obj.icon())         

      self.actionToolsSel.setChecked(True) 
      self.actionCleanLayers.setChecked(False) 

  def showDoubleGlasses(self) :
     if not self.dlgAutoLoaderRasterPlugin : self.dlgAutoLoaderRasterPlugin = uiAutoLoaderRasterPlugin(self, self.iface)
     self.dlgAutoLoaderRasterPlugin.show
     if not self.dlgAutoLoaderRasterPlugin.doubleFocusGlassesDlg :
        self.dlgAutoLoaderRasterPlugin.doubleFocusGlassesDlg = uiDoubleFocusGlassesPlugin(self.dlgAutoLoaderRasterPlugin)
        self.dlgAutoLoaderRasterPlugin.doubleFocusGlassesDlg.rejected.connect(self.dlgAutoLoaderRasterPlugin.changeAspectButton)

     icon = QIcon(getThemeIcon("checkdoubleglasses.png"))
     self.dlgAutoLoaderRasterPlugin.doubleFocusGlasses.setChecked(True)
     self.dlgAutoLoaderRasterPlugin.doubleFocusGlasses.setIcon(icon)
     self.dlgAutoLoaderRasterPlugin.doubleFocusGlassesDlg.show()
     self.dlgAutoLoaderRasterPlugin.doubleFocusGlassesDlg.setFocus()

  def setOptions(self):
      if not self.dlgAutoLoaderRasterPlugin : self.dlgAutoLoaderRasterPlugin = uiAutoLoaderRasterPlugin(self, self.iface)
      if not self.dlgAutoLoaderRasterPlugin.isVisible():
         self.iface.addDockWidget( Qt.DockWidgetArea.RightDockWidgetArea, self.dlgAutoLoaderRasterPlugin )
         #NEW 3.4.0
         self.dlgAutoLoaderRasterPlugin.tabs.setCurrentIndex(self.tabParams)          
         self.changeAspectButtonToolBar()
         self.dlgAutoLoaderRasterPlugin.visibilityChanged.connect(self.changeAspectButtonToolBar)
      #NEW 3.4.0   
      else : self.tabParams = self.dlgAutoLoaderRasterPlugin.tabs.currentIndex() ; self.dlgAutoLoaderRasterPlugin.hide()   

  def getAbout(self):
      self.dialogAbout = ui_About(self); self.dialogAbout.exec();

  def getHelp(self):
      nameHelpFile = "%s/documentation/autoLoaderRaster %s_manuel utilisateur_fr.pdf" % (dirname(__file__), self.version)
      fullFileName = "file://%s" % nameHelpFile
      if exists(nameHelpFile):
         try: webbrowseropen(fullFileName)
         except : pass
      else :   
         try : webbrowseropen("https://qgis.projets.developpement-durable.gouv.fr/projects/autoloaderraster/files")
         except : pass
        
  def changeAspectButtonToolBar(self):
     cond = self.dlgAutoLoaderRasterPlugin.isVisible() if self.dlgAutoLoaderRasterPlugin else False
     #NEW 3.4.0
     self.actionParameters.setIcon(QIcon(getThemeIcon("parameters_%s.png" % (not cond))))     
     self.actionParameters.setToolTip("%s %s" % (iff(not cond, translateMsg("Show"), translateMsg("Hide")), translateMsg("the control panel")))

  def unload(self):
      s = QSettings()
      s.setValue("%sxmlGridFile" % self.settings, self.dlgAutoLoaderRasterPlugin.paramsSave)
    
      menuBar = self.iface.mainWindow().menuBar()
      child = None
      for child in menuBar.children():
          if child.objectName()== "mPluginMenu" :
             break
      if child : child.removeAction(self.menu.menuAction())
      self.toolBar.parentWidget().removeToolBar(self.toolBar)

      if self.dlgAutoLoaderRasterPlugin :
         try : self.dlgAutoLoaderRasterPlugin.canvas.extentsChanged.disconnect(self.dlgAutoLoaderRasterPlugin.updateMireMapViewer)
         except : pass
         try : self.dlgAutoLoaderRasterPlugin.canvas.renderComplete.disconnect(self.dlgAutoLoaderRasterPlugin.updateMire)
         except : pass

         self.dlgAutoLoaderRasterPlugin.close()



class uiAutoLoaderRasterPlugin(QDockWidget):
    
    def __init__(self, parent, iface):
        super(uiAutoLoaderRasterPlugin, self).__init__()
        self.setObjectName("uiAutoLoaderRasterPlugin")
        self.parent = parent
        self.actionServicesWms = self.parent.actionServicesWms
        self.rootToolTipText = self.parent.rootToolTipText
        self.barInfo = self.parent.barInfo

        self.groupBoxWms = QGroupBox(self)
        self.groupBoxWms.setObjectName("groupBoxWms")
        self.groupBoxWms.setTitle("")
        
        default = Qt.ItemFlag.ItemIsSelectable| Qt.ItemFlag.ItemIsEnabled |  Qt.ItemFlag.ItemIsAutoTristate | Qt.ItemFlag.ItemIsUserCheckable  
        defaultalr = Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsAutoTristate 
        checkebable = Qt.ItemFlag.ItemIsUserCheckable
        drag = Qt.ItemFlag.ItemIsDragEnabled
        drop = Qt.ItemFlag.ItemIsDropEnabled

        settings = {"groupdata":(["root"], default|drop), translateMsg("Value"):(["groupdata"], default|drag|drop)}  
        self.treeParamsLinked = legendTreeWidget(settings, self.groupBoxWms, 2, "wms.png", None, self)
        
        self.menuWmsServers = QMenu()
        self.menuWmsServers = self.parent.getInfosInFile("%s/qml/wmsservers.xml" % dirname(__file__), self.menuWmsServers, self.updateWmsServer, self.treeParamsLinked)  #TEMPO
        #NEW 3.4.0
        if self.treeParamsLinked.topLevelItem(0) :
           self.treeParamsLinked.setCurrentItem(self.treeParamsLinked.topLevelItem(0))
           self.treeParamsLinked.treeWidgetItemChanged(self.treeParamsLinked.currentItem(), 0)
        
        self.styleComboBox = self.parent.styleComboBox
        self.styleErrorComboBox = self.parent.styleErrorComboBox
        
        self.resize(600, 600)
        self.setMinimumSize(600, 450)
        self.setWindowFlags(Qt.WindowType.WindowMaximizeButtonHint | Qt.WindowType.WindowCloseButtonHint)
        self.setWindowTitle(translateMsg("Dynamic grid raster loader"))
        windowIcon(self, "catchraster.png")

        if not self.parent.dlgAutoLoaderRasterPlugin :
           self.parent.dlgAutoLoaderRasterPlugin = self
           self.parent.changeAspectButtonToolBar()


        ############################ VARIABLE INITIALIZE #############################
           
        self.iface = iface
        self.initDir, self.initDirXml, self.initDirShp = "%s/qml/" % dirname(__file__), "%s/qml/" % dirname(__file__), "%s/" % dirname(__file__)
        self.currentLayer, self.bgLayer, self.spatialIndex = None, None, None
        self.lastExtent = None
        self.hasExtentForGeom, self.indexForExtentGeom = False, -1
        
        self.crs = QgsCoordinateReferenceSystem()
        self.crs.createFromOgcWmsCrs("EPSG:4326")
        
        self.styleQml = "%s/qml/style.qml" % dirname(__file__)

        s = QSettings() 
        self.paramsSave = s.value("%sxmlGridFile"  % self.parent.settings, "" )
        if self.paramsSave == "" :
            fileName = "%s/qml/gridrasterfiles.xml" % dirname(__file__)
            if exists(fileName) : self.paramsSave = fileName

	
        self.dictGridRaster = {}
        self.forceUpdate = False
        self.newLayerGrid = False

        self.selColor = QColor(255, 0, 0, 255)
        self.selFillColor = QColor(255, 0, 0, 100)
        self.selBrushStyle = Qt.BrushStyle.Dense7Pattern

        self.style = myMenuStyle('Fusion')
        self.styleSheetPushButton = "QPushButton::checked {icon-size: 25px, 25px; border-width: 5px; border-radius: 10px; border-color: black; background-color: #FFFFCC;}"
        self.styleSheetPushButton+= "QPushButton {icon-size: 25px, 25px; border-width: 0px; border-radius: 10px; }"
        self.styleSheetPushButtonWithMenu = "QPushButton::checked {icon-size: 50px, 25px; border-width: 5px; border-radius: 10px; border-color: black; background-color: #FFFFCC;}"
        self.styleSheetPushButtonWithMenu+= "QPushButton {icon-size: 50px, 25px; border-width: 0px; border-radius: 10px; }"

        ############################ START INTERFACE #############################

        self.groupBoxMapViewer = QGroupBox(self)
        self.groupBoxMapViewer.setObjectName("groupBoxMapViewer")
        self.groupBoxMapViewer.setTitle("")

        self.model = QStandardItemModel()
        self.view = QTableView()
        self.view.setModel( self.model )
        self.view.horizontalHeader().setVisible(False)
        self.view.verticalHeader().setVisible(False)
        self.view.setColumnHidden(1, True)
        self.view.horizontalHeader().setDefaultSectionSize(400)
        self.view.verticalHeader().setDefaultSectionSize(20)
        self.view.setStyleSheet("QTableView {min-width: 400px; max-width: 500px; selection-background-color: qlineargradient(x1: 0, y1: 0, x2: 0.5, y2: 0.5, stop: 0 #FFFFFF, stop: 1 #000000);}")
        self.view.setShowGrid(False)

        self.listFiles = QComboBox(self.groupBoxMapViewer)
        self.listFiles.setEditable(False)
        self.listFiles.setEnabled(True)
        self.listFiles.setFixedSize(380, 25) 
        self.listFiles.setFixedWidth(380)
                
        self.listFiles.setObjectName("listFiles")
        self.listFiles.setStyleSheet(self.styleComboBox)

        self.listFiles.setModel(self.model)
        self.listFiles.setView(self.view)
     
        self.projectAlr = QgsProject(self)
        self.mapViewerWmsGrid = QgsMapCanvas(self.groupBoxMapViewer)
        self.mapViewerWmsGrid.setObjectName("mapViewerWmsGrid")

        self.transformer = QgsCoordinateTransform() 
        self.transformer.setSourceCrs(self.crs) 

        self.labelWmsServer = QLabel(self.groupBoxMapViewer)
        self.labelWmsServer.setText("%s :" % translateMsg("Base layer"))


        #NEW 3.4.0
        self.nameWmsServer = QLabel(self.groupBoxMapViewer)
        self.nameWmsServer.setStyleSheet("QLabel {border: 2px solid grey; border-radius: 5px; background-color: #ffffcc;}")
        self.nameWmsServer.setText(self.rootToolTipText) #TEMPO TO CHANGE !
        toolTip = translateMsg("Web services")
        self.wmsServer = funnyPushButton(self.nameWmsServer) 
        self.wmsServer.initPushButton(40, 25, 40, 90, "wmsServer", "", toolTip, True, getThemeIcon("actions.png"), 40, 25, True)
        self.wmsServer.setMenu(self.menuWmsServers)

        color = Qt.GlobalColor.white if self.bgLayer else Qt.GlobalColor.blue
        self.widgetMapViewColors = actionsWindows(self.mapViewerWmsGrid, "widgetMapViewColors", "%s ...:" % translateMsg("Colors"), 120, 400 )

        self.mireColor = QgsColorWheel(self.widgetMapViewColors) 
        self.mireColor.setObjectName("mireColor")
        self.mireColor.setGeometry(5, 30, 110, 110)
        self.mireColor.setBaseSize(24,24)
        self.mireColor.setToolTip(translateMsg("Color used for the extent"))
        self.mireColor.setColor(color)
        self.mireColor.colorChanged.connect(self.setColors)
 
        self.selectionColor = QgsColorWheel(self.widgetMapViewColors) 
        self.selectionColor.setObjectName("selectionColor")
        self.selectionColor.setGeometry(5, 150, 110, 110)
        self.selectionColor.setToolTip(translateMsg("Color used for the selection of tiles"))
        self.selectionColor.setColor(QColor(255, 0, 0, 255))
        self.selectionColor.colorChanged.connect(self.setColors)

        self.backColor = QgsColorWheel(self.widgetMapViewColors) 
        self.backColor.setObjectName("backColor")
        self.backColor.setGeometry(5, 270, 110, 110)
        self.backColor.setToolTip(translateMsg("Color used for the mapCanvas"))
        self.backColor.setColor(QColor(255, 255, 255, 255))
        self.backColor.colorChanged.connect(self.setColors)
        self.mapViewerWmsGrid.setCanvasColor(self.backColor.color()) 

        self.widgetMapViewColors.setVisible(False)

        self.updateWmsServer()

        self.buttonToolBarNav = funnyPushButton(self.groupBoxMapViewer) 
        self.buttonToolBarNav.initPushButton(25, 25, 40, 90, "buttonToolBarNav", "", translateMsg("Show/Hide navigation toolbar"), True, getThemeIcon("navigation_on.png"), 25, 25, True)

        self.buttonToolBarCoords = funnyPushButton(self.groupBoxMapViewer) 
        self.buttonToolBarCoords.initPushButton(25, 25, 40, 90, "buttonToolBarCoords", "", translateMsg("Show/Hide coords widget"), True, getThemeIcon("legend_on.png"), 25, 25, True)

        self.buttonToolBarColors = funnyPushButton(self.groupBoxMapViewer) 
        self.buttonToolBarColors.initPushButton(25, 25, 40, 90, "buttonToolBarColors", "", translateMsg("Show/Hide colors widget"), True, getThemeIcon("colors_off.png"), 25, 25, True)
        self.buttonToolBarNav.clicked.connect(self.getToolBarNav)
        self.buttonToolBarCoords.clicked.connect(self.getToolBarCoords)
        self.buttonToolBarColors.clicked.connect(self.getToolBarColors)

        self.widgetMapViewCoords = actionsWindows(self.mapViewerWmsGrid, "widgetMapViewCoords", "%s ...:" % translateMsg("Coords"), 120, 160 )
                
        self.styleSheetTextEditCoords = "QLineEdit { font-size: 11px;  color : white; background-color: rgba(160, 160, 160, 125); border: 2px solid cyan;  border-radius: 4px;  padding: 2px;}"
        lineInfosCoord = {"latN" : 0, "longW" : 3, "longE" : 2, "latS" : 1}

        pos = 30
        for key in lineInfosCoord :
            obj = labeller("lbl%s" % key, "%s " % key, "coords", Qt.AlignmentFlag.AlignRight, self.widgetMapViewCoords)
            obj.setGeometry(5, pos+2, 40, 20)
            
            obj = QLineEdit(self.widgetMapViewCoords)
            obj.setAlignment(Qt.AlignmentFlag.AlignCenter)
            obj.setStyleSheet(self.styleSheetTextEditCoords)
            obj.setGeometry(45, pos, 70, 25)
            obj.setText("%s" % "0")
            obj.setEnabled(False)
            setattr(self, key, obj)
            pos+= 30

        self.doubleFocusGlassesDlg = None

        self.context = QgsExpressionContext()
        self.scope = QgsExpressionContextScope()

        #NEW 3.6.0 - SINCE QGIS 3.36        
        self.rb = QgsRubberBand(self.mapViewerWmsGrid, Qgis.GeometryType.Polygon)
        self.rbaxesh = QgsRubberBand(self.mapViewerWmsGrid, Qgis.GeometryType.Line)
        self.rbaxesv = QgsRubberBand(self.mapViewerWmsGrid, Qgis.GeometryType.Line)
        self.rbgeomdalles = QgsRubberBand(self.mapViewerWmsGrid, Qgis.GeometryType.Polygon)
        self.rbTool = QgsRubberBand(self.mapViewerWmsGrid, Qgis.GeometryType.Point)
       
        self.rbTool.setColor(QColor(255, 0, 0, 255))
        self.rbTool.setWidth(3)
        self.rbTool.setFillColor(QColor(255, 0, 0,100))

        self.rb.setColor(Qt.GlobalColor.blue)
        self.rb.setWidth(4)
        self.rbaxesh.setColor(color)
        self.rbaxesv.setColor(color)
        self.rbgeomdalles.setColor(QColor(245, 245, 25, 75)) 

        self.canvas = self.iface.mapCanvas()
        try : self.rbCanvas = QgsRubberBand(self.canvas, True)
        except : self.rbCanvas = QgsRubberBand(self.canvas)
        self.rbCanvas.setColor(QColor(255, 0, 0, 255))
        self.rbCanvas.setWidth(3)
        self.rbCanvas.setFillColor(QColor(255, 0, 0, 100))
        

        self.tabs = QTabWidget(self)  
        self.tabs.setTabsClosable(False)
        self.tabs.setDocumentMode(True)
        self.tabs.setTabShape(QTabWidget.TabShape.Rounded)

        #NEW 3.6.4
        self.widgetMapView = actionsWindows(self.mapViewerWmsGrid, "widgetConsole", "%s ...:" % translateMsg("Actions"), 430, 65 ) #400
        ctrlMap(self, self.widgetMapView, True, False, False, 5, 0, 440, 30, True) #410
        
        index = self.tabs.addTab(self.groupBoxMapViewer, QIcon(getThemeIcon("location.png")), translateMsg("MapCanvas"))
        self.tabs.setTabToolTip(index,  translateMsg("MapCanvas"))

        self.groupBoxParams = QGroupBox(self)
        self.groupBoxParams.setObjectName("groupBoxParams")
        self.groupBoxParams.setTitle("")

        self.xmlGridFile = QTextEdit(self.groupBoxParams)
        self.xmlGridFile.setStyleSheet("QTextEdit {border: 2px solid grey; border-radius: 5px; text-align: center;background-color:#ffffcc;}")
        self.xmlGridFile.setReadOnly(True)
        self.xmlGridFile.setObjectName("xmlGridFile")

        toolTip = translateMsg("Actions ...")
        self.actionButton = funnyPushButton(self.groupBoxParams) 
        self.actionButton.initPushButton(40, 24, 40, 90, "actionButton", "", toolTip, True, getThemeIcon("actions.png"), 40, 24, True)
        
        self.contextMnuActions(self.actionButton)

        self.lblListFiles = labeller("lblListFiles","%s : " % (translateMsg("Raster files grid")), "normal", Qt.AlignmentFlag.AlignLeft, self.groupBoxParams)
     
        self.listFilesWidget = myListWidget(self.groupBoxParams) 
        self.listFilesWidget.setObjectName("listFilesWidget")
        self.listFilesWidget.setStyleSheet("* { font-size:12px; background-color:#c0c0c0; padding: 4px ; color:black;}"
                                           "QListWidget::item:selected {color: black; background-color: rgb(240,240,240); padding: 6px;}")
        self.listFilesWidget.setIconSize(QSize(18, 20))
        self.listFilesWidget.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove)
        self.listFilesWidget.setDragDropOverwriteMode(False)
        self.listFilesWidget.setDragEnabled(True)
        self.listFilesWidget.setDropIndicatorShown(True)


        self.counterXmlGridFiles = QLabel(self.groupBoxParams)
        self.counterXmlGridFiles.setStyleSheet("QLabel {border: 2px solid grey; border-radius: 5px; background-color: #ffffcc;}")
        self.counterXmlGridFiles.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.counterXmlGridFiles.setText("%s" % len(self.dictGridRaster))

        self.getItemListFiles = funnyPushButton(self.groupBoxParams)
        self.getItemListFiles.initPushButton(24, 24, 5, 5, "getItemListFiles", "", translateMsg("Add file grid"), True, getThemeIcon("add.png"), 24, 24, True)

        self.delItemListFiles = funnyPushButton(self.groupBoxParams)
        self.delItemListFiles.initPushButton(24, 24, 5, 5, "delItemListFiles", "", translateMsg("Delete current file grid definition"), True, getThemeIcon("del.png"), 24, 24, True)

        self.groupBoxRelativePath = QgsCollapsibleGroupBox(self.groupBoxParams)
        self.groupBoxRelativePath.setObjectName("groupBoxRelativePath")
        self.groupBoxRelativePath.setStyleSheet("QgsCollapsibleGroupBox {border: 2px solid grey; border-radius: 5px; background-color: #c0c0c0; color: white;}") 
        self.groupBoxRelativePath.setMinimumHeight(10)
        self.groupBoxRelativePath.setMaximumHeight(300)
        self.groupBoxRelativePath.setTitle("%s %s" % (translateMsg("Params"), translateMsg("Raster files grid")))

 
        self.selectGridFile = QPushButton(self.groupBoxRelativePath)
        self.selectGridFile.setObjectName("selectGridFile")
        self.selectGridFile.setToolTip(translateMsg("Select file grid"))
        self.selectGridFile.setFixedSize(25, 25)
        self.selectGridFile.setIcon(QIcon(getThemeIcon("open.png")))

        self.lblUsualName = labeller("lblUsualName", "%s : " % (translateMsg("Usual name for the grid file")),
                                       "normal", Qt.AlignmentFlag.AlignRight, self.groupBoxRelativePath)
        
        self.usualName = textEdit(self, self.groupBoxRelativePath)
        self.usualName.setEnabled(True)
        self.usualName.setObjectName("usualName")

        self.lblUsualProjRaster  = labeller("lblUsualProjRaster", "%s : " % (translateMsg("Usual projection")),
                                       "normal", Qt.AlignmentFlag.AlignRight, self.groupBoxRelativePath)


        self.lblGridRaster = labeller("lblGridRaster", "", "infos", Qt.AlignmentFlag.AlignLeft, self.groupBoxRelativePath)
        

        self.projRaster = QgsProjectionSelectionWidget(self.groupBoxRelativePath)
        self.projRaster.setObjectName("projRaster")

        self.lblGroupRaster = labeller("lblGroupRaster", "%s : " % (translateMsg("Name for the raster group")),
                                       "normal", Qt.AlignmentFlag.AlignRight, self.groupBoxRelativePath)
 
        self.groupRaster = textEdit(self, self.groupBoxRelativePath)
        self.groupRaster.setEnabled(True)
        self.groupRaster.setObjectName("groupRaster")

        
        self.selectGroupRaster = QPushButton(self.groupBoxRelativePath)
        self.selectGroupRaster.setObjectName("selectGroupRaster")
        self.selectGroupRaster.setToolTip(translateMsg("Select group raster"))
        self.selectGroupRaster.setFixedSize(25, 25)
        self.selectGroupRaster.setIcon(QIcon(getThemeIcon("bggroup.png")))
 
        self.lblListFields = labeller("lblListFields", "%s : " % (translateMsg("Field with link")),
                                       "normal", Qt.AlignmentFlag.AlignRight, self.groupBoxRelativePath)        
 
        self.listFields = QComboBox(self.groupBoxRelativePath)
        self.listFields.setEditable(False)
        self.listFields.setEnabled(True)
        self.listFields.setObjectName("listFields")
        self.listFields.setStyleSheet(self.styleComboBox)

        self.expressionButton = QPushButton(self.groupBoxRelativePath)
        self.expressionButton.setObjectName("expression")
        self.expressionButton.setToolTip(translateMsg("Call the Expression QGIS Dialog box"))
        self.expressionButton.setFixedSize(25, 25)
        self.expressionButton.setIcon(QIcon(getThemeIcon("expression.png")))        
 
        self.relativePath = QPushButton(self.groupBoxRelativePath) #QCheckBox
        self.relativePath.setText(translateMsg("Relative path"))
        self.relativePath.setToolTip(self.relativePath.text())
        self.relativePath.setObjectName("relativePath")
        self.relativePath.setCheckable(True)
        self.relativePath.setChecked(True)
        self.relativePath.setEnabled(False)


        self.relativePathFolder = textEdit(self, self.groupBoxRelativePath)
        self.relativePathFolder.setEnabled(True)  
        self.relativePathFolder.setStyleSheet("color: black; background-color: #C0C0C0")
        self.relativePathFolder.setObjectName("relativePathFolder")

        self.relativePathFolderButton = QPushButton(self.groupBoxRelativePath)
        self.relativePathFolderButton.setObjectName("relativePathFolderButton")
        self.relativePathFolderButton.setToolTip(translateMsg("Select Folder or path to localize images"))
        self.relativePathFolderButton.setFixedSize(25, 25)
        self.relativePathFolderButton.setIcon(QIcon(getThemeIcon("folder.png")))

        self.deletePathFolderButton = funnyPushButton(self.relativePathFolder)
        self.deletePathFolderButton.initPushButton(23, 23, 5, 5, "deletePathFolderButton", "", translateMsg("Delete the value for the field"), True, getThemeIcon("delvalue.png"), 23, 23, True)
        
        self.lblListExtension = labeller("lblListExtension", "%s : " % (translateMsg("Extension for raster layer")),
                                       "normal", Qt.AlignmentFlag.AlignRight, self.groupBoxRelativePath)          
                                                                    
        self.listExtension = QComboBox(self.groupBoxRelativePath)
        self.listExtension.setEditable(True) 
        self.listExtension.setEnabled(True)
        self.listExtension.setObjectName("listExtension")
        
        self.gdalListExtensions = makeListFormatsExtensions(self, False, True, False)
        self.listExtension.addItems(self.gdalListExtensions)
        self.listExtension.setStyleSheet(self.styleComboBox)

        index = self.tabs.addTab(self.groupBoxParams, QIcon(getThemeIcon("params.png")), translateMsg("Params"))
        self.tabs.setTabToolTip(index,  translateMsg("Params"))

        self.icoLiveUpdate = QLabel(self.groupBoxParams)
        myImgPath = getThemeIcon("uncheckliveupdate.png")
        carIcon = QImage(myImgPath)
        self.icoLiveUpdate.setPixmap(QPixmap.fromImage(carIcon))

        self.lblSliderNeighBors = labeller("lblSliderNeighBors", "%s : " % (translateMsg("Grids max tolerance")),
                                       "normal", Qt.AlignmentFlag.AlignLeft, self.groupBoxParams)           
        
        self.sliderNeighBors = QSlider(self.groupBoxParams)
        self.sliderNeighBors.setObjectName("sliderNeighBors")
        self.sliderNeighBors.setStyleSheet("QSlider { width: 30px }"
                                           "QSlider::groove:horizontal {border: 1px solid #999999; background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4); height: 50px; margin: 0 0 0 0;  border-radius: 3px;}"
                                           "QSlider::handle:horizontal {background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #8f8f8f);border: 1px solid #5c5c5c;width: 30px; margin: -5px 0 -5px 0; border-radius: 3px;}")
        self.sliderNeighBors.setOrientation(Qt.Orientation.Horizontal)
        self.sliderNeighBors.setMinimum(2)
        self.sliderNeighBors.setMaximum(20)
        self.sliderNeighBors.setValue(6)

        self.txtSliderNeighBors = labeller("txtSliderNeighBors", "%s" % self.sliderNeighBors.value(), "special", Qt.AlignmentFlag.AlignCenter, self.groupBoxParams)


        self.icoVisibilityService = QLabel(self.groupBoxParams)
        myImgPath = getThemeIcon("uncheckvisibility.png")
        carIcon = QImage(myImgPath)
        self.icoVisibilityService.setPixmap(QPixmap.fromImage(carIcon))
        
        self.checkVisibilityService = QCheckBox(self.groupBoxParams)
        self.checkVisibilityService.setText(translateMsg("Visibility service only for the group"))
        self.checkVisibilityService.setObjectName("checkVisibilityService")
        self.checkVisibilityService.setChecked(True)

        self.icoOpenGroup = QLabel(self.groupBoxParams)
        myImgPath = getThemeIcon("uncheckgroup.png")
        carIcon = QImage(myImgPath)
        self.icoOpenGroup.setPixmap(QPixmap.fromImage(carIcon))

        self.openGroup = QCheckBox(self.groupBoxParams)
        self.openGroup.setText(translateMsg("Raster group always open"))
        self.openGroup.setIcon(QIcon(getThemeIcon("uncheckgroup.png")))
        self.openGroup.setObjectName("openGroup")
        self.openGroup.setChecked(False)        

        #NEW 3.4.0
        index = self.tabs.addTab(self.groupBoxWms, QIcon(getThemeIcon("wms.png")), translateMsg("Web services"))
        self.tabs.setTabToolTip(index,  translateMsg("Web services"))
 
        styleSheetPushButton = "QPushButton {display: block;  border: 2px solid gray;  border-radius: 10px; text-align: center;  line-height: 10px;}"
        styleSheetPushButton+= "QPushButton::checked {border: 2px solid green; border-radius: 10px;}"

        self.updateLive = funnyPushButton(self)
        self.updateLive.initPushButton(42, 42, 50, 50, "updateLive", "", translateMsg("Live update"), True, getThemeIcon("uncheckliveupdate.png"), 35, 35, True)
        self.updateLive.setStyleSheet(styleSheetPushButton)
        self.updateLive.setCheckable(True)
                     
        self.checkVisibility = funnyPushButton(self)
        self.checkVisibility.initPushButton(42, 42, 50, 50, "checkVisibility", "", translateMsg("Dynamic management of visibility"), True, getThemeIcon("uncheckvisibility.png"), 35, 35, True)
        self.checkVisibility.setStyleSheet(styleSheetPushButton)
        self.checkVisibility.setCheckable(True)


        self.linkMapCanvas = funnyPushButton(self)
        self.linkMapCanvas.initPushButton(42, 42, 50, 50, "linkMapCanvas", "", translateMsg("Link mapcanvas actions (zoom, pan)"), True, getThemeIcon("unchecklinkmapcanvas.png"), 35, 35, True)
        self.linkMapCanvas.setStyleSheet(styleSheetPushButton)
        self.linkMapCanvas.setCheckable(True)

        self.doubleFocusGlasses = funnyPushButton(self)
        self.doubleFocusGlasses.initPushButton(42, 42, 50, 50, "doubleFocusGlasses", "", translateMsg("Show or Hide double Focus Glasses"), True, getThemeIcon("uncheckdoubleglasses.png"), 35, 35, True)
        self.doubleFocusGlasses.setStyleSheet(styleSheetPushButton)
        self.doubleFocusGlasses.setCheckable(True)

        self.cleanGroupButton = funnyPushButton(self)
        self.cleanGroupButton.initPushButton(42, 42, 50, 50, "cleanGroupButton", "", translateMsg("Clean group"), True, getThemeIcon("cleangroup.png"), 35, 35, True)
        self.cleanGroupButton.setStyleSheet(styleSheetPushButton)

        self.saveButton = funnyPushButton(self)
        self.saveButton.initPushButton(42, 42, 50, 50, "saveButton", "", translateMsg("Save configuration"), True, getThemeIcon("savefile.png"), 35, 35, True)
        self.saveButton.setStyleSheet(styleSheetPushButton)
        

        self.closeButton = QPushButton(self)
        self.closeButton.setObjectName("closeButton")
        self.closeButton.setToolTip(translateMsg("Close"))
        self.closeButton.setIcon(QIcon(getThemeIcon("cancel.png")))
        self.closeButton.setIconSize(QSize(32 , 32))

        self.actionsMapCanvas.button(0).setChecked(True)
        self.actionsMapCanvas.buttonClicked.connect(self.actionMapCanvas) #buttonClicked[int]

        #CONNECTORS
        self.selectGridFile.clicked.connect(self.chooseGridFile)  
        self.usualName.textChanged.connect(self.checkUsualName)
        self.updateLive.clicked.connect(self.getUpdateIcon)
        self.checkVisibility.clicked.connect(self.getUpdateIcon)
        self.openGroup.clicked.connect(self.getUpdateIcon)
        self.linkMapCanvas.clicked.connect(self.getUpdateIcon)
        self.doubleFocusGlasses.clicked.connect(self.getUpdateIcon)
        self.cleanGroupButton.clicked.connect(self.cleanGroupRaster)
        
        self.canvas.extentsChanged.connect(self.updateMire)
        self.canvas.layersChanged.connect(self.updateMapCanvasProject)
        QgsProject(self.iface).instance().readProject.connect(self.stabilizeProject)
        
        self.mapViewerWmsGrid.extentsChanged.connect(self.updateMire)
        self.listFiles.currentIndexChanged.connect(self.updateMapViewerWithGrid)

        self.getGridRasterInFile()

        self.toolPan = QgsMapToolPan(self.mapViewerWmsGrid)
        self.toolZoomIn = QgsMapToolZoom(self.mapViewerWmsGrid, False) 
        self.toolZoomOut = QgsMapToolZoom(self.mapViewerWmsGrid, True)
        self.toolHotLink = toolHotLink(self, self.mapViewerWmsGrid, True, False)
        self.toolHotLinkRemove = toolHotLink(self, self.mapViewerWmsGrid, True, True)
        
        self.toolHotLinkRect = toolHotLinkRect(self, self.mapViewerWmsGrid, True)
        self.toolHotLinkFree = toolHotLinkFree(self, self.mapViewerWmsGrid, True)
        self.toolHotLinkPoly = toolHotLinkPoly(self, self.mapViewerWmsGrid, True)
        self.toolHotLinkCircleByCenter = toolHotLinkCircleByCenter(self, self.mapViewerWmsGrid, True)
        self.toolHotLinkCircleByRadius = toolHotLinkCircleByRadius(self, self.mapViewerWmsGrid, True)
        
        self.mapViewerWmsGrid.setMapTool(self.toolZoomIn)

        self.buttonCatchExtent.clicked.connect(self.catchExtent)
        self.buttonPan.clicked.connect(self.pan)
        self.buttonZoomIn.clicked.connect(self.zoomIn)
        self.buttonZoomOut.clicked.connect(self.zoomOut)
        self.buttonZoomAll.clicked.connect(self.zoomAll)
        self.buttonZoomCurrentLayer.clicked.connect(self.zoomToCurrentLayer)
        self.buttonZoomPrevious.clicked.connect(self.zoomPrevious)
        self.buttonZoomNext.clicked.connect(self.zoomNext)
        self.buttonLoadExtent.clicked.connect(self.loadRasterForExtent)
        self.buttonSendExtent.clicked.connect(self.sendExtentToMapCanvas)
        self.buttonLoadSelected.clicked.connect(self.loadForSelectedObj)

        self.getItemListFiles.clicked.connect(self.selectListFiles)
        self.delItemListFiles.clicked.connect(self.deleteInListFiles)

        self.groupBoxRelativePath.collapsedStateChanged.connect(self.changePosGroupOtions)
        self.relativePathFolderButton.clicked.connect(self.getRelativePath)
        self.deletePathFolderButton.clicked.connect(self.deleteRelativePath)

        self.projRaster.crsChanged.connect(self.updateInfosGridRaster)
        self.listFields.currentIndexChanged.connect(self.updateInfosGridRaster)
        
        self.selectGroupRaster.clicked.connect(self.getWizardGroupRaster)
        
        self.expressionButton.clicked.connect(self.getExpression)
        self.listExtension.currentIndexChanged.connect(self.updateInfosGridRaster)
        self.listFilesWidget.currentRowChanged.connect(self.getInfosGridRaster)
        
        self.sliderNeighBors.valueChanged.connect(self.setVisibleValue)
        self.checkVisibilityService.clicked.connect(self.updateMapCanvasProject)
        #NEW 3.4.0
        self.tabs.tabBarClicked.connect(self.updateEnaledSaveButton)
        
        self.saveButton.clicked.connect(self.getSaveGridRasterInFile) 
        self.closeButton.clicked.connect(self.close)
      
        self.updateMapViewerWithGrid()
        self.updateMire()
        self.zoomToCurrentLayer()

        #NEW 3.4.0
        self.updateEnaledSaveButton(self.tabs.currentIndex())
        self.zoomAll()
        
        #NEW 3.6.4
        self.extents = []
        self.currentExtent = -1
        self.mapViewerWmsGrid.extentsChanged.connect(self.storeExtent)
        self.buttonClearExtents.clicked.connect(self.clearHistory)
        self.updateButtonZoomNextPrevious()

    #NEW 3.6.4
    def clearHistory(self):
        self.extents, self.currentExtent = [], -1
        self.updateButtonZoomNextPrevious()
        
    def storeExtent(self):
        self.extents.append(self.mapViewerWmsGrid.extent())
        self.currentExtent = len(self.extents)-1
        self.updateButtonZoomNextPrevious()

    def getWmsGroupRaster(self):
         """
         try : layer = self.iface.activeLayer()
         except : return None        
         """
         root = QgsProject.instance().layerTreeRoot()
         listOrder = root.layerOrder()
         index = len(root.children())
         nameGroupRaster = translateMsg("Base layer")
         group = None
         group = root.findGroup(nameGroupRaster)
         if group == None :
            group = root.insertGroup(index, nameGroupRaster); expanded = True;
         return group

      
    def cleanWmsGroupRaster(self):
        groupRaster = self.getWmsGroupRaster()
        if groupRaster : groupRaster.removeAllChildren()

    #NEW 3.4.0
    def updateEnaledSaveButton(self, index):
        self.saveButton.setEnabled(index > 0)
        
    def getWmsService(self):
        groupRaster = self.getWmsGroupRaster() 
        if groupRaster == None : return
        self.cleanWmsGroupRaster()
        
        nameLayer = self.iface.sender().text()
        urlWms = self.iface.sender().data()

        self.actionServicesWms.setToolTip("%s%s" % (self.rootToolTipText, nameLayer))

        if not urlWms : return
        
        urlWms = cleanUri(urlWms)        

        rasterLayer = QgsRasterLayer(urlWms , "%s - %s" %  (self.iface.sender().parent().title(), nameLayer) , "WMS")
        mapLayer = QgsProject.instance().addMapLayer(rasterLayer, False) 
        nodeLayer = QgsLayerTreeLayer(rasterLayer)
        groupRaster.insertChildNode(0, nodeLayer)


        if urlWms.find("traffic") > -1 :
           if mapLayer :
              mapLayer.setAutoRefreshInterval(60000)                        
              mapLayer.setAutoRefreshEnabled(True)


    def getWizardGroupRaster(self): 
        self.wizardData = wizardData(self)
        self.wizardData.exec()
        self.wizardData = None

    def updateListFiles(self):
        oldValue = self.listFiles.currentText()

        self.listFiles.blockSignals(True)
        self.listFiles.clear()
        for i in range(self.listFilesWidget.count()) :
            item = QStandardItem(self.listFilesWidget.item(i).text())
            item.setData(self.listFilesWidget.item(i).toolTip(), Qt.ItemDataRole.UserRole)
            self.model.appendRow(item)

        self.listFiles.setCurrentIndex(self.listFilesWidget.currentRow())

        self.listFiles.blockSignals(False)     

    def setColors(self):
        if self.sender() == self.mireColor :
           color = self.sender().color()
           self.rb.setColor(color)
           self.rbaxesh.setColor(color)
           self.rbaxesv.setColor(color)
           self.mapViewerWmsGrid.refresh()
        elif self.sender() == self.selectionColor :
           color = self.sender().color()
           self.rbTool.setColor(color)
           self.rbCanvas.setColor(color)
           self.canvas.refresh()
           self.mapViewerWmsGrid.refresh()
        elif self.sender() == self.backColor :
           color = self.sender().color()
           self.mapViewerWmsGrid.setCanvasColor(color)
           self.mapViewerWmsGrid.refresh()

    def checkUsualName(self):
        if self.usualName.toPlainText() == "" :
           self.usualName.setPlainText("%s %s" % (translateMsg("Raster files grid"), self.listFiles.count()-1))


    def initToolHotLinksButton(self):
        self.buttonHotlink.setStyleSheet("QPushButton {icon-size: 50px, 25px; border-width: 0px; border-radius: 10px; }")
        self.sender().setStyleSheet(self.styleSheetPushButton)

      
    def setModeForHotLink(self) :
        tool = ""
        try : tool = self.sender().objectName()
        except : pass
        if tool == "actionToolHotLink" : self.mapViewerWmsGrid.setMapTool(self.toolHotLink)
        elif tool == "actionToolHotLinkRect" : self.mapViewerWmsGrid.setMapTool(self.toolHotLinkRect)
        elif tool == "actionToolHotLinkFree" : self.mapViewerWmsGrid.setMapTool(self.toolHotLinkFree)
        elif tool == "actionToolHotLinkPoly" : self.mapViewerWmsGrid.setMapTool(self.toolHotLinkPoly)
        elif tool == "actionToolHotLinkCircleByCenter" : self.mapViewerWmsGrid.setMapTool(self.toolHotLinkCircleByCenter)
        elif tool == "actionToolHotLinkCircleByRadius" : self.mapViewerWmsGrid.setMapTool(self.toolHotLinkCircleByRadius)
        else : return

        self.buttonPan.setChecked(False)
        self.buttonPan.setStyleSheet("QPushButton {icon-size: 25px, 25px; border-width: 0px; border-radius: 10px; }")
        self.buttonZoomIn.setChecked(False)
        self.buttonZoomIn.setStyleSheet("QPushButton {icon-size: 25px, 25px; border-width: 0px; border-radius: 10px; }")
        self.buttonZoomOut.setChecked(False)
        self.buttonZoomOut.setStyleSheet("QPushButton {icon-size: 25px, 25px; border-width: 0px; border-radius: 10px; }")
        self.buttonHotlink.setStyleSheet("QPushButton {icon-size: 50px, 25px; border-width: 5px; border-radius: 10px; border-color: black; background-color: #FFFFCC;}")
        self.buttonHotlink.setIcon(self.sender().icon())


        
    def contextMnuToolsHotlink(self, button):

        contextMenu = QMenu()

        dicoCtrls = {"actionToolHotLink" : ("selone.png", "Load a raster file"),
                     "actionToolHotLinkRect" : ("selrect.png", "Selection with a rectangle"),
                     "actionToolHotLinkFree" : ("selfree.png", "Selection with free hand"),
                     "actionToolHotLinkPoly" : ("selpoly.png", "Selection with polygon"),
                     "actionToolHotLinkCircleByCenter" : ("selcenter.png", "Selection with circle (center)"),
                     "actionToolHotLinkCircleByRadius" : ("selradius.png", "Selection with circle (radius)")
                    }

        for key in dicoCtrls :
            icon = getThemeIcon(dicoCtrls[key][0])  
            text = translateMsg(dicoCtrls[key][1])
            action = QAction(QIcon(icon), text, contextMenu)
            action.setObjectName(key)
            contextMenu.addAction(action)
            action.triggered.connect(self.setModeForHotLink)
            setattr(self, key, action)
            if key in ("actionToolHotLink", "actionToolHotLinkPoly") : contextMenu.addSeparator()
     

        contextMenu.setStyle(self.style)
        button.setMenu(contextMenu)


    def getToolBarNav(self): self.setVisibility(self.widgetMapView, self.buttonToolBarNav, "navigation_%s.png")
    def getToolBarCoords(self): self.setVisibility(self.widgetMapViewCoords, self.buttonToolBarCoords, "legend_%s.png")
    def getToolBarColors(self): self.setVisibility(self.widgetMapViewColors, self.buttonToolBarColors, "colors_%s.png") 
    
    def setVisibility(self, widget, actionTool, icon):
        if widget :
           widget.setVisible(not widget.isVisible ())
           cond = "on" if widget.isVisible() else "off"
        else : cond = "off"   
        actionTool.setIcon(QIcon(getThemeIcon(icon % cond)))        
    def stabilizeProject(self):
        self.updateWmsServer()
        if self.lastExtent : self.mapViewerWmsGrid.setExtent(self.lastExtent)


    def updateWmsServer(self):
        #NEW 3.4.0
        nameLayer = translateMsg("None")
        urlWms = None
        title = translateMsg("Layer")
        
        if self.iface.sender() :
           if type(self.iface.sender()) != QgsProject :
               #NEW 3.4.1
               if hasattr(self.iface.sender(), 'text'):
                   nameLayer = self.iface.sender().text()
                   urlWms = self.iface.sender().data()
                   if urlWms : title = self.iface.sender().parent().title()
               else : return    

        self.nameWmsServer.setText("%s - %s" % (title, nameLayer))
        self.nameWmsServer.setToolTip("%s%s" % (self.rootToolTipText, nameLayer))
        
        if not urlWms :
           if self.bgLayer != None : self.projectAlr.removeMapLayers([self.bgLayer.id()])
           self.bgLayer = None
           self.mapViewerWmsGrid.setLayers([self.currentLayer])
           self.mapViewerWmsGrid.refresh()
           
        else :
          urlWms = cleanUri(urlWms)  
          if self.bgLayer != None : self.projectAlr.removeMapLayers([self.bgLayer.id()])
          self.bgLayer = QgsRasterLayer(urlWms, "bglayer", "WMS")          
          if not self.lastExtent : self.lastExtent = self.bgLayer.extent()
          self.mapViewerWmsGrid.setLayers([self.currentLayer, self.bgLayer]) 
          self.mapViewerWmsGrid.refresh()
         
        self.crs = QgsCoordinateReferenceSystem()
        self.crs.createFromOgcWmsCrs("EPSG:3857")
        self.projectAlr.setCrs(self.crs) 
        self.transformer.setDestinationCrs(self.crs)
        self.mapViewerWmsGrid.setDestinationCrs(self.crs) 

   
    def catchExtent(self):
        tr = QgsCoordinateTransform(QgsProject(self.iface).instance().crs(), self.crs, self.projectAlr)
        try :
            extent = tr.transform(self.canvas.extent())
            self.mapViewerWmsGrid.setExtent(extent)
            self.mapViewerWmsGrid.refresh()
        except : pass

    def sendExtentToMapCanvas(self): 
        if self.iface.sender().objectName()=="buttonSendExtent" :
           try : self.canvas.extentsChanged.disconnect(self.updateMire)
           except : pass
        extent = self.mapViewerWmsGrid.extent()
        if self.crs != QgsProject(self.iface).instance().crs() :
           tr = QgsCoordinateTransform(self.crs, QgsProject(self.iface).instance().crs(), QgsProject(self.iface).instance()) 
           try : extent = tr.transform(extent)
           except : pass
        self.canvas.setExtent(extent)
        self.canvas.refresh()
        if self.iface.sender().objectName()=="buttonSendExtent" :
           try : self.canvas.extentsChanged.connect(self.updateMire)
           except : pass
        self.updateMire()

        

    def contextMnuActions(self, button):
        contextMenu = QMenu()

        action = QAction(QIcon(getThemeIcon("new.png")), translateMsg("New grid file"), self)
        action.setObjectName("newXmlGridFile")
        contextMenu.addAction(action)
        action.triggered.connect(self.newXmlGridFile)

        contextMenu.addSeparator()

        action = QAction(QIcon(getThemeIcon("open.png")), "%s ..." % translateMsg("Choose grid file"), self)
        action.setObjectName("getXmlGridFile")
        contextMenu.addAction(action)
        action.triggered.connect(self.loadXmlGridFile)

        action = QAction(QIcon(getThemeIcon("reload.png")), translateMsg("Reload grid file"), self)
        action.setObjectName("reloadXmlGridFile")
        contextMenu.addAction(action)
        action.triggered.connect(self.loadXmlGridFile)
       
        contextMenu.addSeparator()

        action = QAction(QIcon(getThemeIcon("savefile.png")), translateMsg("Save configuration"), self)
        action.setObjectName("saveConfButton")
        contextMenu.addAction(action)
        action.triggered.connect(self.getSaveGridRasterInFile) 

        action = QAction(QIcon(getThemeIcon("savefile.png")), "%s ..." % translateMsg("Save configuration as"), self)
        action.setObjectName("saveConfAsButton")
        contextMenu.addAction(action)
        action.triggered.connect(self.saveAsGridRasterInFile)

        action = QAction(QIcon(getThemeIcon("savefile.png")), "%s ..." % translateMsg("Save a copy of configuration"), self)
        action.setObjectName("saveConfAsCopyButton")
        contextMenu.addAction(action)
        action.triggered.connect(self.saveACopyGridRasterInFile)

        button.setMenu(contextMenu)

    
    def close(self):
        self.updateLive.setChecked(False)
        self.hide()

    def newXmlGridFile(self):

        self.xmlGridFile.setText("")
        
        if self.currentLayer : self.projectAlr.removeMapLayers([self.currentLayer.id()])
        self.currentLayer = None
        self.mapViewerWmsGrid.refresh()
      
        self.listFilesWidget.clear()
        self.listFiles.clear()
        self.dictGridRaster = {}
        self.paramsSave = ""
        self.usualName.setPlainText("%s %s" % (translateMsg("Raster files grid"), self.listFiles.count()))
        
        self.lblGridRaster.setText("")
        self.listFields.clear() 
        self.relativePath.setChecked(False)
        self.relativePathFolder.setPlainText("")
        self.groupRaster.setPlainText("")
        self.listExtension.setCurrentIndex(0)

        self.counterXmlGridFiles.setText("%s" % len(self.dictGridRaster))


    #NEW 3.4.0
    def checkGridFiles(self):
        self.listFilesWidget.blockSignals(True)
        self.listFiles.blockSignals(True)

        index = self.listFilesWidget.currentRow()
        counter = self.listFilesWidget.count()
        goodGrids = 0

        self.barInfo.clearWidgets()
        progressMessageBar = self.barInfo.createMessage("%s %s / %s ..." % (translateMsg("Check the grids"), 0, counter))
        progress = QProgressBar()
        progress.setAlignment(Qt.AlignmentFlag.AlignLeft|Qt.AlignmentFlag.AlignVCenter)
        progress.setMaximum(counter)
        progressMessageBar.layout().addWidget(progress)
        self.barInfo.pushWidget(progressMessageBar, Qgis.Info)

        for i in range(counter):
            self.barInfo.items()[0].setText("%s %s / %s ..." % (translateMsg("Check the grids"), i, counter))
            progress.setValue(i)
            self.barInfo.repaint()
            self.listFilesWidget.setCurrentRow(i)
            key = self.listFilesWidget.currentItem().toolTip()
            cond = exists(key)
            icon = QIcon(getThemeIcon("gridraster.png")) if cond else QIcon(getThemeIcon("gridrasterbad.png"))
            if cond : goodGrids+= 1
            self.listFilesWidget.item(i).setIcon(icon)
            self.listFiles.setItemIcon(i, icon)
            self.listFiles.setItemData(i, 33, Qt.ItemDataRole.UserRole -1) if cond else self.listFiles.setItemData(i, 0, Qt.ItemDataRole.UserRole -1)     

        self.listFilesWidget.setCurrentRow(index)
        self.barInfo.clearWidgets()

        title = translateMsg("Check the grids")
        msg = translateMsg("%s %s / %s" % (goodGrids, translateMsg("available"), counter))
        self.barInfo.pushMessage("%s :" % title, "%s" % msg, Qgis.Info, 3)
        
        self.listFilesWidget.blockSignals(False)
        self.listFiles.blockSignals(False)


    def loadXmlGridFile(self):
        if self.sender().objectName() == "reloadXmlGridFile" or self.iface.sender().objectName() == "actionReloadGrids" :
            if self.xmlGridFile.toPlainText() == "" : return
            fileName = self.xmlGridFile.toPlainText()
            if fileName == "" : return
            self.listFilesWidget.clear()
            self.listFiles.clear()
            self.dictGridRaster = {}
            self.getGridRasterInFile()
        else :
            title = self.sender().toolTip()
            dlgFile = QFileDialog(self, title)
            elt = translateMsg("Files")
            dlgFile.setNameFilters(("%s eXtensible Markup Language (*.xml *.XML)" % (elt), "%s ini (*.ini *.INI)" % (elt)))
            extension = "xml" if self.paramsSave == "" else getExtension(self.paramsSave).replace(".", "")
            dlgFile.setDefaultSuffix(extension)            
            dlgFile.setViewMode(QFileDialog.ViewMode.Detail)
            dlgFile.setDirectory(self.initDirXml)
            dlgFile.setFileMode(QFileDialog.FileMode.ExistingFiles) 
            dlgFile.setAcceptMode(QFileDialog.AcceptMode.AcceptOpen)

            fixeLabelsFileDialog(self, dlgFile, 0, True)
                
            if dlgFile.exec():
                    fileName = "%s" % (dlgFile.selectedFiles()[0])
                    if fileName != "" :
                        self.initDirXml = dirname(fileName)
                        self.paramsSave = fileName
                        self.listFilesWidget.clear()
                        self.listFiles.clear()
                        self.dictGridRaster = {}
                        self.getGridRasterInFile()

                 

    def actionMapCanvas(self, int): 
        #NEW 4.0.0
        try :  self.actionsMapCanvas.button(int).setChecked(True)
        except : return

    def getTransform(self, box, sens):
        if self.transformer.sourceCrs() == self.transformer.destinationCrs() : return box 
        if sens == 0 : targetBox = self.transformer.transformBoundingBox(box, QgsCoordinateTransform.ForwardTransform)
        else : targetBox = self.transformer.transformBoundingBox(box, QgsCoordinateTransform.ReverseTransform)
        return targetBox
      
    def updateBoxValues(self):
        box = self.getTransform(self.mapViewerWmsGrid.extent(), 1)
        self.longE.setText("%s" % round(box.xMaximum(), 4)) 
        self.longW.setText("%s" % round(box.xMinimum(), 4))
        self.latN.setText("%s" % round(box.yMaximum(), 4))
        self.latS.setText("%s" % round(box.yMinimum(), 4))     


    def changePosGroupOtions(self):

        if self.groupBoxRelativePath.isCollapsed() : self.groupBoxRelativePath.setGeometry(10, 210, self.width()-30, 25)
        else : self.groupBoxRelativePath.setGeometry(10, 210,  self.width()-30, 260)

        self.lblGridRaster.setGeometry(10, 20, self.groupBoxRelativePath.width()-60, 25)
        self.selectGridFile.setGeometry(self.groupBoxRelativePath.width()-45, 20, 25, 25)

        self.lblUsualName.setGeometry(10, 50, 175, 25)
        self.usualName.setGeometry(190, 50, self.groupBoxRelativePath.width()-240, 25)

        self.lblUsualProjRaster.setGeometry(10, 80, 175, 25)  
        self.projRaster.setGeometry(190, 80, self.groupBoxRelativePath.width()-210, 25)
        
        self.lblGroupRaster.setGeometry(10, 110,175, 25)
        self.groupRaster.setGeometry(190, 110, self.groupBoxRelativePath.width()-240, 25)
        self.selectGroupRaster.setGeometry(self.groupBoxRelativePath.width()-45, 110, 25, 25)
        
        self.lblListFields.setGeometry(10, 140, 175, 25)
        self.listFields.setGeometry(190, 140,  self.groupBoxRelativePath.width()-240, 25)
        self.expressionButton.setGeometry(self.groupBoxRelativePath.width()-45, 140,  25, 25)
        
        self.relativePath.setGeometry(10, 175, 175, 25)
        self.relativePathFolder.setGeometry(190, 175,  self.groupBoxRelativePath.width()-240, 25)
        self.relativePathFolderButton.setGeometry(self.groupBoxRelativePath.width()-45, 175,  25, 25)
        self.deletePathFolderButton.setGeometry(self.relativePathFolder.width()-30, 1,  23, 23)

        self.lblListExtension.setGeometry(10, 215, 175, 25)
        self.listExtension.setGeometry(190, 215, 80, 25)

        posY = self.groupBoxRelativePath.y()+self.groupBoxRelativePath.height()+ 20
        self.icoLiveUpdate.setGeometry(10, posY-10, 40, 40)
        self.lblSliderNeighBors.setGeometry(50, posY+5, 150, 20)
        self.sliderNeighBors.setGeometry(200, posY+5, 180, 20)
        self.txtSliderNeighBors.setGeometry(390, posY, 25, 25) 
        self.icoVisibilityService.setGeometry(10, posY+25, 40, 40)
        self.checkVisibilityService.setGeometry(50, posY+35, 300, 20)
        self.icoOpenGroup.setGeometry(10, posY+65, 40, 40)
        self.openGroup.setGeometry(50, posY+75, 300, 20)    
        
        
    def resizeEvent(self, event):
       
        self.tabs.setGeometry(0, 25, self.width()-10,  self.height()-90)

        self.changePosGroupOtions()

        self.groupBoxMapViewer.setGeometry(5, 0,  self.tabs.width()-10, self.tabs.height())
        self.mapViewerWmsGrid.setGeometry(10, 60, self.groupBoxMapViewer.width()-10, self.groupBoxMapViewer.height()-100)
        
        self.labelWmsServer.setGeometry(5, 30, 100, 25) 
        self.nameWmsServer.setGeometry(105, 30, 300, 25)
        #NEW 3.4.0
        self.wmsServer.setGeometry(self.nameWmsServer.width()-30, 0, 25, 25)
        self.buttonToolBarNav.setGeometry(410, 30, 25, 25)
        self.buttonToolBarCoords.setGeometry(440, 30, 25, 25)
        self.buttonToolBarColors.setGeometry(470, 30, 25, 25)
        self.widgetMapViewColors.setGeometry(self.mapViewerWmsGrid.width()-125, 180, 120, 400)
        
        self.widgetMapViewCoords.setGeometry(self.mapViewerWmsGrid.width()-125, 10, 120, 160)
        
        self.groupBoxParams.setGeometry(5, 0,  self.tabs.width()-10, self.tabs.height())
        self.xmlGridFile.setGeometry(10, 25, self.tabs.width()-55, 38)
        self.actionButton.setGeometry(self.tabs.width()-50, 30, 25, 25)
        self.lblListFiles.setGeometry(10, 65, self.tabs.width()-150, 25)
        
        #NEW 3.4.0
        self.groupBoxWms.setGeometry(5, 0,  self.tabs.width()-10, self.tabs.height())
        

        self.counterXmlGridFiles.setGeometry(self.groupBoxParams.width()-120, 70, 25, 25)
        self.getItemListFiles.setGeometry(self.groupBoxParams.width()-85, 70, 24, 24)
        self.delItemListFiles.setGeometry(self.groupBoxParams.width()-50, 70, 24, 24)

        self.listFilesWidget.setGeometry(10, 65, self.tabs.width()-20, 140)

        refPosY = self.height()-55
        self.updateLive.setGeometry(10, refPosY, 42, 40)
        self.checkVisibility.setGeometry(55, refPosY, 42, 40)
        self.linkMapCanvas.setGeometry(100, refPosY, 42, 40)
        self.cleanGroupButton.setGeometry(145, refPosY, 42, 40)        
        self.doubleFocusGlasses.setGeometry(190, refPosY, 42, 40)

        self.saveButton.setGeometry(self.width()-110, refPosY, 40, 40)
        self.closeButton.setGeometry(self.width()-60, refPosY, 40, 40)


    def showDoubleGlasses(self, cond) :
        if not self.doubleFocusGlassesDlg : self.doubleFocusGlassesDlg = uiDoubleFocusGlassesPlugin(self); self.doubleFocusGlassesDlg.rejected.connect(self.changeAspectButton)
        if not self.doubleFocusGlassesDlg.isVisible() : self.doubleFocusGlassesDlg.show()
        else : self.doubleFocusGlassesDlg.hide()
        self.doubleFocusGlassesDlg.setFocus()

    def changeAspectButton(self):
        self.doubleFocusGlasses.setIcon(QIcon(getThemeIcon("uncheckdoubleglasses.png")))
        self.doubleFocusGlasses.setChecked(False)
        self.parent.actionDoubleGlasses.setIcon(QIcon(getThemeIcon("uncheckdoubleglasses.png")))
        self.parent.actionDoubleGlasses.setChecked(False)

    def getUpdateIcon(self): self.updateIcon(self.sender())
    
    def updateIcon(self, obj):
        if obj :
          obj2 = None
          isUpdateCheck = True
          
          if obj == self.checkVisibility or obj == self.parent.actionCheckVisibility :   
             icon = QIcon(getThemeIcon("checkvisibility.png")) if obj.isChecked() else QIcon(getThemeIcon("uncheckvisibility.png"))
             if obj == self.parent.actionCheckVisibility : obj2 = self.checkVisibility 
             if obj == self.checkVisibility : obj2 = self.parent.actionCheckVisibility 
          elif obj == self.openGroup :  
             icon = QIcon(getThemeIcon("checkgroup.png")) if obj.isChecked() else QIcon(getThemeIcon("uncheckgroup.png"))
          elif obj == self.updateLive or obj == self.parent.actionUpdateLive :   
             icon = QIcon(getThemeIcon("checkliveupdate.png")) if obj.isChecked() else QIcon(getThemeIcon("uncheckliveupdate.png"))
             if  obj == self.parent.actionUpdateLive : obj2 = self.updateLive 
             if obj == self.updateLive : obj2 = self.parent.actionUpdateLive 
          elif obj == self.doubleFocusGlasses or obj == self.parent.actionDoubleGlasses :
             icon = QIcon(getThemeIcon("checkdoubleglasses.png")) if obj.isChecked() else QIcon(getThemeIcon("uncheckdoubleglasses.png"))
             if obj == self.parent.actionDoubleGlasses : obj2 = self.doubleFocusGlasses 
             if obj == self.doubleFocusGlasses : obj2 = self.parent.actionDoubleGlasses   
             self.showDoubleGlasses(obj.isChecked())
             isUpdateCheck = False
          elif obj == self.linkMapCanvas or obj == self.parent.actionLinkMapCanvas :   
             icon = QIcon(getThemeIcon("checklinkmapcanvas.png")) if obj.isChecked() else QIcon(getThemeIcon("unchecklinkmapcanvas.png"))

             
             if obj == self.parent.actionLinkMapCanvas :
                obj2 = self.linkMapCanvas
                #TO FINISH - MUTUALIZE WITH DEF SETOPTIONS
                if obj.isChecked() :
                   if not self.parent.dlgAutoLoaderRasterPlugin : self.parent.dlgAutoLoaderRasterPlugin = uiAutoLoaderRasterPlugin(self.parent, self.iface)
                   if not self.parent.dlgAutoLoaderRasterPlugin.isVisible():
                      self.iface.addDockWidget( Qt.DockWidgetArea.RightDockWidgetArea, self.parent.dlgAutoLoaderRasterPlugin )
                      self.parent.changeAspectButtonToolBar()
                      self.parent.dlgAutoLoaderRasterPlugin.visibilityChanged.connect(self.parent.changeAspectButtonToolBar)
                
             if obj == self.linkMapCanvas : obj2 = self.parent.actionLinkMapCanvas
                  
             if obj.isChecked() :
               self.mapViewerWmsGrid.extentsChanged.connect(self.updateMireWithSynchroMap)
               self.sendExtentToMapCanvas()
             else :
               self.mapViewerWmsGrid.extentsChanged.disconnect(self.updateMireWithSynchroMap)
          else : return

          obj.setIcon(icon)
          if obj2 :
             obj2.setIcon(icon)
             if isUpdateCheck : obj2.setChecked(obj.isChecked())

          
          if obj in (self.checkVisibility, self.parent.actionCheckVisibility, self.updateLive, self.parent.actionUpdateLive, self.linkMapCanvas, self.parent.actionLinkMapCanvas):
             toolTip = "%s" % translateMsg("Services")
             code = "1" if self.updateLive.isChecked() else "0"
             if self.updateLive.isChecked() : toolTip+= "\n- %s" % self.updateLive.toolTip()
             code+= "1" if self.checkVisibility.isChecked() else "0"
             if self.checkVisibility.isChecked() : toolTip+= "\n- %s" % self.checkVisibility.toolTip()
             code+= "1" if self.linkMapCanvas.isChecked() else "0"
             if self.linkMapCanvas.isChecked() : toolTip+= "\n- %s" % self.linkMapCanvas.toolTip()
             icon = getThemeIcon("services%s.png" % code)
             self.parent.actionServices.setIcon(QIcon(icon))
             self.parent.actionServices.setToolTip(toolTip)
             

          if obj == self.openGroup  : self.getGroupRaster(True) 

        self.updateMapCanvasProject()
      
    
    def saveACopyGridRasterInFile(self):
        title = self.sender().toolTip()
        dlgFile = QFileDialog(self, title)
        elt = translateMsg("Files")
        dlgFile.setNameFilters(("%s eXtensible Markup Language (*.xml *.XML)" % (elt), "%s ini (*.ini *.INI)" % (elt)))
        extension = "xml" if self.paramsSave == "" else getExtension(self.paramsSave).replace(".", "") 
        dlgFile.setDefaultSuffix(extension)
        dlgFile.setViewMode(QFileDialog.ViewMode.Detail)
        dlgFile.setDirectory(self.initDirXml)
        dlgFile.setFileMode(QFileDialog.FileMode.ExistingFiles) 
        dlgFile.setAcceptMode(QFileDialog.AcceptMode.AcceptSave)

        fixeLabelsFileDialog(self, dlgFile, 1, True)
            
        if dlgFile.exec():
                fileName = "%s" % (dlgFile.selectedFiles()[0])
                if fileName != "" :
                   self.saveGridRasterInFile(fileName, False)

      
    def saveAsGridRasterInFile(self):

        title = self.sender().toolTip()
        dlgFile = QFileDialog(self, title)
        elt = translateMsg("Files")
        dlgFile.setNameFilters(("%s eXtensible Markup Language (*.xml *.XML)" % (elt), "%s ini (*.ini *.INI)" % (elt)))
        extension = "xml" if self.paramsSave == "" else getExtension(self.paramsSave).replace(".", "") 
        dlgFile.setDefaultSuffix(extension)
        dlgFile.setViewMode(QFileDialog.ViewMode.Detail)
        dlgFile.setDirectory(self.initDirXml)
        dlgFile.setFileMode(QFileDialog.FileMode.ExistingFiles) 
        dlgFile.setAcceptMode(QFileDialog.AcceptMode.AcceptSave)

        fixeLabelsFileDialog(self, dlgFile, 1, True)
            
        if dlgFile.exec():
                fileName = "%s" % (dlgFile.selectedFiles()[0])
                if fileName != "" :
                   self.paramsSave = fileName
                   extension = getExtension(self.paramsSave).replace(".", "")
                   self.xmlGridFile.setText(self.paramsSave)
                  
                   self.saveGridRasterInFile(self.paramsSave, True)

                   if self.listFilesWidget.count() == 0 :
                      title = translateMsg("Information")
                      msg = translateMsg("The file %s was saved as") % extension
                      self.barInfo.pushMessage("%s :" % title, "%s :<br>%s" % (msg, self.paramsSave), Qgis.Info, 3)
    
    
    def getSaveGridRasterInFile(self): self.saveGridRasterInFile(self.paramsSave, True)

    #NEW 3.4.0
    def reloadServicesWms(self):
        self.parent.menuWmsServers.clear()
        self.parent.menuWmsServers = self.parent.getInfosInFile("%s/qml/wmsservers.xml" % dirname(__file__), self.parent.menuWmsServers, self.getWmsService, None) 

        self.menuWmsServers.clear()
        self.menuWmsServers = self.parent.getInfosInFile("%s/qml/wmsservers.xml" % dirname(__file__), self.menuWmsServers, self.updateWmsServer, self.treeParamsLinked)  #TEMPO

    
    def saveGridRasterInFile(self, fileName, activeGrid):

          if self.tabs.currentIndex() == 1 :
        
              if self.listFilesWidget.count() == 0 : return
              if self.xmlGridFile.toPlainText() == "" : return

              oldRow = self.listFilesWidget.currentRow()
              extension = getExtension(fileName).replace(".", "")
            
              if extension == "ini" :              

                  inFile = open(fileName, "w")
                  config = ConfigParser()
                  config.add_section("options")
                  config.set("options",'date', thedatetime.now().strftime("%d/%m/%Y %Hh%Mm%Ss"))
                  config.set("options",'mandatoryPlugin',"AutoLoaderRaster")
                  config.set("options",'version', self.parent.version)
                  config.set("options",'updateLive', '%s' % self.updateLive.isChecked())
                  config.set("options",'openGroup', '%s' % self.updateLive.isChecked())
                  config.set("options",'updateLive', '%s' % self.openGroup.isChecked())
                  config.set("options",'checkVisibility', '%s' % self.checkVisibility.isChecked())
                  config.set("options",'checkVisibilityService', '%s' % self.checkVisibilityService.isChecked())
                  config.set("options",'sliderNeighBors', '%s' % self.sliderNeighBors.value())
                  config.set("options",'nameWmsServer', "")
                  config.set("options",'currentGridRaster', '%s' % self.listFiles.currentIndex())
                  config.set("options",'mireColor', '%s' % self.mireColor.color().name())
                  config.set("options",'selectionColor', '%s' % self.selectionColor.color().name())
                  config.set("options",'backColor', '%s' % self.backColor.color().name())

                  config.set("options",'nbGrids', '%s' % self.listFilesWidget.count())

                  for i in range(self.listFilesWidget.count()):
                      self.listFilesWidget.setCurrentRow(i)
                      key = self.listFilesWidget.currentItem().toolTip()
                      section = "gridraster_%s" % i
                      config.add_section(section)
                      config.set(section, 'path', key)
                      for propertie in self.dictGridRaster[key] :
                          config.set(section, propertie, "%s" % self.dictGridRaster[key][propertie])


                  config.write(inFile)
                  if inFile != None : inFile.close()

             
              elif extension == "xml" :
                
                  doc = etree.Element('autoLoaderRasterPlugin')
                  doc.attrib['version'] = self.parent.version
                  connection = etree.SubElement(doc, 'dynamicview')
                  connection.attrib['updateLive'] = '%s' % self.updateLive.isChecked()
                  connection.attrib['openGroup'] = '%s' % self.openGroup.isChecked()
                  connection.attrib['checkVisibility'] = '%s' % self.checkVisibility.isChecked()
                  connection.attrib['checkVisibilityService'] = '%s' % self.checkVisibilityService.isChecked()
                  connection.attrib['sliderNeighBors'] = '%s' % self.sliderNeighBors.value()
                  connection.attrib['nameWmsServer'] = "" 
                  connection.attrib['currentGridRaster'] = '%s' % self.listFiles.currentIndex()
                  connection.attrib['mireColor'] = '%s' % self.mireColor.color().name()
                  connection.attrib['selectionColor'] = '%s' % self.selectionColor.color().name()
                  connection.attrib['backColor'] = '%s' % self.backColor.color().name()
                  
                  i = 0

                  for i in range(self.listFilesWidget.count()):
                      self.listFilesWidget.setCurrentRow(i)
                      key = self.listFilesWidget.currentItem().toolTip()            
                      connection = etree.SubElement(doc, 'gridraster')
                      connection.attrib['path'] = key
                      for propertie in self.dictGridRaster[key] :
                          connection.attrib[propertie] = "%s" % self.dictGridRaster[key][propertie]

                  with open(fileName, 'w', encoding="utf-8", errors="surrogateescape") as fileobj: fileobj.write(prettifyXml(etree.tostring(doc)))

              
              if activeGrid :
                  self.listFilesWidget.clear()
                  self.listFiles.clear()
                  self.dictGridRaster = {}
                  self.getGridRasterInFile()

              self.listFilesWidget.setCurrentRow(oldRow)

              
              title = translateMsg("Information")
              msg = translateMsg("The file %s was saved as") % extension
              self.barInfo.pushMessage("%s :" % title, "%s :<br>%s" % (msg, fileName), Qgis.Info, 3)

          elif self.tabs.currentIndex() == 2 :

                fileName = join(dirname(__file__), "qml/wmsservers.xml")
                extension = "XML"

                doc = etree.Element('autoLoaderRasterPlugin')
                doc.attrib['local'] = "False" 
                doc.attrib['version'] = self.parent.version 
                
                root = self.treeParamsLinked.invisibleRootItem()
                for i in range(root.childCount()):
                    group = root.child(i)
                    groupData = group.text(0)
                    values = group.data(0, Qt.ItemDataRole.WhatsThisRole) 
                    dictValues = literal_eval(values)                           
                    connection = etree.SubElement(doc, "groupData")
                    for key in dictValues.keys() : connection.attrib[key] = dictValues[key]

                    for j in range(group.childCount()) :
                        values = group.child(j).data(0, Qt.ItemDataRole.WhatsThisRole) 
                        dictValues = literal_eval(values)
                        connectionItem = etree.SubElement(connection, "data") 
                        for key in dictValues.keys() : connectionItem.attrib[key] = dictValues[key]

                try : xml = prettifyXml(etree.tostring(doc))
                except :
                     self.barInfo.pushMessage(translateMsg("Warning"), "%s : %s !" % (translateMsg("Unable to save file"), fileName), Qgis.Warning, duration) 
                     return 
                    
                with open(fileName, 'w', encoding="utf-8", errors="surrogateescape") as fileobj: fileobj.write(xml)
                
           
                title = translateMsg("Information")
                msg = translateMsg("The file %s was saved as") % extension
                self.barInfo.pushMessage("%s :" % title, "%s :<br>%s" % (msg, fileName), Qgis.Info, 3)

                self.reloadServicesWms()


    def parseFile(self, fileName):
        with open(fileName, 'r') as unknown_file:
            data = re.sub(r'\s+', '', unknown_file.read())
            if (re.match(r'^<.+>$', data)): return True
            else : return False

    def getGridRasterInFile(self):
        if exists(self.paramsSave):
           extension = getExtension(self.paramsSave).replace(".", "")

           if extension == "xml" : 
  
               if not self.parseFile(self.paramsSave) :
                   title = translateMsg("Warning")
                   msg = translateMsg("Invalid %s file") % extension
                   msgErr = translateMsg("Root autoLoaderRasterPlugin not found")
                   self.barInfo.pushMessage("%s :" % title, "%s :<br>%s." % (msg, msgErr), Qgis.Warning, 3)
                   return

               self.xmlGridFile.setText(self.paramsSave)
               self.xmlGridFile.setToolTip(self.paramsSave)

               error = 0
               try:
                   doc = etree.parse(self.paramsSave).getroot()
                   if doc.tag != 'autoLoaderRasterPlugin':
                      error = 1
                      msg = translateMsg("Invalid %s file") % extension
                      msgErr = translateMsg("Root autoLoaderRasterPlugin not found")
               except (etree.ParseError, error):
                   error = 1
                   msg = translateMsg("Cannot parse %s file") % extension.upper()
               except (IOError, error):
                   error = 1
                   msg = translateMsg("Cannot open file") 

               if error == 1:
                   title = translateMsg("Warning")
                   self.barInfo.pushMessage("%s :" % title, "%s :<br>%s." % (msg, msgErr), Qgis.Warning, 3)
                   self.setlistFilesWidget()
                   return

               addkeys, indexListFiles = [], 0

               #NEW 3.4.0
               for gridraster in doc.findall('dynamicview'):
                   listProperties = ["updateLive", "checkVisibility", "checkVisibilityService", "openGroup", "sliderNeighBors", "nameWmsServer", "currentGridRaster", "mireColor", "selectionColor", "backColor"]  
                   for propertie in listProperties :
                       value = gridraster.attrib.get(propertie)
                       if propertie in ["updateLive", "checkVisibility"] :
                         obj = self.findChild(myPushButton, propertie)
                         try :
                           if obj :
                              obj.setChecked(eval(value))
                              if propertie!= "checkVisibilityService" : self.updateIcon(obj)
                         except : pass
                       elif propertie == "openGroup"  :
                         obj = self.findChild(QCheckBox, propertie)
                         try :
                           if obj :
                              cond = eval(value)
                              obj.setChecked(cond)
                              obj.setIcon(QIcon(getThemeIcon("uncheckgroup.png"))) if not cond else obj.setIcon(QIcon(getThemeIcon("checkgroup.png")))
                         except : pass

                       elif propertie in ("mireColor", "selectionColor", "backColor")  :
                            obj = self.findChild(QgsColorWheel, propertie)
                            try :
                                obj.setColor(QColor(value))
                                obj.colorChanged.emit(QColor(value))
                            except : pass
                            
                       elif propertie == "currentGridRaster" :
                            try : indexListFiles = int(value)
                            except : pass
                       elif propertie == "nameWmsServer" :  pass  
                       elif propertie == "sliderNeighBors" :
                         obj = self.findChild(QSlider, propertie)
                         try :
                           if obj :
                              obj.setValue(int(value))
                              self.txtSliderNeighBors.setText(value)
                         except : pass                   

               self.blockTheSignals(True)

               i = 0 
               for gridraster in doc.findall('gridraster'):
                   key = gridraster.attrib.get('path')
                   
                   usualName = gridraster.attrib.get('usualName')
                   if not usualName : usualName = "%s %s" % (translateMsg("Raster files grid"), i)
                   if usualName == "" : usualName = "%s %s" % (translateMsg("Raster files grid"), i)
                   i+= 1
                   item = QStandardItem(usualName)
                   item.setData(key, Qt.ItemDataRole.UserRole)
                   self.model.appendRow(item)

                   self.listFiles.setItemIcon(self.listFiles.count()-1, QIcon(getThemeIcon("gridraster.png")))
                   item = QListWidgetItem(QIcon(getThemeIcon("gridraster.png")), usualName, self.listFilesWidget)
                   item.setToolTip(key)

                   if not dicoHasKey(self.dictGridRaster, key) : self.dictGridRaster[key] = {}
                   listProperties = ["usualName", "groupRaster", "listFields", "relativePath", "relativePathFolder", "listExtension", "projRaster" ] 
                   for propertie in listProperties :
                       value = gridraster.attrib.get(propertie)
                       if propertie == "relativePath" : self.dictGridRaster[key][propertie] = eval(value)
                       elif propertie == "usualName" : self.dictGridRaster[key][propertie] = usualName
                       else : self.dictGridRaster[key][propertie] = value
                   addkeys.append("%s\n" % key)

                
               self.blockTheSignals(False)

           elif extension == "ini" :

                self.xmlGridFile.setText(self.paramsSave)
                self.xmlGridFile.setToolTip(self.paramsSave)

                config = ConfigParser()
                config.read(self.paramsSave)
                sections = config.sections()

                addkeys, indexListFiles = [], 0
                
                i = 0

                self.blockTheSignals(True)
               
                for section in sections :

                    if section == 'options' :
                       listProperties = ["updateLive", "checkVisibility", "checkVisibilityService", "openGroup", "sliderNeighBors", "nameWmsServer", "currentGridRaster", "mireColor", "selectionColor", "backColor"]
                       for propertie in listProperties :
                           value = config.get(section, propertie)

                           if propertie in ["updateLive", "checkVisibility"] :
                             obj = self.findChild(myPushButton, propertie)
                             try :
                               if obj :
                                  obj.setChecked(eval(value))
                                  if propertie!= "checkVisibilityService" : self.updateIcon(obj)
                             except : pass
                           elif propertie == "openGroup"  :
                             obj = self.findChild(QCheckBox, propertie)
                             try :
                               if obj :
                                  cond = eval(value)
                                  obj.setChecked(cond)
                                  obj.setIcon(QIcon(getThemeIcon("uncheckgroup.png"))) if not cond else obj.setIcon(QIcon(getThemeIcon("checkgroup.png")))
                             except : pass

                           elif propertie in ("mireColor", "selectionColor", "backColor")  :
                                obj = self.findChild(QgsColorWheel, propertie)
                                try :
                                    obj.setColor(QColor(value))
                                    obj.colorChanged.emit(QColor(value))
                                except : pass
                                
                           elif propertie == "currentGridRaster" :
                                try : indexListFiles = int(value)
                                except : pass
                           elif propertie == "nameWmsServer" : pass
                           elif propertie == "sliderNeighBors" :
                             obj = self.findChild(QSlider, propertie)
                             try :
                               if obj :
                                  obj.setValue(int(value))
                                  self.txtSliderNeighBors.setText(value)
                             except : pass           

                             
                      
                    elif section.startswith('gridraster') :
                      key = config.get(section, 'path')

                      usualName = config.get(section, 'usualName')
                      if not usualName : usualName = "%s %s" % (translateMsg("Raster files grid"), i)
                      if usualName == "" : usualName = "%s %s" % (translateMsg("Raster files grid"), i)
                      i+= 1
                      item = QStandardItem(usualName)
                      item.setData(key, Qt.ItemDataRole.UserRole)
                      self.model.appendRow(item)

                      self.listFiles.setItemIcon(self.listFiles.count()-1, QIcon(getThemeIcon("gridraster.png")))
                      item = QListWidgetItem(QIcon(getThemeIcon("gridraster.png")), usualName, self.listFilesWidget)
                      item.setToolTip(key)

                      if not dicoHasKey(self.dictGridRaster, key) : self.dictGridRaster[key] = {}
                      listProperties = ["usualName", "groupRaster", "listFields", "relativePath", "relativePathFolder", "listExtension", "projRaster" ] 
                      for propertie in listProperties :
                          value = config.get(section, propertie)
                          if propertie == "relativePath" : self.dictGridRaster[key][propertie] = eval(value)
                          elif propertie == "usualName" : self.dictGridRaster[key][propertie] = usualName
                          else : self.dictGridRaster[key][propertie] = value
                      addkeys.append("%s\n" % key)
                         
                self.blockTheSignals(False)
                

           else : return  

          
           if len(addkeys) > 0 :
               if indexListFiles > self.listFiles.count()-1 : indexListFiles = 0            
               self.listFilesWidget.setCurrentItem(self.listFilesWidget.item(indexListFiles))
               self.listFilesWidget.setCurrentRow(indexListFiles, QItemSelectionModel.SelectionFlag.Select)
               self.getInfosGridRaster()
               self.listFiles.setCurrentIndex(indexListFiles)
               key = self.getKeyForGridLayer(self.listFiles.currentIndex())               

               if key :
                 
                   self.currentLayer = QgsVectorLayer(key, basename(key), "ogr")
                   if not self.lastExtent : self.lastExtent = self.currentLayer.extent()
                   self.spatialIndex = self.getSpatialIndex(self.currentLayer)
                   self.getQml()
                   self.initDir = dirname(key)
                   self.barInfo.pushMessage("%s :" % translateMsg("Information"),
                                            "%s (%s)" % (translateMsg("Added grid file"), len(addkeys)), Qgis.Info, 3)

           self.counterXmlGridFiles.setText("%s" % len(self.dictGridRaster))

           if len(self.dictGridRaster) > 0 :
              key = self.getKeyForGridLayer(self.listFiles.currentIndex())
              self.getLayerGrid(key)
              self.zoomToCurrentLayer()

    def getQml(self):
        if self.currentLayer :
           currentLayerName = self.currentLayer.source()
           extension = getExtension(currentLayerName).replace(".", "")
           styleQml = "%sqml" % (currentLayerName[:len(currentLayerName)-len(extension)])
           if not exists(styleQml):  
              if self.currentLayer.geometryType() == 0 : self.styleQml = "%s/qml/stylepoints.qml" % dirname(__file__) 
              else : self.styleQml = "%s/qml/style.qml" % dirname(__file__)   
              if exists(self.styleQml) : self.currentLayer.loadNamedStyle(self.styleQml, True)
           else : self.currentLayer.loadNamedStyle(styleQml, True)

          
    def blockTheSignals(self, cond):
        self.projRaster.blockSignals(cond)
        self.listFiles.blockSignals(cond)
        self.listFields.blockSignals(cond)
        self.listExtension.blockSignals(cond)
        self.listFilesWidget.blockSignals(cond)
        self.groupRaster.blockSignals(cond)
        self.relativePath.blockSignals(cond)
        self.relativePathFolder.blockSignals(cond)

    def getRelativePath(self):
        title = translateMsg("Select the folder")
        dlgRelativePath = QFileDialog(self, title)

        if exists(self.relativePath.text()) : initDir = self.relativePath.text()
        else :
           initDir = "%s/%s" % (dirname(self.lblGridRaster.text()), self.relativePath.text())
           if not exists(initDir) : 
              initDir = dirname(self.lblGridRaster.text()) if exists(dirname(self.lblGridRaster.text())) else  dirname(__file__)
        
        dlgRelativePath.setDirectory(initDir)
        dlgRelativePath.setFileMode(QFileDialog.FileMode.Directory)

        fixeLabelsFileDialog(self, dlgRelativePath, 0, False)      

        if dlgRelativePath.exec(): self.updateRelativePath(dlgRelativePath.selectedFiles()[0])

    def setRelativePath(self, refPath, path):
        infosRefPath = refPath.split("/")
        infosPath = path.split("/")
        if infosRefPath[0] == infosPath[0]: return relpath(path, refPath), True
        else : return path, False

    def updateRelativePath(self, path):
        if path == "" : return
        if self.listFilesWidget.currentRow() < 0 : return
        key = self.listFilesWidget.currentItem().toolTip()
        if key != "":
           if not path.endswith("/") : path = cleanPath(path)
           if exists(path) : 
              relativePath, isRelativePath = self.setRelativePath(dirname(key), path) 
              if isRelativePath : path = relativePath
              self.relativePath.setCheckable(isRelativePath)
           else :
              isRelativePath = True if exists("%s/%s" % (dirname(key), path)) else False
              #if not isRelativePath : path = ""

           text = translateMsg("Relative path") if isRelativePath else translateMsg("Absolute path")
           self.relativePath.setText(text)
           self.relativePath.setToolTip(self.relativePath.text())
           
        self.relativePathFolder.setPlainText(path)
        self.updateInfo(self.relativePathFolder)

    def deleteRelativePath(self):
        self.relativePathFolder.setPlainText("")
        self.updateInfo(self.relativePathFolder)     
        
    def loadRasterForExtent(self): 
        self.forceUpdate = True
        self.updateMapCanvasProject()
        self.forceUpdate = False

    def copyRasterForExtent(self):      
        if not self.currentLayer : return        
        activeLayer = self.iface.activeLayer()
        if not activeLayer :
               self.barInfo.pushMessage("%s :" % translateMsg("Information"), "%s ..." % translateMsg("No active layer"), Qgis.Info, 3)
               return 
        if len(activeLayer.selectedFeatures())== 0 :
               self.barInfo.pushMessage("%s :" % translateMsg("Information"), "%s [<b>%s<//b>]..." % (translateMsg("No selection in active layer"), activeLayer.name()), Qgis.Info, 3)
               return           
        
        title = translateMsg("Select the folder")
        dlgRelativePath = QFileDialog(self, title)
        dlgRelativePath.setDirectory(self.initDirShp)
        dlgRelativePath.setFileMode(QFileDialog.FileMode.Directory)

        fixeLabelsFileDialog(self, dlgRelativePath, 0, False)      

        if dlgRelativePath.exec():

           folderDest = dlgRelativePath.selectedFiles()[0]
           self.initDirShp = folderDest

           if self.canvas.layers() == [] :
              if self.currentLayer : self.rbgeomdalles.reset(); self.currentLayer.removeSelection(); self.mapViewerWmsGrid.refresh();
              return 

           if self.currentLayer :
              selectedSet, featIds = [], []
              g = self.getGeomCurrentLayer()

              group = self.getGroupRaster(True)
              key = self.getKeyForGridLayer(self.listFiles.currentIndex())
              index = self.getIndexLayerField(key)
              if index < 0 : return


              path = "%s%s" % (dirname(key), self.dictGridRaster[key]["relativePathFolder"]) if self.dictGridRaster[key]["relativePath"] else ""

              #PROGRESS BAR
              self.barInfo.clearWidgets()
              progressMessageBar = self.barInfo.createMessage("%s ..." % translateMsg("Copy files"))
              progress = QProgressBar()
              progress.setAlignment(Qt.AlignmentFlag.AlignLeft|Qt.AlignmentFlag.AlignVCenter)
              progressMessageBar.layout().addWidget(progress)
              self.barInfo.pushWidget(progressMessageBar, Qgis.Info)
      
              i = 1
              counterAll = 0
              for feature in activeLayer.selectedFeatures():
                  #PROGRESS BAR
                  progressMessageBar = self.barInfo.createMessage("%s %s / %s ..." % (translateMsg("Copy files"), i, len(activeLayer.selectedFeatures())))
                  counter = 0
                  selectedSet, featIds = [], []
                  selectedSet, featIds = self.intersectsOp(self.currentLayer, selectedSet, featIds, index, feature.geometry())
                  i+= 1

                  nbCounter = len(selectedSet)
                  progress.setMaximum(nbCounter)
                  

                  for fileName in selectedSet :
                      raster = "%s%s" % (path, fileName)
                      if exists(raster):
                         destFile = "%s/%s" % (folderDest, basename(raster))
                         if not exists(destFile) : shutil.copy(raster, destFile); counter+= 1
                      else :
                         raster = "%s.%s" % (raster, self.dictGridRaster[key]["listExtension"])
                         if exists(raster) :
                            destFile =  "%s/%s" % (folderDest, basename(raster))
                            if not exists(destFile) : shutil.copy(raster, destFile); counter+= 1
                      progress.setValue(counter)
                      self.barInfo.repaint()

                  counterAll+= counter
                   
              self.barInfo.clearWidgets()
              
              title = translateMsg("Information")
              msg = translateMsg("Copy %s files successed !" % counterAll)
              self.barInfo.pushMessage("%s :" % title, "%s" % msg, Qgis.Info, 3)
    

    def getSpatialIndex(self, layer):
        spatialIndex = None
        if layer :
           spatialIndex = QgsSpatialIndex()
           feat = QgsFeature()
           features = layer.dataProvider().getFeatures()
           while features.nextFeature(feat): spatialIndex.addFeature(feat)

        return spatialIndex   

    def getNeighBors(self, geom, nb):
        if self.currentLayer :
           if self.spatialIndex :
              return self.spatialIndex.nearestNeighbor(geom, nb)
        return []

    def getIdRaster(self, Ids, index):
        if index < len(self.currentLayer.fields()) :
           try : return [self.currentLayer.getFeature(id)[index] for id in Ids]
           except : return []
        else : return []   

    def setVisibleValue(self):
        value = "%s" % (self.sender().value())
        self.sender().setToolTip(value)
        self.txtSliderNeighBors.setText(value)
  
    def getIndexLayerField(self, key) :
        index = -1
        if dicoHasKey(self.dictGridRaster, key) :
           field = self.dictGridRaster[key]["listFields"]
           index = self.currentLayer.dataProvider().fieldNameIndex(field)
           if index == -1 : index = len(self.currentLayer.fields())
        return index
       
    def updateMapCanvasProject(self, *args):
        if self.canvas.layers() == [] :
           if self.currentLayer : self.rbgeomdalles.reset(); self.currentLayer.removeSelection(); self.mapViewerWmsGrid.refresh();

        if self.currentLayer :
           selectedSet, featIds = [], []
           g = self.getGeomCurrentLayer()

           key = self.getKeyForGridLayer(self.listFiles.currentIndex())
           index = self.getIndexLayerField(key)
           if index < 0 : return

           selectedSet, featIds = self.intersectsOp(self.currentLayer, selectedSet, featIds, index, g)           
           try :    nearestIds = self.getNeighBors(g.centroid().asPoint(), self.sliderNeighBors.value())
           except : nearestIds = []
           if nearestIds == [] : return

           if len(nearestIds) < len(selectedSet) and index != len(self.currentLayer.fields()) :  selectedSet = self.getIdRaster(nearestIds, index)
           if self.updateLive.isChecked() or self.forceUpdate : self.loadRaster(selectedSet)

           self.rbgeomdalles.reset()
          
           geomRasterView = self.updateView(g)
           geom = QgsGeometry.fromMultiPolygonXY(geomRasterView)
           self.rbgeomdalles.setToGeometry(geom, None) 
           self.rbCanvas.reset()
           

    def getGeomCurrentLayer(self):
           g, coords = None, []
           selectedSet, featIds = [], []
           [coords.append(QgsMapTool(self.mapViewerWmsGrid).toLayerCoordinates(self.currentLayer, self.rb.getPoint(0,i))) for i in range(self.rb.numberOfVertices())]
           g = QgsGeometry().fromPolygonXY([coords])
           return g


    def updateView(self, g):

           root = QgsProject.instance().layerTreeRoot() 
           group = self.getGroupRaster(False)
           if group :
              obj = group if self.checkVisibilityService.isChecked() else root
           else : obj = root
           if not obj : return
           geomRasterView = []
       
           for layer in obj.findLayers() :
                rasterLayer = layer.layer()
                if type(rasterLayer) == QgsRasterLayer :
                    extent = rasterLayer.dataProvider().extent()
                    self.rbRectangle(self.rbCanvas, extent, True) 
                    coords = []
                    [coords.append(QgsMapTool(self.canvas).toLayerCoordinates(rasterLayer, self.rbCanvas.getPoint(0,i))) for i in range(self.rbCanvas.numberOfVertices())]
                    geomRaster = QgsGeometry().fromPolygonXY([coords])                    
                    cond = geomRaster.intersects(g)
                    
                    if self.checkVisibility.isChecked() : layer.setItemVisibilityChecked(cond)
                    
                    refLayer = self.bgLayer if self.bgLayer else self.currentLayer
                    points = [[ QgsMapTool(self.canvas).toLayerCoordinates(refLayer, QgsPointXY(extent.xMinimum(),extent.yMaximum())),
                                QgsMapTool(self.canvas).toLayerCoordinates(refLayer, QgsPointXY(extent.xMaximum(),extent.yMaximum())),
                                QgsMapTool(self.canvas).toLayerCoordinates(refLayer, QgsPointXY(extent.xMaximum(),extent.yMinimum())),
                                QgsMapTool(self.canvas).toLayerCoordinates(refLayer, QgsPointXY(extent.xMinimum(),extent.yMinimum())),
                                QgsMapTool(self.canvas).toLayerCoordinates(refLayer, QgsPointXY(extent.xMinimum(),extent.yMaximum()))                                
                             ]]    
 
                    geomRasterView.append(points)
  
           return geomRasterView
    
    def rbGeom(self, rb, geom, crs, reset):
        if reset : rb.reset(); rb.addGeometry(geom, crs)
               
    def rbRectangle(self, rb, extent, reset):
        
        if reset : rb.reset()
        
        rb.addPoint(QgsPointXY(extent.xMinimum(),extent.yMaximum()))
        rb.addPoint(QgsPointXY(extent.xMaximum(),extent.yMaximum()))
        rb.addPoint(QgsPointXY(extent.xMaximum(),extent.yMinimum()))
        rb.addPoint(QgsPointXY(extent.xMinimum(),extent.yMinimum()))
        rb.addPoint(QgsPointXY(extent.xMinimum(),extent.yMaximum()))

    def zoomIn(self): self.initToolHotLinksButton(); self.mapViewerWmsGrid.setMapTool(self.toolZoomIn) 
    def zoomOut(self): self.initToolHotLinksButton(); self.mapViewerWmsGrid.setMapTool(self.toolZoomOut)
    def pan(self): self.initToolHotLinksButton(); self.mapViewerWmsGrid.setMapTool(self.toolPan)

    def zoomToGroup(self):
        group = self.getGroupRaster(False)
        if group :
           extent = QgsRectangle()
           i = 0
           for layer in group.findLayers() :
               rasterLayer = layer.layer()
               if type(rasterLayer) == QgsRasterLayer :                 
                  if i == 0 : extent = rasterLayer.dataProvider().extent()
                  else : extent.combineExtentWith( rasterLayer.dataProvider().extent() )
                  i+= 1   
           self.canvas.setExtent( extent )
           self.canvas.refresh()
    
    
    def zoomAll(self): self.mapViewerWmsGrid.zoomToFullExtent(); self.updateMire()
    def zoomToCurrentLayer(self) :
        if self.currentLayer :
           extent = self.currentLayer.extent()
           if self.currentLayer.crs().authid() != self.projectAlr.crs().authid():
              tr = QgsCoordinateTransform(self.currentLayer.crs(), self.crs, self.projectAlr) 
              extent = tr.transform(extent)
           self.mapViewerWmsGrid.setExtent(extent)
           self.mapViewerWmsGrid.refresh()
           
    #NEW 3.6.4
    def zoomPrevious(self):
        self.currentExtent = zoomPreviousExtent(self.currentExtent, self.extents, self.mapViewerWmsGrid)
        self.updateButtonZoomNextPrevious()
    def zoomNext(self):
        self.currentExtent = zoomNextExtent(self.currentExtent, self.extents, self.mapViewerWmsGrid)
        self.updateButtonZoomNextPrevious()
    def updateButtonZoomNextPrevious(self):
        self.buttonZoomPrevious.setEnabled(self.currentExtent > 0)
        self.buttonZoomNext.setEnabled(self.currentExtent < len(self.extents)-1)

    def linkedMapcanvas(self) :
        if self.linkMapCanvas.isChecked() : self.sendExtentToMapCanvas()

    def updateMapViewerWithGrid(self) :
        if self.listFiles.currentIndex() > -1 :
           index = self.listFiles.currentIndex()
           modelIndex = self.listFiles.model().index(index, 0)
           key = self.listFiles.model().data(modelIndex, Qt.ItemDataRole.UserRole)
           #NEW 3.4.0
           cond = exists(key)
           self.listFiles.setItemData(index, 33, Qt.ItemDataRole.UserRole -1) if cond else self.listFiles.setItemData(index, 0, Qt.ItemDataRole.UserRole -1)
           if not cond :
              if dicoHasKey(self.dictGridRaster, key) : self.listFilesWidget.setCurrentRow(self.listFiles.currentIndex())
              else :
                  msg = translateMsg("Cannot open file")
                  self.barInfo.pushMessage(translateMsg("Warning"), "%s : %s." % (msg, self.listFiles.currentText()), Qgis.Warning, 3)
              return
           
           test = False
           if self.currentLayer :
              try : key != self.currentLayer.source(); test = True
              except : pass
           else : test = True   

           if test :
               self.getLayerGrid(key)
               #NEW 3.4.0
               if not dicoHasKey(self.dictGridRaster, key) : self.updateRelativePath(self.relativePathFolder.toPlainText())
               else : self.listFilesWidget.setCurrentRow(self.listFiles.currentIndex())
               self.zoomToCurrentLayer()

           
    def updateMire(self) :
        if self.linkMapCanvas.isChecked() :
            self.canvas.blockSignals(True)
            extent = self.mapViewerWmsGrid.extent()
            if self.crs != QgsProject(self.iface).instance().crs() :
               tr = QgsCoordinateTransform(self.crs, QgsProject(self.iface).instance().crs(), QgsProject(self.iface).instance()) 
               try : extent = tr.transform(extent)
               except : pass
            self.canvas.setExtent(extent)
            self.canvas.refresh()
            self.canvas.blockSignals(False)
            return
        
            
        self.lastExtent = self.mapViewerWmsGrid.extent()
        
        tr = QgsCoordinateTransform(QgsProject(self.iface).instance().crs(), self.crs, self.projectAlr) 
        try :
            extent = tr.transform(self.canvas.extent())
            self.rbMire(extent) 
            self.mapViewerWmsGrid.refresh()

            self.updateBoxValues()
        except : pass
        
        if self.updateLive.isChecked() : self.updateMapCanvasProject() 
        if self.checkVisibility.isChecked() : self.updateMapCanvasProject() 
 

    def updateMireMapViewer(self) :
           if self.currentLayer : self.currentLayer.removeSelection()
           self.linkedMapcanvas()

    def updateMireWithSynchroMap(self):
        self.sendExtentToMapCanvas()
        self.rbMire(self.mapViewerWmsGrid.extent())
        self.mapViewerWmsGrid.refresh()

        
    def rbMire(self, extent):

           meanX = extent.xMinimum() + abs((extent.xMaximum()-extent.xMinimum())/2)
           meanY = extent.yMinimum() + abs((extent.yMinimum()-extent.yMaximum())/2)
          
           self.rbaxesh.reset()
           self.rbaxesh.addPoint(QgsPointXY(self.mapViewerWmsGrid.extent().xMinimum(), meanY))
           self.rbaxesh.addPoint(QgsPointXY(self.mapViewerWmsGrid.extent().xMaximum(), meanY))

           self.rbaxesv.reset()
           self.rbaxesv.addPoint(QgsPointXY(meanX, self.mapViewerWmsGrid.extent().yMinimum()))
           self.rbaxesv.addPoint(QgsPointXY(meanX, self.mapViewerWmsGrid.extent().yMaximum()))

           self.rbRectangle(self.rb, extent, True)


    def intersectsOp(self, layer, selectedSet, featIds, index, g):
        if not layer : return

        key = layer.source()
        expression = None
        if self.dictGridRaster != [] :
           if dicoHasKey(self.dictGridRaster, key):  expression = self.dictGridRaster[key]["listFields"] 
        else : return [], []

        features = layer.getFeatures(QgsFeatureRequest())
        for feat in features :        
            geom = feat.geometry()
            self.scope.setFeature(feat)
            self.context.appendScope(self.scope)

            if geom and g:
                if geom.intersects(g) :
                   if index < len(layer.fields()) : selectedSet.append(feat[index])
                   else :
                     if not expression : return [], []
                     value = self.evaluateExpression(self.context, feat, expression)
                     selectedSet.append(value)
                   featIds.append(feat.id())
                  
        return selectedSet , featIds        

    def evaluateExpression(self, context, feat, expression):
            expression = QgsExpression(expression)
            value = expression.evaluate(context)
            return value


    def loadForSelectedObj(self):
        activeLayer = self.iface.activeLayer()
        if not activeLayer :
           self.barInfo.pushMessage("%s :" % translateMsg("Information"), "%s ..." % translateMsg("No active layer"), Qgis.Info, 3)
           return           

        if activeLayer.type() == 0 : 

           if not activeLayer.selectedFeatures() :
                     self.barInfo.pushMessage("%s :" % translateMsg("Information"),
                                              "%s : %s" % (translateMsg("No selection in active layer"), activeLayer.name()), Qgis.Info, 3)
                     return
                    
           group = self.getGroupRaster(True)
           key = self.getKeyForGridLayer(self.listFiles.currentIndex())
           index = self.getIndexLayerField(key)
           if index < 0 : return
          
           for feature in activeLayer.selectedFeatures(): 
               selectedSet, featIds = [], []
               selectedSet, featIds = self.intersectsOp(self.currentLayer, selectedSet, featIds, index, feature.geometry()) 
               self.loadRaster(selectedSet)

        elif activeLayer.type() == 1 :

                     key = self.currentLayer.source()
                     expression = None
                     if self.dictGridRaster != [] :
                        if dicoHasKey(self.dictGridRaster, key):  expression = self.dictGridRaster[key]["listFields"] 
                     else : return [], []

                     extent = activeLayer.extent()
                     
                     points = []
                     points.append(QgsPointXY(extent.xMinimum(), extent.yMaximum()))
                     points.append(QgsPointXY(extent.xMaximum(), extent.yMaximum()))
                     points.append(QgsPointXY(extent.xMaximum(), extent.yMinimum()))
                     points.append(QgsPointXY(extent.xMinimum(), extent.yMinimum()))
                     points.append(QgsPointXY(extent.xMinimum(), extent.yMaximum()))
                     
                     geom = QgsGeometry().fromPolygonXY([points])

                     key = self.getKeyForGridLayer(self.listFiles.currentIndex())
                     index = self.getIndexLayerField(key)
                     if index < 0 : return

                     selectedSet, featIds = [], []
                     selectedSet, featIds = self.intersectsOp(self.currentLayer, [], [], index, geom)
                     self.loadRaster(selectedSet)
       


    def getKeyForGridLayer(self, index):
        modelIndex = self.listFiles.model().index(index, 0)
        key = self.listFiles.model().data(modelIndex, Qt.ItemDataRole.UserRole)
        return key

    def removeRaster(self, selectedSet):
        if selectedSet == []: return
        key = self.getKeyForGridLayer(self.listFiles.currentIndex())
        refPath = dirname(key)
        if not refPath.endswith("/") : refPath = cleanPath(refPath)
        path = "%s/%s" % (refPath, self.dictGridRaster[key]["relativePathFolder"])  if self.dictGridRaster[key]["relativePath"] else self.dictGridRaster[key]["relativePathFolder"]
        for raster in selectedSet :
            source = raster
            if not exists(source): 
               source = "%s%s" % (path, raster)
               if not exists(source):
                  source = "%s%s.%s" % (path, raster, self.dictGridRaster[key]["listExtension"])
                  if not exists(source):
                     source = "%s.%s" % (raster, self.dictGridRaster[key]["listExtension"])
            for lyr in QgsProject.instance().mapLayers().values():
                if lyr.source() == source : QgsProject.instance().removeMapLayer(lyr)
        self.canvas.refresh()
    
    def loadRaster(self, selectedSet):
        if selectedSet == []: return
        key = self.getKeyForGridLayer(self.listFiles.currentIndex())
        refPath = dirname(key)
        if not refPath.endswith("/") : refPath = cleanPath(refPath)
        path = "%s/%s" % (refPath, self.dictGridRaster[key]["relativePathFolder"])  if self.dictGridRaster[key]["relativePath"] else self.dictGridRaster[key]["relativePathFolder"]

        commandFiles = ""

        for fileName in selectedSet :
            if urlparse.urlparse(fileName).scheme :
               commandFiles+= "%s<br>" % fileName
            else :
              if path == "" :
                 if exists(fileName): self.loadTheFile(fileName)
                 else : 
                       title = translateMsg("Information")
                       self.barInfo.pushMessage("%s :" % title, "%s :<br>%s" % (translateMsg("Not found"), fileName), Qgis.Warning, 3)
                 
              else : 
                  raster = "%s%s" % (path, fileName)
                  if exists(raster): self.loadTheFile(raster)
                  else :
                     raster = "%s.%s" % (raster, self.dictGridRaster[key]["listExtension"])
                     if exists(raster): self.loadTheFile(raster)
                     else : 
                        title = translateMsg("Information")
                        self.barInfo.pushMessage("%s :" % title, "%s :<br>%s" % ("Not found", raster), Qgis.Warning, 3)

        if commandFiles != "" :
           QMessageBox.information(self, "AutoLoaderRaster", "<center>%s :<br><img src='%s'></center><br>%s" % (translateMsg("Order or Download the files"), getThemeIcon("checkliveupdate.png"),
                                                                                                                commandFiles))                                                                                                                
                     
    
    def loadTheFile(self, fileName):
        cond = self.inCurrentLayers(fileName)
        
        if not cond :
           group = self.getGroupRaster(True)
           nameLayer = basename(fileName).split(".")[0]

           extension = getExtension(fileName).replace(".", "")

           if (extension in self.gdalListExtensions) : rasterLayer = QgsRasterLayer(fileName, nameLayer, "gdal")
           else : rasterLayer = QgsVectorLayer(fileName, nameLayer, "ogr")

           if rasterLayer :
               
               QgsProject.instance().addMapLayer(rasterLayer, False)
               nodeLayer = QgsLayerTreeLayer(rasterLayer)
               group.insertChildNode(0, nodeLayer)

               baseName = xPath(fileName).stem
               fileQml = "%s/%s.qml" % (dirname(__file__), baseName)
               if exists(fileQml) : nodeLayer.layer().loadNamedStyle(fileQml, QgsMapLayer.AllStyleCategories)

               self.canvas.refresh()


    def getGroupRaster(self, force):
         s = QSettings()
         grpRdi = s.value("%sgrpRdi" % self.parent.settings)
         
         try : layer = self.iface.activeLayer()
         except : return         
         root = QgsProject(self.iface).instance().layerTreeRoot()
         index = len(root.children())
         key = self.getKeyForGridLayer(self.listFiles.currentIndex())

         if grpRdi == "" :
            nameGroup = self.dictGridRaster[key]["groupRaster"]
            if nameGroup == "" : nameGroup = "autoLoaderRasterPlugin"
         else : nameGroup = grpRdi
         
         group = root.findGroup(nameGroup)
         if not group :
            groupWms = self.getWmsGroupRaster()
            if groupWms : index-= 1
            
            if force : group = root.insertGroup(index, nameGroup); expanded = True;
         else : expanded = group.isExpanded()
         if self.openGroup.isChecked() : expanded = True
         if group : group.setExpanded(expanded)
       
         return group

    def cleanGroupRaster(self):
        if self.updateLive.isChecked() :
           QMessageBox.information(self, "AutoLoaderRaster", "<center>%s :<br><img src='%s'></center>" % (translateMsg("Live update"), getThemeIcon("checkliveupdate.png")))
           return

        #NEW 3.4.0
        reply = QMessageBox.question(self, translateMsg("Question"), translateMsg("Do you want to keep the group ?"), QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No)
      
        group = self.getGroupRaster(False)
        if group :
           group.removeAllChildren()
           if reply ==  QMessageBox.StandardButton.No :
              root = QgsProject(self.iface).instance().layerTreeRoot()
              root.removeChildNode(group)
           
        self.updateMapCanvasProject()

         
    def inCurrentLayers(self, layerPath):
        root = QgsProject.instance().layerTreeRoot()
        for layer in root.findLayers() :
            geoLayer = layer.layer()
            if type(geoLayer) == QgsRasterLayer :
                if basename(layerPath) == basename(geoLayer.source()) : return True
        return False

    def chooseGridFile(self):
            oldName = self.lblGridRaster.text()
            item = self.listFilesWidget.currentItem()

            title = "%s ..." % translateMsg("Select the grid raster file")
            dlgFile = QFileDialog(self, title)
            elt = translateMsg("files").title()
            dlgFile.setNameFilters(("%s ESRI (*.shp *.SHP)" % (elt), ))
            dlgFile.setViewMode(QFileDialog.ViewMode.Detail)
            if self.lblGridRaster.text() == "" : dlgFile.setDirectory(self.initDirShp)
            else :
               folder = dirname(self.lblGridRaster.text())
               if exists(folder) : dlgFile.setDirectory(folder)
               else : dlgFile.setDirectory(self.initDirShp)
                 
            dlgFile.setFileMode(QFileDialog.FileMode.ExistingFiles) 
            dlgFile.setAcceptMode(QFileDialog.AcceptMode.AcceptOpen)

            fixeLabelsFileDialog(self, dlgFile, 0, True)
            
            if dlgFile.exec():
                fileName = "%s" % (dlgFile.selectedFiles()[0])
                inputFile = QFileInfo(fileName) 
                extension = inputFile.suffix().lower() 
                if fileName != "" :
                   if self.listFiles.findData(fileName) == -1 :
                       self.initDirShp = dirname(fileName)
                       self.lblGridRaster.setText(fileName)

                       self.dictGridRaster[fileName] = self.dictGridRaster.pop(oldName)
                       index = self.listFiles.findData(oldName)

                       if index > -1 and item :
                          self.listFiles.setItemData(index, fileName, Qt.ItemDataRole.UserRole)
                          item.setToolTip(fileName)
                       self.getLayerFields(fileName) 

                       self.getInfosGridRaster()

                   else :
                       self.barInfo.pushMessage("%s :" % translateMsg("Information"),
                                                "%s (%s)" % (translateMsg("File already present"), fileName), Qgis.Warning, 3)


    def selectListFiles(self):
            title = "%s ..." % translateMsg("Select the grid raster file")
            dlgFile = QFileDialog(self, title)
            elt = translateMsg("files").title()
            dlgFile.setNameFilters(("%s ESRI (*.shp *.SHP)" % (elt), ))
            dlgFile.setViewMode(QFileDialog.ViewMode.Detail)
            dlgFile.setDirectory(self.initDirShp)
            dlgFile.setFileMode(QFileDialog.FileMode.ExistingFiles) 
            dlgFile.setAcceptMode(QFileDialog.AcceptMode.AcceptOpen)

            fixeLabelsFileDialog(self, dlgFile, 0, True)
            
            if dlgFile.exec():
                fileName = "%s" % (dlgFile.selectedFiles()[0])
                inputFile = QFileInfo(fileName) 
                extension = inputFile.suffix().lower() 
                if fileName != "" :
                   if self.listFiles.findData(fileName) == -1 :
                       self.initDirShp = dirname(fileName)
                       self.listFiles.blockSignals(True)
                       self.lblGridRaster.setText(fileName)
                       self.listFiles.addItem(fileName)
                       self.listFiles.setItemIcon(self.listFiles.count()-1, QIcon(getThemeIcon("gridraster.png")))
                       item = QListWidgetItem(QIcon(getThemeIcon("gridraster.png")), basename(fileName), self.listFilesWidget)
                       item.setToolTip(fileName)
                       #NEW 4.0.0
                       index = self.listFiles.currentIndex()
                       modelIndex = self.listFiles.model().index(index, 0)
                       self.listFiles.model().setData(modelIndex, basename(fileName), Qt.ItemDataRole.UserRole)
                       self.usualName.setPlainText("%s %s" % (translateMsg("Raster files grid"), self.listFiles.count()-1))
                       
                       self.getLayerFields(fileName)
                       self.groupRaster.setPlainText(basename(fileName).split(".")[0])
                       self.relativePathFolder.setPlainText("")
                       self.initInfosGridRaster(fileName)
                       
                       self.counterXmlGridFiles.setText("%s" % len(self.dictGridRaster))
                       self.listFiles.blockSignals(False)
                       
                       #ducon
                       self.listFilesWidget.setCurrentItem(item)
                       #self.updateMapViewerWithGrid()
                       
                       

                   else :
                       self.barInfo.pushMessage("%s :" % translateMsg("Information"),
                                                "%s (%s)" % (translateMsg("File already present"), fileName), Qgis.Warning, 3)
                       
    def setlistFilesWidget(self):
        self.listFilesWidget.clear()
        item = None
        for key in self.dictGridRaster :
                item = QListWidgetItem(QIcon(getThemeIcon("gridraster.png")), basename(key), self.listFilesWidget)
                item.setToolTip(key)
        if item : self.listFilesWidget.setCurrentItem(item)
        else :
           self.lblGridRaster.setText("")
           self.groupRaster.setPlainText("")
           self.listFields.clear()
           self.relativePathFolder.setPlainText("")

            

    def deleteInListFiles(self):
        if self.listFilesWidget.currentRow() < 0 : return
        key = self.listFilesWidget.currentItem().toolTip()
        if key in self.dictGridRaster : del self.dictGridRaster[key]
        self.setlistFilesWidget()
        index = self.listFiles.findData(key)
        self.listFiles.removeItem(index)
        
        if self.currentLayer.source() == key :
           self.projectAlr.removeMapLayers([self.currentLayer.id()])
           self.currentLayer = None
           self.mapViewerWmsGrid.refresh()

        self.counterXmlGridFiles.setText("%s" % len(self.dictGridRaster))    
       

    def initInfosGridRaster(self, key):
        self.dictGridRaster[key] = {"usualName" : self.usualName.toPlainText(),
                                   "listFields" : self.listFields.currentText(),
                                   "relativePath" : self.relativePath.isChecked(),
                                   "relativePathFolder" : self.relativePathFolder.toPlainText(),
                                   "groupRaster" : self.groupRaster.toPlainText(),
                                   "listExtension" : self.listExtension.currentText(),
                                   "projRaster" : self.projRaster.crs().authid()} 

    def updateInfosGridRaster(self):
        obj = self.sender()
        if obj : self.updateInfo(obj)
        
    def setEnabledExpression(self, cond):
        self.listFields.setEnabled(cond)
        self.expressionButton.setEnabled(cond)

    def updateInfo(self, obj):
        if not obj : return
        keyInfo = obj.objectName()
        if self.listFilesWidget.currentRow() < 0 : return
        item = self.listFilesWidget.currentItem() 
        key = item.toolTip()
        
        if keyInfo in ("usualName", "relativePathFolder", "groupRaster") : value = obj.toPlainText()
        elif keyInfo in ("listFields", "listExtension") :

             if keyInfo == "listFields" :
                expressionText = obj.currentText()
                expression = QgsExpression(expressionText)
                key = self.lblGridRaster.text()
                value = None

                cond = exists(key)
                self.setEnabledExpression(cond)

                if cond :

                   layer = QgsVectorLayer(key, basename(key), "ogr")
                   for feat in layer.getFeatures(QgsFeatureRequest()) : self.context.setFeature(feat); break ; 
                   value = expression.evaluate(self.context)

                #obj.setStyleSheet(self.styleErrorComboBox) if not value else obj.setStyleSheet(self.styleComboBox)

                if not value : return

                  
             
             value = obj.currentText()
             if keyInfo == "listFields" : obj.setStyleSheet(self.styleComboBox)

             
        elif keyInfo == "projRaster" : value = obj.crs().authid()
        else : value = obj.isChecked()

        self.dictGridRaster[key][keyInfo] = value

        if keyInfo == "usualName" :
           item.setText(value)
           index = self.listFiles.findData(key)
           self.listFiles.setItemText(index, value)


    def setInfos(self, infos):
        self.usualName.setPlainText(infos["usualName"])
        self.listFields.setCurrentText(infos["listFields"])
        self.relativePath.setChecked(infos["relativePath"])
        self.relativePathFolder.setPlainText(infos["relativePathFolder"])
        self.groupRaster.setPlainText(infos["groupRaster"])
        self.listExtension.setCurrentText(infos["listExtension"])

           
    def getInfosGridRaster(self): 
      
       if not self.listFilesWidget.currentItem() : return
       key = self.listFilesWidget.currentItem().toolTip()
       cond = exists(key)
       if not cond :
          title = translateMsg("Warning")
          self.barInfo.pushMessage("%s :" % title, "%s : %s" % (translateMsg("Not found"), self.listFilesWidget.currentItem().text()), Qgis.Warning, 3)
           
       self.lblGridRaster.setText(key)
       self.lblGridRaster.setMyStyleSheet("special") if cond else self.lblGridRaster.setMyStyleSheet("error")
       #NEW 3.4.0
       row = self.listFilesWidget.currentRow()
       icon = QIcon(getThemeIcon("gridraster.png")) if cond else QIcon(getThemeIcon("gridrasterbad.png"))
       self.listFilesWidget.currentItem().setIcon(icon)
       self.listFiles.setItemIcon(row, icon)
       self.listFiles.setItemData(row, 33, Qt.ItemDataRole.UserRole -1) if cond else self.listFiles.setItemData(row, 0, Qt.ItemDataRole.UserRole -1)       
       
       fieldsNames = self.getLayerFields(key)
       self.spatialIndex = self.getSpatialIndex(self.currentLayer)
       infos = self.dictGridRaster[key]

       if not infos["listFields"] in fieldsNames : self.listFields.addItem(infos["listFields"])        
        
       expressionText = infos["listFields"]
       expression = QgsExpression(expressionText)

 
       self.setEnabledExpression(cond)
       value = None

       if cond :
          layer = QgsVectorLayer(key, basename(key), "ogr")
          for feat in layer.getFeatures(QgsFeatureRequest()) : self.context.setFeature(feat); break ;
          value = expression.evaluate(self.context)
    
       self.listFields.setStyleSheet(self.styleErrorComboBox) if not value else self.listFields.setStyleSheet(self.styleComboBox) 
          
       try : crs = infos["projRaster"]; self.projRaster.setCrs(QgsCoordinateReferenceSystem(crs)) ; 
       except :
              try : crs = self.getLayerCrs(key)
              except: pass
       self.setInfos(infos)
       
       self.updateRelativePath(self.relativePathFolder.toPlainText())

    def getLayerCrs(self, fileName):
       crs = None
       if exists(fileName):
          self.projRaster.blockSignals(True)
          layer = QgsVectorLayer(fileName, basename(fileName), "ogr")
          try : crs = layer.crs(); self.projRaster.setCrs(crs);
          except : pass
          self.projRaster.blockSignals(False)
       return crs   

    def getLayerFields(self, fileName):
       fieldsNames = [] 
       if exists(fileName):
          self.listFields.blockSignals(True)
          layer = QgsVectorLayer(fileName, basename(fileName), "ogr")
          fieldsNames = [field.name() for field in layer.fields()]
          self.listFields.clear()
          self.listFields.addItems(fieldsNames)
          self.listFields.blockSignals(False)
       return fieldsNames
                  
    def checkExtentField(self, layer):
        fieldsNames = layer.fields().names()
        if "extent" in fieldsNames :
           indexForExtentGeom = fieldsNames.index("extent")
           
           features = layer.getFeatures(QgsFeatureRequest())
           for feat in features :        
               wktGeom = feat[indexForExtentGeom]
               try :
                   geom = QgsGeometry().fromWkt("%s" % wktGeom)
                   return True, indexForExtentGeom
               except : return False, -1
        else : return False, -1

            
    def getLayerGrid(self, fileName):
            if self.currentLayer :
               try : self.projectAlr.removeMapLayers([self.currentLayer.id()])
               except : pass
              
               self.currentLayer = QgsVectorLayer(fileName, basename(fileName), "ogr")
               self.spatialIndex = self.getSpatialIndex(self.currentLayer)
               self.getQml()
               if self.bgLayer : self.mapViewerWmsGrid.setLayers([self.currentLayer, self.bgLayer])
               else : self.mapViewerWmsGrid.setLayers([self.currentLayer])
               self.currentLayer.select([])

               self.hasExtentForGeom, self.indexForExtentGeom = self.checkExtentField(self.currentLayer)
               
            


    def getExpression(self):
           if self.listFilesWidget.currentItem() :

              fileName = self.listFilesWidget.currentItem().toolTip()
              layer = QgsVectorLayer(fileName, basename(fileName), "ogr")                                                            

              changeButtonIcon(self, self.sender(),"expressionedit.png", 24, 24)
              
              expressionText = self.listFields.currentText() 
              expression = QgsExpression(expressionText)
              
              for feat in layer.getFeatures() : self.scope.setFeature(feat); break ;
              value = expression.evaluate(self.context)

              builder = QgsExpressionBuilderDialog(layer, expressionText , self ) 
              windowIcon(builder, "geomaker/expressionedit.png")
              
              if (builder.exec() == QDialog.DialogCode.Accepted):

                  if not expressionText != builder.expressionText(): changeButtonIcon(self, self.sender(),"expression.png", 24, 24); return;
                  
                  expression = QgsExpression(builder.expressionText())
                  value = expression.evaluate(self.context)

                  self.listFields.setStyleSheet(self.styleErrorComboBox) if not value else self.listFields.setStyleSheet(self.styleComboBox)

                  lenFields = len(layer.fields())
                  if (self.listFields.count()== lenFields): self.listFields.addItem(builder.expressionText())
                  else : self.listFields.setItemText(lenFields, builder.expressionText())
                  self.listFields.setCurrentIndex(self.listFields.count()-1)
                  self.updateInfo(self.listFields)

              changeButtonIcon(self, self.sender(),"expression.png", 24, 24)




def actionsWindows(parent, name, title, width, height):
        self = QMdiSubWindow(parent)
        self.setObjectName(name)
        self.setWindowTitle(title)
        
        self.setWindowFlags(Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowMinimizeButtonHint | Qt.WindowType.WindowMaximizeButtonHint)
        self.setFixedSize(width, height)
        self.setGeometry(10, 10, width, height)

        self.setStyleSheet("QMdiSubWindow { border: 1px solid;    border-radius: 5px;    opacity: 0.5;    background-color: rgba(255, 255, 255, 50);}"
                           "QMdiSubWindow QWidget { background-color: transparent; border:1px;}"
                           "QMdiSubWindow:title { height: 18px; background-color: rgba(255, 255, 255, 50);}")
        self.oldPos = self.pos()

        return self

def ctrlMap(self, conteneur, complete, getPointsForExtent, simply, iX, iY, iW, iH, allActions):
        
         self.groupMap = QGroupBox(conteneur)

         self.actionsMapCanvas = QButtonGroup(conteneur) 
         self.actionsMapCanvas.setExclusive(True)

         if allActions :
             #NEW 3.6.4
             dicoCtrls = {"buttonCatchExtent" : ("catchextent.png", "Get extent for QGIS mapcanvas", 10, 20),
                          "buttonZoomIn" : ("zoomin.png", "Zoom in the map window", 40, 20),
                          "buttonZoomOut" : ("zoomout.png", "Zoom out the map window", 70, 20),
                          "buttonZoomAll" : ("zoomall.png", "Zoom all the map window", 100, 20),
                          "buttonZoomCurrentLayer" : ("zoomcurrentlayer.png", "Zoom to grid layer", 130, 20),
                          "buttonZoomPrevious" : ("zoomprev.png", "Previous zoom", 160, 20),
                          "buttonZoomNext" : ("zoomnext.png", "Next zoom", 190, 20),
                          "buttonClearExtents" : ("clearextents.png", "Clear zoom history", 220, 20),
                          "buttonSendExtent" : ("sendextent.png", "Send extent to Qgis mapcanvas", 250, 20),
                          "buttonPan" : ("pan.png", "Move the map window", 280, 20),
                          "buttonHotlink" : ("hotlink.png", "Load a raster file", 310, 20),                          
                          "buttonLoadExtent" : ("hotlinkextent.png", "Load the raster files for extent", 340, 20),
                          "buttonLoadSelected" : ("hotlinkselected.png", "Load the raster files for selected objects", 370, 20)
                          }
             

         else :
             dicoCtrls = {"buttonCatchExtent" : ("catchextent.png", "Get extent for QGIS mapcanvas", 10, 20),
                          "buttonZoomIn" : ("zoomin.png", "Zoom in the map window", 40, 20),
                          "buttonZoomOut" : ("zoomout.png", "Zoom out the map window", 70, 20),
                          "buttonZoomAll" : ("zoomall.png", "Zoom to all ...", 100, 20),
                          "buttonZoomPrevious" : ("zoomprev.png", "Previous zoom", 130, 20),
                          "buttonZoomNext" : ("zoomnext.png", "Next zoom", 160, 20),
                          "buttonSendExtent" : ("sendextent.png", "Send extent to Qgis mapcanvas", 190, 20),
                          "buttonPan" : ("pan.png", "Move the map window", 220, 20),
                          "buttonAddPermanentLayers" : ("add.png", "Add permanent vector layers", 250, 20),
                          "buttonDelPermanentLayers" : ("del.png", "Delete permanent vector layers", 280, 20)
                      }


         pos = 5

       
         for key in dicoCtrls :
      
                   icon = getThemeIcon(dicoCtrls[key][0])
                   toolTip = translateMsg(dicoCtrls[key][1])

                   button = myPushButton(self.groupMap)
                   
                   if key!= "buttonHotlink" : button.initPushButton(25, 25, pos, dicoCtrls[key][3], key, "", toolTip, True, icon, 25, 25, True)
                   else :  button.initPushButton(50, 25, pos, dicoCtrls[key][3], key, "", toolTip, True, icon, 50, 25, True)

                   if key in ("buttonZoomIn", "buttonZoomOut","buttonPan") : 

                      button.setStyleSheet(self.styleSheetPushButton)
                      button.setCheckable(True)

                      if key == "buttonZoomIn" : button.setChecked(True)
 
                      index = ("buttonZoomIn", "buttonZoomOut","buttonPan").index(key)
                      self.actionsMapCanvas.addButton(button, index)
                      

                   if key == "buttonHotlink" :
                      button.setStyleSheet(self.styleSheetPushButtonWithMenu)
                      button.setCheckable(True)

                      self.contextMnuToolsHotlink(button)
                   
                   setattr(self, key, button)
                   
                   if key == "buttonHotlink" : pos+= 50
                   else : pos+= 30 
                   

         sizeWidth = len(self.groupMap.children())*30
         self.groupMap.setGeometry(5, 10, sizeWidth+20, 50)           

         return sizeWidth


def changeSettings(self, crs):
    settings = QSettings()
    oldCrsSettings = settings.value("Projections/layerDefaultCrs")
    settings.setValue("Projections/defaultBehavior", "useGlobal")
    settings.setValue("Projections/layerDefaultCrs", crs.toWkt())
    settings.sync()
    return oldCrsSettings

def restoreSettings(self, crs):
    settings = QSettings()
    if crs : settings.setValue("Projections/defaultBehaviour", crs)


class toolHotLink(QgsMapTool):
    def __init__(self, parent, mapViewer, uiAlr, toRemove):
        QgsMapTool.__init__(self, mapViewer)
      
        self.parent = parent        
        self.mapViewer = mapViewer        
        self.sb = self.parent.iface.mainWindow().statusBar()
        self.cp = None
        self.context = QgsExpressionContext()
        self.scope = QgsExpressionContextScope()
        self.uiAlr  = uiAlr
        self.toRemove = toRemove
        self.setCursor(QCursor(QPixmap(getThemeIcon("toolhotlink.png")))) if not self.toRemove else self.setCursor(QCursor(QPixmap(getThemeIcon("toolhotdelete.png"))))

        if self.uiAlr :  self.rb1, self.rb2 = self.parent.rbTool, self.parent.rbCanvas 
        else :           self.rb1, self.rb2 = self.parent.rbCanvas, self.parent.rbTool


        self.timerMapTips = QTimer( self.mapViewer )
        if self.parent.currentLayer :
           if self.parent.currentLayer.geometryType() == 2 : self.timerMapTips.timeout.connect( self.showMapTip )
        
        self.status=0        
         
    def getRemove(self) : return self.toRemove
    
    def canvasReleaseEvent(self, e):  pass 

    def canvasMoveEvent(self, e):
        if self.mapViewer.underMouse(): 
            QToolTip.hideText()
            self.timerMapTips.start(1000)
            self.cp = e.pos()
            self.rb1.reset()
            self.rb2.reset()            
            self.showExtent()

    def canvasReleaseEvent(self, e):
        if not e.button() == Qt.MouseButton.LeftButton: return
        if not self.parent.currentLayer : return
       
        cp = self.toLayerCoordinates(self.parent.currentLayer, e.pos())
       
        g = QgsGeometry().fromPointXY(QgsPointXY(cp.x(), cp.y()))
   
        if self.parent.currentLayer.geometryType() == 0 : g = g.buffer(250, 12)

        key = self.parent.getKeyForGridLayer(self.parent.listFiles.currentIndex())
        index = self.parent.getIndexLayerField(key) 
        if index < 0 : return
        
        selectedSet, featIds = [], []
        selectedSet, featIds = self.parent.intersectsOp(self.parent.currentLayer, [], [], index, g)

        if not self.toRemove : self.parent.loadRaster(selectedSet)
        else :
            self.parent.removeRaster(selectedSet)
            self.parent.parent.updateToolRemove()



    def deactivate(self):   
        self.timerMapTips.stop()
        self.rb1.reset()
        self.rb2.reset()


    def evaluateExpression(self, context, feat, expression):
            expression = QgsExpression(expression)
            value = expression.evaluate(context)
            return value

    def showExtent( self ):
        if not self.parent.currentLayer : return
        self.timerMapTips.stop()
        
        if self.mapViewer.underMouse():
           cp = self.toLayerCoordinates(self.parent.currentLayer, self.cp) 
           g = QgsGeometry().fromPointXY(QgsPointXY(cp.x(), cp.y()))
           g = g.buffer(250, 12)

           features = self.parent.currentLayer.getFeatures(QgsFeatureRequest())

           for feat in features :        
                  geom = feat.geometry()
                  if geom and g:
                     if geom.intersects(g):
                        self.timerMapTips.start(1000)
                        if self.parent.currentLayer.geometryType() == 0 :
                           if self.parent.hasExtentForGeom :
                              wktGeom = feat[self.parent.indexForExtentGeom]
                              geom = QgsGeometry().fromWkt("%s" % wktGeom)
                           else :  
                              point = g.centroid().asPoint()
                              geom = QgsGeometry().fromPointXY(point).buffer(500, 12)
                             
                        self.parent.rbGeom(self.rb1, geom, self.parent.currentLayer.crs(), True)
                        self.parent.rbGeom(self.rb2, geom, self.parent.currentLayer.crs(), True)

                        break

    def showMapTip(self):

        if not self.parent.currentLayer : return
        self.timerMapTips.stop()
        if self.mapViewer.underMouse():
           
           key = self.parent.currentLayer.source()

           expression = None
           if self.parent.dictGridRaster != [] :
              if dicoHasKey(self.parent.dictGridRaster, key):  expression = self.parent.dictGridRaster[key]["listFields"] 

              if not self.cp : return

              cp = self.toLayerCoordinates(self.parent.currentLayer, self.cp)
              g = QgsGeometry().fromPointXY(QgsPointXY(cp.x(), cp.y()))

              if self.parent.currentLayer.geometryType() == 0 : g = g.buffer(250, 12)                  

              key = self.parent.getKeyForGridLayer(self.parent.listFiles.currentIndex())
              index = self.parent.getIndexLayerField(key)
              if index < 0 : return              
              
              features = self.parent.currentLayer.getFeatures(QgsFeatureRequest())

              for feat in features :        
                  geom = feat.geometry()
                  self.scope.setFeature(feat)
                  self.context.appendScope(self.scope)

                  if geom and g:
                     if geom.intersects(g):
                            if index < len(self.parent.currentLayer.fields()) : expression = feat[index]
                            else :  expression = self.evaluateExpression(self.context, feat, expression)
                            break

              QToolTip.showText( self.mapViewer.mapToGlobal( self.mapViewer.mouseLastXY() ), expression, self.mapViewer )

              msg = translateMsg("Load a raster file") if not self.toRemove else translateMsg("Remove raster file")
              self.sb.showMessage("%s ? %s" % (msg, expression))

              
class toolHotLinkRect(QgsMapTool):
    def __init__(self, parent, mapViewer, uiAlr):
        QgsMapTool.__init__(self, mapViewer)
        self.parent = parent
       
        self.mapViewer = mapViewer
        self.status = 0
        self.uiAlr  = uiAlr
        if self.uiAlr :  self.rb1, self.rb2 = self.parent.rbTool, self.parent.rbCanvas 
        else :           self.rb1, self.rb2 = self.parent.rbCanvas, self.parent.rbTool

        self.setCursor(QCursor(QPixmap(getThemeIcon("toolhotlink.png"))))        
        self.sb = self.parent.iface.mainWindow().statusBar()
        msg = translateMsg("Draw a rectangle : Place the top left point and move the mouse")
        self.sb.showMessage(msg)
        
        self.timerMapTips = QTimer( self.mapViewer )

    def deactivate(self): self.rb1.reset() ; self.rb2.reset();
         

    def canvasPressEvent(self,e):
        if not e.button() == Qt.MouseButton.LeftButton: return
        self.status = 1 if self.status == 0 else 0
        if self.status == 1 :
            self.topleft = self.toMapCoordinates(e.pos())
            geom = rbRectangleByPoint(self.rb1, self.topleft, self.topleft)
            if self.uiAlr : self.parent.rbGeom(self.rb2, geom, self.parent.crs, True)
            else : self.parent.rbGeom(self.rb2, geom, self.parent.currentLayer.crs(), True)            
        else : self.rb1.reset()            
        

    def canvasMoveEvent(self,e):
        if not self.status == 1: return
        cp = self.toMapCoordinates(e.pos())
        geom = rbRectangleByPoint(self.rb1, self.topleft, cp)
        if self.uiAlr : self.parent.rbGeom(self.rb2, geom, self.parent.crs, True)
        else : self.parent.rbGeom(self.rb2, geom, self.parent.currentLayer.crs(), True)          
        msg = translateMsg("Drawing rectangle, extent : width %s - height %s")
        self.sb.showMessage(msg % (round(abs(self.topleft.x()-cp.x()), 2), round(abs(self.topleft.y()-cp.y()), 2))) 

    def canvasReleaseEvent(self,e):
        if not e.button() == Qt.MouseButton.LeftButton: return
        if not self.status == 1: return
        cp = self.toMapCoordinates(e.pos())
        if float(cp.x())!= float(self.topleft.x()) and float(cp.y()) != float(self.topleft.y()) : self.rb2.reset(); getRasterForSelection(self, self.rb1, self.mapViewer, self.parent.currentLayer)
 


class toolHotLinkFree(QgsMapTool):
    def __init__(self, parent, mapViewer, uiAlr):
        QgsMapTool.__init__(self, mapViewer)
        self.parent = parent
        self.mapViewer = mapViewer
        self.uiAlr  = uiAlr
        if self.uiAlr :  self.rb1, self.rb2 = self.parent.rbTool, self.parent.rbCanvas 
        else :           self.rb1, self.rb2 = self.parent.rbCanvas, self.parent.rbTool

        if self.uiAlr : self.transform = QgsCoordinateTransform(self.parent.crs, QgsProject(self.parent.iface).instance().crs(), QgsProject(self.parent.iface).instance())
        else :  self.transform = QgsCoordinateTransform(QgsProject(self.parent.iface).instance().crs(), self.parent.crs, self.parent.projectAlr)
        
        self.setCursor(QCursor(QPixmap(getThemeIcon("toolhotlink.png"))))        
        self.sb = self.parent.iface.mainWindow().statusBar()
        msg = translateMsg("Draw a free polygon")
        self.sb.showMessage(msg)        
        self.firstpoint = False 


    def deactivate(self): self.rb1.reset(); self.rb2.reset();
         
    
    def canvasPressEvent(self,e):
        point = self.toMapCoordinates(e.pos())
        self.rb1.addPoint(point)
        self.rb2.addPoint(self.transform.transform(point))
        self.firstpoint = True
        
    
    def canvasMoveEvent(self,e):
        if self.firstpoint :
           point = self.toMapCoordinates(e.pos())
           self.rb1.addPoint(point)
           self.rb2.addPoint(self.transform.transform(point))
           msg = translateMsg("Drawing Free Polygon : %s points")
           self.sb.showMessage(msg % self.rb1.numberOfVertices())      
        
    def canvasReleaseEvent(self,e):
        if not self.rb1: return
        if self.rb1.numberOfVertices() > 2 :  self.rb2.reset(); getRasterForSelection(self, self.rb1, self.mapViewer, self.parent.currentLayer);  self.firstpoint = False
            

class toolHotLinkPoly(QgsMapTool):
    def __init__(self, parent, mapViewer, uiAlr):
        QgsMapTool.__init__(self, mapViewer)
        self.parent = parent
        self.mapViewer = mapViewer
        self.uiAlr  = uiAlr
        if self.uiAlr :  self.rb1, self.rb2 = self.parent.rbTool, self.parent.rbCanvas 
        else :           self.rb1, self.rb2 = self.parent.rbCanvas, self.parent.rbTool

        if self.uiAlr : self.transform = QgsCoordinateTransform(self.parent.crs, QgsProject(self.parent.iface).instance().crs(), QgsProject(self.parent.iface).instance())
        else :  self.transform = QgsCoordinateTransform(QgsProject(self.parent.iface).instance().crs(), self.parent.crs, self.parent.projectAlr) 

        self.setCursor(QCursor(QPixmap(getThemeIcon("toolhotlink.png"))))                
        self.sb = self.parent.iface.mainWindow().statusBar()
        msg = translateMsg("Draw a Polygon : Left click to place points, right click to complete the entry")
        self.sb.showMessage(msg)        

    def deactivate(self): self.rb1.reset(); self.rb2.reset();
        

    def canvasMoveEvent(self,e):
        if self.rb1.numberOfVertices() > 0:
            self.rb1.removeLastPoint(0)
            self.rb2.removeLastPoint(0)
            point = self.toMapCoordinates(e.pos())
            self.rb1.addPoint(point)
            self.rb2.addPoint(self.transform.transform(point))
            msg = translateMsg("Drawing Polygon : %s points")
            self.sb.showMessage(msg % self.rb1.numberOfVertices())  
        
    
    def canvasPressEvent(self,e):
        if e.button() == Qt.MouseButton.LeftButton :
           point = self.toMapCoordinates(e.pos())   
           self.rb1.addPoint(point)
           self.rb2.addPoint(self.transform.transform(point))
        else:
            if self.rb1.numberOfVertices() > 2 :  self.rb2.reset(); getRasterForSelection(self, self.rb1, self.mapViewer, self.parent.currentLayer)

        

class toolHotLinkCircleByCenter(QgsMapTool):
    def __init__(self, parent, mapViewer, uiAlr):
        QgsMapTool.__init__(self, mapViewer)
        self.parent = parent
        self.mapViewer = mapViewer
        self.uiAlr  = uiAlr
        if self.uiAlr :  self.rb1, self.rb2 = self.parent.rbTool, self.parent.rbCanvas 
        else :           self.rb1, self.rb2 = self.parent.rbCanvas, self.parent.rbTool

        self.setCursor(QCursor(QPixmap(getThemeIcon("toolhotlink.png"))))
        self.sb = self.parent.iface.mainWindow().statusBar()
        msg = translateMsg("Draw a circle : Place the center and move the mouse to set the radius")
        self.sb.showMessage(msg)        
        self.status = 0

    def deactivate(self) : self.rb1.reset(); self.rb2.reset();

    def canvasPressEvent(self,e):
        if not e.button() == Qt.MouseButton.LeftButton: return
        self.status = 1
        self.center = self.toMapCoordinates(e.pos())
        geom = rbcircle(self.rb1, self.center, self.center, 40)
        if self.uiAlr : self.parent.rbGeom(self.rb2, geom, self.parent.crs, True)
        else : self.parent.rbGeom(self.rb2, geom, self.parent.currentLayer.crs(), True)
    
    def canvasMoveEvent(self,e):
        if not self.status == 1: return
        cp = self.toMapCoordinates(e.pos())
        geom = rbcircle(self.rb1, self.center, cp, 40)
        if self.uiAlr : self.parent.rbGeom(self.rb2, geom, self.parent.crs, True)
        else : self.parent.rbGeom(self.rb2, geom, self.parent.currentLayer.crs(), True)
        
        r = sqrt(self.center.sqrDist(cp))
        msg = translateMsg("Drawing circle - Center : (%s - %s), radius : %s")
        self.sb.showMessage(msg % (round(self.center.x(), 2), round(self.center.y(),2), round(r, 2))) 

    def canvasReleaseEvent(self,e):
        if not e.button() == Qt.MouseButton.LeftButton: return
        self.edge = self.toMapCoordinates(e.pos())

        self.rb2.reset()

        if int(self.edge.x())== int(self.center.x()) and int(self.edge.y()) == int(self.center.y()) :
           self.rb1.reset()
           self.rb1.addPoint(QgsPointXY(self.center.x(),self.center.y()))
           self.rb1.addPoint(QgsPointXY(self.center.x(),self.center.y()+1))
           self.rb1.addPoint(QgsPointXY(self.center.x()+1,self.center.y()+1))
           self.rb1.addPoint(QgsPointXY(self.center.x()+1,self.center.y()))

        getRasterForSelection(self, self.rb1, self.mapViewer, self.parent.currentLayer)   



class toolHotLinkCircleByRadius(QgsMapTool):
    def __init__(self, parent, mapViewer, uiAlr):
        QgsMapTool.__init__(self, mapViewer)
        self.parent = parent
        self.mapViewer = mapViewer
        self.uiAlr  = uiAlr
        if self.uiAlr :  self.rb1, self.rb2 = self.parent.rbTool, self.parent.rbCanvas 
        else :           self.rb1, self.rb2 = self.parent.rbCanvas, self.parent.rbTool
        
        self.setCursor(QCursor(QPixmap(getThemeIcon("toolhotlink.png"))))
        self.sb = self.parent.iface.mainWindow().statusBar()
        msg = translateMsg("Draw a circle : Place the first top left point, and move the mouse to fix the diameter")
        self.sb.showMessage(msg)
        self.status = 0 

    def deactivate(self): self.rb1.reset(); self.rb2.reset();
        
    def canvasPressEvent(self,e):
        if not e.button() == Qt.MouseButton.LeftButton: return
        self.status = 1
        self.p1 = self.toMapCoordinates(e.pos())
        geom = rbcircle(self.rb1, self.p1, self.p1, 40)
        if self.uiAlr : self.parent.rbGeom(self.rb2, geom, self.parent.crs, True)
        else : self.parent.rbGeom(self.rb2, geom, self.parent.currentLayer.crs(), True)
    
    def center(self,p2):
        return QgsPointXY((self.p1.x()+p2.x())/2.0,(self.p1.y()+p2.y())/2.0)
        
    def canvasMoveEvent(self,e):
        if not self.status == 1: return
        cp = self.toMapCoordinates(e.pos())
        center =  self.center(cp)
        geom = rbcircle(self.rb1, center, cp, 40)
        if self.uiAlr : self.parent.rbGeom(self.rb2, geom, self.parent.crs, True)
        else : self.parent.rbGeom(self.rb2, geom, self.parent.currentLayer.crs(), True)
        
        r = sqrt(center.sqrDist(cp))
        msg = translateMsg("Drawing circle - Center : (%s - %s), radius : %s")
        self.sb.showMessage(msg % (round(center.x(), 2), round(center.y(),2), round(r, 2)))        

    def canvasReleaseEvent(self,e):
        if not e.button() == Qt.MouseButton.LeftButton: return
        self.edge = self.toMapCoordinates(e.pos())

        self.rb2.reset()

        if int(self.edge.x())== int(self.p1.x()) and int(self.edge.y()) == int(self.p1.y()) :
           self.rb1.reset()
           self.rb1.addPoint(QgsPoint(self.p1.x(),self.p1.y()))
           self.rb1.addPoint(QgsPoint(self.p1.x(),self.p1.y()+1))
           self.rb1.addPoint(QgsPoint(self.p1.x()+1,self.p1.y()+1))
           self.rb1.addPoint(QgsPoint(self.p1.x()+1,self.p1.y()))

        getRasterForSelection(self, self.rb1, self.mapViewer, self.parent.currentLayer)    



def getRasterForSelection(self, rb, mapViewer, currentLayer):

    geom = getGeomFromRb(self, rb, mapViewer, currentLayer)
    key = self.parent.getKeyForGridLayer(self.parent.listFiles.currentIndex())
    index = self.parent.getIndexLayerField(key)
    if index < 0 : return

    selectedSet, featIds = [], []
    selectedSet, featIds = self.parent.intersectsOp(currentLayer, [], [], index, geom)
    self.parent.loadRaster(selectedSet)

    self.sb.showMessage( "%s : %s %s" % (translateMsg("Load the raster files for selected objects"),  len(selectedSet), translateMsg("files")))
  
                  
def getGeomFromRb(self, rb, mapViewer, currentLayer):
    coords = []  
    [coords.append(QgsMapTool(mapViewer).toLayerCoordinates(currentLayer, rb.getPoint(0,i))) for i in range(rb.numberOfVertices())]
    geom = QgsGeometry().fromPolygonXY([coords])

    rb.reset()
    self.status = 0

    return geom

def rbRectangleByPoint(rb, topleft, bottomright):
    rb.reset()
    rb.addPoint(QgsPointXY(topleft.x(),topleft.y()))
    rb.addPoint(QgsPointXY(bottomright.x(),topleft.y()))
    rb.addPoint(QgsPointXY(bottomright.x(),bottomright.y()))
    rb.addPoint(QgsPointXY(topleft.x(),bottomright.y()))
    rb.addPoint(QgsPointXY(topleft.x(),topleft.y()))
    
    coords = []
    [coords.append(rb.getPoint(0, i)) for i in range(rb.numberOfVertices())]
    g = QgsGeometry().fromPolygonXY([coords])

    return g
         
def rbcircle(rb, center, edgePoint, N):
  
    r = sqrt(center.sqrDist(edgePoint))
    rb.reset()
    for itheta in range(N+1):
        theta = itheta*(2.0 * pi/N)
        rb.addPoint(QgsPointXY(center.x()+r*cos(theta),center.y()+r*sin(theta)))

    coords = []
    [coords.append(rb.getPoint(0,ki)) for ki in range(rb.numberOfVertices())]
    g = QgsGeometry().fromPolygonXY([coords])
       
    return g

