DMonde.py 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333
  1. from __future__ import unicode_literals
  2. # -*- coding: utf-8 -*-
  3. import os
  4. from sys import exit, argv
  5. from time import time, sleep
  6. from threading import Thread
  7. from socket import socket, AF_INET, SOCK_STREAM
  8. from subprocess import Popen, PIPE
  9. import logging
  10. import cPickle as pickle
  11. #modules importes
  12. from psutil import process_iter
  13. #import de QT et des interfaces
  14. from PyQt4.QtCore import *
  15. from PyQt4.QtGui import *
  16. from PyQt4 import QtOpenGL
  17. #from PyQt4 import QtCore, QtGui
  18. from ecran_connexion import Ui_ecranConnexion
  19. from ecran_principal import Ui_principal
  20. from ecran_chatPrive import Ui_chatPrive
  21. from visionneuse import Ui_visionneuse
  22. #modules persos
  23. from serveur import Serveur, ServeurVoc
  24. from lancer import jet
  25. from clientvoc import ClientVoc
  26. #fonctions potentiellement utiles:
  27. #print(psutil.connections())
  28. #print(psutil.net_io_counters(pernic=True))
  29. #gestion des erreurs et log
  30. logging.basicConfig(level=logging.DEBUG)
  31. logProg = logging.getLogger(__name__)
  32. handlerProg = logging.FileHandler('prog.log')
  33. handlerProg.setFormatter(logging.Formatter('[%(asctime)s] %(levelname)s- %(message)s')) #'%(name)s' nom du thread
  34. logProg.addHandler(handlerProg)
  35. logProg.debug(" ---------------------- \n")
  36. def ipValide(addr):
  37. """controle la validite d'une adresse ip"""
  38. #if addr == "localhost":
  39. # retour = addr
  40. #else:
  41. # try:
  42. # socket.inet_aton(addr)
  43. # retour = True
  44. #except socket.error:
  45. # except:
  46. # retour = False
  47. retour = True
  48. return retour
  49. class EcranConnexion(QGroupBox):
  50. """fenetre de connexion a l'application et module d'envoi/reception"""
  51. def __init__(self, parent=None):
  52. """initialisation de la connexion et creation de la fenetre"""
  53. super (EcranConnexion, self).__init__(parent)
  54. self.client_connecte = False
  55. self.serveur_connecte = False
  56. self.idServeur = ""
  57. self.idClient = "00"
  58. self.ip = ""
  59. self.pseudo = ""
  60. self.autresCo = {}
  61. #liste des chat prives ouverts avec les autres clients
  62. self.chatPrive = {}
  63. #echanges fichiers
  64. self.eFichier = {"id": "00", "chemin": "", "fichier": None, "dest": "", "envoi" : False, "annule" : False, "invisible": False}
  65. #fichier en cours d'envoi : id fichier, chemin du fichier, fichier (objet), dest, envoi autorise, envoi annule
  66. self.destFichier = {} #liste des clients dont on attend confirmation pour l'envoi de fichier
  67. self.rFichier = {} #liste des fichiers recus ou en cours de reception
  68. #(id fichier: dictionnaire des infos du fichier [nom, taille (en o), recu (en o), ligne du tableau d'affichage])
  69. self.repReceptionFichiers = os.getcwd()+"\\FichiersRecus\\"
  70. #chat voc
  71. self.ipServeurVoc = ""
  72. self.port = 6660
  73. #recup des param et affichage:
  74. try:
  75. logProg.info(self.recupParamCo())
  76. except:
  77. logProg.info("pas de parametres a recuperer")
  78. self.createWidgets()
  79. def createWidgets(self):
  80. """creation de l'interface de connexion"""
  81. self.ui = Ui_ecranConnexion()
  82. self.ui.setupUi(self)
  83. if len(self.ip) > 0:
  84. self.ui.in_ip.setText(QString.fromUtf8(self.ip))
  85. if self.port > 0:
  86. self.ui.in_port.setText(QString.fromUtf8(str(self.port)))
  87. if len(self.pseudo) > 0:
  88. self.ui.in_pseudo.setText(QString.fromUtf8(self.pseudo))
  89. self.connect(self.ui.fermer, SIGNAL("clicked()"), self.fermer)
  90. self.connect(self.ui.creerServeur, SIGNAL("clicked()"), self.creerServeur)
  91. self.connect(self.ui.seConnecter, SIGNAL("clicked()"), self.seConnecter)
  92. def msg(self, txt):
  93. """affichage d'un message informatif sous forme de label"""
  94. self.ui.txt_msg.setText(QString.fromUtf8(txt))
  95. QApplication.processEvents()
  96. def creerServeur(self):
  97. """instancie un serveur local"""
  98. self.pseudo = self.ui.in_pseudo.text()
  99. self.port = self.ui.in_port.text()
  100. if len(self.pseudo) == 0 or len(self.port) == 0:
  101. self.msg("Parametres incorrects")
  102. else:
  103. self.ui.in_ip.setText(QString.fromUtf8("localhost"))
  104. self.s = Serveur(int(self.ui.in_port.text()))
  105. self.serveur_connecte, txt = self.s.creer()
  106. self.msg(txt)
  107. if self.serveur_connecte:
  108. self.seConnecter()
  109. def seConnecter(self):
  110. """se connecte au serveur correspondant a l'ip et au port saisis"""
  111. self.pseudo = self.ui.in_pseudo.text()
  112. self.port = self.ui.in_port.text()
  113. self.ip = self.ui.in_ip.text()
  114. essais = 0
  115. if len(self.pseudo) == 0 or not ipValide(self.ip) or len(self.port) == 0:
  116. self.msg("Parametres incorrects")
  117. else:
  118. self.msg("En attente du serveur...")
  119. while self.client_connecte == False:
  120. #en attente de la connexion
  121. try:
  122. self.cnn = socket(AF_INET, SOCK_STREAM)
  123. self.cnn.connect((self.ip, int(self.port)))
  124. self.client_connecte = True
  125. txt = "Connexion etablie avec le serveur sur le port {}\n".format(self.port)
  126. logProg.info(txt)
  127. except KeyboardInterrupt:
  128. break
  129. except:
  130. essais += 1
  131. if essais > 3:
  132. txt = "Delai depasse"
  133. self.msg(txt)
  134. logProg.warning(txt)
  135. break
  136. txt = "Connexion : essai {}".format(essais)
  137. self.msg(txt)
  138. logProg.info(txt)
  139. if self.client_connecte:
  140. #demarre le fil de reception
  141. Thread(None, self.filReception, None, (), {}).start()
  142. #previent le serveur et envoie le pseudo
  143. self.envoi("ci", "sa", self.pseudo)
  144. self.msg(txt)
  145. sleep(0.01)
  146. self.close()
  147. else:
  148. txt = "Erreur: impossible de se connecter"
  149. self.msg(txt)
  150. logProg.error(txt)
  151. def filReception(self):
  152. """thread de reception des donnees du serveur, reste actif tant que l'application est active"""
  153. while self.client_connecte:
  154. recu = self.cnn.recv(1024)
  155. if len(recu) > 0:
  156. self.traitement(recu)
  157. def traitement(self, msg):
  158. """determine le traitement a apporter a un message recu, selon sa nature"""
  159. if len(msg) >= 6:
  160. emet = msg[2:4]
  161. dest = msg[4:6]
  162. categorie = msg[:1]
  163. nature = msg[:2]
  164. try:
  165. contenu = msg[6:]
  166. except:
  167. contenu = ""
  168. if nature != "fd" and nature != "ff":
  169. #on decode le message, sauf s'il contient des donnees binaires issues d'un fichier
  170. contenu = contenu.decode('utf-8')
  171. if nature == "ci":
  172. #recoit l'identifiant du client fourni par le serveur
  173. self.idClient = dest
  174. logProg.info("mon id est: {}\n".format(self.idClient))
  175. elif nature == "cc":
  176. #un autre client se connecte
  177. if contenu[0:2] != self.idClient:
  178. self.autresCo[str(contenu[0:2])] = str(contenu[2:])
  179. #on lui envoie notre id+x+pseudo (x=c si on est client simple, s si on est serveur)
  180. sleep(0.02)
  181. if self.serveur_connecte:
  182. code = "s"
  183. else:
  184. code = "c"
  185. self.envoi("cp", contenu[0:2], "{}{}{}".format(self.idClient, code, self.pseudo))
  186. logProg.info("{} s'est connecte ({})".format(contenu[2:], contenu[0:2]))
  187. self.recuInfo("cc", "{} s'est connecte ({})".format(contenu[2:], contenu[0:2]))
  188. self.emit(SIGNAL("majAffichageLstClient()"))
  189. elif nature == "cp":
  190. #ce client est deja present
  191. idClient = str(contenu[0:2])
  192. self.autresCo[idClient] = str(contenu[3:])
  193. if str(contenu[2:3]) == "s":
  194. self.idServeur = idClient
  195. sleep(0.001)
  196. logProg.info("{} est deja present [{}]".format(str(contenu[3:]), idClient))
  197. self.emit(SIGNAL("majAffichageLstClient()"))
  198. elif nature == "cd":
  199. #un client se deconnecte
  200. if contenu != self.idClient and len(contenu) == 2:
  201. logProg.info("{} s'est deconnecte ({})".format(self.autresCo[contenu], contenu))
  202. self.recuInfo("cd", "{} s'est deconnecte ({})".format(self.autresCo[contenu], contenu))
  203. if contenu in self.chatPrive:
  204. self.chatPrive[contenu].close()
  205. del self.chatPrive[contenu]
  206. del self.autresCo[contenu]
  207. sleep(0.001)
  208. self.emit(SIGNAL("majAffichageLstClient()"))
  209. elif categorie == "m":
  210. if nature == "m ":
  211. #afficher dans le chat publique
  212. logProg.info("chat: {} -> {}\n".format(emet, contenu))
  213. self.recuMsg(emet, contenu)
  214. elif nature == "mp":
  215. #message pour le chat prive
  216. self.emit(SIGNAL("chatPrive(QString, QString,QString)"), QString.fromUtf8(emet), QString.fromUtf8(contenu), QString.fromUtf8(""))
  217. elif nature == "md":
  218. #jet de des pour le chat prive
  219. self.emit(SIGNAL("chatPrive(QString, QString,QString)"), QString.fromUtf8(emet), QString.fromUtf8(contenu), QString.fromUtf8("red"))
  220. elif categorie == "i":
  221. #afficher dans la fenetre évènement
  222. self.recuInfo(nature, contenu)
  223. if nature == "id":
  224. #jet de dés: afficher en rouge
  225. logProg.info("jet de dé: {} -> {}\n".format(emet, contenu))
  226. elif nature == "ic":
  227. #nouveau client connecte: afficher en bleu
  228. logProg.info("info connexion: {} -> {}\n".format(emet, contenu))
  229. elif categorie == "f":
  230. #envoi ou reception de fichier
  231. if nature == "f0":
  232. #le serveur nous renvoie l'identifiant du fichier que l'on veut envoyer
  233. if self.eFichier["id"] == "00":
  234. self.eFichier["id"] = contenu
  235. else:
  236. logProg.warning("Un fichier est deja en cours d'envoi\n")
  237. elif nature == "fp":
  238. #un clients est pret a recevoir le fichier
  239. self.pretEnvoiFichier(emet)
  240. elif nature == "fi":
  241. #quelqu'un nous envoie un fichier
  242. try:
  243. if len(contenu)>2:
  244. #les 2 premiers car sont l'identifiant, puis le nom/taille du fichier (taille.nom)
  245. try:
  246. taille = int(contenu[2:].split(".",1)[0]) #on coupe seulement suivant le premier point
  247. nom_recu = contenu[2:].split(".",1)[1]
  248. except:
  249. logProg.error("impossible de lire la taille du nouveau fichier: {}".format(contenu[2:]))
  250. taille = 0
  251. nom_recu = contenu[2:]
  252. #on determine le nom qu'aura le fichier recu (au cas ou un fichier portant ce nom existe deja)
  253. essai = self.nouveauFichier(contenu[0:2], nom_recu, taille)
  254. logProg.info("Creation d'un nouveau fichier: {}".format(essai))
  255. if len(essai) > 0:
  256. if dest == self.idClient:
  257. #si le fichier n'est destine qu'a nous, on affiche aussi le msg dans la fenetre de chat prive
  258. txt = "{} vous envoie {} ({} ko)".format(emet, nom_recu, int(taille/1000))
  259. self.emit(SIGNAL("chatPrive(QString, QString, QString)"), QString.fromUtf8(emet), QString.fromUtf8(txt), QString.fromUtf8("blue"))
  260. self.recuInfo(nature, "Fichier {} en cours de reception ({} ko)".format(nom_recu, int(taille/1000)))
  261. #on envoie confirmation de la reception:
  262. sleep(0.001)
  263. self.envoi("fp", emet, contenu[0:2])
  264. self.emit(SIGNAL("majAffichageRecFichier(QString)"), QString.fromUtf8(contenu[0:2]))
  265. else:
  266. self.recuInfo(nature, "Impossible de créer le fichier à recevoir")
  267. logProg.error("Impossible de créer le fichier à recevoir")
  268. else:
  269. logProg.error("erreur reception fichier: id ou nom du fichier incorrect\n")
  270. except:
  271. #erreur de reception
  272. logProg.error("erreur de reception des donnees du fichier\n")
  273. self.envoi("fe", emet, contenu[0:2])
  274. elif nature == "fd":
  275. #on recoit les donnees a ecrire dans le fichier
  276. try:
  277. if len(contenu) > 2:
  278. if not self.rFichier[contenu[0:2]]["annule"]:
  279. self.rFichier[contenu[0:2]]["fichier"].write(contenu[2:])
  280. self.rFichier[contenu[0:2]]["recu"] += len(contenu[2:])
  281. try:
  282. taux = int(100*self.rFichier[contenu[0:2]]["recu"] / self.rFichier[contenu[0:2]]["taille"])
  283. except:
  284. taux = "."
  285. self.emit(SIGNAL("majAffichageRecFichier(QString)"), QString.fromUtf8(contenu[0:2]))
  286. #le client renvoie la longueur de la donnee recue a l'emetteur pour confirmation
  287. sleep(0.001)
  288. self.envoi("fp", emet, contenu[0:2])
  289. elif len(contenu) == 2:
  290. #l'emetteur redemande confirmation, on lui envoie
  291. if not self.rFichier[contenu[0:2]]["annule"]:
  292. self.envoi("fp", emet, contenu[0:2])
  293. else:
  294. #erreur de reception, on annule la reception et on le signale
  295. logProg.error("erreur de reception des donnees du fichier\n")
  296. self.rFichier[contenu[0:2]]["annule"] = True
  297. self.envoi("fe", emet, contenu[0:2])
  298. except:
  299. #erreur de reception, on annule la reception et on le signale
  300. logProg.error("erreur de reception des donnees du fichier\n")
  301. self.rFichier[contenu[0:2]]["annule"] = True
  302. self.envoi("fe", emet, contenu[0:2])
  303. elif nature == "ff":
  304. #fin de reception du fichier
  305. try:
  306. self.rFichier[contenu[0:2]]["fichier"].write(contenu[2:])
  307. sleep(0.001)
  308. self.envoi("fp", emet, contenu[0:2])
  309. sleep(0.01)
  310. self.rFichier[contenu[0:2]]["fichier"].close()
  311. self.rFichier[contenu[0:2]]["termine"] = True
  312. except:
  313. #erreur de reception, on annule la reception et on le signale
  314. logProg.error("erreur de reception des donnees du fichier\n")
  315. self.rFichier[contenu[0:2]]["annule"] = True
  316. self.envoi("fe", emet, contenu[0:2])
  317. if self.rFichier[contenu[0:2]]["termine"]:
  318. self.emit(SIGNAL("majAffichageRecFichier(QString)"), QString.fromUtf8(contenu[0:2]))
  319. self.emit(SIGNAL("imageRecue(QString)"), QString.fromUtf8(contenu[0:2]))
  320. self.recuInfo("ff", "Fichier {} recu\n".format(self.rFichier[contenu[0:2]]["nomOriginal"]))
  321. if dest == self.idClient:
  322. #si le fichier n'est destine qu'a nous, on affiche aussi le msg dans la fenetre de chat prive
  323. txt = "Fichier {} bien recu".format(self.rFichier[contenu[0:2]]["nomOriginal"])
  324. self.emit(SIGNAL("chatPrive(QString, QString, QString)"), QString.fromUtf8(emet), QString.fromUtf8(txt), QString.fromUtf8("blue"))
  325. logProg.info("Fichier recu")
  326. elif nature == "fa":
  327. #envoi annule
  328. logProg.info("Annulation de la reception du fichier")
  329. if self.rFichier[contenu[0:2]]:
  330. self.rFichier[contenu[0:2]]["annule"] = True
  331. self.recuInfo("ff", "Reception {} annule \n".format(self.rFichier[contenu[0:2]]["nom"]))
  332. if dest == self.idClient:
  333. #si le fichier n'est destine qu'a nous, on affiche aussi le msg dans la fenetre de chat prive
  334. txt = "Transfert du fichier {} annule".format(self.rFichier[contenu[0:2]]["nomOriginal"])
  335. self.emit(SIGNAL("chatPrive(QString, QString, QString)"), QString.fromUtf8(emet), QString.fromUtf8(txt), QString.fromUtf8("blue"))
  336. self.emit(SIGNAL("majAffichageRecFichier(QString)"), QString.fromUtf8(contenu[0:2]))
  337. sleep(0.01)
  338. self.rFichier[contenu[0:2]]["fichier"].close()
  339. #on supprime le fichier incomplet:
  340. essais = 0
  341. while essais < 100:
  342. try:
  343. os.remove(self.rFichier[contenu[0:2]]["fichier"].name)
  344. break
  345. except:
  346. essais += 1
  347. if essais == 100:
  348. logProg.error("Possible erreur de suppression du fichier temporaire")
  349. del self.rFichier[contenu[0:2]]
  350. elif nature == "fe":
  351. #le destinataire du fichier signale une erreur de reception
  352. self.recuInfo("fe", "{}: erreur de reception du fichier, l'envoi est annule \n".format(emet))
  353. self.annuleEnvoiFichier()
  354. elif categorie == "s":
  355. #infos sur le fonctionnement du serveur principal
  356. if nature == "sd":
  357. #le serveur a ete ferme
  358. self.serveurDeco()
  359. elif categorie == "v":
  360. #infos liees au chat vocal
  361. if nature == "vs":
  362. #un serveur vocal a ete cree
  363. self.recuInfo("vs", "{} a cree un serveur vocal ({})".format(self.autresCo[emet], contenu))
  364. self.ipServeurVoc = contenu
  365. if nature == "vi":
  366. #un client rejoint le chat vocal
  367. self.recuInfo("vi", "{} a rejoint le chat vocal".format(self.autresCo[emet]))
  368. if nature == "vq":
  369. #un client quitte le chat vocal
  370. self.recuInfo("vq", "{} a quitte le chat vocal".format(self.autresCo[emet]))
  371. if nature == "vf":
  372. #fermeture du serveur vocal
  373. self.recuInfo("vf", "{} a ferme le serveur vocal".format(self.autresCo[emet]))
  374. elif categorie == "p":
  375. if nature == "pi":
  376. #nouveau plateau créé
  377. logProg.info("nouveau plateau: {}\n".format(emet, contenu))
  378. else:
  379. logProg.warning("Erreur: message illisible -> {}\n".format(msg))
  380. def recuInfo(self, nature, contenu):
  381. """signale une nouvelle information"""
  382. self.emit(SIGNAL("nouvelleInfo(QString, QString)"), QString.fromUtf8(nature), QString.fromUtf8(contenu))
  383. def recuMsg(self, emetteur, contenu):
  384. """signale un nouveau message texte pour le chat ecrit"""
  385. self.emit(SIGNAL("msgChat(QString, QString)"), QString.fromUtf8(emetteur), QString.fromUtf8(contenu))
  386. def envoi(self, nature, dest, msg, idFichier = ""):
  387. """envoie un message au serveur TCP
  388. - longueur du message (3 car)
  389. - nature du message (2 car)
  390. - exp: id de l'expediteur (2 car)
  391. - dest: id du destinataire (2 car)
  392. - msg: contenu du message (999 car max)
  393. - un identifiant pour le fichier le cas echeant"""
  394. exp = self.idClient
  395. if self.client_connecte:
  396. try:
  397. if len(msg) <= 999:
  398. if len(idFichier) == 0:
  399. msg = unicode(msg)
  400. lg = "%003.f"%len(msg.encode('utf-8')) #la longueur apres encodage peut changer
  401. txt = "{}{}{}{}{}".format(lg, nature, exp, dest, msg)
  402. txt = txt.encode('utf-8')
  403. else:
  404. lg = "%003.f"%(len(msg)+2)
  405. txt = "{}{}{}{}{}".format(lg, nature, exp, dest, idFichier)
  406. txt = txt.encode('utf-8') + msg
  407. retour = len(txt)
  408. self.cnn.sendall(txt)
  409. else:
  410. self.recuInfo(" ","999 caracteres au max.")
  411. retour = 0
  412. except:
  413. retour = 0
  414. logProg.warning("Envoi impossible")
  415. else:
  416. retour = ""
  417. logProg.warning("Le client n'est pas connecte au serveur")
  418. self.recuInfo(" ","Vous n'etes pas connecte a un serveur")
  419. return retour
  420. def envoiFichier(self, chemin, dest = "ac"):
  421. """intialise l'envoi d'un fichier"""
  422. if self.eFichier["id"] == "00":
  423. # on verifie si le fichier existe:
  424. fichier = None
  425. try:
  426. fichier = open(chemin, "rb")
  427. except:
  428. logProg.error("Le fichier '{}' est introuvable.".format(fichier))
  429. if not os.path.getsize(chemin) > 0:
  430. logProg.error("Envoi impossible - fichier vide")
  431. fichier.close()
  432. fichier = None
  433. if fichier:
  434. #on demande un identifiant au serveur
  435. self.eFichier["fichier"] = fichier
  436. self.eFichier["chemin"] = chemin
  437. self.eFichier["dest"] = dest
  438. self.eFichier["annule"] = False
  439. self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(os.path.basename(chemin)), QString.fromUtf8("0"))
  440. logProg.debug(self.eFichier)
  441. if dest == "ac":
  442. for idC in self.autresCo:
  443. self.destFichier[idC] = False
  444. else:
  445. self.destFichier[dest] = False
  446. #on demande un identifiant au serveur
  447. self.envoi("f0","sa","")
  448. Thread(None, self.envoiFichier_fil, None, (), {}).start()
  449. else:
  450. self.recuInfo("fi", "Impossible d'envoyer le fichier, un fichier est peut-etre deja en cours d'envoi")
  451. def envoiFichier_fil(self):
  452. """le fichier est pret a etre envoye, on attend confirmation des destinataires"""
  453. #on attend que l'id du fichier soit mis a jour
  454. essais = 0
  455. while self.eFichier["id"]=="00" and essais < 3000:
  456. sleep(0.001)
  457. essais += 1
  458. if len(self.eFichier["id"]) == 2 and self.eFichier["id"] != "00":
  459. idFichier = self.eFichier["id"]
  460. dest = self.eFichier["dest"]
  461. nomFichier = os.path.basename(self.eFichier["chemin"])
  462. taille = os.path.getsize(self.eFichier["chemin"])
  463. logProg.debug("{} a pour id {}\n".format(nomFichier, idFichier))
  464. #on previent les destinataires, et on leur transmet l'identifiant et taille.nom du fichier (taille au format numerique, en octets)
  465. logProg.info("En attente des destinataires...")
  466. self.recuInfo("fi", "{} - En attente des destinataires...".format(nomFichier))
  467. self.envoi("fi", dest, "{}{}.{}".format(idFichier, taille, nomFichier))
  468. essais = 0
  469. while not self.eFichier["envoi"] and not self.eFichier["annule"]:
  470. sleep(0.001)
  471. essais += 1
  472. if essais >= 3000:
  473. logProg.error("Pas de reponse des destinataires - envoi avorte")
  474. self.eFichier["annule"] = True
  475. if not self.eFichier["annule"]:
  476. #on a recu confirmation de la part des destinataires
  477. envoye = 0
  478. essais = 0
  479. #on lit un premier paquet de donnees
  480. data = self.eFichier["fichier"].read(512)
  481. while len(data) == 512 and not self.eFichier["annule"]:
  482. #on reinitialise le controle de reception pour le prochain paquet:
  483. self.eFichier["envoi"] = False
  484. if dest == "ac":
  485. for idC in self.autresCo:
  486. self.destFichier[idC] = False
  487. else:
  488. self.destFichier[dest] = False
  489. #on envoie le paquet precedent, que les destinataires ont confirme pouvoir recevoir
  490. self.envoi("fd", dest, data, idFichier)
  491. envoye += len(data)
  492. taux = str((100*envoye)/taille)
  493. self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8(taux))
  494. #logProg.info("{} / {}".format(int(envoye/1000), int(taille/1000))) #attention: ralentit enormement l'envoi
  495. #on attend que les clients confirment reception pour envoyer le prochain
  496. essais = 0
  497. while not self.eFichier["envoi"]:
  498. if self.eFichier["annule"]:
  499. break
  500. sleep(0.001)
  501. essais += 1
  502. if essais >= 500:
  503. #on renvoie un message toutes les demi-secondes pour redemander confirmation
  504. self.envoi("fd", dest, b'', idFichier)
  505. essais = 0
  506. #on lit le paquet suivant
  507. data = self.eFichier["fichier"].read(512)
  508. #FIN DE LA BOUCLE, on a envoye tous les paquets de 512o, il reste donc un dernier paquet a envoyer
  509. #pour dernier paquet on ajoute au drapeau: "%003.f"%len(paquet)
  510. #on signale que c'est le dernier paquet et on ajoute 3 caracteres pour en specifier la taille:
  511. #ENVOI DU DERNIER PAQUET:
  512. if not self.eFichier["annule"]:
  513. #on reinitialise le controle de reception pour le prochain paquet:
  514. self.eFichier["envoi"] = False
  515. if dest == "ac":
  516. for idC in self.autresCo:
  517. self.destFichier[idC] = False
  518. else:
  519. self.destFichier[dest] = False
  520. #on envoie le paquet precedent, que les destinataires ont confirme pouvoir recevoir
  521. self.envoi("ff", dest, data, idFichier)
  522. envoye += len(data)
  523. taux = str((100*envoye)/taille)
  524. self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8(taux))
  525. #on attend que les clients confirment reception pour envoyer le signal de fin
  526. essais = 0
  527. while not self.eFichier["envoi"]:
  528. if self.eFichier["annule"]:
  529. break
  530. sleep(0.001)
  531. essais += 1
  532. if essais >= 500:
  533. #on renvoie un message pour redemander confirmation
  534. logProg.warning("envoi fichier - on redemande confirmation")
  535. self.envoi("fd", dest, b'', idFichier)
  536. essais = 0
  537. #on signale au serveur qu'il peut liberer l'id du fichier
  538. self.envoi("f1", "sa", "{}".format(idFichier))
  539. self.recuInfo("ff", "- {} a bien ete envoye -".format(nomFichier))
  540. logProg.info("\n- Fichier envoye -")
  541. else:
  542. logProg.error("Erreur envoi fichier: signal serveur non-recu -> {}".format(self.eFichier["id"]))
  543. else:
  544. logProg.error("Erreur envoi fichier: identifiant incorrect -> {}".format(idFichier))
  545. self.eFichier["fichier"].close()
  546. self.eFichier = {"id": "00", "chemin": "", "fichier": None, "dest": "", "envoi" : False, "annule": False}
  547. def pretEnvoiFichier(self, idClient):
  548. """signale un destinataire comme etant pret a recevoir le fichier ou le paquet de donnees,
  549. et renvoie Vrai si tous les destinataires sont prets"""
  550. pretEnvoi = False
  551. if self.eFichier["dest"] == "ac":
  552. self.destFichier[idClient] = True
  553. pretEnvoi = True
  554. for idC in self.destFichier:
  555. if self.destFichier[idC] == False:
  556. pretEnvoi = False
  557. else:
  558. if idClient == self.eFichier["dest"]:
  559. pretEnvoi = True
  560. #print("{} -> {}".format(idClient, pretEnvoi))
  561. self.eFichier["envoi"] = pretEnvoi
  562. def annuleEnvoiFichier(self):
  563. """annule l'envoi d'un fichier"""
  564. logProg.warning("Annulation de l'envoi")
  565. self.envoi("fa", self.eFichier["dest"], "{}".format(self.eFichier["id"]))
  566. self.eFichier["annule"] = True
  567. essais = 0
  568. while not self.eFichier["id"] == "00":
  569. sleep(0.01)
  570. essais += 1
  571. if essais > 500:
  572. logProg.error("Erreur: impossible d'annuler l'envoi")
  573. if self.eFichier["id"] == "00":
  574. logProg.info("-> Envoi annulé")
  575. self.recuInfo("fa", "- Envoi du fichier annule -")
  576. self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8("x"))
  577. def nouveauFichier(self, idFichier, nomFichier, taille):
  578. """cree le fichier a recevoir - le renomme si un fichier portant ce nom existe deja - retourne le chemin complet"""
  579. k = 1
  580. tmp = nomFichier
  581. retour = ""
  582. try:
  583. while os.path.isfile(self.repReceptionFichiers+tmp):
  584. k += 1
  585. tmp = nomFichier.split(".")[0]+str(k)+"."+nomFichier.split(".")[1]
  586. if k == 100:
  587. tmp = ""
  588. break
  589. if len(tmp) > 0:
  590. fichier = open((self.repReceptionFichiers + tmp), "wb")
  591. self.rFichier[idFichier] = {"fichier": fichier, "nom": tmp, "nomOriginal": nomFichier, "taille": taille, "recu": 0, "ligneAffichage": None, "termine": False, "annule": False}
  592. retour = tmp
  593. except:
  594. logProg.error("Impossible de creer le fichier")
  595. return retour
  596. def serveurDeco(self):
  597. """le serveur a ferme - on affiche a nouveau l'ecran de connexion"""
  598. #on annule les envois de fichier en cours
  599. if self.eFichier["fichier"] != None:
  600. self.eFichier["annule"] = True
  601. self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8("x"))
  602. #on annule les receptions de fichiers en cours
  603. for idFichier in self.rFichier:
  604. if not self.rFichier[idFichier]["termine"]:
  605. logProg.warning("{} - reception annulee".format(self.rFichier[idFichier]["nom"]))
  606. self.rFichier[idFichier]["fichier"].close()
  607. os.remove(self.rFichier[idFichier]["fichier"].name)
  608. self.emit(SIGNAL("majAffichageRecFichier(QString)"), QString.fromUtf8(idFichier))
  609. self.rFichier = {}
  610. self.recuInfo("sd", "(!) Le serveur a mis la clef sous la porte (!)")
  611. self.idServeur = ""
  612. logProg.warning("Serveur deconnecte")
  613. self.cnn.close()
  614. self.client_connecte = False
  615. self.serveur_lance = False
  616. sleep(0.01)
  617. self.emit(SIGNAL("majAffichage()"))
  618. #on affiche l'ecran de connexion
  619. self.show()
  620. self.raise_()
  621. self.activateWindow()
  622. self.msg("Le serveur a ete deconnecte")
  623. def recupParamCo(self):
  624. """recupere les derniers parametres de connexion enregistres s'il existent"""
  625. try:
  626. with open("parametresCo", 'rb') as input:
  627. dico = pickle.load(input)
  628. self.pseudo = dico["pseudo"]
  629. self.port = dico["port"]
  630. self.ip = dico["ip"]
  631. if os.path.isdir(dico["repReceptionFichiers"]):
  632. self.repReceptionFichiers = dico["repReceptionFichiers"]
  633. retour = dico
  634. input.close()
  635. except IOError:
  636. retour = ("Erreur: parametresCo introuvable")
  637. return retour
  638. def sauverParamCo(self):
  639. """sauvegarde les parametres de connexion pour une prochaine utilisation"""
  640. with open("parametresCo", 'wb') as output:
  641. dico = {"pseudo": str(self.pseudo), "port" : int(self.port), "ip": str(self.ip), "repReceptionFichiers" : str(self.repReceptionFichiers)}
  642. pickle.dump(dico, output, -1)
  643. output.close()
  644. chaine = "parametres sauvegarde."
  645. return chaine
  646. def fermer(self):
  647. """fermeture de la connexion, et du serveur le cas echeant"""
  648. if self.client_connecte:
  649. try:
  650. self.envoi("cd", "sa", "")
  651. except:
  652. logProg.warning("impossible de prévenir le serveur de la deco")
  653. for fenetre in self.chatPrive:
  654. self.chatPrive[fenetre].close()
  655. self.chatPrive = {}
  656. self.client_connecte = False
  657. self.cnn.close()
  658. if self.eFichier["fichier"] != None:
  659. self.eFichier["annule"] = True
  660. sleep(0.001)
  661. logging.info(self.sauverParamCo())
  662. if self.serveur_connecte:
  663. self.s.stop()
  664. self.serveur_connecte = False
  665. sleep(0.001)
  666. self.close()
  667. def closeEvent(self, event):
  668. """sur fermeture de la fenetre"""
  669. if self.client_connecte:
  670. self.emit(SIGNAL("majAffichage()"))
  671. else:
  672. self.fermer()
  673. class AfficherImage(QGroupBox):
  674. """fenetre pop-up permettant l'affichage d'une image"""
  675. def __init__(self, chemin, parent=None):
  676. super (AfficherImage, self).__init__(parent)
  677. self.ui = Ui_visionneuse()
  678. self.ui.setupUi(self)
  679. self.setWindowTitle(QString.fromUtf8(chemin))
  680. myPixmap = QPixmap(chemin)
  681. myScaledPixmap = myPixmap.scaled(self.ui.label.size(), Qt.KeepAspectRatio)
  682. self.ui.label.setPixmap(myScaledPixmap)
  683. self.resize(myScaledPixmap.width(),myScaledPixmap.height())
  684. class ChatPrive(QMainWindow):
  685. """interface de chat prive entre 2 joueurs"""
  686. def __init__(self, connexion, interloc, parent=None):
  687. """initialisation de la fenetre"""
  688. super (ChatPrive, self).__init__(parent)
  689. self.co = connexion
  690. self.idInterloc = interloc
  691. self.createWidgets()
  692. def createWidgets(self):
  693. """construction de l'interface"""
  694. #construction de l'interface
  695. self.ui = Ui_chatPrive()
  696. self.ui.setupUi(self)
  697. self.ui.lblInterlocChatPrive.setText(QString.fromUtf8("Chat prive avec {}".format(self.co.autresCo[self.idInterloc])))
  698. self.connect(self.ui.inSaisieChatPrive, SIGNAL("returnPressed()"), self.envoiMsgPrive)
  699. self.connect(self.ui.envoiFichierChatPrive, SIGNAL("clicked()"), self.envoyerfichierPrive)
  700. self.connect(self.ui.inDesChatPrive, SIGNAL("returnPressed()"), self.jetDesPrive)
  701. def envoiMsgPrive(self):
  702. """ajout d'une ligne au chat prive"""
  703. msg = self.ui.inSaisieChatPrive.text()
  704. self.afficherMsgPrive(self.co.idClient, msg)
  705. self.co.envoi("mp", "{}".format(self.idInterloc), msg)
  706. self.ui.inSaisieChatPrive.clear()
  707. QApplication.processEvents()
  708. def envoyerfichierPrive(self):
  709. """envoi d'un fichier a l'interlocuteur actuel"""
  710. if self.co.eFichier["id"] == "00":
  711. fichier = QFileDialog.getOpenFileName(
  712. self,
  713. "Selectionnez un fichier a envoyer",
  714. "c:\\",
  715. "")
  716. if len(str(fichier)) > 0:
  717. self.co.envoiFichier(str(fichier), self.idInterloc)
  718. else:
  719. self.co.annuleEnvoiFichier()
  720. def jetDesPrive(self):
  721. """ajout d'une ligne de jet de des au chat prive"""
  722. expr = str(self.ui.inDesChatPrive.text())
  723. self.ui.inDesChatPrive.clear()
  724. res, detail = jet(expr)
  725. if res > 0:
  726. txt = "{} ({}) [{}]".format(res, detail, expr)
  727. self.afficherMsgPrive(self.co.idClient, txt, "red")
  728. self.co.envoi("md", self.idInterloc, txt)
  729. else:
  730. self.afficherMsgPrive(self.co.idClient, "mmmhh, pas bon le jet", "red")
  731. return res
  732. def afficherMsgPrive(self, emetteur, msg, couleur="black"):
  733. """ajoute un message au chat prive"""
  734. emetteur = str(emetteur)
  735. if len(couleur)>0 and couleur != "black":
  736. if emetteur != self.co.idClient:
  737. pseudo = self.co.autresCo["{}".format(emetteur)]
  738. else:
  739. pseudo = self.co.pseudo
  740. txt = "<font color=\"{}\">{} - {}</font>".format(couleur, pseudo, msg)
  741. else:
  742. if emetteur == self.co.idClient:
  743. txt = "<font color=\"blue\">{} : </font> {}".format(self.co.pseudo, msg)
  744. elif emetteur in self.co.autresCo:
  745. pseudo = self.co.autresCo["{}".format(emetteur)]
  746. txt = "<font color=\"green\">{} : </font> {}".format(pseudo, msg)
  747. else:
  748. txt = str(msg)
  749. txt = QString.fromUtf8(txt)
  750. item = QListWidgetItem(self.ui.lstChatPrive)
  751. self.ui.lstChatPrive.addItem(item)
  752. label = QLabel()
  753. label.setWordWrap(True)
  754. label.setText(txt)
  755. item.setSizeHint(QSize(1, label.heightForWidth (self.ui.lstChatPrive.width()) + 5))
  756. self.ui.lstChatPrive.setItemWidget(item, label)
  757. self.ui.lstChatPrive.scrollToItem(item)
  758. self.show()
  759. self.raise_()
  760. self.activateWindow()
  761. QApplication.processEvents()
  762. class EcranPrincipal(QMainWindow):
  763. """interface comprenant: chat ecrit, fenetre d'infos, lancer de des, echange de fichiers, lancement du chat vocal"""
  764. def __init__(self, connexion, parent=None):
  765. """initialisation de la fenetre"""
  766. super (EcranPrincipal, self).__init__(parent)
  767. self.co = connexion
  768. self.connecte = True
  769. self.estServeurVoc = False
  770. self.estClientVoc = False
  771. self.cases = {}
  772. self.createWidgets()
  773. def createWidgets(self):
  774. """construction de l'interface"""
  775. #construction de l'interface
  776. self.ui = Ui_principal()
  777. self.ui.setupUi(self)
  778. #connexion des commandes
  779. self.connect(self.ui.inChat, SIGNAL("returnPressed()"), self.envoiMsg)
  780. self.connect(self.ui.d20, SIGNAL("clicked()"), self.d20)
  781. self.connect(self.ui.d100, SIGNAL("clicked()"), self.d100)
  782. self.connect(self.ui.inJetDes, SIGNAL("returnPressed()"), self.autreJet)
  783. self.connect(self.ui.envoiFichier, SIGNAL("clicked()"), self.envoyerfichier)
  784. self.connect(self.ui.repReceptionFichiers, SIGNAL("clicked()"), self.repReception)
  785. self.connect(self.ui.listFichiers, SIGNAL("itemDoubleClicked(QTreeWidgetItem*, int)"), self.ouvrirFichier)
  786. self.connect(self.ui.lstStatutJoueurs, SIGNAL("itemDoubleClicked (QListWidgetItem *)"), self.ouvrirChatPrive)
  787. self.connect(self.ui.chatVoc, SIGNAL("clicked()"), self.chatVoc)
  788. #reception des signaux self.emit(SIGNAL("majAffichage()"))
  789. self.connect(self, SIGNAL("msgChat(QString, QString)"), self.ajoutChat)
  790. self.connect(self.co, SIGNAL("msgChat(QString, QString)"), self.ajoutChat)
  791. self.connect(self, SIGNAL("nouvelleInfo(QString, QString)"), self.ajoutInfo)
  792. self.connect(self.co, SIGNAL("nouvelleInfo(QString, QString)"), self.ajoutInfo)
  793. self.connect(self, SIGNAL("majAffichageRecFichier(QString)"), self.afficheReception)
  794. self.connect(self.co, SIGNAL("majAffichageRecFichier(QString)"), self.afficheReception)
  795. self.connect(self, SIGNAL("imageRecue(QString)"), self.imageRecue)
  796. self.connect(self.co, SIGNAL("imageRecue(QString)"), self.imageRecue)
  797. self.connect(self, SIGNAL("initEnvFichier(QString, QString)"), self.afficheEnvoi)
  798. self.connect(self.co, SIGNAL("initEnvFichier(QString, QString)"), self.afficheEnvoi)
  799. self.connect(self, SIGNAL("majAffichage()"), self.majStatut)
  800. self.connect(self.co, SIGNAL("majAffichage()"), self.majStatut)
  801. self.connect(self, SIGNAL("majAffichageLstClient()"), self.majStatutLstClients)
  802. self.connect(self.co, SIGNAL("majAffichageLstClient()"), self.majStatutLstClients)
  803. self.connect(self, SIGNAL("chatPrive(QString, QString, QString)"), self.chatPrive)
  804. self.connect(self.co, SIGNAL("chatPrive(QString, QString, QString)"), self.chatPrive)
  805. #plateau de jeu
  806. self.creerPlateau(20,20)
  807. self.nouveauPion()
  808. #mise a jour de l'affichage
  809. self.majStatut()
  810. self.majStatutLstClients()
  811. """def msg(self, txt):
  812. self.ui.txt_msg.setText(QString.fromUtf8(txt))
  813. QApplication.processEvents()"""
  814. def ajoutChat(self, emetteur, msg):
  815. """ajoute une nouvelle ligne au chat ecrit"""
  816. emetteur = str(emetteur)
  817. if emetteur == self.co.idClient:
  818. txt = "<font color=\"blue\">{} : </font> {}".format(self.co.pseudo, msg)
  819. else:
  820. pseudo = self.co.autresCo["{}".format(emetteur)]
  821. txt = "<font color=\"green\">{} : </font> {}".format(pseudo, msg)
  822. txt = QString.fromUtf8(txt)
  823. item = QListWidgetItem(self.ui.listAffichage)
  824. self.ui.listAffichage.addItem(item)
  825. label = QLabel()
  826. label.setWordWrap(True)
  827. label.setText(txt)
  828. item.setSizeHint(QSize(1, label.heightForWidth (self.ui.listAffichage.width()) + 5))
  829. self.ui.listAffichage.setItemWidget(item, label)
  830. self.ui.listAffichage.scrollToItem(item)
  831. QApplication.processEvents()
  832. def ajoutInfo(self, nature, msg):
  833. """ajoute une nouvelle ligne a la liste des evenements"""
  834. #couleur selon nature de l'info:
  835. if nature[:1] == "c":
  836. txt = "<font color=\"green\">{}</font>".format(msg)
  837. elif nature == "id":
  838. txt = "<font color=\"red\">{}</font>".format(msg)
  839. elif nature[:1] == "f":
  840. txt = "<font color=\"blue\">{}</font>".format(msg)
  841. elif nature[:1] == "v":
  842. txt = "<font color=\"orange\">{}</font>".format(msg)
  843. else:
  844. txt = msg
  845. txt = QString.fromUtf8(txt)
  846. item = QListWidgetItem(self.ui.listEvenement)
  847. self.ui.listEvenement.addItem(item)
  848. label = QLabel()
  849. label.setWordWrap(True)
  850. label.setText(txt)
  851. item.setSizeHint(QSize(110, label.heightForWidth (self.ui.listEvenement.width()) + 6))
  852. self.ui.listEvenement.setItemWidget(item, label)
  853. self.ui.listEvenement.scrollToItem(item)
  854. QApplication.processEvents()
  855. def envoiMsg(self):
  856. """envoie un message pour le chat ecrit"""
  857. msg = self.ui.inChat.text()
  858. self.co.envoi("m ", "tc", msg)
  859. self.ui.inChat.clear()
  860. QApplication.processEvents()
  861. def lancerD(self, expr):
  862. """fonction de lancer de des"""
  863. res, detail = jet(expr)
  864. if res > 0:
  865. txt = "{}: {} ({}) [{}]".format(self.co.pseudo, res, detail, expr)
  866. self.co.envoi("id", "tc", txt)
  867. else:
  868. self.ajoutInfo("id", "mmmhh, pas bon le jet")
  869. return res
  870. def d20(self):
  871. """lance un D20"""
  872. self.lancerD("1d20")
  873. def d100(self):
  874. """lance un D100"""
  875. self.lancerD("1d100")
  876. def autreJet(self):
  877. """lance un jet personnalise"""
  878. expr = str(self.ui.inJetDes.text())
  879. retour = self.lancerD(expr)
  880. self.ui.inJetDes.clear()
  881. def envoyerfichier(self):
  882. """selectionne et envoie un fichier ou annule l'envoi en cours s'il existe"""
  883. if self.co.eFichier["id"] == "00":
  884. fichier = QFileDialog.getOpenFileName(
  885. self,
  886. "Selectionnez un fichier a envoyer",
  887. "c:\\",
  888. "")
  889. if len(str(fichier)) > 0:
  890. self.co.envoiFichier(str(fichier))
  891. else:
  892. self.co.annuleEnvoiFichier()
  893. def ouvrirFichier(self):
  894. """ouvre un fichier depuis la liste des fichiers recus/envoyes"""
  895. item = self.ui.listFichiers.currentItem()
  896. eR = item.text(0)
  897. taux = item.text(1)
  898. nom = item.text(2)
  899. if eR == "R":
  900. if taux == "ok":
  901. try:
  902. chemin = "{}\\{}".format(self.co.repReceptionFichiers, nom)
  903. Popen(chemin, shell=True, stdout=PIPE) #from subprocess
  904. except:
  905. print("impossible d'ouvrir le fichier")
  906. def repReception(self):
  907. """permet de choisir son repertoire de reception des fichiers"""
  908. dossier = QFileDialog.getExistingDirectory(self)
  909. if len(dossier) > 0:
  910. if dossier[len(dossier)-1:] != "\\":
  911. dossier += "\\"
  912. self.co.repReceptionFichiers = str(dossier)
  913. self.majStatut()
  914. def afficheReception(self, idFichier):
  915. """ajoute/maj une ligne dans la liste des fichiers en cours de reception"""
  916. idFichier = str(idFichier)
  917. #try:
  918. if self.co.rFichier[idFichier]["ligneAffichage"] == None:
  919. self.co.rFichier[idFichier]["ligneAffichage"] = QTreeWidgetItem(self.ui.listFichiers, ["R", "0", self.co.rFichier[idFichier]["nom"]])
  920. self.ui.listFichiers.scrollToItem(self.co.rFichier[idFichier]["ligneAffichage"])
  921. else:
  922. if self.co.rFichier[idFichier]["termine"]:
  923. taux = "ok"
  924. elif self.co.rFichier[idFichier]["annule"]:
  925. taux = "x"
  926. else:
  927. taux = str(int(100*self.co.rFichier[idFichier]["recu"]/self.co.rFichier[idFichier]["taille"]))
  928. self.co.rFichier[idFichier]["ligneAffichage"].setText(1, taux)
  929. #except:
  930. # logProg.error("erreur d'affichage de la progression: " + idFichier)
  931. def imageRecue(self, idFichier):
  932. """verifie si le fichier recu est une image, et l'ouvre le cas echeant"""
  933. idFichier = str(idFichier)
  934. if self.co.rFichier[idFichier]["termine"]:
  935. try:
  936. typeFichier = self.co.rFichier[idFichier]["nom"].split(".")[len(self.co.rFichier[idFichier]["nom"].split("."))-1]
  937. except:
  938. typeFichier = ""
  939. if typeFichier.lower() in ["png", "jpeg", "jpg"]:
  940. #si c'est une image, on l'ouvre dans une nouvelle fenetre
  941. logProg.debug("ouverture d'une image : " + self.co.rFichier[idFichier]["nom"])
  942. chemin = self.co.repReceptionFichiers + self.co.rFichier[idFichier]["nom"]
  943. #print(chemin)
  944. self.affiche = AfficherImage("{}".format(chemin))
  945. self.affiche.show()
  946. self.affiche.raise_()
  947. QApplication.processEvents()
  948. def afficheEnvoi(self, fichier, taux):
  949. """ajoute/maj une ligne a la liste des fichiers en cours d'envoi"""
  950. fichier = str(fichier)
  951. taux = str(taux)
  952. if len(fichier) > 0:
  953. self.ligneEFichier = QTreeWidgetItem(self.ui.listFichiers, ["E", taux, fichier])
  954. self.ui.listFichiers.scrollToItem(self.ligneEFichier)
  955. elif len(taux) > 0:
  956. if taux != self.ligneEFichier.text(1):
  957. self.ligneEFichier.setText(1, taux)
  958. def majStatut(self):
  959. """met a jour l'onglet de statut de connexion"""
  960. self.ui.txtStatutCoPseudo.setText(QString.fromUtf8("Pseudo : {}".format(self.co.pseudo)))
  961. if self.co.serveur_connecte:
  962. self.ui.txtStatutCoServeur.setText(QString.fromUtf8("Serveur : {} [{}]".format(self.co.pseudo, self.co.ip)))
  963. elif len(self.co.idServeur) > 0 and self.co.idServeur in self.co.autresCo:
  964. self.ui.txtStatutCoServeur.setText(QString.fromUtf8("Serveur : {} [{}]".format(self.co.autresCo[self.co.idServeur], self.co.ip)))
  965. else:
  966. self.ui.txtStatutCoServeur.setText(QString.fromUtf8("Serveur : Pas de serveur"))
  967. if self.estServeurVoc:
  968. self.ui.txtStatutCoServeur.setText(QString.fromUtf8("Serveur vocal : {} [{}]".format(self.co.pseudo, self.co.ip)))
  969. QApplication.processEvents()
  970. def majStatutLstClients(self):
  971. """met a jour la liste des joueurs"""
  972. self.ui.lstStatutJoueurs.clear()
  973. txt = "{} - {}".format(self.co.idClient, self.co.pseudo)
  974. self.ui.lstStatutJoueurs.addItem(QString.fromUtf8(txt))
  975. for idClient in self.co.autresCo:
  976. txt = "{} - {}".format(idClient, self.co.autresCo[idClient])
  977. self.ui.lstStatutJoueurs.addItem(QString.fromUtf8(txt))
  978. self.majStatut()
  979. QApplication.processEvents()
  980. def ouvrirChatPrive(self):
  981. """ouvre un chat prive avec le joueur sur lequel on a clique"""
  982. item = self.ui.lstStatutJoueurs.currentItem()
  983. idInterloc = str(item.text())[0:2]
  984. if idInterloc != self.co.idClient:
  985. self.chatPrive(idInterloc)
  986. def chatPrive(self, idInterloc, txt="", couleur=""):
  987. """ouvre la fenetre de chat prive si elle ne l'est pas deja, puis affiche le message"""
  988. idInterloc = str(idInterloc)
  989. if not idInterloc in self.co.chatPrive:
  990. self.co.chatPrive[idInterloc] = ChatPrive(self.co, idInterloc)
  991. self.co.chatPrive[idInterloc].show()
  992. if len(txt)>0:
  993. if len(couleur)>0:
  994. self.co.chatPrive[idInterloc].afficherMsgPrive(idInterloc, txt, couleur)
  995. else:
  996. self.co.chatPrive[idInterloc].afficherMsgPrive(idInterloc, txt)
  997. def creerServeurVoc(self):
  998. """cree un serveur vocal"""
  999. if not self.estServeurVoc:
  1000. self.sVoc = ServeurVoc(6660)
  1001. #on ouvre une boite de dialogue pour demander l'ip distante
  1002. #de celui qui veut ouvrir le serveur voc
  1003. ipS, ok = QInputDialog.getText(self, 'Creation du serveur vocal',
  1004. 'Saisissez votre adresse IP distante :')
  1005. if ok:
  1006. if ipValide(ipS):
  1007. #self.co.ipServeurVoc = self.ui.ipServeurVoc.text()
  1008. self.co.ipServeurVoc = ipS
  1009. txt = self.sVoc.creer()
  1010. self.ajoutInfo("vs", txt)
  1011. if self.sVoc.serveur_lance:
  1012. self.co.envoi("vs","ac","{}".format(self.co.ipServeurVoc))
  1013. self.estServeurVoc = True
  1014. self.majStatut()
  1015. else:
  1016. self.ajoutInfo("vs", "Erreur - Creation du serveur vocal annulee")
  1017. else:
  1018. self.ajoutInfo("vs", "Veuillez entrer une adresse ip valide")
  1019. else:
  1020. self.fermerServeurVoc()
  1021. def fermerServeurVoc(self):
  1022. """ferme le serveur vocal"""
  1023. txt = self.sVoc.stop()
  1024. self.ajoutInfo("vs", txt)
  1025. if not self.sVoc.serveur_lance:
  1026. self.co.envoi("vf","ac","")
  1027. self.estServeurVoc = False
  1028. self.majStatut()
  1029. def chatVoc(self):
  1030. """connexion au chat vocal"""
  1031. if not self.estClientVoc:
  1032. if len(self.co.ipServeurVoc) == 0:
  1033. if QMessageBox.question(self.parent(), "Chat Vocal", "Aucun serveur vocal ne semble avoir ete cree, /nVoulez-vous en creer un?",
  1034. QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
  1035. self.creerServeurVoc()
  1036. sleep(0.01)
  1037. if len(self.co.ipServeurVoc) > 0:
  1038. self.cVoc = ClientVoc(self.co.idClient, self.co.ipServeurVoc, 6660)
  1039. txt = self.cVoc.creer()
  1040. if self.cVoc.connecte:
  1041. self.ajoutInfo("vi", txt)
  1042. self.co.envoi("vi","ac","")
  1043. self.estClientVoc = True
  1044. self.majStatut()
  1045. else:
  1046. self.quitterChatVoc()
  1047. def quitterChatVoc(self):
  1048. """deconnexion du chat vocal"""
  1049. if self.estClientVoc:
  1050. txt = self.cVoc.stop()
  1051. self.ajoutInfo("vq", txt)
  1052. self.co.envoi("vq","ac","")
  1053. self.estClientVoc = False
  1054. self.majStatut()
  1055. if self.sVoc.serveur_lance:
  1056. self.fermerServeurVoc()
  1057. def creerPlateau(self, x, y):
  1058. """Creation du Plateau de combat"""
  1059. if x > 0 and y > 0 and x == int(x) and y == int(y):
  1060. self.plateau = QGraphicsScene(self)
  1061. self.cCase = 30
  1062. self.plateau.setSceneRect(0, 0, self.cCase*x, self.cCase*y)
  1063. pinceau = QPen()
  1064. pinceau.setColor(QColor(85, 85, 85, 85))
  1065. pinceau.setWidth(1)
  1066. i = 0
  1067. j = 0
  1068. for i in range(x):
  1069. for j in range(y):
  1070. if 1 == (i % 2):
  1071. j += 0.5
  1072. polygon = QPolygonF()
  1073. polygon << QPointF(i*self.cCase,(j+0.5)*self.cCase) << QPointF((i+0.34)*self.cCase,j*self.cCase)<< QPointF((i+1)*self.cCase,(j)*self.cCase) << QPointF((i+1.34)*self.cCase,(j+0.5)*self.cCase) << QPointF((i+1)*self.cCase,(j+1)*self.cCase) << QPointF((i+0.34)*self.cCase,(j+1)*self.cCase)
  1074. self.plateau.addPolygon(polygon)
  1075. self.ui.vuePlateau.setScene(self.plateau)
  1076. def nouveauPion(self):
  1077. """essai de creation graphique: ajout d'un pion sur le plateau de jeu"""
  1078. #creation d'un pion
  1079. pinceau = QPen()
  1080. pinceau.setColor(QColor(0, 0, 0, 120))
  1081. pinceau.setWidth(2)
  1082. self.pion = QGraphicsEllipseItem(0, 0, self.cCase, self.cCase)
  1083. self.pion.setPen(pinceau)
  1084. self.pion.setFlag(QGraphicsItem.ItemIsMovable)
  1085. self.pion.setFlag(QGraphicsItem.ItemIsFocusable)
  1086. self.pion.setBrush(QColor(255, 0, 0, 150))
  1087. #ombre
  1088. self.shadow = QGraphicsDropShadowEffect()
  1089. self.shadow.setColor(QColor(50, 50, 50, 200))
  1090. self.shadow.setXOffset(1)
  1091. self.shadow.setYOffset(1)
  1092. self.shadow.setBlurRadius(3)
  1093. self.pion.setGraphicsEffect(self.shadow)
  1094. self.shadow.setEnabled(True)
  1095. self.plateau.addItem(self.pion)
  1096. def closeEvent(self, event):
  1097. """sur fermeture de la fenetre"""
  1098. if self.estClientVoc:
  1099. self.cVoc.stop()
  1100. if self.estServeurVoc:
  1101. self.sVoc.stop()
  1102. self.co.fermer()
  1103. sleep(0.01)
  1104. self.connecte = False
  1105. self.close()
  1106. if __name__ == "__main__":
  1107. demarrageOk = True
  1108. #repertoire de travail et creation des dossiers necessaires:
  1109. try:
  1110. repCourant = os.getcwd()
  1111. except:
  1112. repCourant = ""
  1113. if not len(repCourant) > 0:
  1114. logProg.error("Impossible de determiner le repertoire courant")
  1115. demarrageOk = False
  1116. else:
  1117. try:
  1118. #repertoire media (musiques+images)
  1119. if not os.path.exists(repCourant+"\\media"):
  1120. os.mkdir(repCourant+"\\media")
  1121. #repertoire utilisateur (sauvegardes)
  1122. if not os.path.exists(repCourant+"\\svg"):
  1123. os.mkdir(repCourant+"\\svg")
  1124. #repertoire reception des fichiers persos
  1125. if not os.path.exists(repCourant+"\\FichiersRecus"):
  1126. os.mkdir(repCourant+"\\FichiersRecus")
  1127. except:
  1128. logProg.error("Erreur de creation des repertoires de l'application")
  1129. demarrageOk = False
  1130. #verif si l'appli est deja lancee:
  1131. nomAppli = "DMonde.exe"
  1132. compte = 0
  1133. for proc in process_iter(): #from psutil
  1134. try:
  1135. nomProc = proc.name()
  1136. if nomProc == nomAppli:
  1137. compte += 1
  1138. if compte > 1:
  1139. demarrageOk = False
  1140. logProg.error("Une instance de l'application est deja en cours d'execution")
  1141. break
  1142. except:
  1143. pass
  1144. if demarrageOk:
  1145. #lancement de l'appli
  1146. app = QApplication(argv) #'argv' vient de 'sys'
  1147. connexion = EcranConnexion()
  1148. connexion.show()
  1149. r = app.exec_()
  1150. if r == 0 and connexion.client_connecte:
  1151. #si pas d'erreur et client connecte, on ouvre l'interface principale
  1152. ecranPrincipal = EcranPrincipal(connexion)
  1153. ecranPrincipal.show()
  1154. r = app.exec_()
  1155. exit(r) #'exit' vient de 'sys'