#from __future__ import unicode_literals
# -*- coding: utf-8 -*-
from __future__ import division
import os
from sys import exit, argv, getsizeof, settrace
from time import time, sleep, strftime, localtime
from threading import Thread

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtOpenGL

##from ui.ecran_editionAttaques import Ui_editionAttaques

from Case import Case
from Pion import Pion
from PionDecor import PionDecor
from Forme import Forme

from Cache import Cache
from EntreeSortie import EntreeSortie

from EcranEditionCreature import EcranEditionCreature
from EcranEditionDecors import EcranEditionDecors
from EcranEditionTerrain import EcranEditionTerrain
from EcranAffichageTexte import EcranAffichageTexte
from EcranGestionCombat import EcranGestionCombat

import regles as regles
from outilsSvg import *
from lancer import jet, estJetValide

from operator import itemgetter, attrgetter
from math import *

        
class Plateau(QGraphicsScene):
    """plateau de jeu contenant les cases, decors et pions"""
    def __init__(self, fenetre, parent=None):
        super(Plateau, self).__init__()
        #parametres et variables
        self.id = ""
        self.nom = ""
        self.chapitre = 0
        self.fenetre = fenetre
        self.nbCasesX = 0
        self.nbCasesY = 0
        self.hCase = 0
        self.cases = {}   #dict des cases du plateau   (coordonnées: case)
        self.pions = {}   #liste de pions positionnes sur le plateau
        self.decors = {}  #liste des decors places sur le plateau
        self.ordreJeu = {}  #numero du pion: ordre de jeu
        self.numPionEnCours = 0
        self.tour = 1
        self.cacheEnCours = 1
        self.caches = {}
        self.polygonesCaches = {}
        for i in range(1,5):
            self.caches[i] = {"actif":False,"listeCases":[]}
            self.polygonesCaches[i] = None
            
        self.listeCasesZonePlacement = []
        self.polygoneZonePlacement = None
        self.entreesSorties = []
        self.modePrincipal = "creation"
        self.modeActif = ""
        self.modeCombat = ""
        self.nbZoomActuel = 0
        self.epaisseurpinceau = 0
        self.enCours = False
        self.public = False
        self.dateCreation = ""
        self.dateSvg = ""
        self.notes = ""
        
        #note: la hauteur Z (qui gere l'empilement des objets graphiques est distribuee de cette maniere:
        #cases : 0 a 9
        #pions : 10 et +
        
    def __getstate__(self):
        self.dateSvg = time()
        state = {key:value for key, value in self.__dict__.items() if not key in ["fenetre", "modeActif", "listMode", "cacheEnCours", \
                                                                                  "modeParam", "nbZoomActuel", "epaisseurPinceau", \
                                                                                  "editionTerrain", "editionCreature", "editionDecor", \
                                                                                  "polygoneZonePlacement", "gestionCombat", "polygonesCaches", \
                                                                                  "editionAttaques"]}
        return (state)

    def __setstate__(self, state):
        self.__dict__ = state

    def creer(self, idPlateau, nom, chapitre, formeCases, nbCasesX, nbCasesY, couleur = QColor(0, 255, 0, 80)):
        """cree le plateau"""
        self.id = idPlateau
        self.nom = nom
        self.chapitre = chapitre
        self.dateCreation = time()
        self.hCase = 120  #hauteur d'une case
        self.nbCasesX = nbCasesX   #nb cases en x
        self.nbCasesY = nbCasesY   #nb cases en y
        self.formeCases = formeCases
        self.gestionCombat = None
        self.initialisationGraphique()
        self.connexions()
        
        #cree les cases hexagonales
        for x in range(nbCasesX):
            for y in range(nbCasesY):
                if formeCases == "H":
                     if 1 == (x % 2):
                          y += 0.5
                c = Case(self)
                c.creer(x, y, couleur)
                self.cases[(x,y)] = c
                

    def recreer(self, fenetre):
        self.fenetre = fenetre
        self.gestionCombat = None
        super(Plateau, self).__init__()
        self.connexions()

        self.initialisationGraphique() 

        #recreation des cases 
        for coord in self.cases:
            self.cases[coord].recreer(self)

        #recreation des pions
        for numPion in self.pions:
            self.pions[numPion].recreer(self)
        self.majOrdreJeu()    

        #recreation des decors
        for num in self.decors:
            self.decors[num].recreer(self)

        #recreation des marqueurs entree/sortie
        for entreeSortie in self.entreesSorties:
            entreeSortie.recreer(self)

        #recreation de la zone de placement: 
        if len(self.listeCasesZonePlacement) > 0:
            self.polygoneZonePlacement = None
            self.majZonePlacement(self.listeCasesZonePlacement)    

        #recreation des caches
        self.polygonesCaches = {}
        for i in range(1,5):
            self.polygonesCaches[i] = None

    def fermer(self):
        """ferme le plateau 'proprement'"""
        self.miniature()
        for item in self.items():
            item.prepareGeometryChange()
            self.removeItem(item)
        if self.gestionCombat != None:    
            del self.gestionCombat           
        self.fenetre.reinitialiserPanneauxPlateau()

    def miniature(self):
        """renvoie une miniature du plateau (QPixMap compresse) qui sera enregistree avec les infos de la sauvegarde"""
##        img = QImage(128, 128, QImage.Format_ARGB32_Premultiplied)
        img = QPixmap(1024, 768)
        img.fill(QColor("white"))
        peintre = QPainter(img)
        rendu = self.render(peintre)
        peintre.end()
        img.scaledToHeight(128, Qt.FastTransformation)
        

    def connexions(self):
        """connecte le plateau aux differents widgets de la fenetre principale"""
        self.fenetre.connect(self.fenetre.ui.modeCreationPlateau, SIGNAL("clicked()"), self.plateauModeCreation, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.modeCombatPlateau, SIGNAL("clicked()"), self.plateauModeCombat, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.afficherGestionCombat, SIGNAL("clicked()"), self.afficheEcranGestionCombat, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.terrainCouleur, SIGNAL("clicked()"), self.modePeintureCase, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.terrainCopie, SIGNAL("clicked()"), self.modeCopieTerrain, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.pionCouleur, SIGNAL("clicked()"), self.majCouleurPion, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.terrainEdit, SIGNAL("clicked()"), self.terrainEdit, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.terrainNouveau, SIGNAL("clicked()"), self.terrainNouveau, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.creatureEdit, SIGNAL("clicked()"), self.creatureEdit, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.creatureNouveau, SIGNAL("clicked()"), self.creatureNouveau, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.pionSimpleCreer, SIGNAL("clicked()"), self.modeCreationPion, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.pionSupprimer, SIGNAL("clicked()"), self.majModePionSupprimer, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.decorEdit, SIGNAL("clicked()"), self.decorEdit, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.decorNouveau, SIGNAL("clicked()"), self.decorNouveau, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.decorSupprimer, SIGNAL("clicked()"), self.majModePionSupprimer, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.definirEntree, SIGNAL("clicked()"), self.majModeDefinirEntree, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.definirSortie, SIGNAL("clicked()"), self.majModeDefinirSortie, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.definirZonePlacement, SIGNAL("clicked()"), self.majModeZonePlacement, Qt.UniqueConnection)

        self.fenetre.connect(self.fenetre.ui.formeSimple, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.formeLigne, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.formeLigneOrientee, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.formeEllipseVide, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.formeEllipsePlein, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.formeRectVide, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.formeRectPlein, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)

        self.fenetre.connect(self.fenetre.ui.effFeu, SIGNAL("clicked()"), self.modeCaseEffet, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.effEau, SIGNAL("clicked()"), self.modeCaseEffet, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.effGlace, SIGNAL("clicked()"), self.modeCaseEffet, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.effPoison, SIGNAL("clicked()"), self.modeCaseEffet, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.effEffacer, SIGNAL("clicked()"), self.modeCaseEffet, Qt.UniqueConnection)

        self.fenetre.connect(self.fenetre.ui.cacheActif, SIGNAL("clicked()"), self.majEtatCacheEnCours, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.cacheVoir, SIGNAL("clicked()"), self.voirCacheEnCours, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.cachePlacer, SIGNAL("clicked()"), self.placerCacheEnCours, Qt.UniqueConnection)

        self.fenetre.connect(self.fenetre.ui.combatDeplacement, SIGNAL("clicked()"), self.majModeCombatDeplacement, Qt.UniqueConnection)
        self.fenetre.ui.combatDeplacement.setCheckable(True)
        self.fenetre.connect(self.fenetre.ui.combatAttaqueCaC, SIGNAL("clicked()"), self.majModeCombatAttaqueCaC, Qt.UniqueConnection)
        self.fenetre.ui.combatAttaqueCaC.setCheckable(True)
        self.fenetre.connect(self.fenetre.ui.combatAttaqueDist, SIGNAL("clicked()"), self.majModeCombatAttaqueDist, Qt.UniqueConnection)
        self.fenetre.ui.combatAttaqueDist.setCheckable(True)
        self.fenetre.connect(self.fenetre.ui.combatAttaqueZone, SIGNAL("clicked()"), self.fenetre.barreCombatZone, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.combatAttaqueZone, SIGNAL("clicked()"), self.majModeCombatZone, Qt.UniqueConnection)
        self.fenetre.ui.combatAttaqueZone.setCheckable(True)
        self.fenetre.connect(self.fenetre.ui.combatVol, SIGNAL("clicked()"), self.fenetre.barreCombatVol, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.combatVol_altitude, SIGNAL("valueChanged(int)"), self.majZPion, Qt.UniqueConnection)
        #self.fenetre.connect(self.fenetre.ui.combatVol_altitude, SIGNAL("editingFinished()"), self.majVisibiliteBarreCombat)
        self.fenetre.connect(self.fenetre.ui.combatZone_ligne, SIGNAL("clicked()"), self.majModeCombatZoneForme, Qt.UniqueConnection)
        self.fenetre.ui.combatZone_ligne.setCheckable(True)
        self.fenetre.connect(self.fenetre.ui.combatZone_disque, SIGNAL("clicked()"), self.majModeCombatZoneForme, Qt.UniqueConnection)
        self.fenetre.ui.combatZone_disque.setCheckable(True)
        self.fenetre.connect(self.fenetre.ui.combatZone_cone, SIGNAL("clicked()"), self.majModeCombatZoneForme, Qt.UniqueConnection)
        self.fenetre.ui.combatZone_cone.setCheckable(True)
        self.fenetre.connect(self.fenetre.ui.combatRetour, SIGNAL("clicked()"), self.fenetre.barreCombatMenu, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.combatPasserTour, SIGNAL("clicked()"), self.pionSuivant, Qt.UniqueConnection)
        #self.connect(self.ui.combatInventaire, SIGNAL("clicked()"), self.majModePionSupprimer)

        self.fenetre.connect(self.fenetre.ui.modeAffichagePlateau, SIGNAL("currentIndexChanged(int)"), self.majModeAffichage, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.listTerrains, SIGNAL("cellClicked(int,int)"), self.modeMajTerrainCase, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.listCreatures, SIGNAL("cellClicked(int,int)"), self.modeCreationCreaturePion, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.listDecors, SIGNAL("cellClicked(int,int)"), self.modeCreationDecor, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.epaisseurPinceau, SIGNAL("valueChanged(int)"), self.majEpaisseurPinceau, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.altitudeCase, SIGNAL("valueChanged(double)"), self.modeMajAltitudeCase, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.infoOrdreJeu, SIGNAL("cellClicked(int,int)"), self.clicListOrdreJeu, Qt.UniqueConnection)
        
        self.fenetre.connect(self.fenetre.ui.listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.editerAttaques, SIGNAL("clicked()"), self.afficheEcranEditionAttaques, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.notesPion, SIGNAL("textChanged()"), self.majNotesPion, Qt.UniqueConnection)

        self.fenetre.connect(self.fenetre.ui.notesMjPlateau, SIGNAL("textChanged()"), self.majNotesPlateau, Qt.UniqueConnection)
        self.fenetre.connect(self.fenetre.ui.agrandirNotesMjPlateau, SIGNAL("clicked()"), self.agrandirNotesMjPlateau, Qt.UniqueConnection)
        

    def initialisationGraphique(self):
        """cree la scene graphique et les parametres necessaires a son fonctionnement, et met a jour l'interface""" 
        #on cree la scene graphique
        kx = 1
        if self.formeCases == "H":
            kx = 0.866
        marge = 240    
        self.setSceneRect(0 - marge, 0 - marge, (kx*self.hCase*(self.nbCasesX+2)) + marge, (self.hCase*(self.nbCasesY+2)) + marge)
        self.fenetre.ui.vuePlateau.setScene(self)
        self.fenetre.ui.vuePlateau.scale(0.25, 0.25)
        self.fenetre.ui.vuePlateau.centerOn(QPointF(0,0))
        self.fenetre.ui.vuePlateau.setDragMode(1)
        self.setItemIndexMethod(QGraphicsScene.BspTreeIndex)
        
        #self.setItemIndexMethod(QGraphicsScene.NoIndex)
        self.nbZoomActuel = 0
        self.epaisseurPinceau = 1
        self.polygoneZonePlacement = None
        self.polygonesCaches = {}
        for i in range(1,5):
            self.polygonesCaches[i] = None


        #gestion du mode d'interaction avec le plateau
        self.modeActif = "standard"
        self.listMode = ["standard", "caseMajTerrain", "caseCopie", "caseMajEffet", "caseMajAltitude", "pionCreation", \
                         "pionSelectionne", "pionDecorCreation", "pionDecorSelectionne", "pionSupprimer", "cachePlacer", \
                         "combatDeplacement", "combatAttaqueCaC", "combatAttaqueDist", \
                         "placementEntreeSortie", "majZonePlacement"]
      
        self.modeParam = {"terrain": None, "numPionSelectionne": 0, "pionNouveau": None, "creature": None, "decor": None, "effet":"", "couleurPion": QColor("grey"), \
                          "coordProjectionPosition": (0,0), "formeProjectionPosition": None, "nbRotations": 0, \
                          "typeFormeDessin": "simple", "formeDessin": None, "origineFormeDessin": None, "point2FormeDessin": None, "listeCasesFormeDessin": [], \
                          "projectionFormeDessin": [], "formeCoordEnCours": (0,0), \
                          "zoneAttaqueCaC": [], "cibleAttaqueCaC": None, "cibleAttaqueDist": None, "pionCibleAttaqueDist": None, "ligneAttaqueDist": None, \
                          "typeAttaqueZone": "", "formeAttaqueZone": None, "origineAttaqueZone": None, "point2AttaqueZone": None, "listeCasesAttaqueZone": [], "ligneMireAttaqueZone": None, \
                          "entreeSortie": None}
  

        #mise a jour de l'interface de creation
        self.fenetre.majVisibilitePanneauxPlateau("creation")
        self.fenetre.ui.nomPlateau.setText(QString.fromUtf8(self.nom))
        self.fenetre.ui.nomPlateau.setText(QString.fromUtf8(self.nom))
        self.majBoutonsCouleursPerso()
        self.majBoutonsCaches()
        self.majListTerrains()
        self.majListCreatures()
        self.majListDecors()
        self.initListeOrdreJeu()
        self.initListeAttaques()
        self.fenetre.ui.notesMjPlateau.setText(QString.fromUtf8(self.notes))
        
        if self.modeParam["couleurPion"].isValid(): 
            self.fenetre.ui.pionCouleur.setStyleSheet("QPushButton {backGround:%s}" %(self.modeParam["couleurPion"].name()))
            
        #mise a jour de l'interface d'informations
        self.majInfosPion(None)
        self.majInfosDecor(None)

    def estCree(self):
        """renvoie vrai si des cases ont ete creees"""
        if len(self.cases) > 0:
            retour = True
        else:
            retour = False
        return retour

    def majBoutonsCouleursPerso(self):
        """met a jour l'affichage des couleurs customisees dans la boite de dialogue de selection de couleur"""
        for i in range(0,16):
            rgb = QColorDialog(self.fenetre.ui.vuePlateau).customColor(i)
            couleur = QColor(rgb)
            bouton = self.fenetre.ui.outilsEditionPlateau.findChild(QToolButton, "terrainCouleurPerso{}".format(i+1))
            if couleur.isValid():
                bouton.setStyleSheet("QToolButton {backGround:%s}"%(couleur.name()))
                self.fenetre.connect(bouton, SIGNAL("clicked()"), self.modePeintureCase_perso)

    def chercherCouleur(self):
        """ouvre la boite de dialogue de selection de couleur"""
        couleur = QColorDialog(self.fenetre.ui.vuePlateau).getColor(QColor("white"), self.fenetre.ui.vuePlateau)
        self.majBoutonsCouleursPerso()
        return couleur

    def majBoutonsCaches(self):
        """met a jour l'affichage et connecte les boutons de caches"""
        for i in range(1,5):
            bouton = self.fenetre.ui.outilsEditionPlateau.findChild(QToolButton, "plateauCache{}".format(i))
            self.fenetre.connect(bouton, SIGNAL("clicked()"), self.majAffichageMenuCache)

    def majListesPions(self, numPion = None):
        """met a jour les listes contenant des donnees liees aux pions"""
