# # Sam Hadow - Huffman-py # Copyright (C) 2023 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # from PyQt5 import QtCore, QtGui, QtWidgets, QtSvg from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * import os, json, sys from huffman_py.gui.generate_graph import * from huffman_py.fonctions.decode import * from huffman_py.fonctions.encode import * from huffman_py.gui.InputDialog import * from huffman_py.fonctions.ifFileGetContent import * from huffman_py.gui.messageBox import * class Ui_MainWindow(QWidget): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName(u"MainWindow") MainWindow.resize(800, 800) self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") self.gridLayout = QGridLayout(self.centralwidget) self.gridLayout.setObjectName(u"gridLayout") # widget pour attacher le graphe/texte self.widget = QWidget(self.centralwidget) self.widget.setObjectName(u"widget") self.widget.setMinimumSize(QSize(10, 10)) self.gridLayout.addWidget(self.widget, 1, 0, 1, 1) # widget_2 pour attacher les boutons self.widget_2 = QWidget(self.centralwidget) self.widget_2.setObjectName(u"widget_2") self.widget_2.setMaximumSize(QSize(4000, 50)) self.gridLayout.addWidget(self.widget_2, 0, 0, 1, 1) ## MainWindow.setCentralWidget(self.centralwidget) self.retranslateUi(MainWindow) # grille pour les widget texte ou svg self.gridLayout_main = QGridLayout(self.widget) self.gridLayout_main.setObjectName(u"gridLayout_main") # les widgets en question ##### # graphe de l'arbre self.viewer = QtSvg.QSvgWidget() self.gridLayout_main.addWidget(self.viewer,0, 0, 1, 1) ##### # texte self.texte = QTextEdit() self.texte.setReadOnly(True) self.gridLayout_main.addWidget(self.texte,1, 0, 1, 1) # on cache pour le moment les widget, on les affichera quand on en aura besoin self.viewer.setVisible(False) self.texte.setVisible(False) # éléments de grid 2 # boutons ###################### self.gridLayout_2 = QGridLayout(self.widget_2) self.gridLayout_2.setObjectName(u"gridLayout_2") ##### # push button encodage self.pushButton_encode = QPushButton(self.widget_2) self.pushButton_encode.setObjectName(u"pushButton") self.gridLayout_2.addWidget(self.pushButton_encode, 1, 0, 1, 1) self.pushButton_encode.setText(QCoreApplication.translate("MainWindow", u"encoder", None)) # fonction du bouton self.pushButton_encode.clicked.connect(self.showDialogEncoder) ##### # push button décodage self.pushButton_decode = QPushButton(self.widget_2) self.pushButton_decode.setObjectName(u"pushButton_decode") self.gridLayout_2.addWidget(self.pushButton_decode, 1, 1, 1, 1) self.pushButton_decode.setText(QCoreApplication.translate("MainWindow", u"décoder", None)) # fonction du bouton self.pushButton_decode.clicked.connect(self.showDialogDecoder) ##### # push button encode to file self.pushButton_encodeToFile = QPushButton(self.widget_2) self.pushButton_encodeToFile.setObjectName(u"pushButton_encodeToFile") self.gridLayout_2.addWidget(self.pushButton_encodeToFile, 1, 2, 1, 1) self.pushButton_encodeToFile.setText(QCoreApplication.translate("MainWindow", u"encoder vers fichier", None)) # fonction du bouton self.pushButton_encodeToFile.clicked.connect(self.showDialogEncoderFichier) ##### #push button decode to file self.pushButton_decodeToFile = QPushButton(self.widget_2) self.pushButton_decodeToFile.setObjectName(u"pushButton_decodeToFile") self.gridLayout_2.addWidget(self.pushButton_decodeToFile, 1, 3, 1, 1) self.pushButton_decodeToFile.setText(QCoreApplication.translate("MainWindow", u"décoder vers fichier", None)) # fonction du bouton self.pushButton_decodeToFile.clicked.connect(self.showDialogDecoderFichier) ##### fin boutons # lancement d'une fonction avant la fermeture qApp.aboutToQuit.connect(self.closeEvent) ###### # fonctions des boutons def showDialogEncoder(self): '''affiche le dialogue pour encoder un texte (chemin vers fichier accepté) et affiche l'arbre correspondant''' text, ok = QInputDialog.getText(self, 'données', 'entrez le texte') text = ifFileGetContent(text) if ok and len(text) > 0: the_data = (str(text)) print(the_data) encoding, racine, _ = huffman_encode(the_data) print("Encoded output", encoding) print("Decoded Output", huffman_decode(encoding, racine)) #générer l'arbre à afficher (le .svg) generate_graph(racine) # rafraichir l'affichage de l'arbre self.viewer.load('tree.svg') self.viewer.update() # on affiche le widget contenant l'arbre (et on affiche le texte encodé, dans un petit espace de préférence) self.viewer.setVisible(True) self.texte.setText(encoding) self.texte.setMaximumSize(QSize(4000, 50)) self.texte.setVisible(True) def showDialogDecoder(self): '''affiche le dialogue pour décoder un texte encodé avec ses codes (chemins vers fichiers acceptés)''' dialog = InputDialog("binaire","Dict {lettre:code} JSON-formatted") if dialog.exec(): data = dialog.getInputs() binaire = ifFileGetContent(data[0]) if len(binaire)>0 and len(data[1])>0: try: dico = json.loads(ifFileGetContent(data[1])) except ValueError: create_msg_box("Impossible de lire le dictionnaire fourni, est-ce bien un dictionnaire python formatté en JSON?","Dictionnaire invalide") return 0 try: text = decode_from_dico(binaire, dico) except ValueError: create_msg_box("Impossible de décoder le texte, est-ce bien le dictionnaire correspondant à ce texte encodé?","Erreur décodage") return 0 except TypeError: create_msg_box("Impossible d'utiliser le texte fourni, est-ce bien un texte encodé en binaire?","Erreur entrée") return 0 # on remplace le contenu du widget texte par le texte obtenu en décodant self.texte.setText(text) self.texte.setMaximumSize(QSize(4000, 4000)) # on affiche le widget contenant le texte (et on cache l'arbre) self.viewer.setVisible(False) self.texte.setVisible(True) def showDialogEncoderFichier(self): '''affiche le dialogue pour encoder un texte (chemin vers fichier accepté) et crée 2 fichiers au chemin spécifié (un raw avec le texte encode et un json avec le dictionnaire des codes)''' dialog = InputDialog("texte","chemin vers fichier") if dialog.exec(): data = dialog.getInputs() texte = ifFileGetContent(data[0]) if len(data[1])>0 and len(texte)>0: try: with open(data[1]+'.raw','w') as fd_bin, open(data[1]+'.json','w') as fd_dic: #encoding, _, dico = huffman_encode(data[0]) encoding, _, dico = huffman_encode(texte) json.dump(dico,fd_dic) fd_bin.write(encoding) except FileNotFoundError: create_msg_box("Le chemin est invalide, est-ce que le dossier dans lequel créer le fichier existe?","Erreur entrée") def showDialogDecoderFichier(self): '''affiche le dialogue pour décoder un texte encodé avec ses codes (chemins vers fichiers acceptés), écrit le résultat dans le fichier donné en argument''' dialog = InputDialog("texte","Dict {lettre:code} JSON-formatted", texte3 = "chemin vers fichier", thirdBox = True) if dialog.exec(): data = dialog.getInputs() binaire = ifFileGetContent(data[0]) if len(binaire)>0 and len(data[1])>0: try: dico = json.loads(ifFileGetContent(data[1])) except ValueError: create_msg_box("Impossible de lire le dictionnaire fourni, est-ce bien un dictionnaire python formatté en JSON?","Dictionnaire invalide") return 0 try: texte = decode_from_dico(binaire, dico) except ValueError: create_msg_box("Impossible de décoder le texte, est-ce bien le dictionnaire correspondant à ce texte encodé?","Erreur décodage") return 0 except TypeError: create_msg_box("Impossible d'utiliser le texte fourni, est-ce bien un texte encodé en binaire?","Erreur entrée") return 0 try: with open(data[2],'w') as fd: fd.write(texte) except FileNotFoundError: create_msg_box("Le chemin est invalide, est-ce que le dossier dans lequel créer le fichier existe?","Erreur entrée") ##### fin fonctions des boutons def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(QCoreApplication.translate("Huffman.py", u"Huffman.py", None)) def closeEvent(self): # supprimer le fichier du graphe avant de fermer le programme try: os.unlink('./tree.gv') os.unlink('./tree.svg') except: # si l'utilisateur avait ouvert le programme mais pas généré d'arbre pass print('exit') sys.exit(0)