from qgis.PyQt.QtCore import (QCoreApplication, QFile, QObject, QRegExp, QSize, Qt)
from qgis.PyQt.QtGui import (QIcon, QKeySequence, QStandardItem)
from qgis.PyQt.QtWidgets import (QAbstractItemView, QAction, QApplication, QButtonGroup, QCheckBox, QComboBox, QDialog, QFileDialog, QFrame, QGroupBox, QInputDialog,
                                 QLabel, QLineEdit, QListView, QListWidget, QMenu, QMessageBox, QPushButton, QProgressBar, QProxyStyle, QStyle, QTextEdit, QToolBar,
                                 QTreeWidget, QTreeWidgetItem, QVBoxLayout)
from qgis.PyQt.QtPrintSupport import (QPrintPreviewDialog, QPrinter)
from qgis.core import (Qgis, QgsApplication, QgsLayerTree, QgsLayerTreeGroup, QgsProject, QgsRasterLayer)
from os.path import (basename, dirname, exists, isfile, join, splitext)
from sys import path as sysPath
from xml.dom.minidom import parseString

#NEW 3.4.0
from ast import literal_eval
from webbrowser import open as webbrowseropen
from urllib.parse import urlparse
from urllib.parse import parse_qs

from qgis.core import (QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsLayerTreeLayer, QgsLayerTreeNode)

try:
    from osgeo.gdal import Open as gdalopen
    from osgeo.gdal import GetDriver as gdal_GetDriver
    from osgeo.gdal import GetDriverCount as gdal_GetDriverCount
    from osgeo.gdal import GetDriverByName as gdal_GetDriverByName
    from osgeo.gdal import (DMD_LONGNAME, DMD_MIMETYPE, DMD_EXTENSION)
    from osgeo.ogr import GetDriver as ogr_GetDriver
    from osgeo.ogr import GetDriverCount as ogr_GetDriverCount
except:
    from gdal import Open as gdalopen
    from gdal import GetDriver as gdal_GetDriver
    from gdal import GetDriverCount as gdal_GetDriverCount
    from gdal import GetDriverByName as gdal_GetDriverByName
    from gdal import (DMD_LONGNAME, DMD_MIMETYPE, DMD_EXTENSION)
    from ogr import GetDriver as ogr_GetDriver
    from ogr import GetDriverCount as ogr_GetDriverCount



from math import (floor, log, pow)


#NEW 3.6.4
def zoomPreviousExtent(posExtent, listHistoExtents, mapCanvas):
    if posExtent > 0 :
       mapCanvas.blockSignals(True)
       posExtent = posExtent-1 
       mapCanvas.setExtent(listHistoExtents[posExtent])
       mapCanvas.refresh()       
       mapCanvas.blockSignals(False)
    return posExtent
       
def zoomNextExtent(posExtent, listHistoExtents, mapCanvas):
    if posExtent < len(listHistoExtents)-1 :
       mapCanvas.blockSignals(True)
       posExtent = posExtent + 1
       mapCanvas.setExtent(listHistoExtents[posExtent])
       mapCanvas.refresh()
       mapCanvas.blockSignals(False)
    return posExtent    


def iff(a, b, c):
    if a: return b
    else: return c
    
def cleanUri(uri):
    pos = uri.find("http")
    startUri = uri[:pos]      

    uri = uri.replace(startUri, "")
    uri = uri.replace("{", "%7B")
    uri = uri.replace("}", "%7D")
    uri = uri.replace("=", "%3D")
    uri = uri.replace("&", "%26")

    uri = startUri+uri
        
    return uri


class myGroupBoxButtons(QGroupBox):
      def __init__(self, parent, *args):
          super(myGroupBoxButtons, self).__init__(*args)
          self.parent = parent

          self.setMinimumHeight(60)
          self.setMaximumHeight(60)
          self.setStyleSheet("QGroupBox { border: 0px solid black;}")

          self.parent.dlg.saveButton = QPushButton(self)
          self.parent.dlg.saveButton.setText(translateMsg("Save"))
          self.parent.dlg.saveButton.setToolTip(translateMsg("Save"))
          self.parent.dlg.saveButton.setObjectName("saveButton")
          self.parent.dlg.saveButton.setShortcut(QKeySequence("CTRL+S"))

          self.parent.dlg.saveCloseButton = QPushButton(self)
          self.parent.dlg.saveCloseButton.setText(translateMsg("Save and close"))
          self.parent.dlg.saveCloseButton.setToolTip(translateMsg("Save and close"))
          self.parent.dlg.saveCloseButton.setObjectName("saveCloseButton")
          self.parent.dlg.saveCloseButton.setShortcut(QKeySequence("CTRL+MAJ+S"))

          
          self.parent.dlg.closeButton = QPushButton(self)
          self.parent.dlg.closeButton.setText(translateMsg("Close"))
          self.parent.dlg.closeButton.setToolTip(translateMsg("Close"))
          self.parent.dlg.closeButton.setObjectName("closeButton")
          self.parent.dlg.closeButton.setShortcut(QKeySequence("CTRL+Q"))
          

          self.parent.dlg.saveButton.clicked.connect(self.parent.setValues)
          self.parent.dlg.saveCloseButton.clicked.connect(self.saveAndClose)
          self.parent.dlg.closeButton.clicked.connect(self.parent.dlg.reject)

      def saveAndClose(self):
          self.parent.setValues()
          self.parent.dlg.reject()

      def resizeEvent(self,ev):
          middle = int( self.width()/2) 
          self.parent.dlg.saveButton.setGeometry(10, 30, 100, 24)
          self.parent.dlg.saveCloseButton.setGeometry(middle-100, 30, 200, 24)
          self.parent.dlg.closeButton.setGeometry(self.width() - 110, 30, 100, 24)
          

class myLineEdit(QLineEdit):
      def __init__(self, dlg=None, dockWidget=None):
          super(myLineEdit, self).__init__()
          self.dlg = dlg
          self.dockWidget = dockWidget
          self.setDragEnabled(True)
          self.setAcceptDrops(True)
          self.buttonWizard = None
          self.iconDir = join(dirname(__file__),"icons/")

      def initType(self, key, context):
          if key == "uri" :
             self.buttonWizard = funnyPushButton(self) 
             self.buttonWizard.initPushButton(24, 24, 400, 0, "buttonWizard", "",  translateMsg("Input assistant"), True, getThemeIcon("actions.png"), 24, 24, True)

             icon = QIcon(getThemeIcon("urlweb2.png"))
            
             menuAddTags = QMenu() 
             menuAddTags.setStyleSheet("QMenu {color: white; background-color:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop: 0 #cccccc, stop: 1 #5D5D5D);}")
             #NEW 3.4.0
             icon = QIcon(getThemeIcon("urlweb2.png"))
             self.testUrlInQGIS = menuAddTags.addAction(icon, '{:<30}'.format(translateMsg("Test in QGIS")), self.openUrlInQGIS)
             iconClean = QIcon(getThemeIcon("closenb.png"))
             self.getCleanUrlInQGIS = menuAddTags.addAction(iconClean, '{:<30}'.format(translateMsg("None")), self.cleanUrlInQgis)             
             menuAddTags.addSeparator()
             self.testUrlInWeb = menuAddTags.addAction(icon, '{:<30}'.format(translateMsg("Test in a web browser")), self.openWebUrl)
             self.buttonWizard.setMenu(menuAddTags)
                   
          if key == "iconGroupData" :
             self.buttonWizard = funnyPushButton(self) 
             self.buttonWizard.initPushButton(24, 24, 400, 0, "buttonWizard", "", translateMsg("Input assistant"), True, getThemeIcon("files.png"), 24, 24, True)
             self.buttonWizard.clicked.connect(self.getIcon)             
             self.setReadOnly(True)

          if key in ("groupe", "labelGroupData", "labeluri") : self.regex = QRegExp(r"^[^>$*<%+=@¤~#]*$", Qt.CaseSensitive)
             
          elif key == "uri" :
              if context == 1 : self.regex = QRegExp(r"^(http|https|ftp)\://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))*$", Qt.CaseInsensitive)
              else : self.regex = QRegExp(r"^(.+?)/([\w]+\.log)$", Qt.CaseInsensitive) 
          self.key = key
          self.context = context
          self.slotCtrl = self.buttonWizard


      def setSlotCtrl(self, slotCtrl): self.slotCtrl = slotCtrl    
      def mouseDoubleClickEvent(self, event):
          if self.slotCtrl : self.slotCtrl.clicked.emit()

      #NEW 3.4.0
      def cleanUrlInQgis(self) :
          if self.dockWidget : 
            groupRaster = self.dockWidget.getWmsGroupRaster() 
            if not groupRaster : return
            self.dockWidget.cleanWmsGroupRaster()
            
      def openUrlInQGIS(self):
          if self.dockWidget : 
            groupRaster = self.dockWidget.getWmsGroupRaster() 
            if not groupRaster : return
            self.dockWidget.cleanWmsGroupRaster()
            
            nameLayer = "WMS"
            urlWms = self.text()

            if not urlWms : return
            
            urlWms = cleanUri(urlWms)        

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


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

      def openWebUrl(self):
          url = self.text()
          #NEW 3.4.0
          posUrl = url.find("&url=")
          if posUrl > -1 : url = url[posUrl+5:]
          try : webbrowseropen(url)
          except : pass            


      def checkIconFile(self):
          cond = exists(join(dirname(__file__),"icons/%s" % self.text()))   
          self.setStyleSheet("background-color:#AEEE00;") if cond else self.setStyleSheet("background-color:red;")
      
      def verifiyPath(self, path):
          if path != self.iconDir :
             self.sender().setDirectory(self.iconDir)
      
      def getIcon(self):
            if self.sender() == None: return           

            fileDialog = QFileDialog(None, translateMsg("Extension images folder"))
            mimeTypeFilters = (("image/png", "image/icon", "image/jpeg"))
            fileDialog.setMimeTypeFilters(mimeTypeFilters)
            fileDialog.setViewMode(QFileDialog.Detail)
            fileDialog.setFileMode(QFileDialog.ExistingFiles)  
            fileDialog.setAcceptMode(QFileDialog.AcceptOpen)
            fileDialog.setDirectory(self.iconDir)
            fileDialog.setFileMode(QFileDialog.ExistingFiles)
            fileDialog.currentChanged.connect(self.verifiyPath)

            if fileDialog.exec_():
                if  fileDialog.selectedFiles() != [] :
                           fileName = "%s" % (fileDialog.selectedFiles()[0])
                           self.sender().parent().setText(basename(fileName))            



      def keyPressEvent(self, event) : QLineEdit.keyPressEvent(self, event)

      #NEW 3.4.0
      def checkRegExp(self):
          if self.isEnabled() :
             self.setStyleSheet("background-color:red;")
             if self.text() == "" : return
             if self.key == "iconGroupData" :
                cond = exists(join(dirname(__file__),"icons/%s" % self.text()))
                if not cond : cond = exists(self.text())
                self.setStyleSheet("background-color:#AEEE00;") if cond else self.setStyleSheet("background-color:red;")   
                return

             if self.key in ("groupe", "labelGroupData", "labeluri") :             
                 if self.regex.exactMatch(self.text()) : self.setStyleSheet("background-color:#AEEE00;")
             else :
                 if self.regex.exactMatch(self.text()) : self.setStyleSheet("background-color:#AEEE00;")
                 if self.key == "uri" and self.context == 1 :
                    if self.text().find("&url=http") > 0 : self.setStyleSheet("background-color:#AEEE00;") 
                 else : self.setStyleSheet("background-color:#AEEE00;")                    

      def resizeEvent(self, ev):
          if self.buttonWizard :  self.buttonWizard.setGeometry(self.width()-30, 1, 24, 24)