##        self.majListeOrdreJeu()
##        
##        if numPion == None or numPion == self.pionSelectionne().numero:
##            self.majListeAttributs()
##        QApplication.processEvents()
        pass

    def majNotesPlateau(self):
        """les notes du plateau ont ete maj a l'ecran"""
        self.notes = str(self.fenetre.ui.notesMjPlateau.toPlainText().toUtf8())

    def agrandirNotesMjPlateau(self):
        """affiche les notes du plateau dans une QDialog, puis recupere les donnees qui y sont saisies"""
        affichageTexte = EcranAffichageTexte(self.notes)
        affichageTexte.setAttribute(Qt.WA_DeleteOnClose)
        r = affichageTexte.exec_()
        self.fenetre.ui.notesMjPlateau.setText(QString.fromUtf8(affichageTexte.recupererTexte()))
        
    ##### affichage de la liste des terrains enregistres, et fonctions d'acces aux donnees""""     
    def afficheEcranEditionTerrains(self, terrain = None):
        """affiche l'ecran d'edition/creation de terrains"""
        self.editionTerrain = EcranEditionTerrain(terrain)
        self.connect(self.fenetre, SIGNAL("majListTerrains()"), self.majListTerrains)
        self.connect(self.editionTerrain, SIGNAL("majListTerrains()"), self.majListTerrains)        
        self.editionTerrain.setAttribute(Qt.WA_DeleteOnClose)
        r = self.editionTerrain.exec_()
 
    def majListTerrains(self):
        """mise a jour de la liste des terrains depuis la sauvegarde"""
        dico = afficheSvg("lib\\biblio\\terrain")
        while self.fenetre.ui.listTerrains.rowCount() > 0:
            self.fenetre.ui.listTerrains.removeRow(0)
        index = 0    
        #self.fenetre.ui.listTerrains.setColumnWidth(0,0)
        self.fenetre.ui.listTerrains.hideColumn(0)
        self.fenetre.ui.listTerrains.sizeHintForColumn(1)
        for elt in dico:
            terrain = dico[elt]
            self.fenetre.ui.listTerrains.insertRow(int(index))
            self.fenetre.ui.listTerrains.setItem(int(index),0,QTableWidgetItem(QString.fromUtf8(elt)))
            icon = QIcon("img\\"+terrain.imgTexture)
            item = QTableWidgetItem(icon,QString.fromUtf8(terrain.nom))
            self.fenetre.ui.listTerrains.setItem(int(index),1,item)
            index += 1
        self.fenetre.ui.listTerrains.setIconSize(QSize(30,20))   
        self.fenetre.ui.listTerrains.sizeHintForColumn(1)
        self.fenetre.ui.listTerrains.sortItems(0)
        self.majMode("standard")

    def terrainEdit(self):
        """ouvre la fenetre 'terrains' en mode edition"""
        index = self.fenetre.ui.listTerrains.item(self.fenetre.ui.listTerrains.currentRow(), 0)
        if index > 0:
            terrain = charger("lib\\biblio\\terrain", str(index.text().toUtf8()))
            self.afficheEcranEditionTerrains(terrain)
        
    def terrainNouveau(self):
        """ouvre la fenetre 'terrains' en mode edition"""
        self.afficheEcranEditionTerrains()
    ###############

    ##### affichage de la liste des creatures enregistrees, et fonctions d'acces aux donnees""""     
    def afficheEcranEditionCreatures(self, creature = None):
        """affiche l'ecran d'edition/creation de creatures"""
        self.editionCreature = EcranEditionCreature(creature, self.formeCases)
        self.editionCreature.setAttribute(Qt.WA_DeleteOnClose)
        self.connect(self.fenetre, SIGNAL("majListCreatures()"), self.majListCreatures)
        self.connect(self.editionCreature, SIGNAL("majListCreatures()"), self.majListCreatures)        
        r = self.editionCreature.exec_()       
        
    def majListCreatures(self):
        """mise a jour de la liste des creatures depuis la sauvegarde"""
        dico = afficheSvg("lib\\biblio\\creature")
        while self.fenetre.ui.listCreatures.rowCount() > 0:
            self.fenetre.ui.listCreatures.removeRow(0)
        index = 0    
        #self.fenetre.ui.listTerrains.setColumnWidth(0,0)
        self.fenetre.ui.listCreatures.hideColumn(0)
        self.fenetre.ui.listCreatures.sizeHintForColumn(1)
        for elt in dico:
            creature = dico[elt]
            self.fenetre.ui.listCreatures.insertRow(int(index))
            self.fenetre.ui.listCreatures.setItem(int(index),0,QTableWidgetItem(QString.fromUtf8(elt)))
            icon = QIcon("img\\"+creature.logo)
            item = QTableWidgetItem(icon,QString.fromUtf8(creature.nom))
            self.fenetre.ui.listCreatures.setItem(int(index),1,item)
            index += 1
        self.fenetre.ui.listCreatures.setIconSize(QSize(30,20))   
        self.fenetre.ui.listCreatures.sizeHintForColumn(1)
##        self.fenetre.ui.listCreatures.sortItems(0)
##        trierTable(self.fenetre.ui.listCreatures, 0, 0)
        self.majMode("standard")

    def creatureEdit(self):
        """ouvre la fenetre 'creatures' en mode edition"""
        index = self.fenetre.ui.listCreatures.item(self.fenetre.ui.listCreatures.currentRow(), 0)
        if index > 0:
            creature = charger("lib\\biblio\\creature", str(index.text().toUtf8()))
            self.afficheEcranEditionCreatures(creature)
        
    def creatureNouveau(self):
        """ouvre la fenetre 'creatures' en mode edition"""
        self.afficheEcranEditionCreatures()
        
    ###############

    ##### affichage de la liste des decors enregistrees, et fonctions d'acces aux donnees""""     
    def afficheEcranEditionDecors(self, decor = None):
        """affiche l'ecran d'edition/creation de decors"""
        self.editionDecor = EcranEditionDecors(decor, self.formeCases)
        self.editionDecor.setAttribute(Qt.WA_DeleteOnClose)
        self.connect(self.fenetre, SIGNAL("majListDecors()"), self.majListDecors)
        self.connect(self.editionDecor, SIGNAL("majListDecors()"), self.majListDecors)
        r = self.editionDecor.exec_()
        
    def majListDecors(self):
        """mise a jour de la liste des decors depuis la sauvegarde"""
        dico = afficheSvg("lib\\biblio\\decor")
        while self.fenetre.ui.listDecors.rowCount() > 0:
            self.fenetre.ui.listDecors.removeRow(0)
        index = 0    
        #self.fenetre.ui.listTerrains.setColumnWidth(0,0)
        self.fenetre.ui.listDecors.hideColumn(0)
        self.fenetre.ui.listDecors.sizeHintForColumn(1)
        for elt in dico:
            decor = dico[elt]
            self.fenetre.ui.listDecors.insertRow(int(index))
            self.fenetre.ui.listDecors.setItem(int(index),0,QTableWidgetItem(QString.fromUtf8(elt)))
            icon = QIcon("img\\"+decor.logo)
            item = QTableWidgetItem(icon,QString.fromUtf8(decor.nom))
            self.fenetre.ui.listDecors.setItem(int(index),1,item)
            index += 1
        self.fenetre.ui.listDecors.setIconSize(QSize(30,20))   
        self.fenetre.ui.listDecors.sizeHintForColumn(1)
