from __future__ import unicode_literals
# -*- coding: utf-8 -*-
import os
from sys import exit, argv
from time import sleep
from threading import Thread
from socket import socket, AF_INET, SOCK_STREAM
from subprocess import Popen, PIPE
import logging
import cPickle as pickle
#modules importes
from psutil import process_iter
#import de QT et des interfaces
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from ecran_connexion import Ui_ecranConnexion
from ecran_chat import Ui_chat
#modules persos
from serveur import Serveur, ServeurVoc
from lancer import jet
from clientvoc import ClientVoc
#fonctions potetiellement utiles:
#print(psutil.connections())
#print(psutil.net_io_counters(pernic=True))
#gestion des erreurs et log
logging.basicConfig(level=logging.DEBUG)
logProg = logging.getLogger(__name__)
handlerProg = logging.FileHandler('prog.log')
handlerProg.setFormatter(logging.Formatter('[%(asctime)s] %(levelname)s- %(message)s')) #'%(name)s' nom du thread
logProg.addHandler(handlerProg)
logProg.debug(" ---------------------- \n")
class EcranConnexion(QGroupBox):
"""fenetre de connexion a l'application et module d'envoi/reception"""
def __init__(self, parent=None):
"""initialisation de la connexion et creation de la fenetre"""
super (EcranConnexion, self).__init__(parent)
self.client_connecte = False
self.serveur_connecte = False
self.idClient = "00"
self.ip = ""
self.pseudo = ""
self.autresCo = {}
#echanges fichiers
self.eFichier = {"id": "00", "chemin": "", "fichier": None, "dest": "", "envoi" : False, "annule" : False}
#fichier en cours d'envoi : id fichier, chemin du fichier, fichier (objet), dest, envoi autorise, envoi annule
self.destFichier = {} #liste des clients dont on attend confirmation pour l'envoi de fichier
self.receptionFichier = {} #id du fichier: nom du fichier
self.repReceptionFichiers = os.getcwd()+"\\FichiersRecus\\"
#chat voc
self.ipServeurVoc = ""
self.port = 6660
#recup des param et affichage:
try:
logProg.info(self.recupParamCo())
except:
logProg.info("pas de parametres a recuperer")
self.createWidgets()
def createWidgets(self):
"""creation de l'interface de connexion"""
self.ui = Ui_ecranConnexion()
self.ui.setupUi(self)
if len(self.ip) > 0:
self.ui.in_ip.setText(QString.fromUtf8(self.ip))
if self.port > 0:
self.ui.in_port.setText(QString.fromUtf8(str(self.port)))
if len(self.pseudo) > 0:
self.ui.in_pseudo.setText(QString.fromUtf8(self.pseudo))
self.connect(self.ui.fermer, SIGNAL("clicked()"), self.fermer)
self.connect(self.ui.creerServeur, SIGNAL("clicked()"), self.creerServeur)
self.connect(self.ui.seConnecter, SIGNAL("clicked()"), self.seConnecter)
def msg(self, txt):
"""affichage d'un message informatif sous forme de label"""
self.ui.txt_msg.setText(QString.fromUtf8(txt))
QApplication.processEvents()
def creerServeur(self):
"""instancie un serveur local"""
self.pseudo = self.ui.in_pseudo.text()
self.port = self.ui.in_port.text()
if len(self.pseudo) == 0 or len(self.port) == 0:
self.msg("Parametres incorrects")
else:
self.ui.in_ip.setText(QString.fromUtf8("localhost"))
self.s = Serveur(int(self.ui.in_port.text()))
self.serveur_connecte, txt = self.s.creer()
self.msg(txt)
if self.serveur_connecte:
self.seConnecter()
def seConnecter(self):
"""se connecte au serveur correspondant a l'ip et au port saisis"""
self.pseudo = self.ui.in_pseudo.text()
self.port = self.ui.in_port.text()
self.ip = self.ui.in_ip.text()
essais = 0
if len(self.pseudo) == 0 or len(self.ip) == 0 or len(self.port) == 0:
self.msg("Parametres incorrects")
else:
self.msg("En attente du serveur...")
while self.client_connecte == False:
#en attente de la connexion
try:
self.cnn = socket(AF_INET, SOCK_STREAM)
self.cnn.connect((self.ip, int(self.port)))
self.client_connecte = True
txt = "Connexion etablie avec le serveur sur le port {}\n".format(self.port)
logProg.info(txt)
except KeyboardInterrupt:
break
except:
essais += 1
if essais > 3:
txt = "Delai depasse"
self.msg(txt)
logProg.warning(txt)
break
txt = "Connexion : essai {}".format(essais)
self.msg(txt)
logProg.info(txt)
if self.client_connecte:
#demarre le fil de reception
Thread(None, self.filReception, None, (), {}).start()
#previent le serveur et envoie le pseudo
self.envoi("ci", "sa", self.pseudo)
self.msg(txt)
sleep(0.01)
self.close()
self.emit(SIGNAL("majAffichage()"))
else:
txt = "Erreur: impossible de se connecter"
self.msg(txt)
logProg.error(txt)
def filReception(self):
"""thread de reception des donnees du serveur, reste actif tant que l'application est active"""
while self.client_connecte:
recu = self.cnn.recv(1024)
if len(recu) > 0:
self.traitement(recu)
def traitement(self, msg):
"""determine le traitement a apporter a un message recu, selon sa nature"""
if len(msg) >= 6:
emet = msg[2:4]
dest = msg[4:6]
categorie = msg[:1]
nature = msg[:2]
try:
contenu = msg[6:]
except:
contenu = ""
if nature != "fd" and nature != "ff":
#on decode le message, sauf s'il contient des donnees binaires issues d'un fichier
contenu = contenu.decode('utf-8')
if nature == "ci":
#recoit l'identifiant du client fourni par le serveur
self.idClient = dest
logProg.info("mon id est: {}\n".format(self.idClient))
elif nature == "cc":
if contenu[0:2] != self.idClient:
self.autresCo[str(contenu[0:2])] = str(contenu[2:])
#on lui envoie id+pseudo
sleep(0.02)
self.envoi("cp", contenu[0:2], "{}{}".format(self.idClient, self.pseudo))
logProg.info("{} s'est connecte ({})".format(contenu[2:], contenu[0:2]))
self.recuInfo("cc", "{} s'est connecte ({})".format(contenu[2:], contenu[0:2]))
elif nature == "cp":
self.autresCo[str(contenu[0:2])] = str(contenu[2:])
sleep(0.01)
logProg.info("{} est deja present ({})".format(contenu[2:], contenu[0:2]))
self.recuInfo("cc", "{} est deja la ({})".format(contenu[2:], contenu[0:2]))
elif nature == "cd":
if contenu != self.idClient and len(contenu) == 2:
logProg.info("{} s'est deconnecte ({})".format(self.autresCo[contenu], contenu))
self.recuInfo("cd", "{} s'est deconnecte ({})".format(self.autresCo[contenu], contenu))
del self.autresCo[contenu]
elif categorie == "m":
#afficher dans le chat
logProg.info("chat: {} -> {}\n".format(emet, contenu))
self.recuMsg(emet, contenu)
elif categorie == "i":
#afficher dans la fenetre évènement
self.recuInfo(nature, contenu)
if nature == "id":
#jet de dés: afficher en rouge
logProg.info("jet de dé: {} -> {}\n".format(emet, contenu))
if nature == "ic":
#nouveau client connecte: afficher en bleu
logProg.info("info connexion: {} -> {}\n".format(emet, contenu))
elif categorie == "f":
#envoi ou reception de fichier
if nature == "f0":
#le serveur nous renvoie l'identifiant du fichier que l'on veut envoyer
if self.eFichier["id"] == "00":
if len(contenu) == 2:
Thread(None, self.envoiFichier_1, None, (contenu,), {}).start()
else:
logProg.error("erreur: id du fichier\n")
else:
logProg.warning("Un fichier est en cours d'envoi\n")
elif nature == "fp":
#un clients est pret a recevoir le fichier
self.pretEnvoiFichier(emet)
elif nature == "fi":
#quelqu'un nous envoie un fichier
if len(contenu)>2:
#les 2 premiers car sont l'identifiant, puis le nom du fichier (* la taille)
essai = self.nouveauFichier(contenu[0:2], contenu[2:])
logProg.info("nouveau fichier: {}".format(essai))
if len(essai) > 0:
self.recuInfo(nature, "Fichier {} en cours de reception".format(contenu[2:]))
#on envoie confirmation de la reception:
sleep(0.001)
self.envoi("fp", emet, contenu[0:2])
self.emit(SIGNAL("initRecFichier(QString, QString)"), QString.fromUtf8(essai), QString.fromUtf8(""))
else:
self.recuInfo(nature, "Impossible de créer le fichier à recevoir")
logProg.error("Impossible de créer le fichier à recevoir")
else:
logProg.error("erreur reception fichier: id ou nom du fichier incorrect\n")
elif nature == "fd":
#on recoit les donnees a ecrire dans le fichier
#print("reception: {}".format(contenu))
if len(contenu) > 2:
self.receptionFichier[contenu[0:2]].write(contenu[2:])
#print("{} -> paquet recu".format(contenu[0:2]))
self.emit(SIGNAL("initRecFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8("."))
#le client renvoie la longueur de la donnee recue a l'emetteur pour confirmation
sleep(0.001)
self.envoi("fp", emet, contenu[0:2])
elif len(contenu) == 2:
#l'emetteur redemande confirmation, on lui envoie
self.envoi("fp", emet, contenu[0:2])
else:
logProg.error("erreur de reception des donnees du fichier\n")
#pass
elif nature == "ff":
#fin de reception du fichier
self.receptionFichier[contenu[0:2]].write(contenu[2:])
sleep(0.001)
self.envoi("fp", emet, contenu[0:2])
self.recuInfo("ff", "Fichier {} recu\n".format(os.path.basename(self.receptionFichier[contenu[0:2]].name)))
self.emit(SIGNAL("initRecFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8("ok"))
self.emit(SIGNAL("inserImg(QString, QString)"), QString.fromUtf8(emet), QString.fromUtf8(self.receptionFichier[contenu[0:2]].name))
sleep(0.01)
self.receptionFichier[contenu[0:2]].close()
del self.receptionFichier[contenu[0:2]]
logProg.info("Fichier recu")
elif nature == "fa":
#envoi annule
logProg.info("Annulation de la reception du fichier")
if self.receptionFichier[contenu[0:2]]:
self.recuInfo("ff", "Reception {} annule \n".format(os.path.basename(self.receptionFichier[contenu[0:2]].name)))
self.emit(SIGNAL("initRecFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8("x"))
self.receptionFichier[contenu[0:2]].close()
#on supprime le fichier incomplet:
os.remove(self.receptionFichier[contenu[0:2]].name)
del self.receptionFichier[contenu[0:2]]
elif categorie == "s":
#infos sur le fonctionnement du serveur principal
if nature == "sd":
#le serveur a ete ferme
self.serveurDeco()
elif categorie == "v":
#infos liees au chat vocal
if nature == "vs":
#un serveur vocal a ete cree
self.recuInfo("vs", "{} a cree un serveur vocal ({})".format(self.autresCo[emet], contenu))
self.ipServeurVoc = contenu
if nature == "vi":
#un client rejoint le chat vocal
self.recuInfo("vi", "{} a rejoint le chat vocal".format(self.autresCo[emet]))
if nature == "vq":
#un client quitte le chat vocal
self.recuInfo("vq", "{} a quitte le chat vocal".format(self.autresCo[emet]))
if nature == "vf":
#fermeture du serveur vocal
self.recuInfo("vf", "{} a ferme le serveur vocal".format(self.autresCo[emet]))
elif categorie == "p":
if nature == "pi":
#nouveau plateau créé
logProg.info("nouveau plateau: {}\n".format(emet, contenu))
else:
logProg.warning("Erreur: message illisible -> {}\n".format(msg))
def recuInfo(self, nature, contenu):
"""signale une nouvelle information"""
self.emit(SIGNAL("nouvelleInfo(QString, QString)"), QString.fromUtf8(nature), QString.fromUtf8(contenu))
def recuMsg(self, emetteur, contenu):
"""signale un nouveau message texte pour le chat ecrit"""
self.emit(SIGNAL("msgChat(QString, QString)"), QString.fromUtf8(emetteur), QString.fromUtf8(contenu))
def envoi(self, nature, dest, msg, idFichier = ""):
"""envoie un message au serveur TCP
- longueur du message (3 car)
- nature du message (2 car)
- exp: id de l'expediteur (2 car)
- dest: id du destinataire (2 car)
- msg: contenu du message (999 car max)
- un identifiant pour le fichier le cas echeant"""
exp = self.idClient
if self.client_connecte:
try:
if len(msg) <= 999:
if len(idFichier) == 0:
msg = unicode(msg)
lg = "%003.f"%len(msg.encode('utf-8')) #la longueur apres encodage peut changer
txt = "{}{}{}{}{}".format(lg, nature, exp, dest, msg)
txt = txt.encode('utf-8')
else:
lg = "%003.f"%(len(msg)+2)
txt = "{}{}{}{}{}".format(lg, nature, exp, dest, idFichier)
txt = txt.encode('utf-8') + msg
retour = len(txt)
self.cnn.sendall(txt)
else:
self.recuInfo(" ","999 caracteres au max.")
retour = 0
except:
retour = 0
logProg.warning("Envoi impossible")
else:
retour = ""
logProg.warning("Le client n'est pas connecte au serveur")
self.recuInfo(" ","Vous n'etes pas connecte a un serveur")
return retour
def envoiFichier(self, chemin, dest = "ac"):
"""intialise l'envoi d'un fichier"""
if self.eFichier["id"] == "00":
# on verifie si le fichier existe:
fichier = None
try:
fichier = open(chemin, "rb")
except:
logProg.error("Le fichier '{}' est introuvable.".format(fichier))
if not os.path.getsize(chemin) > 0:
logProg.error("Envoi impossible - fichier vide")
fichier.close()
fichier == None
if fichier:
#on demande un identifiant au serveur
self.eFichier["fichier"] = fichier
self.eFichier["chemin"] = chemin
self.eFichier["dest"] = dest
self.eFichier["annule"] = False
self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(os.path.basename(chemin)), QString.fromUtf8("0"))
logProg.debug(self.eFichier)
if dest == "ac":
for idC in self.autresCo:
self.destFichier[idC] = False
else:
self.destFichier[dest] = False
self.envoi("f0","sa","")
else:
self.annuleEnvoiFichier()
def envoiFichier_1(self, idFichier):
"""le fichier est pret a etre envoye, on attend confirmation des destinataires"""
if len(idFichier) == 2:
dest = self.eFichier["dest"]
self.eFichier["id"] = idFichier
nomFichier = os.path.basename(self.eFichier["chemin"])
taille = os.path.getsize(self.eFichier["chemin"])
logProg.debug("{} a pour id {}\n".format(nomFichier, idFichier))
#on previent les destinataires, et on leur transmet l'identifiant et le nom*taille du fichier
logProg.info("En attente des destinataires...")
self.recuInfo("fi", "{} - En attente des destinataires...".format(nomFichier))
self.envoi("fi", dest, "{}{}".format(idFichier, nomFichier))
while not self.eFichier["envoi"] and not self.eFichier["annule"]:
sleep(0.001)
if not self.eFichier["annule"]:
Thread(None, self.envoiFichier_2, None, (), {}).start()
else:
logProg.error("Erreur envoi fichier: identifiant incorrect -> {}".format(idFichier))
self.annuleEnvoiFichier()
def pretEnvoiFichier(self, idClient):
"""signale un destinataire comme etant pret a recevoir le fichier ou le paquet de donnees"""
pretEnvoi = False
if self.eFichier["dest"] == "ac":
self.destFichier[idClient] = True
pretEnvoi = True
for idC in self.destFichier:
if self.destFichier[idC] == False:
pretEnvoi = False
#si tous les clients sont prets, on enclenche l'envoi du fichier sous forme de thread
else:
if idClient == self.eFichier["dest"]:
pretEnvoi = True
#print("{} -> {}".format(idClient, pretEnvoi))
self.eFichier["envoi"] = pretEnvoi
def envoiFichier_2(self):
"""thread d'envoi de fichier"""
if self.eFichier["envoi"] and not self.eFichier["annule"]:
idFichier = self.eFichier["id"]
taille = os.path.getsize(self.eFichier["chemin"])
nomFichier = os.path.basename(self.eFichier["chemin"])
dest = self.eFichier["dest"]
envoye = 0
essais = 0
#on envoie les donnees
data = self.eFichier["fichier"].read(512)
while len(data) == 512:
if self.eFichier["annule"]:
#en cas d'annulation
break
self.envoi("fd", dest, data, idFichier)
envoye += len(data)
logProg.info("{} / {}".format(int(envoye/1000), int(taille/1000)))
#on attend confirmation de reception:
self.eFichier["envoi"] = False
if dest == "ac":
for idC in self.autresCo:
self.destFichier[idC] = False
else:
self.destFichier[dest] = False
while not self.eFichier["envoi"]:
if self.eFichier["annule"]:
break
sleep(0.001)
essais += 1
if essais >= 1000:
#on renvoie un message pour demander confirmation
self.envoi("fd", dest, b'', idFichier)
essais = 0
taux = str((100*envoye)/taille)
self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8(taux))
data = self.eFichier["fichier"].read(512)
#pour dernier paquet on ajoute au drapeau: "%003.f"%len(paquet)
#on signale que c'est le dernier paquet et on ajoute 3 caracteres pour en specifier la taille:
if not self.eFichier["annule"]:
self.envoi("ff", dest, data, idFichier)
envoye += len(data)
logProg.info("{} / {}".format(int(envoye/1000), int(taille/1000)))
self.eFichier["envoi"] = False
while not self.eFichier["envoi"]:
if self.eFichier["annule"]:
break
sleep(0.001)
essais += 1
if essais >= 1000:
#on renvoie un message pour demander confirmation
logProg.warning("envoi fichier - on redemande confirmation")
self.envoi("fd", dest, b'', idFichier)
essais = 0
taux = str((100*envoye)/taille)
self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8(taux))
self.envoi("f1", "sa", "{}".format(idFichier))
self.recuInfo("ff", "- {} a bien ete envoye -".format(nomFichier))
self.emit(SIGNAL("inserImg(QString, QString)"), QString.fromUtf8(self.idClient), QString.fromUtf8(self.eFichier["chemin"]))
logProg.info("\n- Fichier envoye -")
self.eFichier = {"id": "00", "chemin": "", "fichier": None, "dest": "", "envoi" : False, "annule": False}
else:
self.eFichier = {"id": "00", "chemin": "", "fichier": None, "dest": "", "envoi" : False, "annule": True}
else:
logProg.error("Erreur envoi fichier: signal serveur non-recu -> {}".format(self.eFichier["id"]))
self.eFichier = {"id": "00", "chemin": "", "fichier": None, "dest": "", "envoi" : False, "annule": False}
def annuleEnvoiFichier(self):
"""annule l'envoi d'un fichier"""
logProg.warning("Annulation de l'envoi")
self.envoi("fa", self.eFichier["dest"], "{}".format(self.eFichier["id"]))
self.eFichier["annule"] = True
essais = 0
while not self.eFichier["id"] == "00":
sleep(0.01)
essais += 1
if essais > 100:
logProg.error("Erreur: impossible d'annuler l'envoi")
logProg.info("-> Envoi annulé")
self.recuInfo("fa", "- Envoi du fichier annule -")
self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8("x"))
def nouveauFichier(self, idFichier, nomFichier):
"""cree le fichier a recevoir - le renomme si un fichier portant ce nom existe deja - retourne le chemin complet"""
k = 1
tmp = nomFichier
retour = ""
try:
while os.path.isfile(self.repReceptionFichiers+tmp):
k += 1
tmp = nomFichier.split(".")[0]+str(k)+"."+nomFichier.split(".")[1]
if k == 100:
tmp = ""
break
if len(tmp) > 0:
self.receptionFichier[idFichier] = open((self.repReceptionFichiers + tmp), "wb")
retour = tmp
except:
logProg.error("Impossible de creer le fichier")
return retour
def serveurDeco(self):
"""le serveur a ferme - on affiche a nouveau l'ecran de connexion"""
#on annule les envois de fichier en cours
if self.eFichier["fichier"] != None:
self.eFichier["annule"] = True
self.emit(SIGNAL("initEnvFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8("x"))
#on annule les receptions de fichiers en cours
for idFichier in self.receptionFichier:
logProg.warning("{} - reception annulee".format(self.receptionFichier[idFichier].name))
self.receptionFichier[idFichier].close()
os.remove(self.receptionFichier[idFichier].name)
self.emit(SIGNAL("initRecFichier(QString, QString)"), QString.fromUtf8(""), QString.fromUtf8("x"))
self.receptionFichier = {}
self.recuInfo("sd", "(!) Le serveur a mis la clef sous la porte (!)")
logProg.warning("Serveur deconnecte")
self.cnn.close()
self.client_connecte = False
self.serveur_lance = False
sleep(0.01)
self.show()
self.msg("")
def recupParamCo(self):
"""recupere les derniers parametres de connexion enregistres s'il existent"""
try:
with open("parametresCo", 'rb') as input:
dico = pickle.load(input)
self.pseudo = dico["pseudo"]
self.port = dico["port"]
self.ip = dico["ip"]
self.repReceptionFichiers = dico["repReceptionFichiers"]
retour = dico
input.close()
except IOError:
retour = ("Erreur: parametresCo introuvable")
return retour
def sauverParamCo(self):
"""sauvegarde les parametres de connexion pour une prochaine utilisation"""
with open("parametresCo", 'wb') as output:
dico = {"pseudo": str(self.pseudo), "port" : int(self.port), "ip": str(self.ip), "repReceptionFichiers" : str(self.repReceptionFichiers)}
pickle.dump(dico, output, -1)
output.close()
chaine = "parametres sauvegarde."
return chaine
def fermer(self):
"""fermeture de la connexion, et du serveur le cas echeant"""
if self.client_connecte:
try:
self.envoi("cd", "sa", "")
except:
logProg.warning("impossible de prévenir le serveur de la deco")
self.client_connecte = False
self.cnn.close()
if self.eFichier["fichier"] != None:
self.eFichier["annule"] = True
sleep(0.001)
logging.info(self.sauverParamCo())
if self.serveur_connecte:
self.s.stop()
self.serveur_connecte = False
sleep(0.001)
self.close()
def closeEvent(self, event):
"""sur fermeture de la fenetre"""
if not self.client_connecte:
self.fermer()
class EcranChat(QGroupBox):
"""interface comprenant: chat ecrit, fenetre d'infos, lancer de des, echange de fichiers, lancement du chat vocal"""
def __init__(self, connexion, parent=None):
"""initialisation de la fenetre"""
super (EcranChat, self).__init__(parent)
self.co = connexion
self.connecte = True
self.estServeurVoc = False
self.estClientVoc = False
self.createWidgets()
def createWidgets(self):
"""construction de l'interface"""
#construction de l'interface
self.ui = Ui_chat()
self.ui.setupUi(self)
#connexion des commandes
self.connect(self.ui.inChat, SIGNAL("returnPressed()"), self.envoiMsg)
self.connect(self.ui.d20, SIGNAL("clicked()"), self.d20)
self.connect(self.ui.d100, SIGNAL("clicked()"), self.d100)
self.connect(self.ui.inJetDes, SIGNAL("returnPressed()"), self.autreJet)
self.connect(self.ui.envoiFichier, SIGNAL("clicked()"), self.envoyerfichier)
self.connect(self.ui.repReceptionFichiers, SIGNAL("clicked()"), self.repReception)
self.connect(self.ui.listFichiers, SIGNAL("itemDoubleClicked(QTreeWidgetItem*, int)"), self.ouvrirFichier)
self.connect(self.ui.chatVoc, SIGNAL("clicked()"), self.chatVoc)
self.connect(self.ui.creerServeurVoc, SIGNAL("clicked()"), self.creerServeurVoc)
#reception des signaux self.emit(SIGNAL("majAffichage()"))
self.connect(self, SIGNAL("msgChat(QString, QString)"), self.ajoutChat)
self.connect(self.co, SIGNAL("msgChat(QString, QString)"), self.ajoutChat)
self.connect(self, SIGNAL("nouvelleInfo(QString, QString)"), self.ajoutInfo)
self.connect(self.co, SIGNAL("nouvelleInfo(QString, QString)"), self.ajoutInfo)
self.connect(self, SIGNAL("initRecFichier(QString, QString)"), self.afficheReception)
self.connect(self.co, SIGNAL("initRecFichier(QString, QString)"), self.afficheReception)
self.connect(self, SIGNAL("inserImg(QString, QString)"), self.inserImgChat)
self.connect(self.co, SIGNAL("inserImg(QString, QString)"), self.inserImgChat)
self.connect(self, SIGNAL("initEnvFichier(QString, QString)"), self.afficheEnvoi)
self.connect(self.co, SIGNAL("initEnvFichier(QString, QString)"), self.afficheEnvoi)
self.connect(self, SIGNAL("majAffichage()"), self.majStatut)
self.connect(self.co, SIGNAL("majAffichage()"), self.majStatut)
self.majStatut()
def msg(self, txt):
"""affichage d'un message informatif sous forme de label"""
self.ui.txt_msg.setText(QString.fromUtf8(txt))
QApplication.processEvents()
def ajoutChat(self, emetteur, msg):
"""ajoute une nouvelle ligne au chat ecrit"""
emetteur = str(emetteur)
if emetteur == self.co.idClient:
txt = "{} : {}".format(self.co.pseudo, msg)
else:
pseudo = self.co.autresCo["{}".format(emetteur)]
txt = "{} : {}".format(pseudo, msg)
txt = QString.fromUtf8(txt)
item = QListWidgetItem(self.ui.listAffichage)
self.ui.listAffichage.addItem(item)
label = QLabel()
label.setWordWrap(True)
label.setText(txt)
item.setSizeHint(QSize(120, label.heightForWidth (self.ui.listAffichage.width()) + 5))
self.ui.listAffichage.setItemWidget(item, label)
QApplication.processEvents()
def ajoutInfo(self, nature, msg):
"""ajoute une nouvelle ligne a la liste des evenements"""
#couleur selon nature de l'info:
if nature[:1] == "c":
txt = "{}".format(msg)
elif nature == "id":
txt = "{}".format(msg)
elif nature[:1] == "f":
txt = "{}".format(msg)
elif nature[:1] == "v":
txt = "{}".format(msg)
else:
txt = msg
txt = QString.fromUtf8(txt)
item = QListWidgetItem(self.ui.listEvenement)
self.ui.listEvenement.addItem(item)
label = QLabel()
label.setWordWrap(True)
label.setText(txt)
item.setSizeHint(QSize(120, label.heightForWidth (self.ui.listEvenement.width()) + 5))
self.ui.listEvenement.setItemWidget(item, label)
QApplication.processEvents()
def inserImgChat(self, emet, fichier):
"""insere une image dans le QListWidget chat"""
emet = str(emet)
fichier = str(fichier)
try:
typeFichier = fichier.split(".")[len(fichier.split("."))-1]
except:
typeFichier = ""
if typeFichier.lower() in ["png", "jpeg", "jpg"]:
#si c'est une image, on essaie de l'inserer dans le chat
logProg.debug("ajout d'une image au chat : " + fichier)
self.ajoutChat(str(emet), "
".format(fichier))
def envoiMsg(self):
"""envoie un message pour le chat ecrit"""
msg = self.ui.inChat.text()
self.co.envoi("m ", "tc", msg)
self.ui.inChat.clear()
QApplication.processEvents()
def lancerD(self, expr):
"""fonction de lancer de des"""
res, detail = jet(expr)
if res > 0:
txt = "{}: {} ({}) [{}]".format(self.co.pseudo, res, detail, expr)
self.co.envoi("id", "tc", txt)
else:
self.ajoutInfo("id", "mmmhh, pas bon le jet")
return res
def d20(self):
"""lance un D20"""
self.lancerD("1d20")
def d100(self):
"""lance un D100"""
self.lancerD("1d100")
def autreJet(self):
"""lance un jet personnalise"""
expr = str(self.ui.inJetDes.text())
retour = self.lancerD(expr)
self.ui.inJetDes.clear()
def envoyerfichier(self):
"""selectionne et envoie un fichier ou annule l'envoi en cours s'il existe"""
if self.co.eFichier["id"] == "00":
fichier = QFileDialog.getOpenFileName(
self,
"Selectionnez un fichier a envoyer",
"c:\\",
"")
if len(str(fichier)) > 0:
self.co.envoiFichier(str(fichier))
else:
self.co.annuleEnvoiFichier()
def ouvrirFichier(self):
"""ouvre un fichier depuis la liste des fichiers recus/envoyes"""
item = self.ui.listFichiers.currentItem()
eR = item.text(0)
taux = item.text(1)
nom = item.text(2)
if eR == "R":
if taux == "ok":
#try:
chemin = "{}\\{}".format(self.co.repReceptionFichiers, nom)
Popen(chemin, shell=True, stdout=PIPE) #from subprocess
#except:
# print("impossible d'ouvrir le fichier")
def repReception(self):
"""permet de choisir son repertoire de reception des fichiers"""
dossier = QFileDialog.getExistingDirectory(self)
if dossier[len(dossier)-1:] != "\\":
dossier += "\\"
self.co.repReceptionFichiers = str(dossier)
self.majStatut()
def afficheReception(self, fichier, taux):
"""ajoute une ligne a la liste des fichiers en cours de reception"""
fichier = str(fichier)
taux = str(taux)
if len(fichier) > 0:
self.ligneRFichier = QTreeWidgetItem(self.ui.listFichiers, ["R", taux, fichier])
elif len(taux) > 0:
if taux != self.ligneRFichier.text(1):
self.ligneRFichier.setText(1, taux)
def afficheEnvoi(self, fichier, taux):
"""ajoute une ligne a la liste des fichiers en cours d'envoi"""
fichier = str(fichier)
taux = str(taux)
if len(fichier) > 0:
self.ligneEFichier = QTreeWidgetItem(self.ui.listFichiers, ["E", taux, fichier])
elif len(taux) > 0:
if taux != self.ligneEFichier.text(1):
self.ligneEFichier.setText(1, taux)
def majStatut(self):
"""met a jour la ligne de statut au pied de l'interface"""
if self.co.serveur_connecte:
txt = "Serveur : Oui"
else:
txt = "Serveur : Non"
txt += " \ Pseudo : {}".format(self.co.pseudo)
if self.estServeurVoc:
txt += " \ Serveur vocal"
if self.estClientVoc:
txt += " \ connecte au chat vocal"
self.msg(txt)
self.ui.txt_repReception.setText(QString.fromUtf8("Fichiers recus : '{}'".format(self.co.repReceptionFichiers)))
QApplication.processEvents()
def creerServeurVoc(self):
"""cree un serveur vocal"""
if not self.estServeurVoc:
self.sVoc = ServeurVoc(6660)
self.co.ipServeurVoc = "localhost"
txt = self.sVoc.creer()
self.ajoutInfo("vs", txt)
if self.sVoc.serveur_lance:
self.co.envoi("vs","ac","{}".format("localhost"))
self.estServeurVoc = True
self.majStatut()
else:
self.fermerServeurVoc()
def fermerServeurVoc(self):
"""ferme le serveur vocal"""
txt = self.sVoc.stop()
self.ajoutInfo("vs", txt)
if not self.sVoc.serveur_lance:
self.co.envoi("vf","ac","")
self.estServeurVoc = False
self.majStatut()
def chatVoc(self):
"""connexion au chat vocal"""
if not self.estClientVoc:
if len(self.co.ipServeurVoc) > 0:
self.cVoc = ClientVoc(self.co.idClient, self.co.ipServeurVoc, 6660)
txt = self.cVoc.creer()
if self.cVoc.connecte:
self.ajoutInfo("vi", txt)
self.co.envoi("vi","ac","")
self.estClientVoc = True
self.majStatut()
else:
self.quitterChatVoc()
def quitterChatVoc(self):
"""deconnexion du chat vocal"""
if self.estClientVoc:
txt = self.cVoc.stop()
self.ajoutInfo("vq", txt)
self.co.envoi("vq","ac","")
self.estClientVoc = False
self.majStatut()
def closeEvent(self, event):
"""sur fermeture de la fenetre"""
if self.estClientVoc:
self.cVoc.stop()
if self.estServeurVoc:
self.sVoc.stop()
self.co.fermer()
sleep(0.01)
self.connecte = False
self.close()
if __name__ == "__main__":
demarrageOk = True
#repertoire de travail et creation des dossiers necessaires:
try:
repCourant = os.getcwd()
except:
repCourant = ""
if not len(repCourant) > 0:
logProg.error("Impossible de determiner le repertoire courant")
demarrageOk = False
else:
try:
#repertoire media (musiques+images)
if not os.path.exists(repCourant+"\\media"):
os.mkdir(repCourant+"\\media")
#repertoire utilisateur (sauvegardes)
if not os.path.exists(repCourant+"\\svg"):
os.mkdir(repCourant+"\\svg")
#repertoire reception des fichiers persos
if not os.path.exists(repCourant+"\\FichiersRecus"):
os.mkdir(repCourant+"\\FichiersRecus")
except:
logProg.error("Erreur de creation des repertoires de l'application")
demarrageOk = False
#verif si l'appli est deja lancee:
nomAppli = "DMonde.exe"
compte = 0
for proc in process_iter(): #from psutil
try:
nomProc = proc.name()
if nomProc == nomAppli:
compte += 1
if compte > 1:
demarrageOk = False
logProg.error("Une instance de l'application est deja en cours d'execution")
break
except:
pass
if demarrageOk:
#lancement de l'appli
app = QApplication(argv) #'argv' vient de 'sys'
connexion = EcranConnexion()
connexion.show()
r = app.exec_()
if r == 0 and connexion.client_connecte:
#si pas d'erreur et client connecte, on ouvre l'interface principale
ecranChat = EcranChat(connexion)
ecranChat.show()
r = app.exec_()
exit(r) #'exit' vient de 'sys'