from qgis import processing

from qgis.PyQt.QtCore import (QCoreApplication, QEvent, QEventLoop, QFile, QFileInfo, QIODevice, QLocale, QMetaObject, QModelIndex, QObject, QPoint, QPointF, QProcess, QRect, QRectF,
                              QSize, QRegExp, QSettings, QSizeF, QSortFilterProxyModel, Qt, QTimer, QTranslator, QUrl, QVariant, pyqtSignal, pyqtSlot)
from qgis.PyQt.QtWidgets import (QAbstractItemView, QAction, QApplication, QButtonGroup, QCheckBox, QComboBox, QCompleter, QDialog, QDialogButtonBox, QDockWidget, QFileDialog, QFrame,
                                 QGridLayout, QGroupBox, QInputDialog, QLabel, QLineEdit, QListWidget, QListWidgetItem, QMainWindow, QMdiSubWindow, QMessageBox, QMenu, QProgressBar,
                                 QProxyStyle, QPushButton, QRadioButton, QSizePolicy, QSlider, QStyle, QStyledItemDelegate, QTabWidget, QTextBrowser, QTextEdit, QToolTip, QTreeWidget,
                                 QTreeWidgetItem, QToolBar, QToolButton, QHBoxLayout, QLayout, QWidget, QWidgetAction)

from qgis.PyQt.QtWidgets import QActionGroup, QListView, QVBoxLayout
from qgis.PyQt.QtGui import QStandardItem, QStandardItemModel
from rdigc.objmaker import paramToPrintMap

from qgis.PyQt import QtWidgets

from qgis.PyQt.QtGui import (QBrush, QCloseEvent, QColor, QCursor, QFont, QIcon, QImage, QKeySequence, QPainter, QPalette, QPen, QPixmap, QPolygonF, QTextDocument)
from qgis.PyQt.QtPrintSupport import QPrinter
from qgis.PyQt.QtSvg import QSvgWidget

from qgis.core import (Qgis, QgsApplication, QgsExpression, QgsFeature, QgsFeatureRequest, QgsField, QgsFields, QgsFillSymbol, QgsGeometry, QgsLayerTree, QgsLayerTreeLayer, QgsLayerTreeModel,
                       QgsMapLayer, QgsMarkerSymbol, QgsMeshLayer, QgsPointXY, QgsProcessingFeatureSourceDefinition, QgsProject, QgsRasterLayer, QgsSpatialIndex, QgsVectorLayer, QgsWkbTypes)


from qgis.core import (QgsBasicNumericFormat, QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsLayoutExporter, QgsPrintLayout, QgsLayoutItemLegend, QgsLayoutMeasurement,
                       QgsLayoutItemHtml, QgsLayoutItemPage, QgsLayoutPoint, QgsLayoutSize, QgsMapLayerLegendUtils, QgsMapLayerProxyModel, QgsProject, QgsUnitTypes)

from qgis.core import (QgsLayoutExporter, QgsLayoutFrame, QgsLayoutItemMap, QgsLayoutItemLabel, QgsLayoutItemPicture,
                        QgsLayoutPoint, QgsLayoutItemPolyline, QgsLayoutItemScaleBar, QgsLayoutSize, QgsPointXY, QgsPrintLayout)

from qgis.core import QgsTextAnnotation

from qgis.gui import (QgsBusyIndicatorDialog, QgsCollapsibleGroupBox, QgsFilterLineEdit, QgsLayerTreeMapCanvasBridge, QgsLayerTreeView,
                      QgsMapCanvas, QgsMapLayerComboBox, QgsMapTool, QgsMapToolIdentify, QgsMapToolPan,
                      QgsMapToolZoom, QgsRubberBand, QgsVertexMarker)
from qgis.utils import pluginMetadata

from functools import partial

from rdigc.keyboard import virtualKeyboard
from rdigc.objmaker import (Button, CustomStyleDelegate, funnyPushButton, linkedToolBar, logConsole, myMsgDlgBox, printerPreview,
                            reportingStations, simpleViewerWeb, switchButtonRdi, toolBarSnifferWidget, windowPlotStatsAndGraphs)

#NEW 4.0.0 LAYERWATER - API PARAMETERS
from rdigc.params import (APIHUBEAU, APIHUBEAUMONTHLY, APIMETEO, APIMODELMETEO, APIMODELMETEOITEMS, COMMENTSSEUILRDI, FORMATSRASTER, GROUPSACTIONS, INFORMATIONSSTYLES, LAYERCRUES, FIELDCRUES, RASTERCRUES,
                          LAYERCOMMUNES, TABLEFIELDSCOMMUNES, LAYERSTATIONS, LAYERWATER, TABLEFIELDSWATER, LAYERCOMMUNES, LAYERTERRAIN, LAYERTERRITOIRE, LEGENDSTYLES, MAPPINGDATA, NAMEGROUPRASTER,
                          PATHIMGSTATIONS, PATHLOCALDATA, PATHLOCALFOLDERSTATIONS, STYLECOMBOBOX, STYLEMAPLAYERCOMBOBOX,
                          TABLEFIELDSSTATIONS, TABLEFIELDSCOMMUNES, TABLEFIELDSWATER, THEMATICINONDATIONS, THEMATICSUBMERSIONS, TIMEZONE)

from rdigc.ui_about import ui_About
from rdigc.ui_params import ui_Params
#NEW 4.0.0
from rdigc.ui_impacts import ui_Impacts

#NEW 4.0.0 - playAlarm
from rdigc.utils import (bufferPlus, changeButtonIcon, cleanUri, conditionnalAddChild, createTreeWidgetItem, dicoHasKey, fileNameWithExtension, findExec, fixeLabelsFileDialog,
                         getCloudCover, getFactorsWH, getMeteoIcon, getNivVigilance, getRainForce, getResolutionScreen, getWindForce, getWindOrientation,
                         getLitteralDate, getLogoFile, getMean, getStDev, getThemeIcon, iff, jsonDateToStrDate, jsonToMatplotlibDate, legendSymbolItemChecked,
                         makeListFormatsExtensions, multiGetRequest, myPushButton, playAlarm, setObjSizes, visitTreeList, windowIcon)

from os.path import (basename, dirname, exists, isfile, join, splitext)
from os import makedirs
from os import remove as removeFile
from os import walk
from datetime import datetime as thedatetime
from math import ceil

try:
    from osgeo import gdal
except:
    import gdal

import ast
import calendar
import json
import random
import sys
import time 

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

from webbrowser import open as webbrowseropen
from xml.etree import ElementTree as etree
import re

