# -*- coding: latin-1 -*-

#==========================================================================================================================================
import copy
import os
import subprocess

from PySide import QtCore, QtGui

from Code.Traducir import tr
import Code.Util as Util
import Code.Configuracion as Configuracion
import Code.Partida as Partida
import Code.AperturasStd as AperturasStd
import Code.ControlPosicion as ControlPosicion
import Code.Variantes as Variantes

import QTVarios
import QTUtil, QTUtil2
import Colocacion
import Iconos
import Controles

import Tablero

import Grid
import Columnas

import FormLayout

#==========================================================================================================================================

def dameApertura( pantalla, configuracion, bloqueApertura, posicApertura ) :
    if bloqueApertura :
        me = QTUtil2.mensEspera.inicio( pantalla, tr( "UN_MOMENTO" ) )
    w = WAperturas( pantalla, configuracion, bloqueApertura, posicApertura )
    if bloqueApertura :
        me.final()
    if w.exec_() :
        bloqueApertura, posicApertura = w.resultado()
    else :
        bloqueApertura, posicApertura = None, None
    return bloqueApertura, posicApertura

#==========================================================================================================================================
class BLapertura :
    def __init__( self, parent, siPrimera ) :
        #~ self.lb = Controles.LB( "" )
        self.cb = QtGui.QComboBox(  )
        self.cb.setFixedHeight(40)
        self.cb.setFixedWidth(540)
        self.parent = parent
        parent.connect( self.cb, QtCore.SIGNAL("currentIndexChanged(int)"), self.cambiar )
        ly = Colocacion.V().control( self.cb )#.control( self.lb )
        self.gb = Controles.GB( None, "", ly )
        self.hija = None
        self.siPrimera = siPrimera
        self.rotulo = tr( "APERTURA_LIBRE") if siPrimera else tr( "APERTURA_LINEA_PRINCIPAL" )
        self.hijos = None
        self.activa = False
        self.numero = 0

    def ponerHija( self, hija ) :
        self.hija = hija

    def iniciar( self, num ) :
        self.cb.setCurrentIndex( num )
        self.cambiar( num )

    def cambiar( self, num ) :
        self.numero = num
        if num <= 0 :
            txt = ""
        else :
            if self.hijos :
                txt = self.hijos[num-1].trPGN()
            else :
                self.activar( False )
        x = "<b>"
        buscaPunto = True
        ant = ""
        for c in txt :
            if buscaPunto :
                if c == "." :
                    x += "</b>"
                    buscaPunto = False
            elif c.isdigit() and ant == " ":
                buscaPunto = True
                x += "<br><b>"
            x += c
            ant = c
        self.cb.setToolTip( x )

        if self.hija :
            if num > 0 :
                bl = self.hijos[num-1]
                self.hija.actualizar( bl.hijos )
            else :
                self.hija.actualizar( None )
        if num <= 0 :
            if self.siPrimera :
                self.parent.ponPartida( None )
        else :
            self.parent.ponPartida( self.hijos[num-1] )

    def actualizar( self, hijos ) :
        self.cb.clear()
        self.hijos = hijos
        if hijos :
            self.cb.addItem( self.rotulo, "" )
            for hijo in hijos :
                txt = hijo.trNombre + "\n      %s"%hijo.trPGN()
                key = hijo.a1h8
                ico = Iconos.PuntoEstrella() if hijo.siBasic else Iconos.PuntoNegro()
                self.cb.addItem( ico, txt, key )
            self.activar( True )
        else :
            self.activar( False )
        if self.hija :
            self.hija.actualizar( None )

    def activar( self, siMostrar ) :
        if siMostrar :
            self.activa = True
            self.gb.show()
        else :
            self.activa = False
            self.gb.hide()
            self.numero = -1

#==========================================================================================================================================

