Skip to content

Commit

Permalink
Chgmt majeur: Issues #46, #52, #47
Browse files Browse the repository at this point in the history
	- Passage de gtk.ScrolledWindow à gtk.Label (permet un affichage
	  plus joli)
	- Passage sur un sous-process => plus de saccade
  • Loading branch information
abject committed Jul 17, 2012
1 parent 49225b3 commit c8553ff
Showing 1 changed file with 166 additions and 110 deletions.
276 changes: 166 additions & 110 deletions modules/decrypt.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,140 @@
import gobject
import teams
import time
import fnmatch


class ScrolledLabelBox(gtk.VBox):
def __init__(self,delay=1000,max_line=15,width=50,lines=[]):
## Initialise gtk.VBox, gtk.HBox
gtk.VBox.__init__(self)
self.lines = lines
self.delay = int(delay) # Temps en ms entre deux appels de la fonction onTimeout
self.max_line = int(max_line) # Nombre de lignes à afficher au maximum
self.width = int(width) # Nombre de caractères par lignes
self.phase = "init" # si init, affiche des NO rouges, sinon affiche des OK verts
self.timer = None
self.cursor = 0
self.team = ""
self.updated_team = []

self.text = gtk.Label()
self.text.set_alignment(0,0)
self.add(self.text)
gobject.signal_new("team-update",DecryptBox,gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [gobject.TYPE_STRING,gobject.TYPE_BOOLEAN])
gobject.signal_new("interne-stop", ScrolledLabelBox, gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [])

def start(self,sender=None):
if self.timer is None:
self.timer = gobject.timeout_add(self.delay,self.onTimeout)

def pause(self,sender=None):
if self.timer:
gobject.source_remove(self.timer)
self.timer = None

def changeMaxLine(self,sender,new_max_line):
self.max_line = int(new_max_line)

def changeWidth(self,sender,new_width):
self.width = int(new_width)

def changePhase(self,sender=None):
if self.phase == "init":
self.phase = "clear"
else:
self.phase = "init"

def append(self,text_to_append, root="équipe "):
"""Ajouter du texte à la fin du texte déjà écrit"""

# On ne garde que les N dernières lignes
previous_text = self.text.get_label().split("\n")
if len(previous_text) > self.max_line:
previous_text = previous_text[-self.max_line:]
previous_text = "\n".join(previous_text)

# On supprime la mise en forme générale, qui vient perturber l'insertion
## d'abord le début
previous_text = previous_text.replace("<span foreground='white' font_desc='Monospace'>","",1)
## puis la fin
previous_text = self.rreplace(previous_text,"</span>","",1)

# On comble en points jusqu'à obtenir la taille de ligne désirée
if text_to_append == "":
text_to_append = text_to_append+"\n"
if not text_to_append[-1] == "\n":
text_to_append = text_to_append+"\n"
text_to_append, phase = self.cleanText2append(text_to_append)
## Update team
if root in text_to_append:
self.team = text_to_append.split(root)[1].replace("'", "").replace("\n", "")
if not text_to_append == '\n' and not root in text_to_append and phase != None:
if len(text_to_append) <= self.width - 4:
dots = "".join(["." for i in range(self.width - len(text_to_append) - 4)])
if phase:
text_to_append = text_to_append.replace("\n","") + dots + "[<span foreground='green'>OK</span>]\n"
else:
text_to_append = text_to_append.replace("\n","") + dots + "[<span foreground='red'>NO</span>]\n"

# Puis on met le tout en forme (police à chasse fixe)
next_text = "<span foreground='white' font_desc='Monospace'>"+previous_text+str(text_to_append)+"</span>"
# et on affiche !
self.text.set_markup(next_text)

def cleanText2append(self, text_to_append):
if fnmatch.fnmatch(text_to_append, "*OK*"):
passwd = True
text_to_append = text_to_append.replace("[OK]", "")
elif fnmatch.fnmatch(text_to_append, "*KO*"):
text_to_append = text_to_append.replace("[KO]", "")
passwd = False
else:
passwd = None
text_to_append = text_to_append.replace("\t", "")
if passwd != None and not self.team in self.updated_team:
self.emit("team-update", self.team, passwd)
self.updated_team.append(self.team)
return text_to_append, passwd