class legendTreeWidget( QTreeWidget ):
    def __init__(self, settings, parent=None, context=0, iconData=None, comboBox=None, dockWidget=None):
        QTreeWidget.__init__(self, parent)

        self.vectors, self.rasters, self.alrRasters = None, None, None
        self.parent = parent
        self.dockWidget = dockWidget

        self.context = context
        self.iconData = iconData
        self.comboBox = comboBox
        self.ihmWindow = self.parent.parent()#.parent()
        self.newNode = False

        self.setItemsExpandable(True)
        self.setAnimated(True)
        self.setDragEnabled(True)
        self.setDropIndicatorShown(True)
        self.setDragDropMode(QAbstractItemView.InternalMove)
        self.header().setDefaultSectionSize(150)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setMinimumWidth(300)
        self.setGeometry(500, 25, 300, 400)
        self.settings = settings

        self.groupIcon = QIcon(getThemeIcon("group.png"))


        self.toolBarWidget = QToolBar(self) 
        self.toolBarWidget.setObjectName("toolBarWidget")
        self.toolBarWidget.setGeometry(300, 30, 220, 40)
        self.toolBarWidget.setAllowedAreas(Qt.TopToolBarArea | Qt.BottomToolBarArea)
        self.toolBarWidget.setStyleSheet("QToolBar {icon-size: 32px, 32px; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E1E1E1, stop: 0.4 #9B9B9B, stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3);  border-width: 2px; border-radius: 10px; border-color: beige;}")


        self.buttonReloadWms = funnyPushButton(self.toolBarWidget) 
        self.buttonReloadWms.initPushButton(24, 24, 10, 5, "buttonExpandAllNodes", "", translateMsg("Reload WMS services"), True, getThemeIcon("refresh.png"), 24, 24, True)

        self.buttonExpandAllNodes = funnyPushButton(self.toolBarWidget) 
        self.buttonExpandAllNodes.initPushButton(24, 24, 45, 5, "buttonExpandAllNodes", "", translateMsg("Expand all nodes"), True, getThemeIcon("nodes_expand.png"), 24, 24, True)

        self.buttonReduceAllNodes = funnyPushButton(self.toolBarWidget) 
        self.buttonReduceAllNodes.initPushButton(24, 24, 80, 5, "buttonReduceAllNodes", "", translateMsg("Close all nodes"), True, getThemeIcon("nodes_reduce.png"), 24, 24, True)

        self.buttonAddGroup = funnyPushButton(self.toolBarWidget) 
        self.buttonAddGroup.initPushButton(24, 24, 115, 5, "buttonAddGroup", "", translateMsg("Add a group"), True, getThemeIcon("addgroup.png"), 24, 24, True)

        self.buttonEditNode = funnyPushButton(self.toolBarWidget) 
        self.buttonEditNode.initPushButton(24, 24, 150, 5, "buttonEditNode", "", translateMsg("Modify"), True, getThemeIcon("edit.png"), 24, 24, True)

        self.buttonDelNode = funnyPushButton(self.toolBarWidget) 
        self.buttonDelNode.initPushButton(24, 24, 185, 5, "buttonDelNode", "", translateMsg("Delete"), True, getThemeIcon("del.png"), 24, 24, True)

        self.buttonReloadWms.clicked.connect(self.reloadServicesWms)
        self.buttonExpandAllNodes.clicked.connect(self.expandTreeWidget)
        self.buttonReduceAllNodes.clicked.connect(self.expandTreeWidget)
        self.buttonEditNode.clicked.connect(self.callEditItem)
        self.buttonAddGroup.clicked.connect(self.addGroup)
        self.buttonDelNode.clicked.connect(self.delNode) 


        root = self.invisibleRootItem()
        root.setData(0, Qt.WhatsThisRole,"root")
        self.setRootIsDecorated( False )
        self.setHeaderLabels([translateMsg("Values")])

        styleSheet = "QTreeWidget { border: 1px solid;  border-radius: 5px; opacity: 0.5; background-color: rgba(255, 255, 255, 50);}"
        styleSheet+= "QTreeWidget::item:selected {background-color: #5D5D5D; color: rgb(255,255,255); }"

        self.imgChecked = getThemeIcon("checked.png").replace("\\","/")
        self.imgUnChecked = getThemeIcon("unchecked.png").replace("\\","/")

        styleSheet+= "QTreeWidget {opacity: 0.5;  background-color: rgba(255, 255, 255, 210);}"
        styleSheet+= "QTreeWidget::indicator:checked {image: url(%s);}" % self.imgChecked
        styleSheet+= "QTreeWidget::indicator:unchecked  {image: url(%s);}" % self.imgUnChecked


        self.setStyleSheet(styleSheet)
        self.setColumnWidth(0, 280)
        self.setColumnCount(1)
        
        self.styleSlider = """
        QSlider::groove:horizontal {border: 1px solid #bbb; background: white; height: 10px; border-radius: 4px;}
        QSlider::sub-page:horizontal {background: qlineargradient(x1: 0, y1: 0,    x2: 0, y2: 1,  stop: 0 #66e, stop: 1 #bbf); background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1,  stop: 0 #bbf, stop: 1 #55f);border: 1px solid #777;height: 10px;border-radius: 4px;}
        QSlider::add-page:horizontal {background: #fff; border: 1px solid #777; height: 10px; border-radius: 4px;}
        QSlider::handle:horizontal {background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #eee, stop:1 #ccc); border: 1px solid #777; width: 13px; margin-top: -2px; margin-bottom: -2px; border-radius: 4px;}
        QSlider::handle:horizontal:hover {background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #fff, stop:1 #ddd); border: 1px solid #444; border-radius: 4px;}
        QSlider::sub-page:horizontal:disabled {background: #bbb; border-color: #999;}
        QSlider::add-page:horizontal:disabled {background: #eee; border-color: #999;}
        QSlider::handle:horizontal:disabled {background: #eee; border: 1px solid #aaa; border-radius: 4px;}
        """

        self.itemClicked.connect(self.treeWidgetItemChanged)
        self.parent.installEventFilter(self)

        self.setCurrentItem(self.topLevelItem(0))
        self.treeWidgetItemChanged(self.currentItem(), 0)

    def reloadServicesWms(self):
        self.dockWidget.reloadServicesWms()
        self.dockWidget.barInfo.pushMessage("%s :" % translateMsg("Information"), translateMsg("WMS services have been reloaded !"), Qgis.Info, 3)

    def setContext(self, context, iconData):
        self.context = context
        self.iconData = iconData

    def eventFilter(self, obj, event):
        if obj is self.parent:
           if event.type() == event.Resize: self.resizeObjects()
        return QObject.eventFilter(self, obj, event)
           
    def expandTreeWidget(self):
        if self.sender().objectName() == "buttonExpandAllNodes" : self.expandAll()
        else : self.collapseAll()

    def resizeObjects(self):
        self.setGeometry(10, 25, self.parent.width()-30, self.parent.height()-70) 
        self.setColumnWidth(0, self.parent.width()-150)
        self.setColumnWidth(1, 80)
              
    #NEW 3.4.0
    def addGroup(self):
        i = 0
        groupData = "%s %s %s" % (translateMsg("New"), translateMsg("Group").lower(), i)
        while not self.checkUnicityName(groupData) :
              i+= 1
              groupData = "%s %s %s" % (translateMsg("New"), translateMsg("Group").lower(), i)      
        self.addItem([groupData], "groupdata", -1, self.groupIcon, "groupdata", None, {"labelGroupData" : groupData, "iconGroupData" : "group.png"})


    def getGroupParent(self, nameGroup): 
        results = self.findItems(nameGroup, Qt.MatchContains|Qt.MatchRecursive, 0)
        for item in results :
            return item
        return None


    def delNode(self): 
        if not self.currentItem() : return  
        if self.currentItem().parent() : self.currentItem().parent().removeChild(self.currentItem())
        else : 
           group = self.currentItem()
           self.removeAllItems(group)
           self.invisibleRootItem().removeChild(self.currentItem())

        self.model().submit()
        self.repaint()
        self.treeWidgetItemChanged(self.currentItem(), 0)

    def removeAllItems(self, group):
        for j in range(group.childCount()-1, -1, -1,) : group.removeChild(group.child(j))
  
    def checkUnicityName(self, text):
        checkUnicityName = True  
        root = self.invisibleRootItem()
        for i in range(root.childCount()):
            group = root.child(i)
            if group.data(0, Qt.DisplayRole) == text : checkUnicityName = False ; break
        return checkUnicityName

    def verifyUnicity(self):
        verifyUnicity = True
        text = self.sender().text()
        itemGroup = self.currentItem()
        mainCtrl = self.dlg if self.dlg else self
        
        root = self.invisibleRootItem()
        for i in range(root.childCount()):
            group = root.child(i)
            if group != itemGroup :
               if group.data(0, Qt.DisplayRole) == text : verifyUnicity = False ; break

        if not verifyUnicity : QMessageBox.information(mainCtrl, translateMsg("Warning"), translateMsg("The key <b><u>%s</u></b> already exists !") % text )
        if self.dlg :
           self.dlg.saveButton.setEnabled(verifyUnicity)
           self.dlg.saveCloseButton.setEnabled(verifyUnicity)
           

        return verifyUnicity

    def treeWidgetItemChanged(self, item, column):
        if item :
           self.newNode = False   
           self.buttonDelNode.setEnabled(True)
           self.buttonEditNode.setEnabled(True)
           if item.parent() :
              self.buttonEditNode.setIcon(QIcon(getThemeIcon("edit.png")))
              self.buttonEditNode.setToolTip(translateMsg("Edit item"))
              self.buttonDelNode.setToolTip(translateMsg("Delete item"))
           else :
              self.newNode = True   
              self.buttonEditNode.setIcon(QIcon(getThemeIcon("add.png")))
              self.buttonEditNode.setToolTip(translateMsg("Add an item"))
              self.buttonDelNode.setToolTip(translateMsg("Delete group"))
        else :
              self.buttonDelNode.setEnabled(False)
              self.buttonEditNode.setEnabled(False)
              self.buttonEditNode.setIcon(QIcon(getThemeIcon("noaction.png")))
              self.buttonEditNode.setToolTip(translateMsg("Select an item"))
              self.buttonDelNode.setToolTip(translateMsg("Select an item"))

    def setPropertiesItem(self, item, itemParent):
        self.dlg = QDialog()
        self.dlg.item = item
        self.dlg.setMinimumWidth(480)
        self.dlg.setMaximumWidth(800)
        self.dlg.setMaximumHeight(320)
        self.dlg.setWindowFlags(Qt.WindowMaximizeButtonHint | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint)

        if itemParent and not self.newNode :
              self.dlg.setWindowTitle("%s : %s - %s" % (translateMsg("Property for the item"), translateMsg("Group"), itemParent.data(0, Qt.DisplayRole)))
              self.dlg.setGeometry(200, 200, 480, 180)
        else :
              self.dlg.setWindowTitle("%s : %s - %s" % (translateMsg("Property for the item"), translateMsg("Item"), item.data(0, Qt.DisplayRole))) if item else self.dlg.setWindowTitle("%s : %s - %s %s" % (translateMsg("Property for the item"), translateMsg("Item"), translateMsg("New"), translateMsg("Item").lower())) 
              self.dlg.setGeometry(200, 200, 480, 320)

        self.dlg.setWindowIcon(self.currentItem().icon(0)) if not self.newNode else self.dlg.setWindowIcon(QIcon(getThemeIcon("wms.png")))
        layout = QVBoxLayout(self.dlg)

        role = Qt.WhatsThisRole

        if item :
           values = self.dlg.item.data(0, role)
           dictValues = literal_eval(values)
        else :
           if itemParent :
              values = itemParent.data(0, role)
              dictValues = literal_eval(values)
           if self.newNode : dictValues = {"labeluri" : '', "uri" : '', "paramuri" : '0'}  

        posY = 10
       
        for key in dictValues.keys():
              
            label = QLabel(self.dlg)
            label.setText("%s :" % key)

            label.setMinimumHeight(30)
            label.setMaximumHeight(30)                
            label.setAlignment(Qt.AlignCenter)
            label.setGeometry(10, posY, 100, 30)
            label.setStyleSheet("QLabel { font-size: 11px;  color : black; background-color: rgba(160, 160, 160, 125); border: 1px solid black;  border-radius: 4px;  padding: 8px;}")

            layout.addWidget(label)

            value = myLineEdit(self.dlg, self.dockWidget)
            value.setObjectName(key)
            value.initType(key, self.context)
            value.setMinimumHeight(25)
            value.setMaximumHeight(25)
            value.setGeometry(110, posY, 350, 25)
            value.setText(dictValues[key])
        
                            
            if key == "paramuri" : value.setEnabled(False)
            else :
               if key == "uri" : value.textChanged.connect(self.ctrlValue)
               elif key == "iconGroupData" : pass 
               else : value.textChanged.connect(value.checkRegExp)
               #NEW 3.4.0
               if itemParent and key == "labelGroupData" : value.textChanged.connect(self.verifyUnicity) #editingFinished

            if key != "uri" : value.checkRegExp()

            layout.addWidget(value)
            
            posY+= 30

        self.ctrlValue()

        groupButtons = myGroupBoxButtons(self)

        layout.addWidget(groupButtons)
                        
        self.dlg.exec_()


    def ctrlValue(self):
        obj = self.dlg.findChild(myLineEdit, "uri")
        if obj :          
           obj.checkRegExp()    
           self.countBalises(obj)
           
    def countBalises(self, obj):
        text = obj.text()
        baliseO, baliseF = text.count("["), text.count("]") 
        objToUpdate = self.dlg.findChild(myLineEdit, "paramuri")           
        if objToUpdate :
           if baliseO == baliseF :
              objToUpdate.setStyleSheet("background-color:#AEEE00;")
              objToUpdate.setText("%s" % baliseO)
           else :
              objToUpdate.setStyleSheet("background-color:red;")
              objToUpdate.setText("0")


    def setValues(self):
        if not self.dlg : return
        values = {}
        for child in self.dlg.children():
            if type(child) == myLineEdit : values[child.objectName()] = child.text()

        verifyLabel = True    
            
        if self.currentItem().parent() or self.newNode :    
            if values["labeluri"] == "" : verifyLabel = False 
        else :
            try :  
               if values["labelGroupData"] == "" : verifyLabel = False  
            except :
               try :
                     if values["groupe"] == "" : verifyLabel = False
               except : return

        if not verifyLabel : QMessageBox.information(self.dlg, translateMsg("Warning"), translateMsg("The name cannot be an empty string !")); return    
        
        if not self.newNode :
           #NEW 3.3.2
           if dicoHasKey(values, "labelGroupData") :
              name = values["labeluri"] if self.currentItem().parent() else values["labelGroupData"]
              iconItem = self.getIconForItem(values["uri"]).replace("\\", "/") if self.currentItem().parent() else QIcon(getThemeIcon(values["iconGroupData"]))
           else : return   
     
           self.currentItem().setData(0, Qt.WhatsThisRole, "%s" % values)   
           self.currentItem().setData(0, Qt.DisplayRole, name)           
           self.currentItem().setIcon(0, QIcon(iconItem))
           self.dlg.setWindowIcon(self.currentItem().icon(0))
        else :           
           value = values["uri"]
           iconItem = self.getIconForItem(value).replace("\\", "/")
           self.addItem(['{:<100}'.format(values["labeluri"])], translateMsg("Value"), self.currentItem().childCount(), iconItem, translateMsg("Value"), self.currentItem(), values)
           
        self.model().submit()
        self.repaint()

        if self.newNode : self.newNode = False; self.dlg.close()

    def getIconForItem(self, value):
        iconItem = getThemeIcon("unknow.png")  
        if self.context == 0 :
              if exists(value) :
                 sourceFile = QFileInfo(value)
                 if sourceFile.isFile():
                    iconMime = getThemeIcon("%s.png" % sourceFile.suffix().lower())
                    if exists(iconMime) : iconItem = iconMime
                    else :   iconItem = getThemeIcon("unknow.png")  
                 else : iconItem = getThemeIcon("folder.png")                 
              else : iconItem = getThemeIcon("unknow.png")
        else :
              iconItem = getThemeIcon("urlweb.png")
        return iconItem      
      

    def editItem(self, item) :
        if not item : return
        if item.parent() : self.setPropertiesItem(item, None)
        else : self.setPropertiesItem(None, item)

    def callEditItem(self) :
        if not self.currentItem().parent() : self.newNode = True
        self.editItem(self.currentItem())
        
    def mouseDoubleClickEvent(self, event):
        if not self.currentItem().parent() : self.newNode = False  
        self.editItem(self.currentItem())

    def dragMoveEvent(self, event):
        role = Qt.WhatsThisRole
        itemToDropIn = self.itemAt(event.pos())
        itemBeingDragged = self.currentItem()
        dictValues = literal_eval(itemBeingDragged.data(0,role))
        okList = dictValues["labeluri"]

        dropInValues = None
        if itemToDropIn is None: itemToDropIn = self.invisibleRootItem()
        else : dropInValues = literal_eval(itemToDropIn.data(0, role))
        
        if not dropInValues : return
        return

        if dropInValues["labeluri"] == okList :    
            super(legendTreeWidget, self).dragMoveEvent(event)            
            return
        else:
            parent = itemToDropIn.parent()
            if parent is None : parent=self.invisibleRootItem()
            if parent.data(0,role) in okList:
                super(legendTreeWidget, self).dragMoveEvent(event)
                return
        event.ignore()

    def dropEvent(self, event):
        
        role = Qt.UserRole  

        itemBeingDragged = self.currentItem()
        okList = self.settings[itemBeingDragged.data(0, role)][0]
 
        oldParent = itemBeingDragged.parent()
        if oldParent is None: oldParent = self.invisibleRootItem()
        oldIndex = oldParent.indexOfChild(itemBeingDragged)

        super(legendTreeWidget,self).dropEvent(event)

        newParent = itemBeingDragged.parent()
        if newParent is None : newParent = self.invisibleRootItem()

        if not newParent.data(0, role) in okList :
            newParent.removeChild(itemBeingDragged)
            oldParent.insertChild(oldIndex, itemBeingDragged)

        self.setCurrentItem(itemBeingDragged)
            

    def setDataItem(self, groupText, findText, itemText, layerId, itemIcon, groupKey, category, group):
        group = self.getGroupParent(groupText)
        item = None
        if group :
           for i in range(group.childCount()):
               if group.child(i).text(0).startswith(findText) :
                  group.child(i).setData(0, Qt.DisplayRole, itemText)
                  group.child(i).setStatusTip(0, "%s|%s" % (category, layerId))
                  item = group.child(i)
                  break

    def addItem(self, strings, category, fileId, iconlayer, parentname=None, parent=None, values=None):
        if category not in self.settings:  return False
        if parent is None : parent = self.invisibleRootItem()
        
        item = QTreeWidgetItem(parent, strings)
        item.setData(0, Qt.UserRole , category)
        item.setData(0, Qt.WhatsThisRole, "%s" % values)
        item.setStatusTip(0, "%s|%s" % (category, fileId)) if parent else item.setStatusTip(0, "%s|%s" % (category, parentname))
        item.setExpanded(True)
        item.setFlags(self.settings[category][1])
        
        if type(iconlayer) == str : iconlayer = QIcon(iconlayer)
        item.setIcon(0, iconlayer)
   
        return item

    def removeItemWithId(self, groupText, layerId):
        group = self.getGroupParent(groupText)
        if group :
           for i in range(group.childCount()):
               item = group.child(i)
               infos = item.statusTip(0).split("|")
               if layerId == infos[1] :
                  group.removeChild(item)
                  break