##        self.fenetre.ui.listDecors.sortItems(0)
##        trierTable(self.fenetre.ui.listDecors, 0, 0)
        self.majMode("standard")

    def decorEdit(self):
        """ouvre la fenetre 'decors' en mode edition"""
        index = self.fenetre.ui.listDecors.item(self.fenetre.ui.listDecors.currentRow(), 0)
        if index > 0:
            decor = charger("lib\\biblio\\decor", str(index.text().toUtf8()))
            self.afficheEcranEditionDecors(decor)
        
    def decorNouveau(self):
        """ouvre la fenetre 'decors' en mode edition"""
        self.afficheEcranEditionDecors()
        
    ###############

    ########### affichage des curseurs personnalises ########
    def curseurSelection(self):
        self.fenetre.ui.vuePlateau.setDragMode(0)
        curseurPix = QPixmap("img\\curseurEpee.png")#.scaledToHeight(55, Qt.FastTransformation)
        curseurPix.setMask(curseurPix.createHeuristicMask())
        curseurPointe = QCursor(curseurPix, 0, 0)
        self.fenetre.ui.vuePlateau.setCursor(curseurPointe)

    def curseurPinceau(self):
        self.fenetre.ui.vuePlateau.setDragMode(0)
        curseurPix = QPixmap("img\\curseurPinceau.png")
        curseurPinceau = QCursor(curseurPix, 0, curseurPix.height())
        self.fenetre.ui.vuePlateau.setCursor(curseurPinceau)

    def curseurGomme(self):
        self.fenetre.ui.vuePlateau.setDragMode(0)
        curseurPix = QPixmap("img\\gomme.png")#.scaledToHeight(55, Qt.FastTransformation)
        curseurGomme = QCursor(curseurPix, 0, 0)
        self.fenetre.ui.vuePlateau.setCursor(curseurGomme)

    def curseurSeringue(self):
        self.fenetre.ui.vuePlateau.setDragMode(0)
        curseurPix = QPixmap("img\\curseurSeringue.png")
        curseurSeringue = QCursor(curseurPix, 0, 0)
        self.fenetre.ui.vuePlateau.setCursor(curseurSeringue)

    def curseurEpee(self, valide = True):
        self.fenetre.ui.vuePlateau.setDragMode(0)
        if valide:
            curseurPix = QPixmap("img\\curseurEpee.png")
        curseurSeringue = QCursor(curseurPix, 0, 0)
        self.fenetre.ui.vuePlateau.setCursor(curseurSeringue)

    def curseurArc(self):
        self.fenetre.ui.vuePlateau.setDragMode(0)
        curseurPix = QPixmap("img\\arc.png")
        curseurSeringue = QCursor(curseurPix, curseurPix.width(), 0)
        self.fenetre.ui.vuePlateau.setCursor(curseurSeringue)

    def curseurBaguette(self):
        self.fenetre.ui.vuePlateau.setDragMode(0)
        curseurPix = QPixmap("img\\baguette.png")
        curseurBaguette = QCursor(curseurPix, curseurPix.width(), 0)
        self.fenetre.ui.vuePlateau.setCursor(curseurBaguette)
        
        
    ############

    ##### activation des differents modes d'interaction avec le plateau et mises a jour des principaux parametres  #######
    def plateauModeCreation(self):
        self.fenetre.majVisibilitePanneauxPlateau("creation")
        self.modePrincipal = "creation"

    def plateauModeCombat(self):
        self.fenetre.majVisibilitePanneauxPlateau("combat")
        self.modePrincipal = "combat"
        
    def majModeAffichage(self, index):
        """met a jour le mode d'affichage"""
        nouveauMode = ""
        if index == 0:
            #passe a l'affichage standard
            pass
        elif index == 1:
            #passe en mode affichage de l'altitude
            nouveauMode = "altitude"    
        elif index == 2:
            #affichage des terrains slt
            nouveauMode = "terrain"
        elif index == 3:
            #affichage tactique
            nouveauMode = "tactique"
            
        for coord in self.cases:
            self.cases[coord].majAffichageSpecial(nouveauMode)

    def modePeintureCase(self):
        """enclenche le mode peinture de case a partir de la couleur selectionnee"""
        self.majMode("standard")
        couleur = self.chercherCouleur()
        if couleur.isValid():
            self.majMode("caseMajTerrain", couleur)
        else:
            self.majMode("standard")

    def modePeintureCase_perso(self):
        origine = self.sender().objectName()
        index = int(origine.replace("terrainCouleurPerso",""))-1
        couleur = QColor(QColorDialog(self.fenetre.ui.vuePlateau).customColor(index))
        if couleur.isValid():
            self.majMode("caseMajTerrain", couleur)
        else:
            self.majMode("standard")            

    def modeCopieTerrain(self):
        """enclenche le mode copie de case"""
        self.majMode("caseCopie") 

    def modeCaseEffet(self):
        """enclenche le mode de mise a jour de l'ffet actif des cases"""
        self.majMode("standard")
        origine = self.sender().objectName()
        if origine == "effFeu":
            effet = "brule"
        elif origine == "effEau":
            effet = "eau"
        elif origine == "effGlace":
            effet = "glace"   
        elif origine == "effPoison":
            effet = "poison"   
        elif origine == "effEffacer":
            effet = "aucun"   
            
        self.majMode("caseMajEffet", effet)
        self.fenetre.ui.vuePlateau.setFocus()

    def modeCreationPion(self):
        """enclenche le mode de creation de pions simples"""
        self.majMode("pionCreation")

    def majModePionSupprimer(self):
        """enclenche le mode suppression de pions sur clic gauche (creatures ou decors)"""
        self.majMode("pionSupprimer")        
    
    def modeCreationDecor(self, ligne, col):
        """enclenche le mode de creation de decors depuis la liste des decors"""
        index = self.fenetre.ui.listDecors.item(ligne, 0)
        decor = charger("lib\\biblio\\decor", str(index.text().toUtf8()))
        self.majMode("pionDecorCreation", decor)
        self.fenetre.ui.vuePlateau.setFocus()
        
    def modeCreationCreaturePion(self, ligne, col):
        """enclenche le mode de creation de pions depuis la liste des creatures"""
        index = self.fenetre.ui.listCreatures.item(ligne, 0)
        creature = charger("lib\\biblio\\creature", str(index.text().toUtf8()))
        self.majMode("pionCreation", creature)
        self.fenetre.ui.vuePlateau.setFocus()

    def modeMajTerrainCase(self, ligne, col):
        """enclenche le mode permettant la mise a jour du terrain des cases"""
        index = self.fenetre.ui.listTerrains.item(ligne, 0)
        terrain = charger("lib\\biblio\\terrain", str(index.text().toUtf8()))
        self.majMode("caseMajTerrain", terrain)
        self.fenetre.ui.vuePlateau.setFocus()

    def majCouleurPion(self):
        """selectionne une nouvelle couleur"""
        self.majMode("standard")
        couleur = self.chercherCouleur()
        if couleur.isValid():
            self.modeParam["couleurPion"] = couleur
            self.fenetre.ui.pionCouleur.setStyleSheet("QPushButton {backGround:%s}" %(self.modeParam["couleurPion"].name()))
            
    def majEpaisseurPinceau(self, epaisseur):
        """met a jour l'epaisseur du pinceau (en cases)"""
        self.fenetre.ui.valeurEpaisseurPinceau.setText(QString.fromUtf8(str(epaisseur)))
        self.epaisseurPinceau = int(epaisseur)

    def modeMajAltitudeCase(self):
        self.majMode("caseMajAltitude")

    def majModeForme(self):
        """met a jour la forme utilisee pour la peinture"""
        bouton = self.sender().objectName()
        if bouton == "formeSimple":
            self.modeParam["typeFormeDessin"] = "simple"
        elif bouton == "formeLigne":
            self.modeParam["typeFormeDessin"] = "ligne"
        elif bouton == "formeLigneOrientee":
            self.modeParam["typeFormeDessin"] = "frontiere"
        elif bouton == "formeEllipseVide":
            self.modeParam["typeFormeDessin"] = "ellipseV"
        elif bouton == "formeEllipsePlein":
            self.modeParam["typeFormeDessin"] = "ellipseP"
        elif bouton == "formeRectVide":
            self.modeParam["typeFormeDessin"] = "rectV"
        elif bouton == "formeRectPlein":
            self.modeParam["typeFormeDessin"] = "rectP"

        if self.modeActif[0:7] != "caseMaj":    
            self.majMode("caseMajTerrain", self.modeParam["terrain"])

    def majAffichageMenuCache(self):
        """un bouton 'cache' a ete clique, on met a jour les infos""" 
        origine = self.sender().objectName()
        index = int(origine.replace("plateauCache",""))
        self.cacheEnCours = index
        for i in range(1,5):
            bouton = self.fenetre.ui.outilsEditionPlateau.findChild(QToolButton, "plateauCache{}".format(i))
            bouton.setCheckable(True)
            bouton.setChecked((i == index))
        self.fenetre.ui.cacheActif.setChecked(self.caches[index]["actif"])
        self.voirCacheEnCours()

    def majModeCombatDeplacement(self):
        """active le mode de combat 'deplacement' (mode standard)"""
        self.majModeCombat("combatDeplacement")

    def majModeCombatAttaqueCaC(self):
        """active le mode de combat 'corps-a-corps'"""
        self.majModeCombat("combatAttaqueCaC")

    def majModeCombatAttaqueDist(self):
        """active le mode de combat 'attaque a distance'"""
        self.majModeCombat("combatAttaqueDist")

    def majModeCombatZone(self):
        if not len(self.modeParam["typeAttaqueZone"]) > 0: self.modeParam["typeAttaqueZone"] = "ligne"
        self.majModeCombat("combatAttaqueZone")        

    def majModeCombatZoneForme(self):
        if self.modeCombat == "combatAttaqueZone":
            origine = self.sender().objectName()
            self.modeParam["typeAttaqueZone"] = str(origine).split("_")[1]
            self.majModeCombat("combatAttaqueZone")

    def majModeDefinirEntree(self):
        self.modeParam["entreeSortie"] = EntreeSortie(self, "E")
        self.modeParam["entreeSortie"].creerForme()
        self.majMode("placementEntreeSortie")

    def majModeDefinirSortie(self):
        self.modeParam["entreeSortie"] = EntreeSortie(self, "S")
        self.modeParam["entreeSortie"].creerForme()
        self.majMode("placementEntreeSortie")

    def majModeZonePlacement(self):
        self.majMode("majZonePlacement")
    
    def majMode(self, mode = "standard", param = None):
        """modifie ou reinitialise le type d'interaction avec le plateau"""   
        reinit = True    #doit-on reinitialiser a la fin de l'operation
        ##on desactive le mode precedent
        if self.pionSelectionne() != None:
            self.pionSelectionne().afficheOmbreSelection(False)
            if self.modeActif == "pionSelectionne":    
                 self.majModeCombat("")   
            self.modeParam["numPionSelectionne"] = 0
        elif self.pionDecorSelectionne() != None:
            self.pionDecorSelectionne().afficheOmbreSelection(False)
            self.modeParam["numPionSelectionne"] = 0

        if self.modeActif == "pionSelectionne" or self.modeActif == "pionCreation" or self.modeActif == "pionDecorSelectionne" or self.modeActif == "pionDecorCreation":  
            self.majProjectionPosition(False)
            self.modeParam["formeProjectionPosition"] = None
            self.modeParam["coordProjectionPosition"] = None
            self.modeParam["nbRotations"] = 0
                
        if self.modeActif[0:7] == "caseMaj" or self.modeActif == "cachePlacer" or self.modeActif == "majZonePlacement":
            if self.modeParam["formeDessin"] != None:
                self.modeParam["formeDessin"].prepareGeometryChange()
                self.removeItem(self.modeParam["formeDessin"])    
            self.modeParam["formeDessin"] = None
            self.modeParam["origineFormeDessin"] = None
            self.modeParam["point2FormeDessin"] = None
            
            self.afficherListeCases(self.modeParam["listeCasesFormeDessin"], False)
            self.modeParam["listeCasesFormeDessin"] = []

        if self.modeActif == "placementEntreeSortie":            
            if self.modeParam["entreeSortie"] != None:
                self.modeParam["entreeSortie"].prepareGeometryChange()
                self.removeItem(self.modeParam["entreeSortie"])
                self.modeParam["entreeSortie"] = None
   
        ### definition du nouveau mode
        if mode in self.listMode and mode != "standard":
            self.modeActif = mode
            reinit = False
            if mode == "caseMajTerrain":
                #curseur pinceau, on ajoute des terrains au cases
                if param != None:
                    self.curseurPinceau()
                    self.fenetre.ui.vuePlateau.setDragMode(0)
                    self.modeParam["terrain"] = param                
                    
            elif mode == "caseCopie":
                #curseur seringue, on 'preleve' le terrain sur la case cliquee, avant de passer en mode majTerrain
                self.curseurSeringue()
                self.fenetre.ui.vuePlateau.setDragMode(0)

            elif mode == "caseMajEffet":
                #on met a jour l'effet actif sur les cases
                if param != None:
                    self.curseurPinceau()
                    self.fenetre.ui.vuePlateau.setDragMode(0)
                    self.modeParam["effet"] = param                

            elif mode == "caseMajAltitude":
                self.curseurPinceau()
                self.fenetre.ui.vuePlateau.setDragMode(0)                           

            elif mode == "cachePlacer":
                self.curseurPinceau()
                self.fenetre.ui.vuePlateau.setDragMode(0)
                self.modeParam["typeFormeDessin"] = "rectP"

            elif mode == "majZonePlacement":
                self.curseurPinceau()
                self.fenetre.ui.vuePlateau.setDragMode(0)
                self.modeParam["typeFormeDessin"] = "rectP"

            elif mode == "placementEntreeSortie":
                self.fenetre.ui.vuePlateau.setDragMode(0)               
                
            elif mode == "pionDecorCreation":
                #curseur 'plus', on cree de nouveaux decors
                self.modeParam["decor"] = None
                self.fenetre.ui.vuePlateau.setDragMode(0)
                self.modeParam["formeProjectionPosition"] = Forme(self.formeCases)
                self.modeParam["nbRotations"] = 0
                if param != None:
                    if param.__class__.__name__ == "Decor":
                         self.modeParam["decor"] = param
                         self.modeParam["formeProjectionPosition"].definirForme(self.modeParam["decor"].formeDef[self.formeCases])

            elif mode == "pionDecorSelectionne":
                #un pion decor est selectionne
                if param != None:
                    self.modeParam["numPionSelectionne"] = param
                    self.pionDecorSelectionne().afficheOmbreSelection(True)
                    self.fenetre.ui.vuePlateau.setCursor(QCursor(Qt.ArrowCursor))
                    self.modeParam["formeProjectionPosition"] = Forme(self.formeCases)
                    self.modeParam["formeProjectionPosition"].definirForme(self.pionDecorSelectionne().forme.formeDef)
                    self.modeParam["nbRotations"] = self.pionDecorSelectionne().nbRotations 

            elif mode == "pionCreation":
                #curseur 'plus', on cree de nouveaux pions
                self.modeParam["creature"] = None
                self.fenetre.ui.vuePlateau.setDragMode(0)
                self.modeParam["formeProjectionPosition"] = Forme(self.formeCases)
                self.modeParam["nbRotations"] = 0
                if param != None:
                    if param.__class__.__name__ == "Creature":
                         self.modeParam["creature"] = param
                         self.modeParam["formeProjectionPosition"].definirForme(self.modeParam["creature"].formeDef[self.formeCases])
                
            elif mode == "pionSupprimer":
                #mode suppression de pions/pions decors
                self.curseurGomme()
                self.fenetre.ui.vuePlateau.setDragMode(0)

            elif mode == "pionSelectionne":
                #un pion est selectionne, on affiche les deplacements possibles
                if param != None:
                    self.modeParam["numPionSelectionne"] = param
                    self.pionSelectionne().afficheOmbreSelection(True)
                    self.numPionEnCours = param
                    for i in range(0, self.fenetre.ui.infoOrdreJeu.rowCount()):
                        if str(self.fenetre.ui.infoOrdreJeu.item(i, 0).text().toUtf8()) == str(param):
                            self.fenetre.ui.infoOrdreJeu.setCurrentCell(i,0)
                            
                    self.majAffichagePionSelectionne()
                    self.majListeAttributs()
                    self.afficherNotesPion()
                    self.majListeAttaques()
                    self.majModeCombat("aucun")                  

        elif not mode in self.listMode:
            print("mode non reconnu")

        ##on reinitialise si necessaire    
        if reinit:
            #mode standard : pas d'interaction avec les cases, on deplace le plateau en le saisissant ou les pions en cliquant dessus
            self.modeActif = "standard"
            self.majAffichagePionSelectionne()
            self.majInfosPion()
            self.majInfosDecor()
            self.majListeAttributs()
            self.majListeAttaques()
            self.afficherNotesPion()
            self.fenetre.majVisibiliteBarreCombat("menu")
            QApplication.processEvents()
            self.fenetre.ui.vuePlateau.setCursor(QCursor(Qt.ArrowCursor))
            self.fenetre.ui.vuePlateau.setDragMode(1)
        else:
            self.fenetre.ui.vuePlateau.setFocus()

    def majModeCombat(self, mode = ""):
        """met a jour le mode de combat actif pour le pion selectionne"""
        ## on desactive le mode precedent si besoin
        #la projection de position
        
        if self.modeCombat == "combatDeplacement":
            #le champ de deplacement
            if self.modePrincipal == "combat":
                self.afficherChampDeplacement(False)
            self.majProjectionPosition(False)
            self.modeParam["formeProjectionPosition"] = None
            self.modeParam["coordProjectionPosition"] = None
            self.modeParam["nbRotations"] = 0    
                
        elif self.modeCombat == "combatAttaqueCaC":        
            #la zone d'attaque au cac
            self.materialiserPions(True)
            self.majZoneAttaqueCaC(False)
            self.modeParam["zoneAttaqueCaC"] = []
            if self.modeParam["cibleAttaqueCaC"] != None:
                self.modeParam["cibleAttaqueCaC"].estCibleAttaque(False)
                self.modeParam["cibleAttaqueCaC"] = None
                
        elif self.modeCombat == "combatAttaqueDist":
            self.materialiserPions(True)
            self.majLigneMireAttaqueDist()
            
        elif self.modeCombat == "combatAttaqueZone":  
            #l'attaque de zone
            self.materialiserPions(True)
            QApplication.processEvents()
            self.reinitAttaqueZone()
            if mode != "combatAttaqueZone": self.fenetre.majVisibiliteBarreCombat("menu")
            self.modeParam["listeCasesAttaqueZone"] = []
               
        ## maj de l'aspect des boutons selon le mode demande  
        for item in self.fenetre.ui.barreBasCombat.children():
            if item.__class__.__name__ == "QToolButton":
                if item.isCheckable():
                    item.setChecked((item.objectName() == mode and self.pionSelectionne() != None))
                    if mode == "combatAttaqueZone":
                        item.setChecked((item.objectName() == "combatZone_{}".format(self.modeParam["typeAttaqueZone"])\
                                                  and self.pionSelectionne() != None))    
        
        ## definition du nouveau mode de combat
        if self.pionSelectionne() != None:
            self.modeCombat = mode
            self.fenetre.ui.vuePlateau.setDragMode(0)
            self.fenetre.ui.combatVol_altitude.setValue(self.pionSelectionne().z)
            if mode == "aucun":
                self.fenetre.ui.vuePlateau.setCursor(QCursor(Qt.ArrowCursor))
            
            if mode == "combatDeplacement":
                self.fenetre.ui.vuePlateau.setCursor(QCursor(Qt.ArrowCursor))
                self.modeParam["formeProjectionPosition"] = Forme(self.formeCases)
                self.modeParam["formeProjectionPosition"].definirForme(self.pionSelectionne().forme.formeDef)
                self.modeParam["nbRotations"] = self.pionSelectionne().nbRotations

                if self.modePrincipal == "combat":
                    #si mode combat, affichage de la zone de deplacement
                    self.afficherChampDeplacement(True)
                         
            elif mode == "combatAttaqueCaC":
                self.curseurEpee()
                self.materialiserPions(False)
                self.modeParam["zoneAttaqueCaC"] = self.zone(self.pionSelectionne().position, self.pionSelectionne().creature.allonge, True, True)
                self.majZoneAttaqueCaC(True)
                
            elif mode == "combatAttaqueDist":
                self.curseurArc()
                self.materialiserPions(False)

            elif mode == "combatAttaqueZone":
                self.curseurBaguette()
                self.materialiserPions(False)
                self.majFormeAttaqueZone()
        else:
            self.fenetre.ui.combatVol_altitude.setValue(0)
            
    ###############

    ########## Gestion du combat ##############
    def majAffichageTour(self):
        """met a jour l'affichage du tour en cours"""
        self.fenetre.ui.combatTour.setText(QString.fromUtf8("Tour: {}".format(self.tour)))

    def majAffichagePionSelectionne(self):
        """affiche le nom et le logo du pion actuellement selectionne"""
        if self.pionSelectionne() != None:
            self.fenetre.ui.combatPionSelectionne.setText(QString.fromUtf8(self.pionSelectionne().txtId()))
            if len(self.pionSelectionne().creature.img["nom"]) > 0:
                pix = QPixmap(QString.fromUtf8("img\\"+self.pionSelectionne().creature.img["nom"]))
                pix = pix.scaled(44, 44, Qt.KeepAspectRatio, Qt.SmoothTransformation)
                self.fenetre.ui.combatPionSelectionne_img.setPixmap(pix)
            else:    
                self.fenetre.ui.combatPionSelectionne_img.setPixmap(QPixmap())    
        else:
            self.fenetre.ui.combatPionSelectionne_img.setPixmap(QPixmap())  
            self.fenetre.ui.combatPionSelectionne.setText(QString.fromUtf8("Pas de pion selectionné"))

    def initListeOrdreJeu(self):
        """cree les colonnes et met en forme la table ordre jeu"""
