EcranEditionCombattant.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. #from __future__ import unicode_literals
  2. # -*- coding: utf-8 -*-
  3. from __future__ import division
  4. import sys
  5. from PyQt4.QtCore import SIGNAL, Qt, QString, QSize
  6. from PyQt4.QtGui import QDialog, QColorDialog, QColor, QHBoxLayout, QFrame, \
  7. QApplication
  8. import Actions
  9. from Combattant import Combattant
  10. from EcranEditionObjet import EcranEditionObjet
  11. from Objet import Objet
  12. from VueEditionForme import VueEditionForme
  13. from dialogues import dmMessage
  14. from frameAttaque import FrameAttaque
  15. import regles
  16. from rsc import selectionImage, RImage
  17. import ui.dm as dm
  18. from ui.ecran_editionCombattant import Ui_edc_fenetre
  19. class EcranEditionMateriel(QDialog):
  20. """interface de creation/edition de terrains"""
  21. def __init__(self, mat, mode = "creation", parent=None):
  22. """initialisation de la fenetre"""
  23. super (EcranEditionMateriel, self).__init__()
  24. self._mat = mat
  25. self._mode = mode
  26. self._sections = []
  27. def mat(self):
  28. """retourne le materiel de la fenetre"""
  29. return self._mat
  30. def mode(self):
  31. return self._mode
  32. def createWidgets(self):
  33. """construction de l'interface"""
  34. #construction de l'interface
  35. self.ui = Ui_edc_fenetre()
  36. self.ui.setupUi(self)
  37. self.connect(self.ui.edc_enregistrer, SIGNAL("clicked()"), self.valider)
  38. self.connect(self.ui.edc_annuler, SIGNAL("clicked()"), self.annuler)
  39. def toutesLesSections(self):
  40. return [EdEnTete, EdPageCreation, EdPageCombat, EdPageDeplacement, EdPageAttributs, \
  41. EdPageAttaques, EdPageInventaire, EdPageNotes]
  42. def section(self, nom):
  43. for section in self._sections:
  44. if section.__class__.__name__ == nom: return section
  45. return None
  46. def afficher(self, pageInitiale = 0, formeCases = "H"):
  47. """affiche la fenetre"""
  48. self.createWidgets()
  49. #on instancie et on construit les sections necessaires
  50. for section in self.toutesLesSections():
  51. instance = section(self)
  52. if self.mat().__class__.__name__ in instance.filtre() \
  53. and self._mode in instance.modes():
  54. self._sections.append(instance)
  55. instance.construire()
  56. if section == EdPageCreation:
  57. if formeCases == "C": self.ui.edc_casesCarrees.setChecked(True)
  58. instance.charger()
  59. else:
  60. self.ui.edc_menu.setRowHidden((self.toutesLesSections().index(section) - 1), True)
  61. self.allerAPage(pageInitiale)
  62. self.majAffichage()
  63. self.show()
  64. def allerAPage(self, index, sens = "+"):
  65. while self.ui.edc_menu.isRowHidden(index):
  66. index += 1 if sens == "+" else -1
  67. if index > self.ui.edc_menu.rowCount(): return
  68. self.ui.edc_menu.setCurrentCell(index, 0)
  69. self.ui.edc_menu.setCurrentCell(index, 1)
  70. self.ui.edc_pages.setCurrentIndex(index)
  71. def pageSuivante(self):
  72. index = self.ui.edc_menu.currentRow() + 1
  73. if index > (self.ui.edc_menu.rowCount() - 1): index = 0
  74. print index
  75. self.allerAPage(index)
  76. def pagePrecedente(self):
  77. index = self.ui.edc_menu.currentRow() - 1
  78. if index < 0: index = self.ui.edc_menu.rowCount() - 1
  79. print index
  80. self.allerAPage(index, "-")
  81. def nomModifie(self):
  82. """le nom du pion a ete modifie"""
  83. self.majAffichage()
  84. sectionForme = self.section("EdPageCreation")
  85. if sectionForme: sectionForme.majEtiquetteVueForme()
  86. def logoModifie(self):
  87. """le logo du pion a ete modifie"""
  88. sectionForme = self.section("EdPageCreation")
  89. if sectionForme: sectionForme.logoModifie()
  90. #### barre d'outils
  91. def majAffichage(self):
  92. """verifie la validite des saisies"""
  93. self.ui.edc_enregistrer.setEnabled(len(self.ui.edc_nom.texte()) > 0)
  94. def valider(self):
  95. """enregistre le materiel cree/edite"""
  96. for section in self._sections:
  97. section.enregistrer()
  98. self.done(1)
  99. def annuler(self):
  100. """annule la creation/edition"""
  101. self._mat = None
  102. self.done(0)
  103. def wheelEvent(self, event):
  104. if event.delta() < 0:
  105. self.pageSuivante()
  106. return
  107. elif event.delta() > 0:
  108. self.pagePrecedente()
  109. return
  110. return QDialog.wheelEvent(self, event)
  111. class EdSectionBase(object):
  112. """classe de base pour les differentes sections de l'ecran d'edition des pions"""
  113. def __init__(self, ecran):
  114. self.ecran = ecran
  115. self._filtre = []
  116. self._modes = ["creation", "combat"]
  117. def filtre(self):
  118. """liste des classes de materiel concernees par cette section"""
  119. return self._filtre
  120. def modes(self):
  121. return self._modes
  122. def ui(self):
  123. return self.ecran.ui
  124. def mat(self):
  125. return self.ecran.mat()
  126. def construire(self):
  127. """construit et met en forme"""
  128. pass
  129. def charger(self):
  130. """charge les donnees du materiel dans la section"""
  131. pass
  132. def enregistrer(self):
  133. """met a jour le materiel en fonction des donnees saisies"""
  134. pass
  135. class EdEnTete(EdSectionBase):
  136. def __init__(self, ecran):
  137. super(EdEnTete, self).__init__(ecran)
  138. self._filtre = ["Combattant", "Decor"]
  139. def construire(self):
  140. self.ecran.connect(self.ui().edc_nom, SIGNAL("textEdited(QString)"), self.ecran.nomModifie)
  141. self.ecran.connect(self.ui().edc_logo, SIGNAL("clicked()"), self.selectionnerLogo)
  142. # couleur = "rgb(250,100,50)" if self.ecran.mode() == "combat" else "rgb(20,100,250)"
  143. # self.ui().edc_enTete.setStyleSheet(QString("#edc_enTete {border-bottom: 3px solid "+couleur+";}"))
  144. # self.ui().edc_enTete.setStyleSheet(QString("#edc_enTete {background-color: "+couleur+";}"))
  145. def selectionnerLogo(self):
  146. img = selectionImage()
  147. if img:
  148. self.ui().edc_logo.chargerImage(img)
  149. self.ecran.logoModifie()
  150. def charger(self):
  151. self.ui().edc_nom.majTexte(self.mat().nom())
  152. if self.mat().logo.estValide():
  153. self.ui().edc_logo.chargerImage(self.mat().logo)
  154. else:
  155. self.ui().edc_logo.majTexte("Choisissez \nun fichier\nimage")
  156. def enregistrer(self):
  157. self.mat().majNom(self.ui().edc_nom.texte())
  158. self.mat().logo = self.ui().edc_logo.image() if self.ui().edc_logo.image() else RImage()
  159. class EdPageCreation(EdSectionBase):
  160. def __init__(self, ecran):
  161. super(EdPageCreation, self).__init__(ecran)
  162. self._filtre = ["Combattant", "Decor"]
  163. self._modes = ["creation"]
  164. def construire(self):
  165. self.vueForme = VueEditionForme(self.ui().edc_vueForme)
  166. self.ecran.connect(self.ui().edc_aideForme, SIGNAL("clicked()"), self.afficherAideForme)
  167. self.ecran.connect(self.ui().edc_casesHexa, SIGNAL("clicked()"), self.majFormeCases)
  168. self.ecran.connect(self.ui().edc_casesCarrees, SIGNAL("clicked()"), self.majFormeCases)
  169. self.ecran.connect(self.ui().edc_couleur, SIGNAL("clicked()"), self.selectionCouleur)
  170. self.ecran.connect(self.ui().edc_image, SIGNAL("clicked()"), self.selectionImage)
  171. def formeCases(self):
  172. return "H" if self.ui().edc_casesHexa.isChecked() else "C"
  173. def majFormeCases(self):
  174. if self.vueForme.formeCases() != self.ecran.formeCases():
  175. #on enregistre la def de forme, d'image et d'etiquette en cours
  176. self.mat().formeDef[self.vueForme.formeCases()] = self.vueForme.formeDef()
  177. self.mat().img = self.vueForme.imageDef()
  178. self.mat().etiquette = self.vueForme.etiquetteDef()
  179. #on recree la scene avec la nouvelle forme de cases
  180. self.vueForme.vider()
  181. self.vueForme.creer(self.ecran.formeCases())
  182. #on charge les def correspondantes a la nouvelle forme
  183. self.vueForme.chargerFormeDef(self.mat().formeDef[self.formeCases()])
  184. self.vueForme.chargerImageDef(self.mat().img)
  185. self.vueForme.chargerEtiquetteDef(self.mat().etiquette)
  186. def majEtiquetteVueForme(self):
  187. self.mat().etiquette.txt = self.ui().edc_nom.texte()
  188. self.vueForme.chargerEtiquetteDef(self.mat().etiquette)
  189. def logoModifie(self):
  190. self.vueForme.nouvelleImageDef(self.ui.edc_logo.image())
  191. def selectionImage(self):
  192. """selectionne le fichier image dans la boite de dialogue dediee"""
  193. img = selectionImage()
  194. if img:
  195. self.vueForme.nouvelleImageDef(img)
  196. def selectionCouleur(self):
  197. """selectionne la couleur dans la boite de dialogue dediee"""
  198. couleur = QColorDialog(self).getColor(QColor("white"), self)
  199. if couleur.isValid():
  200. self.mat().couleur = couleur
  201. self.vueForme.majCouleur(couleur)
  202. def afficherAideForme(self):
  203. msg = "Sur l'écran ci-contre, vous pouvez éditer la forme et l'apparence de votre pion. Vous pouvez: \n\n" \
  204. "Choisir la couleur du pion \n" \
  205. "Choisir une image (qui remplacera alors le logo sur le pion) \n" \
  206. "Deplacer l'etiquette et l'image sur le pion en cliquant dessus \n" \
  207. "Faire pivoter l'image avec [FLECHE HAUT] et [FLECHE BAS] \n" \
  208. "Modifier la taille de l'image avec [FLECHE GAUCHE] et [FLECHE DROITE] \n" \
  209. "Activer desactiver l'etiquette en gras avec [G] \n" \
  210. "Modifier la taille de la police avec [FLECHE HAUT] et [FLECHE BAS]"
  211. dmMessage(msg)
  212. def charger(self):
  213. self.vueForme.creer(self.formeCases())
  214. self.vueForme.autoriserModifForme(True)
  215. self.vueForme.majCouleur(self.mat().couleur)
  216. self.vueForme.chargerFormeDef(self.mat().formeDef[self.formeCases()])
  217. self.vueForme.chargerImageDef(self.mat().img)
  218. self.vueForme.chargerEtiquetteDef(self.mat().etiquette)
  219. def enregistrer(self):
  220. self.mat().formeDef[self.vueForme.formeCases()] = self.vueForme.formeDef()
  221. self.mat().img = self.vueForme.imageDef()
  222. self.mat().etiquette = self.vueForme.etiquetteDef()
  223. class EdPageCombat(EdSectionBase):
  224. def __init__(self, ecran):
  225. super(EdPageCombat, self).__init__(ecran)
  226. self._filtre = ["Combattant", "Decor"]
  227. self._modes = ["combat"]
  228. def charger(self):
  229. pass
  230. def enregistrer(self):
  231. pass
  232. class EdPageDeplacement(EdSectionBase):
  233. def __init__(self, ecran):
  234. super(EdPageDeplacement, self).__init__(ecran)
  235. self._filtre = ["Combattant", "Decor"]
  236. def charger(self):
  237. self.ui().edc_taille.setValue(self.mat().hauteur)
  238. self.ui().edc_depMarche.setValue(self.mat().depMarche)
  239. self.ui().edc_depNage.setValue(self.mat().depNage)
  240. self.ui().edc_depEscalade.setValue(self.mat().depEscalade)
  241. self.ui().edc_depVol.setValue(self.mat().depVol)
  242. self.ui().edc_saut.setValue(self.mat().saut)
  243. def enregistrer(self):
  244. self.mat().hauteur = self.ui().edc_taille.value()
  245. self.mat().depMarche = self.ui().edc_depMarche.value()
  246. self.mat().depNage = self.ui().edc_depNage.value()
  247. self.mat().depEscalade = self.ui().edc_depEscalade.value()
  248. self.mat().depVol = self.ui().edc_depVol.value()
  249. self.mat().saut = self.ui().edc_saut.value()
  250. class EdPageAttributs(EdSectionBase):
  251. def __init__(self, ecran):
  252. super(EdPageAttributs, self).__init__(ecran)
  253. self._filtre = ["Combattant"]
  254. self._modes = ["creation", "combat"]
  255. def layoutCarac(self):
  256. """retourne le layout des attributs"""
  257. return self.ecran.ui.edc_deroulementAttributs_layout
  258. def construire(self):
  259. """construit les champs d'attributs"""
  260. """cree les champs dedies a la saisie des attributs dans la grille dediee"""
  261. self.layoutCarac().setSpacing(4)
  262. self.layoutCarac().setMargin(0)
  263. for nomAttribut in regles.ordreAttributsFichePerso():
  264. if len(nomAttribut) > 0:
  265. lay = QHBoxLayout()
  266. lay.setMargin(0)
  267. lay.setSpacing(2)
  268. etiquette = dm.DmLabel()
  269. etiquette.majTexte(regles.attribut(nomAttribut).nom)
  270. etiquette.setObjectName("{}_etiquette".format(nomAttribut))
  271. etiquette.setAlignment(Qt.AlignLeft|Qt.AlignVCenter)
  272. etiquette.setMinimumSize(QSize(110, 24))
  273. etiquette.setMaximumSize(QSize(110, 24))
  274. lay.addWidget(etiquette)
  275. champ = dm.DmLineEdit()
  276. champ.setMinimumSize(QSize(80, 24))
  277. champ.setMaximumSize(QSize(80, 24))
  278. champ.setAlignment(Qt.AlignCenter)
  279. champ.majTexte(regles.listeAttributs()[nomAttribut])
  280. champ.setObjectName("{}_champ".format(nomAttribut))
  281. champ.setStyleSheet("background-color: rgb({},{},{});".format(248,248,248))
  282. ## self.connect(champ, SIGNAL("textChanged()"), self.controlerAttribut)
  283. lay.addWidget(champ)
  284. self.layoutCarac().addLayout(lay)
  285. else:
  286. lay = QHBoxLayout()
  287. etiquetteVide = dm.DmLabel()
  288. etiquetteVide.setMinimumHeight(9)
  289. etiquetteVide.setMaximumHeight(9)
  290. lay.addWidget(etiquetteVide)
  291. lay.addWidget(etiquetteVide)
  292. self.layoutCarac().addLayout(lay)
  293. def listeAttributs(self):
  294. """renvoie la liste des attributs tels qu'ils
  295. sont saisis dans la liste des attributs"""
  296. attributs = regles.listeAttributs()
  297. for i in range(0, self.layoutCarac().count()):
  298. layout = self.layoutCarac().itemAt(i).layout()
  299. widget = layout.itemAt(1).widget()
  300. if widget != 0 and widget != None:
  301. if str(widget.objectName()[-6:]) == "_champ":
  302. attr = str(widget.objectName()[:-6])
  303. attributs[attr] = widget.texte()
  304. return attributs
  305. def charger(self):
  306. """met a jour la liste des attributs du Combattant"""
  307. for i in range(0, self.layoutCarac().count()):
  308. layout = self.layoutCarac().itemAt(i).layout()
  309. widget = layout.itemAt(1).widget()
  310. if widget != 0:
  311. if str(widget.objectName()[-6:]) == "_champ":
  312. attr = str(widget.objectName()[:-6])
  313. widget.majTexte(self.ecran.mat().listeAttributs[attr])
  314. def enregistrer(self):
  315. self.mat().attributs = self.listeAttributs()
  316. class EdPageAttaques(EdSectionBase):
  317. def __init__(self, ecran):
  318. super(EdPageAttaques, self).__init__(ecran)
  319. self._filtre = ["Combattant"]
  320. self._compteurAttaque = 0
  321. def layoutAtt(self):
  322. """retourne le layout des attaques"""
  323. return self.ecran.ui.edc_deroulementAttaques_layout
  324. def construire(self):
  325. self.layoutAtt().setAlignment(Qt.AlignLeft)
  326. def attaqueNouvelle(self, attaque = None):
  327. """ajoute une nouvelle ligne a la liste des attaques"""
  328. #on ajoute de suite un panneau 'nouvelle attaque en dessous'
  329. self._compteurAttaque += 1
  330. panneau = FrameAttaque(self._compteurAttaque)
  331. if attaque: panneau.chargerAttaque(attaque)
  332. panneau.setObjectName(QString("att_frame_{}".format(self._compteurAttaque)))
  333. self.ecran.connect(panneau, SIGNAL("attaqueNouvelle()"), self.attaqueNouvelle)
  334. self.ecran.connect(panneau, SIGNAL("attaqueSupprimer(int)"), self.attaqueSupprimer)
  335. self.layoutAtt().addWidget(panneau)
  336. def attaqueSupprimer(self, index):
  337. """supprime la ligne selectionnee de la liste des attaques"""
  338. panneau = self.findChild(QFrame, "att_frame_{}".format(index))
  339. self.layoutAtt().removeWidget(panneau)
  340. def charger(self):
  341. self.layoutAtt().setAlignment(Qt.AlignTop)
  342. for attaque in self.mat().attaques:
  343. self.attaqueNouvelle(attaque)
  344. self.attaqueNouvelle()
  345. def enregistrer(self):
  346. listeAttaques = []
  347. for i in range(0, self.layoutAtt().count()):
  348. panneau = self.layoutAtt().itemAt(i).widget()
  349. if panneau != 0:
  350. attaque = panneau.attaque()
  351. if attaque:
  352. listeAttaques.append(attaque)
  353. self.mat().attaques = listeAttaques
  354. class EdPageInventaire(EdSectionBase):
  355. def __init__(self, ecran):
  356. super(EdPageInventaire, self).__init__(ecran)
  357. self._filtre = ["Combattant", "Decor"]
  358. def construire(self):
  359. self.ecran.ui.edc_listeInventaire.construire()
  360. self.ecran.connect(self.ecran.ui.edc_filtreTypeObjet, SIGNAL("currentChanged(int)"), self.filtrerInventaire)
  361. self.ecran.ui.edc_filtreTypeObjet.stackUnder(self.ecran.ui.edc_listeInventaire)
  362. self.ecran.connect(self.ecran.ui.edc_listeInventaire, SIGNAL("objetClique(int)"), self.editerObjet)
  363. def editerObjet(self, indexObjet):
  364. if indexObjet < len(self.ecran.ui.edc_listeInventaire.inventaire()):
  365. objet = self.ecran.ui.edc_listeInventaire.inventaire()[indexObjet]
  366. else:
  367. objet = None
  368. typeObjet = self.ecran.ui.edc_filtreTypeObjet.currentIndex() - 1
  369. self.fenetreEO = EcranEditionObjet(objet, typeObjet)
  370. self.fenetreEO.show()
  371. self.fenetreEO.exec_()
  372. resultat = self.fenetreEO.resultat()
  373. if resultat:
  374. if objet:
  375. self.ecran.ui.edc_listeInventaire.majObjet(objet, resultat)
  376. else:
  377. self.ecran.ui.edc_listeInventaire.ajouterObjet(resultat)
  378. else:
  379. if objet:
  380. self.ecran.ui.edc_listeInventaire.supprimerObjet(objet)
  381. self.fenetreEO = None
  382. self.majTotauxInventaire()
  383. def majTotauxInventaire(self):
  384. inv = self.ecran.ui.edc_listeInventaire.inventaire()
  385. poidsTotal = 0.00
  386. for obj in inv:
  387. poidsTotal += obj.poidsTotal()
  388. self.ecran.ui.edc_inventaire_poids.majTexte("{} kg".format(poidsTotal))
  389. def filtrerInventaire(self, index):
  390. filtre = index - 1
  391. self.ecran.ui.edc_listeInventaire.filtrer(filtre)
  392. def charger(self):
  393. self.ui().edc_listeInventaire.charger(self.mat().inventaire)
  394. self.majTotauxInventaire()
  395. def enregistrer(self):
  396. self.mat().inventaire = self.ui.edc_listeInventaire.inventaire()
  397. class EdPageNotes(EdSectionBase):
  398. def __init__(self, ecran):
  399. super(EdPageNotes, self).__init__(ecran)
  400. self._filtre = ["Combattant", "Decor"]
  401. def construire(self):
  402. pass
  403. def charger(self):
  404. for detail in self.mat().details:
  405. widget = self.ui().edc_pages.findChild(dm.DmLineEdit, "edc_detail_{}".format(detail))
  406. if widget:
  407. widget.majTexte(self.mat().details[detail])
  408. self.ui().edc_notes.setText(QString.fromUtf8(self.mat().notes))
  409. def enregistrer(self):
  410. listeWidget = self.ui().edc_pages.findChildren(dm.DmLineEdit)
  411. for widget in listeWidget:
  412. detail = str(widget.objectName()).replace("edc_detail_","")
  413. txt = widget.texte()
  414. if len(txt) > 0: self.mat().details[detail] = txt
  415. self.mat().notes = str(self.ui().edc_notes.toPlainText().toUtf8())
  416. if __name__ == "__main__":
  417. app = QApplication(sys.argv)
  418. mat = Combattant()
  419. ecran = EcranEditionMateriel(mat, "creation")
  420. ecran.afficher()
  421. r = app.exec_()
  422. exit(r)