#END NEW 3.4.0
                
def translateMsg(message): return QCoreApplication.translate('autoLoaderRasterPlugin', message)

def convertSize(size):
   size_name = ("", "K.", "M.", "G.", "T.", "P.", "E.", "Z.", "Y.")
   i = 0
   if size > 0 :
      i = int(floor(log(size, 1000)))
      p = pow(1000, i)
      s = round(size/p, 2)
   else :
      s = 0
   return '%s %s ' % (s, size_name[i])
    
##### ======= FUNCTIONS QTREEWIDGET ======== ####
def visitTreeElt(listItems, item, level, maxlevel):
  listItems.append([level, item.text(0), item.whatsThis(0), item.text(1)])
  for i in range(item.childCount()):
      if maxlevel < level+1 : maxlevel = level+1  
      maxlevel = visitTreeElt(listItems, item.child(i), level+1, maxlevel)
  return maxlevel    

def visitTreeList(tree) :
  listItems = []
  maxlevel = 0
  for i in range(tree.topLevelItemCount()) :
      maxlevel = visitTreeElt(listItems, tree.topLevelItem(i), 0, 1)
  return listItems, maxlevel
    
def legendSymbolItemChecked(node, ruleKey):
    isCheckedElt = False
    if Qgis.QGIS_VERSION_INT <= 31299 : isCheckedElt = node.layer().renderer().legendSymbolItemChecked(ruleKey)
    else :
          try : isCheckedElt = node.layer().featureRenderer().legendSymbolItemChecked(ruleKey)
          except : isCheckedElt = node.layer().renderer().legendSymbolItemChecked(ruleKey) #NEW AFTER QGIS 3.4
    return isCheckedElt