##        self.fenetre.ui.infoOrdreJeu.setColumnWidth(0, 20)
        self.fenetre.ui.infoOrdreJeu.setColumnWidth(2, 30)
        self.fenetre.ui.infoOrdreJeu.hideColumn(0)
##        self.fenetre.ui.infoOrdreJeu.hideColumn(2)      
        self.fenetre.ui.infoOrdreJeu.setIconSize(QSize(30,20))   
            
    def majListeOrdreJeu(self):
        """met a jour la liste des pions infoOrdreJeu"""
        while self.fenetre.ui.infoOrdreJeu.rowCount() > 0:
            self.fenetre.ui.infoOrdreJeu.removeRow(0)
        index = 0
        for num in self.ordreJeu:
            self.fenetre.ui.infoOrdreJeu.insertRow(int(index))
            self.fenetre.ui.infoOrdreJeu.setItem(int(index), 0, QTableWidgetItem(QString.fromUtf8(str(num))))
            icon = QIcon("img\\"+self.pions[num].creature.logo)
            item = QTableWidgetItem(icon,QString.fromUtf8(self.pions[num].txtId()))
            self.fenetre.ui.infoOrdreJeu.setItem(int(index), 1, item)
            self.fenetre.ui.infoOrdreJeu.setItem(int(index), 2, QTableWidgetItem(QString.fromUtf8(str(self.ordreJeu[num]))))
            index += 1

        self.fenetre.ui.infoOrdreJeu.sizeHintForColumn(1)
##        trierTable(self.fenetre.ui.infoOrdreJeu, 2, 0)

    def clicListOrdreJeu(self, ligne, col):
        """on a clique dans la liste d'ordre de jeu, le pion correspondant est selectionne et centre sur la carte"""
        numPion = int(self.fenetre.ui.infoOrdreJeu.item(ligne, 0).text().toUtf8())  
        self.fenetre.ui.vuePlateau.centerOn(self.cases[self.pions[numPion].position].centreGraphique)
        self.pionSaisir(numPion)

    def pionSuivant(self):
        """selection du pion suivant dans la liste d'ordre de jeu"""
        if self.numPionEnCours in self.pions:
            suivant = self.ordreJeu[self.numPionEnCours] + 1
        else:
            suivant = 1
        if suivant > len(self.ordreJeu):
            self.tour += 1
            self.majAffichageTour()
            suivant = 1
        for num in self.ordreJeu:
            if self.ordreJeu[num] == suivant:
                numPion = num
                break

        for ligne in range(0, self.fenetre.ui.infoOrdreJeu.rowCount()):
            item = self.fenetre.ui.infoOrdreJeu.item(ligne, 0)
            item.setSelected(int(self.fenetre.ui.infoOrdreJeu.item(ligne, 0).text().toUtf8()) == numPion)
            if int(item.text().toUtf8()) == numPion:
                self.fenetre.ui.infoOrdreJeu.scrollToItem(item)

        self.fenetre.ui.vuePlateau.centerOn(self.cases[self.pions[numPion].position].centreGraphique)
        self.pionSaisir(numPion)        
 
    def afficheEcranGestionCombat(self):
        #*egc
        """affiche l'ecran de gestion du combat"""
        self.gestionCombat = EcranGestionCombat(self)
        self.gestionCombat.show()
        self.connect(self.fenetre, SIGNAL("majListesPions"), self.majListesPions)
        self.connect(self.gestionCombat, SIGNAL("majListesPions"), self.majListesPions)
        QApplication.processEvents()
