# -*- coding: iso-8859-1 -*-

import datetime
import locale
import os

try: from osgeo import gdal
except : import gdal
try: from osgeo import ogr
except : import ogr

from qgis.core import (QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsFeature, QgsField, QgsFields, Qgis, QgsGeometry, QgsPointXY, QgsProject, QgsRasterLayer,
                       QgsRectangle, QgsVectorLayer, QgsVectorFileWriter)
from qgis.gui import (QgsBusyIndicatorDialog, QgsCollapsibleGroupBox, QgsMapCanvas, QgsMapTool, QgsMapToolPan, QgsMapToolZoom, QgsMessageBar, QgsProjectionSelectionWidget, QgsRubberBand)

from qgis.PyQt.QtCore import (QItemSelectionModel, QObject, QProcess, QSettings, QSize, QTime, Qt, QVariant, pyqtSlot)
from qgis.PyQt.QtGui import (QIcon, QMovie)
from qgis.PyQt.QtWidgets import (QAbstractItemView, QAction, QApplication, QButtonGroup, QCheckBox, QDial, QDialog, QDialogButtonBox, QFileDialog, QGridLayout, QGroupBox,
                                 QHBoxLayout, QLabel, QLCDNumber, QListWidget, QMenu, QMessageBox, QProgressBar, QRadioButton, QSizePolicy , QTabWidget,
                                 QTextEdit, QToolBar, QVBoxLayout, QWidget)

from math import ceil

from autoLoaderRaster.utils import (editor, funnyPushButton, makeListFormatsExtensions, myPushButton, progressBar, textEditFolder, translateMsg)
from autoLoaderRaster.utils import (changeButtonIcon, cleanPath, fixeLabelsFileDialog, getThemeIcon, windowIcon, labeller, zoomNextExtent, zoomPreviousExtent) #NEW 3.6.4