def onTimeout(self, *args):
"""Fonction appelée toutes les self.delay ms"""
if self.lines != []:
line = self.lines[self.cursor]
self.append(line)
self.cursor += 1
if self.cursor >= len(self.lines):
self.emit("interne-stop")
return False
return True # Si True, continue
else:
print "WARNING: self.lines = '%s'"%(self.lines)
return False # Stop scroll

def rreplace(self, s, old, new, occurrence):
li = s.rsplit(old, occurrence)
return new.join(li)

def update_pbar(self, percent=None, team_data=None):
""" Met à jour le texte de la barre de progression
"""
## Met à jour percent
if percent == None:
percent = self.percent
if percent > 1.0:
percent = 1.0
## Met à jour le texte et la valeur de la barre
self.pbar.set_fraction(percent)
if team_data == None:
team_data = self.team
self.pbar.set_text("Équipe '%s' (%d/%d)"%(team_data[0], team_data[1], self.nteam))

class DecryptBox(gtk.VBox):
""" Fenêtre de décryptage
"""

def __init__(self, passwd="passwd", team_list=[teams.team("Orion1", passwd="asswd"), teams.team("Pegase2", passwd="Passwd"), teams.team("Ariane3", passwd="")],data_folder="data/"):
def __init__(self, passwd="passwd", team_list=[teams.team("Orion1", passwd="passwd"), teams.team("Pegase2", passwd="Passwd"), teams.team("Ariane3", passwd="")],data_folder="data/"):
""" Initialisation
"""
## Initialise la fenetre
Expand All @@ -41,37 +169,26 @@ def __init__(self, passwd="passwd", team_list=[teams.team("Orion1", passwd="assw
## Charge les variables
self.has_at_least_one_time = False
self.passwd = passwd
self.team_list = team_list
self.nteam = len(self.team_list)
self.setTeams(team_list)
self.team = ("", 0)
self.percent = 0.0
self.data_folder = data_folder
self.win = None

## Initialise la barre de progression
self.pbar = gtk.ProgressBar()
self.pbar.set_size_request(500, 50)
self.update_pbar(team_data=("", 0))
self.continuer=True
## Label
self.scrolledlabel = ScrolledLabelBox()

## Scroll text
self.textview = gtk.TextView()
self.textview.set_editable(False)
self.textview.set_cursor_visible(False)
self.scrolledwindow = gtk.ScrolledWindow()
self.scrolledwindow.add(self.textview)
self.scrolledwindow.set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER)
self.set_size_request(500, 300)

## Buffer
self.buffer = self.textview.get_buffer()
## Size request
self.scrolledlabel.set_size_request(800, 300)

## Affichage sur self
self.pack_start(self.pbar, expand=False, fill=True, padding=0)
self.pack_start(self.scrolledwindow, True, True, 0)
self.pack_start(self.scrolledlabel, True, True, 0)

## Signaux
gobject.signal_new("team-update",DecryptBox,gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [gobject.TYPE_STRING,gobject.TYPE_BOOLEAN])
self.scrolledlabel.connect("interne-stop", self.onStop)

def setTeams(self,team_list):
""" Initialize les equipe """
self.team_list = team_list
self.nteam = len(self.team_list)

Expand All @@ -93,52 +210,19 @@ def phase1(self):
if self.nteam == 0:
self.continuer = False

text = []
## Boucle sur toutes les équipes
while self.continuer:
## Recupere la classe de l'équipe
team = self.team_list[num]
for num, team in enumerate(self.team_list):
passwd_check = False
if self.passwd == team.passwd:
at_least_one_passwd = True
passwd_check = True

## Met à jour le texte de la barre
self.update_pbar(team_data=(team.name, num+1))

## Génère le texte de l'équipe
text = self.team_text(team).split('\n')

## Boucle sur les lignes
for line in text:
time.sleep(1)
count = count + 1
self.update_pbar(percent=float(count)/total)
self.text = self.text + '\n' + line
self.update_buffer(self.text)

self.emit("team-update",team.name,passwd_check)

## Incrémente le compteur
num = num + 1

## Arrêt de la boucle while
if num >= self.nteam:
self.continuer = False
time.sleep(2)
text = text + self.team_text(team).split('\n')

## Renvoie at_least_one_passwd
return at_least_one_passwd

def update_buffer(self, text):
""" Met à jour le buffer et fait défiler le texte
"""
## Met à jour le buffer
self.buffer.set_text(text)
## Fait défiler le text
adj = self.scrolledwindow.get_vadjustment()
adj.set_value( adj.upper - adj.page_size )
while gtk.events_pending():
gtk.main_iteration()
return text, at_least_one_passwd

def show_warning_and_continue(self, msg):
""" Montre que le mot de passe a été trouvé et valide le décryptage
Expand All @@ -157,46 +241,35 @@ def phase2(self):
## Lecture du fichier 'phase2'
with open(self.data_folder+'decrypt_msg_phase2.txt') as f:
lines = f.readlines()

## Activation de la barre de progression en mode activité
self.pbar.set_text("")
self.pbar.set_orientation(gtk.PROGRESS_RIGHT_TO_LEFT)

## Affichage du fichier 'phase2'
nlines = len(lines)
n = 0
while self.continuer:
line = lines[n]
time.sleep(0.1)
self.update_pbar(percent=float(n+1)/float(nlines))
self.text = self.text + line
self.update_buffer(self.text)
n = n + 1
if n >= nlines:
self.continuer = False
return lines

def start(self):
""" Lance la procédure de décryptage
"""
## Set has_at_least_one_time
self.has_at_least_one_time = True

## Reset les variables
self.text = ""
self.continuer = True
self.update_pbar(team_data=("", 0))
self.pbar.set_orientation(gtk.PROGRESS_LEFT_TO_RIGHT)
## Génération du texte à faire défiler
text1, self.win = self.phase1()
if not self.win:
text2 = self.phase2()
else:
text2 = []
lines = text1 + text2

## Lancement de la phase 1
win = self.phase1()
## Faire défiler le texte
self.scrolledlabel.lines = lines
self.scrolledlabel.start()

def onStop(self, sender=None):
""" Affiche le message final"""
## Test la réussite
if win:
if self.win == None:
print "Lancer start avant"
if self.win:
msg = self.msg_from_file(self.data_folder+'decrypt_msg_phase1win.txt')
self.show_warning_and_continue(msg)
else:
self.continuer = True
self.phase2()
msg = self.msg_from_file(self.data_folder+'decrypt_msg_phase2win.txt')
self.show_warning_and_continue(msg)

Expand All @@ -208,22 +281,6 @@ def msg_from_file(self, filename):
msg = "".join(msg)
return msg

def update_pbar(self, percent=None, team_data=None):
""" Met à jour le texte de la barre de progression
"""
## Met à jour percent
if percent != None:
if percent > 1.0:
percent = 1.0
self.percent = percent
## Met à jour le texte et la valeur de la barre
self.pbar.set_fraction(self.percent)
if team_data != None:
self.pbar.set_text("Équipe '%s' (%d/%d)"%(team_data[0], team_data[1], self.nteam))
## On fordce la mise à jour de la fenêtre
while gtk.events_pending():
gtk.main_iteration(False)

def get_template(self):
""" Charge le template du texte
"""
Expand All @@ -249,18 +306,11 @@ def team_text(self, team):
## Renvoie
return lines

def quit(self, *parent):
""" Fonction qui permet de quitter proprement
"""
if self.continuer:
self.continuer = False

class popupWindow(gtk.Window):
""" Fenêtre principale pour tester le module
"""
def __init__(self,showcontrol=False,dataf="data/", passwd="passwd"):
## Charge gobject (Important pour ScrollTextBox)
gobject.threads_init()
gobject.signal_new("team-ask-teams",popupWindow,gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [])
gobject.signal_new("team-update",popupWindow,gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [gobject.TYPE_STRING, gobject.TYPE_BOOLEAN])
gobject.signal_new("main-enigme", popupWindow, gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [gobject.TYPE_INT])
Expand All @@ -270,9 +320,13 @@ def __init__(self,showcontrol=False,dataf="data/", passwd="passwd"):
self.set_title("Décryptage")
self.ready = False

# Definition d'une couleur
bgcolor = gtk.gdk.color_parse("#000000")
self.modify_bg(gtk.STATE_NORMAL, bgcolor)

## DecryptBox
self.decryptbox = DecryptBox(data_folder=dataf, passwd=passwd)
self.decryptbox.connect("team-update",self.onUpdateTeam)
self.decryptbox.scrolledlabel.connect("team-update",self.onUpdateTeam)

## Affichage
if showcontrol:
Expand All @@ -296,6 +350,7 @@ def onUpdateTeam(self,sender,team_name,check):

def start(self, *parent):
self.emit("team-ask-teams")
self.decryptbox.start()

def getTeams(self,sender,team_list):
self.decryptbox.setTeams(team_list)
Expand All @@ -319,3 +374,4 @@ def main(self):
r = popupWindow(showcontrol=True,dataf="../data/")
r.show_all()
r.main()

8 comments on commit c8553ff

@ViviCoder
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effectivement, ça améliore les choses pour le décryptage. Par contre, lorsque tu tapes start, là ça rame toujours.

@abject
Copy link
Collaborator

@abject abject commented on c8553ff Jul 18, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

En même temps je n'ai touché qu'au décryptage 😏

Je ne vois pas ce qui "rame" avec start ? Tu peux être plus précis car chez moi je n'ai rien noté de tel 😖

@ViviCoder
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

En fait, ça arrive même si tu ne lances pas start
Une fois les clés testées et le message comme quoi ça va marcher affiché, quand tu fermes la popup, le texte commence à ralentir et finalement s'affiche en clair.
Peut-être que c'est l'effet voulu, mais je ne trouve ça pas terrible. Il vaudrait mieux que le texte continue à dérouler et que les lignes cryptées soient progressivement remplacées par le texte clair (qui déroule toujours).

@abject
Copy link
Collaborator

@abject abject commented on c8553ff Jul 18, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, c'est voulu (et j'ai mis longtemps pour arriver à ça 😢) !

Je ne suis pas contre faire apparaître le texte décrypté peu à peu mais comment dire . . . je suis à cours d'idée de comment coder ça ?

Et plus j'y pense plus je vois des problèmes en fonction de la taille (nombre de lignes) des énigmes, de l'affichage de celles-ci (car il FAUT qu'elles entrent entièrement dans la zone de texte) que si l'on fait suivant ton idée il faut pouvoir stopper le texte pile en bas de page . . .
Enfin plein de choses comme ça que je ne vois pas comment on peut faire pour le gérer (surtout avant Fleurance...).

@ViviCoder
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tu as un tableau qui pour chaque ligne de texte te dit si elle est crypté ou pas.
Au début, tout est crypté et régulièrement tu en décrypte une.
À l'affichage, pour chaque ligne, tu l'affiches telle quelle si le tableau indique qu'elle est en clair, ou alors tu met une somme MD5 aléatoire.
En fait, il n'y a pas besoin que le texte crypté défile, on peut dire qu'il suffit qu'il semble aléatoire, non ?

@abject
Copy link
Collaborator

@abject abject commented on c8553ff Jul 18, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tu as un tableau qui pour chaque ligne de texte te dit si elle est crypté ou pas.
Au début, tout est crypté et régulièrement tu en décrypte une.
À l'affichage, pour chaque ligne, tu l'affiches telle quelle si le tableau indique qu'elle est en clair, ou alors tu met une somme MD5 aléatoire.

C'est pas une mauvaise idée mais un md5 ne rempli pas la zone de texte car il ne fait que quelques caractères de taille.
Du coup j'ai contourné le problème en sommant le md5 de plusieurs lignes pour "remplir" la zone (et même un peu plus).

En fait, il n'y a pas besoin que le texte crypté défile, on peut dire qu'il suffit qu'il semble aléatoire, non ?

C'est plus sympas s'il défile. Du coup on a toujours le problème de l'affichage final . . . .

@ViviCoder
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Si le texte en clair derrière ne défile pas, je ne vois pas trop ce que le défilement du texte crypté apporte. Si c'est aléatoire, ça donne une impression de fourmillement sans mouvement global (ce qui est cohérent avec le texte clair immobile). Et puis ça fait genre le code de cryptage change en permanence...
Si tu tiens absolument à ce que le texte défile et si les lignes cryptées qui défilent sont toujours les mêmes, il suffit que tu les stockes dans un tableau, pour le défilement tu fais une permutation circulaire et après, pour l'affichage, à chaque ligne tu vérifies si elle est claire ou pas.

@abject
Copy link
Collaborator

@abject abject commented on c8553ff Jul 18, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je vois que tu as plein d'idée, je t'en prie n'hésites pas à les mettre en œuvre 😏

Plus sérieusement, je vais poser la question à l'équipe d'animation pour voir ce qu'ils en pense.

Je vous tiens au courant.

Please sign in to comment.