##        r = self.gestionCombat.exec_()

    def majOrdreJeu(self):
        """met a jour l'ordre de jeu des pions en fonction de l'attribut prevu par les regles s'il existe,
           ou en fonction de l'ordre de jeu parametre sinon"""
        attribut = regles.attributOrdreJeu()
        if attribut != None:
            dico = {}
            for numPion in self.pions:
                dico[numPion] = int(self.pions[numPion].lstCarac[attribut])
            ordre = sorted(dico, key = dico.get, reverse=(regles.sensTriOrdreJeu() == 1)) 
            self.ordreJeu = {}    
            for numPion in self.pions:
                self.ordreJeu[numPion] = ordre.index(numPion) + 1
        self.majListeOrdreJeu()  

    def pionDeplacerDansOrdreJeu(self, numPion, nouvellePosition):
        """deplace un pion dans le dictionnaire gerant l'ordre de jeu de maniere a assurer sa coherence
           nouvellePosition = 0 supprime le pion de la liste"""
        if numPion in self.ordreJeu:
            if nouvellePosition == 0:
                del self.ordreJeu[numPion]
        if len(self.ordreJeu) > 0:        
            i = 0    
            tmp = sorted(self.ordreJeu, key=self.ordreJeu.get)
            if numPion in tmp:
                tmp.remove(numPion)
            for num in tmp:
                i += 1
                if i == nouvellePosition:
                    self.ordreJeu[numPion] = i
                    i += 1
                self.ordreJeu[num] = i
            if i < nouvellePosition:
                self.ordreJeu[numPion] = i + 1 
        elif nouvellePosition > 0:
            self.ordreJeu[numPion] = 1
        self.majOrdreJeu()
        
    def majListeAttributs(self):
        """met a jour la liste des attributs dans le panneau de combat"""
        self.fenetre.ui.listeAttributs.setColumnWidth(0, (0.4*self.fenetre.ui.listeAttributs.width())) 
        self.fenetre.ui.listeAttributs.setColumnWidth(1, (0.4*self.fenetre.ui.listeAttributs.width()))
        self.disconnect(self.fenetre.ui.listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee)
        
        #on vide la liste
        while self.fenetre.ui.listeAttributs.rowCount() > 0:
            self.fenetre.ui.listeAttributs.removeRow(0)
        self.fenetre.ui.listeAttributs.setVisible((self.pionSelectionne() != None))    
        if self.pionSelectionne() != None:        
            #creation des lignes de base    
            lignesBase = ["Nom","Etat","Alt."]   #attention: modifier aussi dans listeAttributCelluleModifiee
            for i in range(0, 10):    #10 premieres colonnes reservees pour les infos de base
                self.fenetre.ui.listeAttributs.insertRow(i)
                item = QTableWidgetItem()
                if i < len(lignesBase):
                    item.setText(QString.fromUtf8(lignesBase[i]))
                item.setFlags(Qt.NoItemFlags)    
                self.fenetre.ui.listeAttributs.setItem(i, 0, item)
                self.fenetre.ui.listeAttributs.setRowHidden(i, (i >= len(lignesBase)))

            #maj des donnees de base    
            self.fenetre.ui.listeAttributs.setItem(lignesBase.index("Nom"), 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().nom))))
            self.fenetre.ui.listeAttributs.setItem(lignesBase.index("Etat"), 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().etat))))
            self.fenetre.ui.listeAttributs.setItem(lignesBase.index("Alt."), 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().z))))
            
            #attributs issus des regles utilisees    
            ordre = regles.ordreAttributs()
            for elt in ordre:
                ligne = 10 + ordre.index(elt)
                self.fenetre.ui.listeAttributs.insertRow(ligne)
                item = QTableWidgetItem(QString.fromUtf8(elt))
                item.setFlags(Qt.NoItemFlags)
                self.fenetre.ui.listeAttributs.setItem(ligne, 0, item)
                self.fenetre.ui.listeAttributs.setItem(ligne, 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().lstCarac[elt]))))
                
            self.connect(self.fenetre.ui.listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee)
            
    def listeAttributCelluleModifiee(self, ligne, colonne):
        """une cellule de la liste des attributs a ete modifiee"""
        if colonne != 1:
            print("valeur non modifiable")
        else:
            #on verifie la validite de la donnee entree
            lignesBase = ["Nom","Etat","Alt."]   #attention: modifier aussi dans majListeAttribut
            if ligne < len(lignesBase):
                pass
            elif ligne >= 10:
                attribut = regles.ordreAttributs()[(ligne - 10)]
                nouvelleVal = str(self.fenetre.ui.listeAttributs.item(ligne, 1).text().toUtf8())
                valVerifiee = regles.listeControle()[attribut].controler(nouvelleVal)
                if valVerifiee != None:
                    self.pionSelectionne().lstCarac[attribut] = valVerifiee
                    if attribut == regles.attributOrdreJeu():
                        print("maj ordre (a implementer)")
                else:    
                    self.fenetre.ui.listeAttributs.setItem(ligne, 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().lstCarac[attribut]))))

    def initListeAttaques(self):
        """met en forme et connecte la liste des attaques du pion"""
        self.fenetre.ui.listeAttaques.setColumnWidth(0, 0) 
        self.fenetre.ui.listeAttaques.setColumnWidth(1, (0.3*self.fenetre.ui.listeAttaques.width()))
        self.fenetre.ui.listeAttaques.setColumnWidth(2, (0.7*self.fenetre.ui.listeAttaques.width()))
        self.connect(self.fenetre.ui.listeAttaques, SIGNAL("itemSelectionChanged()"), self.majInfosAttaqueEC)
        self.connect(self.fenetre.ui.listeAttaques, SIGNAL("cellClicked(int, int)"), self.listeAttaquesCelluleCliquee)
        self.connect(self.fenetre.ui.notesAttaqueEC, SIGNAL("textChanged()"), self.majNotesAttaqueEC)
        self.fenetre.ui.listeAttributsAttaqueEC.setColumnWidth(0, (0.49*self.fenetre.ui.listeAttributsAttaqueEC.width())) 
        self.fenetre.ui.listeAttributsAttaqueEC.setColumnWidth(1, (0.5*self.fenetre.ui.listeAttributsAttaqueEC.width()))
        
    def majListeAttaques(self):
        #*eea
        """met a jour la liste des attaques du pion dans le panneau de combat"""
        #on vide la liste
        while self.fenetre.ui.listeAttaques.rowCount() > 0:
            self.fenetre.ui.listeAttaques.removeRow(0)
            
        self.fenetre.ui.listeAttaques.setVisible((self.pionSelectionne() != None))
        self.fenetre.ui.titreAttaques.setVisible((self.pionSelectionne() != None))
        self.fenetre.ui.editerAttaques.setVisible((self.pionSelectionne() != None))
        self.fenetre.ui.panneauAttaqueEC.setVisible((self.pionSelectionne() != None))

        i = 0
        if self.pionSelectionne() != None:        
            for attaque in self.pionSelectionne().attaques:
                self.fenetre.ui.listeAttaques.insertRow(i)
                self.fenetre.ui.listeAttaques.setItem(i, 0, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().attaques.index(attaque)))))
                icone = None
                if attaque.typ == "cac":
                    icone = QIcon("img\\curseurEpee.png")
                if attaque.typ == "dist":
                    icone = QIcon("img\\arc.png")
                if attaque.typ == "zone":
                    icone = QIcon("img\\baguette.png")
                if icone != None:
                    self.fenetre.ui.listeAttaques.setItem(i, 1, QTableWidgetItem(icone, QString.fromUtf8("")))
                self.fenetre.ui.listeAttaques.setItem(i, 2, QTableWidgetItem(QString.fromUtf8(attaque.nom)))
        self.majInfosAttaqueEC()                                                 

    def listeAttaquesCelluleCliquee(self, ligne, colonne):
        """on a clique sur une cellule de la liste des attaques"""
        numAttaque = int(str(self.fenetre.ui.listeAttaques.item(ligne, 0).text().toUtf8()))
        if numAttaque >= 0:
            self.utiliserAttaque(numAttaque)  

    def utiliserAttaque(self, numAttaque):
        """le pion selectionne utilise son attaque n"""
        if self.pionSelectionne() != None:
            if numAttaque < len(self.pionSelectionne().attaques):
                attaque = self.pionSelectionne().attaques[numAttaque]
                if attaque.typ == "cac":
                    self.majModeCombat("combatAttaqueCaC")
                if attaque.typ == "dist":
                    self.majModeCombat("combatAttaqueDist")                
                if attaque.typ == "zone":
                    self.modeParam["typeAttaqueZone"] = attaque.formeZone
                    self.fenetre.ui.combatZone_disqueRayon.setValue(attaque.rayon)
                    self.majModeCombat("combatAttaqueZone")

    def majInfosAttaqueEC(self):
        #*aec
        """met a jour les infos de l'attaque en cours (selectionnee)"""
        selection = self.fenetre.ui.listeAttaques.selectedItems()
        self.fenetre.ui.panneauAttaqueEC.setVisible(self.pionSelectionne() != None and len(selection) > 0)
        if self.pionSelectionne() != None and len(selection) > 0:
            ligne = selection[0].row()
            numAttaque = int(str(self.fenetre.ui.listeAttaques.item(ligne, 0).text().toUtf8()))
            self.disconnect(self.fenetre.ui.listeAttributsAttaqueEC, SIGNAL("cellChanged(int,int)"), self.attaqueECCelluleModifiee)
            #on vide la liste
            while self.fenetre.ui.listeAttributsAttaqueEC.rowCount() > 0:
                self.fenetre.ui.listeAttributsAttaqueEC.removeRow(0)
                
            self.fenetre.ui.listeAttributsAttaqueEC.insertRow(0)
            self.fenetre.ui.listeAttributsAttaqueEC.setItem(0, 0, QTableWidgetItem(QString.fromUtf8("numAtt")))
            self.fenetre.ui.listeAttributsAttaqueEC.setItem(0, 1, QTableWidgetItem(QString.fromUtf8(str(numAttaque))))
            self.fenetre.ui.listeAttributsAttaqueEC.setRowHidden(0, True)
            
            #attributs issus des regles utilisees    
            ordre = regles.ordreAttributsAttaques()
            for elt in ordre:
                ligne = 1 + ordre.index(elt)
                self.fenetre.ui.listeAttributsAttaqueEC.insertRow(ligne)
                item = QTableWidgetItem(QString.fromUtf8(elt))
                item.setFlags(Qt.NoItemFlags)
                self.fenetre.ui.listeAttributsAttaqueEC.setItem(ligne, 0, item)
                self.fenetre.ui.listeAttributsAttaqueEC.setItem(ligne, 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().attaques[numAttaque].attributs[elt]))))
                
            self.connect(self.fenetre.ui.listeAttributsAttaqueEC, SIGNAL("cellChanged(int,int)"), self.attaqueECCelluleModifiee)
            #maj des notes
            self.disconnect(self.fenetre.ui.notesAttaqueEC, SIGNAL("textChanged()"), self.majNotesAttaqueEC)
            self.fenetre.ui.notesAttaqueEC.setText(QString.fromUtf8(self.pionSelectionne().attaques[numAttaque].notes))
            self.connect(self.fenetre.ui.notesAttaqueEC, SIGNAL("textChanged()"), self.majNotesAttaqueEC)
            
    def attaqueECCelluleModifiee(self, ligne, colonne):
        """une cellule de la liste d'attributs de l'attaque en cours a ete modifiee"""
        pass

    def majNotesAttaqueEC(self):
        """met a jour les notes de l'attaque en cours (selectionnee)"""
        selection = self.fenetre.ui.listeAttaques.selectedItems()
        self.fenetre.ui.panneauAttaqueEC.setVisible(self.pionSelectionne() != None and len(selection) > 0)
        if self.pionSelectionne() != None and len(selection) > 0:
            ligne = selection[0].row()
            numAttaque = int(str(self.fenetre.ui.listeAttaques.item(ligne, 0).text().toUtf8()))        
            self.pionSelectionne().attaques[numAttaque].notes = str(self.fenetre.ui.notesAttaqueEC.toPlainText().toUtf8())

    def afficheEcranEditionAttaques(self):
        """affiche l'ecran d'edition/creation d'attaques"""
        if self.pionSelectionne() != None:
            self.editionAttaques = QDialog()
            frame = EcranEditionAttaques(self.pionSelectionne())
            frame.setParent(self.editionAttaques)
            self.editionAttaques.setAttribute(Qt.WA_DeleteOnClose) 
            r = self.editionAttaques.exec_()
            del self.editionAttaques
            self.majListeAttaques()

    def majNotesPion(self):
        """les notes du pion ont ete mises a jour"""
        if self.pionSelectionne() != None:
            self.pionSelectionne().notes = str(self.fenetre.ui.notesPion.toPlainText().toUtf8())
        else:
            pass

    def afficherNotesPion(self):
        """affiche les notes du pion selectionne dans le QTextEdit dedie"""
        self.fenetre.ui.notesPion.setVisible((self.pionSelectionne() != None))
        if self.pionSelectionne() != None:
            self.fenetre.ui.notesPion.setText(QString.fromUtf8(self.pionSelectionne().notes))
            
    ###############

    ############### fonctions de calcul ################ 
    def zone(self, origine, distance, z=0, conditionFranchissable = False, conditionVisible = False):
        """renvoie un dictionnaire representant la liste des coordonnees des cases comprises dans la zone
           la zone en question est la liste des cases situees a une distance d des coordonnees d'origine
           z = 0 -> hauteur z de l'origine par rapport a l'altitude de la case
           conditionFranchissable = Vrai -> les cases infranchissables ne sont pas prises en compte
           conditionVisible = Vrai -> les cases bloquant la visibilite ne sont pas prises en compte
           [cf methode A* (A-star)]"""
        
        aVerifier = []
        aVerifier2 = []
        resultat = {}
        k = 0           
        #on part de la premiere case, puis on itere a partir de chaque nouveau depart
        if origine in self.cases:
            aVerifier.append(origine)
            while k <= distance:
                for depart in aVerifier:
                    for coord in self.cases[depart].voisins:
                         if not coord in aVerifier and not coord in aVerifier2 and not coord in resultat:
                              if conditionFranchissable and not conditionVisible:
                                   if self.cases[coord].estFranchissable(z):
                                       aVerifier2.append(coord)
                              elif not conditionFranchissable and conditionVisible:          
                                   if self.cases[coord].terrain.visibilite:
                                       aVerifier2.append(coord)
                              elif conditionFranchissable and conditionVisible:          
                                   if self.cases[coord].estFranchissable(z) and self.cases[coord].terrain.visibilite:
                                       aVerifier2.append(coord)
                              else:
                                   aVerifier2.append(coord)      
                for elt in aVerifier:
                    resultat[elt] = k
                aVerifier = aVerifier2
                aVerifier2 = []
                k += 1
         
        return resultat

    def coordonneesValides(self, coord):
        """les coordonnees entrees en parametre sont elles celles d'une case du plateau"""
        return (coord[0] >= 0 and coord[1] >= 0 and coord[0] < self.nbCasesX and coord[1] < self.nbCasesY)

    def polygoneAgglo(self, listeCases):
        """renvoie un polygone contruit par agglomeration des polygones des cases de la liste
           les cases doivent etre adjacentes (cases hexagonales ou carrees)"""
        pointsPolygone = []
        segments = []
        case = Case(self)
        
        #on verifie que toutes les cases sont adjacentes les unes aux autres
        valide = True
        if len(listeCases) > 1:
            for coord in listeCases:
                if not len(set(listeCases).intersection(self.lstCoordAdjacentes(coord[0], coord[1]))) > 0: valide = False
        if not len(listeCases) > 0:
            valide = False
        
        if valide:
            #on parcourt les faces des polygones des cases, et on ne garde que ceux qui n'ont pas de case 'en face'
            for coord in listeCases:
                polygone = case.polygone(coord[0], coord[1])
                voisins =  self.lstCoordAdjacentes(coord[0], coord[1])
                for i in range(0, len(voisins)):
                    if not voisins[i] in listeCases:
                       j = i+1
                       if j > len(voisins) - 1:
                           j = 0
                       segments.append(QLineF(polygone[i], polygone[j]))

            #on 'accroche' les segments les uns aux autres, dans l'ordre
            segments2 = [segments[0]]
            for segment2 in segments2:
                for segment in segments:
                    if not QLineF(segment.p1(), segment.p2()) in segments2 and not QLineF(segment.p2(), segment.p1()) in segments2:
                        if sqrt((segment.p1().x()-segment2.p2().x())**2+(segment.p1().y()-segment2.p2().y())**2) < 1:
                            segments2.append(QLineF(segment.p1(), segment.p2()))
                        elif sqrt((segment.p2().x()-segment2.p2().x())**2+(segment.p2().y()-segment2.p2().y())**2) < 1:   
                            segments2.append(QLineF(segment.p2(), segment.p1()))

            pointsPolygone = []
            premierPoint = segments2[0].p1()
            pointsPolygone.append(premierPoint)
            for segment in segments2:
                pointSuivant = segment.p2()
                if pointSuivant != premierPoint:
                     pointsPolygone.append(pointSuivant)

            #creation du polygone
            polygone = QPolygonF()
            for point in pointsPolygone:   
                polygone.append(point)   
        else:
            polygone = None

        return polygone  

    def lstCoordAdjacentes(self, x, y):
        """renvoie la liste des coordonnees adjacentes, sans condition d'existence sur le plateau
           attention: l'ordre est important"""
        if self.formeCases == "H":
            voisins = [(x, y-1), (x+1, y-0.5), (x+1, y+0.5), (x,  y+1), (x-1, y+0.5), (x-1, y-0.5)]         
        else:
            voisins = [(x, y-1), (x+1, y), (x,   y+1), (x-1, y)]
        return voisins                                        

    def coordCentreListeCases(self, listeCases):
        """renvoie les coordonnees centrales d'une liste de cases"""
        retour = None
        if len(listeCases) > 0:
            listeTriee = sorted(listeCases)
            posMilieu = int(len(listeCases)/2)
            retour = listeTriee[posMilieu]
        return retour    

    def coordonneesAuPoint(self, point):
        """renvoie les coordonnees de la case situee au QPointF entre en parametre"""
        coord = None
        if point != None:
            lstObjets = self.fenetre.ui.vuePlateau.scene().items(point)
            for objet in lstObjets:
                if objet:
                    if objet.__class__.__name__ == "Case":
                        coord = (objet.x, objet.y)
                        break       
        return coord            

    def creerOrigineFormeDessin(self, coord):
        """place le point d'origine de la forme de selection"""
        self.modeParam["listeCasesFormeDessin"] = []
        self.modeParam["origineFormeDessin"] = self.cases[coord].centreGraphique
        self.modeParam["point2FormeDessin"] = self.cases[coord].centreGraphique
        self.modeParam["listeCasesFormeDessin"] = [coord]
        self.afficherListeCases(self.modeParam["listeCasesFormeDessin"], True)
        
    def majFormeDessin(self):
        """cree/maj la forme utilisee pour selectionner les cases et met a jour la liste des cases selectionnes"""
        self.afficherListeCases(self.modeParam["listeCasesFormeDessin"], False)
        
        pinceau = QPen()
        pinceau.setColor(QColor("black"))
        point2 = self.modeParam["point2FormeDessin"]
        
        if self.modeParam["typeFormeDessin"] == "simple":
            #pas de forme: on ajoute les cases survolees a la liste des cases
            coordPoint2 = self.coordonneesAuPoint(point2)
            zone = self.zone(coordPoint2, self.epaisseurPinceau-1)
            for coord in zone:
                if not coord in self.modeParam["listeCasesFormeDessin"]:
                    self.modeParam["listeCasesFormeDessin"].append(coord)

        elif self.modeParam["typeFormeDessin"] == "frontiere":
            #droite qui selectionne toutes les cases situees au dessus d'elle
            if self.modeParam["formeDessin"] == None:
                self.modeParam["formeDessin"] = QGraphicsLineItem()
                self.modeParam["formeDessin"].setPen(pinceau)
                self.addItem(self.modeParam["formeDessin"])    
            ligne = QLineF(self.modeParam["origineFormeDessin"], point2)
            orientation = int((1+int(ligne.angle()/22.5))/2)
            ligne.setAngle(orientation*45)
            self.modeParam["formeDessin"].setLine(ligne)
            self.modeParam["listeCasesFormeDessin"] = self.selectionFrontiere()

        else:    
            if self.modeParam["typeFormeDessin"] == "ligne":
                #segment simple
                if self.modeParam["formeDessin"] == None:
                    self.modeParam["formeDessin"] = QGraphicsLineItem()
                    self.modeParam["formeDessin"].setPen(pinceau)
                    self.modeParam["formeDessin"].prepareGeometryChange()
                    self.addItem(self.modeParam["formeDessin"])
                ligne = QLineF(self.modeParam["origineFormeDessin"], point2)
                self.modeParam["formeDessin"].setLine(ligne)
            
            elif self.modeParam["typeFormeDessin"] == "rectV" or self.modeParam["typeFormeDessin"] == "rectP":
                #rectangle
                if self.modeParam["formeDessin"] == None:
                    self.modeParam["formeDessin"] = QGraphicsRectItem()
                    self.modeParam["formeDessin"].prepareGeometryChange()
                    self.modeParam["formeDessin"].setPen(pinceau)
                    self.addItem(self.modeParam["formeDessin"])
                rect = self.rectFormeDessin(self.modeParam["origineFormeDessin"], point2)
                self.modeParam["formeDessin"].setRect(rect)
            
            elif self.modeParam["typeFormeDessin"] == "ellipseV" or self.modeParam["typeFormeDessin"] == "ellipseP":
                #ellipse
                if self.modeParam["formeDessin"] == None:
                    self.modeParam["formeDessin"] = QGraphicsEllipseItem()
                    self.modeParam["formeDessin"].prepareGeometryChange()
                    self.modeParam["formeDessin"].setPen(pinceau)
                    self.addItem(self.modeParam["formeDessin"])
                rect = self.rectFormeDessin(self.modeParam["origineFormeDessin"], point2)
                self.modeParam["formeDessin"].setRect(rect)

            #on liste les cases intersectant la forme
            plein = (self.modeParam["typeFormeDessin"][len(self.modeParam["typeFormeDessin"])-1:] == "P")
            self.modeParam["listeCasesFormeDessin"] = self.casesSousForme(self.modeParam["formeDessin"], plein, self.epaisseurPinceau - 1)      
        self.afficherListeCases(self.modeParam["listeCasesFormeDessin"], True)

    def casesSousForme(self, forme, plein = True, epaisseur = 0):
        """renvoie la liste des cases en collision avec un QGraphicsItem en parametre
            plein = False: pas le contenu de la forme
            epaisseur = renvoie aussi les cases voisines jusqu'a la distance demandee"""
        tmp = []
        listeCases = []
        point1 = None
        point2 = None
        #point 1 et 2
        if forme.__class__.__name__ == "QGraphicsLineItem":
            point1 = forme.line().p1()
            point2 = forme.line().p2()
        elif forme.__class__.__name__ == "QGraphicsRectItem" or forme.__class__.__name__ == "QGraphicsEllipseItem":
            point1 = forme.rect().topLeft()
            point2 = forme.rect().bottomRight()
        else:
            point1 = forme.boundingRect().topLeft()
            point2 = forme.boundingRect().bottomRight()            
 
        #preselection des cases (meilleures perf)    
        if point1 != None and point2 != None and point1 != point2:
            preSelection = self.preSelectionCollision(point1, point2)
        else:
            preSelection = []
            for coord in self.cases:
                preSelection.append(coord)
       
        #on liste les cases en collision avec la forme 
        for coord in preSelection:
            if self.cases[coord].collidesWithItem(forme, Qt.IntersectsItemShape):
                if plein:
                    tmp.append(coord) 
                else:
                    contenu = True
                    for i in range(0,len(self.cases[coord].polygon())):
                        if not forme.contains(self.cases[coord].polygon().at(i)):
                            contenu = False
                            break
                    if contenu == False:
                         tmp.append(coord)    
        #on applique l'epaisseur du pinceau (lignes ou formes vides seulement) si necessaire
        if not plein and epaisseur > 0:
            for coord in tmp:
                zone = self.zone(coord, epaisseur)
                for coord2 in zone:
                    if not coord2 in listeCases:
                        listeCases.append(coord2)
        else:
            listeCases = tmp
        #si la liste est vide, on ajoute l'origine de la forme
        if len(listeCases) == 0:
            listeCases = [self.coordonneesAuPoint(point1)]    
        return listeCases                

    def preSelectionCollision(self, point1, point2):
        """renvoie une liste des cases qui peuvent etre concernees par une collision avec
           un graphicsItem (pour des raisons de performance)"""
        preSelection = []
        coord1 = self.coordonneesAuPoint(point1)  
        coord2 = self.coordonneesAuPoint(point2)
        if coord1 != None and coord2 != None:
            minX = min(coord1[0], coord2[0]) - 1
            maxX = max(coord1[0], coord2[0]) + 1
            minY = min(coord1[1], coord2[1]) - 1
            maxY = max(coord1[1], coord2[1]) + 1
            for coord in self.cases:
                if coord[0] >= minX and coord[0] <= maxX and coord[1] >= minY and coord[1] <= maxY :
                    preSelection.append(coord)
        else:
            preSelection = self.cases
        return preSelection                         

    def selectionFrontiere(self):
        """retourne les cases selectionnees lors de l'utilisation de la forme 'frontiere'"""
        listeCases = []
        ligne = self.modeParam["formeDessin"].line()
        normale = ligne.normalVector()
        normale = normale.unitVector()
        coordOrigine = self.coordonneesAuPoint(self.modeParam["origineFormeDessin"])
        dx = normale.p2().x() - normale.p1().x()
        dy = normale.p2().y() - normale.p1().y()
        for coord in self.cases:
            if dx < 0 and dy == 0:  #normale pointe vers la gauche
                if (coord[0] - coordOrigine[0]) <= 0:
                    listeCases.append(coord)
            if dx > 0 and dy == 0:  #normale pointe vers la droite
                if (coord[0]  - coordOrigine[0]) >= 0:
                    listeCases.append(coord)   
            if dx == 0 and dy < 0:  #pointe vers le haut (rappel: axe y vers le bas)
                if (coord[1] - coordOrigine[1]) <= 0:
                    listeCases.append(coord)
            elif dx == 0 and dy > 0:  #pointe vers le bas
                if (coord[1] - coordOrigine[1]) >= 0:
                    listeCases.append(coord)
            if dx > 0 and dy < 0:  #pointe vers le haut droite
                if (coord[0] - coordOrigine[0]) + -1*(coord[1] - coordOrigine[1]) >= 0:
                    listeCases.append(coord)
            elif dx > 0 and dy > 0:  #pointe vers le bas droite
                if -1*(coord[0] - coordOrigine[0]) + -1*(coord[1] - coordOrigine[1]) <= 0:
                    listeCases.append(coord)
            if dx < 0 and dy < 0:  #pointe vers le haut gauche
                if (coord[0] - coordOrigine[0]) + (coord[1] - coordOrigine[1]) <= 0:
                    listeCases.append(coord)
            elif dx < 0 and dy > 0:  #pointe vers le bas gauche
                if -1*(coord[0] - coordOrigine[0]) + (coord[1] - coordOrigine[1]) >= 0:
                    listeCases.append(coord)
        return listeCases
        
    def validerFormeDessin(self):
        """la projection des cases a peindre a ete acceptee, on peint ces cases"""
        if self.modeActif[0:7] == "caseMaj" or self.modeActif == "caseCopie" or self.modeActif == "cachePlacer" or self.modeActif == "majZonePlacement":
            self.majListeCases(self.modeParam["listeCasesFormeDessin"])
        self.majMode(self.modeActif)    