class ui_gridRasterMaker(QDialog):

    def __init__(self, iface, parent):
        QDialog.__init__(self, None, Qt.WindowType.WindowStaysOnTopHint)
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        self.project = QgsProject(self).instance()
        self.parent = parent
        self.setupUi()

    def setupUi(self):
        self.setObjectName("ui_gridRasterMaker")
        self.minwidth, self.minheight = 1000, 840
        self.setMinimumSize(self.minwidth, self.minheight)
        self.resize(self.minwidth, self.minheight)
        self.ractitle = "ALR - %s" % translateMsg("Grid Raster Maker")
        self.setWindowTitle(self.ractitle)
        self.setWindowFlags(Qt.WindowType.WindowMinimizeButtonHint | Qt.WindowType.WindowMaximizeButtonHint | Qt.WindowType.WindowCloseButtonHint)
        
        self.startdate = None
        self.fullExtent = None
        windowIcon(self, "makegrid_on.png")

        self.pos = 0
        self.coordX, self.coordY = {}, {}
        self.transformer = self.getTransformer(27572, 2154) #27574, 2154)

        self.osEncoding = locale.getpreferredencoding()
        self.settings = 'jp2maker/'
        self.alrMakerGridSettings = ["folder"]
        
        self.fieldsDefinition = [("id", QVariant.LongLong, "integer", 12), ("fullname", QVariant.String, "string"), ("name", QVariant.String, "string")]
        self.fieldsDefinitionPoint = [("id", QVariant.LongLong, "integer", 12), ("fullname", QVariant.String, "string"), ("name", QVariant.String, "string"), ("extent", QVariant.String, "string") ]  

        self.titleConfirmation = translateMsg("Question")

        self.initDir = ""
        listExtensions = makeListFormatsExtensions(self, False, True, False)
        self.authorizedMime = ["*.%s" % extension for extension in listExtensions]
        
        self.dictExtensions = {}
        self.listprocess, self.listFilesJp2 = [], {}
        self.outprocess = []
        self.killing = False

        self.groupParams = QGroupBox(self)
        self.groupParams.setObjectName("groupParams")

        #=====================================================================
        #GROUP RASTER SOURCE
        #=====================================================================
        self.groupBoxDir = QGroupBox(self.groupParams)
        self.groupBoxDir.setObjectName("groupBoxDir")
        self.groupBoxDir.setTitle("%s : [ %s ]" % (translateMsg("Raster source"), translateMsg("Folder")))

        self.folder = textEditFolder(self.groupBoxDir)
        self.folder.initTextEdit(380, 25, 70, 20, "folder", True, False, True, False, True)
        self.folder.setStyleSheet("color: black; background-color: #D3D3D3")

        self.getFolderButton = funnyPushButton(self.groupBoxDir)
        self.getFolderButton.initPushButton(28, 28, 455, 20, "getFolderButton", "", translateMsg("Select a folder"), True, getThemeIcon("folder.png"), 28, 28, True)


        self.lblListFormats = QLabel(self.groupBoxDir)
        self.lblListFormats.setText("%s : " % (translateMsg("Type")))
        self.lblListFormats.setAlignment(Qt.AlignmentFlag.AlignRight)
        self.lblListFormats.setObjectName("lblListFormats")

        self.listFormats = QListWidget(self.groupBoxDir)
        self.listFormats.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
        self.listFormats.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
        self.listFormats.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
        self.listFormats.setObjectName("listFormats")

        self.lblFiles = QLabel(self.groupBoxDir)
        self.lblFiles.setText("%s : " % translateMsg("Files"))
        self.lblFiles.setAccessibleDescription(self.lblFiles.text())
        self.lblFiles.setAlignment(Qt.AlignmentFlag.AlignLeft)
        self.lblFiles.setObjectName("lblFiles")


        self.busyIndicator = progressBar(self.groupBoxDir)
        self.busyIndicator.setObjectName("busyIndicator")
        self.busyIndicator.setValue(0)
        self.busyIndicator.setVisible(False)


        self.listFiles = QListWidget(self.groupBoxDir)
        self.listFiles.setGeometry(200, 50, 250, 120)
        self.listFiles.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
        self.listFiles.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
        self.listFiles.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
        self.listFiles.setObjectName("listFiles")
        self.listFiles.setDragEnabled(False)
        self.listFiles.setAcceptDrops(False)
        self.listFiles.setDropIndicatorShown(False)
        self.listFiles.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)

        self.toolBarListFiles = QToolBar(self.listFiles)
        ctrlMap(self, self.toolBarListFiles, True, False, False, 5, 5, 200, 35)
        self.toolBarListFiles.setAllowedAreas(Qt.ToolBarArea.TopToolBarArea | Qt.ToolBarArea.BottomToolBarArea)


        self.movie = QMovie(getThemeIcon("attente.gif"))
        self.status_txt = QLabel(self.groupBoxDir)
        self.status_txt.setMovie(self.movie)
        self.status_txt.setLayout(QHBoxLayout())
        self.status_txt.layout().addWidget(QLabel(''))
        self.status_txt.setVisible(False)        


        #=====================================================================
        # GROUP PARAMS
        #=====================================================================
        self.groupBoxParams = QgsCollapsibleGroupBox(self.groupParams)
        self.groupBoxParams.setObjectName("groupBoxParams")
        self.groupBoxParams.setTitle("%s : [ %s ]" % (translateMsg("Params").lower(), translateMsg("Grid file")))
        self.groupBoxParams.setMinimumHeight(140)
        self.groupBoxParams.setMaximumHeight(140)

        self.lblTargetCrs = QLabel(self.groupBoxParams)
        self.lblTargetCrs.setGeometry(5, 35, 70, 25)
        self.lblTargetCrs.setText("%s : " % (translateMsg("SRS")))
        self.lblTargetCrs.setAlignment(Qt.AlignmentFlag.AlignRight)
        self.lblTargetCrs.setObjectName("lblTargetCrs")

        self.lblAddToMapCanvas = QLabel(self.groupBoxParams)
        self.lblAddToMapCanvas.setGeometry(5, 65, 70, 20)
        self.lblAddToMapCanvas.setText("%s : " % (translateMsg("File"))) 
        self.lblAddToMapCanvas.setAlignment(Qt.AlignmentFlag.AlignRight)
        self.lblAddToMapCanvas.setObjectName("lblAddToMapCanvas")  

        self.targetCrs = QgsProjectionSelectionWidget(self.groupBoxParams)
        self.targetCrs.setObjectName("targetCrs")
        #NEW 3.3.0
        crs = QSettings().value('/Projections/layerDefaultCrs')
        self.targetCrs.setCrs(QgsCoordinateReferenceSystem(crs))

        self.checkPointNotPolygon = QCheckBox(self.groupBoxParams)
        self.checkPointNotPolygon.setObjectName("checkPointNotPolygon")
        text = translateMsg("Point, not polygon")
        self.checkPointNotPolygon.setText(text)
        self.checkPointNotPolygon.setToolTip(text)
        self.checkPointNotPolygon.setGeometry(80, 65, 200, 20)
        
        self.checkAddToMapCanvas = QCheckBox(self.groupBoxParams)
        self.checkAddToMapCanvas.setObjectName("checkAddToMapCanvas")
        text = translateMsg("Add result to MapCanvas")
        self.checkAddToMapCanvas.setText(text)
        self.checkAddToMapCanvas.setToolTip(text)
        self.checkAddToMapCanvas.setGeometry(80, 90, 200, 20)


        icon = getThemeIcon("message.png")
        self.tabs = QTabWidget(self.groupParams)
        self.tabs.setTabsClosable(True)
        self.tabs.setDocumentMode(True)
        index = self.tabs.addTab(editor(self, False), QIcon(icon), "Console")
        self.tabs.setTabToolTip(index, "General console")
        self.edit = self.findChild(editor, self.objectName())


        self.groupViewer = QGroupBox(self)
        self.groupViewer.setObjectName("groupViewer")

        self.mapViewer = QgsMapCanvas(self.groupViewer)
        self.mapViewer.setObjectName("mapViewer")

        #NEW 3.6.0 - SINCE QGIS 3.36        
        self.rb = QgsRubberBand(self.mapViewer, Qgis.GeometryType.Polygon)
        #self.rb = QgsRubberBand(self.mapViewer)
        self.rb.setColor(Qt.GlobalColor.blue)        


        self.toolBarMapViewer = QToolBar(self.mapViewer)
        ctrlMap(self, self.toolBarMapViewer, True, False, False, 5, 5, 280, 35)
        self.toolBarMapViewer.setAllowedAreas(Qt.ToolBarArea.TopToolBarArea | Qt.ToolBarArea.BottomToolBarArea)

        self.closeButton = funnyPushButton(self.mapViewer)
        self.closeButton.initPushButton(128, 128, self.width()-140,  self.height()-140, "closeButton", "",  translateMsg("Close"), True, getThemeIcon("closeabout.png"), 128, 128, True)

        
        self.lcdClock = QLCDNumber(self.groupViewer)
        self.lcdClock.setGeometry(75, 160, 120, 30)
        self.lcdClock.setObjectName("lcdClock")
        self.lcdClock.setSegmentStyle(QLCDNumber.SegmentStyle.Filled)
        self.lcdClock.setStyleSheet("QLCDNumber {border: 2px solid grey; border-radius: 5px; background-color: #6C96C6; color: yellow;   text-align: center;}")
        self.lcdClock.setDigitCount(8)
        self.lcdClock.display(QTime.currentTime().toString("hh:mm:ss"))
        self.startTimer(1000)

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


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

        self.mapViewer.setMapTool(self.toolZoomIn)

        self.buttonAddLayerToMapView.clicked.connect(self.addToMapCanvas)
                            
        self.buttonNewProject.clicked.connect(self.newProject)
        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.buttonSendExtent.clicked.connect(self.sendExtentToMapCanvas)
        self.buttonPan.clicked.connect(self.pan)
        self.buttonInfosFile.clicked.connect(self.infosFile)

        self.getFolderButton.clicked.connect(self.getFolder)
        self.listFormats.itemClicked.connect(self.updateListFiles)
        self.listFormats.itemSelectionChanged.connect(self.updateListFiles)
        self.listFiles.itemDoubleClicked.connect(self.addToMapCanvas)
        
        self.folder.textChanged.connect(self.loadFilesforType)

        self.buttonZoomToLayerExtent.clicked.connect(self.zoomToLayerExtent)
        self.buttonUpdateListFiles.clicked.connect(self.udpdateListFiles)
        self.tabs.tabCloseRequested.connect(self.closeTabs)
        self.groupBoxParams.collapsedStateChanged.connect(self.resizeCollapsedGroupBox)

        #NEW 3.6.4
        self.extents, self.currentExtent = [], -1
        self.mapViewer.extentsChanged.connect(self.storeExtent)
        self.buttonClearExtents.clicked.connect(self.clearHistory)
        self.updateButtonZoomNextPrevious()

        self.closeButton.clicked.connect(self.closeDlg)
        self.loadSettings()

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

    def loadSettings(self):
        settings = QSettings()
        for elt in self.alrMakerGridSettings :
            value = settings.value("%s%s" % (self.settings, elt))
            obj = self.findChild(textEditFolder, elt)
            if obj : obj.setPlainText(value)
	

    def saveSettings(self):
        settings = QSettings()
        for elt in self.alrMakerGridSettings :
            obj = self.findChild(textEditFolder, elt)
            if obj : settings.setValue("%s%s" % (self.settings, elt), obj.toPlainText())


    def infosFile(self) : 
        indexfile = self.listFiles.currentRow()
        if indexfile < 0 : return
        fileName = "%s%s" % (self.folder.toPlainText(), self.listFiles.item(indexfile).text())
        self.edit.clear(); self.edit.append(gdal.Info(fileName))

       
    def contextMnuObj(self, obj):

            contextMenu = QMenu()
            
            if obj == self.buttonExtentActions :

                self.buttonDrawExtent = contextMenu.addAction(QIcon(getThemeIcon("draw.png")), translateMsg("Show extent for all files"))
                self.buttonDrawExtent.setObjectName("buttonDrawExtent")
                self.buttonDrawExtent.triggered.connect(self.drawExtentOfFiles)

                self.buttonEraseExtent = contextMenu.addAction(QIcon(getThemeIcon("erase.png")), translateMsg("Erase extent in the canvas"))
                self.buttonEraseExtent.setObjectName("buttonEraseExtent")
                self.buttonEraseExtent.triggered.connect(self.eraseExtent)

                contextMenu.addSeparator()

                self.buttonSaveExtent = contextMenu.addAction(QIcon(getThemeIcon("save.png")), "%s ..." % translateMsg("Save extent for all files in a GRID file (SHP)"))
                self.buttonSaveExtent.setObjectName("buttonSaveExtent")
                self.buttonSaveExtent.triggered.connect(self.saveExtentAsShpFile)


            elif obj == self.buttonListFilesActions :

                self.addrastertomapcanvasqgis = contextMenu.addAction(QIcon(getThemeIcon("addtomapcanvas.png")), "%s" %  translateMsg("Add file to QGIS project"))
                self.addrastertomapcanvasqgis.setObjectName("addrastertomapcanvasqgis")
                self.addrastertomapcanvasqgis.triggered.connect(self.addToMapCanvas)

                self.addallrastertomapcanvasqgis = contextMenu.addAction(QIcon(getThemeIcon("addalltomapcanvas.png")), "%s" % translateMsg("Add all files to QGIS project"))
                self.addallrastertomapcanvasqgis.setObjectName("addallrastertomapcanvasqgis")
                self.addallrastertomapcanvasqgis.triggered.connect(self.addAllToMapCanvas)

                indexSelectedItem = self.listFormats.selectionModel().currentIndex().row()
                
                mime = ""
                if indexSelectedItem >= 0:
                    mime = self.listFormats.model().index(indexSelectedItem, 0).data(Qt.ItemDataRole.DisplayRole)
                    if mime == ".vrt" :
                        contextMenu.addSeparator()
                        self.openraster = contextMenu.addAction(QIcon(getThemeIcon("openeditor.png")), translateMsg("Open file with editor"))
                        self.openraster.setObjectName("openraster")
                        self.openraster.triggered.connect(self.openEditor)

            obj.setMenu(contextMenu)

    def resizeCollapsedGroupBox(self, state) :
        
        if self.groupBoxParams.isCollapsed() : soustract = self.groupBoxDir.x() + self.groupBoxDir.height() + self.groupBoxParams.x()+40
        else : soustract = self.groupBoxDir.x() + self.groupBoxDir.height() + self.groupBoxParams.x()+self.groupBoxParams.height()+20

        self.tabs.setGeometry(10, soustract-10, self.groupParams.width()-20, self.groupParams.height()-soustract)

    def resizeEvent(self, ev):
        
        self.groupParams.setGeometry(5, 5, int(2*self.width()/5), self.height()-10)
        self.groupViewer.setGeometry( self.groupParams.width()+5, 5, self.width()- self.groupParams.width()-10, self.height()-10)
        
        self.mapViewer.setGeometry(10, 10, self.groupViewer.width()-20, self.groupViewer.height()-20)
        #NEW 3.6.4
        self.toolBarMapViewer.setGeometry(int(self.mapViewer.width()/2)-160, self.mapViewer.height()-70, 310, 80)
        
        self.lcdClock.setGeometry(self.groupViewer.width()-110, 0, 100, 35)
        
        
        self.groupBoxDir.setGeometry(5, 5, self.groupParams.width()-10, 290)
        
        self.folder.setGeometry(5, 15, self.groupBoxDir.width()-40, 25)
        self.getFolderButton.setGeometry(self.groupBoxDir.width()- 32, 12, 28, 28)

        self.lblListFormats.setGeometry(self.groupBoxDir.width()-170, 50, 60, 20)
        self.listFormats.setGeometry(self.groupBoxDir.width()-105, 50, 100, 45)
        self.lblFiles.setGeometry(5, 80, 80, 20)
        self.busyIndicator.setGeometry(90, 80, self.groupBoxDir.width()-200, 15)
        
        self.listFiles.setGeometry(5, 100, self.groupBoxDir.width()-10, 180)
        self.status_txt.setGeometry(int(self.groupBoxDir.width()/2)-50, int(self.groupBoxDir.height()/2)-59, 100, 118)
        self.toolBarListFiles.setGeometry(int(self.listFiles.width()/2)-140, self.listFiles.height()-70, 280, 80)

        self.groupBoxParams.setMaximumWidth(self.groupParams.width()-10)
        self.groupBoxParams.setMinimumWidth(self.groupParams.width()-10)
        self.groupBoxParams.setGeometry(5, 305, self.groupParams.width()-10, 140)
       
        self.targetCrs.setGeometry(80, 30, self.groupBoxParams.width()- 125, 25)

        self.resizeCollapsedGroupBox(self.groupBoxParams.isCollapsed())
        
        self.closeButton.setGeometry(self.mapViewer.width()-140, self.mapViewer.height()-140, 128, 128)

        self.barInfo.setGeometry(0, 0, self.width(), 90)



    def zoomToLayerExtent(self):
        index = self.listFiles.currentRow()
        if index < 0 : return
        fileName = "%s%s" % (self.folder.toPlainText(), self.listFiles.item(index).text())

        ds = gdal.Open(fileName)

        if ds.GetProjection().strip() == "" : self.mapViewer.zoomToFullExtent(); return
        
        minX, maxX = ds.GetGeoTransform()[0], (ds.RasterXSize*ds.GetGeoTransform()[1])+ds.GetGeoTransform()[0] 
        maxY, minY = ds.GetGeoTransform()[3], ds.GetGeoTransform()[3]+(ds.RasterYSize*ds.GetGeoTransform()[5])
        ds = None

        self.mapViewer.setExtent(QgsRectangle(minX, minY, maxX, maxY))
        self.mapViewer.refresh()

        
    def newProject(self): self.rb.reset(); self.mapViewer.setLayers([]); self.mapViewer.refresh()
    
    def zoomIn(self): self.mapViewer.setMapTool(self.toolZoomIn)
    def zoomOut(self): self.mapViewer.setMapTool(self.toolZoomOut) 
    def zoomAll(self): self.mapViewer.setExtent(self.fullExtent) if self.fullExtent else self.mapViewer.zoomToFullExtent() 
    #NEW 3.6.4
    def zoomPrevious(self):
        self.currentExtent = zoomPreviousExtent(self.currentExtent, self.extents, self.mapViewer)
        self.updateButtonZoomNextPrevious()
    def zoomNext(self):
        self.currentExtent = zoomNextExtent(self.currentExtent, self.extents, self.mapViewer)
        self.updateButtonZoomNextPrevious()
    def updateButtonZoomNextPrevious(self):
        self.buttonZoomPrevious.setEnabled(self.currentExtent > 0)
        self.buttonZoomNext.setEnabled(self.currentExtent < len(self.extents)-1)
        
    def pan(self): self.mapViewer.setMapTool(self.toolPan)
    def sendExtentToMapCanvas(self): 
        try :
           self.canvas.setExtent(self.mapViewer.extent())
           self.canvas.refresh()
        except : pass    

    def closeActions(self) : self.saveSettings()
    def closeDlg(self): self.closeActions(); self.reject()
    def closeEvent(self, event): self.closeActions()

    def processAreNotRunning(self):
        isProcessAreNotRunning = True
        for process in self.listprocess:
            if process.state() != QProcess.NotRunning:
                isProcessAreNotRunning = False
                break
        return isProcessAreNotRunning

    def closeTabs(self, index):
        if index > 0:
            processSenderName = self.tabs.tabToolTip(index)
            self.editprocess = self.findChild(editor, processSenderName)
            self.tabs.removeTab(index)
        else:
            msg = translateMsg("This console can't be close.")
            msg1 = translateMsg("Would you like to clear content ?")
            reply = QMessageBox.question(self, self.titleConfirmation, "%s\n%s" % (msg, msg1), QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No)
            if reply ==  QMessageBox.StandardButton.Yes : self.edit.clear()

    def getWidget(self, zCible):
        index, tab = -1, None
        for i in range(self.tabs.count()):
            if self.tabs.tabToolTip(i) == zCible:
                index = i
                self.tabs.setCurrentIndex(i)
                tab = self.tabs.currentWidget()
                break
        return index, tab

    def openEditor(self):
        index = self.listFiles.currentRow()
        if index >= 0:
            file = "%s%s" % (self.folder.toPlainText(), self.listFiles.item(index).text())
            os.startfile(file)

    def inQgisCurrentLayers(self, fileName):
        root = QgsProject.instance().layerTreeRoot()
        for layer in root.findLayers() :
            geoLayer = layer.layer()
            if type(geoLayer) == QgsVectorLayer :
                if fileName == os.path.realpath(geoLayer.source()) : return True, geoLayer.id()
        return False, None


    def addAllToMapCanvas(self):
        qgisProject = False
        try : qgisProject = (self.sender() == self.addallrastertomapcanvasqgis)
        except : pass
        for i in range(self.listFiles.count()): self.doAddToMapCanvas(i, qgisProject)

    def addToMapCanvas(self):
        index = self.listFiles.currentRow()
        qgisProject = False
        try : qgisProject = (self.sender() == self.addrastertomapcanvasqgis)
        except : pass        
        if index >= 0 : self.doAddToMapCanvas(index, qgisProject)

    def doAddToMapCanvas(self, index, qgisProject):
        fileJp2 = "%s%s" % (self.folder.toPlainText(), self.listFiles.item(index).text())
        layer = QgsRasterLayer(fileJp2, os.path.basename(fileJp2))
         
        if qgisProject : QgsProject.instance().addMapLayers([layer], qgisProject); self.canvas.refresh(); 
        else : self.project.addMapLayers([layer], False)
        
        self.mapViewer.setLayers([layer])
        self.zoomToLayerExtent()
        self.infosFile()

    def startMovie(self):
        self.status_txt.setVisible(True)
        self.movie.start()
        self.status_txt.repaint()

    def stopMovie(self):
        self.movie.stop()
        self.status_txt.setVisible(False)


    def timerEvent(self, e):
        try :
            if self.startdate != None:
                timedelta = datetime.datetime.now().replace(microsecond=0)-self.startdate
                msg = "%s [%s]" % (self.ractitle, timedelta)
                self.setWindowTitle(msg)
        except : pass
        
        try : self.lcdClock.display(QTime.currentTime().toString("hh:mm:ss"))
        except : pass


    def addLayer(self, fileJp2):
        try:
            layer = QgsRasterLayer(fileJp2, os.path.basename(fileJp2))
            self.project.addMapLayers([layer], False);
            self.mapViewer.setLayers([layer])
            self.mapViewer.refresh()
            
        except:
            msg1 = translateMsg("Add file to QGIS project")
            msg3 = translateMsg("Cannot open file")
            self.barInfo.pushMessage("%s :" % (self.windowTitle()), "%s :<br><b>%s</b>. <u><b>%s</b></u>." % (msg1, fileJp2, msg3), Qgis.Warning, 3)


        folder = self.folder.toPlainText()
        dirName = "%s/" % (os.path.dirname(fileJp2))
        if dirName == folder: self.udpdateListFiles()


    def udpdateListFiles(self):
        indexSelectedItem = self.listFormats.selectionModel().currentIndex()
        try : self.loadFilesforType()
        except : pass
        self.listFormats.selectionModel().setCurrentIndex(indexSelectedItem, QItemSelectionModel.ClearAndSelect)


    def getTypeFilesInVrt(self, fileVrt):
        mime = ".tif"
        f = open(fileVrt, "r")
        for line in f:
            if line.find("SourceFilename") != -1:
                tempo = line.split(".")
                mime = ".%s" % (tempo[1].replace("</SourceFilename>", ""))
                break
        f.close
        return mime

    def getFilesVrt(self, path):
        listFilesVrt = []
        folder = self.folder.toPlainText()
        for f in os.listdir(folder):
            if os.path.isfile(os.path.join(folder, f)):
                extension = os.path.splitext(f)[1]
                if extension == ".vrt" : listFilesVrt.append(os.path.join(folder, f))
        return listFilesVrt


    def loadFilesforType(self):
        if self.folder.toPlainText() == "" : return
        self.dictExtensions = {}
        self.listFormats.clear()

        folder = self.folder.toPlainText()
        if not os.path.exists(folder) : return
        
        for f in os.listdir(folder):
            if os.path.isfile(os.path.join(folder, f)):
                extension = os.path.splitext(f)[1].lower()
                if ("*%s" % (extension)) in self.authorizedMime:
                    if extension not in self.dictExtensions:
                        self.dictExtensions[extension] = []
                    self.dictExtensions[extension].append(f)
                    
        self.listFormats.addItems(self.dictExtensions.keys())
        if len(self.dictExtensions.keys()) > 0: self.listFormats.setCurrentRow(0)
        self.updateListFiles()


    def updateListFiles(self):
        indexSelectedItem = indexSelectedItem = self.listFormats.selectionModel().currentIndex().row()
        self.listFiles.clear()

        self.contextMnuObj(self.buttonListFilesActions)
        if indexSelectedItem >= 0:
            mime = self.listFormats.model().index(indexSelectedItem, 0).data(Qt.ItemDataRole.DisplayRole) 
            if mime in self.dictExtensions : self.listFiles.addItems(self.dictExtensions[mime])
              
        self.rb.reset()           
        self.lblFiles.setText("(%s) %s" % (self.listFiles.count(), self.lblFiles.accessibleDescription()))
        


    def getTransformer(self, sourceEpsgCode, targetEpsgCode):
        transformer = QgsCoordinateTransform()
        transformer.setSourceCrs(QgsCoordinateReferenceSystem(sourceEpsgCode))
        transformer.setDestinationCrs(QgsCoordinateReferenceSystem(targetEpsgCode))
        return transformer



    def saveExtentAsShpFile(self):

        if not self.targetCrs.crs().isValid() : return
        if not self.targetCrs.crs().authid().startswith("EPSG") : return
        
        title = QApplication.translate("jp2maker", "Save as a file")
        self.initDir = os.path.dirname(__file__) if self.folder.toPlainText() == "" else self.folder.toPlainText()

        fileDialog = QFileDialog(self, title)
        fileDialog.setNameFilters(("*.shp", ))
        fileDialog.selectNameFilter("*.shp")
        fileDialog.setViewMode(QFileDialog.ViewMode.Detail)
        fileDialog.setDirectory(self.initDir)
        fileDialog.setAcceptMode(QFileDialog.DialogLabel.AcceptSave)

        fixeLabelsFileDialog(self, fileDialog, 1, False)
        windowIcon(self, "save.png")
        fileDialog.selectFile("")
        
        if fileDialog.exec():
            fileName = fileDialog.selectedFiles()[0]
            isLoaded, layerId = self.inQgisCurrentLayers(os.path.realpath(fileName))
            layerName = os.path.splitext(os.path.basename(fileName))[0]

            if isLoaded :
                QgsProject.instance().removeMapLayer(layerId)
                self.canvas.refresh()
            

            self.busyIndicator.setVisible(True)
            if os.path.exists(fileName) : ogr.GetDriverByName('ESRI Shapefile').DeleteDataSource(fileName)

            pointNotPolygon = self.checkPointNotPolygon.isChecked()

            if pointNotPolygon : layerShp = QgsVectorLayer("Point?crs=%s" % self.targetCrs.crs().authid(), "gridraster", "memory")
            else : layerShp = QgsVectorLayer("Polygon?crs=%s" % self.targetCrs.crs().authid(), "gridraster", "memory")
            
            provider = layerShp.dataProvider()

            layerShp.startEditing()

            #NEW 2.2
            if pointNotPolygon :  fieldsDefinition = self.fieldsDefinitionPoint
            else : fieldsDefinition = self.fieldsDefinition

        
            fields = QgsFields()   
            for i in range(len(fieldsDefinition)) :
                field = fieldsDefinition[i]
                #NEW 2.2
                if len(field)== 5 : fields.append(QgsField(field[0], field[1], field[2], field[3], field[4]))
                elif len(field)== 4 : fields.append(QgsField(field[0], field[1], field[2], field[3]))
                else : fields.append(QgsField(field[0], field[1]))
            provider.addAttributes(fields) 
    
            feature = QgsFeature()

            bounds = self.listFiles.count()
            folder = self.folder.toPlainText()
            
            for i in range(bounds):
                    self.busyIndicator.setValue(int(100 * i/bounds))
                    self.busyIndicator.repaint()
                    name = self.listFiles.item(i).text()
                    fileNameRaster = "%s%s" % (folder, name)
                    ds = gdal.Open(fileNameRaster)
                    minX, maxX = ds.GetGeoTransform()[0], (ds.RasterXSize*ds.GetGeoTransform()[1])+ds.GetGeoTransform()[0] 
                    maxY, minY = ds.GetGeoTransform()[3], ds.GetGeoTransform()[3]+(ds.RasterYSize*ds.GetGeoTransform()[5])
                    ds = None

                    #NEW 2.2
                    if pointNotPolygon :
                       point = QgsPointXY(minX+((maxX-minX)/2), maxY+((minY-maxY)/2))
                       geom = QgsGeometry().fromPointXY(point)
                       geomExtent = self.rbRectangle(self.rb, minX, maxX, maxY, minY, True).asWkt(12)
                    else : geom = self.rbRectangle(self.rb, minX, maxX, maxY, minY, True)
                    #NEW 2.2                    
                    if pointNotPolygon : attributes = [i+1, fileNameRaster, name, geomExtent]
                    else : attributes = [i+1, fileNameRaster, name]
                    
                    feature.setGeometry(geom)
                    feature.setAttributes(attributes)

                    provider.addFeatures([ feature ] )
                    layerShp.updateExtents()


            layerShp.commitChanges()

    
            crs = QgsCoordinateReferenceSystem(self.targetCrs.crs().authid())
            writer = QgsVectorFileWriter.writeAsVectorFormat(layerShp, fileName, "utf-8", crs, "ESRI Shapefile", skipAttributeCreation=False)
                                                     

        self.busyIndicator.setValue(0)        
        self.busyIndicator.setVisible(False)
        windowIcon(self, "jp2maker_ico.png")   

    def eraseExtent(self): self.rb.reset()
    
    def drawExtentOfFiles(self):
        self.busyIndicator.setVisible(True)
        self.rb.reset()
        extXmin, extXMax, extYMin, extYMax = 10000000000000, 0, 10000000000000, 0
        bounds = self.listFiles.count()
        for i in range(bounds):
                self.busyIndicator.setValue(int(100 * i/bounds))
                self.busyIndicator.repaint()
                fileName = "%s%s" % (self.folder.toPlainText(), self.listFiles.item(i).text())
                ds = gdal.Open(fileName)
                minX, maxX = ds.GetGeoTransform()[0], (ds.RasterXSize*ds.GetGeoTransform()[1])+ds.GetGeoTransform()[0] 
                maxY, minY = ds.GetGeoTransform()[3], ds.GetGeoTransform()[3]+(ds.RasterYSize*ds.GetGeoTransform()[5])
                ds = None
                self.rbRectangle(self.rb, minX, maxX, maxY, minY, True)

                extXmin = min(extXmin, minX)
                extXMax = max(extXMax, maxX)
                extYMin = min(extYMin, minY)
                extYMax = max(extYMax, maxY)

        self.fullExtent = QgsRectangle(extXmin, extYMin, extXMax, extYMax)
        self.mapViewer.setExtent(self.fullExtent)
        self.mapViewer.refresh()

        self.busyIndicator.setValue(0)        
        self.busyIndicator.setVisible(False)


    def rbRectangle(self, rb, x1, x2, y1, y2, toDraw):
        coords = []
        
        coords.append(QgsPointXY(x1, y1))
        coords.append(QgsPointXY(x1, y2))
        coords.append(QgsPointXY(x2, y2))
        coords.append(QgsPointXY(x2, y1))
        coords.append(QgsPointXY(x1, y1))

        geom = QgsGeometry().fromPolygonXY([coords])
        
        if toDraw : rb.addGeometry(geom)

        return geom
    


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

        windowIcon(self, "folder.png")

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

        fileDialog = QFileDialog(self, title) 
        fileDialog.setDirectory(self.initDir)
        fileDialog.setFileMode(QFileDialog.FileMode.Directory)
        fileDialog.setOption(QFileDialog.Option.ShowDirsOnly, False)
        #NEW 3.6.0
        #fileDialog.setOption(QFileDialog.Option.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("\\", "/")))

        
        windowIcon(self, "catchraster.png")