def conditionnalAddChild(treeWidget, parent, legendItem) :    
    if not parent : treeWidget.addTopLevelItem(legendItem) 
    else : parent.addChild(legendItem)

def createTreeWidgetItem(iconPath, icon, text):
    legendItem = QTreeWidgetItem()
    legendItem.setIcon(0, icon)
    legendItem.setText(0, text)
    legendItem.setWhatsThis(0, iconPath)
    return legendItem    
##### ======= END FUNCTIONS QTREEWIDGET ======== ####    

##### =======    FUNCTIONS LISTLAYERS   ======== #### 
def getListLayers(self, targetList, model, comboBox):
   root = QgsProject.instance().layerTreeRoot()
   targetList.clear()
   comboBox.clear()
   
   targetList[0], maxDim, dim = [], 0, 400

   i = 0
   if root != None :
       nameGroup = ""
       for layer in root.findLayers() : 
           if type(layer.layer()) == QgsRasterLayer :
              if nameGroup != layer.parent().name():
                 nameGroup = layer.parent().name() 
                 try : comboBox.addGroup(model, nameGroup)
                 except : pass
              if not dicoHasKey(targetList, layer.layerId()):
                 dim = addItemInModel(self, targetList, model, layer)
                 maxDim = max(maxDim, dim)
   
   comboBox.setModelColumn(0)
   comboBox.show()
   comboBox.setCurrentIndex(-1)
   
   return maxDim

def addItemInModel(self, targetList, model, layer):
   item = QStandardItem(QIcon(getThemeIcon("raster.png")), "%s, [ %s ]" % (layer.name(), layer.layer().crs().authid()))
   item.setData("%s" % layer.layerId(), Qt.UserRole)
   font = QFont('Times New Roman', 9)
   font.setItalic(True)        
   item.setFont(font)   
   model.appendRow(item) 
   targetList[layer.layerId()] = []
   return len(layer.name())

def getComboLayer(self, comboBox, index):
   targetLayer = None
   if index != -1 :
       modelIndex = comboBox.model().index(index, 0)
       layerId = comboBox.model().data(modelIndex, Qt.UserRole)
       root = QgsProject.instance().layerTreeRoot()
       if root != None :
               for layer in root.findLayers() :
                   if layer.layerId() == layerId: targetLayer = layer.layer(); break;
   return targetLayer

def getComboLayerIndex(self, comboBox, text):
   model, index = comboBox.model(), 0
   for i in range(comboBox.count()):
       if model.item(i).text() == text :    
          index = i  
          break
   return index
##### =======  END FUNCTIONS LISTLAYERS ======== ####


def textForMenu(pattern, text, maxDim, shorcuts):
    return pattern % (text, shorcuts.ljust(maxDim-len(text)-len(shorcuts))) if pattern else text 

def fixeMaxDim(listItems):
    maxDim = 40
    if listItems != []:
       for item in listItems: maxDim = max(maxDim, len(item))
    return maxDim

def iff(a, b, c):
    if a: return b
    else: return c

def makeListFormatsExtensions(self, vector, raster, includeJoker):
    listFormatsExtensions, listFormatsExtensionsVector, listFormatsExtensionsAll = [], [], []

    for iDriver in range(ogr_GetDriverCount()):
        poDriver = ogr_GetDriver(iDriver)
        poValue = poDriver.GetName()
        driver = gdal_GetDriverByName("%s" % (poValue))
        listFormatsExtensionsVector = setEltListFormatsExtensions(self, listFormatsExtensionsVector, driver, poValue)
        

    for iDriver in range(gdal_GetDriverCount()):
        poDriver = gdal_GetDriver(iDriver)
        poValue = poDriver.ShortName
        driver = gdal_GetDriverByName("%s" % (poValue))
        listFormatsExtensionsAll = setEltListFormatsExtensions(self, listFormatsExtensionsAll, driver, poValue)

    if vector and raster : listFormatsExtensions =  listFormatsExtensionsAll
    else :
        if vector : listFormatsExtensions = listFormatsExtensionsVector
        elif raster :
            listFormatsExtensions = [value for value in listFormatsExtensionsAll if value not in listFormatsExtensionsVector] 
            if not "jp2" in listFormatsExtensions : listFormatsExtensions.append('jp2')
            
    if includeJoker : listFormatsExtensions.append('*')
    return sorted(listFormatsExtensions)

def setEltListFormatsExtensions(self, listFormatsExtensions, driver, poValue):
       if driver :
            poDriverMetadata = driver.GetMetadata()
            if dicoHasKey(poDriverMetadata, DMD_EXTENSION):
                if poDriverMetadata[DMD_EXTENSION]!= '' and not poDriverMetadata[DMD_EXTENSION] in  listFormatsExtensions : listFormatsExtensions.append(poDriverMetadata[DMD_EXTENSION])
       else :
           if poValue != '' and not poValue in  listFormatsExtensions : listFormatsExtensions.append[poValue]
       return listFormatsExtensions


def getExtension(fileName):
    from os.path import (basename, splitext)
    textension = splitext(fileName)
    extension = textension[len(textension)-1].lower()
    return extension

def windowIcon(qtWindow, icon):
    if not qtWindow : return
    icon = getThemeIcon(icon)
    if icon != "" : qtWindow.setWindowIcon(QIcon(icon)) 

def changeButtonIcon(self, button, icon, iconWidth, iconHeight):
    icon = getThemeIcon(icon)
    button.setIcon(QIcon(icon))