##        self.majMode("standard")
            
    def rectFormeDessin(self, point1, point2):
        """retourne le rectangle repesentant la forme de selection
           determine pour ce faire les points A et B, cad le point haut-droit et le point bas-gauche"""
        pointA = QPointF(min(point1.x(), point2.x()), min(point1.y(), point2.y()))
        pointB = QPointF(max(point1.x(), point2.x()), max(point1.y(), point2.y()))             
        rect = QRectF(pointA, pointB)
        return rect

    def majLigneMireAttaqueDist(self, coordCible = None):
        """met a jour la ligne de mire representant l'attaque a distance"""
        if self.modeParam["cibleAttaqueDist"] != None and self.modeParam["cibleAttaqueDist"] != coordCible:
            self.cases[self.modeParam["cibleAttaqueDist"]].majEstCibleCurseur(False)
##        if self.modeParam["pionCibleAttaqueDist"] != None and self.modeParam["pionCibleAttaqueDist"] != self.cases[coordCible].pionOccupant():
        if self.modeParam["pionCibleAttaqueDist"] != None:
            self.modeParam["pionCibleAttaqueDist"].estCibleAttaque(False)
            
        if coordCible != None and self.pionSelectionne() != None and self.modeCombat == "combatAttaqueDist":
            if coordCible == None:
                coordCible = pion.position
                
            if coordCible != self.modeParam["cibleAttaqueDist"]:
                if self.modeParam["ligneAttaqueDist"] == None:
                    self.modeParam["ligneAttaqueDist"] = QGraphicsLineItem()
                    self.modeParam["ligneAttaqueDist"].setZValue(100)
                    pinceau = QPen()
                    pinceau.setWidth(6)
                    self.modeParam["ligneAttaqueDist"].setPen(pinceau)
                    self.modeParam["ligneAttaqueDist"].prepareGeometryChange()
                    self.addItem(self.modeParam["ligneAttaqueDist"])

                z = 0
                pionSurCase = self.cases[coordCible].pionOccupant()
                if pionSurCase != None:
                    z = pionSurCase.z
                cibleValide = self.estCibleAttaqueDistValide(self.pionSelectionne().position, coordCible, z)

                if pionSurCase != None:
                    pionSurCase.estCibleAttaque(True, cibleValide)
                    self.modeParam["pionCibleAttaqueDist"] = pionSurCase
                else:
                    self.cases[coordCible].majEstCibleCurseur(True, cibleValide)
                self.modeParam["cibleAttaqueDist"] = coordCible
                    
                point1 = self.cases[self.pionSelectionne().position].centreGraphique
                point2 = self.cases[coordCible].centreGraphique
                ligne = QLineF(point1, point2)
                self.modeParam["ligneAttaqueDist"].setLine(ligne)
        else:
            if self.modeParam["ligneAttaqueDist"] != None:
                self.modeParam["ligneAttaqueDist"].prepareGeometryChange()
                self.removeItem(self.modeParam["ligneAttaqueDist"])
            self.modeParam["ligneAttaqueDist"] = None
            self.modeParam["cibleAttaqueDist"] = None
            