#==========================================================================================================================================
class WAperturas( QtGui.QDialog ):

    def __init__( self, wParent, configuracion, bloqueApertura, posicApertura ) :

        super(WAperturas, self).__init__(wParent)

        self.setMaximumWidth( QTUtil.anchoEscritorio() )

        self.apStd = AperturasStd.ListaAperturasStd(configuracion, True, False)
        self.numMovs = 0
        self.posJugada = -1

        self.setWindowFlags( QtCore.Qt.Dialog | QtCore.Qt.WindowTitleHint )

        self.configuracion = configuracion
        self.partida = Partida.Partida()

        self.setWindowTitle( tr( "PGN_OPENING" ) )
        self.setWindowIcon( Iconos.Datos() )

        self.liBL = []
        for i in range( 5 ) :
            self.liBL.append( BLapertura(self, i == 0 ) )
        for i in range( 4 ) :
            self.liBL[i].ponerHija( self.liBL[i+1] )

        # Tablero
        confTablero = Configuracion.ConfigTablero()
        confTablero.lee( configuracion.cTableroN.graba() )
        confTablero.anchoPieza = 32
        self.tablero = Tablero.Tablero(self, confTablero)
        self.tablero.crea()

        # Movimiento
        liAcciones = []
        def x( tit ) :
            liAcciones.append( ( tr(tit), tit, tit ) )

        liAcciones.append( None )
        x( "MoverInicio" )
        liAcciones.append( None )
        x( "MoverAtras" )
        liAcciones.append( None )
        x( "MoverAdelante" )
        liAcciones.append( None )
        x( "MoverFinal" )
        liAcciones.append( None )
        x( "MoverTiempo" )
        liAcciones.append( None )

        self.siMoviendoTiempo = False

        lyBM, tbBM = QTVarios.lyBotonesMovimiento( self, "", siLibre = False, tamIcon=24 )
        self.tbBM = tbBM

        # Tool bar
        tb = QTUtil2.creaTBAceptarCancelar( self )

        # Layout

        ## Niveles
        vbox = Colocacion.V()
        for i in range(5) :
            vbox.control(self.liBL[i].gb)
        vbox.relleno(1)
        lyD = Colocacion.V().control( tb ).otro( vbox ).margen(3)

        ## Izquierda
        lyI = Colocacion.V().control( self.tablero ).otro( lyBM )

        ## Completo
        ly = Colocacion.H().otro(lyI).otro(lyD).relleno(1).margen(3)
        self.setLayout( ly )

        bl0 = self.liBL[0]
        bl0.actualizar( self.apStd.hijos )
        self.bloqueApertura = bloqueApertura
        if bloqueApertura :
            self.bloqueApertura = self.apStd.dic[bloqueApertura.a1h8]
            if posicApertura :
                for i in range(5) :
                    bl = self.liBL[i]
                    bl.iniciar( posicApertura[i] )

    #--------------------------------------------------------------------------------------------------------------------------------
    def ponPartida( self, bloqueAp ) :
        self.bloqueApertura = bloqueAp
        self.partida.reset()
        if bloqueAp :
            self.partida.leerPV( bloqueAp.a1h8 )

        self.numJugadas = len(self.partida.liJugadas)
        self.mueve( siFinal = True )
    #--------------------------------------------------------------------------------------------------------------------------------
    def procesarTB( self ) :
        accion = self.sender().clave
        if accion == "aceptar" :
            self.accept()
        elif accion == "cancelar" :
            self.reject()
        elif accion == "MoverAdelante" :
            self.mueve(nSaltar=1)
        elif accion == "MoverAtras" :
            self.mueve(nSaltar=-1)
        elif accion == "MoverInicio" :
            self.mueve(siInicio = True)
        elif accion == "MoverFinal" :
            self.mueve(siFinal = True)
        elif accion == "MoverTiempo" :
            self.mueveTiempo()

    # -----------------------------------------------------------------------------------------------------------------------------------
    def mueve( self, siInicio = False, nSaltar=0, siFinal = False ) :
        if nSaltar :
            pos = self.posJugada + nSaltar
            if pos >= 0 and pos < self.numJugadas :
                self.posJugada = pos
            else :
                return
        elif siInicio :
            self.posJugada = 0
        elif siFinal :
            self.posJugada = self.numJugadas-1
        else :
            return
        if self.numJugadas :
            jg = self.partida.liJugadas[self.posJugada]
            self.tablero.ponPosicion( jg.posicion )
            self.tablero.ponFlechaSC( jg.desde, jg.hasta )
        else :
            self.tablero.ponPosicion( self.partida.iniPosicion )
            self.posJugada = 0
    # -----------------------------------------------------------------------------------------------------------------------------------
    def mueveTiempo( self ) :
        if self.siMoviendoTiempo :
            self.siMoviendoTiempo = False
            self.tiempoOtrosTB( True )
            self.paraReloj()
            return
        def otrosTB( siHabilitar ) :
            for accion in self.tbBM.liAcciones :
                if not accion.clave.endswith("MoverTiempo") :
                    accion.setEnabled( siHabilitar )

        self.tiempoFuncion = self.mueve
        self.tiempoPosMax = self.numJugadas
        self.tiempoPos = 0
        self.tiempoOtrosTB = otrosTB
        self.siMoviendoTiempo = True
        otrosTB( False )
        self.mueve( siInicio = True )
        self.iniciaReloj( self.mueveTiempo1 )

    #-----------------------------------------------------------------------------------
    def mueveTiempo1( self ) :
        self.tiempoPos += 1
        if self.tiempoPos == self.tiempoPosMax :
            self.siMoviendoTiempo = False
            self.tiempoOtrosTB( True )
            self.paraReloj()
            return
        self.tiempoFuncion( nSaltar = 1 )

    #--------------------------------------------------------------------------------------------------------------------------------
    def resultado( self ) :
        resp = []
        for i in range(5) :
            bl = self.liBL[i]
            resp.append( bl.numero )
        return self.bloqueApertura, resp

    #--------------------------------------------------------------------------------------------------------------------------------
    def iniciaReloj( self, funcion ) :
        if not hasattr( self, "timer" ) :
            self.timer = QtCore.QTimer(self)
            self.connect(self.timer, QtCore.SIGNAL("timeout()"), funcion )
        self.timer.start(1000)

    #--------------------------------------------------------------------------------------------------------------------------------
    def paraReloj( self ) :
        if hasattr( self, "timer" )  :
            self.timer.stop()
            delattr( self, "timer" )