def getThemeIcon(theName):
    dirs = list(sysPath)
    dirs.insert(0, "%s%s" % (cleanPath(dirname(__file__)),"icons/"))
    dirs.insert(0, "%s%s" % (cleanPath(QgsApplication.pluginPath()),"autoLoaderRaster/icons/"))
    for dir in dirs :
        myPath = cleanPath(dir)
        myIconPath = "%s%s" % (myPath, theName)
        if QFile.exists(myIconPath): return myIconPath
    return ""
    
def cleanPath(path):
    path = "%s" % (path)
    a = len(path)
    letter = "/"
    b = path.rfind(letter, 0, a)
    return ("%s/" % (path)) if a != b else path 
    
def fixeLabelsFileDialog(self, dlgFile, context, hasName):
    dlgFile.setLabelText(QFileDialog.Accept, translateMsg("Open")) if context == 0 else dlgFile.setLabelText(QFileDialog.Accept, translateMsg("Save"))
    dlgFile.setLabelText(QFileDialog.Reject, translateMsg("Cancel"))        
    dlgFile.setLabelText(QFileDialog.FileName, "%s : " % (translateMsg("Name"))) if hasName else dlgFile.setLabelText(QFileDialog.FileName, translateMsg("Folder : "))
    dlgFile.setLabelText(QFileDialog.FileType, "%s : " % translateMsg("Filters"))
    dlgFile.setLabelText(QFileDialog.LookIn,   "%s : " % translateMsg("Folder"))

def dicoHasKey(dico, key):
    cond = False
    try : cond = dico.has_key(key)
    except : cond = (key in dico)
    return cond

def prettifyXml(xml):
    return parseString(xml).toprettyxml()


class textEditFolder(QTextEdit):
    def __init__(self, * args):
        QTextEdit.__init__(self, * args)

    def initTextEdit(self, SizeW, SizeH, posX, posY, name, isGeom, undoRedo, isReadOnly, isRichText, isSizable):
        if not isSizable:  self.setMaximumSize(SizeW, SizeH)
        if isGeom: self.setGeometry(posX, posY, SizeW, SizeH)
        self.setUndoRedoEnabled(undoRedo)
        self.setReadOnly(isReadOnly)
        self.setAcceptRichText(isRichText)
        self.setObjectName(name)
        self.setAccessibleName(name)
        self.setAcceptDrops(True)

class editor(QTextEdit):
    def __init__(self, parent, withProgressBar):
        super(editor, self).__init__(parent)
        self.setWindowTitle("QTextEdit Standard Output Redirection")
        self.setStyleSheet("color: white; background-color: black;")
        self.setAcceptRichText(True)
        self.setObjectName(parent.objectName())
        self.parent = parent
        self.progressBar = None

        if withProgressBar :
            self.progressBar = progressBar(self)
            self.progressBar.initTextEdit(200, 25, 200, 140, "progressBar", True, 0, True, Qt.AlignCenter, 0)
            self.progressBar.setStyleSheet("progressBar {border: 2px solid grey; border-radius: 5px; text-align: center;}"
                                            "progressBar::chunk {background-color: #6C96C6; width: 20px;}")


class funnyPushButton(QPushButton):
     def __init__(self, *args): super(funnyPushButton, self).__init__(*args)
            
     def initPushButton(self, sizeWidth, sizeHeight, coordX, coordY, name, text, toolTip, isGeom, icon, iconWidth, iconHeight, isStyleSheeted):
            self.setMinimumSize(sizeWidth, sizeHeight)
            self.setMaximumSize(sizeWidth, sizeHeight)
            self.iconWidth = iconWidth
            self.iconHeight = iconHeight
            self.selfFocused = False
            self.subMenuVisble = False
            if isGeom : self.setGeometry(coordX, coordY, sizeWidth, sizeHeight)
            if icon != "" :
               self.setIcon(QIcon(icon))
               self.setIconSize(QSize(self.iconWidth , self.iconHeight))
            self.setToolTip(toolTip)
            if isStyleSheeted : self.setStyleSheet(" QPushButton {border-width: 0px; border-radius: 10px;  border-color: beige;}")
            self.setObjectName(name)
            if text != "" : self.setText(text)

     def enterEvent(self, event):
          if not self.selfFocused :
             #NEW 3.4.1 - QSIZE BUG QGIS >= 3.36 
             self.setIconSize(QSize(int(self.iconWidth *0.8), int(self.iconHeight *0.8)))
             self.selfFocused = True
          
     def leaveEvent(self, event):
        if self.subMenuVisble == False : self.restoreButton()
     
     def restoreButton(self):
           self.selfFocused = False    
           self.setIconSize(QSize(self.iconWidth, self.iconHeight))
           
      
class labeller(QLabel):
     def __init__(self, name, text, styleSheet, alignment, *args):
             super(labeller, self).__init__(*args)
             self.setObjectName(name)
             self.setText(text)
             self.setMyStyleSheet(styleSheet)
             """
             if styleSheet == "special": self.setStyleSheet("QLabel {display: block;  border: 2px solid gray;  border-radius: 10px; text-align: center;  line-height: 10px; background-color: #C0C0C0; border: 1px solid black; color: black}")
             elif styleSheet == "infos": self.setStyleSheet("QLabel {font-size:10px; background-color:#C0C0C0; border: 1px solid #e1e1e1; padding: 4px ; color: black}")
             elif styleSheet == "coords": self.setStyleSheet("QLabel {  color : white; font-size: 11px; background-color: rgba(93, 93, 93, 125);}")
             """
             self.setAlignment(alignment)

     #NEW 3.0.0
     def setMyStyleSheet(self, style):
         styleSheet = {"special": "QLabel {display: block;  border: 2px solid gray;  border-radius: 10px; text-align: center;  line-height: 10px; background-color: #C0C0C0; border: 1px solid black; color: black}",
                       "infos": "QLabel {font-size:10px; background-color:#C0C0C0; border: 1px solid #e1e1e1; padding: 4px ; color: black}",
                       "normal": "QLabel {font-size:10px; background-color:#C0C0C0; border: 1px solid #e1e1e1; padding: 4px ; color: black}",
                       "coords": 'QLabel {color : white; font-size: 11px; background-color: rgba(93, 93, 93, 125)}',
                       "error" : "QLabel {display: block;  border: 2px solid gray;  border-radius: 10px; text-align: center;  line-height: 10px; background-color: #CC0000; border: 1px solid red; color: white}"}

         styleCss = styleSheet[style]
         self.setStyleSheet(styleCss)
      
         
         

class myPushButton(QPushButton):
     def __init__(self, *args): super(myPushButton, self).__init__(*args)
            
     def initPushButton(self, sizeWidth, sizeHeight, coordX, coordY, name, text, toolTip, isGeom, icon, iconWidth, iconHeight, isStyleSheeted):
            self.setMinimumSize(sizeWidth, sizeHeight)
            self.setMaximumSize(sizeWidth, sizeHeight)
            if isGeom : self.setGeometry(coordX, coordY, sizeWidth, sizeHeight)
            if icon != "" :
               self.setIcon(QIcon(icon))
               self.setIconSize(QSize(iconWidth, iconHeight))
            self.setToolTip(toolTip)
            if isStyleSheeted : self.setStyleSheet("QPushButton {border: none;}")
            self.setObjectName(name)
            if text != "" : self.setText(text)

class progressBar(QProgressBar):
    def __init__(self, * args):
        QProgressBar.__init__(self, * args)

    def initTextEdit(self, width, heigth, posX, posY, name, isGeom, initValue, viewText, alignement, isStyleSheet):
        self.setMinimumSize(width, heigth)
        self.setMaximumSize(width, heigth)
        if isGeom: self.setGeometry(posX, posY, width, heigth)
        self.setProperty("value", initValue)
        self.setAlignment(alignement)
        self.setTextVisible(viewText)
        self.setObjectName(name)
        self.setAccessibleName(name)
        if isStyleSheet == 0:
            self.setStyleSheet(
                               "progressBar {border: 2px solid grey; border-radius: 5px; text-align: center;}"
                               "progressBar::chunk {background-color: #6C96C6; width: 10px; margin: 0.5px;}"
                               )            


class printerDlg(object):
      def __init__(self, parent, obj, title, orientation):
                    
              printer = QPrinter() 
              printer.setPageSize(QPrinter.A4)
              printer.setOrientation(orientation)
              printer.setPageMargins(5, 10, 5, 10, QPrinter.Millimeter)
              printer.setOrientation(orientation)
              printer.setOutputFormat(QPrinter.NativeFormat)
              self = QPrintPreviewDialog(printer)
              windowIcon(self, "print.png")
              self.setWindowTitle(title)
              self.setWindowFlags(Qt.WindowMaximizeButtonHint | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint)
              self.paintRequested.connect(obj.print_)
              self.exec_()