from PyQt5.QtWebKit import QWebSettings
from PyQt5.QtWebKitWidgets import QWebView, QWebPage
from qgis.PyQt.QtNetwork import (QNetworkAccessManager, QNetworkDiskCache, QNetworkReply, QNetworkRequest)


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

    self.itemValuesOccurences = []

    self.transformer = None
    self.widgetToolBarViewer = None 
    self.widgetToolBarNav = None
    self.widgetToolBarIdentify = None
    self.widgetToolBarIdentifyData = None
    self.widgetLegendsBar = None
    self.widgetRisquesEnjeux = None
    self.vKeyboard = None
    #NEW 4.0.0
    self.logConsole = None
    self.widgetDynamicLegend = None
    self.identifyResultsDock = None
    self.actionAddWmsLayer = None
    self.NorthArrow = None
    self.buttonIdentifyWebH = None
    self.buttonIdentifyWebD = None
    self.buttonIdentifyWebStats = None
    self.buttonFullStations = None
    self.dialogReportingStations = None

    #NEW 4.0.0
    self.vlcPath = findExec("C:\\Program Files", "vlc.exe")
    self.manager = None
    
    self.buttonPrinterData = None
    self.buttonZoomIn, self.buttonZoomOut, self.buttonPan, self.buttonIdentify = None, None, None, None

    self.comboActiveLayer = None
    self.noVisibleLayers = []

    self.statutMaximized = False
    self.buttonIdentifyObj = None
    self.buttonDynamicLegend = None
    self.qgisActionZoomIn = self.getActionQgisZoomIn()
    self.qgisActionZoomOut = self.getActionQgisZoomOut()
    self.qgisActionPan = self.getActionQgisPan()

    self.widgetDynamicLegend = self.getLegendQgisPanel()
    if self.widgetDynamicLegend :
       self.widgetDynamicLegend.visibilityChanged.connect(self.updateVisibilityButtonDL)
       self.widgetDynamicLegend.topLevelChanged.connect(self.updateTopLevelWidgetDynamicLegend)


    self.withComposer, self.withLegend, self.withNorthArrow = True, False, False
    self.orientationIndex, self.pageFormatIndex = 0, 4
    self.chkMapTips = None    
    self.svgNorthArrow = None
    s = QSettings() 
    self.pathFolderParams = s.value("%spathFolderParams"  % self.settings, "" )

    isSettings = True
    if self.pathFolderParams == "" : isSettings = False
    elif not exists(self.pathFolderParams) : isSettings = False
    if not isSettings :
       pathFolderParams = join(dirname(__file__),"data/").replace("\\", "/") 
       if exists(pathFolderParams): self.pathFolderParams = pathFolderParams
       else : self.pathFolderParams =  dirname(__file__)
       s.setValue("%spathFolderParams" % self.settings, self.pathFolderParams) 

    self.menuLocalInfos = self.getInfosInFile(join(self.pathFolderParams, "localdata.xml"), None) 
    self.menuWebInfos = self.getInfosInFile(join(self.pathFolderParams, "webdata.xml"), None)  
    
      
    self.defaultBackRasterLayerIndex = 0
    self.index = 0
    self.groupIconPath = getThemeIcon("group.png").replace("\\","/")
    self.groupIcon = QIcon(self.groupIconPath)
    self.polygonIconPath = getThemeIcon("polygon.png").replace("\\","/")
    self.polygonIcon = QIcon(self.polygonIconPath)
    self.lineIconPath = getThemeIcon("linestring.png").replace("\\","/")
    self.lineIcon = QIcon(self.lineIconPath)
    self.pointIconPath = getThemeIcon("point.png").replace("\\","/")
    self.pointIcon = QIcon(self.pointIconPath)
    self.tableIconPath = getThemeIcon("tabledata.png").replace("\\","/")
    self.tableIcon = QIcon(self.tableIconPath)
    self.rasterIconPath = getThemeIcon("raster.png").replace("\\","/")
    self.rasterIcon = QIcon(self.rasterIconPath)
    self.unknowIconPath = getThemeIcon("unknown.png").replace("\\","/")
    self.unknowIcon = QIcon(self.unknowIconPath)
    self.imgpuce = getThemeIcon("imgpuce.png").replace("\\","/")
    self.imgChecked = getThemeIcon("checked.png").replace("\\","/")
    self.imgUnChecked = getThemeIcon("unchecked.png").replace("\\","/")
    
    self.initLogos(join("%s/%s" % (dirname(__file__), "data/logos"), "logo_pref2a_m.png"),  join("%s/%s" % (dirname(__file__), "data/logos"), "logo_rdi2a_m.png"), "DDTM 2A / RDI",
                   join("%s/%s" % (dirname(__file__), "icons"), "noaction.png"))
    self.initStyleForTempoLayer()    

    self.saveFolder = dirname(__file__)      
    self.orientation = QPrinter.Landscape

    self.barInfo = self.iface.messageBar() 
    self.barInfo.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
   
    self.buttonProfilTool = None

    self.rbCanvas = QgsRubberBand(self.canvas, Qgis.GeometryType.Line)
    self.rbCanvas.setWidth(2)
    self.rbCanvas.setColor(QColor(Qt.red))
    self.rbCanvasPoint = QgsVertexMarker(self.canvas)
    self.rbCanvasPoint.setColor(QColor(Qt.red))
    self.rbCanvasPoint.setIconSize(5)
    self.rbCanvasPoint.setIconType(QgsVertexMarker.ICON_BOX) 
    self.rbCanvasPoint.setPenWidth(3)

    self.oldToolMap, self.mZoomOut = None, None
    self.lastToolMap = None
    self.dockWidgetProfileTool = None
    self.dockWidgetProfileTool = None
    self.activateProfileTool, self.actionProfileTool = self.getActionProfilTool()
  
    self.cache_path = self.checkFoldersForExtension()

    self.toolBarSniffer = toolBarSnifferWidget(self.iface.mainWindow(), self.canvas, self)
 
    self.layer, self.column, self.suggestions, self.listOfValues = None, None, [], []
    self.memoryLayer = None
    self.listForDataSearch = None
    self.index = 0  

    self.grid = QGridLayout(self.iface.mainWindow())
    widget = eval("QgsBusyIndicatorDialog")
    self.movieCtrl = widget(None)
    self.grid.addWidget(self.movieCtrl, 0, 0)
    self.grid.setAlignment(self.movieCtrl, Qt.AlignTop)
    self.movieCtrl.setVisible(False)

    self.printMapview = QTextDocument()

    self.printInformations = QWebView(self.widgetToolBarNav)  
    self.printInformations.setObjectName("printInformations")
    self.printInformations.settings().setAttribute(QWebSettings.AutoLoadImages, True)
    self.printInformations.setVisible(False)
    self.printInformations.setHtml("<body><img src='file:///%s' width=16px height=16px><br><img src='file:///%s'><br><img src='file:///%s'></body>" % (self.imgpuce, self.fileLogoLeft, self.fileLogoRight))

    self.printStaticLegend = QWebView(self.widgetToolBarNav)  
    self.printStaticLegend.setObjectName("printStaticLegend")
    self.printStaticLegend.page().settings().setAttribute(QWebSettings.AutoLoadImages, True)
    self.printStaticLegend.setVisible(False)

    self.requestWebServicesViewer = QWebView(self.widgetToolBarNav)  
    self.requestWebServicesViewer.setObjectName("requestWebServicesViewer")
    self.requestWebServicesViewer.setVisible(False)
       
    self.mappingData, self.groupsActions, self.thematicInondations, self.thematicSubmersions = {}, {},  [], []

    #NEW 4.0.0
    self.layerStations, self.layerTerrain, self.layerTerritoire, self.layerCrues, self.layerWater, self.layerCommunes, self.rasterCrues, self.fieldCrues = "", "", "", "", "", "", "", ""
    
    self.pathImgStations, self.pathLocalData, self.pathLocalFolderStations, self.timezone, self.apimodelmeteo, self.nameGroupRaster = "", "", "", "Europe/Paris", "meteofrance_seamless", ""
    self.tableFieldsStations = {}
    self.tableFieldsCommunes = {}
    self.tableFieldsWater = {}

    self.loadParamsRdi()
    self.htmlLegend = ""
    
    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/rdi_%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


    #QGIS INTERFACE AND PROJECT CONNECTORS
    QgsProject.instance().readProject.connect(self.loadProjectRdi)
    QgsProject.instance().layerRemoved.connect(self.updateMemoryLayer)
    self.iface.projectRead.connect(self.initLayerBackGround) 
    self.iface.newProjectCreated.connect(self.updateCompleter)
    self.iface.layerTreeView().currentLayerChanged.connect(self.updateComboActiveLayer)
    self.canvas.mapToolSet.connect(self.setOldToolMap)

    self.showProfilTool()

    self.initTransformer()
    self.initComboActiveLayer()


  def blockIdentifyToolMap(self):
      if type(self.canvas.mapTool()) == QgsMapToolIdentify :
         if type(self.oldToolMap) == QgsMapToolZoom :
            if self.mZoomOut :   
               self.zoomOut()
               self.buttonZoomIn.setStyleSheet("QPushButton {border-width: 5px; border-radius: 10px; border-color: black; background-color:  #7eff00;}") ;
            else :
               self.zoomIn()
               self.buttonZoomOut.setStyleSheet("QPushButton {border-width: 5px; border-radius: 10px; border-color: black; background-color:  #7eff00;}") ;
         else :
               self.pan() 
               self.buttonPan.setStyleSheet("QPushButton {border-width: 5px; border-radius: 10px; border-color: black; background-color:  #7eff00;}") ; 
          
        
  def setOldToolMap(self, newToolMap, oldToolMap):
      if type(self.canvas.mapTool()) == QgsMapToolIdentify : self.oldToolMap = oldToolMap
      if type(newToolMap) == QgsMapToolZoom :
         self.mZoomOut = self.qgisActionZoomOut.isChecked()
         self.initAllToolMapButtons()
         if self.mZoomOut :   
            if self.buttonZoomOut : self.buttonZoomOut.setStyleSheet("QPushButton {border-width: 5px; border-radius: 10px; border-color: black; background-color:  #7eff00;}") ;
         else :
            if self.buttonZoomIn : self.buttonZoomIn.setStyleSheet("QPushButton {border-width: 5px; border-radius: 10px; border-color: black; background-color:  #7eff00;}") ;

      elif type(newToolMap) == QgsMapToolPan :
         self.mZoomOut = self.qgisActionPan.isChecked()
         self.initAllToolMapButtons()
         if self.buttonPan : self.buttonPan.setStyleSheet("QPushButton {border-width: 5px; border-radius: 10px; border-color: black; background-color:  #7eff00;}") ;
          

  def initAllToolMapButtons(self):
      for button in (self.buttonZoomIn, self.buttonZoomOut, self.buttonPan, self.buttonIdentify):
          if button : button.setStyleSheet("QPushButton {border-width: 0px; border-radius: 10px; background: transparent; }")
         
  def initGui(self):

    self.defaultIconSize = 28  
    self.style = myProxyStyle('Fusion')

    self.styleComboBox = STYLECOMBOBOX
    self.styleMapLayerComboBox = STYLEMAPLAYERCOMBOBOX  

    self.styleComboBoxAleas = "QComboBox {font-family: 'Arial';font-size: 16px; font-weight: bold;}" + self.styleComboBox
    
    windowIcon(self.iface.mainWindow(), "inondation.png")

    self.widgetMainToolBar = actionsWindows(self.canvas, "widgettoolmainbar", "", 45, 360 )
    sizeWidth = ctrlMap(self, self.widgetMainToolBar, True, False, False, 0, 0, 30, 350)
    
    initSizeToolBar(self.widgetMainToolBar, 10, 10, 45, sizeWidth+20)

    self.actionFullScreen.setShortcut(QKeySequence("F4"))
    self.actionFullScreen.clicked.connect(self.getActionToggleMapOnly)
    self.actionFullScreen.setText("")

    self.actionToolBarNav.clicked.connect(self.getToolBarNav)
    self.buttonFullStations.clicked.connect(self.extractDataForReporting)

    self.actionToolIdentify.clicked.connect(self.getToolBarIdentify)
    
    self.widgetMainToolBar.show()

    self.widgetRisquesEnjeux = actionsWindows(self.canvas, "widgetRisquesEnjeux", " %s " % QApplication.translate("rdigc","Risques - Enjeux"), 500, 120 )
    self.toolBarRisquesEnjeux = QToolBar(self.widgetRisquesEnjeux)
    self.toolBarRisquesEnjeux.setObjectName("toolBarRisquesEnjeux")
    self.toolBarRisquesEnjeux.setGeometry(5, 0, 690, 130) 
    self.toolBarRisquesEnjeux.setIconSize(QSize(125, 62))

    self.groupThematicSearch  = QGroupBox(self.toolBarRisquesEnjeux)
    setObjSizes(self.groupThematicSearch, 490, 90)

    font = QFont("Arial", 12)
    font.setBold(True)

    self.dicoButtonsIhm = { "buttonAleas" :{"actionAleaNone" : ("none.png", "Aucun Aléa"),
                                            "actionAleasAll" : ("all.png", "Tous les Aléas"),
                                            "actionAleaInondation" : ("inondations.png", "Aléa Inondation"),
                                            "actionAleaSubmersion" : ("submersions.png", "Aléa Submersion")},
                            "buttonSurAleas" : {"actionRisquesMt" : ("mt_off.png", "Mouvements de terrains"),
                                                "actionRisquesOh" : ("oh_off.png", "Rupture barrage ou digue"),
                                                "actionRisquesStep" : ("step_off.png", "STEP - assainissement"),
                                                "actionRisquesIcpe" : ("icpe_off.png", "Risque industriel") },
                            "buttonEnjeux" : {"actionEnjeuxPersonnes" : ("personnes_off.png", "Personnes"),
                                              "actionEnjeuxReseaux" : ("reseaux_off.png", "Réseaux, VRD, etc"),
                                              "actionEnjeuxBiens" : ("biens_off.png", "Biens"),
                                              "actionEnjeuxEcologie" : ("ecologie_off.png", "Ecologie")}
                            }
    

    self.buttonAleas = myPushButton(self.groupThematicSearch)
    self.buttonAleas.initPushButton(135, 24, 0, 0, "buttonAleas", "Aléas", "Aléas : aucun, Tous, Inondation, Submersion.", False, "", 135, 24, True)
    self.buttonAleas.setFont(font)
    self.buttonAleas.setStyleSheet("QPushButton {border-width: 5px; border-radius: 5px; border-color: black; background-color: #7eff00;}") 

    self.contextMnuAleas(self.buttonAleas)
    self.buttonAleas.setGeometry(80, 5, 135, 24)

    self.buttonGroupAlea = QButtonGroup(self.groupThematicSearch)
    self.buttonGroupAlea.setExclusive(True)

    self.createMnuForButton(90, "buttonAleas", self.groupThematicSearch)
    
    self.buttonGroupAlea.buttonClicked[int].connect(self.updateGroupAleaByClick)

    font10 = QFont("Arial", 8)
    font10.setBold(False)

    #NEW 4.0.0
    self.deltaScrutationStation = 300000
    self.groupCrues  = QGroupBox(self.groupThematicSearch)
    setObjSizes(self.groupCrues, 163, 32)
    self.groupCrues.setGeometry(73, 55, 163, 32)
    self.groupCrues.setStyleSheet("QGroupBox { border-style: outset; border-radius: 3px;  selection-color: black; selection-background-color: lightgray;}")
    self.groupStations = QGroupBox(self.groupThematicSearch)
    setObjSizes(self.groupStations, 163, 32)
    self.groupStations.setGeometry(73, 55, 163, 32)
    self.groupStations.setStyleSheet("QGroupBox { border-style: outset; border-radius: 3px;  selection-color: black; selection-background-color: lightgray;}")
    self.groupMeteo = QGroupBox(self.groupThematicSearch)
    setObjSizes(self.groupStations, 163, 32)
    self.groupMeteo.setGeometry(73, 55, 163, 32)
    self.groupMeteo.setStyleSheet("QGroupBox { border-style: outset; border-radius: 3px;  selection-color: black; selection-background-color: lightgray;}")

    
    #CONSTRUCT GROUP CRUES
    self.lblOccurrenceValue = QLabel(self.groupCrues)
    self.lblOccurrenceValue.setGeometry(1, 1, 35, 30)
    self.lblOccurrenceValue.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
    self.lblOccurrenceValue.setFont(font10)
    self.lblOccurrenceValue.setText("Crue :")
   
    self.listOccurrenceValue = QComboBox(self.groupCrues)
    self.listOccurrenceValue.setObjectName("listOccurrenceValue")
    setObjSizes(self.listOccurrenceValue, 65, 25)
    self.listOccurrenceValue.setGeometry(35, 2, 95, 25)
    self.listOccurrenceValue.setStyleSheet(self.styleComboBox)
    self.listOccurrenceValue.setFont(font10)
    self.listOccurrenceValue.setToolTip("Liste des valeurs pour les occurrences de crues")
    self.listOccurrenceValue.setCurrentIndex(0)

    self.playStopButton = funnyPushButton(self.groupCrues)
    self.playStopButton.initPushButton(25, 25, 0, 0, "playStopButton", "", "Jouer les occurences de crues", True, QIcon(getThemeIcon("play.png")), 25, 25, True, False)
    self.playStopButton.setGeometry(105, 2, 25, 25)

    self.chkOccurrenceValue = myPushButton(self.groupCrues)
    self.chkOccurrenceValue.initPushButton(25, 25, 0, 0, "chkOccurrenceValue", "", "Afficher / Masquer la couche des occurrences de crues", True, QIcon(getThemeIcon("legenddynamic_off.png")), 25, 25, True) #, False)
    self.chkOccurrenceValue.setGeometry(133, 2, 20, 20)
    self.chkOccurrenceValue.clicked.connect(self.changeVisibilityOccurrence)

    #CONSTRUCT GROUP STATIONS
    self.labelComboTypeInfos = QLabel(self.groupStations)
    self.labelComboTypeInfos.setObjectName("labelComboTypeInfos")
    self.labelComboTypeInfos.setGeometry(1, 1, 35, 30)
    self.labelComboTypeInfos.setText("Info : ")
    self.labelComboTypeInfos.setToolTip("Choix de l'information à rapatrier")
    self.labelComboTypeInfos.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)

    self.comboTypeInfos = QComboBox(self.groupStations)
    self.comboTypeInfos.setObjectName("comboTypeInfos")
    self.comboTypeInfos.setGeometry(35, 2, 95, 25)
    self.comboTypeInfos.setStyleSheet(self.styleComboBox)
    self.comboTypeInfos.setToolTip("Choix de l'information à rapatrier")
    self.comboTypeInfos.addItems(["Débit","Hauteur"])
    self.comboTypeInfos.setCurrentIndex(1)

    self.playStopButtonStations = funnyPushButton(self.groupStations)
    self.playStopButtonStations.initPushButton(25, 25, 0, 0, "playStopButtonStations", "", "Jouer la scrutation dynamique des stations", True, QIcon(getThemeIcon("play.png")), 25, 25, True, False)
    self.playStopButtonStations.setGeometry(105, 2, 25, 25)    

    self.cleanButtonStations = funnyPushButton(self.groupStations)
    self.cleanButtonStations.initPushButton(25, 25, 0, 0, "cleanButtonStations", "", "Supprimer la scrutation dynamique des stations", True, QIcon(getThemeIcon("deldata.png")), 25, 25, True, False)
    self.cleanButtonStations.setGeometry(135, 2, 25, 25) 

    #CONSTRUCT GROUP METEO
    self.listTargetMeteo = QComboBox(self.groupMeteo)
    self.listTargetMeteo.setObjectName("listTargetMeteo")
    setObjSizes(self.listTargetMeteo, 65, 25)
    self.listTargetMeteo.setGeometry(5, 2, 125, 25)
    self.listTargetMeteo.setStyleSheet(self.styleComboBox)
    self.listTargetMeteo.setFont(font10)
    self.listTargetMeteo.setToolTip("Liste des choix pour le service météo")
    self.listTargetMeteo.addItems(["Stations", "Communes", "Cours d'eau", "Placement libre"])
    self.listTargetMeteo.setCurrentIndex(0)

    self.playButtonMeteo = funnyPushButton(self.groupMeteo)
    self.playButtonMeteo.initPushButton(25, 25, 0, 0, "playButtonMeteo", "", "Afficher les informations météorologiques", True, QIcon(getThemeIcon("play.png")), 25, 25, True, False)
    self.playButtonMeteo.setGeometry(105, 2, 25, 25)    

    self.cleanButtonMeteo = funnyPushButton(self.groupMeteo)
    self.cleanButtonMeteo.initPushButton(25, 25, 0, 0, "cleanButtonMeteo", "", "Effacer les informations météorologiques", True, QIcon(getThemeIcon("deldata.png")), 25, 25, True, False)
    self.cleanButtonMeteo.setGeometry(135, 2, 25, 25) 
    
    self.setGroupVisibility(self.groupCrues)
    
    #NEW 4.0.0
    self.services = funnyPushButton(self.groupThematicSearch)
    self.services.initPushButton(20, 25, 0, 0, "services", "", "Services", True, QIcon(getThemeIcon("actions.png")), 20, 25, True, True)
    setObjSizes(self.services, 20, 32)
    self.services.setGeometry(238, 55, 20, 32)
    self.contextMnuServices(self.services)

    self.isStartChrono = False
    self.timer = QTimer()
    self.timer.timeout.connect(self.updateTimer)    

    #NEW 4.0.0    
    self.playStopButton.clicked.connect(self.startStopOccurrence)
    self.playStopButtonStations.clicked.connect(self.startStopStations)
    self.cleanButtonStations.clicked.connect(self.deleteAnnotations)
    self.listTargetMeteo.currentIndexChanged.connect(self.setPlayButtonMeteo)
    self.playButtonMeteo.clicked.connect(self.getInfosMeteo)
    self.cleanButtonMeteo.clicked.connect(self.deleteAnnotations)
    self.actionIdentifyWebMeteo = getDataMeteoFromWebServices(self.iface, self, self.canvas)

    self.annotationManager = QgsProject.instance().annotationManager()
    
    self.updateComboCrues()
    
    self.listOccurrenceValue.currentIndexChanged.connect(self.updateViewOccurenceLayer)
    self.updateViewOccurenceLayer()

    self.groupWidgets = QGroupBox(self.groupThematicSearch)
    self.groupWidgets.setStyleSheet("QGroupBox { border-style: outset; border-radius: 3px;  selection-color: black; selection-background-color: lightgray;}") 
    self.groupWidgets.setGeometry(0, 2, 70, 85)
    self.groupWidgets.setFont(QFont("Arial", 6))
    self.groupWidgets.setTitle("Widgets :")
    
    self.buttonDynamicLegend = myPushButton(self.groupWidgets)
    self.buttonDynamicLegend.initPushButton(28, 28, 0, 0, "buttonDynamicLegend", "", "Afficher / Masquer le panneau de gestion de la visibilité des couches", False, getThemeIcon("legenddynamic_off.png"), 28, 28, True)
    self.buttonDynamicLegend.setGeometry(5, 20, 28, 28)
    self.buttonDynamicLegend.clicked.connect(self.getWidgetDynamicLegend)

    self.buttonNorthArrow = myPushButton(self.groupWidgets)
    self.buttonNorthArrow.initPushButton(28, 28, 0, 0, "buttonNorthArrow", "", "Afficher / Masquer la boussole", False, getThemeIcon("northarrow_off.png"), 28, 28, True)
    self.buttonNorthArrow.setGeometry(40, 20, 28, 28)
    self.buttonNorthArrow.clicked.connect(self.showNorthArrowDialog)  
    
    self.buttonVirtualKeyboard = myPushButton(self.groupWidgets)
    self.buttonVirtualKeyboard.initPushButton(28, 28, 0, 0, "buttonVirtualKeyboard", "", "Afficher / Masquer le clavier tactile", False, getThemeIcon("keyboard_off.png"), 28, 28, True)
    self.buttonVirtualKeyboard.setGeometry(5, 50, 28, 28)
    self.buttonVirtualKeyboard.clicked.connect(self.getVirtualKeyboard)

    #NEW 4.0.0
    self.buttonLogConsole = myPushButton(self.groupWidgets)
    self.buttonLogConsole.initPushButton(28, 28, 0, 0, "buttonLogConsole", "", "Afficher / Masquer la console journal", False, getThemeIcon("logconsole_off.png"), 28, 28, True)
    self.buttonLogConsole.setGeometry(40, 50, 28, 28)
    self.buttonLogConsole.clicked.connect(self.getLogConsole)
    

    self.listLayersRaster = myPushButton(self.groupThematicSearch)
    self.listLayersRaster.initPushButton(225, 25, 0, 0, "buttonEnjeux", "Fonds de plan", "Fonds de plan", False, "", 225, 25, True)
    self.listLayersRaster.setFont(font)
    self.listLayersRaster.setStyleSheet("QPushButton {border-width: 5px; border-radius: 5px; border-color: black; background-color: #7eff00;}")
    setObjSizes(self.listLayersRaster, 225, 32)
    self.listLayersRaster.setGeometry(260, 55, 225, 32)

    self.refreshListLayersRaster = funnyPushButton(self.listLayersRaster)
    self.refreshListLayersRaster.initPushButton(25, 19, 5, 3, "setCompleter", "", "Recharger la liste des Fonds de plan", True, QIcon(getThemeIcon("refresh.png")), 25, 19, True, False)
    self.refreshListLayersRaster.clicked.connect(self.updatelistLayersRaster) 

    self.listeWmsServer = [
                           ("view_none_m.png", "Aucun fond"),
                           ("view_orthophoto_m.png", "Fond Ortho Photo avec AutoloaderRaster"),
                           ("view_scan25_m.png", "Fonds raster dossier RDI"),
                           ("web.png", "Services web")
                           ]  
    
    self.updatelistLayersRaster()
    
    self.buttonSurAleas = myPushButton(self.groupThematicSearch)
    self.buttonSurAleas.initPushButton(135, 24, 0, 0, "buttonSurAleas", "Sur-Aléas", "Sur-Aléas : Mouvements de terrain, Ruptures de digues, STEP, Industriels", False, "", 135, 24, True)
    self.buttonSurAleas.setFont(font)
    self.buttonSurAleas.setStyleSheet("QPushButton {border-width: 5px; border-radius: 5px; border-color: black; background-color: #7eff00;}")
    self.buttonSurAleas.setGeometry(220, 5, 135, 24)

    self.contextMnuSurAleas = QMenu()
    self.contextMnuButtons(self.buttonSurAleas, self.contextMnuSurAleas)
    self.createMnuForButton(235, "buttonSurAleas", self.groupThematicSearch)

    self.buttonEnjeux = myPushButton(self.groupThematicSearch)
    self.buttonEnjeux.initPushButton(125, 24, 0, 0, "buttonEnjeux", "Enjeux", "Enjeux : Populations, Réseaux et VRD, Biens, Ecologie.", False, "", 125, 24, True)
    self.buttonEnjeux.setFont(font)
    self.buttonEnjeux.setStyleSheet("QPushButton {border-width: 5px; border-radius: 5px; border-color: black; background-color: #7eff00;}")
    self.buttonEnjeux.setGeometry(360, 5, 125, 24)

    self.contextMnuEnjeux = QMenu()
    self.contextMnuButtons(self.buttonEnjeux, self.contextMnuEnjeux)
    self.createMnuForButton(365, "buttonEnjeux", self.groupThematicSearch)
    
    self.toolBarRisquesEnjeux.addWidget(self.groupThematicSearch) 
    
    self.actionToggleFullScreen = None
    self.actionToggleMapOnly = None
    self.actionTogglePanelsVisibility = None

    if self.iface.mainWindow().actions() != [] :
       for action in self.iface.mainWindow().actions() :
           if action.objectName() == "mActionToggleFullScreen" : self.actionToggleFullScreen = action ; self.actionToggleFullScreen.setIcon(QIcon(getThemeIcon("fullscreen_off.png")))
           if action.objectName() == "mActionToggleMapOnly" : action.setShortcut(QKeySequence("")) ; self.actionToggleMapOnly = action ; self.actionToggleMapOnly.setIcon(QIcon(getThemeIcon("fullscreen_off.png")))
           if action.objectName() == "mActionTogglePanelsVisibility" : self.actionTogglePanelsVisibility = action ; self.actionTogglePanelsVisibility.setIcon(QIcon(getThemeIcon("fullscreen_off.png")))
    else :
       action = self.iface.mainWindow().findChild(QAction, "mActionToggleFullScreen") 
       if action : self.actionToggleFullScreen = action ; self.actionToggleFullScreen.setIcon(QIcon(getThemeIcon("fullscreen_off.png")))       
       action = self.iface.mainWindow().findChild(QAction, "mActionToggleMapOnly")
       if action : action.setShortcut(QKeySequence("")) ; self.actionToggleMapOnly = action ; self.actionToggleMapOnly.setIcon(QIcon(getThemeIcon("fullscreen_off.png")))
       action = self.iface.mainWindow().findChild(QAction, "mActionTogglePanelsVisibility")
       if action : self.actionTogglePanelsVisibility = action ; self.actionTogglePanelsVisibility.setIcon(QIcon(getThemeIcon("fullscreen_off.png")))

    self.widgetRisquesEnjeux.setGeometry(10, self.iface.mainWindow().centralWidget().height()-self.widgetRisquesEnjeux.height()-10, self.widgetRisquesEnjeux.width(), self.widgetRisquesEnjeux.height())
    self.widgetRisquesEnjeux.show()

    self.NorthArrow = QSvgWidget(self.iface.mapCanvas())
    setObjSizes(self.NorthArrow, 64, 64)
    self.NorthArrow.setStyleSheet("background-color: rgba(255, 255, 255, 50);")
    self.NorthArrow.setVisible(False)
    self.initNorthArrow()

    self.getToolBarNav()
    self.canvas.renderStarting.connect(self.getUpdateRightWidgets)

    self.actionToolIdentify.clicked.emit()
    self.widgetToolBarNav.setVisible(True)
    self.actionToolIdentify.clicked.emit()
    self.buttonIdentifyData.clicked.emit()
    self.actionToolBarNav.setIcon(QIcon(getThemeIcon("navigation_on.png")))
    self.buttonIdentifyData.setIcon(QIcon(getThemeIcon("identifydata_on.png")))
        
    try : self.widgetToolBarIdentify.setVisible(False)
    except : pass

    self.buttonPan.setChecked(True)
    #NEW 4.0.0
    self.getLogConsole()
    self.buttonLogConsole.clicked.emit()

  def createMnuForButton(self, posX, themeButton, group):
      if not dicoHasKey(self.dicoButtonsIhm, themeButton) : return
      styleButtonGroupAlea  = "QPushButton:checked{background-color: #7eff00; border: none;}"
      dicoButtons = self.dicoButtonsIhm[themeButton]
      index = 1
      for key in dicoButtons :
          img = dicoButtons[key][0] 
          text = QApplication.translate("rdigc", dicoButtons[key][1])
          button = switchButtonRdi(group, img)
          button.setGeometry(posX, 25, 24, 24)
          button.setObjectName(key)
          button.setCheckable(True)
          button.setToolTip(text)
          if themeButton == "buttonAleas" :
             button.setProperty("id", index) 
             button.setStyleSheet(styleButtonGroupAlea)
             if index == 1 : button.setChecked(True)
             self.buttonGroupAlea.addButton(button, index)
             index+= 1
          else :
             button.clicked.connect(self.updateCkeckedGroups)
          setattr(self, key, button)
          posX+= 30       

  def updateGroupAleaByListMember(self):
      self.buttonGroupAlea.blockSignals(True)
      id = self.actionGroupAleas.checkedAction().property("id")
      for button in self.buttonGroupAlea.buttons() : 
          button.setChecked(True) if id == button.property("id") else button.setChecked(False)
      self.buttonGroupAlea.blockSignals(False)
      self.updateViewThematicLayers()
      
  def updateGroupAleaByClick(self, id):
      self.updateViewThematicLayers()
      for action in self.actionGroupAleas.actions() : 
          action.setChecked(True) if id == action.property("id") else action.setChecked(False)

  def updatelistLayersRaster(self):
        index = 0
        menuBackRasterLayer = QMenu()
        for elt in self.listeWmsServer :

            if index < 3 :
                icon = getThemeIcon(elt[0])  
                text = QApplication.translate("rdigc", elt[1])

                action = QWidgetAction(menuBackRasterLayer)
                button = QPushButton(text)
                button.setIcon(QIcon(icon))

                if index == 0 :
                   color = "#FFFFFF"
                   button.clicked.connect(self.noBackLayerRaster)               
                elif index == 1 :    
                   color = "#919191"
                   button.clicked.connect(self.updateBackRasterLayerWithALR)
                else : color = "#C8C8C8"   

                button.setStyleSheet("QPushButton { background-color : %s; text-align: left; padding: 4 4 4 4px;}" % color)

                if index == 2 :
                   subMenu = QMenu()
                   icon = QIcon(getThemeIcon("localraster.png"))
                   for dirName, dirNames, fileNames in walk(self.pathLocalData):
                     for fileName in fileNames:
                         currentFile = join(self.pathLocalData, dirName, fileName)
                         textension = splitext(basename(currentFile))
                         extension = textension[len(textension)-1].upper().replace(".", "")
                         if extension in FORMATSRASTER :
                            subAction = QAction(icon, basename(currentFile), subMenu)
                            subAction.setData(currentFile)
                            subAction.triggered.connect(self.updateBackRasterLayerWithLocalFiles)
                            subMenu.addAction(subAction)

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


                if button and action :
                   action.setDefaultWidget(button)            
                   menuBackRasterLayer.addAction(action)
                   menuBackRasterLayer.addSeparator()

            else :
                menuWmsServers = self.getInfosInFile(join(self.pathFolderParams, "wmsservers.xml"), menuBackRasterLayer)
           
            index+= 1       

        self.listLayersRaster.setMenu(menuBackRasterLayer)  


  #NEW 4.0.0
  def updateTimer(self) :
      #TO FINISH - TO CHANGE CONDITION ?
      if self.groupStations.isVisible() :
         #1) GET STATIONS IN MAPCANVAS EXTENT OR ALL ?         
         instance = QgsProject.instance()
         if iff(instance.mapLayersByName(self.layerStations), True, False) :

            layerStations = instance.mapLayersByName(self.layerStations)[0]
             
            if self.tableFieldsStations == {} : return

            fieldsNames = layerStations.fields().names()
            mapfieldsNames = map(lambda x:x.upper(), fieldsNames)

            if not "DtFermetur".upper() in mapfieldsNames :
               features = layerStations.getFeatures()
            else : 
               exp = QgsExpression(" \"{}\" = '{}' ".format("DtFermetur", '0'))
               request = QgsFeatureRequest(exp)
               features = layerStations .getFeatures(request)
   

            fieldCdStationH = self.tableFieldsStations['CdStationH']
            fieldLbStationH = self.tableFieldsStations['LbStationH']
            fieldCdAncieRef = self.tableFieldsStations['CdAncieRef']
            fieldSeuilRDI   = self.tableFieldsStations['SEUIL_RDI']
 
            try : indexRdi = layerStations.fields().names().index(fieldSeuilRDI) 
            except : indexRdi = -1

            if indexRdi == -1 : return
                        
            stations = {} 
            for feat in features:
                idStation = feat[fieldCdStationH]
                seuilRdi = feat[fieldSeuilRDI] if indexRdi >-1 else "Pas d'infos"
                stations[idStation] = {"pointStation" : feat.geometry().asPoint(),"lbStation" : feat[fieldLbStationH], "idHydro" : feat[fieldCdAncieRef], "SEUIL_RDI" : seuilRdi if seuilRdi else "Pas d'infos"}

            self.stations = stations
            orderedStations = dict(sorted(stations.items()))

            i = 1

            if not self.manager :  self.manager = QNetworkAccessManager(self.iface)            
            typeInfos = "H" if  self.comboTypeInfos.currentIndex() == 1 else "Q"
            labelInfos = "m3/s" if typeInfos == "Q" else "m" 

            self.deleteAnnotations()
            self.dictAlarms = {}
  
            factorW, factorH = getFactorsWH()
            width = int(100 / (factorW+0.25)) 
            height = int(40 / (factorH+0.4))
            
            for idStation in orderedStations :

                self.replyObject = None
                lbStation, idHydro = orderedStations[idStation]["lbStation"], orderedStations[idStation]["idHydro"]
                point = orderedStations[idStation]["pointStation"]
                url = APIHUBEAU % (idStation, typeInfos, 1) 
                        
                loop = QEventLoop()
                self.replyObject = self.manager.get(QNetworkRequest(QUrl(url)))
                self.replyObject.finished.connect(loop.quit)
                loop.exec_()
               
                html = self.readContent(idStation, lbStation, idHydro, typeInfos, self.stations[idStation]["SEUIL_RDI"])

                if html != "" :
                    a = QgsTextAnnotation() 
                    c = QTextDocument()

                    c.setHtml(html)
                    a.setDocument(c)

                    fill_symbol = QgsFillSymbol.createSimple({'color': '0, 0, 0 ,0', 'line_color': '255, 255, 255, 150', 'line_style': 'solid', 'line_width': '0.4' })
                    a.setFillSymbol(fill_symbol)

                    a.setFrameSizeMm(QSizeF(width, height))
                    a.setMapLayer(layerStations)
                    a.setFrameOffsetFromReferencePoint(QPointF(30, -70))
                    a.setMapPosition(point)
                    a.setMapPositionCrs(QgsCoordinateReferenceSystem(layerStations.crs()))

                    instance.annotationManager().addAnnotation(a)

      
            if self.dictAlarms != {}:
                               
               for idStation in self.dictAlarms.keys() :
                   keySeuil      = self.dictAlarms[idStation][0]
                   iAlarm        = self.dictAlarms[idStation][2]
                   commentStatut = self.dictAlarms[idStation][3]
                   bgColor       = self.dictAlarms[idStation][4]
                   color         = self.dictAlarms[idStation][5]
                   
                   lbStation = self.stations[idStation]["lbStation"]
                   titleAlarm = "<font style='background-color: %s; color: %s;'> &lt;&lt;&lt; Attention !!! &gt;&gt;&gt; </font> &nbsp;" % (bgColor, color)

                   if iAlarm > 0 :
                      self.barInfo.pushMessage(titleAlarm, "La station %s [%s] : %s." % (lbStation, idStation, commentStatut), Qgis.Warning, 10)
                      QApplication.processEvents()
  
                   if self.vlcPath :
                      startTimeChrono = thedatetime.now()
                      deltaChrono = 7500
                      fileAlarm = self.dictAlarms[idStation][1]
                      p = playAlarm([self.vlcPath, fileAlarm, '--play-and-exit', '--qt-start-minimized', '--no-fullscreen'], startTimeChrono, deltaChrono)       

            self.dictAlarms = {}
        
      else :    
          index = self.listOccurrenceValue.currentIndex()+1 
          if index > self.listOccurrenceValue.count()-1 : index = 0
          self.listOccurrenceValue.setCurrentIndex(index)


  #NEW 4.0.0
  def deleteAnnotations(self):
      for annotation in self.annotationManager.annotations() : self.annotationManager.removeAnnotation(annotation)
      
          
  def readContent(self, idStation, lbStation, idHydro, typeInfos, infosStation):
      answerAsText = None
      answerAsText = bytes(self.replyObject.readAll()).decode("utf-8")
      datenow = thedatetime.now().strftime("%d/%m/%Y à %Hh%M")
      denum = 1000
      labelInfos = "Débit en m3/s" if typeInfos == "Q" else "Hauteur en m"
      lblInfos = "débit" if typeInfos == "Q" else "hauteur"
      unitInfos = "m3/s" if typeInfos == "Q" else "m"
      html = ""
      
      if answerAsText :
         try :
             json_data = json.loads(answerAsText)
             if dicoHasKey(json_data, "data") :
                mesure = json_data["data"][0]["resultat_obs"]

                dateObs = jsonDateToStrDate(json_data["data"][0]["date_obs"], "", " ", self.timezone)                
                lastObs = round(mesure/denum, 2)

                try : dicoSeuils = ast.literal_eval(infosStation)
                except : pass

                bgColor, color, soundAlarm, iAlarm, keySeuil = "#DEDEDF", "#000000", None, -1, -1 #PAS DE SEUIL

                bgColor, color, commentStatut, iAlarm, imgStatut, keySeuil = getNivVigilance(dicoSeuils, lastObs, typeInfos, unitInfos)

                html+= "<small>\n"
                html+= "<table style='border-radius: 5px; text-align: center;cellspacing: 0px; background: rgba(125, 125, 125, 50)'>\n"
                html+= "<tr>\n"
                html+= "<td colspan='2' style='color: #FFFFFF; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4, radius: 1.35, stop: 0 #0c6af6, stop: 1 #12cfeb); text-align: center;'>%s<br>[%s]</td>\n" % (lbStation, idStation)
                html+= "</tr>\n"
                html+= "<tr>\n"
                html+= "<td style='text-align: right; margin-right: 5px; color: cyan;'>Dernière scrutation : </td><td style='text-align: center; color: white;'>%s</td>" % (datenow)
                html+= "</tr>\n"                
                html+= "<tr>\n"
                html+= "<td style='text-align: right; margin-right: 5px; color: cyan;'>Dernière remontée : </td><td style='text-align: center; color: white;'>%s</td>\n" % (dateObs)
                html+= "</tr>\n"
                html+= "<tr style='background-color: %s; color: %s;'>\n" % (bgColor, color) 
                html+= "<td style='text-align: right; margin-right: 5px;'>%s : </td><td style='text-align: center'>%s</td>\n" % (labelInfos, lastObs)
                html+= "</tr>\n"
                html+= "</table>\n"
                html+= "</small>\n"

                
                lblDate = getLitteralDate(thedatetime.now(), "le", False, True)
                textStation = "<p style='background-color: %s; color: %s;'>Relevé pour la station %s [%s] %s :<br>" % (bgColor, color, lbStation, idStation, lblDate)
                textStation+= "[%s] Mesure du %s : %s %s" % (lblInfos, dateObs, lastObs, unitInfos)
              
                if iAlarm != -1 and keySeuil != -1 :
                   pathAlarm = "%s/%s" % (dirname(__file__), "data/sounds")
                   pathAlarm = pathAlarm.replace("/", "\\")
                   fileAlarm = r"%s\\alarm_seuil_%s.wav" % (pathAlarm, iAlarm)
                   self.dictAlarms[idStation] = [keySeuil, fileAlarm, iAlarm, commentStatut, bgColor, color]
                   textStation+= "<br>%s" % commentStatut

                textStation+= "</p>"

                if self.logConsole : self.logConsole.setAnnontation(textStation, False)

                return html
                
         except : return ""
      

  def getVisibilityOccurrence(self):
      rootLayers = QgsProject.instance().layerTreeRoot()
      layerCrues = QgsProject.instance().mapLayersByName(self.layerCrues)
      layerCrues = layerCrues[0] if layerCrues != [] else None
      cond = False
      if layerCrues :
         nodeLayerCrues = rootLayers.findLayer(layerCrues)
         if nodeLayerCrues : cond = not nodeLayerCrues.itemVisibilityChecked() 
      return cond, nodeLayerCrues        

  #NEW 4.0.0 - A AMELIORER   
  def changeVisibilityOccurrence(self):
      cond, nodeLayerCrues = self.getVisibilityOccurrence()
      nodeLayerCrues.setItemVisibilityChecked(cond)
      if nodeLayerCrues :
         if nodeLayerCrues.parent() :
            nodeLayerCrues.parent().setItemVisibilityChecked(cond)

      self.canvas.refresh()           
      
  def updateChkOccurrenceValue(self) :
      cond, nodeLayerCrues = self.getVisibilityOccurrence()
      self.chkOccurrenceValue.setStyleSheet(iff(cond, "QPushButton {border-width: 5px; border-radius: 5px; border-color: black; background-color: #7eff00;}", "")) 

  #NEW 4.0.0 - IL FAUT PEUT-ETRE METTRE UN DISTINGO TIMER CRUES AND TIMER CHRONO
  def selAllItems(self):
      model = self.listView.model()
      for index in range(0, model.rowCount()):
          item = model.item(index)
          item.setData(Qt.Checked, Qt.CheckStateRole) 
      
  def unSelAllItems(self):
      model = self.listView.model()
      for index in range(0, model.rowCount()):
          item = model.item(index)
          item.setData(Qt.Unchecked, Qt.CheckStateRole) 

  def invertSelItems(self):
      model = self.listView.model()
      for index in range(0, model.rowCount()):
          item = model.item(index)
          if  item.checkState() == Qt.Unchecked : item.setData(Qt.Checked, Qt.CheckStateRole)
          else : item.setData(Qt.Unchecked, Qt.CheckStateRole)


  def majItemsCounter(self, item): self.countItems()
        
  def countItems(self):
        rows, counter = self.listView.model().rowCount(), 0
        for i in range(rows):
            if self.listView.model().item(i, 0).checkState()== Qt.Checked:
                counter+= 1
        self.dialogInput.setWindowTitle("Paramètre%s : %s" % ("s" if counter > 1 else "", counter))
        self.dialogInput.buttonOk.setEnabled(counter > 0)

      
  def getParamMeteo(self, uCase, dictCases):
      self.dialogInput = QInputDialog()
      self.dialogInput.setWindowTitle("Paramètre")
      self.dialogInput.setWindowFlags(Qt.MSWindowsFixedSizeDialogHint | Qt.WindowTitleHint)      

      lstTitle = ["Choix de la / des station(s)", "Choix de la / des commune(s)", "Choix du / des cours d'eau"]
      self.dialogInput.setLabelText(lstTitle[uCase])
      self.dialogInput.setOptions(QInputDialog.UseListViewForComboBoxItems)

      maxWidth, maxheight = 500, 340
      setObjSizes(self.dialogInput, maxWidth, maxheight)
      self.dialogInput.resize(maxWidth, maxheight)

      self.dialogInput.setFixedWidth(maxWidth)
      self.dialogInput.setFixedHeight(maxheight)

      #ADD CONTEXT MENU
      self.listView = None
      contextMenu = QMenu()

      actions = {"selectAll" : ("selectall.png", "Sélectionner tous les membres", "" , self.selAllItems, True, "Ctrl+A"),
                 "unSelectAll" : ("unselectall.png", "Aucune membre sélectionné", "" , self.unSelAllItems, True, "Ctrl+Z"),
                 "invertSelected" : ("invertselection.png", "Inverser la sélection", "" , self.invertSelItems, True, "Ctrl+I"),
                }          

      height = 0
      for key in actions :
        if key.startswith("~") : contextMenu.addSeparator()
        else :
              icon = actions[key][0]
              icon = getThemeIcon(icon)

              action = QAction(QIcon(icon), actions[key][1], self.dialogInput)
              
              if actions[key][2] != "" : action.setShortcut(QKeySequence(actions[key][2]))
              action.setEnabled(actions[key][4])
              action.setObjectName(key)
              action.setShortcut(QKeySequence(actions[key][5]))
              contextMenu.addAction(action)
              action.triggered.connect(actions[key][3])

              setattr(self, key, action)
              height+= 20


      butContextMenu = funnyPushButton(self.dialogInput)
      butContextMenu.initPushButton(25, 19, 0, 0, "setCompleter", "", "Actions sur les membres", True, QIcon(getThemeIcon("actions.png")), 25, 19, True, False)
      butContextMenu.setGeometry(460, 6, 25, 19)

      butContextMenu.setMenu(contextMenu)

      if not uCase in dictCases.keys() : return
      layerMeteo = QgsProject.instance().mapLayersByName(dictCases[uCase]["name"])
      fieldObj = dictCases[uCase]["fieldDefinition"][dictCases[uCase]["field"]]
      lblFieldObj = dictCases[uCase]["fieldDefinition"][dictCases[uCase]["lblField"]]

      if layerMeteo :
         items = [] 
         layerMeteo = layerMeteo[0]
         subSetString = layerMeteo.subsetString() 

         filterWith = (dictCases[uCase]["fieldDefinition"]["FILTERWITH"])
         
         if filterWith != None :
            filterWith = filterWith.replace("{", "\"").replace("}", "\"")
            layerMeteo.setSubsetString(filterWith)
         
         request = QgsFeatureRequest().addOrderBy(fieldObj)
         
         for feat in layerMeteo.getFeatures(request) : items.append("%s - %s" % (feat[fieldObj], feat[lblFieldObj]))

         layerMeteo.setSubsetString(subSetString)    
      
      if items == [] : self.dialogInput = None; return       
      
      self.dialogInput.setComboBoxItems(items)      
      for child in self.dialogInput.children():
         if type(child) == QListView :
            self.listView = child 
            for index in range(child.model().rowCount()):
                item = child.model().item(index)
                item.setCheckable(True)
                item.setCheckState(Qt.Unchecked)
            child.model().itemChanged.connect(self.majItemsCounter)

         elif type(child) == QDialogButtonBox :
             for children in child.children() :
                 if type(children) == QPushButton :
                    self.dialogInput.buttonOk = children
                    break


  def getInfosMeteo(self):

      uCase = self.listTargetMeteo.currentIndex()
      
      dictCases = {0 : {"name" : self.layerStations, "fieldDefinition" : self.tableFieldsStations, "field" : "CdStationH", "lblField" : "LbStationH" },
                    1 : {"name" : self.layerCommunes, "fieldDefinition" : self.tableFieldsCommunes, "field" : "INSEE_COM", "lblField" : "NOM" },
                    2 : {"name" : self.layerWater, "fieldDefinition" : self.tableFieldsWater, "field" : "ID", "lblField" : "TOPONYME" }
                    }
      
      self.getParamMeteo(uCase, dictCases)

      if self.dialogInput.exec_() :

         lstTargetMeteo = []
         for child in self.dialogInput.children():
             if type(child) == QListView :
                for index in range(child.model().rowCount()):
                    item = child.model().item(index)
                    if (item.checkState() == 2) : lstTargetMeteo.append(item.text())
                 
         if lstTargetMeteo == [] : return
         
         layerMeteo, fieldObj = None, None
         pathIconMeteo = join(dirname(__file__), "icons/meteo/")
         #CASE TABLEFIELDS DEFINITION
         dictCases = {0 : {"name" : self.layerStations, "fieldDefinition" : self.tableFieldsStations, "field" : "CdStationH" },
                      1 : {"name" : self.layerCommunes, "fieldDefinition" : self.tableFieldsCommunes, "field" : "INSEE_COM" },
                      2 : {"name" : self.layerWater, "fieldDefinition" : self.tableFieldsWater, "field" : "ID" }
                      }

         if not uCase in dictCases.keys() : return
         layerMeteo = QgsProject.instance().mapLayersByName(dictCases[uCase]["name"])
         fieldObj = dictCases[uCase]["fieldDefinition"][dictCases[uCase]["field"]]             

         if layerMeteo : layerMeteo = layerMeteo[0]
         if layerMeteo == None or fieldObj == None: return

         #VERIFY fieldObj in layer.fields ()
         try : indexFieldObj = layerMeteo.fields().names().index(fieldObj) 
         except : indexFieldObj = -1
         if indexFieldObj == -1 : return

         instance = QgsProject.instance()
         if not self.manager : self.manager = QNetworkAccessManager(self.iface)
         loop = QEventLoop()         
         
         for targetMeteo in lstTargetMeteo :
             infos = targetMeteo.split(" - ")
             idObj = infos[0]
             lblObj = "Station "+infos[1] if uCase == 0 else infos[1]

             sexp = QgsExpression("\"{}\" = '{}'".format(fieldObj, idObj))
             request = QgsFeatureRequest(sexp)    


             if uCase in (0, 1) : self.getAnnotationMeteo(instance, loop, layerMeteo, lblObj, request, 0)
             else :
                 #PROPAGATION AGAINST WATER LINE
                 layerMeteo.selectByExpression("\"{}\" = '{}'".format(fieldObj, idObj))                                  
                 for feat in layerMeteo.getFeatures(request)  :
                     portion = int(feat.geometry().length()/3)                     
                     result = processing.run("native:pointsalonglines",
                                             {'DISTANCE' : portion,
                                              'END_OFFSET' : 0,
                                              'INPUT' : QgsProcessingFeatureSourceDefinition(layerMeteo.source(), selectedFeaturesOnly=True, featureLimit=-1, geometryCheck=QgsFeatureRequest.GeometryAbortOnInvalid),
                                              'OUTPUT' : 'TEMPORARY_OUTPUT',
                                              'START_OFFSET' : 0 })    
                     layerResult = result['OUTPUT']
                     self.getAnnotationMeteo(instance, loop, layerResult, lblObj, None, 1)   

                 layerMeteo.removeSelection()


  def setPlayButtonMeteo(self, index) :
      cond = (index < 3)
      self.playButtonMeteo.setVisible(cond)
      if not cond :
          self.lastToolMap = self.canvas.mapTool()
          self.actionIdentifyWebMeteo.setOldMapTool(self.lastToolMap)
          self.canvas.setMapTool(self.actionIdentifyWebMeteo)
      else :
          self.canvas.setMapTool(self.lastToolMap)
          


  def getContent(self, point):
      pointLL = self.transformer.transform(point, QgsCoordinateTransform.ForwardTransform)
      longitude = pointLL.x()
      latitude = pointLL.y()
                     
      url = APIMETEO % (latitude, longitude, self.apimodelmeteo[1])
      url = url.replace(" ", "%2F")    

      if not self.manager : self.manager = QNetworkAccessManager(self.iface)

      loop = QEventLoop()  
      self.replyObject = self.manager.get(QNetworkRequest(QUrl(url)))
      self.replyObject.finished.connect(loop.quit)
      loop.exec_()

      try : answerAsText = eval(bytes(self.replyObject.readAll()).decode("utf-8"))
      except : answerAsText = {}

      return answerAsText
      


  def getAnnotationMeteo(self, instance, loop, layer, lblObj, request, mode):
      
      features = layer.getFeatures(request) if request != None else  layer.getFeatures()  

      for feat in features  :
          point = feat.geometry().centroid().asPoint()

          answerAsText = self.getContent(point)
          if answerAsText != {} : self.setAnnotationMeteo(point, answerAsText, instance, layer, lblObj, mode)


  def setAnnotationMeteo(self, point, answerAsText, instance, layer, lblObj, mode):

      lblRainForce = getRainForce(answerAsText["current"]["precipitation"])
      lblWindSpeed10m = getWindForce(answerAsText["current"]["wind_speed_10m"])
      lblWindOrientation = getWindOrientation(answerAsText["current"]["wind_direction_10m"])
      lblCloudCover = getCloudCover(answerAsText["current"]["cloud_cover"])

      textMeteo = ""

      factorW, factorH = getFactorsWH()
      if mode == 0 : width, height = int(160 / (factorW+0.25)), int(120 / (factorH+0.4))
      else : width, height = int(140 / (factorW+0.25)), int(100 / (factorH+0.4))
      
      if mode == 1 :                 
         infosMeteo = """
         <table style='width: 300px; max-width: 300px; color: white; font-size: 10px; background-color : rgba(255, 255, 255, 75);'>
         <tr>
         <td style='background-color : rgba(0, 255, 255, 80); border: 1px solid #FFFFFF; border-radius: 5px; text-align: center;'><u>Températures</u> :<br>%s %s<br>%s %s ressentie</td>
         <td style='background-color : rgba(0, 0, 255, 80); border: 1px solid #FFFFFF; border-radius: 5px; text-align: center;'><u>Précipitations</u> :<br>%s %s<br>%s</td>
         </tr>                
         <tr><td style='background-color : rgba(113, 113, 113, 80); border: 1px solid #FFFFFF; border-radius: 5px; text-align: center;'><u>Couv. nuageuse</u> :<br>%s %s<br>%s</td>
         <td style='background-color : rgba(68, 68, 68, 80); border: 1px solid #FFFFFF; border-radius: 5px; text-align: center;'><u>Vent</u> :<br>%s %s<br>%s<br>%s</td>
         </tr>
         </table>
         """ % (answerAsText["current"]["temperature_2m"], answerAsText["current_units"]["temperature_2m"],
                answerAsText["current"]["apparent_temperature"], answerAsText["current_units"]["apparent_temperature"],
                answerAsText["current"]["precipitation"], answerAsText["current_units"]["precipitation"], lblRainForce,
                answerAsText["current"]["cloud_cover"], answerAsText["current_units"]["cloud_cover"], lblCloudCover,
                answerAsText["current"]["wind_speed_10m"], answerAsText["current_units"]["wind_speed_10m"], lblWindSpeed10m, lblWindOrientation)
         
      else :

         infosMeteo = """
                     <small>
                     <table style="width: 300px; max-width: 300px; background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4, radius: 1.35, stop: 0 rgba(125,125,125, 90) , stop: 1 rgba(55, 55, 255, 90));  border-radius: 8px; cellpadding: 1px;">
                     """
         #TO VERIFY WITH FACTUAL METEO
         weather_code = answerAsText["current"]["weather_code"] if "weather_code" in answerAsText["current"].keys() else 0
         isDay = answerAsText["current"]["is_day"] if "is_day" in answerAsText["current"].keys() else True
         imgWeather, contextWeather = getMeteoIcon(weather_code, isDay)

         key = sorted(APIMODELMETEOITEMS.keys())[self.apimodelmeteo[0]]
         organismeMeteo = APIMODELMETEOITEMS[key]["organisme"]
       
         infosMeteo+= """<tr style="background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4, radius: 1.35, stop: 0 #0c6af6, stop: 1 #12cfeb); padding: 20px 0; text-align: center;  border-bottom: 2px solid cyan;">
                         <td colspan=2 style="text-align : center;">   
                         <font style="font-size: 12px;  color: #fff; margin: 0 0 5px 5px;"><br>Météo <small>%s</small><br></font>
                         </td>
                     </tr>
                     <tr>
                        <td style="vertical-align : top;">
                            <font style="font-size: 14px; font-weight: bold; color: cyan; background-color: #1C6EA4;">&nbsp;%s %s
                            <img src="file:///%s" style="width: 24px; height: 24px; vertical-align:middle;"> %s </font>
                            <br><br>
                            <font style="font-size: 11px; color: cyan;">Température ressentie : </font><font style="color: #fff; background-color: #1C6EA4;">%s %s</font>
                        </td>
                        <td style="vertical-align : top">
                           <font style="font-size: 11px; color: cyan;">Précipitation</font><font style="color: #fff; background-color: #1C6EA4;"><br> %s %s, %s<br><br></font>
                           <font style="font-size: 11px; color: cyan;">Humidité</font><font style="color: #fff; background-color: #1C6EA4;"><br> %s %s<br><br></font>
                           <font style="font-size: 11px; color: cyan;">Vent</font><font style="color: #fff; background-color: #1C6EA4;"><br> %s %s, %s<br></font>
                           <font style="color: #fff; background-color: #1C6EA4;"> direction : %s %s<br> %s<br></font>
                        </td>
                     </tr>
                     <tr style="background: qradialgradient(cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4, radius: 1.35, stop: 0 #0c6af6, stop: 1 #12cfeb); padding: 20px 0; text-align: center;  border-bottom: 2px solid cyan;">
                         <td colspan=2 style="text-align: center;"><font style="font-size: 8px; font-weight: bold; color: #fff;  margin: 0 0 5px 0;">Source : <i>OpenMeteo.com - %s</i></font> 
                         </td>
                     </tr>                     
                     """ % (lblObj, answerAsText["current"]["temperature_2m"], answerAsText["current_units"]["temperature_2m"], imgWeather, contextWeather,
                            answerAsText["current"]["apparent_temperature"], answerAsText["current_units"]["apparent_temperature"],
                            answerAsText["current"]["precipitation"], answerAsText["current_units"]["precipitation"], lblRainForce,
                            answerAsText["current"]["relative_humidity_2m"], answerAsText["current_units"]["relative_humidity_2m"],
                            answerAsText["current"]["wind_speed_10m"], answerAsText["current_units"]["wind_speed_10m"], lblWindSpeed10m,
                            answerAsText["current"]["wind_direction_10m"], answerAsText["current_units"]["wind_direction_10m"], lblWindOrientation, organismeMeteo)

         date = thedatetime.now().strftime("%A %d-%B-%Y").split("-")
         lblDate = "%s %s %s" % (date[0], date[1], date[2])        
         textMeteo = "Fiche Météo %s le %s à %s :<br>" % (lblObj , lblDate, thedatetime.now().strftime("%Hh%M"))
         textMeteo+= "Température : %s %s<br>" % (answerAsText["current"]["temperature_2m"], answerAsText["current_units"]["temperature_2m"])
         textMeteo+= "Température ressentie : %s %s<br>" % (answerAsText["current"]["apparent_temperature"], answerAsText["current_units"]["apparent_temperature"])
         textMeteo+= "Précipitation : %s %s - %s<br>" % (answerAsText["current"]["precipitation"], answerAsText["current_units"]["precipitation"], lblRainForce)
         textMeteo+= "Couverture nuageuse : %s %s - %s<br>" % (answerAsText["current"]["cloud_cover"], answerAsText["current_units"]["cloud_cover"], lblCloudCover)
         textMeteo+= "Vent : %s %s - %s<br>" % (answerAsText["current"]["wind_speed_10m"], answerAsText["current_units"]["wind_speed_10m"], lblWindSpeed10m)
         textMeteo+= "Vent (direction) : %s %s - %s<br>" % (answerAsText["current"]["wind_direction_10m"], answerAsText["current_units"]["wind_direction_10m"], lblWindOrientation)
         textMeteo+= "<br>"
        
      a = QgsTextAnnotation()
      c = QTextDocument()
      c.setHtml(infosMeteo)
      a.setDocument(c)

      if self.logConsole and mode == 0 : self.logConsole.setAnnontation(textMeteo, False)

      fill_symbol = QgsFillSymbol.createSimple({'color': '0,0,0,0', 'line_color': '255,255,255, 0', 'line_style': 'solid', 'line_width': '0.4' })
      a.setFillSymbol(fill_symbol)
      marker_symbol = QgsMarkerSymbol.createSimple({'name': 'arrow', 'color_border': '55, 55, 255, 100', 'color': '144, 215, 230', 'offset': '0,0', 'size': '10.0', 'angle': '-45.0'})
      a.setMarkerSymbol(marker_symbol)

      a.setFrameSizeMm(QSizeF(width, height)) if mode == 1 else a.setFrameSizeMm(QSizeF(width, height))
      if layer : a.setMapLayer(layer)  
      a.setFrameOffsetFromReferencePoint(QPointF(0, 0))
      a.setMapPosition(point)
      if layer : a.setMapPositionCrs(QgsCoordinateReferenceSystem(layer.crs()))
      else : a.setMapPositionCrs(QgsCoordinateReferenceSystem(QgsProject().instance().crs())) 
      instance.annotationManager().addAnnotation(a) 

    
  def startStopStations(self):      
      if not self.isStartChrono :         
         deltaScrutationStation, ok = QInputDialog.getInt(None, "Paramètre", "<h2>%s :</h2><br>[%s]" % ("Intervalle de scrutation", "minutes"), 5, 1, 60, 5) 
         if not ok: return
         if deltaScrutationStation <= 0 : return
         self.deltaScrutationStation = int(deltaScrutationStation)*1000*60 

         self.timer.stop()

      self.isStartChrono = not(self.isStartChrono)
      if self.isStartChrono : self.timer.start(self.deltaScrutationStation)
      if not self.isStartChrono :
         self.playStopButtonStations.setIcon(QIcon(getThemeIcon("play.png")))
         self.playStopButtonStations.setToolTip("Jouer la scrutation dynamique des stations")
      else :
          self.updateTimer() #GET FIRST SCRUTATION
          self.playStopButtonStations.setIcon(QIcon(getThemeIcon("stop.png")))
          self.playStopButtonStations.setToolTip("Arrêter la scrutation dynamique des stations (%s min.)" % deltaScrutationStation)
      if self.isStartChrono : self.timer.start(self.deltaScrutationStation) 
      else : self.timer.stop()
 

  def reinitOccurences(self, cond):
      rootLayers = QgsProject.instance().layerTreeRoot()
      layerCrues = QgsProject.instance().mapLayersByName(self.layerCrues)
      layerCrues = layerCrues[0] if layerCrues != [] else None
      if layerCrues :
         nodeLayerCrues = rootLayers.findLayer(layerCrues)
         nodeLayerCrues.setItemVisibilityChecked(cond) 
         
         nodeParent = nodeLayerCrues.parent()
         while nodeParent :
               if cond :
                  if not nodeParent.itemVisibilityChecked() : nodeParent.setItemVisibilityChecked(cond)
               else :
                  if nodeParent.itemVisibilityChecked() : nodeParent.setItemVisibilityChecked(cond) 
               nodeParent = nodeParent.parent()
               
         self.canvas.refresh()      

      
  def startStopOccurrence(self):
      self.isStartChrono = not(self.isStartChrono)
      if self.isStartChrono : self.timer.start(5000)

      self.reinitOccurences(True)  
      
      self.updateChkOccurrenceValue()
      
      if not self.isStartChrono :
         self.playStopButton.setIcon(QIcon(getThemeIcon("play.png")))
         self.playStopButton.setToolTip("Jouer les occurences de crues")
      else :
          self.playStopButton.setIcon(QIcon(getThemeIcon("stop.png")))
          self.playStopButton.setToolTip("Arrêter les occurences de crues")
      if self.isStartChrono : self.timer.start(5000)
      else : self.timer.stop()
  
  def updateComboCrues(self):
      self.listOccurrenceValue.clear()      
      layerCrues = QgsProject.instance().mapLayersByName(self.layerCrues)
      layerCrues = layerCrues[0] if layerCrues != [] else None
      itemsValues = []
      if layerCrues :
         layerCrues.setSubsetString("")   
         itemsValues = self.listOfValuesForField(layerCrues, self.fieldCrues)
 
      listOfOccurrenceValues = self.listOfOccurrenceValues()
      diff = set(listOfOccurrenceValues)-set(itemsValues)
      itemValues = itemsValues + list(diff)
      self.itemValuesOccurences = self.getSortedValues(itemValues)
              
      self.itemValuesOccurences.insert(0, "Aucune")
      self.listOccurrenceValue.addItems(self.itemValuesOccurences)

      self.listOccurrenceValue.setEnabled(self.itemValuesOccurences != ["Aucune"])
      self.playStopButton.setEnabled(self.itemValuesOccurences != ["Aucune"])
      
      
   
  def listOfValuesForField(self, layer, fieldName):
      idx = layer.fields().indexOf(fieldName)
      uniquevalues = layer.uniqueValues(idx, -1)
      return self.getSortedValues(list(uniquevalues))


  def listOfOccurrenceValues(self):
      layers = QgsProject.instance().mapLayers()
      crues = []  
      for layer in layers :
          if re.search(self.rasterCrues, layer, re.IGNORECASE):
             mapLayer = QgsProject.instance().mapLayer(layer)
             crue = mapLayer.name().replace(self.rasterCrues, "") 
             crues.append(crue)      
      return self.getSortedValues(crues)


  def getSortedValues(self, listValues) :
      listSorted = []  
      crues = []
      for value in listValues :
          if type(value) == str :  
             crue = int(value.replace("Q", ""))
             crues.append(crue)
          elif type(value) == int : crues.append(crue)   
      for value in sorted(crues) : listSorted.append("Q%s" % value)
      return listSorted
        
  def updateViewOccurenceLayer(self) :
      root = QgsProject.instance().layerTreeRoot()
      layerCrues = QgsProject.instance().mapLayersByName("Occurrences de crues")
      layerCrues = layerCrues[0] if layerCrues != [] else None
      if layerCrues : layerCrues.setSubsetString("%s = '%s'" % (self.fieldCrues, self.listOccurrenceValue.currentText()))

      valueCrue = self.listOccurrenceValue.currentText()
      nodeCrue = None
      for crue in self.itemValuesOccurences :  
          layerCrues = QgsProject.instance().mapLayersByName("%s%s" % (crue, self.rasterCrues))
          layerCrues = layerCrues[0] if layerCrues != [] else None
          if layerCrues :
             node = root.findLayer(layerCrues.id()) 
             if crue == valueCrue : nodeCrue = node
             node.setItemVisibilityChecked(False)
             self.updateTreeLegendExpand(node, False, False)

      if nodeCrue :           
         nodeCrue.setItemVisibilityCheckedParentRecursive(True)
         nodeCrue.setItemVisibilityChecked(True)
         self.updateTreeLegendExpand(nodeCrue, False, True)

  def initLogos(self, fileLogoLeft, fileLogoRight, titleService, noaction) :
      self.fileLogoLeft, self.fileLogoRight, self.titleService, self.noaction = fileLogoLeft, fileLogoRight, titleService, noaction

  #NEW 4.0.0
  def initParamsRdi(self):
      self.mappingData, self.groupsActions, self.thematicInondations, self.thematicSubmersions = dict(MAPPINGDATA), GROUPSACTIONS, THEMATICINONDATIONS, THEMATICSUBMERSIONS
      self.layerStations, self.layerTerrain, self.layerWater, self.layerTerritoire, self.layerCrues, self.rasterCrues = LAYERSTATIONS, LAYERTERRAIN, LAYERWATER, LAYERTERRITOIRE, LAYERCRUES, RASTERCRUES
      self.pathImgStations, self.pathLocalData, self.pathLocalFolderStations, self.timezone, self.apimodelmeteo, self.nameGroupRaster = PATHIMGSTATIONS, PATHLOCALDATA, PATHLOCALFOLDERSTATIONS, TIMEZONE, APIMODELMETEO, NAMEGROUPRASTER
      self.fieldCrues = FIELDCRUES
      self.tableFieldsStations = TABLEFIELDSSTATIONS
      self.tableFieldsCommunes = TABLEFIELDSCOMMUNES
      self.tableFieldsWater = TABLEFIELDSWATER
  
  def initNorthArrow(self):
      self.svgNorthArrow = join(self.pathFolderParams, "northarrow.svg")
      if self.svgNorthArrow :
         if not exists(self.svgNorthArrow) : self.svgNorthArrow = join("%s/%s" % (dirname(__file__), "data/boussoles"), "northarrow.svg")
         if self.NorthArrow : self.NorthArrow.load(self.svgNorthArrow)
      else :
          self.svgNorthArrow = join("%s/%s" % (dirname(__file__), "data/boussoles"), "northarrow.svg")
          if not exists(self.svgNorthArrow) : self.svgNorthArrow = QgsApplication.iconPath("default.svg")
      
  def initStyleForTempoLayer(self):
      fileName = join(self.pathFolderParams, "default_mask_style.qml")
      if exists(fileName) : self.styleQml = fileName
      else : self.styleQml = join("%s/%s" % (dirname(__file__), "data/styles"), "default_mask_style.qml")
      
  def loadParamsRdi(self):      
      self.initParamsRdi()
      self.initStyleForTempoLayer()
      self.initNorthArrow()
      
      fileParam = join(self.pathFolderParams,"params.xml").replace("\\", "/") 
      error, msg, msgErr = 0, "Fichier XML valide", "Aucune erreur"
      
      try:
          doc = etree.parse(fileParam).getroot()
          if not doc.tag in ('RDI', 'rdiPlugin', 'rdigcPlugin') :
             error, msg, msgErr = 1, "Fichier XML invalide",  "Racine RDIGC absente du fichier"
      except (etree.ParseError, error):
             error, msg, msgErr = 1, "Impossibilité de parser le fichier XML", ""
      except (IOError, error):
              error, msg, msgErr = 1, "Impossible d'ouvrir le fichier XML", ""
      
      if error == 1:
         self.barInfo.pushMessage("Avertissment :", "%s [%s]." % (msg, msgErr), Qgis.Warning, 3)
         self.initParamsRdi()
      else :
        for node in doc :
            ctrlName, ctrlValue = node.tag, node.attrib.get('value')
            ctrl, ctrlType = None,  None

            if not ctrlName in ("dicosViewer","tableFieldsStations", "tableFieldsCommunes", "tableFieldsWater") :
               if ctrlName in ("fileLogoLeft", "fileLogoRight"): ctrlValue = getLogoFile(ctrlValue)
               if ctrlName == "pathImgStations" :
                  if not exists(ctrlValue) : ctrlValue = PATHIMGSTATIONS
               #NEW 4.0.0
               if ctrlName == "apimodelmeteo" :
                  index = 0
                  for key in APIMODELMETEOITEMS.keys() :
                      if APIMODELMETEOITEMS[key]["model"] == ctrlValue : break
                      index+= 1
                  ctrlValue = [index, ctrlValue]     
               setattr(self, ctrlName, ctrlValue)
               
            elif ctrlName == "dicosViewer" :
               for node in doc.iter('dicosViewer'):
                   for item in node :    
                       ctrlName =  item.tag
                       ctrlValue = {} if ctrlName in ("mappingData", "groupsActions") else [] 
                       for subItem in item :    
                           key = subItem.attrib.get('value')  
                           if type(ctrlValue) == dict : ctrlValue[key] = []
                           else : ctrlValue.append(key)      
                           for valueItem in subItem : 
                               value = valueItem.attrib.get('value')
                               try : value = eval(value)
                               except : pass
                               if type(ctrlValue) == dict : ctrlValue[key].append(value)
                       setattr(self, ctrlName, ctrlValue)
            #NEW 4.0.0
            elif ctrlName in ("tableFieldsStations", "tableFieldsCommunes", "tableFieldsWater") :           
                 ctrlValue = {}
                 for node in doc.iter(ctrlName):
                     for item in node :
                         for subItem in item :
                             key = subItem.attrib.get('name')
                             value = subItem.attrib.get('value')
                             ctrlValue[key] = value
                           
                 setattr(self, ctrlName, ctrlValue) 
                
            else : pass 


  def startMovie(self): self.movieCtrl.setVisible(True)
  def stopMovie(self): self.movieCtrl.setVisible(False)    

  def initTransformer(self):
      self.transformer = QgsCoordinateTransform() 
      self.transformer.setSourceCrs(QgsProject(self.iface).instance().crs())
      crs = QgsCoordinateReferenceSystem()
      crs.createFromOgcWmsCrs("EPSG:4326")        
      self.transformer.setDestinationCrs(crs)        

  def loadProjectRdi(self):
      currentLayer = self.iface.layerTreeView().currentLayer()
      self.updateComboActiveLayer(currentLayer)

      items = self.updateItemsForListForDataSearch() 
      if self.listForDataSearch : self.listForDataSearch.clear()
      self.listForDataSearch.addItems(items)

      if self.timer.isActive() : self.timer.stop()
      self.updateComboCrues()
      
      self.updateCompleter()
      self.zoomAll()

      if self.buttonDynamicLegend : self.updateVisibilityButtonDL()
      self.initTransformer()


  def deleteImagesInFolder(self, folder): 
      if exists(folder) :
         for dirname, dirnames, filenames in walk(folder):
             for fileName in filenames:
                 try : removeFile("%s/%s" % (folder, fileName))
                 except : pass


  def checkFoldersForExtension(self):
      folder = join(dirname(__file__),"data/temp/")
      if not exists(folder) :
         try : makedirs(folder); return folder
         except : return None

  def getActionProfilTool(self):
      try :
             from profiletool.tools.profiletool_core import ProfileToolCore
             menu = self.iface.mainWindow().findChild(QMenu, "ProfileTool")
             return True, menu.actions()[0]
      except : return False, None
      
        
  def showProfilTool(self):
 
      if not self.actionProfileTool : self.activateProfileTool, self.actionProfileTool = self.getActionProfilTool()
      if self.actionProfileTool : self.actionProfileTool.triggered.emit()
      
      self.dockWidgetProfileTool = self.iface.mainWindow().findChild(QDockWidget, "ProfileTool")
    
      if self.dockWidgetProfileTool :
            self.dockWidgetProfileTool.profiletoolcore.toolrenderer.rubberband = self.rbCanvas
            self.dockWidgetProfileTool.profiletoolcore.toolrenderer.rubberbandpoint = self.rbCanvasPoint
            self.rbCanvas.reset()
            self.rbCanvasPoint.hide()
            self.canvas.refresh()

      if self.dockWidgetProfileTool :
              self.dockWidgetProfileTool.setFloating(False)
              self.dockWidgetProfileTool.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable)
              self.dockWidgetProfileTool.setAllowedAreas(Qt.NoDockWidgetArea)
              self.dockWidgetProfileTool.setStyleSheet(
                          "QDockWidget { color:rgb(255,255,255); font-size:12px; font-weight: bold; border: 1px solid lightgray;}"
                          "QDockWidget::title {  text-align: center; background: #3e5598; padding-left: 5px;}")
              try :    
                    terrainLayer = QgsProject.instance().mapLayersByName(self.layerTerrain)[0]
                    if self.dockWidgetProfileTool.mdl.rowCount() == 0 : self.dockWidgetProfileTool.addLayer(terrainLayer)
              except : pass

                           
      if self.dockWidgetProfileTool and self.buttonProfilTool : self.setVisibility(self.dockWidgetProfileTool, self.buttonProfilTool, "profiletool_%s.png")


      if self.dockWidgetProfileTool and not self.dockWidgetProfileTool.isVisible() :
            self.dockWidgetProfileTool.profiletoolcore.cleaning()
            if self.dockWidgetProfileTool.profiletoolcore.toolrenderer : self.dockWidgetProfileTool.iface.mapCanvas().unsetMapTool(self.dockWidgetProfileTool.profiletoolcore.toolrenderer.tool)
            self.dockWidgetProfileTool.iface.mapCanvas().setMapTool(self.dockWidgetProfileTool.profiletoolcore.saveTool)
            self.dockWidgetProfileTool.iface.mainWindow().statusBar().showMessage( "" )
            self.rbCanvas.reset()
            self.canvas.refresh()

            self.canvas.setMapTool(self.lastToolMap)

      self.getUpdateRightWidgets()


  def quit(self):
      reply = QMessageBox.question(self.iface.mainWindow(), "Confirmation", "Voulez-vous vraiment quitter\nQGIS et %s maintenant ?" % self.namePlugin, QMessageBox.Yes, QMessageBox.No)
      if reply ==  QMessageBox.Yes :
         if not (self.iface.mainWindow().menuBar().isVisible() and self.iface.mainWindow().statusBar().isVisible()) :
            if self.actionToggleMapOnly : self.actionToggleMapOnly.triggered.emit()
         self.iface.actionExit().triggered.emit()

  def showNorthArrowDialog(self) :  self.setVisibility(self.NorthArrow, self.buttonNorthArrow, "northarrow_%s.png")

  #UPDATE CHART  
  def getPrintMap(self):
    
      self.buttonPrinterMap.setIcon(QIcon(getThemeIcon("printermap_on.png")))
      self.movieCtrl.setVisible(True)
      dialogInput = paramToPrintMap(self)
      
      if dialogInput.exec_() :
          
          self.orientationIndex = dialogInput.getOrientationIndex()
          self.pageFormatIndex = dialogInput.getPageFormatIndex()
          self.withComposer = dialogInput.getComposition()
          self.withLegend = dialogInput.getLegende()
          self.withNorthArrow = dialogInput.getNorthArrow()          
          pageSize = dialogInput.getPageSize()
          pageFormat = dialogInput.getPageFormat()

          orientation = QPrinter.Landscape if self.orientationIndex == 0 else QPrinter.Portrait

          if orientation == QPrinter.Portrait :  widthPage, heightPage = pageSize[0], pageSize[1]
          else : widthPage, heightPage = pageSize[1], pageSize[0]
          units = pageSize[2]
          
          fileName = None
          if not self.withComposer :
             title = "Sauvegarder une impression de la carte ..."
            
             dlgFile = QFileDialog(self.widgetToolBarNav, title)
             dlgFile.setNameFilters(("Portable Network Graphic (*.png)", "PDF (*.pdf)"))  
             dlgFile.setViewMode(QFileDialog.Detail)
             dlgFile.setDirectory(self.saveFolder)
             dlgFile.setAcceptMode(QFileDialog.AcceptSave)

             fixeLabelsFileDialog(self, dlgFile, 1, True)
          
             if dlgFile.exec_():
                fileName = fileNameWithExtension(self, dlgFile.selectedFiles()[0], dlgFile.selectedNameFilter())
                self.saveFolder = dirname(fileName)
          
          project = QgsProject.instance()         
          manager = project.layoutManager()
            
          layoutName = "PrintLayout"

          for layout in manager.printLayouts():
              if layout.name() == layoutName:  manager.removeLayout(layout)

          layout = QgsPrintLayout(project)  
          layout.initializeDefaults()  
          layout.setName(layoutName)
          manager.addLayout(layout)

          layout.pageCollection().page(0).setPageSize(pageFormat, QgsLayoutItemPage.Orientation.Portrait) if orientation == QPrinter.Portrait else layout.pageCollection().page(0).setPageSize(pageFormat, QgsLayoutItemPage.Orientation.Landscape)
            
          mappy = QgsLayoutItemMap(layout)
          mappy.setRect(20, 20, 20, 20)
          mappy.setExtent(self.canvas.extent())
          mappy.setFrameEnabled(True)
          layout.addLayoutItem(mappy)
          

          retrait = 75 if self.withLegend else 15

          mappy.attemptMove(QgsLayoutPoint(retrait-5, 30, units))
          mappy.attemptResize(QgsLayoutSize(widthPage-retrait, heightPage-45, units))

          mapScale = mappy.scale()

          if self.withLegend :
              #NEW 4.0.0  
              legend = QgsLayoutItemLegend(layout)
              layout.addLayoutItem(legend)

              legend.setResizeToContents(False)
              legend.setAutoUpdateModel(False)
              legend.setLinkedMap(mappy)
              legend.setLegendFilterByMapEnabled(True)

              legend.setMinimumSymbolSize(2.0)
              legend.setMaximumSymbolSize(2.0)
              legend.setSymbolWidth(2.0)
              legend.setSymbolHeight(2.0)

              legend.setId('Legend')
              layout.addLayoutItem(legend)
              legend.setFrameEnabled(True)
              legend.setFrameStrokeColor(QColor(0, 0, 0, 0)) 
              legend.setFrameStrokeWidth(QgsLayoutMeasurement(0.1))
              legend.setTitle('Légende :')
              legend.attemptMove(QgsLayoutPoint(10, 30, units))
              legend.attemptResize(QgsLayoutSize(retrait-16, heightPage-45, units))

              fontTitle = QFont()
              fontTitle.setPointSize(8)
              fontTitle.setItalic(False)
              fontTitle.setBold(True)
              fontTitle.setOverline(False)
              fontTitle.setUnderline(True)
              legend.setStyleFont(2, fontTitle)
              legend.setStyleMargin(2, 2.0)

              fontTitle = QFont()
              fontTitle.setPointSize(7)
              fontTitle.setItalic(True)
              fontTitle.setBold(False)
              fontTitle.setOverline(False)
              fontTitle.setUnderline(False)
              legend.setStyleFont(3, fontTitle)
              legend.setStyleMargin(3, 0.0)

              fontElement = QFont()
              fontElement.setPointSize(7)
              fontElement.setItalic(True)
              fontElement.setBold(False)
              fontElement.setOverline(False)
              fontElement.setUnderline(False)
              legend.setStyleFont(4, fontElement)
              legend.setStyleMargin(4, 0.0)

              fontSymbol = QFont()
              fontSymbol.setPointSize(7)
              fontSymbol.setItalic(True)
              fontSymbol.setBold(False)
              fontSymbol.setOverline(False)
              fontSymbol.setUnderline(False)
              legend.setStyleFont(6, fontSymbol)      

          logoPref = QgsLayoutItemPicture(layout)
          logoPref.setPicturePath(self.fileLogoLeft) 
          logoPref.setFrameEnabled(False)
          logoPref.setFrameStrokeColor(QColor(0, 0, 0, 0))            
          logoPref.attemptSetSceneRect(QRectF(10, 5, 25, 25))
          logoPref.setFrameEnabled(True)
          layout.addLayoutItem(logoPref)

          title = QgsLayoutItemLabel(layout)
          title.setText("%s" % self.titleService)
          title.setFont(QFont("Arial", 16))
          title.attemptResize(QgsLayoutSize(int(widthPage/2), 10, units))
          layout.addLayoutItem(title)
         
          title.attemptMove(QgsLayoutPoint(40, 10, units))     

          titleMap = QgsLayoutItemLabel(layout)
          titleMap.setText("Carte de situation")
          titleMap.setFont(QFont("Arial", 14))
          titleMap.adjustSizeToText()
          layout.addLayoutItem(titleMap)
          titleMap.attemptResize(QgsLayoutSize(int(widthPage/2), 10, units))
          titleMap.attemptMove(QgsLayoutPoint(40, 20, units))   

          logoRdi = QgsLayoutItemPicture(layout)
          logoRdi.setPicturePath(self.fileLogoRight) 
          logoRdi.setFrameEnabled(False)
          logoRdi.setFrameStrokeColor(QColor(0, 0, 0, 0))
          logoRdi.attemptSetSceneRect(QRectF(widthPage-55, 5, 50, 25)) 
          logoRdi.setFrameEnabled(True)
          layout.addLayoutItem(logoRdi)

           
          if self.withNorthArrow : 
              northArrow = QgsLayoutItemPicture(layout)
              northArrow.setPicturePath(self.svgNorthArrow) 
              northArrow.setFrameEnabled(False)
              northArrow.setFrameStrokeColor(QColor(0, 0, 0, 0))
              northArrow.attemptSetSceneRect(QRectF(widthPage-27, 32, 20, 20))
              northArrow.setFrameEnabled(True)
              northArrow.setLinkedMap(mappy)
              layout.addLayoutItem(northArrow)

          p = QPolygonF()
          p.append(QPointF(10.0, 30.0))
          p.append(QPointF(widthPage-6, 30.0)) 
          lineUp = QgsLayoutItemPolyline(p, layout)
          lineUp.setStartMarker(0)
          lineUp.setEndMarker(0)
          layout.addLayoutItem(lineUp)

          p = QPolygonF()
          p.append(QPointF(10.0, heightPage-15))  
          p.append(QPointF(widthPage-6, heightPage-15)) 
          lineDown = QgsLayoutItemPolyline(p, layout)
          lineDown.setStartMarker(0)
          lineDown.setEndMarker(0)
          layout.addLayoutItem(lineDown)

          scaleBar  = QgsLayoutItemScaleBar(layout)
          scaleBar.setLinkedMap(mappy)
          scaleBar.setStyle('Single Box') #('Line Ticks Middle')
          scaleBar.setNumberOfSegments(4)
          scaleBar.setFont(QFont('Arial', 8))
          scaleBar.applyDefaultSize()
          scaleBar.attemptMove(QgsLayoutPoint(10, heightPage-15, units)) 
          layout.addLayoutItem(scaleBar)

          subtitle = QgsLayoutItemLabel(layout)
          subtitle.setMode(1)
          
          infos = "<i>RDI Gestion de Crise, édition le [% format_date( now() ,  'dd MMMM yyyy') %] à [% lpad(hour(now()), 2, '0')%]h[%lpad(minute(now()),  2, '0')%] - Echelle :</i>"
          subtitle.setText(infos)
          subtitle.adjustSizeToText()
          layout.addLayoutItem(subtitle)
          subtitle.attemptMove(QgsLayoutPoint(widthPage-len(infos)+20, heightPage-10, units))
            
          scaleBarNum  = QgsLayoutItemScaleBar(layout)
          scaleBarNum.setLinkedMap(mappy)
          scaleBarNum.setStyle('Numeric') 
          scaleBarNum.setFont(QFont('Arial', 8))

          formatNumeric = QgsBasicNumericFormat()
          formatNumeric.setRoundingType(0)
          formatNumeric.setNumberDecimalPlaces(0)
          scaleBarNum.setNumericFormat(formatNumeric)
          scaleBarNum.applyDefaultSize()
          scaleBarNum.attemptMove(QgsLayoutPoint(widthPage-27, heightPage-10.25, units ))
          layout.addLayoutItem(scaleBarNum)
          

          if self.withComposer : self.iface.openLayoutDesigner(layout)             
          else : 
              if not fileName : return  
              exporter = QgsLayoutExporter(layout)

              if dlgFile.selectedNameFilter() == "PDF (*.pdf)" : exporter.exportToPdf(fileName, QgsLayoutExporter.PdfExportSettings())
              else :  exporter.exportToImage(fileName, QgsLayoutExporter.ImageExportSettings())

              if not exists(fileName):
                 self.barInfo.pushMessage("Attention :", "Fichier non trouvé : %s." % fileName, Qgis.Warning, 3)   
                 return 
              else :
                 self.barInfo.pushMessage("Information :", "Fichier %s sauvegardé !" % fileName, Qgis.Info, 3)   
                 try : webbrowseropen(fileName)
                 except :
                       self.barInfo.pushMessage("Attention :", "Application par défaut non trouvée pour ouverture du fichier :\n%s" % fileName, Qgis.Warning, 3)   

      self.movieCtrl.setVisible(False)      
      self.buttonPrinterMap.setIcon(QIcon(getThemeIcon("printermap_off.png")))

  def getPrintInformations(self):
      if not self.identifyResultsDock : return
      if not type(self.identifyResultsDock) == QDockWidget : return
      if not self.identifyResultsDock.isVisible() : return
      treeWidgetResults = self.identifyResultsDock.findChildren(QTreeWidget, "lstResults")[0]
      if not type(treeWidgetResults) == QTreeWidget : return

      self.updatePrintInformations(treeWidgetResults)
      
      if self.buttonPrinterData : self.buttonPrinterData.setIcon(QIcon(getThemeIcon("printerdata_on.png")))  
      printer = QPrinter(); printer.setPageSize(QPrinter.A4); printer.setOrientation(QPrinter.Portrait);
      printer.setPageMargins(5, 5, 5, 5, QPrinter.Millimeter); printer.setOutputFormat(QPrinter.NativeFormat);
      orientation = QPrinter.Portrait
      dlgPrint = printerPreview(self, self.printInformations, "%s : Imprimer les informations" % self.namePlugin, orientation, "printer.png")
      if self.buttonPrinterData : self.buttonPrinterData.setIcon(QIcon(getThemeIcon("printerdata_off.png")))
    
  def updatePrintInformations(self, treeWidgetResults):

      #NEW 4.4.0
      if not treeWidgetResults : return
      results, maxlevel = visitTreeList(treeWidgetResults)
      if results == [] : return

      html = "<HTML><BODY><head><title>Rapport</title></head>%s" % INFORMATIONSSTYLES
      html+= "<table width='100%%'>\n"
      html+= "<tr>\n"
      html+= "<td width='10%%'><img src='file:///%s' width='90px' height='90px'></td>\n" % self.fileLogoLeft
      html+= "<td width='85%%'><h2>%s, fiche informations</h2></td>\n" % self.titleService
      html+= "<td width='5%%'><img src='file:///%s' width='170px' height='80px'></td></tr><tr><td colspan='3'><hr></td>\n" % self.fileLogoRight
      html+= "</tr>\n"
      html+= "<tr><td colspan='3'>"
      html+= "<table id='information'>"
      nbInfos = maxlevel + 2

      for elt in results :
          if elt[0] > 0 :
              html+= "<tr>"    
              balise = "th" if elt[0] == 1 else "td" 
              for i in range(elt[0]): html+= "<%s>&nbsp;</%s>" % (balise, balise)
              html+= "<%s width=12px height=12px><img src='file:///%s' width='16px' height='16px'></%s><%s colspan=%s>%s</%s>\n" % (balise, self.imgpuce, balise, balise, nbInfos-elt[0], elt[1] + " : " + elt[3], balise)
              html+= "</tr>" 
          else :
              html+= "<tr>"
              html+= "<td colspan='3'><center><h3>%s</h3></center></td>" % (elt[1] + " : " + elt[3])
              html+= "</tr>"

      #NEW 4.0.0
      date = thedatetime.now().strftime("%A %d-%B-%Y").split("-")
      lblDate = "%s %s %s" % (date[0], date[1], date[2])        
      html+= "</table>"
      html+= "</td></tr><tr><td colspan='3'><hr></td></tr><tr><td align=right colspan='3'><i>%s, édition le %s à %s</i></td></tr></table>" % (self.namePlugin, lblDate, thedatetime.now().strftime("%Hh%M"))
      html+= "</BODY>\n</HTML>"
     
      self.printInformations.setHtml(html)


  #NEW 4.0.0     
  def updateVisibleLayersInComboActiveLayer(self):
      root = QgsProject.instance().layerTreeRoot()
      self.visibleLayers, self.noVisibleLayers = [], []
      for layer in root.findLayers() :
       if not layer.isVisible() : self.noVisibleLayers.append(layer.layer())
       else : self.visibleLayers.append(layer.layer())

      if self.comboActiveLayer : self.comboActiveLayer.setExceptedLayerList(self.noVisibleLayers) 

  def setWidgetsControls(self):
      self.qgisConsole = None
      self.layerTreeViewWidget = None
      self.layerTreeViewModel = None
      self.progressBar = None
      
      self.qgisConsole = self.iface.mainWindow().findChild(QDockWidget, "PythonConsole")

      self.layerTreeViewWidget = self.iface.mainWindow().findChild(QDockWidget, "Layers") 
      for child in self.layerTreeViewWidget.children() :
          for widget in child.children() :
              if type(widget) == QgsLayerTreeView : self.layerTreeViewModel = widget.model()    

      for child in self.iface.mainWindow().statusBar().children():
          for widget in (child.children()) :
              if type(widget) == QProgressBar :
                 self.progressBar = widget
                 self.progressBar.setMinimum(0)
                 self.progressBar.setMaximum(100)

  #NEW 4.0.0   
  def getLogConsole(self):  
      if not self.logConsole :
          w, h = 300, 300
          self.logConsole = logConsole(self.iface.mapCanvas(), self.buttonLogConsole, w, h, self.namePlugin) 
          self.logConsole.setupUi()
          sW, sH = getResolutionScreen()
          self.logConsole.setGeometry(sW-w-10, sH-h-80, w, h)

      self.setVisibility(self.logConsole, self.buttonLogConsole, "logconsole_%s.png")

  def getVirtualKeyboard(self):
      if not self.vKeyboard :
          self.vKeyboard = virtualKeyboard(self) 
          self.vKeyboard.setupUi()
          mw= self.iface.mainWindow()  
          w, h = int(self.vKeyboard.width()/2), self.vKeyboard.height()
          self.vKeyboard.setGeometry(int(mw.width()/2)-w, mw.height()-h, w, h)

      self.setVisibility(self.vKeyboard, self.buttonVirtualKeyboard, "keyboard_%s.png")


  def getWidthUnder(self):
      widthUnder, partialWidthUnder = 0, 0
      
      dockWidget = self.iface.mainWindow().findChildren(QDockWidget, "Layers")
      if dockWidget :
         if  type(dockWidget) == list : dockWidget = dockWidget[0]
         if dockWidget.isVisible() :  widthUnder = dockWidget.width(); partialWidthUnder = dockWidget.width()
         
      
      if self.identifyResultsDock :
         if type( self.identifyResultsDock) == QDockWidget :  
            if self.identifyResultsDock.isVisible() :  widthUnder+= self.identifyResultsDock.width()
            if self.buttonPrinterData : self.buttonPrinterData.setEnabled(self.identifyResultsDock.isVisible())
      return widthUnder, partialWidthUnder

  def getHeightUnder(self):
      heightUnder = 0  
      if self.dockWidgetProfileTool :
         if type( self.dockWidgetProfileTool) == QDockWidget :    
            if self.dockWidgetProfileTool.isVisible() :  heightUnder = self.dockWidgetProfileTool.height()
      return heightUnder


  def getUpdateRightWidgets(self):
      cond, value = self.getIsFullScreen()
      self.updateRightWidgets(cond)  


  def updateRightWidgets(self, cond):
      widthUnder, partialWidthUnder = self.getWidthUnder()
      mw = self.iface.mainWindow()
              
      if self.NorthArrow :
         w, h = self.NorthArrow.width(), self.NorthArrow.height()
         self.NorthArrow.setGeometry(self.iface.mapCanvas().width()-w-20 , 25, w, h)

      #NEW 4.0.0
      if self.logConsole :      
          w, h = self.logConsole.width(), self.logConsole.height()
          sW, sH = getResolutionScreen()
          self.logConsole.setGeometry(sW-w-10, sH-h-80, w, h)
           
      if self.vKeyboard :
         if self.vKeyboard.isVisible() :   
            w, h = int(self.vKeyboard.width()/2), self.vKeyboard.height()
            self.vKeyboard.setGeometry(int(mw.width()/2)-w, mw.height()-h, w, h)
            
      if self.widgetRisquesEnjeux :      
            w, h = self.widgetRisquesEnjeux.width(), self.widgetRisquesEnjeux.height()
            if not cond : self.widgetRisquesEnjeux.setGeometry(10, mw.height()-h-10, w, h)
            else : self.widgetRisquesEnjeux.setGeometry(10, mw.centralWidget().height()-h-10, w, h)


  def quitFullScreen(self):
      if not self.iface.mainWindow().menuBar().isVisible() and not self.iface.mainWindow().statusBar().isVisible() : self.getActionToggleMapOnly()
      
        
  def getIsFullScreen(self):
      cond = self.iface.mainWindow().menuBar().isVisible() and self.iface.mainWindow().statusBar().isVisible()
      value = "on" if not cond else "off"
      return cond, value

  def updateVisibilityButtonDL(self):
      cond = "on" if self.widgetDynamicLegend.isVisible() else "off"   
      if self.buttonDynamicLegend : self.buttonDynamicLegend.setIcon(QIcon(getThemeIcon("legenddynamic_%s.png" % cond)))
      
  def updateTopLevelWidgetDynamicLegend(self):
      if self.widgetDynamicLegend.isFloating() :  self.widgetDynamicLegend.setFloating(False) 
    
  def getActionToggleMapOnly(self):
      visibilityDl = False  
      if self.widgetDynamicLegend :  visibilityDl = self.widgetDynamicLegend.isVisible()   

      if self.dockWidgetProfileTool :  visibilityPt = self.dockWidgetProfileTool.isVisible()
      if self.identifyResultsDock :
         if type(self.identifyResultsDock) == QDockWidget :   visibilityRd = self.identifyResultsDock.isVisible()

      if self.actionToggleMapOnly : self.actionToggleMapOnly.triggered.emit()

      cond, value = self.getIsFullScreen()
     
      self.actionFullScreen.setIcon(QIcon(getThemeIcon("fullscreen_%s.png" % value)))
      self.actionFullScreen.setShortcut(QKeySequence("Escape")) if value == "on" else self.actionFullScreen.setShortcut(QKeySequence("F4"))
      self.statutMaximized = not cond

      if self.dockWidgetProfileTool :  self.dockWidgetProfileTool.setVisible(visibilityPt)
      if self.identifyResultsDock :
         if type(self.identifyResultsDock)==QDockWidget : self.identifyResultsDock.setVisible(visibilityRd)

      self.updateRightWidgets(cond)

      if self.buttonDynamicLegend :
         if self.widgetDynamicLegend : self.widgetDynamicLegend.setVisible(visibilityDl)

      
  def getWidgetDynamicLegend(self):
      if not self.widgetDynamicLegend : return 
      self.setVisibility(self.widgetDynamicLegend, self.buttonDynamicLegend, "legenddynamic_%s.png")  


  def setVisibilityToolBarNav(self) : self.setVisibility(self.widgetToolBarNav, self.actionToolBarNav, "navigation_%s.png")
  
  def getToolBarNav(self):  
    
     if not self.widgetToolBarNav :
                
           self.widgetToolBarNav = actionsWindows(self.canvas, "widgetToolBarNav", "Outils de navigation", 320, 65 )
           sizeWidth = ctrlMap(self, self.widgetToolBarNav, True, False, False, 5, 0, 310, 30)           
           initSizeToolBar(self.widgetToolBarNav, 55, 10, sizeWidth+20, 65)           

           self.toolPan = QgsMapToolPan(self.canvas)
           self.toolZoomIn = QgsMapToolZoom(self.canvas, False) 
           self.toolZoomOut = QgsMapToolZoom(self.canvas, True)

           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.buttonZoomPrevious.clicked.connect(self.zoomPrevious)
           self.buttonZoomNext.clicked.connect(self.zoomNext)
 
           self.buttonIdentifyData.clicked.connect(self.getToolBarIdentifyData)

           self.canvas.setMapTool(self.toolPan) 
           self.lastToolMap = self.canvas.mapTool()
           self.oldToolMap

     self.setVisibility(self.widgetToolBarNav, self.actionToolBarNav, "navigation_%s.png")     


  def setActiveLayer(self, layer):
      if not layer : return
      if not self.comboActiveLayer : return
      
      self.comboActiveLayer.blockSignals(True)
      self.canvas.blockSignals(True)
      self.widgetDynamicLegend.blockSignals(True)
      self.iface.layerTreeView().blockSignals(True)
      self.canvas.blockSignals(True)

      self.initComboActiveLayer()      
      self.iface.setActiveLayer(layer)
      self.canvas.blockSignals(False)
      self.comboActiveLayer.blockSignals(False)

      self.widgetDynamicLegend.blockSignals(False)
      self.iface.layerTreeView().blockSignals(False)
      self.canvas.blockSignals(False)

      self.setMapTips() 

  def setUpdateComboActiveLayer(self):
      if not self.comboActiveLayer : return
      self.comboActiveLayer.blockSignals(True)
      if self.comboActiveLayer.currentLayer() : self.iface.setActiveLayer(self.comboActiveLayer.currentLayer())
      self.comboActiveLayer.blockSignals(False)
      self.blockIdentifyToolMap()      

  def updateComboActiveLayer(self, layer):
      if not self.comboActiveLayer : return
      if not layer : return

      #NEW 4.0.0
      self.updateVisibleLayersInComboActiveLayer()

      layerTree = QgsProject.instance().layerTreeRoot().findLayer(layer.id())
      if not layerTree :
            self.comboActiveLayer.blockSignals(False)
            return
        
      if not layerTree.isVisible() : return
      
      self.comboActiveLayer.blockSignals(True)              
      if layerTree.itemVisibilityChecked() : self.comboActiveLayer.setLayer(layer)
      else : self.setUpdateComboActiveLayer()
      self.comboActiveLayer.blockSignals(False)
      self.setMapTips() 
      
  
  def updateMemoryLayer(self):
      instance = QgsProject.instance()
      try : cond = (self.memoryLayer.id() in instance.mapLayers().keys())
      except : cond = False
      try :
          self.deleteMaskData.setEnabled(cond)
          self.activeMaskData.setEnabled(not cond)
      except : pass
      if not cond : self.memoryLayer = None

  def updateEnabledButtons(self, cond):
      if self.buttonIdentifyWebH : self.buttonIdentifyWebH.setEnabled(cond)
      if self.buttonIdentifyWebD : self.buttonIdentifyWebD.setEnabled(cond)
      if self.buttonIdentifyWebStats : self.buttonIdentifyWebStats.setEnabled(cond)
      
      if cond == False :
         self.emitAction("buttonIdentifyObj")
         if not self.comboActiveLayer : return
         if not self.comboActiveLayer.currentLayer() : return
         self.canvas.setCurrentLayer(self.comboActiveLayer.currentLayer())

  def emitAction(self, nameAction):
      try : action = self.toolsHotLink.findChild(QAction, nameAction)
      except : action = None      
      if action : action.triggered.emit()
      else : self.updateTool(nameAction, None)
      self.setMapTips()   
      
  def initComboActiveLayer(self):
      instance = QgsProject.instance()
      if not self.comboActiveLayer : cond = False
      else : cond = iff(instance.mapLayersByName(self.layerStations) and self.comboActiveLayer.currentText() == self.layerStations, True, False)
      self.updateEnabledButtons(cond)

      if self.iface.sender() == self.comboActiveLayer :
          nameAction = "buttonIdentifyObj"  if not cond else self.buttonIdentify.whatsThis()
          self.emitAction(nameAction)
  
  def updateToolByNameAction(self): 
      self.buttonIdentify.setStyleSheet("QPushButton {border-width: 5px; border-radius: 10px; border-color: black; background-color:  #7eff00;}")
      self.emitAction(self.buttonIdentify.whatsThis())

  def setUpdateTool(self):
      #NEW 4.0.0
      if self.iface.sender() != self.listTargetMeteo :
         self.updateTool(self.iface.sender().objectName(), self.iface.sender())
         self.buttonIdentify.setIcon(self.iface.sender().icon())
         self.buttonIdentify.setToolTip(self.iface.sender().toolTip())
         self.setMapTips()
      else : self.resetActionIdentifyObj()
  
         
  def updateTool(self, nameTool, obj):
      if not self.buttonIdentify : return
      if not self.buttonIdentify.isChecked() : self.buttonIdentify.setChecked(True)
      if nameTool == "buttonIdentifyObj" : self.canvas.setMapTool(self.actionIdentifyObj())      
      else : self.canvas.setMapTool(self.extractDataFromWebService())
      self.resetActionIdentifyObj()
      self.buttonIdentify.setStyleSheet("QPushButton {border-width: 5px; border-radius: 10px; border-color: black; background-color: #7eff00;}")
      self.lastToolMap = self.canvas.mapTool()

      if obj :
         self.buttonIdentify.setWhatsThis(nameTool)
         self.buttonIdentify.setIcon(obj.icon())
          
   
  def getToolBarIdentify(self):
      if not self.widgetToolBarIdentify :
           self.widgetToolBarIdentify = actionsWindows(self.canvas, "widgetToolBarIdentify", "Outils d'interrogation", 230, 65 )
           sizeWidth = ctrlMap(self, self.widgetToolBarIdentify, True, False, False, 5, 0, 220, 40) 
           
           self.comboActiveLayer.layerChanged.connect(self.setActiveLayer) 
           initSizeToolBar(self.widgetToolBarIdentify, 55, 80, sizeWidth+20, 65)

           dicoCtrls = {"buttonIdentifyObj"  : ("identifyobj_off.png", "Interroger les entités de la couche sélectionnée...\n"),
                        "chkMapTips"   :  ("tooltipobj_off.png", "Visualiser les infos-bulles pour les entités de la couche sélectionnée...\n"),
                        "buttonIdentifyWebH" : ("identifywebH_off.png", "Interroger une station sur ses hauteurs d'eau (H)...\nLa couche des stations hydro doit être sélectionnée."),
                        "buttonIdentifyWebD" : ("identifywebD_off.png", "Interroger une station sur ses débits d'eau (Q)...\nLa couche des stations hydro doit être sélectionnée."),
                        "buttonIdentifyWebStats" : ("identifywebSTATS_off.png", "Interroger les statistiques d'une station...\nLa couche des stations hydro doit être sélectionnée.")
                        }
        
           self.toolsHotLink = QMenu("Interrogation des objets")

           for key in dicoCtrls :
               icon = getThemeIcon(dicoCtrls[key][0])  
               text = dicoCtrls[key][1]
               action = QAction(QIcon(icon), text.split("\n")[0], self.toolsHotLink)
               action.setObjectName(key)
               action.setToolTip(text)
               if key == "chkMapTips" :
                  action.setCheckable(True)
                  action.triggered.connect(self.setMapTips)
               else : action.triggered.connect(self.setUpdateTool)               
               self.toolsHotLink.addAction(action)                   
               setattr(self, key, action)

               if key in ("chkMapTips", "buttonIdentifyWebD") : self.toolsHotLink.addSeparator()

           self.buttonIdentify.setCheckable(True)
           self.buttonIdentify.setChecked(False)
           self.buttonIdentify.setWhatsThis("buttonIdentifyObj")
           self.buttonIdentify.clicked.connect(self.updateToolByNameAction)

           self.optionsIdentify.setMenu(self.toolsHotLink)

           self.actionQgisIdentify = self.getActionQgisIdentifyObj()
           self.actionIdentifyWebH = getDataFromWebServices(self.iface, self, self.canvas, "H")
           self.actionIdentifyWebD = getDataFromWebServices(self.iface, self, self.canvas, "Q")
           self.actionIdentifyWebStats = getDataFromWebServices(self.iface, self, self.canvas, "STATS")
           self.identifyResultsDock = self.iface.mainWindow().findChildren(QDockWidget, "IdentifyResultsDock")          
           
      self.setVisibility(self.widgetToolBarIdentify, self.actionToolIdentify, "datasearch_%s.png")
      if type(self.lastToolMap) == QgsMapToolIdentify : self.initComboActiveLayer()


  def extractDataForReporting(self):
      if not self.dialogReportingStations :  
          changeButtonIcon(self, self.buttonFullStations,"bulletin_on.png")
          self.dialogReportingStations = reportingStations(self, self.iface, self.canvas, self.buttonFullStations, "", self.namePlugin); self.dialogReportingStations.show();       
      else :
          if not self.dialogReportingStations.isVisible() : changeButtonIcon(self, self.buttonFullStations,"bulletin_on.png");
          self.dialogReportingStations.show()
          self.dialogReportingStations.repaint() 


  def updateItemsForListForDataSearch(self):
      items = [key for key in self.mappingData.keys()]
      itemsOut = self.checkItemsForListForDataSearch(self.mappingData)
      items = sorted([item for item in items if item not in itemsOut])
      return items

  def checkItemsForListForDataSearch(self, dico) :
      itemsOut = []
      instance = QgsProject.instance()
      for key in dico.keys() :
          findKey = False  
          for value in self.mappingData[key][0]:  
              if instance.mapLayersByName(value) : findKey = True; break      

          if not findKey : itemsOut.append(key)
      return itemsOut   

  def getToolBarIdentifyData(self):
      if not self.widgetToolBarIdentifyData :

           self.widgetToolBarIdentifyData = actionsWindows(self.canvas, "widgetToolBarIdentifyData", "Outils de recherche par la donnée", 630, 65 )
           self.widgetToolBarIdentifyData.setGeometry(430, 10, 690, 65) 

           self.toolBarSearch = QToolBar(self.widgetToolBarIdentifyData)
           self.toolBarSearch.setObjectName("toolBarSearch")
           self.toolBarSearch.setGeometry(10, 20, 680, 48)
           
           self.groupListForDataSearch = QGroupBox(self.toolBarSearch)
           setObjSizes(self.groupListForDataSearch, 160, 30)
           self.groupListForDataSearch.setStyleSheet("QGroupBox { border-style: outset; border-radius: 3px;  selection-color: black; selection-background-color: lightgray;}") 
           
           self.setCompleter = funnyPushButton(self.groupListForDataSearch)
           self.setCompleter.initPushButton(25, 19, 0, 0, "setCompleter", "", "Recharger la liste des couches paramétrées pour la recherche", True, QIcon(getThemeIcon("refresh.png")), 25, 19, True, False)
           self.setCompleter.setGeometry(3, 6, 25, 19)           
           self.setCompleter.clicked.connect(self.updateCompleter)

           items = self.updateItemsForListForDataSearch() 

           self.listForDataSearch = QComboBox(self.groupListForDataSearch)
           setObjSizes(self.listForDataSearch, 130, 30)
           self.listForDataSearch.setGeometry(30, 0, 130, 30)
           self.listForDataSearch.addItems(items)
           self.listForDataSearch.setToolTip("Liste des couches paramétrées pour la recherche")
           self.listForDataSearch.setCurrentIndex(1)
           self.listForDataSearch.setStyleSheet(self.styleComboBox)
           

           self.toolBarSearch.addWidget(self.groupListForDataSearch)

           self.previousData = funnyPushButton(self.toolBarSearch)
           self.previousData.initPushButton(45, 32, 0, 0, "previousData", "", "Enregistrement précédent", True, QIcon(getThemeIcon("previous.png")), 45, 32, True, False)
           self.previousData.clicked.connect(self.goToData)           
           self.toolBarSearch.addWidget(self.previousData)

           self.textForDataSearch = QgsFilterLineEdit(self.toolBarSearch)
           setObjSizes(self.textForDataSearch, 220, 30)
           self.textForDataSearch.completer = QCompleter([])  
           self.textForDataSearch.completer.setCaseSensitivity(Qt.CaseInsensitive)
           self.textForDataSearch.completer.setMaxVisibleItems(1000)
           self.textForDataSearch.completer.setModelSorting(QCompleter.UnsortedModel)
           self.textForDataSearch.setToolTip("Zone de saisie de la valeur recherchée")
           self.textForDataSearch.setStyleSheet("QLineEdit { border-style: outset; background-color: rgba(255, 255, 255, 175);}")

           self.textForDataSearch.textChanged.connect(self.lineEditTextChanged)
           self.textForDataSearch.completer.activated[QModelIndex].connect(self.resultSelected)
           self.textForDataSearch.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) 
           self.textForDataSearch.completer.setFilterMode(Qt.MatchStartsWith)

           self.toolBarSearch.addWidget(self.textForDataSearch)
           
           self.zoomData = funnyPushButton(self.toolBarSearch)
           self.zoomData.initPushButton(45, 32, 0, 0, "zoomData", "", "Localiser l'entité", True, QIcon(getThemeIcon("zoomdata.png")), 45, 32, True, False)
           self.zoomData.clicked.connect(self.zoomToData)
           self.toolBarSearch.addWidget(self.zoomData)

           self.nextData = funnyPushButton(self.toolBarSearch)
           self.nextData.initPushButton(45, 32, 0, 0, "nextData", "", "Enregistrement suivant", True, QIcon(getThemeIcon("next.png")), 45, 32, True, False)
           self.nextData.clicked.connect(self.goToData)
           self.toolBarSearch.addWidget(self.nextData)
           
           self.activeMaskData = funnyPushButton(self.toolBarSearch)
           self.activeMaskData.initPushButton(45, 32, 0, 0, "searchData", "", "Localiser et activer le masque", True, QIcon(getThemeIcon("addfilter.png")), 45, 32, True, False)
           self.activeMaskData.clicked.connect(self.zoomToData)
           self.toolBarSearch.addWidget(self.activeMaskData)

           self.deleteMaskData = funnyPushButton(self.toolBarSearch)
           self.deleteMaskData.initPushButton(45, 32, 0, 0, "deleteMaskData", "", "Désactiver le masque", True, QIcon(getThemeIcon("nofilter.png")), 45, 32, True, False)
           #NEW 4.0.0
           self.deleteMaskData.setEnabled(False)
           self.deleteMaskData.clicked.connect(self.killMemoryLayerFromProject) 
           self.toolBarSearch.addWidget(self.deleteMaskData)

           self.deleteSelections = funnyPushButton(self.toolBarSearch)
           self.deleteSelections.initPushButton(45, 32, 0, 0, "deleteSelections", "", "Désélectionner Tout\n(Toutes les couches)", True, QIcon(getThemeIcon("noselection.png")), 45, 32, True, False)
           self.deleteSelections.clicked.connect(self.cleanSelection)
           self.toolBarSearch.addWidget(self.deleteSelections)
           

           self.updateCompleter()
           self.listForDataSearch.currentIndexChanged.connect(self.updateCompleter)

      self.setVisibility(self.widgetToolBarIdentifyData, self.buttonIdentifyData, "identifydata_%s.png")


  #NEW 4.0.0
  def getIhmImpacts(self):    
      changeButtonIcon(self, self.buttonServiceImpacts,"stationimpacth_on.png")
      self.dialogImpacts = ui_Impacts(self); self.dialogImpacts.exec_()
      changeButtonIcon(self, self.buttonServiceImpacts,"stationimpacth_off.png")
      if self.layerStations : self.layerStations.setSubsetString("") 
      
  def getParamsRdi(self):
      changeButtonIcon(self, self.buttonParams,"parametres_on.png")
      self.dialogParams = ui_Params(self); self.dialogParams.exec_()
      changeButtonIcon(self, self.buttonParams,"parametres_off.png")
 
  def addWmsLayer(self):
      self.buttonGetWMS.setIcon(QIcon(getThemeIcon("addwms_on.png")))
      self.actionAddWmsLayer.triggered.emit()
      self.buttonGetWMS.setIcon(QIcon(getThemeIcon("addwms_off.png")))
        
  def setEnabledPrintData(self):
      if self.identifyResultsDock :
         if type(self.identifyResultsDock) == QDockWidget : self.buttonPrinterData.setEnabled(self.identifyResultsDock.isVisible())
         else : self.buttonPrinterData.setEnabled(False) 
      else : self.buttonPrinterData.setEnabled(False) 

  def resetActionIdentifyObj(self):
      if self.identifyResultsDock :
         if type(self.identifyResultsDock) == QDockWidget :   
               if self.identifyResultsDock.isVisible() : self.identifyResultsDock.hide()

      self.buttonIdentify.setChecked(False)
      for button in (self.buttonZoomIn, self.buttonZoomOut, self.buttonPan, self.buttonIdentify):
            if self.iface.sender() != button :
                 if button :
                    button.setStyleSheet("QPushButton {border-width: 0px; border-radius: 10px; background: transparent; }")
                    
      self.getUpdateRightWidgets()

  
  def setCursorForMapTips(self):
      if not self.chkMapTips.isChecked() :          
          self.chkMapTips.setIcon(QIcon(getThemeIcon("tooltipobj_off.png")))
          if type(self.canvas.mapTool()) == QgsMapToolIdentify : self.canvas.mapTool().setCursor(QCursor(QPixmap(QgsApplication.iconPath("mIdentify.svg"))))
      else :
          self.chkMapTips.setIcon(QIcon(getThemeIcon("tooltipobj_on.png")))
          if type(self.canvas.mapTool()) == QgsMapToolIdentify : self.canvas.mapTool().setCursor(QCursor(QPixmap(QgsApplication.iconPath("mActionMapTips.svg"))))
      
  def setMapTips(self):
      if not self.chkMapTips : return
      self.iface.actionMapTips().setChecked(self.chkMapTips.isChecked())
      self.setCursorForMapTips()
  
  def actionIdentifyObj(self):
      
      self.resetActionIdentifyObj()
      self.setMapTips()
      
      if not self.identifyResultsDock :
  
         self.actionQgisIdentify.triggered.emit()
               
         self.identifyResultsDock = self.iface.mainWindow().findChildren(QDockWidget, "IdentifyResultsDock")
         
         if self.identifyResultsDock :
            
            if type(self.identifyResultsDock) == list : self.identifyResultsDock = self.identifyResultsDock[0]
            self.identifyResultsDock.visibilityChanged.connect(self.getUpdateRightWidgets)
            self.identifyResultsDock.topLevelChanged.connect(self.updateButPrintInDockWidget)            
            
            conteneur  = self.identifyResultsDock.findChildren(QDialog, "QgsIdentifyResultsBase")[0]

            target = None
            try : target = self.identifyResultsDock.findChildren(QComboBox, "cmbIdentifyMode")[0]
            except : pass

            targetFeatureForm = None
            try : targetFeatureForm = self.identifyResultsDock.findChildren(QAction, "mActionAutoFeatureForm")[0] 
            except : pass

            targetButtonHelp = None
            try : targetButtonHelp = self.identifyResultsDock.findChildren(QToolButton, "mHelpToolButton")[0]
            except : pass

            if target : target.setCurrentIndex(0); target.setEnabled(False);
            if targetFeatureForm : targetFeatureForm.setChecked(False); targetFeatureForm.setEnabled(False) ;
            if targetButtonHelp : targetButtonHelp.setEnabled(False)
            if conteneur : conteneur.setContextMenuPolicy(Qt.NoContextMenu)

            self.updateIdentifyDock()            
            self.identifyResultsDock.show()

      else :
            if type(self.identifyResultsDock) == list : self.identifyResultsDock = self.identifyResultsDock[0]
            if not self.identifyResultsDock.isVisible() :
                
               self.actionQgisIdentify.triggered.emit()

               self.updateIdentifyDock()               
               self.identifyResultsDock.show()
               
            else :
               self.canvas.setMapTool(self.lastToolMap)

      
      self.getUpdateRightWidgets()

  def updateIdentifyDock(self):
      if not self.identifyResultsDock : return 
      self.identifyResultsDock.buttonPrintData = QPushButton(self.identifyResultsDock)
      self.identifyResultsDock.buttonPrintData.setIconSize(QSize(24, 24))
      self.identifyResultsDock.buttonPrintData.setIcon(QIcon(getThemeIcon("printerdata_off.png")))
      self.identifyResultsDock.buttonPrintData.setToolTip("Imprimer les informations")
      self.updateButPrintInDockWidget()
      self.identifyResultsDock.buttonPrintData.clicked.connect(self.getPrintInformations)
      self.identifyResultsDock.buttonPrintData.setVisible(True)      

  def updateButPrintInDockWidget(self):
      self.identifyResultsDock.buttonPrintData.setGeometry(5, 5, 24, 24) if self.identifyResultsDock.isFloating() else self.identifyResultsDock.buttonPrintData.setGeometry(5, 20, 24, 24)    

  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 updateCkeckedGroups(self):

      obj = self.iface.sender()
      key = obj.objectName()
      if not key : return          
      if key == "" : return

      key = key.replace("button", "action")
                
      if dicoHasKey(self.groupsActions, key) :
         thematics = self.groupsActions[key]
         target = self.contextMnuSurAleas if key.lower().find("risques") > -1 else self.contextMnuEnjeux   
         
         icon = key.lower().replace("action", "").replace("enjeux", "").replace("risques", "") 
         for thematic in thematics :
             node = self.updateCheckedGroup(thematic)
             if node :
                value = "on" if node.itemVisibilityChecked() else "off"

                if value == "on" : self.updateTreeLegendExpand(node, True, True)
                else : self.updateTreeLegendExpand(node, True, False)
                
                icon = QIcon(getThemeIcon("%s_%s.png" % (icon, value )))

                for action in target.actions():
                    if action.objectName() == key :
                       action.setIcon(icon)
                       action.setChecked(value == "on")
                       break

                button = self.groupThematicSearch.findChild(switchButtonRdi, key)
                if button :
                   button.setIcon(icon)
                   button.setChecked(value == "on")

      #NEW 4.0.0 
      self.updateVisibleLayersInComboActiveLayer()            

                

  def updateCheckedGroup(self, nameGroup) :
      group = None
      root = QgsProject.instance().layerTreeRoot()
      group = root.findGroup(nameGroup)
      if group :
         cond = group.itemVisibilityChecked()
         if not group.parent().itemVisibilityChecked() : group.setItemVisibilityCheckedParentRecursive(True)
         group.setItemVisibilityCheckedRecursive(not cond)
      return group


  #NEW 4.0.0 
  def setGroupVisibility(self, visibleGroup):
      groups = [self.groupCrues, self.groupStations, self.groupMeteo]
      for group in groups :
          group.setVisible(False) if group != visibleGroup else group.setVisible(True)
    
  def updateGroupServices(self):      
      if not self.iface.sender() : return
      self.isStartChrono = False 
      self.timer.stop()
      if self.iface.sender().objectName() == "actionServiceCrues" :
         self.setGroupVisibility(self.groupCrues)
         self.playStopButton.setIcon(QIcon(getThemeIcon("play.png")))
         self.playStopButton.setToolTip("Jouer les occurences de crues")         
         
      elif self.iface.sender().objectName() == "actionServiceStations" :
           self.setGroupVisibility(self.groupStations)
           self.playStopButtonStations.setIcon(QIcon(getThemeIcon("play.png")))
           self.playStopButtonStations.setToolTip("Jouer la scrutation dynamique des stations")

      elif self.iface.sender().objectName() == "actionServiceMeteo" :
           self.setGroupVisibility(self.groupMeteo)
        
      
  def contextMnuServices(self, obj):  
      self.contextMnuServices = QMenu()
      self.contextMnuServices.setStyleSheet("QMenu::item:checked { background: #7eff00;}")
      self.actionGroupServices = QActionGroup(self.contextMnuServices)
      self.actionGroupServices.setExclusive(True)

      dicoCtrls = {"actionServiceCrues" : ("crues.png", "Service crues"),
                   "actionServiceStations" : ("station.png", "Service stations"),
                   "actionServiceMeteo" : ("meteo.png", "Service météo"),
                   }
      i = 1  
      for key in dicoCtrls :
          icon = getThemeIcon(dicoCtrls[key][0])  
          text = QApplication.translate("rdigc", dicoCtrls[key][1])
          action = QAction(QIcon(icon), text, self.contextMnuAleas)
          action.setObjectName(key)
          action.setCheckable(True)
          action.setProperty("id", i)
          action.setActionGroup(self.actionGroupAleas)
          if i == 1 : action.setChecked(True)
          action.setData(i)
          self.contextMnuServices.addAction(action)
          action.triggered.connect(self.updateGroupServices)
          setattr(self, key, action)
          if key == "actionServiceCrues" : self.contextMnuServices.addSeparator()
          i+= 1

      self.contextMnuServices.setStyle(self.style)
      obj.setMenu(self.contextMnuServices)

  def contextMnuAleas(self, obj):

      self.contextMnuAleas = QMenu()
      self.contextMnuAleas.setStyleSheet("QMenu::item:checked { background: #7eff00;}")
      self.actionGroupAleas = QActionGroup(self.contextMnuAleas)
      self.actionGroupAleas.setExclusive(True)

      dicoCtrls = {"actionAleaNone" : ("none.png", "Aucun Aléa"),
                   "actionAleasAll" : ("all.png", "Tous les Aléas"),
                   "actionAleaInondation" : ("inondations.png", "Aléa Inondation"),
                   "actionAleaSubmersion" : ("submersions.png", "Aléa Submersion")
                   }
      i = 1  
      for key in dicoCtrls :
          icon = getThemeIcon(dicoCtrls[key][0])  
          text = QApplication.translate("rdigc", dicoCtrls[key][1])
          action = QAction(QIcon(icon), text, self.contextMnuAleas)
          action.setObjectName(key)
          action.setCheckable(True)
          action.setProperty("id", i)
          action.setActionGroup(self.actionGroupAleas)
          if i == 1 : action.setChecked(True)
          action.setData(i)
          self.contextMnuAleas.addAction(action)
          action.triggered.connect(self.updateGroupAleaByListMember)
          if key != "actionAleaSubmersion" : self.contextMnuAleas.addSeparator()
          setattr(self, key, action)
          i+= 1

      self.contextMnuAleas.setStyle(self.style)
      obj.setMenu(self.contextMnuAleas)


  def contextMnuButtons(self, obj, mnu) :
      dicoCtrls = {}
      
      if mnu == self.contextMnuSurAleas :
          dicoCtrls = {"actionRisquesMt" : ("mt_off.png", "Mouvements de terrains"),
                       "actionRisquesOh" : ("oh_off.png", "Rupture barrage ou digue"),
                       "actionRisquesStep" : ("step_off.png", "STEP - assainissement"),
                       "actionRisquesIcpe" : ("icpe_off.png", "Risque industriel")
                       }
      elif  mnu == self.contextMnuEnjeux :
          dicoCtrls = {"actionEnjeuxPersonnes" : ("personnes_off.png", "Personnes"),
                       "actionEnjeuxReseaux" : ("reseaux_off.png", "Réseaux, VRD, etc"),
                       "actionEnjeuxBiens" : ("biens_off.png", "Biens"),
                       "actionEnjeuxEcologie" : ("ecologie_off.png", "Ecologie")
                       }          
      
      for key in dicoCtrls :
          icon = getThemeIcon(dicoCtrls[key][0])  
          text = QApplication.translate("rdigc", dicoCtrls[key][1])
          action = QAction(QIcon(icon), text, mnu)
          action.setObjectName(key)
          action.setCheckable(True)
          mnu.addAction(action)
          action.triggered.connect(self.updateCkeckedGroups)
          setattr(self, key, action)
          mnu.addSeparator()
      
      mnu.setStyle(self.style)
      obj.setMenu(mnu)


  def saveMapAsImage(self):
        title = "Sauvegarder une image de la carte ..."
        
        dlgFile = QFileDialog(self.widgetToolBarNav, title)
        dlgFile.setNameFilters(("Portable Network Graphic (*.png)", "JPEG (*.jpg)"))  
        dlgFile.setViewMode(QFileDialog.Detail)
        dlgFile.setDirectory(self.saveFolder)
        dlgFile.setAcceptMode(QFileDialog.AcceptSave)

        fixeLabelsFileDialog(self, dlgFile, 1, True)     

        if dlgFile.exec_():
           fileName = fileNameWithExtension(self, dlgFile.selectedFiles()[0], dlgFile.selectedNameFilter())
           self.canvas.saveAsImage(fileName, None, QFileInfo(fileName).suffix().upper())
           self.saveFolder = dirname(fileName)

 
  def lineEditTextChanged(self):
      self.listOfValues = self.returnFilter(self.textForDataSearch.text())
      if self.listOfValues != [] : self.textForDataSearch.completer.model().setStringList(sorted(self.listOfValues))
      else : self.textForDataSearch.completer.model().setStringList(self.suggestions)
      self.textForDataSearch.completer.complete()
      self.textForDataSearch.setStyleSheet("QLineEdit { border-style: outset; background-color: rgba(255, 255, 255, 175);}")
      index = -1 
      if self.textForDataSearch.text() in self.suggestions :  index = self.suggestions.index(self.textForDataSearch.text())
      self.updateButNextPrevious(index)     

  def updateViewThematicLayers(self):
     
      thematics = []
      allThematics = self.thematicInondations + self.thematicSubmersions

      if not self.buttonGroupAlea.sender() : return
      id = self.buttonGroupAlea.checkedId() 
      if id == 1 : thematics = []
      elif id == 2 : thematics = list(allThematics)
      elif id == 3 : thematics =  self.thematicInondations
      elif id == 4 : thematics =  self.thematicSubmersions      
      
      root = QgsProject.instance().layerTreeRoot()
      
      if root != None :
         for layerName in allThematics :
             layer = None
             try : layer = QgsProject.instance().mapLayersByName(layerName)[0]
             except : pass
             if layer :
                node = root.findLayer( layer.id())
                node.setItemVisibilityChecked(False)
                self.updateTreeLegendExpand(node, False, False)
             
         for layerName in thematics :
             layer = None
             try : layer = QgsProject.instance().mapLayersByName(layerName)[0]
             except : pass
             if layer :
                node = root.findLayer( layer.id())
                node.setItemVisibilityCheckedParentRecursive(True)
                node.setItemVisibilityChecked(True)
                self.updateTreeLegendExpand(node, False, True)

         self.initComboActiveLayer()       
                
  def updateTreeLegendExpand(self, node, isGroup, cond):
      node.setExpanded(cond)
      if not isGroup :
          if node.parent() : node.parent().setExpanded(cond)
          if node.parent().parent() : node.parent().parent().setExpanded(cond)      
      else :
          node.parent().setExpanded(cond)
          node.setExpanded(cond)
          for child in node.children(): child.setExpanded(cond)

          
  def updateCompleter(self):
        
         if not self.listForDataSearch : return
         key = self.listForDataSearch.currentText()
         #NEW 4.0.0   
         self.cleanSelection()

         self.listOfValues = []
         suggestions = []
         self.layer, self.column, self.suggestions = None, None, []
         
         if dicoHasKey(self.mappingData, key) :

             data = self.textForDataSearch.setText("")

             for layerName in self.mappingData[self.listForDataSearch.currentText()][0] :
                 layers = QgsProject.instance().mapLayersByName(layerName)
                 if layers != [] :
                    for layer in layers :
                       fields = [field.name() for field in layer.fields()]
                       
                       columns = self.mappingData[key][1]
                       for column in columns :
                           if column in fields :
                              self.layer, self.column = layer, column
                              for feature in layer.getFeatures():
                                  value = "%s" % feature[column]
                                  if not value in suggestions : suggestions.append(value)
                              self.suggestions = sorted(suggestions)
                              break     
                       break 

         model = self.textForDataSearch.completer.model()
         model.setStringList(self.suggestions)
         self.textForDataSearch.setCompleter(self.textForDataSearch.completer)
         self.updateButNextPrevious(-1)
           

  def clearSuggestions(self):
      model = self.textForDataSearch.completer.model()
      self.listOfValues = []
      model.setStringList(self.listOfValues)
  
  def resultSelected(self, result_index):
      try : self.textForDataSearch.setText(self.listOfValues[result_index.row()])
      except : pass


  def returnFilter(self, text):
      #NEW 4.0.0 suggestion.lower().startswith(text.lower()) ]
      return [suggestion for suggestion in self.suggestions if suggestion.lower().find(text.lower()) > -1 ]

  def getGroupRaster(self):
       try : layer = self.iface.activeLayer()
       except : return         
       root = QgsProject.instance().layerTreeRoot()
       listOrder = root.layerOrder()
       index = len(root.children())
       if self.nameGroupRaster == "" : self.nameGroupRaster = "Fond de plan"
       group = root.findGroup(self.nameGroupRaster)
       if not group :
          group = root.insertGroup(index, self.nameGroupRaster); expanded = True;
       return group

  def cleanGroupRaster(self):
      group = self.getGroupRaster()
      group.removeAllChildren()
    
  def getActionQgisZoomIn(self) : return self.iface.mainWindow().findChildren(QAction, "mActionZoomIn")[0]
  def getActionQgisZoomOut(self) : return self.iface.mainWindow().findChildren(QAction, "mActionZoomOut")[0]
  def getActionQgisPan(self) : return self.iface.mainWindow().findChildren(QAction, "mActionPan")[0]
  def getLegendQgisPanel(self) : return self.iface.mainWindow().findChildren(QDockWidget, "Layers")[0]
  def getActionQgisIdentifyObj(self) : return self.iface.mainWindow().findChildren(QAction, "mActionIdentify")[0]
  def getActionNew3DMapCanvas(self):  return self.iface.mainWindow().findChildren(QAction, "mActionNew3DMapCanvas")[0]

  def checkLayer(self):
      try : self.canvas.currentLayer().name()
      except : return False
      if self.canvas.currentLayer().name() != self.layerStations :
         mapLayer = QgsProject.instance().mapLayersByName(self.layerStations)
         if mapLayer : mapLayer = mapLayer[0]
         else : return False
         if mapLayer : self.canvas.setCurrentLayer(mapLayer) ; return True
         else : return False
      else : return True

      
  def extractDataFromWebService(self):
      button = self.iface.sender()
      if button in (self.buttonIdentifyWebH, self.buttonIdentifyWebD, self.buttonIdentifyWebStats): self.checkLayer()         
      if button == self.buttonIdentifyWebH  : action, icon = self.actionIdentifyWebH, "identifywebH_%s.png"
      elif button == self.buttonIdentifyWebD  : action, icon = self.actionIdentifyWebD, "identifywebD_%s.png"
      else : action, icon = self.actionIdentifyWebStats, "identifywebSTATS_%s.png"
      
      cond = (self.canvas.mapTool() == action)
      if not cond : self.canvas.setMapTool(action); self.resetActionIdentifyObj(); self.lastToolMap = self.canvas.mapTool(); 
      else : self.canvas.setMapTool(self.lastToolMap)
        
  def pan(self): self.canvas.setMapTool(self.toolPan); self.qgisActionPan.setChecked(True) ; self.resetActionIdentifyObj(); self.buttonPan.setStyleSheet("QPushButton {border-width: 5px; border-radius: 10px; border-color: black; background-color: #7eff00;}") ; self.lastToolMap = self.canvas.mapTool();
  def zoomIn(self): self.canvas.setMapTool(self.toolZoomIn); self.qgisActionZoomIn.setChecked(True) ; self.resetActionIdentifyObj(); self.buttonZoomIn.setStyleSheet("QPushButton {border-width: 5px; border-radius: 10px; border-color: black; background-color:  #7eff00;}") ; self.lastToolMap = self.canvas.mapTool();
  def zoomOut(self): self.canvas.setMapTool(self.toolZoomOut); self.qgisActionZoomOut.setChecked(True) ; self.resetActionIdentifyObj(); self.buttonZoomOut.setStyleSheet("QPushButton {border-width: 5px; border-radius: 10px; border-color: black; background-color:  #7eff00;}") ; self.lastToolMap = self.canvas.mapTool();
  def zoomAll(self):
      layers = QgsProject.instance().mapLayersByName(self.layerTerritoire)
      if layers : self.canvas.setExtent(layers[0].extent())
      else : self.canvas.zoomToFullExtent()
      self.canvas.refresh()

  def zoomPrevious(self): self.canvas.zoomToPreviousExtent() 
  def zoomNext(self): self.canvas.zoomToNextExtent()
  
  def fullScreen(self): self.iface.actionToggleFullScreen().triggered.emit() 

  def updateButNextPrevious(self, index):
      if index == -1 : self.previousData.setEnabled(False); self.nextData.setEnabled(False); return 
      self.previousData.setEnabled(index > 0)
      self.nextData.setEnabled(index < len(self.suggestions)-1)
        
  def goToData(self):
      index = self.suggestions.index(self.textForDataSearch.text())  
      if self.iface.sender() == self.previousData :
         if index > 0 : index+= -1
         else : return 
      else :
         if index < len(self.suggestions)-1 : index+= 1
         else : return
      self.textForDataSearch.setText(self.suggestions[index])
      self.updateButNextPrevious(index)
      self.zoomToData()


  def zoomToData(self):
      
      key = self.listForDataSearch.currentText()
      data = self.textForDataSearch.text()

      if key == "" or data == "" : return
      try :
          if not self.layer or not self.column : return
      except : return    

      index = self.comboActiveLayer.currentIndex()

      cond = (self.memoryLayer != None)
      self.killMemoryLayerFromProject()
               
      fields = [field.name() for field in self.layer.fields()]
      if self.column in fields :

         exp = QgsExpression(" \"{}\" = '{}' ".format(self.column, data.replace("'", "''")))
         request = QgsFeatureRequest(exp)

         self.layer.removeSelection()
         geomType = self.layer.geometryType()

         self.startMovie()
         geom = None
         ids = []
         for feat in self.layer.getFeatures(request):
              geomFeat = feat.geometry()
              if geom == None : geom = geomFeat
              else : geom = geom.combine(geomFeat)
              ids.append(feat.id())

         if geom :
            self.layer.selectByIds(ids) #select #NEW 4.0.0
            if geomType == 0 :
               bufferLayer = bufferPlus(input=self.layer.id(), distance=500, output=r'TEMPORARY_OUTPUT')
               for feature in bufferLayer["OUTPUT"].getFeatures(): 
                   geom = feature.geometry()
                   break
            elif geomType == 1 :
               bufferLayer = bufferPlus(input=self.layer.id(), distance=250, output=r'TEMPORARY_OUTPUT')
               for feature in bufferLayer["OUTPUT"].getFeatures(): 
                   geom = feature.geometry()
                   break
               
            rect = geom.boundingBox() 
            self.canvas.setExtent(rect)

            if self.iface.sender() == self.activeMaskData : self.getMaskForMemoryLayer(geom)
            if cond : self.getMaskForMemoryLayer(geom)
            
         #NEW 4.0.0
         self.comboActiveLayer.setCurrentIndex(index)
         try : self.setActiveLayer(self.comboActiveLayer.currentLayer())
         except : pass
         if self.lastToolMap : self.canvas.setMapTool(self.lastToolMap)

         #NEW 4.0.0
         self.layer.selectByIds(ids)

         self.canvas.refresh()
         self.stopMovie()

  #NEW 4.0.0
  def cleanSelection(self): self.iface.mainWindow().findChild(QAction, 'mActionDeselectAll').trigger()
  
               
  def resetFilterData(self):
      root = QgsProject.instance().layerTreeRoot()
      self.setWidgetsControls()
      
      if root != None :
         for layer in root.findLayers() :
             
             if (type(layer.layer()) == QgsRasterLayer or type(layer.layer()) == QgsVectorLayer) :
                   if type(layer.layer()) == QgsVectorLayer :
                      layer.layer().removeSelection(); layer.layer().setSubsetString (""); 
                   elif type(layer.layer()) == QgsRasterLayer : layer.setItemVisibilityChecked(True)

                   if self.layerTreeViewModel : self.layerTreeViewModel.refreshLayerLegend(layer)
                   if self.layerTreeViewWidget : self.layerTreeViewWidget.repaint()
                   
         if self.layerTreeViewModel : self.layerTreeViewModel.refreshLayerLegend(layer)
         if self.layerTreeViewWidget : self.layerTreeViewWidget.repaint()
 

  def getMaskForMemoryLayer(self, geom):
      
      crsAuthId = self.layer.crs().authid() if self.layer.crs().authid() else QgsProject.instance().crs()  
      
      self.memoryLayer = QgsVectorLayer("MultiPolygon?crs=%s" % crsAuthId, "tempo", "memory")
      if exists(self.styleQml) : self.memoryLayer.loadNamedStyle(self.styleQml, True)
      provider = self.memoryLayer.dataProvider()
      self.memoryLayer.startEditing()
      
      fields = QgsFields()
      fields.append(QgsField("id", QVariant.LongLong, "integer", 12))
      provider.addAttributes(fields)

      feature = QgsFeature()
      feature.setGeometry(geom)
      feature.setAttributes([0])

      provider.addFeatures([ feature ] )
      self.memoryLayer.updateExtents()

      self.memoryLayer.commitChanges()

      root = QgsProject.instance().layerTreeRoot()
      QgsProject.instance().addMapLayers([self.memoryLayer], True)

      myExistingLayer = root.findLayer(self.memoryLayer.id())
      myClone = myExistingLayer.clone()
      root.insertChildNode(0, myClone)
      parent = myExistingLayer.parent()
      parent.removeChildNode(myExistingLayer)

      self.canvas.refresh()
      #NEW 4.0.0  
      try :
          self.deleteMaskData.setEnabled(self.memoryLayer != None)
          self.activeMaskData.setEnabled(self.memoryLayer == None)
      except : pass


  def killMemoryLayerFromProject(self):
      try :
         if self.memoryLayer :
            QgsProject.instance().removeMapLayers([self.memoryLayer.id()])
            self.canvas.refresh()
      except : pass
      self.memoryLayer = None
      try :
          self.deleteMaskData.setEnabled(self.memoryLayer != None)
          self.activeMaskData.setEnabled(self.memoryLayer == None)
      except : pass

      
  def checkForAutoLoaderRaster(self):    
        isAutoLoaderRasterPlugin, autoLoaderRasterPlugin, autoLoaderRasterPluginActionUpdateLive, autoLoaderRasterPluginActionCheckVisibility = False, None, None, None
        
        try :
                 from autoLoaderRaster.autoLoaderRaster import autoLoaderRasterPlugin as toto
                 isAutoLoaderRasterPlugin = True
                 autoLoaderRasterPluginActionUpdateLive = self.iface.mainWindow().findChild(QAction, "mActionUpdateLive")
                 autoLoaderRasterPluginActionCheckVisibility = self.iface.mainWindow().findChild(QAction, "mActionCheckVisibility")
        except : pass
        
        return isAutoLoaderRasterPlugin, autoLoaderRasterPlugin, autoLoaderRasterPluginActionUpdateLive, autoLoaderRasterPluginActionCheckVisibility    


  def initLayerBackGround(self):
      groupRaster = self.getGroupRaster()
      if not groupRaster : return

      nameLayer = ""  
      for child in groupRaster.children():
          nameLayer = child.name()
          break

      self.listLayersRaster.setToolTip("Fond de plan : %s" %  nameLayer)
      self.canvas.blockSignals(True)
      self.setUpdateComboActiveLayer()
      self.canvas.blockSignals(False)
     

  def beforeUpdateBackLayerRaster(self, fromALR) :
      groupRaster = self.getGroupRaster() 
      if not groupRaster : return False, None

      s = QSettings() 
      s.setValue("Plugin-autoLoaderRasterPlugin/grpRdi", "")
      isAutoLoaderRasterPlugin, autoLoaderRasterPlugin, autoLoaderRasterPluginActionUpdateLive, autoLoaderRasterPluginActionCheckVisibility = self.checkForAutoLoaderRaster()
      if not fromALR :
          if isAutoLoaderRasterPlugin :
             autoLoaderRasterPluginActionUpdateLive.setChecked(False)
             autoLoaderRasterPluginActionCheckVisibility.setChecked(False)
             autoLoaderRasterPluginActionCheckVisibility.triggered.emit()
             autoLoaderRasterPluginActionUpdateLive.triggered.emit()

      self.barInfo.clearWidgets()
      self.cleanGroupRaster()
      return True, groupRaster
      
  def noBackLayerRaster(self):
      isClean, groupRaster = self.beforeUpdateBackLayerRaster(False)
      if isClean :
          self.barInfo.pushMessage("Information :", "Aucun fond de plan.", Qgis.Info, 3)
          self.canvas.refresh()

  def updateBackRasterLayerWithWMS(self): 
      isClean, groupRaster = self.beforeUpdateBackLayerRaster(False)

      if isClean :

          nameLayer = self.iface.sender().text()
          urlWms = self.iface.sender().data()
          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)

          self.listLayersRaster.setToolTip("Fond de plan : %s - %s" %  (self.iface.sender().parent().title(), nameLayer))

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

          self.canvas.refresh()
          
         
  def updateBackRasterLayerWithLocalFiles(self): 
      isClean, groupRaster = self.beforeUpdateBackLayerRaster(False)

      if isClean :
         fileName = self.iface.sender().data()
         if exists(fileName):
            inputFile = QFileInfo(fileName) 
            extension = inputFile.suffix().lower()
            nameLayer = basename(fileName).split(".")[0]

            rasterLayer = QgsRasterLayer(fileName, nameLayer, "gdal")
            QgsProject.instance().addMapLayer(rasterLayer, False)
            nodeLayer = QgsLayerTreeLayer(rasterLayer)
            groupRaster.insertChildNode(0, nodeLayer)            

            self.barInfo.pushMessage("Information :", "Fichier %s en Fond de plan." % nameLayer, Qgis.Info, 3)
            self.listLayersRaster.setToolTip("Fond de plan : %s" %  nameLayer)
            self.canvas.refresh()

      
  def updateBackRasterLayerWithALR(self):
      isClean, groupRaster = self.beforeUpdateBackLayerRaster(True)

      if isClean :
          isAutoLoaderRasterPlugin, autoLoaderRasterPlugin, autoLoaderRasterPluginActionUpdateLive, autoLoaderRasterPluginActionCheckVisibility = self.checkForAutoLoaderRaster()
                 
          if isAutoLoaderRasterPlugin :
             s = QSettings() 
             s.setValue("Plugin-autoLoaderRasterPlugin/grpRdi", groupRaster.name())

             nameLayer = "Gestion du fond de plan par AutoLoaderRaster."
             self.barInfo.pushMessage("Information :", nameLayer, Qgis.Info, 3)
             autoLoaderRasterPluginActionUpdateLive.setChecked(True)
             autoLoaderRasterPluginActionCheckVisibility.setChecked(True)
             autoLoaderRasterPluginActionCheckVisibility.triggered.emit()
             autoLoaderRasterPluginActionUpdateLive.triggered.emit()

             self.listLayersRaster.setToolTip("Fond de plan : %s" %  nameLayer)


  def getTransformer(self, sourceCrs, targetCrs):
      transformer = QgsCoordinateTransform()
      transformer.setSourceCrs(sourceCrs)
      transformer.setDestinationCrs(targetCrs)
      return transformer    

  def goToWebPage(self):
      if not self.transformer : return  
      url = self.iface.sender().whatsThis()
      mapScale = self.canvas.scale()
          
      if type(url) != str : url = url.toString()
      if url.startswith("addons.") : url = url.replace("addons.", "")
       
      if url.find("[LAT]") != -1 :
         centerMap = self.canvas.center()
         wgsCenter = self.transformer.transform(centerMap,  QgsCoordinateTransform.ForwardTransform)
         url = url.replace("[LAT]", "%s" % wgsCenter.y())
         url = url.replace("[LONG]", "%s" % wgsCenter.x())

      if url.find("[DYNAMAP]") != -1 :
         if mapScale > 100000 : indice = "8"
         else :
              indice = "16" if mapScale < 20000 else "12"
         url = url.replace("[DYNAMAP]", indice)
        
      try : webbrowseropen(url)
      except : pass


  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):
      if not contextMenu : contextMenu = QMenu(); cond = False
      else : cond = True
      
      if exists(fileName):

           if not self.parseFile(fileName) :
               msg = "Fichier XML invalide"
               msgErr = "Racine RDI introuvable"
               self.barInfo.pushMessage("Attention :", "%s :<br>%s." % (msg, msgErr), Qgis.Warning, 3)
               return
            
           error = 0
           try:
               doc = etree.parse(fileName).getroot()
               if not doc.tag in ('RDI', 'rdiPlugin', 'rdigcPlugin') :
                  error, msg, msgErr = 1, "Fichier XML invalide", "Racine RDI introuvable"
           except (etree.ParseError, error):
               error, msg = 1, "Impossible de parser le fichier XML"
           except (IOError, error):
               error, msg = 1, "Impossible d'ouvrir le fichier XML"

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

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

           i = 0
           groupData = ""
           version = int(doc.attrib.get('version').split('.')[0])

           if version >= 3 :
               
               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)

                      data = []
                      try : data = gridraster.getchildren()
                      except : data = gridraster.findall('data')
                      
                      for child in data : 
                          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)
                          action.triggered.connect(self.updateBackRasterLayerWithWMS) if cond else action.triggered.connect(self.goToWebPage)                             
                          setattr(self, text, action)

                   contextMenu.addSeparator()
                   if cond :
                      actionGroupData.setDefaultWidget(button)            
                      contextMenu.addAction(actionGroupData)
                      subMenu.setStyle(self.style)
                      button.setMenu(subMenu)
                   
           else :    
               for gridraster in doc.findall('data'):
                   key = gridraster.attrib.get('uri')
                   if groupData != gridraster.attrib.get('groupData') :
                      if groupData != "" : contextMenu.addSeparator()
                      groupData = gridraster.attrib.get('groupData')   
                   
                   test = exists(key) if isLocal else True
                   if test :
                      if isLocal :
                         sourceFile = QFileInfo(key)
                         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")
                      action = QAction(QIcon(iconRessource), '{:<45}'.format(text), contextMenu)
                      action.setWhatsThis(key)
                      contextMenu.addAction(action)                      
                      action.triggered.connect(self.updateBackRasterLayerWithWMS) if cond else action.triggered.connect(self.goToWebPage)
                      setattr(self, text, action)

      return contextMenu

    
  def getAbout(self): 
      changeButtonIcon(self, self.actionAboutRdi,"about_on.png")
      self.dialogAbout = ui_About(self); self.dialogAbout.exec_()
      changeButtonIcon(self, self.actionAboutRdi,"about_off.png")
    
  def unload(self):
      self.index = 0
      
      s = QSettings() 
      s.setValue("Plugin-autoLoaderRasterPlugin/grpRdi", "")
      self.killMemoryLayerFromProject()
      
      folder = join(dirname(__file__),"data/temp/").replace("\\", "/")
      self.deleteImagesInFolder(folder)

      if self.actionToggleMapOnly : self.actionToggleMapOnly.setShortcut(QKeySequence("Ctrl+Shift+Tab"))

      #NEW 4.0.0
      widgetsRdi = (self.widgetToolBarViewer, self.logConsole, self.widgetMainToolBar, self.widgetToolBarNav, self.widgetToolBarIdentify,
                    self.widgetToolBarIdentifyData, self.widgetLegendsBar, self.widgetRisquesEnjeux, self.vKeyboard, self.actionAddWmsLayer,
                    self.NorthArrow, self.identifyResultsDock, self.dialogReportingStations)
      
      for widget in widgetsRdi :
          if widget :
             try : widget.close(); widget = None;
             except : pass