#==========================================================================================================================================

#==========================================================================================================================================
class TutorApertura(QtGui.QDialog):
    def __init__(self, ventana, confTablero, siBlancas, posicion, usuDesde, usuHasta, apDesde, apHasta ) :
        super(TutorApertura, self).__init__(ventana)

        # Creamos los controles
        self.setWindowTitle( tr( "PGN_OPENING" ) )
        self.setWindowFlags( QtCore.Qt.Dialog | QtCore.Qt.WindowMinimizeButtonHint)
        self.setWindowIcon( Iconos.Tutor() )
        self.setStyleSheet("QWidget { background: #f5f5f5 }")

        posic = posicion.copia()
        posic.mover( usuDesde, usuHasta )
        self.tablero = Tablero.Tablero(self, confTablero)
        self.tablero.crea()
        self.tablero.ponerPiezasAbajo( siBlancas )
        self.tablero.ponPosicion( posic )
        self.tablero.ponFlechaSC( usuDesde, usuHasta )

        posic = posicion.copia()
        posic.mover( apDesde, apHasta )
        self.tableroA = Tablero.Tablero(self, confTablero)
        self.tableroA.crea()
        self.tableroA.ponerPiezasAbajo( siBlancas )
        self.tableroA.ponPosicion( posic )
        self.tableroA.ponFlechaSC( apDesde, apHasta )

        btUsuario = Controles.CHB( tr( "NUESTRA_JUGADA" ), False )
        self.connect( btUsuario, QtCore.SIGNAL("clicked()"), self.eligeUsuario )
        btApertura = Controles.CHB( tr( "PGN_OPENING" ), False )
        self.connect( btApertura, QtCore.SIGNAL("clicked()"), self.eligeApertura )

        # Creamos los layouts
        layout = Colocacion.G().controlc(btApertura, 0, 0).control(self.tableroA, 1, 0)
        layout.controlc(btUsuario, 0, 1).control(self.tablero, 1, 1)

        self.setLayout( layout )

        self.move( ventana.x()+20, ventana.y()+20 )

    def eligeUsuario(self) :
        self.resp = "U"
        self.accept()

    def eligeApertura(self) :
        self.resp = "A"
        self.accept()
#==========================================================================================================================================