##        if pion == None:
##            self.modeParam["pionCibleAttaqueDist"] = None
                
    def estCibleAttaqueDistValide(self, coordOrigine, coordCible, zPion = 0):
         """la case cible est elle valide pour une attaque a distance depuis la position et hauteur
            du pion selectionne? on compare pour ce faire les altitudes des cases sur la ligne de mire"""
         casesLigneMire = []
         #on preselectionne les cases concernees
         preSelection = self.preSelectionCollision(self.cases[coordOrigine].centreGraphique, self.cases[coordCible].centreGraphique)
         if coordOrigine in preSelection:
             preSelection.remove(coordOrigine)
         if coordCible in preSelection:
             preSelection.remove(coordCible)    
         for coord in preSelection:
             ligne = QLineF(self.cases[coordOrigine].centreGraphique, self.cases[coordCible].centreGraphique)
             ligneGraphique = QGraphicsLineItem(ligne)
             ligneGraphique.prepareGeometryChange()
             self.addItem(ligneGraphique)
             if self.cases[coord].collidesWithItem(ligneGraphique, Qt.IntersectsItemShape):
                  casesLigneMire.append(coord)
             self.removeItem(ligneGraphique)     
             del ligneGraphique     

         #on trie les cases par distance au point d'origine (de la plus proche a la plus eloignee)
         casesLigneMireDistance = {} #distance: coord
         for coord in casesLigneMire:
             distance = sqrt((coordOrigine[0] - coord[0])**2 + (coordOrigine[1] - coord[1])**2)
             casesLigneMireDistance[coord] = distance

         #on compare enfin les altitudes de chaque case en fonction de la distance
         zOrigine = self.cases[coordOrigine].altitude + self.pionSelectionne().z + self.pionSelectionne().creature.hauteur 
         zCible = self.cases[coordCible].altitude + zPion
         distanceTot = sqrt((coordCible[0] - coordOrigine[0])**2 + (coordCible[1] - coordOrigine[1])**2)
         valide = True
         for coord in casesLigneMireDistance:
              if self.cases[coord].terrain.visibilite == False:
                  valide = False
                  break
              else:  
                  if zOrigine >= zCible:
                      z = (zOrigine - zCible) * (casesLigneMireDistance[coord] / distanceTot)
                  else:
                      z = (zCible - zOrigine) * ((distanceTot - casesLigneMireDistance[coord]) / distanceTot)
                  if self.cases[coord].estOccupee(int(z)):
                      if self.modeParam["pionCibleAttaqueDist"] != None:
                          if self.cases[coord].estOccupeePar(int(z)) != self.modeParam["pionCibleAttaqueDist"]:
                              valide = False
                      else:        
                          valide = False
                      break
         return valide       

    def validerAttaqueDist(self):
        """on essaie de valider une attaque a distance vers un pion ou une case"""
        if self.modeParam["pionCibleAttaqueDist"] != None:
            msg = "{} attaque a distance le pion {}".format(self.pionSelectionne().txtId(),
                                                              self.modeParam["pionCibleAttaqueDist"].txtId())
            valide = self.estCibleAttaqueDistValide(self.pionSelectionne().position, self.modeParam["cibleAttaqueDist"], self.modeParam["pionCibleAttaqueDist"].z)
        else:
            msg = "{} attaque a distance la case {}".format(self.pionSelectionne().txtId(), 
                                                              self.modeParam["cibleAttaqueDist"])
            valide = self.estCibleAttaqueDistValide(self.pionSelectionne().position, self.modeParam["cibleAttaqueDist"])
        if not valide:
            msg += " [INVALIDE]"
        print(msg)
        self.majModeCombat("aucun")


    def rectEllipseCirculaire(self, centre, rayon):
        """renvoie le QRectF definissant une ellipse ayant le QPointF pour centre et le rayon en cases entres en param
           attention: l'ellipse n'est pas tout a fait circulaire, elle couvre horizontalement et
           verticalement le nombre de cases demandees"""
        rect = QRectF()
        if rayon > 0:
            p1 = QPointF((centre.x() - (rayon*self.hCase)), (centre.y() - (rayon*self.hCase)))
            p2 = QPointF((centre.x() + (rayon*self.hCase)), (centre.y() + (rayon*self.hCase)))
            rect.setTopLeft(p1)
            rect.setBottomRight(p2)
        else:
            rect = None
        return rect

    def polygoneCone(self, point1, point2):
        """renvoie le polygone du cone defini par les deux points (origine, distance)"""
        ligne1 = QLineF(point1, point2)
        longueur = ligne1.length()
        ligne1.setAngle(ligne1.angle() + 22.5)
        ligne1.setLength(1.1547*longueur)
        ligne2 = QLineF(point1, point2)    
        ligne2.setAngle(ligne2.angle() - 22.5)
        ligne2.setLength(1.1547*longueur)
        polygone = QPolygonF()
        polygone.append(point1)
        polygone.append(ligne1.p2())
        polygone.append(ligne2.p2())
        return polygone

    def majFormeAttaqueZone(self):
        """cree la forme de l'attaque de zone"""
        for coord in self.modeParam["listeCasesAttaqueZone"]:
            self.cases[coord].majEstCibleAttaque(False)
        for numPion in self.pionsSurListeCase(self.modeParam["listeCasesAttaqueZone"]):
             self.pions[numPion].estCibleAttaque(False)
        
        if self.modeCombat == "combatAttaqueZone" and self.pionSelectionne() != None:
            if self.modeParam["typeAttaqueZone"] == "ligne":
                if self.modeParam["formeAttaqueZone"] == None:
                    self.modeParam["origineAttaqueZone"] = self.cases[self.pionSelectionne().position].centreGraphique
                    self.modeParam["point2AttaqueZone"] = self.cases[self.pionSelectionne().position].centreGraphique
                    self.modeParam["formeAttaqueZone"] = QGraphicsLineItem()
                    self.modeParam["formeAttaqueZone"].setPen(QPen(QColor("black")))
                    self.modeParam["formeAttaqueZone"].prepareGeometryChange()
                    self.addItem(self.modeParam["formeAttaqueZone"])
                if self.modeParam["origineAttaqueZone"] != self.modeParam["point2AttaqueZone"]: 
                    ligne = QLineF(self.modeParam["origineAttaqueZone"], self.modeParam["point2AttaqueZone"])
                    self.modeParam["formeAttaqueZone"].setLine(ligne)
                    self.modeParam["listeCasesAttaqueZone"] = []
                    lst = self.casesSousForme(self.modeParam["formeAttaqueZone"],False)
                    for coord in lst:
                        self.modeParam["listeCasesAttaqueZone"].append(coord)                
                    #on retire la case du pion selectionne si besoin:
                    if self.pionSelectionne().position in self.modeParam["listeCasesAttaqueZone"]:
                        self.modeParam["listeCasesAttaqueZone"].remove(self.pionSelectionne().position)
                                                 
            elif self.modeParam["typeAttaqueZone"] == "disque":
                if self.modeParam["ligneMireAttaqueZone"] == None:
                    self.modeParam["origineAttaqueZone"] = self.cases[self.pionSelectionne().position].centreGraphique
                    self.modeParam["point2AttaqueZone"] = self.cases[self.pionSelectionne().position].centreGraphique
                    self.modeParam["ligneMireAttaqueZone"] = QGraphicsLineItem()
                    self.modeParam["ligneMireAttaqueZone"].setPen(QPen(QColor("black")))
                    self.modeParam["ligneMireAttaqueZone"].prepareGeometryChange()
                    self.addItem(self.modeParam["ligneMireAttaqueZone"])
   
                if self.modeParam["origineAttaqueZone"] != self.modeParam["point2AttaqueZone"]: 
                    ligne = QLineF(self.modeParam["origineAttaqueZone"], self.modeParam["point2AttaqueZone"])
                    self.modeParam["ligneMireAttaqueZone"].setLine(ligne)
                    coordCible = self.coordonneesAuPoint(self.modeParam["point2AttaqueZone"])
                    cibleValide = self.estCibleAttaqueDistValide(self.pionSelectionne().position, coordCible)
                    
                    if cibleValide:
                        rayon = self.fenetre.ui.combatZone_disqueRayon.value()
                        if self.modeParam["formeAttaqueZone"] == None:
                            self.modeParam["formeAttaqueZone"] = QGraphicsEllipseItem()
                            self.modeParam["formeAttaqueZone"].setPen(QPen(QColor("black")))
                            self.modeParam["formeAttaqueZone"].prepareGeometryChange()
                            self.addItem(self.modeParam["formeAttaqueZone"])
                        rect = self.rectEllipseCirculaire(self.modeParam["point2AttaqueZone"], rayon)
                        self.modeParam["listeCasesAttaqueZone"] = []
                        if rect != None and rect.bottomRight() != rect.topLeft():
                            self.modeParam["formeAttaqueZone"].setRect(rect)
                            lst = self.zone(coordCible, rayon, 0)   #zone bcp plus rapide que casesSousforme
                            self.modeParam["listeCasesAttaqueZone"] = lst
                    else:
                        self.cases[coordCible].majEstCibleCurseur(True, False)
                        self.modeParam["listeCasesAttaqueZone"] = []
                    
                    if self.modeParam["formeAttaqueZone"] != None:        
                        self.modeParam["formeAttaqueZone"].setVisible(cibleValide == True and rect != None)    
                
            elif self.modeParam["typeAttaqueZone"] == "cone":
                if self.modeParam["formeAttaqueZone"] == None:
                    self.modeParam["origineAttaqueZone"] = self.cases[self.pionSelectionne().position].centreGraphique
                    self.modeParam["point2AttaqueZone"] = self.cases[self.pionSelectionne().position].centreGraphique
                    self.modeParam["formeAttaqueZone"] = QGraphicsPolygonItem()
                    self.modeParam["formeAttaqueZone"].setPen(QPen(QColor("black")))
                    self.modeParam["formeAttaqueZone"].prepareGeometryChange()
                    self.addItem(self.modeParam["formeAttaqueZone"])
                    
                if self.modeParam["origineAttaqueZone"] != self.modeParam["point2AttaqueZone"]:
                    cone = self.polygoneCone(self.modeParam["origineAttaqueZone"], self.modeParam["point2AttaqueZone"])
                    self.modeParam["formeAttaqueZone"].setPolygon(cone)
                    lst = self.casesSousForme(self.modeParam["formeAttaqueZone"], True, True)
                    self.modeParam["listeCasesAttaqueZone"] = []
                    for coord in lst:
                        if coord != self.pionSelectionne().position:
                            self.modeParam["listeCasesAttaqueZone"].append(coord)

            for coord in self.modeParam["listeCasesAttaqueZone"]:
                self.cases[coord].majEstCibleAttaque(True)
            for numPion in self.pionsSurListeCase(self.modeParam["listeCasesAttaqueZone"]):
                self.pions[numPion].estCibleAttaque(True)


    def validerAttaqueZone(self):
        """l'attaque de zone est validee"""
        if self.modeActif == "pionSelectionne" and self.modeCombat == "combatAttaqueZone":
            for numPion in self.pionsSurListeCase(self.modeParam["listeCasesAttaqueZone"]):
                print("{} a lance une attaque de zone sur {}".format(self.pionSelectionne().nom, self.pionSelectionne().numero , \
                                                                     self.pions[numPion].nom, self.pions[numPion].numero))
        self.majModeCombat("aucun")        

    def reinitAttaqueZone(self):
        if self.modeParam["formeAttaqueZone"] != None:
            self.modeParam["formeAttaqueZone"].prepareGeometryChange()
            self.removeItem(self.modeParam["formeAttaqueZone"])
            self.modeParam["formeAttaqueZone"] = None
        if self.modeParam["ligneMireAttaqueZone"] != None:
            self.modeParam["ligneMireAttaqueZone"].prepareGeometryChange()
            self.removeItem(self.modeParam["ligneMireAttaqueZone"])
            self.modeParam["ligneMireAttaqueZone"] = None
        if self.modeParam["point2AttaqueZone"] != None:
            self.cases[self.coordonneesAuPoint(self.modeParam["point2AttaqueZone"])].majEstCibleCurseur(False)
        for coord in self.modeParam["listeCasesAttaqueZone"]:
            self.cases[coord].majEstCibleAttaque(False)
        for numPion in self.pionsSurListeCase(self.modeParam["listeCasesAttaqueZone"]):
            self.pions[numPion].estCibleAttaque(False)
                      
    def pionSurCase(self, coord):
        """renvoie le pion present sur la case, none sinon"""
        retour = None
        for num in self.pions:
            if self.pions[num].position == coord:
                retour = num
        return retour        

    def pionsSurListeCase(self, listeCases):
        """renvoie la liste des pions presents sur la liste de cases"""
        retour = []
        for coord in listeCases:
            pion = self.cases[coord].pionOccupant()
            if pion != None and not pion.numero in retour:
                retour.append(pion.numero)
        return retour   

    def majZonePlacement(self, listeCases):
        """met a jour la forme et l'affichage de la zone de placement initale des joueurs"""
        if len(listeCases) > 0:
            if self.polygoneZonePlacement == None:
                self.polygoneZonePlacement = QGraphicsPolygonItem(scene=self)
                self.polygoneZonePlacement.setZValue(0)
                qCouleurFond = QColor("white")
                qCouleurFond.setAlpha(50)
                self.polygoneZonePlacement.setBrush(qCouleurFond)
                pinceau = QPen(QColor("orange"))
                pinceau.setWidth(20)
                self.polygoneZonePlacement.setPen(pinceau)
                self.polygoneZonePlacement.setAcceptedMouseButtons(Qt.NoButton)
                self.polygoneZonePlacement.setAcceptHoverEvents(False)
                self.addItem(self.polygoneZonePlacement)
            listeCases2 = []    
            for coord in listeCases:
                if self.cases[coord].estFranchissable():
                    listeCases2.append(coord)
            self.polygoneZonePlacement.setPolygon(self.polygoneAgglo(listeCases2))
            self.listeCasesZonePlacement = listeCases

    def materialiserPions(self,actif):
        """avtive/desactive la reception par les pions (autres que le pion selectionne) des hover events"""
        for numPion in self.pions:
            if numPion != self.modeParam["numPionSelectionne"]:
                self.pions[numPion].setAcceptsHoverEvents(actif)
                self.pions[numPion].polygoneGraphique.setAcceptsHoverEvents(actif)
        for numPion in self.decors:
            self.decors[numPion].setAcceptsHoverEvents(actif)
            self.decors[numPion].polygoneGraphique.setAcceptsHoverEvents(actif)
                
    #######################

    ######## interaction avec les cases, decors et pions  #############
    def pionSelectionne(self):
        """renvoie le pion actuellement selectionne"""
        if self.modeParam["numPionSelectionne"] in self.pions:
            retour = self.pions[self.modeParam["numPionSelectionne"]]
        else:
            retour = None
        return retour    

    def pionDecorSelectionne(self):
        """renvoie le pion actuellement selectionne"""
        if self.modeParam["numPionSelectionne"] in self.decors:
            retour = self.decors[self.modeParam["numPionSelectionne"]]
        else:
            retour = None
        return retour    
            
    def caseCliquee(self, x, y):
        """on a clique sur la case (clic gauche)"""
        coord = (x, y)
        accepte = False
        if coord in self.cases:
            case = self.cases[coord]
            if self.modeActif == "caseCopie":
                if len(case.terrain.nom) > 0:
                     self.majMode("caseMajTerrain", case.terrain)
                     accepte = True
                else:
                     self.majMode("caseMajTerrain", case.couleur)
                     accepte = True
                 
            elif self.modeActif[0:7] == "caseMaj" or self.modeActif == "cachePlacer" or self.modeActif == "majZonePlacement":
                self.creerOrigineFormeDessin(coord)
                accepte = True
                
            elif self.modeActif == "pionDecorSelectionne":
                if coord != self.pionDecorSelectionne().position:
                    self.pionDeposer(coord)
                    accepte = True
                    
            elif self.modeActif == "pionSelectionne":
                if self.modeCombat == "combatDeplacement":
                    if self.pionSelectionne() != None:
                        if coord != self.pionSelectionne().position:
                            self.pionDeposer(coord)
                            accepte = True
                elif self.modeCombat == "combatAttaqueCaC":
                    if self.modeParam["cibleAttaqueCaC"] in self.modeParam["zoneAttaqueCaC"]:
                        print("{} attaque {} au corps a corps".format(self.pionSelectionne().nom, self.modeParam["cibleAttaqueCaC"]))
                        self.majMode("pionSelectionne", None)
                        accepte = True
                    else:
                        print("cette case est invalide pour une corps a corps")
                        accepte = True
                elif self.modeCombat == "combatAttaqueDist":
                    self.validerAttaqueDist()
                    accepte = True
                        
                elif self.modeCombat == "combatAttaqueZone":
                    self.validerAttaqueZone()
                    accepte = True
                    
            elif self.modeActif == "pionCreation":
                self.pionCreer(coord)
                accepte = True
                
            elif self.modeActif == "pionDecorCreation":
                self.pionDecorCreer(coord)
                accepte = True    
        return accepte       

    def caseSurvolClicEnfonce(self, coordCase):
        """une case est survolee par le curseur (le clic gauche est enfonce)"""
        if self.modeActif[0:7] == "caseMaj" or self.modeActif == "cachePlacer" or self.modeActif == "majZonePlacement":
            if self.cases[coordCase].centreGraphique != self.modeParam["point2FormeDessin"]:
                if self.modeParam["origineFormeDessin"] == None: self.modeParam["origineFormeDessin"] = self.cases[coordCase].centreGraphique
                self.modeParam["point2FormeDessin"] = self.cases[coordCase].centreGraphique
                self.majFormeDessin()

    def clicGaucheRelache(self):
       """si une forme de selection etait affichee, elle est validee""" 
       if len(self.modeParam["listeCasesFormeDessin"]) > 0:
            self.validerFormeDessin()

    def caseSurvol(self, x, y):
        """une case est survole par le curseur, on affiche ses informations dans la zone prevue"""
        case = self.cases[(x, y)]
        self.majInfosCase(case)
        if (self.modeActif == "pionSelectionne" and self.modeCombat == "combatDeplacement") or self.modeActif == "pionCreation"\
           or self.modeActif == "pionDecorSelectionne" or self.modeActif == "pionDecorCreation":
            self.majProjectionPosition(False)
            self.modeParam["coordProjectionPosition"] = (case.x, case.y)
            self.majProjectionPosition(True)
        elif self.modeActif == "pionSelectionne" and self.modeCombat == "combatAttaqueDist" and self.modeParam["cibleAttaqueDist"] != (case.x, case.y):
            self.majLigneMireAttaqueDist((case.x,case.y))
        elif self.modeActif == "pionSelectionne" and self.pionSelectionne() != None and self.modeCombat == "combatAttaqueZone":
            if case.centreGraphique != self.modeParam["point2AttaqueZone"]:
                self.cases[self.coordonneesAuPoint(self.modeParam["point2AttaqueZone"])].majEstCibleCurseur(False)
                self.modeParam["point2AttaqueZone"] = case.centreGraphique
                self.majFormeAttaqueZone()                       

    def afficherListeCases(self, listeCases, actif):
        """met ou non en evidence les cases selectionnees"""
        for coord in listeCases:
            self.cases[coord].majEstCibleCurseur(actif)
        
    def majListeCases(self, listeCases):
        """met a jour les cases dont les coordonnees sont dans la liste"""
        self.afficherListeCases(listeCases, False)    
            
        if self.modeActif[0:7] == "caseMaj":
            for coord in listeCases:
                self.caseMaj(coord)
        elif self.modeActif == "cachePlacer":
            self.majAffichageCache(self.cacheEnCours, False)
            self.caches[self.cacheEnCours]["listeCases"] = listeCases
            self.majAffichageCache(self.cacheEnCours, True)
        elif self.modeActif == "majZonePlacement":
            self.majZonePlacement(listeCases)

    def caseMaj(self, coordCase):
        """met a jour la case selon le mode actif (et les cases adjacentes selon l'epaisseur du pinceau)"""
        if self.modeActif == "caseMajTerrain":
            if self.modeParam["terrain"] != None:
                if self.modeParam["terrain"].__class__.__name__ == "Terrain":
                     self.cases[coordCase].majTerrain(self.modeParam["terrain"])
                elif self.modeParam["terrain"].__class__.__name__ == "QColor":
                     if self.modeParam["terrain"].isValid():
                         self.cases[coordCase].majTerrain(None)
                         self.cases[coordCase].majCouleur(self.modeParam["terrain"])
                self.cases[coordCase].majAltitude(int(self.fenetre.ui.altitudeCase.value()))
        elif self.modeActif == "caseMajEffet":
            self.cases[coordCase].majEffet(self.modeParam["effet"])
        elif self.modeActif == "caseMajAltitude":
            self.cases[coordCase].majAltitude(int(self.fenetre.ui.altitudeCase.value()))
        
    def majInfosCase(self, case=None):
        """met a jour les informations d'un pion dans la zone prevue"""
        if case != None:
            if len(case.terrain.nom) > 0:
                self.fenetre.ui.infoCaseEnCours_terrain.setText(QString.fromUtf8(case.terrain.nom))
            else:
                self.fenetre.ui.infoCaseEnCours_terrain.setText(QString.fromUtf8("Case"))
            self.fenetre.ui.infoCaseEnCours_coord.setText(QString.fromUtf8("X: {}  Y: {}".format(case.x, case.y)))
            self.fenetre.ui.infoCaseEnCours_altitude.setText(QString.fromUtf8("Alt.: {}".format(case.altitude)))
            if case.effetActif != "":
                pix = QPixmap(QString.fromUtf8("img\\"+case.imgEffet[case.effetActif]))
                pix = pix.scaled(21, 21, Qt.KeepAspectRatio, Qt.SmoothTransformation)
                self.fenetre.ui.infoCaseEnCours_effetImg.setPixmap(pix)                
                self.fenetre.ui.infoCaseEnCours_effetNom.setText(QString.fromUtf8(case.effetActif))
            else:
                self.fenetre.ui.infoCaseEnCours_effetImg.clear()
                self.fenetre.ui.infoCaseEnCours_effetNom.clear()
            self.fenetre.ui.infoCase.setVisible(True)
        else:
            self.fenetre.ui.infoCase.setVisible(False)

    def pionClique(self, numPion):
        """on a clique sur ce pion"""
        accepte = False
        if self.pionSelectionne() != None and self.modeCombat == "combatAttaqueDist":    
            self.validerAttaqueDist()
            accepte = True
            
        elif self.modeActif == "standard" and self.pionSelectionne() == None:
            self.pionSaisir(numPion)
            accepte = True
        return accepte    

    def pionSurvol(self, numPion):
        """le pion est survole par le curseur, on affiche ses informations dans la zone prevue"""
        if numPion in self.pions:
            pion = self.pions[numPion]
        else:
            pion = None
        self.majInfosPion(pion)
        if self.pionSelectionne() != None and self.modeCombat == "combatAttaqueCaC":
            self.majProjectionAttaqueCaC(pion)
            pass
        if numPion in self.pions:
            case = self.cases[self.pions[numPion].position]
            self.caseSurvol(case)

    def pionDoubleClic(self, numPion):
        """on a double-clique sur le pion"""
        accepte = False
        if self.pionSelectionne() == self.pions[numPion] and self.modeCombat == "aucun":
##            self.pionSaisir(numPion)
            self.majModeCombat("combatDeplacement")
            accepte = True
        return accepte          

    def pionCreer(self, coordCase):
        """creer un jeton aux coordonnees indiquees"""
        valide = True
        for coord in self.modeParam["formeProjectionPosition"].listeCases(coordCase):
            if not coord in self.cases:
                valide = False
            else:    
                 if not self.cases[coord].estFranchissable():
                      valide = False
        if valide:
            numero = 1
            if len(self.pions) > 0:
                numero = max(self.pions) + 1   
            pion = Pion(self, numero)
            if self.modeParam["creature"] != None:
                nom = self.modeParam["creature"].nom
            elif len(self.fenetre.ui.pionSimple_nom.text().toUtf8()) > 0:
                nom = self.fenetre.ui.pionSimple_nom.text().toUtf8()            
            numTxt = self.numeroterNom(nom)
            self.pions[numero] = pion
            pion.creer(coordCase[0], coordCase[1], nom, numTxt, self.modeParam["creature"], self.modeParam["couleurPion"], self.modeParam["nbRotations"])
            self.pionDeplacerDansOrdreJeu(numero, len(self.ordreJeu) + 2)

    def numeroterNom(self, nom):
        """renvoie le nom du pion avec un numero complementaire si necessaire """
        i = 1
        for numPion in self.pions:
            if self.pions[numPion].nom == nom:
                i += 1     
        if i == 1:
            retour = ""
        else:
            retour = str(i)
        return retour
    
    def pionSaisir(self, numPion):
        """on saisit un pion"""
        if numPion != self.modeParam["numPionSelectionne"]:
            self.majMode("pionSelectionne", numPion)
        
    def pionDeposer(self, coordCase):
        """on depose le pion sur la case voulue"""
        if self.pionSelectionne() != None:
            pion = self.pionSelectionne()
        else:
            pion = self.pionDecorSelectionne()
        
        if pion != None:
           valide = True
           for coord in self.modeParam["formeProjectionPosition"].listeCases(coordCase, self.modeParam["nbRotations"]):
               if coord in self.cases:
                    if not self.cases[coord].estFranchissable(pion.z):
                        if not self.cases[coord].estOccupeePar(pion.z) == pion:
                             #si la case est occupee par le pion qu'on depose, elle est donc valide pour un deplacement  
                             valide = False
               else:
                   valide = False
           if valide:        
               positionPrecedente = pion.position 
               #mise a jour de la position du pion selon le mode
               if self.modePrincipal == "combat":