def ctrlMap(self, conteneur, complete, getPointsForExtent, simply, iX, iY, iW, iH):
        
         self.groupMap = QGroupBox(conteneur)
         self.groupMap.setStyleSheet("QGroupBox { border: 1px solid;    border-radius: 5px;    opacity: 0.5;    background-color: rgba(255, 255, 255, 50);}")

         self.actionsMapCanvas = QButtonGroup(conteneur) 
         self.actionsMapCanvas.setExclusive(True)
         sizeWidth = 0
         
         if conteneur == self.toolBarListFiles :
             dicoCtrls = {"buttonUpdateListFiles" : ("refresh.png", "Refresh list formats and files", 10, 2),
                          "buttonExtentActions" : ("drawextent.png", "Show extent for all files", 40, 2),
                          "buttonZoomToLayerExtent" : ("zoomtoselection.png", "Zoom to raster layer extent", 70, 2),
                          "buttonAddLayerToMapView" : ("viewlayer.png", "Add file to QGIS project", 100, 2),                          
                          "buttonInfosFile" : ("infos.png",  "GDAL informations for current file", 130, 2),
                          "buttonListFilesActions" : ("actions.png", "Actions for files", 160, 2)                          
                          }
         elif conteneur == self.toolBarMapViewer :
             #NEW 3.6.4 
             dicoCtrls = {"buttonNewProject" : ("new.png", "New project", 10, 2),
                          "buttonZoomAll" : ("zoomall.png", "Zoom all the map window", 40, 2),
                          "buttonPan" : ("pan.png", "Move the map window", 70, 2),
                          "buttonZoomIn" : ("zoomin.png", "Zoom in the map window", 100, 2),
                          "buttonZoomOut" : ("zoomout.png", "Zoom out the map window", 130, 2),
                          "buttonZoomPrevious" : ("zoomprev.png", "Previous zoom", 160, 2),
                          "buttonZoomNext" : ("zoomnext.png", "Next zoom", 190, 2),
                          "buttonClearExtents" : ("clearextents.png", "Clear zoom history", 220, 2),
                          "buttonSendExtent" : ("sendextent.png", "Send extent to Qgis mapcanvas", 250, 2)
                          }
         pos = 10       
         for key in dicoCtrls :
      
                   icon = getThemeIcon(dicoCtrls[key][0])
                   toolTip = translateMsg(dicoCtrls[key][1])

                   button = myPushButton(self.groupMap)
                   if key in ("buttonExtentActions", "buttonListFilesActions") : button.initPushButton(50, 25, pos, dicoCtrls[key][3], key, "", toolTip, True, icon, 50, 25, True) ; sizeWidth+= 50;                                               
                   else : button.initPushButton(25, 25, pos, dicoCtrls[key][3], key, "", toolTip, True, icon, 25, 25, True); sizeWidth+= 30;
                   
                   if key in ("buttonZoomIn", "buttonZoomOut","buttonPan", "buttonHotlink"):

                      styleSheetPushButton = "QPushButton::checked {icon-size: 25px, 25px; border-width: 5px; border-radius: 10px; border-color: black; background-color: #FFFFCC;}"
                      styleSheetPushButton+= "QPushButton {icon-size: 25px, 25px; border-width: 0px; border-radius: 10px; }"
                      button.setStyleSheet(styleSheetPushButton)
                      button.setCheckable(True)

                      if key == "buttonZoomIn" : button.setChecked(True)
                     
                      index = ("buttonZoomIn", "buttonZoomOut","buttonPan", "buttonHotlink").index(key)
                      self.actionsMapCanvas.addButton(button, index)
                      
                   setattr(self, key, button)
                   pos+= 50 if key in ("buttonExtentActions", "buttonListFilesActions") else 30

                   if key in ("buttonExtentActions", "buttonListFilesActions") : self.contextMnuObj(button)

         self.groupMap.setGeometry(20, 30, sizeWidth+15, 35) 

         return sizeWidth