#==========================================================================================================================================
class EntrenamientoApertura(QTVarios.WDialogo):
    def __init__(self, owner, listaAperturasStd, dicDatos ) :

        icono = Iconos.Apertura()
        titulo = tr("APERTURAS_ENTRENAR")
        extparam = "opentrainingE"
        QTVarios.WDialogo.__init__(self, owner, titulo, icono, extparam )

        nombre = dicDatos.get( "NOMBRE", "" )
        lista = dicDatos.get( "LISTA", [] )
        self.listaAperturasStd = listaAperturasStd

        tb = QTUtil2.creaTBAceptarCancelar( self )

        lbNombre = Controles.LB( tr( "APERTURAS_NOMBRE" ) + " : ")
        self.edNombre = Controles.ED( self, nombre )

        lyNombre = Colocacion.H().control(lbNombre).control(self.edNombre)

        self.treeView = QtGui.QTreeView()
        self.treeView.setAlternatingRowColors(True)
        self.treeView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.treeView.customContextMenuRequested.connect(self.menu)

        self.model = QtGui.QStandardItemModel()
        li, self.dicHijos = self.leer( lista )
        self.treeView.setModel(self.model)

        self.model.setHorizontalHeaderLabels([tr("APERTURAS_ELEGIR")])

        layout = Colocacion.V().control(tb).otro(lyNombre).control(self.treeView)

        self.setLayout(layout)

        self.recuperarVideo(siTam=True)

        for item in li :
            self.treeView.scrollTo( item.index() )

    #--------------------------------------------------------------------------------------------------------------------------------
    def procesarTB( self ) :
        getattr( self, self.sender().clave )()

    #--------------------------------------------------------------------------------------------------------------------------------
    def aceptar( self ) :

        self.nombre = self.edNombre.texto().strip()

        if not self.nombre :
            QTUtil2.mensError( self, tr("APERTURAS_ERROR_NOMBRE"))
            return

        self.lista = self.listaElegidas()

        if not self.lista :
            QTUtil2.mensError( self, tr("APERTURAS_ERROR_LISTA"))
            return

        self.guardarVideo()
        self.accept()

    #--------------------------------------------------------------------------------------------------------------------------------
    def cancelar( self ) :
        self.reject()

    #--------------------------------------------------------------------------------------------------------------------------------
    def listaElegidas( self ) :
        lista = []
        def miraHijo( hijo ) :

            if hijo.item.checkState() == QtCore.Qt.Checked :
                lista.append(hijo.a1h8)
            for nieto in hijo.hijos :
                miraHijo( nieto )

        for hijo in self.listaAperturasStd.hijos :
            miraHijo( hijo )

        return lista

    #--------------------------------------------------------------------------------------------------------------------------------
    def leer( self, lista ) :

        li = []
        dic = {}

        def nuevoHijo( padre, hijo, siCheckable ) :
            data = hijo.trNombre + "\n" + hijo.trPGN()
            item = QtGui.QStandardItem( data )
            item.setEditable(False)
            item.setCheckable(siCheckable)
            item.clave = data

            item.nombre = hijo.trNombre

            hijo.item = item
            if hijo.a1h8 in lista :
                item.setCheckState( QtCore.Qt.Checked )
                li.append( item )
            padre.appendRow(item)
            dic[data] = [item]
            for nieto in hijo.hijos :
                nitem = nuevoHijo( item, nieto, True )
                dic[data].append(nitem)
            return item

        for hijo in self.listaAperturasStd.hijos :
            nuevoHijo( self.model, hijo, len(hijo.hijos) == 0  )

        return li, dic

    #--------------------------------------------------------------------------------------------------------------------------------
    def menu( self, position):
        indexes = self.treeView.selectedIndexes()
        if len(indexes) > 0:
            i0 = indexes[0]
            liItems = self.dicHijos[i0.data()]
            if len(liItems) > 1 :
                # itemPadre = liItems[0]

                menu = Controles.LMenu()
                menu_marcar = menu.submenu( tr("GM_MARCAR"), Iconos.PuntoVerde() )
                menu_marcar.opcion( "mt", tr( "GM_MARCARTODOS"), Iconos.PuntoNaranja() )
                menu_marcar.opcion( "ms", tr( "MARCAR_NIVEL"), Iconos.PuntoAzul() )

                menu.separador()
                menu_desmarcar = menu.submenu( tr("DESMARCAR"), Iconos.PuntoNegro() )
                menu_desmarcar.opcion( "dt", tr( "GM_MARCARTODOS"), Iconos.PuntoNaranja() )
                menu_desmarcar.opcion( "ds", tr( "MARCAR_NIVEL"), Iconos.PuntoAzul() )

                resp = menu.lanza()
                if resp :
                    estado = QtCore.Qt.Checked if resp[0] == "m" else QtCore.Qt.Unchecked
                    sitodos = resp[1] == "t"

                    def marca( liItems, sihijos ) :
                        for n, item in enumerate(liItems) : # el primero es el padre
                            if n == 0 :
                                item.setCheckState( estado )
                            else :
                                if sihijos :
                                    liItems = self.dicHijos[item.clave]
                                    marca( liItems, sitodos )

                    marca( liItems, True )