def initSizeToolBar(toolBar, x, y, width, height):
    toolBar.setMinimumWidth(width)
    toolBar.setMaximumWidth(width)
    toolBar.setMinimumHeight(height)
    toolBar.setMaximumHeight(height)
    toolBar.setGeometry(x, y, width, height)

def actionsWindows(parent, name, title, width, height):
        self = QMdiSubWindow(parent)
        self.setObjectName(name)
        self.setWindowTitle(title)

        if name == "widgettoolmainbar" :
           self.setWindowFlags(Qt.Window | Qt.CustomizeWindowHint | Qt.FramelessWindowHint  | Qt.WindowStaysOnTopHint)
           self.setStyleSheet("QMdiSubWindow {background-color: rgba(255, 255, 255, 50)}")
        else :
           self.setWindowFlags(Qt.WindowTitleHint | Qt.WindowStaysOnTopHint)
           self.setStyleSheet("QMdiSubWindow { border: 1px solid;  border-radius: 5px;  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.setGeometry(10, 10, width, height)
        self.oldPos = self.pos()

        return self

#NEW 4.0.0 buttonServiceImpacts
def contextMnus(self, obj): 

      contextMnu = QMenu()
      contextMnu.setStyleSheet("""
         QMenu { border: 1px solid; border-radius: 5px;   background-color: rgba(255, 255, 255, 210);}
         QMenu::item { background-color: transparent; border:1px;}
      """)

      if obj.objectName() == "actionToolPrint" :
         dicoCtrls = {"buttonSaveMapAsImage" : ("savemap.png", "Sauvegarder une image de la carte", 10, 25),
                       "buttonPrinterMap" : ("printermap_off.png", "Imprimer la carte", 45, 25),
                       "buttonPrinterData" : ("printerdata_off.png", "Imprimer les informations", 80, 25) #115
                      } 
      elif obj.objectName() == "actionToolsAdvanced" :
         dicoCtrls = {"buttonGetWMS" : ("addwms_off.png", "Ajouter une couche WMS", 10, 25), 
                      "buttonServiceImpacts" : ("stationimpacth_off.png", "Analyse d'impact (hauteur)", 45, 25),
                      "buttonProfilTool" : ("profiletool_off.png", "Activer l'outil profils en long", 80, 25),
                      "button3d" : ("stats.png", "Ouvrir une vue 3D", 115, 25),
                      "buttonParams" : ("parametres_off.png", "Paramétrage de %s ..." % self.namePlugin, 150, 25)
                      }  

      elif obj.objectName() == "actionToolHelpDoc" :
         dicoCtrls = {"localInfos" : ("dico.png", "Informations locales ...", 10, 25),
                      "webInfos" : ("lienweb.png", "Accèder aux liens web ...", 45, 25),
                      "actionManualRdi" : ("manual.png", "Documentation pour %s ..." % self.namePlugin, 80, 25),
                      "actionAboutRdi" : ("about_off.png", "A propos de %s ..." % self.namePlugin, 115, 25)
                      }
 
      height = 0  
      for key in dicoCtrls :
          
          icon = getThemeIcon(dicoCtrls[key][0])  
          text = QApplication.translate("rdigc", dicoCtrls[key][1])
           
          button = QPushButton(contextMnu) if key != "button3d" else QToolButton(contextMnu)
          button.setFixedSize(48,48)
          objType = "QPushButton" if key != "button3d" else "QToolButton"
          button.setStyleSheet("""%s { border: none;  }
                                  %s:hover {background-color: #7eff00;}""" % (objType, objType))
          if key == "actionManualRdi" : button.setWhatsThis("%s/documentation" % dirname(__file__))
          button.setToolTip(text)
          button.setIconSize(QSize(32, 32))
          button.setIcon(QIcon(icon))

          if   key == "buttonSaveMapAsImage" :  button.clicked.connect(self.saveMapAsImage)
          elif key == "buttonPrinterMap" :  button.clicked.connect(self.getPrintMap)
          elif key == "buttonPrinterData" :
               button.setEnabled(False)
               button.clicked.connect(self.getPrintInformations)
          #NEW 4.0.0
          elif key == "buttonServiceImpacts" : button.clicked.connect(self.getIhmImpacts)     
          elif key == "buttonGetWMS" :
               if not self.actionAddWmsLayer : self.actionAddWmsLayer = self.iface.actionAddWmsLayer()
               button.clicked.connect(self.addWmsLayer)
          elif key == "buttonProfilTool" :  button.clicked.connect(self.showProfilTool)
          elif key == "button3d" :
               self.actionNew3DMapCanvas = self.getActionNew3DMapCanvas()
               button.setDefaultAction(self.actionNew3DMapCanvas)
          elif key == "buttonParams" : button.clicked.connect(self.getParamsRdi)
          elif key == "localInfos" :  button.setMenu(self.menuLocalInfos)
          elif key == "webInfos" :  button.setMenu(self.menuWebInfos)
          elif key == "actionManualRdi" :  button.clicked.connect(self.goToWebPage) 
          elif key == "actionAboutRdi" :  button.clicked.connect(self.getAbout)                    
          
          action = QWidgetAction(contextMnu) 
          action.setDefaultWidget(button)
          action.setObjectName(key)
          contextMnu.addAction(action)
          setattr(self, key, button)
          height+= 49

      setObjSizes(contextMnu, 50, height)
      obj.setMenu(contextMnu)

    

def ctrlMap(self, conteneur, complete, getPointsForExtent, simply, iX, iY, iW, iH):
         #NEW 4.0.0
         self.groupMap = QFrame(conteneur)
         self.groupMap.setStyleSheet("QFrame:active {color: #FFFFCC; border-width: 0px;}")

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

         if conteneur ==  self.widgetMainToolBar :  
             dicoCtrls = {"actionFullScreen" : ("fullscreen_off.png", "Activer / Quitter le mode plein écran", 7, 30),
                          "actionToolBarNav" : ("navigation_off.png", "Outils de navigation", 7, 65),
                          "actionToolIdentify" : ("datasearch_off.png", "Outils d'interrogation", 7, 100),
                          "buttonFullStations" : ("bulletin_off.png", "Bulletin des stations ...", 7, 135), 
                          "actionToolPrint"  : ("printer_off.png", "Imprimer ...", 7, 170),
                          "actionToolsAdvanced" : ("tools_off.png", "Outils avancés", 7, 205),
                          "actionToolHelpDoc" : ("helpdoc_off.png", "Informations (ressources locales, liens web, A propos ...)", 7, 240)                        
                          }

         elif conteneur == self.widgetToolBarNav :   
             dicoCtrls = {"buttonZoomAll" : ("zoomall.png", "Zoomer sur la couche territoire", 10, 25),
                          "buttonPan" : ("pan.png", "Se déplacer dans la carte", 45, 25),
                          "buttonZoomIn" : ("zoomin.png", "Zoomer dans la carte", 80, 25),
                          "buttonZoomOut" : ("zoomout.png", "DéZoomer dans la carte", 115, 25),
                          "buttonZoomPrevious" : ("zoomprev.png", "Zoom précédent", 150, 25),
                          "buttonZoomNext" : ("zoomnext.png", "Zoom suivant", 185, 25),
                          "buttonIdentifyData" : ("identifydata_off.png", "Outils de recherche par la donnée", 220, 25)                          
                          }

         elif conteneur == self.widgetToolBarIdentify :
             dicoCtrls = {
                          "comboActiveLayer"   : (None, "Définir la couche active", 10, 25),
                          "buttonIdentify"     : ("identifyobj_off.png", "Interroger les entités de la couche sélectionnée...", 210, 25),
                          "optionsIdentify"    : ("actions.png", "Liste des modes d'interrogation", 245, 25)
                          }

        #NEW 4.0.0
         pos = 10 
         sizeIcon = 32 
       
         for key in dicoCtrls :
      
                   icon = getThemeIcon(dicoCtrls[key][0])
                   toolTip = QApplication.translate("rdigc", dicoCtrls[key][1])
                   if not key in ("actionFullScreen",  "listLayersRaster", "buttonGetWMS", "button3d", "buttonParams", "comboActiveLayer", "labelActiveRaster") : button = myPushButton(self.groupMap)
                   elif key == "labelActiveRaster" : button = QLabel(self.groupMap)   
                   elif key == "comboActiveLayer" : button = QgsMapLayerComboBox(self.groupMap)
                   else : button = QToolButton(self.groupMap)                   
                   
                   if not key in("actionFullScreen", "listLayersRaster", "buttonGetWMS", "button3d", "buttonParams", "comboActiveLayer", "labelActiveRaster") :
                      #NEW 4.0.0
                      #if not conteneur in (self.widgetMainToolBar, self.toolBarWidgetStaticLegend) :  button.initPushButton(sizeIcon, sizeIcon, pos, dicoCtrls[key][3], key, "", toolTip, True, icon, sizeIcon, sizeIcon, True)   
                      if not conteneur == self.widgetMainToolBar :  button.initPushButton(sizeIcon, sizeIcon, pos, dicoCtrls[key][3], key, "", toolTip, True, icon, sizeIcon, sizeIcon, True)  
                      else :
                            button.initPushButton(sizeIcon, sizeIcon, dicoCtrls[key][2], pos, key, "", toolTip, True, icon, sizeIcon, sizeIcon, True)
                            if key in ("actionToolPrint", "actionToolsAdvanced", "actionToolHelpDoc") :
                               contextMnus(self, button)
                               button.setStyleSheet("""
                                                QPushButton {icon-size:32px; border-width: 5px; border-radius: 5px; border-color: black; }
                                                QPushButton:hover {background-color: #7eff00;}
                                                """)

                      if  key in ("buttonZoomInImage", "buttonZoomOutImage"): button.setAutoRepeat(True)


                   elif key == "comboActiveLayer" :
                        button.setObjectName(key)
                        button.setEditable(False)
                        button.setEnabled(True)
                        button.setFilters(QgsMapLayerProxyModel.All) #QgsMapLayerProxyModel.VectorLayer
                        #button.setExceptedLayerList(self.noVisibleLayers)

                        button.setExcludedProviders(['WMS'])                        
                        button.setAllowEmptyLayer(False) 
                        button.model().sortOrder()
                        button.setStyleSheet(self.styleMapLayerComboBox)
                        button.setToolTip("Liste des couches interrogeables")
                        button.setGeometry(10, 25, 200, 30)
                        setObjSizes(button, 200, 30)

                        delegate = CustomStyleDelegate(button)
                        button.setItemDelegate(delegate)
                       
                        pos+= 160


                   elif key == "labelActiveRaster" :
                        button.setGeometry(pos, 25, 32, 32)
                        setObjSizes(button, 32, 32)
                        button.setToolTip(QApplication.translate("rdigc", dicoCtrls[key][1]))

                        image = QImage(getThemeIcon(dicoCtrls[key][0]))
                        button.setPixmap(QPixmap.fromImage(image))
                        
                   else :
                      setObjSizes(button, sizeIcon, sizeIcon)
                      button.setIcon(QIcon(icon))
                      button.setIconSize(QSize(sizeIcon, sizeIcon))
                      #NEW 4.0.0
                      button.setGeometry(pos, dicoCtrls[key][3], sizeIcon, sizeIcon)  if not conteneur == self.widgetMainToolBar else button.setGeometry(dicoCtrls[key][2], pos, sizeIcon, sizeIcon)
                      button.setToolTip(toolTip)
                      styleSheetPushButton = "QToolButton::checked {icon-size: %spx, %spx; border-width: 5px; border-radius: 10px; border-color: black; background-color: #FFFFCC;}" % (sizeIcon, sizeIcon)
                      styleSheetPushButton+= "QToolButton {icon-size:  %spx, %spx; border-width: 0px; border-radius: 10px; }" % (sizeIcon, sizeIcon)
                      button.setStyleSheet(styleSheetPushButton)
                      button.setText("")

                   if key in ("buttonZoomIn", "buttonZoomOut", "buttonPan", "buttonIdentify"):
                      styleSheetPushButton = "QPushButton::checked {icon-size:  %spx, %spx; border-width: 1px; border-radius: 5px; border-color: black; background-color: #7eff00;}" % (sizeIcon, sizeIcon)
                      styleSheetPushButton+= "QPushButton {icon-size:  %spx, %spx; border-width: 0px; border-radius: 10px; background: transparent; }" % (sizeIcon, sizeIcon)
                      button.setStyleSheet(styleSheetPushButton)
                      button.setCheckable(True)

                      if key == "buttonPan" : button.setChecked(True)
                     
                      index = ("buttonIdentify", "buttonZoomIn", "buttonZoomOut", "buttonPan", "buttonToolTip", "buttonHotlink").index(key)
                      self.actionsMapCanvas.addButton(button, index)
                      
                   setattr(self, key, button)
                   #NEW 4.0.0
                   if key == "comboActiveLayer" : self.updateVisibleLayersInComboActiveLayer()
                                         
                   pos+= 50 

         #NEW 4.0.0
         sizeWidth = len(self.groupMap.children())*50 #if conteneur!= self.toolBarWidgetStaticLegend else len(self.groupMap.children())*30
         #NEW 4.0.0
         if not conteneur in (self.widgetMainToolBar, self.widgetLegendsBar, self.widgetToolBarIdentify) :  self.groupMap.setGeometry(5, 0, sizeWidth+20, 60)
         else :
            if conteneur == self.widgetToolBarIdentify : sizeWidth+= 150; self.groupMap.setGeometry(5, 0, sizeWidth+20, 60)
            elif conteneur == self.widgetLegendsBar : sizeWidth+= 250; self.groupMap.setGeometry(5, 0, sizeWidth+20, 60); 
            else : self.groupMap.setGeometry(0, 0, 55, sizeWidth+20)
          
         return sizeWidth


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


class getDataMeteoFromWebServices(QgsMapToolIdentify):
    
        def __init__(self, iface, parent, canvas):
            QgsMapToolIdentify.__init__(self, canvas)
            self.iface = iface
            self.parent = parent
            self.canvas = canvas
            self.oldMapTool = self.canvas.mapTool()
            self.setCursor(QCursor(QPixmap(getThemeIcon("toolhotlinkmeteo.png"))))


        def deactivate(self): self.parent.listTargetMeteo.setCurrentIndex(0)
        def activate(self):
            self.namePlugin = self.parent.namePlugin
            self.timezone = self.parent.timezone
            self.transformer = self.parent.transformer
            self.setCursor(QCursor(QPixmap(getThemeIcon("toolhotlinkmeteo.png" ))))
            self.parent.setUpdateTool()
  

        def setOldMapTool(self, oldMapTool) : self.oldMapTool = oldMapTool   

        def canvasReleaseEvent(self, event):
            if not event.button() == Qt.LeftButton: return
            if not self.parent.checkLayer() : return

            pointScreen = QPoint(event.x(),event.y())
            point = self.canvas.getCoordinateTransform().toMapCoordinates(pointScreen)

            answerAsText = self.parent.getContent(point)
            if answerAsText != {} : self.parent.setAnnotationMeteo(point, answerAsText, QgsProject().instance(), None, "Point [%s - %s]" % (round(point.x(), 2), round(point.y(), 2)), 2)

         
class getDataFromWebServices(QgsMapToolIdentify):   

        def __init__(self, iface, parent, canvas, typeInfos):
            QgsMapToolIdentify.__init__(self, canvas)
            self.iface = iface
            self.parent = parent
            self.canvas = canvas
            self.typeInfos = typeInfos            
            self.tableValuesStations = {}
            self.setCursor(QCursor(QPixmap(getThemeIcon("toolhotlink%s.png" % typeInfos.lower()))))

            self.manager = QNetworkAccessManager(self)

            self.parent.checkLayer()
           
        def activate(self):
            self.namePlugin = self.parent.namePlugin
            self.timezone = self.parent.timezone
            self.titleService = self.parent.titleService
            self.fileLogoLeft = self.parent.fileLogoLeft
            self.fileLogoRight = self.parent.fileLogoRight
            self.tableFieldsStations = self.parent.tableFieldsStations
            self.path = self.parent.pathImgStations
            self.setCursor(QCursor(QPixmap(getThemeIcon("toolhotlink%s.png" % self.typeInfos.lower()))))
            

        def getIdAndLabel(self):
            if self.tableFieldsStations == {} : return None, None
            try :
                idStationField = self.tableFieldsStations["CdStationH"]
                lblStationField = self.tableFieldsStations["LbStationH"]
                return idStationField, lblStationField
            except : return None, None
            

        def canvasMoveEvent(self, event):
            results = self.identify(event.x(),event.y(), QgsMapToolIdentify.TopDownStopAtFirst, [self.canvas.currentLayer()], QgsMapToolIdentify.VectorLayer)
            self.canvas.currentLayer().removeSelection()
            if results :               
               idStationField, lblStationField = self.getIdAndLabel()
               if not idStationField : return

               img = results[0].mFeature[idStationField] #1
               if not exists("%s/%s.jpg" % (self.path, img)) : img = "noimg"
               
               self.canvas.currentLayer().selectByIds([results[0].mFeature.id()])
               
               expression = "Station : <u>%s</u><br><b>%s</b><br><img src='file:///%s/%s.jpg'>" % (results[0].mFeature[idStationField], results[0].mFeature[lblStationField], self.path, img)
               QToolTip.showText( self.canvas.mapToGlobal( self.canvas.mouseLastXY() ), expression, self.canvas )

            else : self.canvas.currentLayer().removeSelection() 

        def readContent(self):
            answerAsText = None  
            answerAsText = bytes(self.replyObject.readAll()).decode("utf-8")
            self.parent.stopMovie()
            if not answerAsText : return

            denum = 1000
            img = "%s/%s.jpg" % (self.path, self.idStation)
            json_data = json.loads(answerAsText)

            lblTypeInfos = "H" if self.typeInfos == "H" else "D"            
            dicoSeuils = None
            stationDicoSeuils = {}
            try : dicoSeuils = ast.literal_eval(self.seuilsStation)
            except : pass
            if dicoSeuils :
                 i = 1
                 for key in dicoSeuils.keys() :
                     if key == "S%s%s" % (lblTypeInfos, i) :
                        valueSeuil = dicoSeuils[key]
                        if valueSeuil > -1 :
                           nKey = key.replace(lblTypeInfos, "")
                           nKeyDico = 'S3' if i > 3 else nKey
                           stationDicoSeuils[nKey] = { "valueSeuil" : valueSeuil, "commentsSeuilRDI" : COMMENTSSEUILRDI[nKeyDico]} 
                           
                        i+= 1   


            if dicoHasKey(json_data, "data") :
                  mesures = json_data["data"]
                  if mesures :
                        case = 0 if "resultat_obs" in mesures[0].keys() else  1
                        date_obs, resultat_obs, firstDate = [], [], False

                        if case == 0 :
                              theLastDate, minY, maxY = "", 1000000000.0, 0.0
                              for mesure in mesures :
                                  data = mesure["resultat_obs"]/denum  
                                  resultat_obs.append(data)
                                  if data > maxY : maxY = data
                                  if data < minY : minY = data
                                  if not firstDate : theLastDate = jsonDateToStrDate(mesure["date_obs"],"", " ", self.timezone) ; firstDate = True 
                                  date_obs.append(jsonToMatplotlibDate(mesure["date_obs"], self.timezone))
                              self.title = "%s\n[du %s au %s]" % (self.title, jsonDateToStrDate(mesure["date_obs"],"", " ", self.timezone), theLastDate)                              
                        else :
                              for mesure in mesures :
                                  resultat_obs.append(mesure["resultat"])
                                  if not firstDate : self.title = "%s\n[du %s" % (self.title, jsonDateToStrDate(mesure["date_prelevement"], "", " ", self.timezone)); firstDate = True
                                  date_obs.append(jsonToMatplotlibDate(mesure["date_prelevement"], self.timezone))
                              self.title = "%s au %s]" % (self.title, jsonDateToStrDate(mesure["date_prelevement"], "", " ", self.timezone))

                        average = getMean(resultat_obs, 3)
                        ecartType = getStDev(resultat_obs, 3)
                        
                              
                        if case == 0 : self.dlgStats = windowPlotStatsAndGraphs(self, "https://hubeau.eaufrance.fr", "linechart0", resultat_obs, date_obs, self.title, img, minY, maxY, self.typeInfos, self.idHydro, self.lbStation, self.idStation, self.parent.pathLocalFolderStations, self.timezone, self.titleService, average, ecartType, None, None, stationDicoSeuils) #TEMPO INCLURE INFOS SEUILS 
                        else : self.dlgStats = windowPlotStatsAndGraphs(self, "https://hubeau.eaufrance.fr", "linechart1", resultat_obs, date_obs, self.title, img, 0, 0, self.typeInfos, self.idHydro, self.lbStation, self.idStation, self.parent.pathLocalFolderStations, self.timezone, self.titleService, average, ecartType, None, None, stationDicoSeuils)  #TEMPO INCLURE INFOS SEUILS
                        
                        self.dlgStats.show()         

                  else :
                        msgDlgBox = myMsgDlgBox(self, QMessageBox.Information, "%s, résultat de la requête ..." % self.parent.namePlugin,
                                          "<center><br><img src='%s'><br><b><u>%s</u></b><br>Pas de service HubEau...<b>%s</b>.</center>" % (img, self.title, mesures), "rdistop.png", "inondation.png", 1, None, self)
                        msgDlgBox.toolbar = linkedToolBar(self, msgDlgBox, self.lbStation, self.idStation, self.typeInfos, self.idHydro, 2, 45, True, self.parent.pathLocalFolderStations) 
                        msgDlgBox.exec_()

            else : 
                   msgDlgBox = myMsgDlgBox(self, QMessageBox.Information, "%s, résultat de la requête ..." % self.parent.namePlugin,
                                          "<center><img src='%s'><br><b><u>%s</u></b><br>Erreur de clef pour le service...<b>%s</b>.</center>" % (img, self.title, json_data), "rdistop.png", "inondation.png", 1, None, self)
                   msgDlgBox.exec_()


        def openUrl(self):
              url = self.sender().whatsThis()
              try : webbrowseropen(url)
              except : pass
            
        def canvasReleaseEvent(self, event):
            if not event.button() == Qt.LeftButton: return
            if not self.parent.checkLayer() : return            
            if self.tableFieldsStations == {} : return

            self.parent.startMovie()
 
            results = self.identify(event.x(),event.y(), QgsMapToolIdentify.TopDownStopAtFirst, [self.canvas.currentLayer()], QgsMapToolIdentify.VectorLayer)
            self.canvas.currentLayer().removeSelection()

            self.idStation, self.lbStation, self.codeCommune, self.idHydro, self.seuilsStation = None, None, None, None, None

            if results :                
                  
                mapLayer = results[0].mLayer
                idObj = results[0].mFeature.id()
                fieldsNames = mapLayer.fields().names()
                mapfieldsNames = map(lambda x:x.upper(), fieldsNames)
                self.canvas.currentLayer().select(idObj)

                for key, value in self.tableFieldsStations.items():
                    #NEW 4.0.0
                    if key != "FILTERWITH" :
                        if not value.upper() in mapfieldsNames :
                           self.parent.barInfo.pushMessage("Avertissment :", "Attribut [%s] non trouvé !" % key, Qgis.Warning, 3)
                           return
                        else :
                           index = fieldsNames.index(value)
                           self.tableValuesStations[key] = results[0].mFeature[index]


                self.idStation = self.tableValuesStations["CdStationH"]
                self.lbStation = self.tableValuesStations["LbStationH"]
                self.idHydro = self.tableValuesStations["CdAncieRef"]
                self.seuilsStation = self.tableValuesStations["SEUIL_RDI"]


                if self.typeInfos != "STATS" :

                    if type(self.idHydro) == QVariant : self.idHydro = "%s" % self.idStation
                    self.title = "Station %s : %s" % (self.idStation, self.lbStation)                    

                    #hauteurs d'eau (H) et débit (Q) ou les deux H,Q : 1 enregistrement sur 2 -> H et l'autre pour Q - dépend des capacités de la station
                    url = APIHUBEAU % (self.idStation, self.typeInfos, 2000) 
                    self.replyObject = None
                    self.replyObject = self.manager.get(QNetworkRequest(QUrl(url)))
                    self.replyObject.finished.connect(self.readContent)

                else :
                    url = APIHUBEAUMONTHLY % self.idStation 
                    try : webbrowseropen(url)
                    except : pass                    

                self.canvas.currentLayer().removeSelection()

            self.parent.stopMovie()      