class saveDlg(QDialog):
    def __init__(self, parent, initDir):
        QDialog.__init__(self)
        self.parent = parent
        self.initDir = initDir
        self.setupUi()

    def setupUi(self):
        self.setObjectName("saveDlg")
        self.maxWidth, self.maxheight = 620, 200 
        self.setMinimumSize(self.maxWidth,self.maxheight)
        self.setMaximumSize(self.maxWidth,self.maxheight)        
        self.resize(self.maxWidth, self.maxheight) 
        windowIcon(self, "checkdoubleglasses.png")

        self.setWindowTitle("%s ..." % translateMsg("Save maps as images"))

        self.styleTextEdit = """
                    color: black; background-color: rgba(255, 255, 125, 50);
                    border-left-width: 1px;
                    border-left-color: black;
                    border-left-style: solid;
                    border-right-color: black;
                    border-right-width: 1px;
                    border-right-style: solid;
                    border-right-radius: 3px;"""

        self.styleTextEditDisaBled  = """
                    color: black; background-color: rgba(125, 125, 125, 50);
                    border-left-width: 1px;
                    border-left-color: black;
                    border-left-style: solid;
                    border-right-color: black;
                    border-right-width: 1px;
                    border-right-style: solid;
                    border-right-radius: 3px;"""

        self.authorizedMime = ["*.*"]


        icon = getThemeIcon("savefile.png")
        toolTip = translateMsg("Save maps as images")
        self.saveButton = funnyPushButton(self)
        self.saveButton.initPushButton(24, 24, self.width()-160, self.height()-30, "saveButton", "", toolTip, True, icon, 24, 24, True)
        self.saveButton.setShortcut(QKeySequence("Ctrl+S"))

        icon = getThemeIcon("close.png")
        toolTip = translateMsg("Close")
        self.closeButton = QPushButton(self)
        self.closeButton.setObjectName("closeButton")
        self.closeButton.setText("&%s" % translateMsg("Close"))
        self.closeButton.setGeometry(self.width()-120, self.height()-30, 100, 25)


        self.lblNameFirstImage = QLabel(self)
        self.lblNameFirstImage.setAlignment(Qt.AlignRight)
        self.lblNameFirstImage.setText("%s %s 1 :" % (translateMsg("Name"), translateMsg("MapCanvas").lower()))
        self.lblNameFirstImage.setGeometry(20, 20, 120, 25)


        self.listExtension = QComboBox(self)
        self.listExtension.setGeometry(520, 20, 60, 25)
        self.listExtension.setEditable(False) 
        self.listExtension.setEnabled(True)
        self.listExtension.setObjectName("listExtension")
        #listExtensions = makeListFormatsExtensions(self, False, True, False)
        listExtensions = ["bmp", "jpg", "png", "tif"]
        self.listExtension.addItems(listExtensions)

        if "png" in listExtensions : self.listExtension.setCurrentIndex( listExtensions.index("png"))
                

        self.nameFirstImage = lineEditNameFile(self)
        self.nameFirstImage.initCtrlWidget(self.saveButton, self.listExtension)
        self.nameFirstImage.setGeometry(150, 20, 360, 25)
        self.nameFirstImage.setObjectName("nameFirstImage")
        self.nameFirstImage.setStyleSheet(self.styleTextEdit)
        self.nameFirstImage.setText("mapviewer1.png")
        self.nameFirstImage.textChanged.connect(self.nameFirstImage.checkRegExp)
        self.nameFirstImage.checkRegExp()

        self.lblNameSecondImage = QLabel(self)
        self.lblNameSecondImage.setAlignment(Qt.AlignRight)
        self.lblNameSecondImage.setText("%s %s 2 :" % (translateMsg("Name"), translateMsg("MapCanvas").lower()))
        self.lblNameSecondImage.setGeometry(20, 50, 120, 25)


        self.nameSecondImage = lineEditNameFile(self)
        self.nameSecondImage.initCtrlWidget(self.saveButton, self.listExtension)
        self.nameSecondImage.setGeometry(150, 50, 360, 25)
        self.nameSecondImage.setObjectName("nameSecondImage")
        self.nameSecondImage.setStyleSheet(self.styleTextEdit)
        self.nameSecondImage.setText("mapviewer2.png")
        self.nameSecondImage.textChanged.connect(self.nameSecondImage.checkRegExp)
        self.nameSecondImage.checkRegExp()
        
        self.lblFolder = QLabel(self)
        self.lblFolder.setText("%s :" % translateMsg("Folder"))
        self.lblFolder.setAlignment(Qt.AlignRight)
        self.lblFolder.setGeometry(20, 80, 120, 25)
 
        self.pathToSaveImage = textEditFolder(self)
        self.pathToSaveImage.initTextEdit(360, 40, 150, 80,  "pathToSaveImage", True, False, True, False, True)
        self.pathToSaveImage.setStyleSheet(self.styleTextEditDisaBled)
        self.pathToSaveImage.setText(self.initDir)

        self.getFolderButton = funnyPushButton(self)
        self.getFolderButton.initPushButton(28, 28, 520, 80, "getFolderButton", "", translateMsg("Select a folder"), True, getThemeIcon("folder.png"), 28, 28, True)

        self.getFolderButton.clicked.connect(self.getFolder)

        self.listExtension.currentTextChanged.connect(self.updateExtension)
        self.saveButton.clicked.connect(self.createFilesImages)
        self.closeButton.clicked.connect(self.close)

    def updateExtension(self):
        widgets = (self.nameFirstImage, self.nameSecondImage)
        for widget in widgets :
            if widget.text().find(".") == 0 : widget.setText("%s.%s" % (widget.text(), self.listExtension.currentText()))
            else :
               extension = widget.text().split(".")[-1]
               widget.setText("%s%s" % (widget.text()[:-3], self.listExtension.currentText()))
            widget.checkRegExp()              
        

    def closeEvent(self, event):
        self.parent.initDir = self.initDir

    def getFolder(self):
        if self.sender() == None: return
        if self.sender() == self.getFolderButton : obj = self.pathToSaveImage
        else: return

        windowIcon(self, "folder.png")

        self.initDir = dirname(__file__) if obj.toPlainText() == "" else dirname(obj.toPlainText())
        title = translateMsg("Select the folder")

        fileDialog = QFileDialog(self, title)
        fileDialog.setDirectory(self.initDir)
        fileDialog.setFileMode(QFileDialog.Directory)
        fileDialog.setOption(QFileDialog.ShowDirsOnly, False)
        #NEW 3.6.0
        #fileDialog.setOption(QFileDialog.DontUseNativeDialog)
        fileDialog.setNameFilters(self.authorizedMime)
        fileDialog.selectNameFilter(self.authorizedMime[0])

        fixeLabelsFileDialog(self, fileDialog, 0, False) 

        if fileDialog.exec_():
            inputDir = fileDialog.selectedFiles()[0]
            obj.setPlainText(cleanPath(inputDir.replace("\\", "/")))
            self.initDir = obj.toPlainText()

        
    def createFilesImages(self):

        folder = self.pathToSaveImage.toPlainText()
        fileName1 = self.nameFirstImage.text()
        fileName2 = self.nameSecondImage.text()
        extension = self.listExtension.currentText().upper()

        if folder == "" : return
        if fileName1 == fileName2 : return

        fileName = join(folder, fileName1) 
        self.parent.mapCanvas1.saveAsImage(fileName, None, extension)

        fileNameDouble = join(folder , fileName2) 
        self.parent.mapCanvas2.saveAsImage(fileNameDouble, None, extension)

        return fileName, fileNameDouble


class lineEditNameFile(QLineEdit):
      def __init__(self, *args):
          super(lineEditNameFile, self).__init__(*args)
          self.regex = QRegExp(r"^[\w\-\. ]+$", Qt.CaseSensitive)
          
      def initCtrlWidget(self, widgetCtrl, extension):
          self.widgetCtrl = widgetCtrl
          self.extension = extension

      def checkRegExp(self):
          self.setStyleSheet("background-color:red;")
          self.widgetCtrl.setEnabled(False)
          cond = self.regex.exactMatch(self.text())
          if self.text().find(".") == 0 : return
          extension = self.text().split(".")[-1]
          if cond and extension.lower() == self.extension.currentText().lower() : #"png" :
             self.setStyleSheet("background-color:#AEEE00;")
             self.widgetCtrl.setEnabled(True)
             
          
#NEW 3.0.0
class myListWidget(QListWidget):
    def __init__(self, parent=None):
        QListWidget.__init__(self, parent)
        self.parent = parent.parent()

    def dropEvent(self, event):
        super(myListWidget, self).dropEvent(event)
        self.parent.updateListFiles()
        self.parent.updateMapViewerWithGrid()

class textEdit(QTextEdit):
      def __init__(self, parent, *args):
          super(textEdit, self).__init__(*args)
          self.parent = parent
          
      def focusOutEvent(self, event): self.parent.updateInfo(self)


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