#==========================================================================================================================================
class EntrenamientoAperturas(QTVarios.WDialogo):
    def __init__(self, procesador ) :

        self.procesador = procesador
        self.ficheroDatos = procesador.configuracion.ficheroEntAperturas
        self.ficheroParam = procesador.configuracion.ficheroEntAperturasPar
        self.listaAperturasStd = AperturasStd.ListaAperturasStd(procesador.configuracion, True, True)
        self.lista = []

        owner = procesador.pantalla
        icono = Iconos.Apertura()
        titulo = tr("APERTURAS_ENTRENAR")
        extparam = "opentraining"
        QTVarios.WDialogo.__init__(self, owner, titulo, icono, extparam )

        # Toolbar
        liAcciones = [  ( tr( "TB_TERMINAR" ), Iconos.TB_FinPartida(), "terminar" ), None,
                        ( tr( "TB_APERTURAS_ENTRENAR" ), Iconos.Entrenar(), "entrenar" ), None,
                        ( tr( "NUEVO" ), Iconos.TutorialesCrear(), "nuevo" ), None,
                        ( tr( "MODIFICAR" ), Iconos.TB_Modificar(), "modificar" ), None,
                        ( tr( "BORRAR" ), Iconos.TB_Borrar(), "borrar" ), None,
                        ( tr( "COPIAR" ), Iconos.TB_Copiar(), "copiar" ), None,
                        ( tr( "ARRIBA" ), Iconos.TB_Arriba(), "arriba" ), None,
                        ( tr( "ABAJO" ), Iconos.TB_Abajo(), "abajo" ), None,
                        ( "+"+tr( "TB_APERTURAS" ), Iconos.Aperturas(), "masaperturas" ), None,
                        ( tr( "LIBROS_POLYGLOT" ), Iconos.TB_Libros(), "polyglot" ), None
                    ]
        tb = Controles.TB( self, liAcciones )

        # Lista
        oColumnas = Columnas.ListaColumnas()
        oColumnas.nueva( "NOMBRE", tr( "APERTURAS_NOMBRE" ), 240 )
        oColumnas.nueva( "BLANCAS", tr( "PGN_WHITE" ), 120, siCentrado = True )
        oColumnas.nueva( "NEGRAS", tr( "PGN_BLACK" ), 120, siCentrado = True )
        oColumnas.nueva( "AMBOS", tr( "BLANCAS_Y_NEGRAS" ), 120, siCentrado = True )

        self.grid = Grid.Grid( self, oColumnas )
        n = self.grid.anchoColumnas()
        self.grid.setMinimumWidth( n + 20 )
        self.registraGrid( self.grid )

        # Layout
        layout = Colocacion.V().control(tb).control(self.grid).margen(8)
        self.setLayout( layout )

        self.recuperarVideo(siTam=True)

        self.lista = self.leer()

        self.siReverse = False

    #--------------------------------------------------------------------------------------------------------------------------------
    def procesarTB( self ) :
        getattr( self, self.sender().clave )()

    #--------------------------------------------------------------------------------------------------------------------------------
    def terminar( self ) :
        self.guardarVideo()
        self.reject()
        return

    #--------------------------------------------------------------------------------------------------------------------------------
    def masaperturas( self ) :
        w = AperturasPersonales( self.procesador, self )
        w.exec_()
        self.listaAperturasStd = AperturasStd.ListaAperturasStd(self.procesador.configuracion, True, True)

    #--------------------------------------------------------------------------------------------------------------------------------
    def polyglot( self ) :
        recno = self.grid.recno()
        if recno < 0 :
            return
        reg = self.lista[recno]

        # Pedimos el fichero a generar
        fbin = QTUtil2.salvaFichero( self, tr("LIBROS_POLYGLOT"), reg["NOMBRE"]+".bin", tr("LIBROS_POLYGLOT") + " (*.bin)" )
        if not fbin :
            return

        me = QTUtil2.mensEspera.inicio( self, tr( "UN_MOMENTO" ) )

        # Determinamos el fichero de trabajo
        plTMP = "deleteme_%d.pgn"
        n = 0
        while True :
            fichTMP = plTMP%n
            if Util.existeFichero(fichTMP) :
                n += 1
            else :
                break

        # Creamos el fichero de trabajo
        f = open( fichTMP, "wb" )
        for pv in reg["LISTA"] :
            f.write( '[Result "1/2-1/2"]\n' )
            p = Partida.Partida()
            p.leerPV(pv)
            f.write( p.pgnBase() + " 1/2-1/2\n\n" )
        f.close()

        # Ejecutamos
        li = [ os.path.abspath('engines/polyglot/polyglot.exe'), \
                'make-book', \
                "-pgn", fichTMP, \
                "-bin", fbin, \
                "-max-ply", "99", \
                "-min-game", "1", \
                "-uniform" ]
        Util.borraFichero( fbin )

        process = subprocess.Popen( li, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

        me.final()

        # Mostramos el resultado
        txt = process.stdout.read()
        if os.path.isfile( fbin ) :
            txt += "\n" + tr( "LIBROS_CREADO", fbin )

        QTUtil2.mensaje( self, txt )

        Util.borraFichero( fichTMP )

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridNumDatos( self, grid ) :
        return len(self.lista)

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDato( self, grid, fila, oColumna ) :
        clave = oColumna.clave
        reg = self.lista[fila]
        if clave == "NOMBRE" :
            return reg["NOMBRE"]

        return "%d"%reg[clave]

    #--------------------------------------------------------------------------------------------------------------------------------
    def entrenar( self, fil=None, col=None ) :
        if len(self.lista) == 0 :
            return
        if fil is None :
            fil = self.grid.recno()

        # Ultimo entrenamiento
        dicPar = Util.recuperaVar( self.ficheroParam )
        if dicPar is None :
            jugamos = "BLANCAS"
            repeticiones = 5
        else :
            jugamos = dicPar["JUGAMOS"]
            repeticiones = dicPar["REPETICIONES"]
        if not ((col is None) or (col.clave == "NOMBRE")) :
            jugamos = col.clave

        # Datos
        liGen = [(None,None)]

        liJ = [ (tr( "PGN_WHITE" ),"BLANCAS"), (tr( "PGN_BLACK" ),"NEGRAS"), (tr( "BLANCAS_Y_NEGRAS" ), "AMBOS")  ]
        config = FormLayout.Combobox( tr( "JUGAMOS_CON" ), liJ )
        liGen.append( ( config, jugamos ) )

        liR = [ ( tr("INDEFINIDO"), 0 ) ]

        for x in range( 4 ) :
            liR.append( (str(x+1), x+1) )

        for x in range( 5,105, 5 ) :
            liR.append( (str(x), x) )
        config = FormLayout.Combobox( tr( "REPETICIONES" ), liR )
        liGen.append( ( config, repeticiones ) )

        # Editamos
        resultado = FormLayout.fedit( liGen, title=tr( "TB_APERTURAS_ENTRENAR" ), parent=self, anchoMinimo=360, icon=Iconos.Entrenar(), siDefecto=False )
        if resultado is None :
            return

        accion, liResp = resultado
        jugamos = liResp[0]
        repeticiones = liResp[1]

        dicPar = {}
        dicPar["JUGAMOS"] = jugamos
        dicPar["REPETICIONES"] = repeticiones
        Util.guardaVar( self.ficheroParam, dicPar )

        self.resultado = (self.listaAperturasStd, self.ficheroDatos, self.lista, fil, jugamos, repeticiones)
        self.accept()

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDobleClick( self, grid, fil, col ) :
        self.entrenar( fil, col )

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDobleClickCabecera( self, grid, oColumna ) :
        clave = oColumna.clave
        if clave != "NOMBRE" :
            return

        li = sorted(self.lista, key=lambda x : x['NOMBRE'].upper() )

        if self.siReverse :
            li.reverse()

        self.siReverse = not self.siReverse

        self.lista = li

        self.grid.refresh()
        self.grid.gotop( )

        self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def editar( self, fila ) :
        reg = {} if fila is None else self.lista[fila]
        w = EntrenamientoApertura( self, self.listaAperturasStd, reg )
        if w.exec_() :
            reg = {}
            reg["NOMBRE"] = w.nombre
            reg["LISTA"] = w.lista
            reg["BLANCAS"] = 0
            reg["NEGRAS"] = 0
            reg["AMBOS"] = 0

            if fila is None :
                self.lista.append( reg )
                self.grid.gobottom()
            else :
                self.lista[fila] = reg
            self.grid.refresh()
            self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def nuevo( self ) :
        self.editar( None )

    #--------------------------------------------------------------------------------------------------------------------------------
    def modificar( self ) :
        recno = self.grid.recno()
        if recno >= 0 :
            self.editar( recno )

    #--------------------------------------------------------------------------------------------------------------------------------
    def borrar( self ) :
        fila = self.grid.recno()
        if fila >= 0:
            if QTUtil2.pregunta( self, tr( "APERTURAS_BORRAR", self.lista[fila]["NOMBRE"] ) ) :
                del self.lista[fila]
                self.grid.refresh()
                self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def copiar( self ) :
        fila = self.grid.recno()
        if fila >= 0:
            reg = self.lista[fila]
            nreg = copy.deepcopy(reg)
            self.lista.append(nreg)
            self.grid.refresh()
            self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def leer( self ) :
        lista = Util.recuperaVar( self.ficheroDatos )
        if lista is None :
            lista = []

        return lista

    #--------------------------------------------------------------------------------------------------------------------------------
    def grabar( self ) :
        Util.guardaVar( self.ficheroDatos, self.lista )

    #--------------------------------------------------------------------------------------------------------------------------------
    def arriba( self ) :
        fila = self.grid.recno()
        if fila > 0 :
            self.lista[fila-1],self.lista[fila] = self.lista[fila],self.lista[fila-1]
            self.grid.goto(fila-1,0)
            self.grid.refresh()
            self.grid.setFocus()
            self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def abajo( self ) :
        fila = self.grid.recno()
        if fila >= 0 and fila < (len(self.lista)-1) :
            self.lista[fila+1],self.lista[fila] = self.lista[fila],self.lista[fila+1]
            self.grid.goto(fila+1,0)
            self.grid.refresh()
            self.grid.setFocus()
            self.grabar()

#==========================================================================================================================================
class AperturasPersonales(QTVarios.WDialogo):
    def __init__(self, procesador, owner = None ) :

        self.procesador = procesador
        self.ficheroDatos = procesador.configuracion.ficheroPersAperturas
        self.lista = []

        if owner is None :
            owner = procesador.pantalla
        icono = Iconos.Apertura()
        titulo = tr("APERTURAS_PERSONALES")
        extparam = "customopen"
        QTVarios.WDialogo.__init__(self, owner, titulo, icono, extparam )

        # Toolbar
        liAcciones = [  ( tr( "TB_TERMINAR" ), Iconos.TB_FinPartida(), "terminar" ), None,
                        ( tr( "NUEVO" ), Iconos.TutorialesCrear(), "nuevo" ), None,
                        ( tr( "MODIFICAR" ), Iconos.TB_Modificar(), "modificar" ), None,
                        ( tr( "BORRAR" ), Iconos.TB_Borrar(), "borrar" ), None,
                        ( tr( "COPIAR" ), Iconos.TB_Copiar(), "copiar" ), None,
                        ( tr( "ARRIBA" ), Iconos.TB_Arriba(), "arriba" ), None,
                        ( tr( "ABAJO" ), Iconos.TB_Abajo(), "abajo" ), None,
                    ]
        tb = Controles.TB( self, liAcciones )

        # Lista
        oColumnas = Columnas.ListaColumnas()
        oColumnas.nueva( "NOMBRE", tr( "APERTURAS_NOMBRE" ), 240 )
        oColumnas.nueva( "ECO", "ECO", 70, siCentrado = True )
        oColumnas.nueva( "PGN", "PGN", 280 )
        oColumnas.nueva( "ESTANDAR", tr( "APERTURAS_PERS_ESTANDAR" ), 120, siCentrado = True )

        self.grid = Grid.Grid( self, oColumnas )
        n = self.grid.anchoColumnas()
        self.grid.setMinimumWidth( n + 20 )
        self.registraGrid( self.grid )

        # Layout
        layout = Colocacion.V().control(tb).control(self.grid).margen(8)
        self.setLayout( layout )

        self.recuperarVideo(siTam=True)

        self.lista = self.leer()

        self.dicPGNSP = {}

    #--------------------------------------------------------------------------------------------------------------------------------
    def procesarTB( self ) :
        getattr( self, self.sender().clave )()

    #--------------------------------------------------------------------------------------------------------------------------------
    def terminar( self ) :
        self.guardarVideo()
        self.reject()
        return

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridNumDatos( self, grid ) :
        return len(self.lista)

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDato( self, grid, fila, oColumna ) :
        clave = oColumna.clave
        reg = self.lista[fila]
        if clave == "ESTANDAR" :
            return tr("SI") if reg["ESTANDAR"] else tr( "NO" )
        elif clave == "PGN" :
            pgn = reg["PGN"]
            if pgn not in self.dicPGNSP :
                p = Partida.Partida()
                p.leerPV(reg["A1H8"])
                self.dicPGNSP[pgn] = p.pgnSP()
            return self.dicPGNSP[pgn]
        return reg[clave]

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDobleClick( self, grid, fil, col ) :
        self.editar( fil )

    #--------------------------------------------------------------------------------------------------------------------------------
    def gridDobleClickCabecera( self, grid, oColumna ) :
        clave = oColumna.clave

        li = sorted(self.lista, key=lambda x : x[clave].upper() )

        self.lista = li

        self.grid.refresh()
        self.grid.gotop( )

        self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def editar( self, fila ) :

        if fila is None :
            nombre = ""
            eco = ""
            pgn = ""
            estandar = True
            titulo = tr( "APERTURAS_PERS_NUEVA" )

        else :
            reg = self.lista[fila]

            nombre = reg["NOMBRE"]
            eco = reg["ECO"]
            pgn = reg["PGN"]
            estandar = reg["ESTANDAR"]

            titulo = nombre

        # Datos
        liGen = [(None,None)]
        liGen.append( ( tr( "APERTURAS_NOMBRE" ) + " :", nombre ) )
        config = FormLayout.Editbox( tr( "ECO" ), ancho=30, rx = "[A-Z, a-z][0-9][0-9]" )
        liGen.append( (config, eco ) )
        liGen.append( ( tr( "APERTURAS_PERS_ESTANDAR" ) + " :", estandar ) )

        # Editamos
        resultado = FormLayout.fedit( liGen, title= titulo, parent = self, anchoMinimo = 460, icon = Iconos.Apertura(), siDefecto = False )
        if resultado is None :
            return

        accion, liResp = resultado
        nombre = liResp[0].strip()
        if not nombre :
            return
        eco = liResp[1].upper()
        estandar = liResp[2]

        fen = ControlPosicion.ControlPosicion().fenInicial

        self.procesador.procesador = self.procesador # ya que editaVariante espera un gestor

        resp = Variantes.editaVariante( self.procesador, fen, pgn, titulo=nombre )

        if resp :
            pgn, a1h8 = resp

            reg =  {}
            reg["NOMBRE"] = nombre
            reg["ECO"] = eco
            reg["PGN"] = pgn
            reg["A1H8"] = a1h8
            reg["ESTANDAR"] = estandar

            if fila is None  :
                self.lista.append( reg )
                self.grid.refresh()
                self.grabar()
            else :
                self.lista[fila] = reg
            self.grid.refresh()
            self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def nuevo( self ) :
        self.editar( None )

    #--------------------------------------------------------------------------------------------------------------------------------
    def modificar( self ) :
        recno = self.grid.recno()
        if recno >= 0 :
            self.editar( recno )

    #--------------------------------------------------------------------------------------------------------------------------------
    def borrar( self ) :
        fila = self.grid.recno()
        if fila >= 0:
            if QTUtil2.pregunta( self, tr( "APERTURAS_PERS_BORRAR", self.lista[fila]["NOMBRE"] ) ) :
                del self.lista[fila]
                self.grid.refresh()
                self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def copiar( self ) :
        fila = self.grid.recno()
        if fila >= 0:
            reg = self.lista[fila]
            nreg = copy.deepcopy(reg)
            self.lista.append(nreg)
            self.grid.refresh()
            self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def leer( self ) :
        lista = Util.recuperaVar( self.ficheroDatos )
        if lista is None :
            lista = []

        return lista

    #--------------------------------------------------------------------------------------------------------------------------------
    def grabar( self ) :
        Util.guardaVar( self.ficheroDatos, self.lista )

    #--------------------------------------------------------------------------------------------------------------------------------
    def arriba( self ) :
        fila = self.grid.recno()
        if fila > 0 :
            self.lista[fila-1],self.lista[fila] = self.lista[fila],self.lista[fila-1]
            self.grid.goto(fila-1,0)
            self.grid.refresh()
            self.grid.setFocus()
            self.grabar()

    #--------------------------------------------------------------------------------------------------------------------------------
    def abajo( self ) :
        fila = self.grid.recno()
        if fila >= 0 and fila < (len(self.lista)-1) :
            self.lista[fila+1],self.lista[fila] = self.lista[fila],self.lista[fila+1]
            self.grid.goto(fila+1,0)
            self.grid.refresh()
            self.grid.setFocus()
            self.grabar()