##                   if coordCase in pion.champDeplacement:
##                       print("le pion a ete deplace de {} vers {} \n    -> soit une distance de {} cases"\
##                             "".format(positionPrecedente, coordCase, self.pionSelectionne().champDeplacement[coordCase]))
                   self.majInfosPion()
               pion.majPosition(coordCase, self.modeParam["nbRotations"])
               self.majModeCombat("aucun")
           else:
               print("Deplacement impossible!")

    def afficherChampDeplacement(self, actif):
        """cree et affiche ou efface et detruit le champ de deplacement du pion selectionne"""
        if self.pionSelectionne() != None:
            if actif:
                self.pionSelectionne().champDeplacement = self.zone(self.pionSelectionne().position, \
                                                                           self.pionSelectionne().deplacementRestant, \
                                                                           True)
            for coord in self.pionSelectionne().champDeplacement:
                 self.cases[coord].majEstDansChampDeplacement(actif)
             
            if not actif:
                self.pionSelectionne().champDeplacement = {}
            
    def majInfosPion(self, pionSurvole=None):
        """met a jour les informations d'un pion dans la zone prevue"""
        if pionSurvole != None:
            pion = pionSurvole
        else:
            if self.pionSelectionne() != None:
                pion = self.pionSelectionne()
            else:
                pion = None

        if pion != None:  
            self.fenetre.ui.infoPionEnCours_nom.setText(QString.fromUtf8(pion.nom))
            self.fenetre.ui.infoPionEnCours_depRestant.setText(QString.fromUtf8("Dep.: {}".format(pion.deplacementRestant)))
            if len(pion.creature.img["nom"]) > 0:
                pix = QPixmap(QString.fromUtf8("img\\"+pion.creature.img["nom"]))
                pix = pix.scaled(61, 51, Qt.KeepAspectRatio, Qt.SmoothTransformation)
                self.fenetre.ui.infoPionEnCours_image.setPixmap(pix)
            self.fenetre.ui.infoPion.setVisible(True)
            self.fenetre.ui.infoPionEnCours_etourdi.setVisible(False)
            self.fenetre.ui.infoPionEnCours_brule.setVisible(False)
            self.fenetre.ui.infoPionEnCours_mouille.setVisible(False)
            self.fenetre.ui.infoPionEnCours_vol.setVisible((pion.z != 0))
            self.fenetre.ui.infoPionEnCours_endormi.setVisible(False)
            self.fenetre.ui.infoPionEnCours_paralyse.setVisible(False)
            self.fenetre.ui.infoPionEnCours_entrave.setVisible(False)
            self.fenetre.ui.infoPionEnCours_mort.setVisible(False)
        else:
            self.fenetre.ui.infoPion.setVisible(False)

    def majZPion(self, valeur):
        """met a jour l'altitude du pion selectionne"""
        if self.pionSelectionne() != None:
            self.pionSelectionne().majZ(valeur)


    def pionDecorSurvol(self, numPionDecor):
        """le pion-decor est survole par le curseur, on affiche ses informations dans la zone prevue"""
        if numPionDecor in self.decors:
            self.majInfosDecor(self.decors[numPionDecor])
        else:
            self.majInfosDecor(None)

    def pionDecorSaisir(self, numPionDecor):
        """on saisit un pion decor (mode creation seulement)"""
        if numPionDecor != self.modeParam["numPionSelectionne"]:
            self.majMode("pionDecorSelectionne", numPionDecor)

    def majInfosDecor(self, pionDecor=None):
        """met a jour les informations d'un pion dans la zone prevue"""
        if pionDecor != None:  
            self.fenetre.ui.infoDecorEnCours_nom.setText(QString.fromUtf8(pionDecor.decor.nom))
            self.fenetre.ui.infoDecorEnCours_hauteur.setText(QString.fromUtf8("Haut.: {}".format(pionDecor.decor.hauteur)))
            if len(pionDecor.decor.img["nom"]) > 0:
                pix = QPixmap(QString.fromUtf8("img\\"+pionDecor.decor.img["nom"]))
                pix = pix.scaled(61, 51, Qt.KeepAspectRatio, Qt.SmoothTransformation)
                self.fenetre.ui.infoDecorEnCours_image.setPixmap(pix)
            self.fenetre.ui.infoDecor.setVisible(True)
        else:
            self.fenetre.ui.infoDecor.setVisible(False)

    def majProjectionPosition(self, activer, z=0):
        """maj l'affichage de la projection de la position d'un objet avant creation ou deplacement (pion, decor...)"""
        valide = True
        possible = True

        if self.modeParam["formeProjectionPosition"] != None and self.modeParam["coordProjectionPosition"] != None:
            proj = self.modeParam["formeProjectionPosition"].listeCases(self.modeParam["coordProjectionPosition"], self.modeParam["nbRotations"])
                 
            for coord in proj:
                if not coord in self.cases:
                    valide = False   #deplacement valide? (pas d'occupation d'une case hors plateau)
    
            if valide == True:
                for coord in proj:
                    if self.cases[coord].estFranchissable(z) or self.cases[coord].estOccupeePar(z) == self.pionSelectionne():
                    #la case est franchissable, ou elle ne l'est pas mais est occupée par le pion meme qu'on deplace
                        self.cases[coord].majEstCibleCurseur(activer, True)
                             
                        #on affiche la distance correspondante en bulle-info
                        if activer and self.modeActif == "pionSelectionne" and self.modePrincipal == "combat":
                             if coord in self.pionSelectionne().champDeplacement:
                                  msg = "Distance {}".format(self.pionSelectionne().champDeplacement[coord])
                                  QToolTip.showText(QCursor.pos(), msg, self.fenetre.ui.vuePlateau)
                    else:
                        self.cases[coord].majEstCibleCurseur(activer, False)


    def majProjectionAttaqueCaC(self, pionCible):
        """affiche ou non la cible de l'attaque au corps a corps, selon sa validite ou non"""
        if self.modeActif == "pionSelectionne" and self.modeCombat == "combatAttaqueCaC":
            if pionCible != self.pionSelectionne():
                if pionCible != None:
                    conditionPossible = (pionCible.position in self.modeParam["zoneAttaqueCaC"])
                    pionCible.estCibleAttaque(True, conditionPossible)
                else:
                    if self.modeParam["cibleAttaqueCaC"] != None:
                        self.modeParam["cibleAttaqueCaC"].estCibleAttaque(False)
                self.modeParam["cibleAttaqueCaC"] = pionCible
             

    def majZoneAttaqueCaC(self, actif = True):
        """affiche ou non les cases a portee du pion selectionne pour une attaque au corps-a-corps"""
        for coord in self.modeParam["zoneAttaqueCaC"]:
            self.cases[coord].majEstDansChampDeplacement(actif)

    def pionDecorCreer(self, coordCase):
        """creer un jeton aux coordonnees indiquees"""
        valide = True
        for coord in self.modeParam["formeProjectionPosition"].listeCases(coordCase, self.modeParam["nbRotations"]):
            if not self.cases[coord].estFranchissable():
                 valide = False
        if valide:  
            numero = 10001
            if len(self.decors) > 0:
                numero = max(self.decors) + 10001 
            pionDecor = PionDecor(self, numero)
            pionDecor.creer(coordCase[0], coordCase[1], self.modeParam["decor"], self.modeParam["nbRotations"])
            self.decors[numero] = pionDecor
 
    def pionSupprimer(self, num):
        """supprime le pion entre en parametre"""
        #settrace(trace_calls)
        if num in self.pions:    
            for coord in self.pions[num].forme.listeCases(self.pions[num].position, self.pions[num].nbRotations):
                 self.cases[coord].majOccupation(self.pions[num])
            self.pionSurvol(None)     
            self.pionDeplacerDansOrdreJeu(num, 0)
            pionSuppr = self.pions.pop(num)
            pionSuppr.supprimer()
        else:
            print("erreur: ce pion n'est pas dans la liste des pions")
            
    def pionDecorSupprimer(self, num):
        """supprime le pion entre en parametre"""
        if num in self.decors:
            for coord in self.decors[num].forme.listeCases(self.decors[num].position, self.decors[num].nbRotations):
                 self.cases[coord].majOccupation(self.decors[num])
            self.pionDecorSurvol(None)
            pionDecorASuppr = self.decors.pop(num)
            pionDecorASuppr.supprimer()
        else:
            print("ce pion n'est pas dans la liste des decors")
            
    ###############

    ######### caches ###############
    def voirCacheEnCours(self):
        """centre la vue sur et met en evidence le cache actif"""
        if len(self.caches[self.cacheEnCours]["listeCases"]) > 0: 
            #centre la vue sur le premier point du polygone d'une case du milieu de la liste
            indiceMilieu = int((len(self.caches[self.cacheEnCours]["listeCases"])/2))
            self.fenetre.ui.vuePlateau.centerOn(self.cases[self.caches[self.cacheEnCours]["listeCases"][indiceMilieu]].polygon()[0])
            #mettre en surbrillance
            #for coord in self.caches[self.cacheEnCours]["listeCases"]:
            #    self.

    def placerCacheEnCours(self):
        """active le mode de mise a jour de la liste des cases cachees par ce cache"""
        self.majMode("cachePlacer")
        self.fenetre.ui.cacheActif.setChecked(True)
        self.majEtatCacheEnCours()

    def majEtatCacheEnCours(self):
        """met a jour l'etat (actif ou non) du cache selon l'etat de la case correspondante"""
        self.caches[self.cacheEnCours]["actif"] = self.fenetre.ui.cacheActif.isChecked()
        self.majAffichageCache(self.cacheEnCours, self.caches[self.cacheEnCours]["actif"])

    def majAffichageCache(self, numCache, afficher = True):
        """met a jour l'affichage des cases selon les parametres enregistres pour le cache"""
        if self.polygonesCaches[numCache] == None:
            self.polygonesCaches[numCache] = Cache(self, numCache)
        self.polygonesCaches[numCache].afficher(afficher, self.caches[numCache]["listeCases"])    
        
    ###############"
        
    ######### gestion des evenements souris et clavier ###############
    #*ES 
    def wheelEvent(self, event):
        """zoom/dezoom avec la molette de la souris"""
        #on zoom/dezoom et on recentre sur la position du curseur
        #super (Plateau, self).wheelEvent(event)
        zoom = 1.00
        if event.delta() > 0:
            if self.nbZoomActuel <= 10:
                self.nbZoomActuel += 1
                zoom = 1.25
        elif event.delta() < 0:
            if self.nbZoomActuel >= -10:
                zoom = 0.8
                self.nbZoomActuel -= 1 
        if zoom != 0.00:
           self.fenetre.ui.vuePlateau.scale(zoom, zoom)
           self.fenetre.ui.vuePlateau.centerOn(event.scenePos())
        event.accept() #pour considerer l'evenement comme resolu, sans ca les barres de defilement reagissent aussi  

    def mouseMoveEvent(self, event):
        super(Plateau, self).mouseMoveEvent(event)
        if event.buttons() == Qt.LeftButton and self.fenetre.ui.vuePlateau.dragMode() != QGraphicsView.ScrollHandDrag:
            coord = self.coordonneesAuPoint(event.scenePos())
            if coord != None:
                self.caseSurvolClicEnfonce(coord)  
        else:
            if self.modeActif == "placementEntreeSortie":
                self.modeParam["entreeSortie"].majProjection(event.scenePos())
            event.ignore() 

    def mousePressEvent(self, event):
        super(Plateau, self).mousePressEvent(event)
        if event.button() == 1 and self.fenetre.ui.vuePlateau.dragMode() != QGraphicsView.ScrollHandDrag:
            if self.modeActif == "placementEntreeSortie" and not event.isAccepted():
                self.modeParam["entreeSortie"].positionner()
                self.entreesSorties.append(self.modeParam["entreeSortie"])
                self.modeParam["entreeSortie"] = None
                self.majMode("standard")
            elif self.modeActif == "pionSupprimer":
                for item in self.items(event.scenePos()):
                    if item.__class__.__name__ == "PionDecor":
                        self.pionDecorSupprimer(item.numero)
                        break  
                    elif item.parentItem().__class__.__name__ == "Pion":
                        self.pionSupprimer(item.parentItem().numero)
                        break
                      
            else:
##                if not event.isAccepted():
##                    self.caseCliquee(self.coordonneesAuPoint(event.scenePos()))
                event.ignore()
        elif event.button() == 2:
            if self.pionSelectionne() != None and self.modeCombat != "" and self.modeCombat != "aucun":
                self.majModeCombat("aucun")
            else:    
                self.majMode("standard")
            event.accept()
        #event.ignore()

    def mouseReleaseEvent(self, event):
        super(Plateau, self).mouseReleaseEvent(event)
        self.clicGaucheRelache()

    def keyPressEvent(self, event):
        """gestion des evenements clavier"""
        toucheClavier = event.key()
        if self.modeActif == "pionCreation" or self.modeActif == "pionSelectionne" or self.modeActif == "pionDecorSelectionne" or self.modeActif == "pionDecorCreation":
            #pivots de la projection du deplacement
            if toucheClavier == Qt.Key_Right:
                self.majProjectionPosition(False)
                self.modeParam["nbRotations"] += 1
                self.majProjectionPosition(True)
                event.accept()
            elif toucheClavier == Qt.Key_Left:
                self.majProjectionPosition(False)
                self.modeParam["nbRotations"] -= 1
                self.majProjectionPosition(True)
                event.accept()
        elif self.modeActif == "creerEntreeSortie":
            if toucheClavier == Qt.Key_Right: self.modeParam["entreeSortie"].nbRotations += 1
            if toucheClavier == Qt.Key_Left: self.modeParam["entreeSortie"].nbRotations -= 1
            self.modeParam["entreeSortie"].majProjection()
        if self.modeActif[0:7] == "caseMaj":             
            if toucheClavier == Qt.Key_Up:
                self.fenetre.ui.epaisseurPinceau.setValue(self.fenetre.ui.epaisseurPinceau.value()+1)
            elif toucheClavier == Qt.Key_Down:
                self.fenetre.ui.epaisseurPinceau.setValue(self.fenetre.ui.epaisseurPinceau.value()-1)
        if toucheClavier == Qt.Key_Delete:
            if self.pionSelectionne() != None:
                num = self.pionSelectionne().numero
                if self.modeActif == "pionSelectionne":
                    self.pionSupprimer(num)
                elif self.modeActif == "pionDecorSelectionne":            
                    self.pionDecorSupprimer(num)
                self.majMode("standard")    
            elif self.modeActif == "placementEntreeSortie":
                self.modeParam["entreeSortie"].plateau = None
                self.removeItem(self.modeParam["entreeSortie"])
                self.entreesSorties.remove(self.modeParam["entreeSortie"])
                self.modeParam["entreeSortie"] = None
                self.majMode("standard")
            
    ################   

















        
  