class wizardData(QDialog):
    def __init__(self, parent):
        QDialog.__init__(self)
        self.parent = parent
        self.setupUi()
    
    def setupUi(self):
        self.setObjectName("ui_wizardData")
        self.maxWidth, self.maxheight = 400, 350 
        self.setMinimumSize(self.maxWidth, self.maxheight)
        self.setMaximumSize(self.maxWidth, self.maxheight)
        self.resize(self.maxWidth, self.maxheight) 
        windowIcon(self, "bggroup.png")

        self.setWindowTitle(translateMsg("Select group raster"))


        self.groupsViewer = None
        self.groupIconPath = getThemeIcon("group.png").replace("\\","/")
        self.groupIcon = QIcon(self.groupIconPath)

        self.applyButton = QPushButton(self)
        self.applyButton.setObjectName("applyButton")
        self.applyButton.setText(translateMsg("Validate"))

        self.closeButton = QPushButton(self)
        self.closeButton.setObjectName("closeButton")
        self.closeButton.setText(translateMsg("Close"))

        self.closeButton.clicked.connect(self.close)

        sender = self.parent.sender()        
        
        self.getGroupsViewer(True)
        if self.groupsViewer :
           self.identifyGroup(self.parent.groupRaster.toPlainText())  
           self.groupsViewer.itemDoubleClicked.connect(self.setValueForGroupRaster)
           self.applyButton.clicked.connect(self.setValueForGroupRaster)


    def getGroupsViewer(self, getGroups):
        self.groupsViewer = QTreeWidget(self)
        self.groupsViewer.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.groupsViewer.setObjectName("groupsViewer")
        self.groupsViewer.headerItem().setText(0, "1")
        self.groupsViewer.header().setVisible(False)
        self.groupsViewer.header().setDefaultSectionSize(200)
        self.groupsViewer.setStyleSheet("QTreeWidget { font-size:12px; color: black; background-color: rgba(255, 255, 125, 50); border-left-width: 1px; border-left-color: black;  border-left-style: solid;  border-right-color: black; border-right-width: 1px; border-right-style: solid; border-right-radius: 3px;}"
                                       "QTreeWidget::item:selected {background-color: #5D5D5D; color: rgb(255,255,255); }")
        self.groupsViewer.setVisible(True)
        self.groupsViewer.setItemsExpandable(True)
        self.groupsViewer.setExpandsOnDoubleClick(True)
        self.groupsViewer.setContextMenuPolicy(Qt.NoContextMenu)

        self.populateGroupsViewer(getGroups)


    def identifyGroup(self, txt) :
        if txt != "" :
           items = self.groupsViewer.findItems(txt, Qt.MatchContains|Qt.MatchRecursive, 0) 
           if items :
              if items[0] : self.groupsViewer.setCurrentItem(items[0])

    
    def setValueForGroupRaster(self):
        self.parent.groupRaster.setPlainText(self.groupsViewer.currentItem().text(0))
        self.parent.updateInfo(self.parent.groupRaster)
        self.close()

    def introspectNodes(self, group, nodes, parent, getGroups):
        for node in nodes:
                if QgsLayerTree.isGroup(node): 
                   legendItem = createTreeWidgetItem(self.groupIconPath, self.groupIcon, node.name())
                   conditionnalAddChild(self.groupsViewer, parent, legendItem)
                   legendItem.setExpanded(node.isExpanded())
                   self.introspectNodes(node, node.children(), legendItem, getGroups)        


    def populateGroupsViewer(self, getGroups):
        if not self.groupsViewer : return
        self.groupsViewer.clear()
        root = QgsProject.instance().layerTreeRoot() 
        if getGroups : self.introspectNodes(root, root.children(), None, getGroups)
        else :
            listLayers = QgsProject.instance().mapLayers()
            dictLayers = {}
            for key in listLayers :
                layer = listLayers[key]
                if not layer.name() in dictLayers.keys() : dictLayers[layer.name()]=key
            
            iconTypes = {0: (self.pointIcon, self.pointIconPath) , 1 : (self.lineIcon, self.lineIconPath),  2: (self.polygonIcon, self.polygonIconPath)}
        
            for layerName in sorted(dictLayers) :
                key = dictLayers[layerName]
                layer = listLayers[key]
                if layer.name()!= "tempo" and type(layer) == QgsVectorLayer :
                   
                   typeGeom = layer.geometryType()
                   if dicoHasKey(iconTypes, typeGeom) : icon, iconPath = iconTypes[typeGeom][0], iconTypes[typeGeom][1]
                   else  :  icon, iconPath = self.unknowIcon, self.unknowIconPath
                    
                   legendItem = createTreeWidgetItem(iconPath, icon, layer.name())
                   conditionnalAddChild(self.groupsViewer, None, legendItem)    

    def close(self): self.reject()

    def resizeEvent(self,ev):
        self.groupsViewer.setGeometry(10, 10, self.width()-20, self.height()-60)
        self.applyButton.setGeometry(self.width()-230, self.height()-35, 100, 25)
        self.closeButton.setGeometry(self.width()-120, self.height()-35, 100, 25)
        

#NEW 3.2.0
from qgis.PyQt.QtWidgets import QStyledItemDelegate
from qgis.PyQt.QtGui import (QBrush, QColor, QFont, QStandardItemModel)
        
class GroupDelegate(QStyledItemDelegate):
    def initStyleOption(self, option, index):
        super(GroupDelegate, self).initStyleOption(option, index)
        if not index.data(Qt.UserRole):
            option.text = "   %s" % option.text


class GroupItem(QStandardItem):
    def __init__(self, text):
        super(GroupItem, self).__init__(text)
        self.setData(True, Qt.UserRole)
        self._number_of_childrens = 0
        font = QFont('Times New Roman', 10)
        font.setBold(True)
        font.setUnderline(True)
        font.setOverline(True)
        self.setFont(font)
        self.setFlags(self.flags() & ~Qt.ItemIsSelectable)

    def addChild(self, text):
        it = QStandardItem(text)        
        it.setData(False, Qt.UserRole)
        self._number_of_childrens += 1
        self.model().insertRow(self.row() + self._number_of_childrens, it)
        return it

class GroupComboBox(QComboBox):
    def __init__(self, parent=None):
        super(GroupComboBox, self).__init__(parent)
        self.setModel(QStandardItemModel(self))
        delegate = GroupDelegate(self)
        self.setItemDelegate(delegate)
        self.setIconSize(QSize(24, 24))
        self.iconGroup = QIcon(getThemeIcon("group.png"))
        self.iconChild = QIcon(getThemeIcon("raster.png"))

    def addGroup(self, model, text):
        it = GroupItem(text)
        it.setBackground(QBrush(QColor(25, 230, 240, 200)))
        model.appendRow(it)
        self.setItemIcon(self.count()-1, self.iconGroup)
        return it

    def addChild(self, text):
        it = QStandardItem(text)
        it.setData(True, Qt.UserRole)
        self.model().appendRow(it)
        self.setItemIcon(self.count()-1, self.iconChild)
        return it        

#NEW 3.3.0
def getGroupForTheLayer(mapCanvasLayer):      
    root = QgsProject.instance().layerTreeRoot()
    groupLayer = None
    if not mapCanvasLayer : return None
    if not isinstance(mapCanvasLayer, QgsRasterLayer) : return None
    for layer in root.findLayers() :
        if isinstance(layer.layer(), QgsRasterLayer) :                
           if layer.layer().id() == mapCanvasLayer.id() :
              if type(layer.parent()) == QgsLayerTreeGroup : groupLayer = layer.parent() ; break
    return groupLayer
    
class layersComboBox(QFrame):
    def __init__(self, parent, objectName, mapViewerLayer, scanVisibility):
        super(layersComboBox, self).__init__(parent)
        self.parent = parent
        self.objectName = objectName
        self.mapViewerLayer = mapViewerLayer
        self.scanVisibility = scanVisibility
        self.imgProj = join(dirname(__file__), "icons/projection.png")
        self.imgGroupe = join(dirname(__file__), "icons/group.png")
        
        self.layer = None
        self.layerGroup = None
        self.includeGroup = False
        
        self.setStyleSheet("QFrame{color: black; background-color: rgba(255, 255, 125, 50); border: 1px solid; border-radius: 5px; background-color: rgba(255, 255, 255, 210);")

        self.layerLabel = QTextEdit(self)
        self.layerLabel.setText("%s !" % translateMsg("Please select a layer"))
        self.layerLabel.setEnabled(False)
        self.layerLabel.setStyleSheet("QTextEdit{font-size:10px; color: black; background-color: rgba(255, 255, 125, 50); border-left-width: 1px; border-left-color: black;  border-left-style: solid;  border-right-color: black; border-right-width: 1px; border-right-style: solid; border-right-radius: 3px;}")
        self.installEventFilter(self)   
        
        self.buttonSelLayer = funnyPushButton(self) 
        self.buttonSelLayer.initPushButton(20, 20, 40, 90, "buttonSelLayer", "", "%s : %s" % (translateMsg("Select Master layer for Map"), self.mapViewerLayer.objectName()), True, getThemeIcon("layers-icon.png"), 18, 18, True)
        self.buttonSelLayer.clicked.connect(self.getLayerForCombo)

    def eventFilter(self, obj, event):
        if obj :
           if obj == self :
              if event.type() == event.MouseButtonDblClick :self.buttonSelLayer.clicked.emit(); return True
        return False

    def setLayer(self):
        if self.layer :           
           self.layerGroup = getGroupForTheLayer(self.layer)
           self.layerLabel.setHtml("<table><tr valign='middle'><td valign='middle'><b>%s</b> %s : %s, %s : %s</td></tr></table>" % (self.layer.name(),
                                                                     "<img src='file:///{}' width='{}' height='{}'>".format(self.imgProj, 13, 13),
                                                                     self.layer.crs().authid(),
                                                                     "<img src='file:///{}' width='{}' height='{}'>".format(self.imgGroupe, 20, 20),
                                                                     self.layerGroup.name() if self.layerGroup else "Aucun" ))
           self.layerLabel.setToolTip(self.layer.id())
           self.mapViewerLayer.refresh() 
          
    def setLayerGroup(self) :
        if self.layer : self.layerGroup = getGroupForTheLayer(self.layer)

    def getLayerName(self) : return self.layer.name()
    def getLayerSource(self) : return self.layer.source()
    def getLayerCrs(self) : return self.layer.crs()
    def getLayerGroup(self) : return self.layerGroup

    def resizeEvent(self, event):
        self.layerLabel.setGeometry(5, 2, self.width(), 25)
        self.buttonSelLayer.setGeometry(self.layerLabel.width()-35, 5, 25, 25)
        

    def getLayerForCombo(self) :
        self.dialogLayer = myLayerTreeView(self, self.parent, self.mapViewerLayer, self.scanVisibility, self.layer) 
        self.dialogLayer.exec_()




class myLayerTreeView(QDialog):
      
      def __init__(self, parent, ihm, mapViewerLayer, scanVisibility, layer):
        super(myLayerTreeView, self).__init__()  
        self.setObjectName("uiMyLayerTreeView")
        self.parent = parent
        self.ihm = ihm
        self.mapViewerLayer = mapViewerLayer
        self.layer = layer
        
        self.resize(500, 500)
        self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint)
        self.setWindowTitle(translateMsg("Double glass viewer"))
        windowIcon(self, "layers-icon.png")
        self.setWindowTitle(self.parent.sender().toolTip())


        self.groupIconPath = getThemeIcon("group.png").replace("\\","/")
        self.groupIcon = QIcon(self.groupIconPath)
        self.iconPathVectorLayer = getThemeIcon("polygon.png").replace("\\","/")
        self.iconVectorLayer = QIcon(self.iconPathVectorLayer)
        self.iconPathRasterLayer = getThemeIcon("raster.png").replace("\\","/")
        self.iconRasterLayer = QIcon(self.iconPathRasterLayer)        
        self.iconPathRasterLayerOut = getThemeIcon("raster_out.png").replace("\\","/")
        self.iconRasterLayerOut = QIcon(self.iconPathRasterLayerOut)

        self.styleSheetPushButton = "QPushButton::checked {icon-size: 48px, 48px; border-width: 5px; border-radius: 6px; border-color: black; background-color : #58a41c; border-right-color: black;}"
        self.styleSheetPushButton+= "QPushButton {icon-size: 48px, 48px; border-width: 0px; border-radius: 10px; }"

        self.mapTarget = QButtonGroup(self)
        self.mapTarget.setExclusive(True)
        self.butMap1 = QPushButton("%s 1" % translateMsg("MapCanvas"), self)
        self.butMap1.setCheckable(True)        
        self.butMap1.setStyleSheet(self.styleSheetPushButton)
        self.butMap2 = QPushButton("%s 2" % translateMsg("MapCanvas"), self)
        self.butMap2.setCheckable(True)
        self.butMap2.setStyleSheet(self.styleSheetPushButton)
        self.mapTarget.addButton(self.butMap1, 1)
        self.mapTarget.addButton(self.butMap2, 2)

        self.butMap1.setChecked(True) if self.parent == self.ihm.listLayers1 else self.butMap2.setChecked(True)

        icon = getThemeIcon("reload.png")
        toolTip = translateMsg("Reload layers from current project")
        self.reloadData = funnyPushButton(self)
        self.reloadData.initPushButton(24, 24, self.width()-160, self.height()-30, "reloadData", "", toolTip, True, icon, 24, 24, True)

        self.buttonExpandAllNodes = funnyPushButton(self) 
        self.buttonExpandAllNodes.initPushButton(24, 24, self.width()-80, 5, "buttonExpandAllNodes", "", translateMsg("Expand all nodes"), True, getThemeIcon("nodes_expand.png"), 15, 15, True)

        self.buttonReduceAllNodes = funnyPushButton(self) 
        self.buttonReduceAllNodes.initPushButton(24, 24, self.width()-60, 5, "buttonReduceAllNodes", "", translateMsg("Close all nodes"), True, getThemeIcon("nodes_reduce.png"), 15, 15, True)

        icon = getThemeIcon("add.png")
        toolTip = "%s" % translateMsg("Add layers")
        self.addPermanentLayers = funnyPushButton(self)
        self.addPermanentLayers.initPushButton(24, 24, self.width()-160, self.height()-30, "addPermanentLayers", "", toolTip, True, icon, 24, 24, True)   

        icon = getThemeIcon("del.png")
        toolTip = "%s" % translateMsg("Delete layers")
        self.delPermanentLayers = funnyPushButton(self)
        self.delPermanentLayers.initPushButton(24, 24, self.width()-160, self.height()-30, "delPermanentLayers", "", toolTip, True, icon, 24, 24, True)  

        self.viewer = QTreeWidget(self)
        self.viewer.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.viewer.setObjectName("viewer")
        self.viewer.headerItem().setText(0, "1")
        self.viewer.header().setVisible(False)
        self.viewer.header().setDefaultSectionSize(200)
        self.viewer.setStyleSheet("QTreeWidget { font-size:12px; color: black; background-color: rgba(255, 255, 125, 50); border-left-width: 1px; border-left-color: black;  border-left-style: solid;  border-right-color: black; border-right-width: 1px; border-right-style: solid; border-right-radius: 3px;}"
                                  "QTreeWidget::item:selected {background-color: #5D5D5D; color: rgb(255,255,255); }")
        self.viewer.setVisible(True)
        self.viewer.setItemsExpandable(True)
        self.viewer.setExpandsOnDoubleClick(True)
        self.viewer.setContextMenuPolicy(Qt.NoContextMenu)

        self.includeGroup = QCheckBox(self)
        self.includeGroup.setText(translateMsg("Extend the resource to the group"))
        self.includeGroup.setEnabled(False) if self.parent == self.ihm.listLayers1 else self.includeGroup.setEnabled(True)
        self.includeGroup.setCheckState(False)             

        self.applyButton = QPushButton(self)
        self.applyButton.setObjectName("applyButton")
        self.applyButton.setText(translateMsg("Validate"))

        self.closeButton = QPushButton(self)
        self.closeButton.setObjectName("closeButton")
        self.closeButton.setText(translateMsg("Close"))
        self.closeButton.clicked.connect(self.close)

        self.populateGroupsViewer(True)

        self.viewer.itemDoubleClicked.connect(self.setValueForGroupRaster)
        self.includeGroup.stateChanged[int].connect(self.setValueForGroupRaster)
        self.applyButton.clicked.connect(self.setValueForGroupRaster)
        #NEW 3.3.0
        self.mapTarget.buttonClicked[int].connect(self.updatePopulate)
        self.buttonExpandAllNodes.clicked.connect(self.expandTreeWidget)
        self.buttonReduceAllNodes.clicked.connect(self.expandTreeWidget)                
        self.addPermanentLayers.clicked.connect(self.ihm.addLayersToMapCanvas)
        self.delPermanentLayers.clicked.connect(self.ihm.delLayersFromMapCanvas)
        self.reloadData.clicked.connect(self.updatePopulate)


      def expandTreeWidget(self):
          if self.sender().objectName() == "buttonExpandAllNodes" : self.viewer.expandAll()
          else : self.viewer.collapseAll()
      

      def updatePopulate(self, idButton):
          self.populateGroupsViewer(True)
          self.includeGroup.setEnabled(False) if idButton == 1 else self.includeGroup.setEnabled(True)
          self.setWindowTitle("%s : %s" % (translateMsg("Select Master layer for Map"), idButton))

      def introspectNodes(self, group, nodes, parent, getGroups):
        transformer, geomTargetExtent = None, None
        scanVisibility = self.butMap2.isChecked()
        if scanVisibility :
           geomTargetExtent = self.ihm.mapCanvas1.extent()
           if self.ihm.mapCanvas1.layers() :
              refCrs = self.ihm.mapCanvas1.layers()[0].crs()
              transformer = QgsCoordinateTransform()
              transformer.setDestinationCrs(refCrs)  

           
        for node in nodes:
            if QgsLayerTree.isGroup(node):
               if node.children() : 
                   legendItem = createTreeWidgetItem(None, self.groupIcon, node.name())
                   conditionnalAddChild(self.viewer, parent, legendItem)
                   legendItem.setExpanded(False)
                   self.introspectNodes(node, node.children(), legendItem, getGroups) 
            elif QgsLayerTree.isLayer(node):
                   if type(node) == QgsLayerTreeLayer : layer = node.layer()
                   elif type(node) == QgsLayerTreeNode :
                        try : layer = node.checkedLayers()[0]
                        except : layer = None
                   else : layer = None
                   icon = self.iconRasterLayer
                   if layer :
                       
                      if type(layer) == QgsRasterLayer :
                         if scanVisibility :
                            if transformer :
                               extent = layer.extent()
                               if layer.crs() != refCrs :
                                   transformer.setSourceCrs(layer.crs())
                                   extent = transformer.transform(extent, QgsCoordinateTransform.ForwardTransform)
                                   
                            if self.ihm.mapCanvas1.layers() :      
                               if not extent.intersects(geomTargetExtent) : icon = self.iconRasterLayerOut                            
                    
                         legendItem = createTreeWidgetItem(layer.id(), icon, node.name())
                         conditionnalAddChild(self.viewer, parent, legendItem)

                         if self.layer :  
                            if layer == self.layer : self.viewer.setCurrentItem(legendItem)
      
        
      def populateGroupsViewer(self, getGroups):
        if not self.viewer : return
        self.viewer.clear()
        root = QgsProject.instance().layerTreeRoot() 
        self.introspectNodes(root, root.children(), None, getGroups)

      def close(self): self.reject()
      
      def resizeEvent(self, event):
          self.butMap1.setGeometry(10, 10, 120, 30)
          self.butMap2.setGeometry(130, 10, 120, 30)
          self.buttonExpandAllNodes.setGeometry(260, 10, 25, 25)
          self.buttonReduceAllNodes.setGeometry(300, 10, 25, 25)          
          self.addPermanentLayers.setGeometry(340, 10, 25, 25)
          self.delPermanentLayers.setGeometry(380, 10, 25, 25)
          self.reloadData.setGeometry(420, 10, 25, 25)
          self.viewer.setGeometry(10, 60, self.width()-10, self.height()-130)
          self.includeGroup.setGeometry(10, self.height()-65, self.width()-10, 25) 
          self.applyButton.setGeometry(self.width()-230, self.height()-35, 100, 25)
          self.closeButton.setGeometry(self.width()-120, self.height()-35, 100, 25)


      def setValueForGroupRaster(self):
          if not self.viewer : return
          if not self.viewer.currentItem() : return
          if self.viewer.currentItem().whatsThis(0) :
             layer = QgsProject.instance().mapLayer(self.viewer.currentItem().whatsThis(0))
             if layer :
                #NEW 3.3.0
                self.parent = self.ihm.listLayers1 if self.butMap1.isChecked() else self.ihm.listLayers2
                self.parent.layer = layer
                self.parent.includeGroup = (self.includeGroup.isChecked() and self.includeGroup.isEnabled())
                self.parent.setLayer()

                
                
