class GraphicalApp(tk.Frame): """Interface graphique du jeu.""" def __init__(self, dispatcher): self.dispatcher = dispatcher self.master = None self.treeview = None self.chats = { } # contient des listes [id, treeview, entry, bouton, messageCpt] self.progress = None self.previousAngles = {} self.initializeGraphicalApp() self.dispatcher.setGraphicalApp(self) self.mainloop() def initializeGraphicalApp(self): """Initialise l'interface graphique.""" self.master = tk.Tk() self.master.title("To the conquest of the dragon balls !") super().__init__(self.master) self.master.resizable(False, False) self.createWidgets() self.setUpBindingEvent() self.master.protocol("WM_DELETE_WINDOW", self.closeWindow) msg = "Welcome space travelers !\n\n" msg += "A brand new race has been created. " msg += "You may ask yourself : \"Why should i participate ?\" " msg += "Well because the reward is worth it, it's nothing more than the seven dragon balls !\n" msg += "Suddenly fell more excited right ?!\n" msg += "But watch out, you are not the only one interested...\n\n" msg += "In order to move your vehicle, use your keyboard's directional arrows.\n" msg += "You can also drop a bomb with the \"B\" button.\n\n" msg += "Good luck !" messagebox.showinfo(title="Welcome !", message=msg) def createWidgets(self): """Crée tous les widgets de l'interface.""" tk.Label(self.master, text="Your pseudo", font="-weight bold").grid(row=0, column=0, sticky=tk.W) self.pseudoEntry = tk.Entry(self.master) self.pseudoEntry.grid(row=0, column=1, sticky=tk.EW) self.pseudoEntry.focus_set() tk.Label(self.master, text="Status : ", font="-weight bold").grid(row=1, column=0, sticky=tk.W) self.statusLabel = tk.Label(self.master, text="Not yet connected...") self.statusLabel.grid(row=1, column=1, sticky=tk.W) self.progress = Progressbar(self.master, orient=tk.HORIZONTAL, mode='indeterminate') self.progress.grid(row=1, column=2) self.exitButton = tk.Button(self.master) self.exitButton["text"] = "Exit" self.exitButton["state"] = tk.DISABLED self.exitButton["bg"] = "#FF0A2D" self.exitButton["activebackground"] = "#FF415C" self.exitButton["fg"] = "#FFFFFF" self.exitButton["activeforeground"] = "#FFFFFF" self.exitButton["relief"] = tk.FLAT self.exitButton["bd"] = 0 self.exitButton["command"] = lambda: self.dispatcher.onExitClicked() self.exitButton.grid(row=2, column=1, sticky=tk.EW) self.connectionButton = tk.Button(self.master) self.connectionButton["text"] = "Connect to the server" self.connectionButton["bg"] = "#1296EC" self.connectionButton["activebackground"] = "#33A5EF" self.connectionButton["fg"] = "#FFFFFF" self.connectionButton["activeforeground"] = "#FFFFFF" self.connectionButton["relief"] = tk.FLAT self.connectionButton["bd"] = 0 self.connectionButton["command"] = lambda: self.onConnectionClicked( self.connectionButton) self.connectionButton.grid(row=2, column=0, sticky=tk.EW) self.createScoreTable() self.createSpaceEnvironment() self.notebook = Notebook(self.master) self.notebook.grid(row=5, column=3, columnspan=2, rowspan=3, sticky=tk.NSEW) self.createChat("Public", enable=False) def setUpBindingEvent(self): """Met en place tous les événement permettant eu joueur de contrôler son pod.""" # Les code de mise à jour du joueur doivent être exécutés dans un autre thread. # Dans le cas contraire, il y a un interblocage entre le thread de # l'interface graphique (celui-ci), et celui qui met à jour périodiquement les position des joueurs. self.master.bind('<Left>', self.dispatcher.antiClockEvent) self.master.bind('<Right>', self.dispatcher.clockEvent) self.master.bind('<Up>', self.dispatcher.thrustEvent) self.master.bind('b', self.dispatcher.putBomb) def createSpaceEnvironment(self): """Crée un décor spatial.""" self.canvasLock = Lock() self.canvas = tk.Canvas(self.master, width=dat.ARENA_L * 2, height=dat.ARENA_H * 2, bg="black") self.canvas.grid(row=5, column=0, columnspan=3, rowspan=5, pady=(10, 0)) # Ajoute 200 étoiles for __ in range(0, 200): self.drawRandomStar() def drawRandomStar(self): """Dessine une étoile à une position aléatoire.""" maxX = int(self.canvas["width"]) maxY = int(self.canvas["height"]) x = random.randint(0, maxX) y = random.randint(0, maxY) self.canvas.create_oval(x, y, x + 5, y + 5, fill="white") def createScoreTable(self): """Crée le tableau des scores.""" tk.Label(self.master, text="Scores", font="-weight bold").grid(row=3, column=0, columnspan=2) tv = Treeview(self.master, height=3) tv['columns'] = ('Score', "Bomb") tv.heading("#0", text='User', anchor=tk.W) tv.heading('Bomb', text='Bombs available', anchor=tk.W) tv.column('Bomb', anchor=tk.W, width=100) tv.heading('Score', text='Score', anchor=tk.W) tv.column('Score', anchor=tk.W, width=100) tv.grid(row=4, column=0, columnspan=3, sticky=tk.EW) self.treeview = tv def increaseBombOf(self, player): """Incrémente le nombre de bombe que possède un joueur dans le tableau d'affichage. Arguments: player - Le pseudo du joueur pour lequel on doit incrémenter son nombre de bombe. """ for i in self.treeview.get_children(): item = self.treeview.item(i) # Nous sommes bien sur l'item du joueur qui nous interesse if item["text"] == player: oldValue = item['values'] oldValue[1] += 1 self.treeview.item(i, values=oldValue) break def decreaseBombOf(self, player): """Décrémente le nombre de bombe que possède un joueur dans le tableau d'affichage. Arguments: player - Le pseudo du joueur pour lequel on doit décrémenter son nombre de bombe. """ for i in self.treeview.get_children(): item = self.treeview.item(i) # Nous sommes bien sur l'item du joueur qui nous interesse if item["text"] == player: oldValue = item['values'] oldValue[1] -= 1 self.treeview.item(i, values=oldValue) break def setBombOf(self, player, nbBomb): """Met à jour le nombre de bombe que possède un joueur dans le tableau d'affichage. Arguments: player - Le pseudo du joueur pour lequel on doit mettre à jour son nombre de bombe. nbBomb - Le nouveau nombre de bombe du joueur. """ for i in self.treeview.get_children(): item = self.treeview.item(i) # Nous sommes bien sur l'item du joueur qui nous interesse if item["text"] == player: oldValue = item['values'] oldValue[1] = nbBomb self.treeview.item(i, values=oldValue) break def createChat(self, nom, enable=True): """Créer un nouveau chat pour un joueur donné. Arguments: nom - Le nom du joueur avec lequel l'utilisateur pourra parler avec ce chat Keyword Arguments: enable -- Est-ce que le chat doit être activer par défaut. (default: {True}) """ frame = tk.Frame(self.notebook) self.notebook.add(frame, text=nom) chat = Treeview(frame, height=15) chat['columns'] = ('Date') chat.heading("#0", text='Messages', anchor=tk.W) chat.heading('Date', text='Date', anchor=tk.W) chat.column('Date', anchor=tk.W, width=150) chat.grid(row=0, column=0, columnspan=2, rowspan=3, sticky=tk.NSEW) chat.tag_configure('even', background='#DAE5F4') chat.tag_configure('odd', background='#B8D1F3') chat.tag_configure('from_me', font=("Helvetica", 10, "bold")) chat.tag_configure('not_from_me', font=("Helvetica", 10)) messageEntry = tk.Entry(frame) messageEntry.grid(row=4, column=0, sticky=tk.S) messageButton = tk.Button(frame) messageButton["text"] = "Envoyer" if not enable: messageButton["state"] = tk.DISABLED messageButton["bg"] = "#1296EC" messageButton["activebackground"] = "#33A5EF" messageButton["fg"] = "#FFFFFF" messageButton["activeforeground"] = "#FFFFFF" messageButton["relief"] = tk.FLAT messageButton["bd"] = 0 messageButton["command"] = lambda: self.sendMessage(nom, messageEntry) messageButton.grid(row=4, column=1, sticky=tk.S) self.chats[nom] = [frame, chat, messageEntry, messageButton, 0] def deleteChat(self, name): """Supprime un chat permmetant de communiquer avec un joueur donnée. Arguments: name -- Le nom du joueur pour lequel on doit supprimer le chat. """ self.notebook.forget(self.chats[name][0]) def sendMessage(self, target, entry): """Signale au dispatcher la volonté de l'utilisateur d'envoyer un message. Arguments: target -- La cible à laquelle le joueur souhaite envoyer le message. entry -- L'entry source sur laquelle l'utilisateur a saisi son message. """ message = entry.get() if message == "": messagebox.showerror(title="Empty message", message="You cannot send an empty message") else: self.dispatcher.sendMessage(target, message) entry.delete(0, tk.END) def addMessage(self, chatName, message, fromMe=False): """Ajout un message à un chat. Arguments: chatName -- Le nom du chat. message -- Le message. Keyword Arguments: fromMe -- Indique si le message vient de l'utilisateur de l'application cliente. (default: {False}) """ currentDate = strftime("%d/%m/%Y-%H:%M:%S", gmtime()) fromMeTag = 'from_me' if fromMe else 'not_from_me' odd_even_tag = 'even' if (self.chats[chatName][4] % 2) == 0 else 'odd' self.chats[chatName][1].insert('', 'end', text=message, values=currentDate, tags=(odd_even_tag, fromMeTag)) self.chats[chatName][4] += 1 def addScoreToTable(self, user, score): """ Ajoute un nouveau score au tableau des scores. Si le joueur est déjà présent, met à jour sa ligne. Arguments: user -- Un pseudo. score -- Un score. """ edited = False for i in self.treeview.get_children(): item = self.treeview.item(i) # Nous sommes bien sur l'item du joueur qui nous interesse if item["text"] == user: oldValue = item['values'] oldValue[0] = score self.treeview.item(i, values=oldValue) edited = True break if not edited: self.treeview.insert('', 'end', text=str(user), values=(str(score), "0")) def createGraphicalPlayer(self, playerX, playerY): """Crée un joueur à une position spécifique. Arguments: playerX -- La coordonnée X du joueur. playerY -- La coordonnée Y du joueur. Returns: tuple -- Un tuple contenant le tag du joueur dans le canvas et ses images. """ convertedPos = self.convertPosition(playerX, playerY) playerImage = Image.open('images/pod_sprite_50.png') podPicture = ImageTk.PhotoImage(playerImage) self.canvasLock.acquire() tagPlayer = self.canvas.create_image(convertedPos[0], convertedPos[1], image=podPicture) self.canvasLock.release() return (tagPlayer, playerImage, podPicture) def createGraphicalOpponent(self, playerX, playerY): """Crée un adversaire à une position spécifique. Arguments: playerX -- La coordonnée X de l'adversaire. playerY -- La coordonnée Y de l'adversaire. Returns: tuple -- Un tuple contenant le tag de l'adversaire dans le canvas et ses images. """ convertedPos = self.convertPosition(playerX, playerY) opponentImage = Image.open('images/pod2_sprite_50.png') podPicture = ImageTk.PhotoImage(opponentImage) self.canvasLock.acquire() tagOpponent = self.canvas.create_image(convertedPos[0], convertedPos[1], image=podPicture) self.canvasLock.release() return (tagOpponent, opponentImage, podPicture) def createGraphicalObstacle(self, obstacleX, obstacleY): """Crée un obstacle à une position spécifique. Arguments: obstacleX -- La coordonnée X de l'obstacle. obstacleY -- La coordonnée Y de l'obstacle. Returns: tuple -- Un tuple contenant le tag de l'obstacle dans le canvas et sa photoImage. """ convertedPos = self.convertPosition(obstacleX, obstacleY) obstacleImage = Image.open('images/obstacles/asteroid_sprite_55.png') obstaclePicture = ImageTk.PhotoImage(obstacleImage) self.canvasLock.acquire() tagOstacle = self.canvas.create_image(convertedPos[0], convertedPos[1], image=obstaclePicture) self.canvasLock.release() return (tagOstacle, obstaclePicture) def createGraphicalGenkidma(self, genkidamaX, genkidamaY): """Crée un genkidama à une position spécifique. Arguments: genkidamaX -- La coordonnée X du genkidama. genkidamaY -- La coordonnée Y du genkidama. Returns: tuple -- Un tuple contenant le tag du genkidama dans le canvas et sa photoImage. """ convertedPos = self.convertPosition(genkidamaX, genkidamaY) genkidamaImage = Image.open('images/bombs/spirit_bomb_35.png') genkidamaPicture = ImageTk.PhotoImage(genkidamaImage) self.canvasLock.acquire() tagGenkidama = self.canvas.create_image(convertedPos[0], convertedPos[1], image=genkidamaPicture) self.canvasLock.release() return (tagGenkidama, genkidamaPicture) def deleteGraphicalGenkidma(self, genkidamaX, genkidamaY): """Enlève un genkidama situé à une position spécifique. Arguments: genkidamaX -- La coordonnée X du genkidama. genkidamaY -- La coordonnée Y du genkidama. Returns: tuple -- Un tuple contenant le tag du genkidama dans le canvas et sa photoImage. """ convertedPos = self.convertPosition(genkidamaX, genkidamaY) self.canvasLock.acquire() tagGenki = self.canvas.find_closest(convertedPos[0], convertedPos[1]) self.canvas.delete(tagGenki) self.canvasLock.release() def onConnectionClicked(self, button): """Handler du clique sur le bouton de connexion Arguments: button -- Le bouton source. """ pseudo = self.pseudoEntry.get() if pseudo == "": msg = "No pseudo given. You have to give a pseudo in order to connect to the server." messagebox.showerror(title="No pseudo", message=msg) else: success = self.dispatcher.onConnectionClicked(pseudo) if success: button["state"] = tk.DISABLED self.exitButton["state"] = tk.NORMAL self.chats["Public"][3]["state"] = tk.NORMAL self.statusLabel["text"] = "Connection succeed !" self.pseudoEntry.delete(0, tk.END) else: msg = "Connection to the server failed.\nMake sure the server is running." messagebox.showerror(title="Connection failed", message=msg) def closeWindow(self): """Handler de la fermeture de la fenêtre. Signale au dispatcher que l'utilisateur souhaite quitter l'application et ferme l'interface. """ self.dispatcher.onCloseWindow() # Il se peut qu'un thread soit bloqué en attente d'une réponse du thread de l'interface # En exécutant un update, on va le débloquer self.master.update() self.master.destroy() def updateUIPlayer(self, player): """Met à jour la position et l'angle de rotation d'un joueur. Arguments: player -- Le joueur. """ self.canvasLock.acquire() if player.getPseudo( ) not in self.previousAngles or self.previousAngles[ player.getPseudo()] != player.getAngle(): self.rotatePlayer(player) self.updatePlayer(player) self.canvasLock.release() def updatePlayer(self, player): """Met à jour la position d'un joueur. Arguments: player -- Le joueur. """ convertedPos = self.convertPosition(player.getPositionX(), player.getPositionY()) self.canvas.coords(player.getCanvasTagId(), (convertedPos[0], convertedPos[1])) def rotatePlayer(self, player): """Met à jour l'angle de rotation d'un joueur. Arguments: player -- Le joueur. """ self.previousAngles[player.getPseudo()] = player.getAngle() self.canvas.delete(player.getCanvasTagId()) podPicture = ImageTk.PhotoImage(player.getImage().rotate( player.getAngle())) convertedPos = self.convertPosition(player.getPositionX(), player.getPositionY()) newId = self.canvas.create_image(convertedPos[0], convertedPos[1], image=podPicture) player.setCanvasTagId(newId) player.setPhotoImage(podPicture) def convertPosition(self, x, y): """Convertie des coordonnées pour qu'elle soit utilisable par le canvas. Arguments: x -- La coordonnée X. y -- La coordonnée Y. Returns: tuple(x, y) -- Un tuple contenant les positions converties. """ newX = x + dat.ARENA_L newY = y + dat.ARENA_H return (newX, newY) def showDeniedMessage(self): """Affiche un message indiquant à l'utilisateur que sa tentative de connexion à été refusée.""" msg = "The server refused the connection.\nYou may try again with an other pseudo" messagebox.showerror(title="Connection refused", message=msg) self.statusLabel["text"] = "Pseudo already used..." self.connectionButton["state"] = tk.NORMAL def showWaitingMessage(self): """Met à jour le label de status pour indiquer à l'utilisateur d'attendre le début de la partie.""" print("Waiting") self.statusLabel["text"] = "Waiting for game to start..." self.progress.start(10) def showStartMessage(self): """Met à jour le label de status pour indiquer à l'utilisateur que la partie à commencé.""" print("Good game") self.statusLabel["text"] = "Good game !" self.progress.stop() def showWinner(self, winnerName, iWin): """Affiche une fenêtre avec le nom du gagnant. Arguments: winnerName -- Le nom du gagnant. iWin -- Indique si le gagnant est le joueur actuel. """ msg = "" if iWin: msg = "Congratulation you have won !" else: msg = winnerName + " has won !" messagebox.showinfo(title="We have a winner !", message=msg) def showObjectif(self, objectifX, objectifY, objectifNumber): """Ajoute un objectif (une dragon ball). Arguments: objectifX -- La coordonnée X de l'objectif. objectifY -- La coordonnée Y de l'objectif. objectifNumber -- Le numéro de l'objectif (utiliser pour choisir quelle dragon ball utiliser). Returns: tuple(idTag, photoImage) -- Un tuple contenant le tag de l'objectif et son image. """ converted = self.convertPosition(objectifX, objectifY) newImage = Image.open('images/dragon_ball/ball_' + str(objectifNumber) + ".png") newPhotoImage = ImageTk.PhotoImage(newImage) self.canvasLock.acquire() tagImage = self.canvas.create_image(converted[0], converted[1], image=newPhotoImage) self.canvasLock.release() return (tagImage, newPhotoImage) def reset(self): """Remet à zéro l'application graphique.""" self.resetScores() for (_, chat) in self.chats.items(): self.notebook.forget(chat[0]) self.chats = {} # On ajoute de nouveau le chat public self.createChat("Public", enable=True) def resetScores(self): """Remet à zéro le tableau des scores.""" self.progress.stop() for i in self.treeview.get_children(): self.treeview.delete(i) def removeOpponent(self, opponentName): """Supprime un adversaire dde l'interface graphique. Arguments: opponentName -- Le nom de l'adversaire. """ for child in self.treeview.get_children(): item = self.treeview.item(child) if (item["text"]) == opponentName: self.treeview.delete(child) if opponentName in self.chats: del self.chats[opponentName] def deleteFromCanvas(self, tag): """Supprime un élément du canavas identifié par son tag. Arguments: tag -- Le tag de l'élément à supprimer. """ self.canvas.delete(tag) def showElement(self, tag): self.canvas.itemconfigure(tag, state='normal') def hideElement(self, tag): self.canvas.itemconfigure(tag, state='hidden')
class Statistics(Page): """This class provides the statistics view, in table and graphical form""" def __init__(self, mainUI): super().__init__(mainUI) self.columnconfigure(0, weight=1) self.back_button = Button(self, text="< Back", command=lambda: self.go_to("Welcome")()) self.back_button.grid(row=1, padx=(10, 0), pady=(10, 5), sticky="w") self.choose_date_label = Label(self, text="View statistics from event on: ") self.choose_date_label.grid(row=1, column=1) self.date_to_view = StringVar(name="date") self.choose_date_menu = OptionMenu(self, self.date_to_view, *StatsData.available_dates()) self.date_to_view.set(StatsData.available_dates()[0]) self.choose_date_menu.grid(row=1, column=2) self.date_to_view.trace("w", self.update_ui) # hide border # https://groups.google.com/forum/#!topic/comp.lang.tcl/8a6e4tfWJvo s = Style(self) s.configure('flat.TNotebook', borderwidth=0) self.tabbed_section = Notebook(self, style="flat.TNotebook") # # FIXME: padding self.tabbed_section.grid(row=2, columnspan="3", padx=20, sticky="n") # self.button = Button(self, text="Export event statistics as CSV", command=self.csv_export) self.button.grid(row=3, columnspan="3", pady=10, sticky="n") self.update_ui() def update_ui(self, *args): new_date = StatsData.dates[self.date_to_view.get()] for tab in self.tabbed_section.tabs(): self.tabbed_section.forget(tab) for package in StatsData.packages_for_date(new_date): test_tab = PackageView(self.tabbed_section, new_date, package) self.tabbed_section.add(test_tab, text=package) def csv_export(self): date = StatsData.dates[self.date_to_view.get()] file_path = filedialog.asksaveasfilename(filetypes=(("CSV", ".csv"), ), initialfile=date) # code taken from https://docs.python.org/3/library/csv.html if file_path: with open(file_path, 'w', newline='') as csvfile: csvwriter = csv.writer(csvfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) csvwriter.writerow(("package name", "quiz", "question id", "question text", "total times shown", "successful answers", "skips", "abandons")) for package in StatsData.packages_for_date(date): for quiz in StatsData.quizzes_for_package(package, date): for q in StatsData.get_data(date, package, quiz): csvwriter.writerow( (q.package_name, q.quiz, q.q_id, q.text, total_times_shown(q), q.successes, q.skips, q.abandons))
class LpoViewer(Frame): """ This class implements the window of the Lpo viewer. This class implements a menu and tab management for the LpoView. """ def __init__(self, parent): """ Create new window. """ Frame.__init__(self, parent) self.__parent = parent self.__initUI() def __initUI(self): """ Set up UI. """ self.pack(fill=BOTH, expand=1) # notebook for LpoView tabs self.__notebook = Notebook(self) self.__notebook.pack(fill=BOTH, expand=1) # menu bar with file menu self.__menubar = Menu(self.__parent) self.__parent.config(menu=self.__menubar) self.__filemenu = Menu(self.__menubar, tearoff=0) self.__filemenu.add_command(label="Open", command=self.__onOpen) self.__filemenu.add_command(label="Close", command=self.__onClose) self.__filemenu.add_command(label="Exit", command=self.__onExit) self.__menubar.add_cascade(label="File", menu=self.__filemenu) # size and title self.__parent.geometry("300x300+300+300") self.__parent.title("Lpo viewer Tk") def __onExit(self): """ Close the app. """ self.__parent.withdraw() self.quit() def __onClose(self): """ Close the selected LPO. """ tab = self.__notebook.select() if tab != '': self.__notebook.forget(tab) def __onOpen(self): """ Open a new LPO (with file chooser). """ ftypes = [('LPO files', '*.lpo'), ('All files', '*')] dialog = filedialog.Open(self, filetypes=ftypes) file = dialog.show() if file != '': self.openLpo(file) def openLpo(self, file): """ This method shows the LPO contained in the given file as new tab. """ lpos = partialorder.parse_lpo_file(file) # parse LPO from file print(lpos[0]) self.showLpo(lpos[0]) # show first lpo (Assumption: Only 1 LPO in a file) def showLpo(self, lpo): """ Show the given LPO in a new tab. """ lpo_view = LpoView(self.__notebook) self.__notebook.add(lpo_view, text=lpo.name, sticky="nswe") lpo_view.showLpo(lpo)
class OpeningPage(): """@summary: Widget servant à lancer la simulation après avoir renseigné les persos """ def __init__(self, fenetre): self.notebk = Notebook(fenetre) self.fenetre = fenetre self.persoViews = [] self.caracsNotebk = [] self.framesPersos = [] def formSubmission(self, _): """@summary: Lance la simulation de combat avec les persos du notebook """ persos = [] for persoVw in self.persoViews: persoVw.inputsToPerso() persos.append(persoVw.perso) writeSaveFile("save.json", persos) launchSimu(self.persoViews) def addEmptyPage(self, _): """@summary: Ajoute un onglet avec un stub perso dans le notebook0 """ self.addPage(readSaveFile("./persos/empty.json")) def deleteActiveNotePage(self): """@summary: Supprime l'onglet actif et les valeurs de personnages associés. """ nomPanneau = self.notebk.tab(self.notebk.select())["text"] indPanneau = int(nomPanneau.split(" ")[1]) self.notebk.forget(self.notebk.select()) del self.persoViews[indPanneau - 1] def addPage(self, values): """@summary: Ajoute un onglet avec les valeurs de personnages données. """ self.framesPersos.append(Frame(self.notebk)) framePerso = self.framesPersos[-1] self.persoViews.append(PersoView(values)) persoVw = self.persoViews[-1] self.caracsNotebk.append(Notebook(framePerso)) caracNotebk = self.caracsNotebk[-1] caracNotebk.pack() for inputsCategory, inputValues in persoVw.perso.items(): frameCaracs = LabelFrame(framePerso, text=inputsCategory) if persoVw.inputs.get(inputsCategory, None) is None: persoVw.inputs[inputsCategory] = dict() j = 0 for inputName, inputValue in inputValues.items(): if inputName == "Classe": classesDisponibles = \ Combobox(frameCaracs, textvariable=StringVar(), values=["Cra", "Xelor", "Iop", "Sram", "Poutch", "Eniripsa", "Pandawa"], state='readonly') persoVw.inputs[inputsCategory][ inputName] = classesDisponibles persoVw.inputs[inputsCategory][inputName].set(inputValue) else: persoVw.inputs[inputsCategory][inputName] = \ Entry(frameCaracs, textvariable=StringVar(), width=10) persoVw.inputs[inputsCategory][inputName].insert( END, inputValue) lblCarac = Label(frameCaracs, text=inputName + ":") lblCarac.grid(row=j, column=0) persoVw.inputs[inputsCategory][inputName].grid(row=j, column=1) j += 1 caracNotebk.add(frameCaracs, text=inputsCategory) # Pack de la fenêtre, détermine la taille de la fenêtre selon la taille des composants. #framePerso.pack(fill="both", expand="yes") self.notebk.add(framePerso, text="Perso " + str(len(self.persoViews))) saveBtn = Button(framePerso, text='Sauvegarder ce perso', command=persoVw.save) loadBtn = Button(framePerso, text='Charger un perso', command=persoVw.load) deleteThisBtn = Button(framePerso, text="Supprimer ce perso", command=self.deleteActiveNotePage) # Mise du bouton sur la droite de la fenetre saveBtn.pack(side="left") # Mise du bouton sur la droite de la fenetre loadBtn.pack(side="left") deleteThisBtn.pack(side="left") def main(self): """@summary: Lance la création des personnages pour ensuite lancer la simulation """ # Créer la fenêtre Tkinter values = readSaveFile("save.json") self.notebk.pack() for inputPerso in values: self.addPage(inputPerso) self.notebk.enable_traversal() # Ajout du bouton pour lancer la simulation submit = Button(self.fenetre, text='Lancer la simulation') # Permet au gestionnaire d'événement d'ajouter des paramètres # Gestionnaire d'événement pour le clic du bouton submit.bind("<Button-1>", self.formSubmission) # Mise du bouton sur la droite de la fenetre submit.pack(side="right") addPersoBtn = Button(self.fenetre, text='Ajouter un perso') addPersoBtn.bind("<Button-1>", self.addEmptyPage) addPersoBtn.pack(side="right")
class Main(object): def __init__(self, title): root = Tk() root.title(title) root.focus_set() root.rowconfigure(0, weight=0) root.columnconfigure(0, weight=1) root.rowconfigure(1, weight=1) self._root = root self.menubar = Frame(root) self.menubar.grid(row=0, column=0, sticky=(W, E)) self.menubar['takefocus'] = False quit_button = Button(self.menubar, text='Quit', command=self.quit) quit_button.grid(row=0, column=0) self._menucolumn = 1 self.views = list() self.paned_win = PanedWindow(root, orient=HORIZONTAL) self.paned_win.grid(row=1, column=0, sticky=(N, S, W, E)) self._query = None self._accept_func = None self.sidebar_views = dict() self.sidebar_count = 0 self.sidebar = PanedWindow(self.paned_win) self.paned_win.add(self.sidebar, weight=1) self.tabs = Notebook(self.paned_win) self.tabs.enable_traversal() self.paned_win.add(self.tabs, weight=5) self.root = self.tabs def add_menubutton(self, label, action): button = Button(self.menubar, text=label, command=action) button.grid(row=0, column=self._menucolumn) self._menucolumn += 1 def add_sidebar(self, view, name): self.sidebar_views[name] = view self.sidebar.add(view.widget, weight=1) view.widget.focus_set() self.sidebar_count += 1 if self.sidebar_count == 1: self.sidebar_views['main'] = view def remove_sidebar_view(self, name): self.sidebar.forget(self.sidebar_views[name].widget) self.sidebar_count -= 1 del self.sidebar_views[name] if self.sidebar_count == 0: del self.sidebar_views['main'] def get_sidebar_view(self, name): return self.sidebar_views.get(name) def focus_sidebar(self): if 'main' in self.sidebar_views.keys(): self.sidebar_views['main'].widget.focus_set() def focus_main_view(self): self.get_current_view().widget.focus_set() def new_view(self, view): self.views.append(view) self.tabs.add(view.widget, text=" {}.".format(self.tabs.index('end'))) self.tabs.select(view.widget) view.widget.focus_set() self.view_changed() def remove_view(self, view): self.views.remove(view) self.tabs.forget(view.widget) if len(self.views) >= 1: widget = self.views[-1].widget self.tabs.select(widget) widget.focus_set() else: self.sidebar_views['main'].widget.focus_set() self.view_changed() def delete_current_view(self, event): if self.tabs.index('end') > 0: self.remove_view(self.get_current_view()) def close_query(self): if self._query is not None: self._query.event_generate('<<MainQueryClose>>') self._query.destroy() self._query = None self._accept_func = None self._menucolumn -= 1 def accept_query(self, event): if self._query is not None: if self._accept_func is not None: self._accept_func(event.widget.get(), event.widget.original_value) self.close_query() else: event.widget.event_generate('<<MainQueryAccept>>') def text_query(self, query_lable, original_text=None, accept_func=None): if self._query is not None: return frame = Frame(self.menubar) label = Label(frame, text=query_lable) label.grid(column=0, row=0, sticky=(N, S)) self._accept_func = accept_func entry = Entry(frame) if original_text is not None: entry.insert(0, original_text) entry.original_value = original_text entry.grid(column=1, row=0, sticky=(N, S, W, E)) kb.make_bindings(kb.text_query, { 'accept': self.accept_query, 'cancel': lambda e: self.close_query() }, entry.bind) frame.grid(column=self._menucolumn, row=0) self._menucolumn += 1 entry.focus_set() self._query = frame def get_current_view(self): if self.tabs.index('end') > 0: return self.views[self.tabs.index('current')] else: return self.sidebar_views['main'] def view_changed(self): self._root.event_generate('<<MainViewChanged>>') def display(self): self._root.mainloop() def quit(self): self._root.destroy()
class Main(object): def __init__(self, title): root = Tk() root.title(title) root.focus_set() root.rowconfigure(0, weight=0) root.columnconfigure(0, weight=1) root.rowconfigure(1, weight=1) self._root = root self.menubar = Frame(root) self.menubar.grid(row=0, column=0, sticky=(W, E)) self.menubar['takefocus'] = False quit_button = Button(self.menubar, text='Quit', command=self.quit) quit_button.grid(row=0, column=0) self._menucolumn = 1 self.views = list() self.paned_win = PanedWindow(root, orient=HORIZONTAL) self.paned_win.grid(row=1, column=0, sticky=(N, S, W, E)) self._query = None self._accept_func = None self.sidebar_views = dict() self.sidebar_count = 0 self.sidebar = PanedWindow(self.paned_win) self.paned_win.add(self.sidebar, weight=1) self.tabs = Notebook(self.paned_win) self.tabs.enable_traversal() self.paned_win.add(self.tabs, weight=5) self.root = self.tabs def add_menubutton(self, label, action): button = Button(self.menubar, text=label, command=action) button.grid(row=0, column=self._menucolumn) self._menucolumn += 1 def add_sidebar(self, view, name): self.sidebar_views[name] = view self.sidebar.add(view.widget, weight=1) view.widget.focus_set() self.sidebar_count += 1 if self.sidebar_count == 1: self.sidebar_views['main'] = view def remove_sidebar_view(self, name): self.sidebar.forget(self.sidebar_views[name].widget) self.sidebar_count -= 1 del self.sidebar_views[name] if self.sidebar_count == 0: del self.sidebar_views['main'] def get_sidebar_view(self, name): return self.sidebar_views.get(name) def focus_sidebar(self): if 'main' in self.sidebar_views.keys(): self.sidebar_views['main'].widget.focus_set() def focus_main_view(self): self.get_current_view().widget.focus_set() def new_view(self, view): self.views.append(view) self.tabs.add(view.widget, text=" {}.".format(self.tabs.index('end'))) self.tabs.select(view.widget) view.widget.focus_set() self.view_changed() def remove_view(self, view): self.views.remove(view) self.tabs.forget(view.widget) if len(self.views) >= 1: widget = self.views[-1].widget self.tabs.select(widget) widget.focus_set() else: self.sidebar_views['main'].widget.focus_set() self.view_changed() def delete_current_view(self, event): if self.tabs.index('end') > 0: self.remove_view(self.get_current_view()) def close_query(self): if self._query is not None: self._query.event_generate('<<MainQueryClose>>') self._query.destroy() self._query = None self._accept_func = None self._menucolumn -= 1 def accept_query(self, event): if self._query is not None: if self._accept_func is not None: self._accept_func(event.widget.get(), event.widget.original_value) self.close_query() else: event.widget.event_generate('<<MainQueryAccept>>') def text_query(self, query_lable, original_text=None, accept_func=None): if self._query is not None: return frame = Frame(self.menubar) label = Label(frame, text=query_lable) label.grid(column=0, row=0, sticky=(N, S)) self._accept_func = accept_func entry = Entry(frame) if original_text is not None: entry.insert(0, original_text) entry.original_value = original_text entry.grid(column=1, row=0, sticky=(N,S,W,E)) kb.make_bindings(kb.text_query, {'accept': self.accept_query, 'cancel': lambda e: self.close_query()}, entry.bind) frame.grid(column=self._menucolumn, row=0) self._menucolumn += 1 entry.focus_set() self._query = frame def get_current_view(self): if self.tabs.index('end') > 0: return self.views[self.tabs.index('current')] else: return self.sidebar_views['main'] def view_changed(self): self._root.event_generate('<<MainViewChanged>>') def display(self): self._root.mainloop() def quit(self): self._root.destroy()
class translator(Tk): def __init__(self): super().__init__() self.title("Translator") self.geometry("500x300") self.langname = [] self.langcode = [] self.langans = [] self.langtab = [] self.langlabel = [] self.tab = [] self.tfname = None self.tfcode = None self.addwin = None self.dialog = None self.proxy = None self.proxyentry = None self.proxystate = 0 self.pwin = None self.menu = Menu(self, bg='lightgrey', fg='black') self.langmenu = Menu(self.menu, tearoff=0, bg='lightgrey', fg='black') self.langmenu.add_command(label="Add Language", command=self.addlang) self.proxymenu = Menu(self.menu, tearoff=0, bg='lightgrey', fg='black') self.proxymenu.add_command(label="Set Proxy", command=self.setproxy) self.menu.add_cascade(label='Languages', menu=self.langmenu) self.config(menu=self.menu) self.nb = Notebook(self) self.entab = Frame(self.nb) translatebutton = Button(self.entab, text='Translate', command=self.translate) translatebutton.pack(side=BOTTOM, fill=X) self.tf = Text(self.entab, bg='white', fg='black') self.tf.pack(side=TOP, fill=BOTH, expand=1) self.nb.add(self.entab, text='English') self.nb.pack(fill=BOTH, expand=1) self.delmenu = Menu(self.menu, tearoff=0, bg='lightgrey', fg='black') self.delmenu.add_command(label='Delete Tab', command=self.deltab) self.menu.add_cascade(label='Delete', menu=self.delmenu) self.delmenu.add_command(label='Delete Language', command=self.dellang) self.menu.add_cascade(label='Proxy', menu=self.proxymenu) if not os.path.isfile("lcodes.db"): self.conn = sqlite3.connect("lcodes.db") self.cur = self.conn.cursor() self.cur.execute('CREATE TABLE languages (name TEXT, code TEXT)') else: self.conn = sqlite3.connect("lcodes.db") self.cur = self.conn.cursor() self.cur.execute('SELECT * FROM languages ORDER BY name') self.fromdb() if os.path.isfile('proxy.txt'): f = open("proxy.txt", "rt") pr = f.readline() if len(pr) > 0: self.proxystate = 1 self.proxy = {"https": "https://" + pr} f.close() def addlang(self): self.addwin = Toplevel() self.addwin.title("Add Language") self.addwin.geometry("300x150") topframe = Frame(self.addwin, pady=10, height=70) midframe = Frame(self.addwin, pady=10, height=70) bottomframe = Frame(self.addwin) name = Label(topframe, text='Language Name', bg='lightgrey', fg='black', font=(20)) name.pack(side=LEFT, fill=BOTH, expand=1) self.tfname = Text(topframe, height=1, bg='white', fg='black', font=(20)) self.tfname.pack(side=RIGHT, fill=BOTH, expand=1) code = Label(midframe, text='Language Code', bg='lightgrey', fg='black', font=(20)) code.pack(side=LEFT, fill=BOTH, expand=1) self.tfcode = Text(midframe, height=1, bg='white', fg='black', font=(20)) self.tfcode.pack(side=RIGHT, fill=BOTH, expand=1) submit = Button(bottomframe, text='Add', bg='lightgrey', fg='black', pady=10, command=self.submitentry, font=(20)) submit.pack(fill=X) bottomframe.pack(side=BOTTOM, fill=X) midframe.pack(side=BOTTOM, fill=BOTH, expand=1) topframe.pack(side=TOP, fill=BOTH, expand=1, anchor=N) def submitentry(self): name = self.tfname.get(1.0, END).strip() code = self.tfcode.get(1.0, END).strip() if name and code: if (code in self.langcode) or (name in self.langname): showerror('Exists', 'Language alredy added') return self.langmenu.add_command(label=name, command=lambda: self.addtab(name)) self.langname.append(name) self.langcode.append(code) st = "INSERT INTO languages\nVALUES ('" + name + "', '" + code + "');" self.cur.execute(st) self.conn.commit() self.addwin.destroy() showinfo("Added", name + " is added successfully") else: showerror("Missing Info", "Please add both language name and code") def addtab(self, txt): ltab = Frame(self.nb) ans = StringVar(ltab) ans.set(txt + "translation") self.langlabel.append(ans) self.langtab.append(txt) self.langans.append(str(txt + "translation")) index = self.langtab.index(txt) button = Button(ltab, text='Copy to Clipboard', bg='lightgrey', fg='black', pady=10, command=lambda: self.copytoclip(self.langans[index])) button.pack(side=BOTTOM, fill=X) label = Label(ltab, textvar=ans, bg='lightgrey', fg='black') label.pack(side=TOP, fill=BOTH, expand=1) self.nb.add(ltab, text=txt) self.tab.append(ltab) def copytoclip(self, text): self.clipboard_clear() self.clipboard_append(text) showinfo('Copied', 'Message copied Successfully') def translate(self): que = self.tf.get(1.0, END) self.langans = [] err = 0 for i in self.langtab: index = self.langname.index(i) code = self.langcode[index] url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl={}&dt=t&q={}".format( code, que) try: if self.proxystate == 1: r = requests.get(url, proxies=self.proxy) else: r = requests.get(url) r.raise_for_status() self.langans.append(r.json()[0][0][0]) except Exception as e: showerror("Failed", "Failed for " + i + " error: " + str(e)) err = 1 if err == 0: showinfo("Successful", "Translation Successful") for i in range(0, len(self.langans)): self.langlabel[i].set(self.langans[i]) def deltab(self, text=None): if text: if not text in self.langtab: return index = self.langtab.index(text) tab = self.tab[index] self.nb.forget(tab) return if self.nb.select() != str(self.entab): target = None for i in self.tab: if self.nb.select() == str(i): target = i break index = self.tab.index(target) self.tab.remove(target) self.langlabel.pop(index) self.langtab.pop(index) self.langans.pop(index) self.nb.forget(self.nb.select()) else: showerror("Failed", "English tab can't be deleted") def dellang(self): self.dialog = Toplevel() self.dialog.title("Delete Language") self.dialog.geometry("150x100") button = Button(self.dialog, text='Delete', bg='lightgrey', fg='black', pady=10, font=(20), command=lambda: self.removelang(entry)) entry = Entry(self.dialog, bg='white', fg='black', font=(20)) label = Label(self.dialog, text='Language Name', bg='lightgrey', fg='black', pady=8, font=(20)) button.pack(side=BOTTOM, fill=X) entry.pack(side=BOTTOM, fill=X) label.pack(side=TOP, fill=BOTH, anchor=N) def removelang(self, entry): text = entry.get() if text: target = None for name in self.langname: if text.lower() == name.lower(): target = name break if not target: showerror("Not Found", "Language not found") return self.langmenu.delete(target) self.dialog.destroy() index = self.langname.index(target) code = self.langcode[index] self.langname.remove(target) self.langcode.remove(code) '''index=self.langtab.index(target) self.langtab.remove(target) self.tab.pop(index) self.langans.pop(index) self.langlabel.pop(index)''' st = 'DELETE FROM languages WHERE code = "' + code + '";' self.cur.execute(st) self.conn.commit() showinfo('Deleted', target + " deleted successfully") else: showerror('Blank', 'You had not entered anything') def fromdb(self): self.cur.execute('SELECT * FROM languages') data = self.cur.fetchall() for row in data: self.langname.append(row[0]) self.langcode.append(row[1]) self.langmenu.add_command(label=row[0], command=lambda: self.addtab(row[0])) def setproxy(self): self.pwin = Toplevel() self.pwin.title("Proxy") label = Label(self.pwin, text='proxy(hostname:port)', fg='black', bg='lightgrey') self.proxyentry = Entry(self.pwin, fg='black', bg='white') subbutton = Button(self.pwin, text='submit', fg='black', bg='lightgrey', command=lambda: self.applyproxy(1)) dupbutton = Button(self.pwin, text="Don't use proxy", fg='black', bg='lightgrey', command=lambda: self.applyproxy(0)) label.grid(row=0, column=0) self.proxyentry.grid(row=0, column=1) subbutton.grid(row=1, columnspan=2) dupbutton.grid(row=2, columnspan=2) def applyproxy(self, n): if n == 0: self.proxystate = 0 f = open("proxy.txt", "wt") f.write("") f.close() self.pwin.destroy() return proxy = self.proxyentry.get(1.0, END).strip() self.proxystate = 1 self.proxy = {"https": "https://" + proxy} f = open("proxy.txt", "wt") f.write(proxy) f.close() self.pwin.destroy()
class translator(Tk): def __init__(self): super().__init__() self.title("Translator") self.geometry("500x300") self.langname = [] self.langcode = [] self.langans = [] self.langtab = [] self.langlabel = [] self.tab = [] self.tfname = None self.tfcode = None self.addwin = None self.dialog = None self.menu = Menu(self, bg='lightgrey', fg='black') self.langmenu = Menu(self.menu, tearoff=0, bg='lightgrey', fg='black') self.langmenu.add_command(label="Add Language", command=self.addlang) self.menu.add_cascade(label='Languages', menu=self.langmenu) self.config(menu=self.menu) self.nb = Notebook(self) self.entab = Frame(self.nb) translatebutton = Button(self.entab, text='Translate', command=self.translate) translatebutton.pack(side=BOTTOM, fill=X) self.tf = Text(self.entab, bg='white', fg='black') self.tf.pack(side=TOP, fill=BOTH, expand=1) self.nb.add(self.entab, text='English') self.nb.pack(fill=BOTH, expand=1) self.delmenu = Menu(self.menu, tearoff=0, bg='lightgrey', fg='black') self.delmenu.add_command(label='Delete Tab', command=self.deltab) self.menu.add_cascade(label='Delete', menu=self.delmenu) self.delmenu.add_command(label='Delete Language', command=self.dellang) def addlang(self): self.addwin = Toplevel() self.addwin.title("Add Language") self.addwin.geometry("300x150") topframe = Frame(self.addwin, pady=10, height=70) midframe = Frame(self.addwin, pady=10, height=70) bottomframe = Frame(self.addwin) name = Label(topframe, text='Language Name', bg='lightgrey', fg='black', font=(20)) name.pack(side=LEFT, fill=BOTH, expand=1) self.tfname = Text(topframe, height=1, bg='white', fg='black', font=(20)) self.tfname.pack(side=RIGHT, fill=BOTH, expand=1) code = Label(midframe, text='Language Code', bg='lightgrey', fg='black', font=(20)) code.pack(side=LEFT, fill=BOTH, expand=1) self.tfcode = Text(midframe, height=1, bg='white', fg='black', font=(20)) self.tfcode.pack(side=RIGHT, fill=BOTH, expand=1) submit = Button(bottomframe, text='Add', bg='lightgrey', fg='black', pady=10, command=self.submitentry, font=(20)) submit.pack(fill=X) bottomframe.pack(side=BOTTOM, fill=X) midframe.pack(side=BOTTOM, fill=BOTH, expand=1) topframe.pack(side=TOP, fill=BOTH, expand=1, anchor=N) def submitentry(self): name = self.tfname.get(1.0, END).strip() code = self.tfcode.get(1.0, END).strip() if name and code: self.langmenu.add_command(label=name, command=lambda: self.addtab(name)) self.langname.append(name) self.langcode.append(code) self.addwin.destroy() showinfo("Added", name + " is added successfully") else: showerror("Missing Info", "Please add both language name and code") def addtab(self, txt): ltab = Frame(self.nb) ans = StringVar(ltab) ans.set(txt + "translation") self.langlabel.append(ans) self.langtab.append(txt) self.langans.append(str(txt + "translation")) index = self.langtab.index(txt) button = Button(ltab, text='Copy to Clipboard', bg='lightgrey', fg='black', pady=10, command=lambda: self.copytoclip(self.langans[index])) button.pack(side=BOTTOM, fill=X) label = Label(ltab, textvar=ans, bg='lightgrey', fg='black') label.pack(side=TOP, fill=BOTH, expand=1) self.nb.add(ltab, text=txt) self.tab.append(ltab) def copytoclip(self, text): self.clipboard_clear() self.clipboard_append(text) showinfo('Copied', 'Message copied Successfully') def translate(self): que = self.tf.get(1.0, END).strip() self.langans = [] err = 0 for i in self.langtab: index = self.langname.index(i) code = self.langcode[index] url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl={}&dt=t&q={}".format( code, que) try: r = requests.get(url) r.raise_for_status() self.langans.append(r.json()[0][0][0]) except Exception as e: showerror("Failed", "Failed for " + i + " error: " + str(e)) err = 1 if err == 0: showinfo("Successful", "Translation Successful") for i in range(0, len(self.langans)): self.langlabel[i].set(self.langans[i]) def deltab(self, text=None): if text: index = self.langtab.index(text) tab = self.tab[index] self.nb.forget(tab) return if self.nb.select() != str(self.entab): self.nb.forget(self.nb.select()) else: showerror("Failed", "English tab can't be deleted") def dellang(self): self.dialog = Toplevel() self.dialog.title("Delete Language") self.dialog.geometry("150x100") button = Button(self.dialog, text='Delete', bg='lightgrey', fg='black', pady=10, font=(20), command=lambda: self.removelang(entry)) entry = Entry(self.dialog, bg='white', fg='black', font=(20)) label = Label(self.dialog, text='Language Name', bg='lightgrey', fg='black', pady=8, font=(20)) button.pack(side=BOTTOM, fill=X) entry.pack(side=BOTTOM, fill=X) label.pack(side=TOP, fill=BOTH, anchor=N) def removelang(self, entry): text = entry.get() if text: target = None for name in self.langname: if text.lower() == name.lower(): target = name break if not target: showerror("Not Found", "Language not found") return self.langmenu.delete(target) self.deltab(target) self.dialog.destroy() showinfo('Deleted', target + " deleted successfully") else: showerror('Blank', 'You had not entered anything')
class App(tk.Tk): window = None def get_title(self, info): return "Музыка {} {} (id{})".format(info["first_name"], info["last_name"], info["id"]) def __init__(self, audio_obj, vk_audio, info): #initialize self if (App.window is not None): return super().__init__() self.vk_audio = vk_audio self.geometry('733x450') self.columnconfigure(0, weight=1) self.count, self.SortDir, self.player_window = False, True, None #initialize notebook self.tabs = Notebook(self) self.tabs.place(x=0, y=0, relwidth=1, relheight=1) self.tabs.bind('<<NotebookTabChanged>>', self.tab_changed) self.list = [] self.add_tab(audio_obj, info) App.window = self def add_tab(self, audio: vk_audio.Audio, info): if (audio in self.list): self.tabs.select(self.list.index(audio)) return title = self.get_title(info) f = tk.Frame(self.tabs) tk.Button(f, text="Закрыть", command=self.on_close_tab_clicked).pack() #add_albums_frame if (audio.Playlists): AlbumsFrame(f, audio.Playlists, self.add_tab_playlist, self.author_clicked).pack(side=tk.TOP, fill=tk.BOTH, expand=False) #add_audios_frame AudiosFrame(f, audio.Audios, True).pack(fill=tk.BOTH, expand=True, side=tk.BOTTOM) self.tabs.add(f, text=title) self.list.append(audio) self.focus_force() self.tabs.select(len(self.list) - 1) return self def on_close_tab_clicked(self): t = self.tabs.select() index = self.tabs.tabs().index(t) self.list.pop(index) if (not self.list): self.destroy() self.tabs.forget(t) def tab_changed(self, event): tab = self.tabs.tab( event.widget.index("current" ) if not isinstance(event, int) else event) self.title(tab['text']) def add_tab_playlist(self, playlist: vk_audio.Playlist): if (playlist in self.list): self.tabs.select(self.list.index(playlist)) return self.list.append(playlist) title = "Плейлист {} (id{})".format(playlist.title, playlist.owner_id) f = tk.Frame(self.tabs) tk.Button(f, text="Закрыть", command=self.on_close_tab_clicked).pack() #region add playlist info tk.Label(f, text=playlist.title, font=('times', 16)).pack() author = tk.Label(f, text=",".join(i['name'] for i in playlist.author_info), font=AlbumsFrame.DEFAULT_FONT, fg=AlbumsFrame.DEF_FG, cursor="hand2") author.pack() author.bind("<Button-1>", lambda _: self.author_clicked(playlist)) author.bind( "<Enter>", lambda _: author.config(font=AlbumsFrame.HOVER_FONT, fg=AlbumsFrame.HOVER_FG)) author.bind( "<Leave>", lambda _: author.config(font=AlbumsFrame.DEFAULT_FONT, fg=AlbumsFrame.DEF_FG)) img = tk.Canvas(f, width=160, height=160) img.pack(pady=5) AlbumsFrame.set_image_from_album(None, img, playlist) #endregion AudiosFrame(f, playlist.Audios, True).pack(fill=tk.BOTH, expand=True, side=tk.BOTTOM) self.tabs.add(f, text=title) self.focus_force() self.tabs.select(len(self.list) - 1) def author_clicked(self, playlist): if (playlist.author_hrefs): for i, item in enumerate(self.list): if (isinstance(item, vk_audio.Audio) and item.owner_id == playlist.owner_id): self.tabs.select(i) break else: artist_music = playlist.artist_music(0) self.add_tab( artist_music, { "first_name": artist_music.nick, "last_name": "", "id": artist_music.owner_id }) elif (playlist.owner_id > 0): for i, item in enumerate(self.list): if (isinstance(item, vk_audio.Audio) and item.owner_id == playlist.owner_id): self.tabs.select(i) break else: self.add_tab(self.vk_audio.load(playlist.owner_id)) else: messagebox.showerror("Ошибка", "Пока брать музыку у артиста(") def destroy(self): if (App.window is self): App.window = None return super().destroy() @staticmethod def get(item=None, owner_id=None, vk_audio=None, info=None): if (item is None and vk_audio is not None): item = vk_audio.load(owner_id=owner_id) return App( audio_obj=item, info=info, vk_audio=vk_audio) if App.window is None else App.window.add_tab( item, info)
class CimApp(Frame): def __init__(self): Frame.__init__(self) self.file = None; self.master.title("Tiborcim") self.master.iconphoto(True, PhotoImage(file=ICON_PNG)) self.files = [] self.current_tab = StringVar() self.pack(expand=1, fill="both") self.master.minsize(300,300) self.master.geometry("500x500") self.menubar = Menu(self.master) self.fileMenu = Menu(self.master, tearoff=0) self.fileMenu.add_command(label="New", command=self.new_file, underline=0, accelerator="Ctrl+N") self.fileMenu.add_command(label="Open...", command=self.load_file, underline=0, accelerator="Ctrl+O") self.fileMenu.add_command(label="Save", command=self.file_save, underline=0, accelerator="Ctrl+S") self.fileMenu.add_command(label="Save As...", command=self.file_save_as, underline=5, accelerator="Ctrl+Alt+S") self.fileMenu.add_command(label="Close", command=self.close_file, underline=0, accelerator="Ctrl+W") self.fileMenu.add_separator() self.fileMenu.add_command(label="Exit", command=self.file_quit, underline=1) self.menubar.add_cascade(label="File", menu=self.fileMenu, underline=0) self.edit_program = Menu(self.master, tearoff=0) self.edit_program.add_command(label="Undo", command=self.edit_undo, underline=0, accelerator="Ctrl+Z") self.edit_program.add_command(label="Redo", command=self.edit_redo, underline=0, accelerator="Ctrl+Y") self.edit_program.add_separator() self.edit_program.add_command(label="Cut", command=self.edit_cut, underline=2, accelerator="Ctrl+X") self.edit_program.add_command(label="Copy", command=self.edit_copy, underline=0, accelerator="Ctrl+C") self.edit_program.add_command(label="Paste", command=self.edit_paste, underline=0, accelerator="Ctrl+V") self.menubar.add_cascade(label="Edit", menu=self.edit_program, underline=0) self.menu_program = Menu(self.master, tearoff=0) self.menu_program.add_command(label="Convert", command=self.convert_file, underline=0, accelerator="Ctrl+T") self.menu_program.add_command(label="Flash", command=self.flash_file, underline=0, accelerator="Ctrl+B") self.menu_program.add_separator() self.menubar.add_cascade(label="Program", menu=self.menu_program, underline=0) self.menu_view = Menu(self.master, tearoff=0) self.viewmode = StringVar() self.viewmode.set("tiborcim") self.menu_view.add_radiobutton(label="Tiborcim", command=self.view_tiborcim, variable=self.viewmode, value="tiborcim", underline=0) self.menu_view.add_radiobutton(label="Python", command=self.view_python, variable=self.viewmode, value="python", underline=0) self.menubar.add_cascade(label="View", menu=self.menu_view, underline=0) self.menu_help = Menu(self.master, tearoff=0) self.menu_samples = Menu(self.master, tearoff=0) samples = tiborcim.resources.samples_list() def add_sample (sample): self.menu_samples.add_command(label=sample, command=lambda: self.help_sample(sample)) for sample in samples: add_sample(sample) self.menu_help.add_cascade(label="Samples", menu=self.menu_samples, underline=0) self.menu_help.add_separator() self.menu_help.add_command(label="README", command=self.help_readme, underline=0) self.menu_help.add_separator() self.menu_help.add_command(label="About", command=self.help_about, underline=0) self.menubar.add_cascade(label="Help", menu=self.menu_help, underline=0) self.master.config(width=450, height=400, menu=self.menubar) self.bind_all("<Control-o>", self.load_file) self.bind_all("<Control-s>", self.file_save) self.bind_all("<Control-Alt-s>", self.file_save_as) self.bind_all("<Control-t>", self.convert_file) self.bind_all("<Control-b>", self.flash_file) self.bind_all("<Control-w>", self.close_file) self.master.protocol("WM_DELETE_WINDOW", self.file_quit) self.file_tabs = Notebook(self) self.file_tabs.bind_all("<<NotebookTabChanged>>", self.file_changed) self.file_tabs.pack(expand=1, fill="both") def file_changed(self, event): if len(self.file_tabs.tabs()) <= 0: self.add_file() return title = str(event.widget.tab(event.widget.index("current"),"text")).upper().strip() self.menu_program.delete(3, END) for tab in self.file_tabs.tabs(): tabtext = self.file_tabs.tab(self.file_tabs.index(tab),"text") if tabtext.upper().strip() == title: self.current_tab.set(tab) self.menu_program.add_radiobutton(label=tabtext, command=self.program_switch, underline=1, value=tab, variable=self.current_tab) if title != "PYTHON" or title != "TIBORCIM": if self.current_file().filename is not None: self.master.title(self.current_file().get_file() + " - Tiborcim") else: self.master.title("Tiborcim") if str(self.current_file().tab(self.current_file().index("current"),"text")).upper().strip() == "TIBORCIM": self.menubar.entryconfig("Edit", state=NORMAL) else: self.menubar.entryconfig("Edit", state=DISABLED) self.viewmode.set(self.current_file().viewmode) if title == "PYTHON": self.menubar.entryconfig("Edit", state=DISABLED) self.current_file().viewmode = "python"; self.viewmode.set("python"); if title == "TIBORCIM": self.menubar.entryconfig("Edit", state=NORMAL) self.current_file().viewmode = "tiborcim"; self.viewmode.set("tiborcim"); def add_file(self, file=None): filepage = CimFilePage(self.file_tabs) if file is None: self.file_tabs.add(filepage, text="Unsaved Program") else: filepage.load_file(file) self.file_tabs.add(filepage, text=filepage.get_file()) self.files.append(filepage) self.file_tabs.select(filepage) def view_tiborcim(self, event=None): self.current_file().view_tiborcim() def view_python(self, event=None): self.current_file().view_python() def program_switch(self): self.file_tabs.select(self.current_tab.get()) def new_file(self, event=None): self.add_file() def load_file(self, event=None): fname = askopenfilename(filetypes=(("Tiborcim", "*.tibas"),("All files", "*.*") ), parent=self.master) if fname: self.add_file(fname) def file_save(self, event=None): self.current_file().save_file() self.file_tabs.tab(self.current_file(), text=self.current_file().get_file()) def file_save_as(self, event=None): self.current_file().save_file_as() self.file_tabs.tab(self.current_file(), text=self.current_file().get_file()) def convert_file(self, event=None): self.current_file().convert_file() def current_file(self, event=None): return self.files[int(self.file_tabs.index(self.file_tabs.select()))] def flash_file(self, event=None): from tiborcim.tibc import compiler as tibc from tiborcim.tibc import flash from tiborcim.tibc import TibcStatus as status com = tibc(self.current_file().text_tiborcim.get("1.0", "end")) res = flash(''.join(com.output)) if res is status.SUCCESS: showinfo(title='Success', message='File Flashed', parent=self.master) else: showerror(title='Failure', message='An Error Occured. Code: %s' % res, parent=self.master) def close_file(self, event=None): logging.debug("Close File") file = self.current_file() if file.close(): self.file_tabs.forget(file) self.files.remove(file) def edit_cut(self, event=None): self.current_file().text_tiborcim.event_generate('<Control-x>') def edit_copy(self, event=None): self.current_file().text_tiborcim.event_generate('<Control-c>') def edit_paste(self, event=None): self.current_file().text_tiborcim.event_generate('<Control-v>') def edit_redo(self, event=None): self.current_file().text_tiborcim.edit_redo() def edit_undo(self, event=None): self.current_file().text_tiborcim.edit_undo() def help_about(self, event=None): CimAbout.show(self) def help_readme(self, event=None): CimReadme.show(self) def help_sample(self, sam): print(sam) filepage = CimFilePage(self.file_tabs) filepage.load_file(tiborcim.resources.sample_path(sam)) filepage.filename = None self.file_tabs.add(filepage, text="Unsaved Program") self.files.append(filepage) self.file_tabs.select(filepage) def file_quit(self, event=None): for ndx, member in enumerate(self.files): logging.debug(self.files[ndx].saved) if not self.files[ndx].close(): return self.quit()
class WorkTimer: def __init__(self, master): # initialize the master self.master = master master.title("SDL Work Timer") # timer counter self.timers = 0 # master dictionary # this will contain indexed dictionaries representing instances of # the work timer. Those dictionaries will contain timers so that the clocks remain separate. ''' { 'notebook1': { 'masterframe': masterframe, # this is the frame containing the entire timer 'timer': timerobject, # this is the timer object, holding timer # functions and numbers 'toggle_button', timer_toggler, # needs to be accessible to alter color 'date': date_label, 'hours': hour_label, 'mins': min_label, 'secs': second_label, 'desc': short_text, 'filename': filename_entry, 'todo': todo_editor, 'done': done_editor, 'notes': notes_editor, }, } ''' self.timer_dict = {} self.timerframe = Frame(self.master, padx=10, pady=10) self.systemframe = Frame(self.master, padx=10, pady=10) self.timer_notebook = Notebook(self.timerframe) self.create_timer(self.timer_dict, self.timer_notebook) # <> system frame elements <> # instantiate system frame elements self.new_timer_button = Button( self.systemframe, width=10, text='New timer', command=lambda: self.create_timer(self.timer_dict, self. timer_notebook)) self.system_label = Label(self.systemframe, text='System:', anchor=W) self.system_output = Label(self.systemframe, text='Loading...', anchor=W) self.system_copyright = Label( self.systemframe, text='Designed and Developed by Stardust Labs', anchor=E) # grid system frame elements self.system_label.grid(row=0, column=0, sticky=W) self.system_output.grid(row=0, column=1) self.new_timer_button.grid(row=0, column=2) self.system_copyright.grid(row=1, column=0, columnspan=3, sticky=E) # grid master elements self.timer_notebook.grid() self.timerframe.grid(row=0, column=0) self.systemframe.grid(row=1, column=0) self.tick() self.system_output.config(text='Ready') def create_timer(self, timer_dict, notebook): # name the timer and instantiate it within the master dictionary self.timers += 1 name = 'notebook' + str(self.timers) self.timer_dict[name] = {} this_timer = self.timer_dict[name] this_timer['id'] = self.timers # initialize dictionary abstractions this_timer['masterframe'] = Frame(notebook, padx=5, pady=5) masterframe = this_timer['masterframe'] this_timer['timer'] = Timer() # frames used to contain timer elements timerframe = Frame(masterframe, padx=10, pady=10) textframe = Frame(masterframe, padx=10, pady=10) # <> Timerframe Elements <> # instantiate timer buttons this_timer['toggle_button'] = Button( timerframe, width=9, text="Start", background='#f00', command=lambda: this_timer['timer'].toggle_timer(this_timer)) timer_reset_button = Button( timerframe, width=9, text='Reset', command=lambda: this_timer['timer'].reset(this_timer)) save_timelog_button = Button( timerframe, width=9, text='Save', command=lambda: self.save_timelog(this_timer)) # container frame for output, will be inline with other items timer_outputframe = Frame(timerframe) # instantiate output items date_label = Label(timer_outputframe, text='Date:', anchor=W) this_timer['date'] = Label(timer_outputframe, text=str(this_timer['timer'].output_date)) hour_label = Label(timer_outputframe, text='Hour:', anchor=W) this_timer['hours'] = Label(timer_outputframe, text=str(this_timer['timer'].output_hour)) min_label = Label(timer_outputframe, text='Min:', anchor=W) this_timer['mins'] = Label(timer_outputframe, text=str(this_timer['timer'].output_min)) sec_label = Label(timer_outputframe, text='Sec:', anchor=W) this_timer['secs'] = Label(timer_outputframe, text=str(this_timer['timer'].output_sec)) # grid output items to timer_outputframe so it can be grid later date_label.grid(row=0, column=0, sticky=W) hour_label.grid(row=1, column=0, sticky=W) min_label.grid(row=2, column=0, sticky=W) sec_label.grid(row=3, column=0, sticky=W) this_timer['date'].grid(row=0, column=1, sticky=E) this_timer['hours'].grid(row=1, column=1, sticky=E) this_timer['mins'].grid(row=2, column=1, sticky=E) this_timer['secs'].grid(row=3, column=1, sticky=E) # instantiate description label and entry description_label = Label(timerframe, text='Desc:', anchor=E) this_timer['desc'] = Entry(timerframe) def change_tab(event, self=self, tab_id=this_timer['id'] - 1, entry=this_timer['desc']): return self.update_tab(event, tab_id, entry) this_timer['desc'].bind('<KeyRelease>', change_tab) # grid timerframe elements this_timer['toggle_button'].grid(row=0, column=0, pady=5) timer_reset_button.grid(row=1, column=0, pady=5) save_timelog_button.grid(row=2, column=0, pady=5) timer_outputframe.grid(row=3, column=0, pady=5) description_label.grid(row=4, column=0, sticky=W) this_timer['desc'].grid(row=5, column=0) # <> Textframe Elements <> filename_frame = Frame(textframe) text_editor_frame = Notebook(textframe) text_system_frame = Frame(textframe) # instantiate filename_frame elements filename_label = Label(filename_frame, text='Filename:') this_timer['filename'] = Entry(filename_frame, width=50) # grid filename_frame elements filename_label.grid(row=0, column=0) this_timer['filename'].grid(row=0, column=1) # instantiate text editors this_timer['todo'] = Text(text_editor_frame, font=('consolas', '10'), width=75, height=17) this_timer['done'] = Text(text_editor_frame, font=('consolas', '10'), width=75, height=17) this_timer['notes'] = Text(text_editor_frame, font=('consolas', '10'), width=75, height=17) # grid text editors and add them to the notebook this_timer['todo'].grid(padx=5) this_timer['done'].grid(padx=5) this_timer['notes'].grid(padx=5) text_editor_frame.add(this_timer['todo'], text='TODO') text_editor_frame.add(this_timer['done'], text='DONE') text_editor_frame.add(this_timer['notes'], text='NOTES') # instantiate text system elements text_save_button = Button(text_system_frame, text='Save Report', command=lambda: self.save_report(this_timer), anchor=E) text_load_button = Button(text_system_frame, text='Load Report', command=lambda: self.load_report(this_timer), anchor=E) # grid text system elements text_save_button.grid(row=0, column=0, padx=5, pady=5, sticky=E) text_load_button.grid(row=0, column=1, padx=5, pady=5, sticky=E) # instantiate notebook delete button timer_delete_button = Button( text_system_frame, text='Delete Timer', command=lambda: self.destroy_timer(this_timer), anchor=E) # grid notebook delete button timer_delete_button.grid(row=0, column=2, padx=5, pady=5, sticky=E) # grid all textframe internal frames filename_frame.grid(row=0, column=0) text_editor_frame.grid(row=1, column=0) text_system_frame.grid(row=2, column=0) # grid submaster frames timerframe.grid(row=0, column=0) textframe.grid(row=0, column=1) # add the timer to the main notebook this_timer['masterframe'].grid() notebook.add(this_timer['masterframe'], text='New Timer') def destroy_timer(self, timer): name = timer['desc'].get() title = 'Deleting timer {timer_name}'.format(timer_name=name) message = 'Are you sure you want to delete {timer_name}?'.format( timer_name=name) destroy = messagebox.askquestion(title, message) if destroy: self.timer_notebook.forget(timer['masterframe']) def save_timelog(self, timer): self.system_update( 'Logging {desc} time...'.format(desc=timer['desc'].get())) description = timer['desc'].get() time = '{date} {h}:{m}:{s} - {desc}\r\n'.format( date=timer['timer'].output_date, h=timer['timer'].output_hour, m=timer['timer'].output_min, s=timer['timer'].output_sec, desc=description, ) with open('timelog.txt', 'a') as timelog: timelog.write(time) self.system_update( '{desc} time logged.'.format(desc=timer['desc'].get())) def save_report(self, timer): self.system_update( 'Saving {desc} report...'.format(desc=timer['desc'].get())) todo_header = '---=== TODO ===---\r\n\r\n' done_header = '---=== DONE ===---\r\n\r\n' notes_header = '---=== NOTES ===---\r\n\r\n' todo_body = timer['todo'].get('1.0', END) done_body = timer['done'].get('1.0', END) notes_body = timer['notes'].get('1.0', END) output_text = '{todo_h}{todo}\r\n\r\n{done_h}{done}\r\n\r\n{notes_h}{notes}'.format( todo_h=todo_header, todo=todo_body, done_h=done_header, done=done_body, notes_h=notes_header, notes=notes_body, ) filename = timer['filename'].get() with open('reports/' + filename + '.txt', 'w') as report: report.write(output_text) self.system_update( '{desc} report saved.'.format(desc=timer['desc'].get())) def load_report(self, timer): self.system_update( 'Loading {file}'.format(file=timer['filename'].get())) filename = timer['filename'].get() with open(filename + '.txt', 'r') as report: input_text = report.read() input_text = input_text.split('---=== DONE ===---') todo_text = input_text[0] input_text = input_text[1].split('---=== NOTES ===---') done_text = input_text[0] notes_text = input_text[1] todo_text = todo_text.replace('---=== TODO ===---', '').replace('\r\n', '') done_text = done_text.replace('\r\n', '') notes_text = notes_text.replace('\r\n', '') timer['todo'].delete('1.0', END) timer['todo'].insert(END, todo_text) timer['done'].delete('1.0', END) timer['done'].insert(END, done_text) timer['notes'].delete('1.0', END) timer['notes'].insert(END, notes_text) self.system_update( '{file} loaded.'.format(file=timer['filename'].get())) def tick(self): for work_timer in self.timer_dict: self.timer_dict[work_timer]['timer'].tick( self.timer_dict[work_timer]) self.systemframe.after(1000, self.tick) def update_tab(self, event, tab_id, entry_widget): updated_title = entry_widget.get() self.timer_notebook.tab(tab_id, text=updated_title) def system_update(self, sys_text): self.system_output.config(text=sys_text)
class OpeningPage(): """@summary: Widget servant à lancer la simulation après avoir renseigné les persos """ def __init__(self, fenetre): self.notebk = Notebook(fenetre) self.fenetre = fenetre self.persoViews = [] self.caracsNotebk = [] self.framesPersos = [] def formSubmission(self, _): """@summary: Lance la simulation de combat avec les persos du notebook """ persos = [] for persoVw in self.persoViews: persoVw.inputsToPerso() persos.append(persoVw.perso) writeSaveFile("save.json", persos) launchSimu(self.persoViews) def addEmptyPage(self, _): """@summary: Ajoute un onglet avec un stub perso dans le notebook0 """ self.addPage(readSaveFile("./persos/empty.json")) def deleteActiveNotePage(self): """@summary: Supprime l'onglet actif et les valeurs de personnages associés. """ nomPanneau = self.notebk.tab(self.notebk.select())["text"] indPanneau = int(nomPanneau.split(" ")[1]) self.notebk.forget(self.notebk.select()) del self.persoViews[indPanneau-1] def addPageSorts(self, persoVw, sortsSuppl=[], sortsDebtCombatSuppl=[]): tab_names = [persoVw.caracsNotebk.tab(i, option="text") for i in persoVw.caracsNotebk.tabs()] if "Sorts" in tab_names: persoVw.caracsNotebk.forget(tab_names.index("Sorts")) classe = persoVw.perso["Perso"]["Classe"] lvl = persoVw.perso["Perso"]["Level"] frameSorts = LabelFrame(persoVw.framePerso, text="Sorts") sorts, sortsDebtCombat = Personnages.Personnage.chargerSorts(classe, lvl, {}, True) sorts += sortsSuppl sortsDebtCombat += sortsDebtCombatSuppl for extSort in [x for x in persoVw.perso["Sorts"] if "::" in x]: classe, nom_sort = extSort.split("::") sortsSuppl, sortsDebtCombatSuppl = Personnages.Personnage.chargerSorts(classe, lvl, {nom_sort:1}, False, 1) for sortSuppl in sortsSuppl: sortSuppl.nom = classe+"::"+nom_sort for sortDebtCombatSuppl in sortsDebtCombatSuppl: sortDebtCombatSuppl.nom = classe+"::"+nom_sort sorts += sortsSuppl sortsDebtCombat += sortsDebtCombatSuppl self.variantesFrame = ScrolledWindow(frameSorts, width=400, height=400) persoVw.sortsLignes = 0 persoVw.images = [] if "Sorts" not in persoVw.inputs: persoVw.inputs["Sorts"] = dict() addedSpells = {} for sort in sorts+sortsDebtCombat: if not sort.lancableParJoueur: continue isVariante = sort.nom_variante != "" and sort.nom_variante in addedSpells root_pic1 = Image.open(sort.image) # Open the image like this first persoVw.images.append(ImageTk.PhotoImage(root_pic1)) if not isVariante: persoVw.sortsLignes += 1 ind = persoVw.sortsLignes imgLbl = Label(self.variantesFrame.scrollwindow, image=persoVw.images[-1], anchor="nw") imgLbl.grid(row=ind, column=2 if isVariante else 0, sticky="e") varSort = IntVar() varSort.set(persoVw.perso["Sorts"].get(sort.nom, 0)) persoVw.inputs["Sorts"][sort.nom] = varSort cbSort = Checkbutton(self.variantesFrame.scrollwindow, text=sort.nom, variable=varSort, onvalue=1, offvalue=0, anchor="w") cbSort.grid(row=ind, column=3 if isVariante else 1, sticky="w") addedSpells[sort.nom] = ind addSortButton = Button(frameSorts, text="Ajout Sort/Item", command=self.ajoutSort) addSortButton.grid() persoVw.caracsNotebk.add(frameSorts, text="Sorts") def ajoutSort(self): nomPanneau = self.notebk.tab(self.notebk.select())["text"] indPanneau = int(nomPanneau.split(" ")[1]) persoVw = self.persoViews[indPanneau-1] dialog = ChildDialogChooseSpell(self.fenetre, persoVw) self.fenetre.wait_window(dialog.app) filename, sort_name = tuple(dialog.rvalue.split("::")) perso = persoVw.perso classename = os.path.splitext(filename)[0] sorts, sortsDebtCombat = Personnages.Personnage.chargerSorts(classename, int(perso["Perso"]["Level"]), {sort_name:1}, False, 0) current = persoVw.caracsNotebk.index("current") for sort in sorts: sort.nom = filename+"::"+sort_name for sort in sortsDebtCombat: sort.nom = filename+"::"+sort_name self.addPageSorts(persoVw, sorts, sortsDebtCombat) persoVw.caracsNotebk.select(current) def onClassChange(self, event): nomPanneau = self.notebk.tab(self.notebk.select())["text"] indPanneau = int(nomPanneau.split(" ")[1]) persoVw = self.persoViews[indPanneau-1] self.addPageSorts(persoVw) def addPage(self, values): """@summary: Ajoute un onglet avec les valeurs de personnages données. """ self.persoViews.append(PersoView(values)) persoVw = self.persoViews[-1] self.framesPersos.append(Frame(self.notebk)) framePerso = self.framesPersos[-1] persoVw.framePerso = framePerso self.caracsNotebk.append(Notebook(framePerso)) caracNotebk = self.caracsNotebk[-1] caracNotebk.pack() persoVw.caracsNotebk = caracNotebk for inputsCategory, inputValues in persoVw.perso.items(): frameCaracs = LabelFrame(framePerso, text=inputsCategory) if persoVw.inputs.get(inputsCategory, None) is None: persoVw.inputs[inputsCategory] = dict() j = 0 if inputsCategory == "Sorts": self.addPageSorts(persoVw) continue for inputName, inputValue in inputValues.items(): if inputName == "Classe": classesDisponibles = \ Combobox(frameCaracs, textvariable=StringVar(), values=["Cra", "Xelor", "Iop", "Sacrieur", "Sram", "Poutch", "Eniripsa", "Pandawa"], state='readonly') classesDisponibles.bind('<<ComboboxSelected>>', self.onClassChange) persoVw.inputs[inputsCategory][inputName] = classesDisponibles persoVw.inputs[inputsCategory][inputName].set(inputValue) else: persoVw.inputs[inputsCategory][inputName] = \ Entry(frameCaracs, textvariable=StringVar(), width=10) persoVw.inputs[inputsCategory][inputName].insert(END, inputValue) lblCarac = Label(frameCaracs, text=inputName+":") lblCarac.grid(row=j, column=0) persoVw.inputs[inputsCategory][inputName].grid(row=j, column=1) j += 1 caracNotebk.add(frameCaracs, text=inputsCategory) # Pack de la fenêtre, détermine la taille de la fenêtre selon la taille des composants. #framePerso.pack(fill="both", expand="yes") self.notebk.add(framePerso, text="Perso "+str(len(self.persoViews))) saveBtn = Button(framePerso, text='Sauvegarder ce perso', command=persoVw.save) loadBtn = Button(framePerso, text='Charger un perso', command=persoVw.load) deleteThisBtn = Button(framePerso, text="Supprimer ce perso", command=self.deleteActiveNotePage) # Mise du bouton sur la droite de la fenetre saveBtn.pack(side="left") # Mise du bouton sur la droite de la fenetre loadBtn.pack(side="left") deleteThisBtn.pack(side="left") def main(self): """@summary: Lance la création des personnages pour ensuite lancer la simulation """ # Créer la fenêtre Tkinter values = readSaveFile("save.json") self.notebk.pack() for inputPerso in values: self.addPage(inputPerso) self.notebk.enable_traversal() # Ajout du bouton pour lancer la simulation submit = Button(self.fenetre, text='Lancer la simulation') # Permet au gestionnaire d'événement d'ajouter des paramètres # Gestionnaire d'événement pour le clic du bouton submit.bind("<Button-1>", self.formSubmission) # Mise du bouton sur la droite de la fenetre submit.pack(side="right") addPersoBtn = Button(self.fenetre, text='Ajouter un perso') addPersoBtn.bind("<Button-1>", self.addEmptyPage) addPersoBtn.pack(side="right")
class App(Tk): def __init__(self, args): Tk.__init__(self) self.height = '720' self.width = '1280' self.Editors = [] self.Filenames = {} self.lexer_selector = self.createLexers() self.Lexers = dict() self._icon = Image("photo", file='img/notebook/icon.png') self.code_font = Font(family="Latin Modern Mono", size=15) self.title_font = Font(family="Ubuntu Mono", size=15) self.underline_font = Font(underline=True) self.MainWindow = Frame(self, background='#282c34') self.notebook = Notebook(self) self.configureUI() self.args = args self.awk_img = PhotoImage(file='img/fext/awk.png') self.bash_img = PhotoImage(file='img/fext/bash.png') self.c_img = PhotoImage(file='img/fext/c.png') self.cs_img = PhotoImage(file='img/fext/c#.png') self.cmake_img = PhotoImage(file='img/fext/cmake.png') self.coffee_img = PhotoImage(file='img/fext/coffee.png') self.cpp_img = PhotoImage(file='img/fext/cpp.png') self.css_img = PhotoImage(file='img/fext/css.png') self.delphi_img = PhotoImage(file='img/fext/delphi.png') self.eiffel_img = PhotoImage(file='img/fext/eiffel.png') self.erlang_img = PhotoImage(file='img/fext/erlang.png') self.fs_img = PhotoImage(file='img/fext/f#.png') self.fortran_img = PhotoImage(file='img/fext/fortran.png') self.go_img = PhotoImage(file='img/fext/golang.png') self.haskell_img = PhotoImage(file='img/fext/haskell.png') self.html_img = PhotoImage(file='img/fext/html.png') self.java_img = PhotoImage(file='img/fext/java.png') self.js_img = PhotoImage(file='img/fext/js.png') self.json_img = PhotoImage(file='img/fext/json.png') self.kotlin_img = PhotoImage(file='img/fext/kotlin.png') self.lisp_img = PhotoImage(file='img/fext/lisp.png') self.makefile_img = PhotoImage(file='img/fext/makefile.png') self.matlab_img = PhotoImage(file='img/fext/matlab.png') self.mysql_img = PhotoImage(file='img/fext/mysql.png') self.perl_img = PhotoImage(file='img/fext/perl.png') self.php_img = PhotoImage(file='img/fext/php.png') self.prolog_img = PhotoImage(file='img/fext/prolog.png') self.python_img = PhotoImage(file='img/fext/python.png') self.ruby_img = PhotoImage(file='img/fext/ruby.png') self.sass_img = PhotoImage(file='img/fext/sass.png') self.scala_img = PhotoImage(file='img/fext/scala.png') self.swift_img = PhotoImage(file='img/fext/swift.png') self.tcl_img = PhotoImage(file='img/fext/tcl.png') self.ts_img = PhotoImage(file='img/fext/ts.png') self.txt_img = PhotoImage(file='img/fext/txt.png') self.verilog_img = PhotoImage(file='img/fext/verilog.png') self.vhdl_img = PhotoImage(file='img/fext/vhdl.png') self.xml_img = PhotoImage(file='img/fext/xml.png') self.yaml_img = PhotoImage(file='img/fext/yaml.png') for file_name in self.args: self.openFileByName(file_name) self.mainloop() def configureUI(self): self.configureWindow() self.configureMenu() self.configureNotebook() self.contextualMenu() self.bindWindowEvents() self.configureStatusBar() def configureWindow(self): self.geometry(self.width+'x'+self.height+'+0+0') self.title("Quode-IDE") self.wm_iconphoto(False, self._icon) self.MainWindow.pack() def configureMenu(self): self.menu_bar = Menu(self, background='#21252b', foreground='#ffffff') self.file_menu = Menu(self.menu_bar, tearoff=0) self.file_menu.add_command(label='New Tab', font=self.title_font, command=self.createNewEditor, activebackground='#123456', activeforeground='#ffffff', accelerator='Ctrl + N') self.file_menu.add_command(label="Open", font=self.title_font, command=self.openFile, activebackground='#123456', activeforeground='#ffffff', accelerator='Ctrl + O') self.file_menu.add_command(label="Save", font=self.title_font, command=self.saveFile, activebackground='#123456', activeforeground='#ffffff', accelerator='Ctrl + S') self.file_menu.add_command(label='Remove Tab', font=self.title_font, command=self.removeCurrentEditor, activebackground='#123456', activeforeground='#ffffff', accelerator='Ctrl + R') self.file_menu.add_separator() self.file_menu.add_command(label="Exit", font=self.title_font, command=self.askQuit, activebackground='#123456', activeforeground='#ffffff', accelerator='Ctrl + Q') self.menu_bar.add_cascade(label="File", font=self.title_font, activebackground='#123456', activeforeground='#ffffff', menu=self.file_menu) self.edit_menu = Menu(self.menu_bar, tearoff=0, activebackground='#123456') self.edit_menu.add_command(label="Cut", font=self.title_font, command=self.cutSelection, activebackground='#123456', activeforeground='#ffffff', accelerator="Ctrl + X") self.edit_menu.add_command(label="Copy", font=self.title_font, command=self.copySelection, activebackground='#123456', activeforeground='#ffffff', accelerator="Ctrl + C") self.edit_menu.add_command(label="Paste", font=self.title_font, command=self.pasteSelection, activebackground='#123456', activeforeground='#ffffff', accelerator="Ctrl + V") self.edit_menu.add_command(label="Replace (All)", font=self.title_font, activebackground='#123456', activeforeground='#ffffff', command=self.replaceAllWindow) self.menu_bar.add_cascade(label="Edit", font=self.title_font, activebackground='#123456', activeforeground='#ffffff', menu=self.edit_menu) self.view_menu = Menu(self.menu_bar, tearoff=0) self.view_menu.add_command(label="Increase Font Size", font=self.title_font, command=self.increaseFontSize, activebackground='#123456', activeforeground='#ffffff', accelerator="Ctrl + +/=") self.view_menu.add_command(label="Decrease Font Size", font=self.title_font, command=self.decreaseFontSize, activebackground='#123456', activeforeground='#ffffff', accelerator="Ctrl + -/_") self.view_menu.add_command(label="Find", font=self.title_font, command=self.searchWindow, activebackground='#123456', activeforeground='#ffffff', accelerator="Ctrl + f") self.view_menu.add_command(label="File tree", font=self.title_font, command=self.showFileTree, activebackground='#123456', activeforeground='#ffffff', accelerator="Ctrl + t") self.menu_bar.add_cascade(label="View", font=self.title_font, activebackground='#123456', activeforeground='#ffffff', menu=self.view_menu) self.run_menu = Menu(self.menu_bar, tearoff=0) self.run_menu.add_command(label='Run', activebackground='#123456', activeforeground='#ffffff', command=self.runCurrentEditor, font=self.title_font) self.menu_bar.add_cascade(label='Run', activebackground='#123456', activeforeground='#ffffff', font=self.title_font, menu=self.run_menu) self.help_menu = Menu(self.menu_bar, tearoff=0) self.help_menu.add_command(label="About", activebackground='#123456', activeforeground='#ffffff', font=self.title_font, command=self.printAbout) self.menu_bar.add_cascade(label="Help", font=self.title_font, activebackground='#123456', activeforeground='#ffffff', menu=self.help_menu) self.config(menu=self.menu_bar) def configureNotebook(self): self.notebook.place_configure(relx=0, rely=0, relheight=0.97, relwidth=1) self.notebook.enable_traversal() def configureStatusBar(self): self.status_bar_label = Label(self) self.status_bar_label.place_configure(relx=0, rely=0.97, relheight=0.03, relwidth=1) self.status_bar_label.config(text=self.getStatusText()) def langImg(self, ext): img = None if (ext == '.c'): img = self.c_img elif(ext == '.h'): img = self.c_img elif(ext == '.cpp'): img = self.cpp_img elif(ext == '.hpp'): img = self.cpp_img elif(ext == '.css'): img = self.css_img elif(ext == '.sass'): img = self.sass_img elif(ext == '.yaml'): img = self.yaml_img elif(ext == '.yml'): img = self.yaml_img elif(ext == '.json'): img = self.json_img elif(ext == '.cs'): img = self.cs_img elif(ext == '.fs'): img = self.fs_img elif(ext == '.e'): img = self.eiffel_img elif(ext == '.erl'): img = self.erlang_img elif(ext == '.hrl'): img = self.erlang_img elif(ext == '.es'): img = self.erlang_img elif(ext == '.f03'): img = self.fortran_img elif(ext == '.f90'): img = self.fortran_img elif(ext == '.F03'): img = self.fortran_img elif(ext == '.F90'): img = self.fortran_img elif(ext == '.go'): img = self.go_img elif(ext == '.hs'): img = self.haskell_img elif(ext == '.v'): img = self.verilog_img elif(ext == '.vhdl'): img = self.vhdl_img elif(ext == '.vhd'): img = self.vhdl_img elif(ext == '.html'): img = self.html_img elif(ext == '.htm'): img = self.html_img elif(ext == '.xhtml'): img = self.html_img elif(ext == '.xml'): img = self.xml_img elif(ext == '.js'): img = self.js_img elif(ext == '.tex'): img = self.ts_img elif(ext == '.coffee'): img = self.coffee_img elif(ext == '.java'): img = self.java_img elif(ext == '.scala'): img = self.scala_img elif(ext == '.kt'): img = self.kotlin_img elif(ext == '.ktm'): img = self.kotlin_img elif(ext == '.kts'): img = self.kotlin_img elif(ext == '.lisp'): img = self.lisp_img elif(ext == 'make'): img = self.makefile_img elif(ext == 'Make'): img = self.makefile_img elif(ext == 'cmake'): img = self.cmake_img elif(ext == 'CMake'): img = self.cmake_img elif(ext == '.m'): img = self.matlab_img elif(ext == '.mat'): img = self.matlab_img elif(ext == '.dpr'): img = self.delphi_img elif(ext == '.perl'): img = self.perl_img elif(ext == '.php'): img = self.php_img elif(ext == '.pr'): img = self.prolog_img elif(ext == '.py'): img = self.python_img elif(ext == '.rb'): img = self.ruby_img elif(ext == '.sh'): img = self.bash_img elif(ext == '.sql'): img = self.mysql_img elif(ext == '.mysql'): img = self.mysql_img elif(ext == '.tcl'): img = self.tcl_img elif(ext == '.awk'): img = self.awk_img else: img = self.txt_img return img def _get_current_editor(self): try: index = self.notebook.index('current') curr_editor = self.Editors[index] return curr_editor except _tkinter.TclError: messagebox.showerror('Error', 'No Editors Opened!!') return None def createNewEditor(self): new_tab_name = askstring('New Tab', 'Enter name of new tab') if new_tab_name: f_name, ext = os.path.splitext(new_tab_name) scrolled_text = ScrolledText(font=self.code_font, undo=True, tabs=('2c'), background='#282c34', insertbackground='#ffffff', foreground='#abb2a4') self.Editors.append(scrolled_text) self.Filenames[scrolled_text] = None try : lexer = self.lexer_selector[ext] except KeyError: lexer = None self.Lexers[scrolled_text] = lexer self.notebook.add(scrolled_text, image=self.langImg(ext), text=os.path.split(new_tab_name)[1], compound='left') self.notebook.select(scrolled_text) self.createTags() self.recolorize(None) self.setStatusText(self.getStatusText()) self.miscBindings(scrolled_text) scrolled_text.focus_set() scrolled_text.edit_reset() def openFile(self): opened_file_name = fd.askopenfilename(initialdir=".", title="Select file", filetypes=(('all files', '*.*'),)) if not isinstance(opened_file_name, tuple): ext = os.path.splitext(opened_file_name)[1] scrolled_text = ScrolledText(font=self.code_font, undo=True, tabs=('2c'), background='#282c34', insertbackground='#ffffff', foreground='#abb2a4') self.Editors.append(scrolled_text) self.Filenames[scrolled_text] = opened_file_name self.notebook.add(scrolled_text, image=self.langImg(ext), text=os.path.split(opened_file_name)[1], compound='left') with open(opened_file_name) as f: file_text = f.read() f.close() scrolled_text.insert('end', file_text) self.notebook.select(scrolled_text) try : lexer = self.lexer_selector[ext] except KeyError: lexer = None self.Lexers[scrolled_text] = lexer self.createTags() self.recolorize(None) scrolled_text.focus_set() scrolled_text.edit_reset() self.miscBindings(scrolled_text) self.setStatusText(self.getStatusText()) def openFileByName(self, path): opened_file_name = path if opened_file_name[0] != '/': opened_file_name = os.path.dirname(os.path.abspath(__file__)) + '/' + path if not os.path.isdir(opened_file_name): ext = os.path.splitext(opened_file_name)[1] scrolled_text = ScrolledText(font=self.code_font, undo=True, tabs=('1.28c'), background='#282c34', insertbackground='#ffffff', foreground='#abb2a4') self.Editors.append(scrolled_text) self.Filenames[scrolled_text] = opened_file_name print(opened_file_name) self.notebook.add(scrolled_text, image=self.langImg(ext), text=os.path.split(opened_file_name)[1], compound='left') with open(opened_file_name) as f: file_text = f.read() f.close() scrolled_text.insert('end', file_text) self.notebook.select(scrolled_text) try: lexer = self.lexer_selector[ext] except KeyError: lexer = None self.Lexers[scrolled_text] = lexer self.createTags() self.recolorize(None) scrolled_text.focus_set() scrolled_text.edit_reset() self.miscBindings(scrolled_text) self.setStatusText(self.getStatusText()) def saveFile(self): try: editor_index = self.notebook.index('current') curr_editor = self.Editors[editor_index] curr_text = curr_editor.get("1.0", "end") if self.Filenames[curr_editor] is not None: with open(self.Filenames[curr_editor], 'r+') as f: f.write(curr_text) messagebox.showinfo('Save', 'File Saved!!!') curr_editor.edit_reset() else: new_file_path = fd.asksaveasfilename(initialdir='.', filetypes=[("All files", "*")]) if not isinstance(new_file_path, tuple): self.Filenames[curr_editor] = new_file_path new_file = open(new_file_path, 'w+') new_file.close() new_file = open(new_file_path, 'r+') new_file.write(curr_text) messagebox.showinfo('Save', 'File Saved!!!') self.Filenames[curr_editor] = new_file_path curr_editor.edit_reset() except _tkinter.TclError: messagebox.showerror("Save File", "No file to save") def removeCurrentEditor(self): try: curr_editor = self._get_current_editor() if messagebox.askyesno('Remove Current Tab', 'Are you sure you want to remove this Editor?', icon='warning'): index = self.notebook.select('current') self.notebook.forget(index) self.Editors.remove(curr_editor) self.Filenames.pop(curr_editor, None) self.Lexers.pop(curr_editor, None) except _tkinter.TclError: messagebox.showerror('Remove Tab', 'Oops!! No tabs to remove!!') def askQuit(self): if messagebox.askyesno('Remove Current Tab', 'Do you really wanna Exit?', icon='warning'): self.destroy() def bindWindowEvents(self): self.bind('<Control-n>', func=lambda e:self.createNewEditor()) self.bind('<Control-o>', func=lambda e:self.openFile()) self.bind('<Control-s>', func=lambda e:self.saveFile()) self.bind('<Control-r>', func=lambda e:self.removeCurrentEditor()) self.bind('<Control-q>', func=lambda e:self.askQuit()) self.bind('<Control-x>', func=lambda e:self.cutSelection()) self.bind('<Control-c>', func=lambda e:self.copySelection()) self.bind('<Control-v>', func=lambda e:self.pasteSelection()) self.bind('<Control-a>', func=lambda e:self.selectAll()) self.bind('<Control-f>', func=lambda e:self.searchWindow()) self.bind('<Control-z>', func=lambda e:self.undoChange()) self.bind('<Control-y>', func=lambda e:self.redoChange()) self.bind('<Control-t>', func=lambda e:self.showFileTree()) self.bind('<Control-N>', func=lambda e:self.createNewEditor()) self.bind('<Control-O>', func=lambda e:self.openFile()) self.bind('<Control-S>', func=lambda e:self.saveFile()) self.bind('<Control-R>', func=lambda e:self.removeCurrentEditor()) self.bind('<Control-Q>', func=lambda e:self.askQuit()) self.bind('<Control-X>', func=lambda e:self.cutSelection()) self.bind('<Control-C>', func=lambda e:self.copySelection()) self.bind('<Control-V>', func=lambda e:self.pasteSelection()) self.bind('<Control-A>', func=lambda e:self.selectAll()) self.bind('<Control-F>', func=lambda e:self.searchWindow()) self.bind('<Control-Z>', func=lambda e:self.undoChange()) self.bind('<Control-Y>', func=lambda e:self.redoChange()) self.bind('<Control-T>', func=lambda e:self.showFileTree()) self.bind('<Control-plus>', func=lambda e:self.increaseFontSize()) self.bind('<Control-minus>', func=lambda e:self.decreaseFontSize()) self.bind('<Control-KP_Add>', func=lambda e:self.increaseFontSize()) self.bind('<Control-KP_Subtract>', func=lambda e:self.decreaseFontSize()) self.bind("<Key>", func=lambda e:self.anyKeyBindings(e)) # self.bind("<Key>", func=lambda e:self.setStatusText(self.getStatusText())) self.bind('<Button>', func=lambda e: self.anyButtonBindings(e)) self.bind('<Button-3>', func=lambda e: self.contextual_menu.post(e.x_root, e.y_root)) def anyKeyBindings(self, event): self.recolorize(None) self.setStatusText(self.getStatusText()) def anyButtonBindings(self, event): self.contextual_menu.unpost() self.setStatusText(self.getStatusText()) def cutSelection(self): curr_editor = self._get_current_editor() curr_editor.event_generate('<<Cut>>') def copySelection(self): curr_editor = self._get_current_editor() curr_editor.event_generate('<<Copy>>') def pasteSelection(self): curr_editor = self._get_current_editor() curr_editor.event_generate('<<Paste>>') def contextualMenu(self): self.contextual_menu = Menu(self, tearoff=False) self.contextual_menu.add_command(label='New Editor', command=self.createNewEditor) self.contextual_menu.add_command(label='Open File', command=self.openFile) self.contextual_menu.add_command(label='Save Editor', command=self.saveFile) self.contextual_menu.add_separator() self.contextual_menu.add_command(label='Remove Editor', command=self.removeCurrentEditor) self.contextual_menu.add_command(label='Change title', command=self.changeEditorTitle) def unpostContextMenu(self): self.contextual_menu.unpost() def changeEditorTitle(self): curr_editor = self._get_current_editor() new_title = askstring('New Editor', "Enter new title") new_ext = os.path.splitext(new_title)[1] self.notebook.tab(curr_editor, text=new_title, image=self.langImg(new_ext)) try : new_lexer = self.lexer_selector[new_ext] except KeyError: new_lexer = None self.Lexers[curr_editor] = new_lexer self.recolorize(None) def increaseFontSize(self): curr_editor = self._get_current_editor() # FIXME curr_font = Font(curr_editor, curr_editor.cget("font")) curr_size = curr_font.cget('size') new_size = curr_size+1 curr_font.configure(size=new_size) new_font = curr_font curr_editor.configure(font=new_font) # print(Font(curr_editor, curr_editor.cget("font")).cget("size")) def decreaseFontSize(self): curr_editor = self._get_current_editor() # FIXME curr_font = Font(curr_editor, curr_editor.cget("font")) curr_size = curr_font.cget('size') if curr_size > 1: new_size = curr_size-1 curr_font.configure(size=new_size) def undoChange(self): try: curr_editor = self._get_current_editor() curr_editor.edit_undo() self.createTags() self.recolorize(None) except _tkinter.TclError: pass def redoChange(self): try: curr_editor = self._get_current_editor() curr_editor.edit_redo() except _tkinter.TclError: pass def selectAll(self): curr_editor = self._get_current_editor() curr_editor.tag_add('sel', '1.0', 'end') return "break" def searchWindow(self): self.search_window = SearchWindow(self, 0) def removeAllTags(self): curr_editor = self._get_current_editor() for tag in curr_editor.tag_names(): curr_editor.tag_delete(tag) def replaceAllWindow(self): self.replace_window = ReplaceTextWindow(self) def replaceAll(self, a, b): curr_editor = self._get_current_editor() start = "1.0" text = curr_editor.get(start, "end") if curr_editor: pos = curr_editor.search(a, start, stopindex="end") while pos: length = len(text) row, col = pos.split('.') end = int(col) + length end = row + '.' + str(end) curr_editor.tag_add('found', pos, end) start = end pos = curr_editor.search(a, start, stopindex="end") replaced = 0 if a: coordinates = [] index_list = list(curr_editor.tag_ranges("found")) index_list.reverse() while index_list: coordinates.append([index_list.pop(), index_list.pop()]) for start, end in coordinates: curr_editor.delete(start, end) curr_editor.insert(start, b) replaced += 1 curr_editor.tag_delete("found") return replaced def createTags(self): curr_editor = self._get_current_editor() bold_font = Font(curr_editor, curr_editor.cget("font")) bold_font.configure(weight='bold') italic_font = Font(curr_editor, curr_editor.cget("font")) italic_font.configure(slant='italic') bold_italic_font = Font(curr_editor, curr_editor.cget("font")) bold_italic_font.configure(weight='bold', slant='italic') style = get_style_by_name('default') for ttype, ndef in style: tag_font = None if ndef['bold'] and ndef['italic']: tag_font = bold_italic_font elif ndef['bold']: tag_font = bold_font elif ndef['italic']: tag_font = italic_font if ndef['color']: foreground = "#%s" % ndef['color'] else: foreground = None curr_editor.tag_configure(str(ttype), foreground=foreground, font=tag_font) def recolorize(self, event): if len(self.Editors) != 0: curr_editor = self._get_current_editor() code = curr_editor.get("1.0", "end-1c") lexer = self.Lexers[curr_editor] if lexer is not None: tokensource = lexer.get_tokens(text=code) start_line = 1 start_index = 0 end_line = 1 end_index = 0 for ttype, value in tokensource: if "\n" in value: end_line += value.count("\n") end_index = len(value.rsplit("\n", 1)[1]) else: end_index += len(value) if value not in (" ", "\n"): index1 = "%s.%s" % (start_line, start_index) index2 = "%s.%s" % (end_line, end_index) for tagname in curr_editor.tag_names(index1): curr_editor.tag_remove(tagname, index1, index2) curr_editor.tag_add(str(ttype), index1, index2) start_line = end_line start_index = end_index # self.underlineComplement() def createLexers(self): lex = {} lex['.c'] = CFamilyLexer() lex['.h'] = CFamilyLexer() lex['.cpp'] = CppLexer() lex['.hpp'] = CppLexer() lex['.css'] = CssLexer() lex['.sass'] = SassLexer() lex['.yaml'] = YamlLexer() lex['.yml'] = YamlLexer() lex['.json'] = JsonLexer() lex['.cs'] = CSharpLexer() lex['.fs'] = FSharpLexer() lex['.e'] = EiffelLexer() lex['.erl'] = ErlangLexer() lex['.hrl'] = ErlangLexer() lex['.es'] = ErlangLexer() lex['.f03'] = FortranLexer() lex['.f90'] = FortranLexer() lex['.F03'] = FortranLexer() lex['.F90'] = FortranLexer() lex['.go'] = GoLexer() lex['.hs'] = HaskellLexer() lex['.v'] = VerilogLexer() lex['.vhdl'] = VhdlLexer() lex['.vhd'] = VhdlLexer() lex['.html'] = HtmlLexer() lex['.htm'] = HtmlLexer() lex['.xhtml'] = HtmlLexer() lex['.xml'] = XmlLexer() lex['.js'] = JavascriptLexer() lex['.tex'] = TypeScriptLexer() lex['.coffee'] = CoffeeScriptLexer() lex['.java'] = JavaLexer() lex['.scala'] = ScalaLexer() lex['.kt'] = KotlinLexer() lex['.ktm'] = KotlinLexer() lex['.kts'] = KotlinLexer() lex['.lisp'] = CommonLispLexer() lex['make'] = MakefileLexer() lex['Make'] = MakefileLexer() lex['CMake'] = CMakeLexer() lex['cmake'] = CMakeLexer() lex['.m'] = MatlabLexer() lex['.mat'] = MatlabLexer() lex['.dpr'] = DelphiLexer() lex['.perl'] = PerlLexer() lex['.php'] = PhpLexer() lex['.pr'] = PrologLexer() lex['.py'] = Python3Lexer() lex['.rb'] = RubyLexer() lex['.sh'] = BashLexer() lex['.sql'] = MySqlLexer() lex['.mysql'] = MySqlLexer() lex['.tcl'] = TclLexer() lex['.awk'] = AwkLexer() return lex def getStatusText(self): if len(self.Editors): curr_editor = self._get_current_editor() cursor_position = curr_editor.index('insert') if cursor_position is not None: row, col = cursor_position.split('.') return "Row: %s Col: %s"%(row, col) else: return "Quode-IDE" else: return "Quode-IDE" def setStatusText(self, text): if len(self.Editors): self.status_bar_label.config(text=text) else: self.status_bar_label.config(text="Quode-IDE") def miscBindings(self, scrolled_text): scrolled_text.bind('<Control-z>', func=self.undoChange) scrolled_text.bind('<Control-y>', func=self.redoChange) scrolled_text.bind('<KeyRelease-quoteright>', func=lambda e: self.completeQuoteright(scrolled_text)) scrolled_text.bind('<KeyRelease-quotedbl>', func=lambda e: self.completeQuotedbl(scrolled_text)) scrolled_text.bind('<KeyRelease-parenleft>', func=lambda e: self.completeParen(scrolled_text)) scrolled_text.bind('<KeyRelease-bracketleft>', func=lambda e: self.completeBracket(scrolled_text)) scrolled_text.bind('<KeyRelease-braceleft>', func=lambda e: self.completeBrace(scrolled_text)) scrolled_text.bind('<KeyRelease-less>', func=lambda e: self.completeAngles(scrolled_text)) scrolled_text.bind('<KeyRelease-Return>', func=lambda e: self.returnNewLine(scrolled_text)) scrolled_text.bind('<parenright>', func=lambda e: self.skipRParen(scrolled_text)) scrolled_text.bind('<bracketright>', func=lambda e: self.skipRBracket(scrolled_text)) scrolled_text.bind('<braceright>', func=lambda e: self.skipRBrace(scrolled_text)) scrolled_text.bind('<greater>', func=lambda e: self.skipRAngle(scrolled_text)) scrolled_text.bind('<BackSpace>', func=lambda e: self.erasePair(scrolled_text)) def completeParen(self, scrolled_text): scrolled_text.mark_gravity('insert', 'left') scrolled_text.insert('insert', ')') scrolled_text.mark_gravity('insert', 'right') self.recolorize(None) def completeBracket(self, scrolled_text): scrolled_text.mark_gravity('insert', 'left') scrolled_text.insert('insert', ']') scrolled_text.mark_gravity('insert', 'right') self.recolorize(None) def completeBrace(self, scrolled_text): scrolled_text.mark_gravity('insert', 'left') scrolled_text.insert('insert', '}') scrolled_text.mark_gravity('insert', 'right') self.recolorize(None) def completeQuoteright(self, scrolled_text): scrolled_text.mark_gravity('insert', 'left') scrolled_text.insert('insert', '\'') scrolled_text.mark_gravity('insert', 'right') self.recolorize(None) def completeQuotedbl(self, scrolled_text): scrolled_text.mark_gravity('insert', 'left') scrolled_text.insert('insert', '"') scrolled_text.mark_gravity('insert', 'right') self.recolorize(None) def completeAngles(self, scrolled_text): scrolled_text.mark_gravity('insert', 'left') scrolled_text.insert('insert', '>') scrolled_text.mark_gravity('insert', 'right') self.recolorize(None) def returnNewLine(self, scrolled_text): curr_editor = self._get_current_editor() cursor_position = curr_editor.index('insert') row_index = int(cursor_position.split('.')[0]) prev_row_index = str(row_index - 1) + '.0' prev_line = curr_editor.get(prev_row_index, prev_row_index + ' lineend') this_line = curr_editor.get(cursor_position + ' linestart', cursor_position + ' lineend') if(len(prev_line) > 1): left_char = prev_line[-1] new_line = ''.join(self.notAlphaLine(prev_line)) if len(this_line) > 0: right_char = this_line[0] if self._are_braces_paired(left_char, right_char): curr_editor.insert('insert', new_line + '\t') curr_editor.mark_gravity('insert', 'left') curr_editor.insert('insert', '\n\t') curr_editor.mark_gravity('insert', 'right') else: curr_editor.insert('insert', new_line) elif(len(prev_line) == 1): if(len(this_line) == 0): if (prev_line == '\t'): curr_editor.insert('insert', '\t') if(len(this_line) > 0): left_char = prev_line[0] right_char = this_line[0] if self._are_braces_paired(left_char, right_char): curr_editor.insert('insert', '\t') curr_editor.mark_gravity('insert', 'left') curr_editor.insert('insert', '\n') curr_editor.mark_gravity('insert', 'right') def _are_braces_paired(self, lchar, rchar): if(lchar == '(' and rchar == ')'): return True if(lchar == '[' and rchar == ']'): return True if(lchar == '{' and rchar == '}'): return True return False def notAlphaLine(self, line): new_line = [] line = ''.join(line) for char in line: if (char == ' ' or char == '\t'): new_line.append(char) else: return new_line return new_line def skipRParen(self, scrolled_text): try: cursor_position = scrolled_text.index('insert') row, col = map(int, cursor_position.split('.')) next_position = str(row) + '.' + str(col+1) if scrolled_text.get(cursor_position, next_position) == ')': scrolled_text.delete(cursor_position, next_position) except: pass def skipRBracket(self, scrolled_text): try: cursor_position = scrolled_text.index('insert') row, col = map(int, cursor_position.split('.')) next_position = str(row) + '.' + str(col+1) if scrolled_text.get(cursor_position, next_position) == ']': scrolled_text.delete(cursor_position, next_position) except: pass def skipRBrace(self, scrolled_text): try: cursor_position = scrolled_text.index('insert') row, col = map(int, cursor_position.split('.')) next_position = str(row) + '.' + str(col+1) if scrolled_text.get(cursor_position, next_position) == '}': scrolled_text.delete(cursor_position, next_position) except: pass def skipRAngle(self, scrolled_text): try: cursor_position = scrolled_text.index('insert') row, col = map(int, cursor_position.split('.')) next_position = str(row) + '.' + str(col+1) if scrolled_text.get(cursor_position, next_position) == '>': scrolled_text.delete(cursor_position, next_position) except: pass def erasePair(self, scrolled_text): try: cursor_position = scrolled_text.index('insert') row, col = map(int, cursor_position.split('.')) prev_position = str(row) + '.' + str(col-1) next_position = str(row) + '.' + str(col+1) curr_char = scrolled_text.get(cursor_position, next_position) prev_char = scrolled_text.get(prev_position, cursor_position) if curr_char == ')' and prev_char == '(': scrolled_text.delete(cursor_position, next_position) if curr_char == ']' and prev_char == '[': scrolled_text.delete(cursor_position, next_position) if curr_char == '}' and prev_char == '{': scrolled_text.delete(cursor_position, next_position) if curr_char == '>' and prev_char == '<': scrolled_text.delete(cursor_position, next_position) except: pass def runCurrentEditor(self): if len(self.Editors): curr_editor = self._get_current_editor() if self.Filenames[curr_editor] is not None: os.system('gnome-terminal --working-directory=%s' % os.path.dirname(self.Filenames[curr_editor])) else: messagebox.showerror(title="Could Not Open Terminal", message="Please save the File to run it") def showFileTree(self): if len(self.Editors): curr_editor = self._get_current_editor() directory = os.path.dirname(self.Filenames[curr_editor]) FileTree(curr_editor, directory) def printAbout(self): about = """ qqqqq dd ii ddddddd eeeeeee qqq qqq dd ii dd dd ee qqq qqq dd ii dd dd ee qqq qqq dd ii dd dd ee qqq qqq uu uu oo ddddd eeeee ii dd dd eeeeeee qqq qqq uu uu oo oo dd dd ee ee ii dd dd ee qqq qqq uu uu oo oo dd dd ee ee zzzzz ii dd dd ee qqq qqq uu uu oo oo dd dd eeeeeeeee ii dd dd ee qqq qqq uu uu oo oo dd dd ee ii dd dd ee qqqqq uuuu oo ddddd eeeeee ii dddddd eeeeeee qqqqqq Quode-IDE(Integrated Development Environment) Author : Yash Khasbage DISCLAIMER: Identifiers used in this software are purely fictious and bear no resembalance to any person living or dead. Any resembalace is purely co-incidental. No animals were harmed in coding of this software. """ print(about) messagebox.showinfo(title="About", message="Check terminal") def _get_int_row_col(self): curr_editor = self._get_current_editor() return list(map(int, curr_editor.index('insert').split('.'))) def _get_str_row_col(self): curr_editor = self._get_current_editor() return curr_editor.index('insert') def _str_to_int(self, pos): return list(map(int, pos.split('.'))) def _get_current_char(self): row, col = self._get_int_row_col() curr_pos = str(row)+'.'+str(col) next_pos = str(row)+'.'+str(col+1) curr_editor = self._get_current_editor() return curr_editor.get(curr_pos, next_pos) def _next_position(self, pos): row, col = list(map(int, pos.split('.'))) return '%d.%d'%(row, col+1) def underlineComplement(self): if len(self.Editors): pos = self._get_str_row_col() curr_char = self._get_current_char() if(curr_char == '('): self.underlineRParen(pos) elif(curr_char == ')'): self.underlineLParen(pos) elif(curr_char == '['): self.underlineRBracket(pos) elif(curr_char == ']'): self.underlineLBracket(pos) elif(curr_char == '{'): self.underlineRBrace(pos) elif(curr_char == '}'): self.underlineLBrace(pos) elif(curr_char == '<'): self.underlineRAngle(pos) elif(curr_char == '>'): self.underlineLAngle(pos) def underlineRParen(self, l_pos): return curr_editor = self._get_current_editor() text = curr_editor.get(l_pos, 'end') count = 0 index = 0 for i in range(len(text)): if(text[i] == ')' and count == 0): index = i elif(text[i] == '('): count += 1 elif(text[i] == ')'): count -= 1 j = 0 line = self._str_to_int(l_pos)[0] line_number = 0 start = l_pos end = '%d.end' % line j_prev = 0 while(index > j): j_prev = j j += len(curr_editor.get(start, end)) - 1 line_number += 1 start = "%d.0" % (line+line_number) r_paren_index = '%d.%d' % (line+line_number, index-j_prev) print("index", index) print("j", j) print("linenumber", line_number) print("r_paren_index", r_paren_index) curr_editor.tag_add('underline', l_pos, self._next_position(l_pos)) curr_editor.tag_add('underline', r_paren_index, self._next_position(r_paren_index)) curr_editor.tag_configure('underline', underline=True) def underlineLParen(self, r_pos): pass def underlineRBracket(self, l_pos): pass def underlineLBracket(self, r_pos): pass def underlineRbrace(self, l_pos): pass def underlineLBrace(self, r_pos): pass def underlineRAngle(self, l_pos): pass def underlineLAngle(self, r_pos): pass
class MainApp(Tk): def __init__(self): Tk.__init__(self) self.notebook = Notebook(self) self.wm_title("Sensitivity Analysis Tool") self.notebook.grid() self.construct_home_tab() self.simulations = [] self.current_simulation = None self.current_tab = None self.abort = Value('b', False) self.abort_univar_overall = Value('b', False) self.simulation_vars = {} self.attributes("-topmost", True) self.tot_sim_num = 0 self.sims_completed = Value('i',0) self.start_time = None self.univar_plot_counter = 1 self.finished_figures = [] self.univar_row_num=0 self.last_results_plotted = None self.last_update = None def construct_home_tab(self): self.home_tab = Frame(self.notebook) self.notebook.add(self.home_tab, text = 'Home') Button(self.home_tab, text='Upload Excel Data', command=self.open_excel_file).grid(row=0,column=1, sticky = E, pady = 5,padx = 5) self.input_csv_entry = Entry(self.home_tab) self.input_csv_entry.grid(row=0, column=2) Button(self.home_tab, text="Upload Aspen Model", command=self.open_aspen_file).grid(row=1, column = 1,sticky = E, pady = 5,padx = 5) self.aspen_file_entry = Entry(self.home_tab) self.aspen_file_entry.grid(row=1, column=2,pady = 5,padx = 5) Button(self.home_tab, text="Upload Excel Model", command=self.open_solver_file).grid(row=2,column = 1,sticky = E, pady = 5,padx = 5) self.excel_solver_entry = Entry(self.home_tab) self.excel_solver_entry.grid(row=2, column=2,pady = 5,padx = 5) Button(self.home_tab, text="Load Data", command=self.make_new_tab).grid(row=5,column = 3,sticky = E, pady = 5,padx = 5) self.analysis_type = StringVar(self.home_tab) self.analysis_type.set("Choose Analysis Type") OptionMenu(self.home_tab, self.analysis_type,"Single Point Analysis","Univariate Sensitivity", "Multivariate Sensitivity").grid(row = 5,sticky = E,column = 2,padx =5, pady = 5) Label(self.home_tab, text='CPU Core Count :').grid(row=3, column=1, sticky=E) self.num_processes_entry = Entry(self.home_tab) self.num_processes_entry.grid(row=3, column=2, pady=5, padx=5) def make_new_tab(self): if self.current_tab: self.notebook.forget(self.current_tab) self.current_tab = None if self.analysis_type.get() == 'Choose Analysis Type': print("ERROR: Select an Analysis Type") elif self.analysis_type.get() == 'Univariate Sensitivity': self.current_tab = Frame(self.notebook) self.notebook.add(self.current_tab,text = "Univariate Analysis") ##############Tab 2 LABELS################## Label(self.current_tab, text="Save As :").grid(row=4, column= 1, sticky = E,pady = 5,padx = 5) self.save_as_entry= Entry(self.current_tab) self.save_as_entry.grid(row=4, column=2,pady = 5,padx = 5) Label(self.current_tab,text = ".csv").grid(row = 4, column = 3, sticky = W) Label(self.current_tab, text ='').grid(row= 13, column =1) Button(self.current_tab, text='Run Univariate Sensitivity Analysis', command=self.initialize_univar_analysis).grid(row=14, column=3, columnspan=2, pady=4) Button(self.current_tab, text='Display Variable Distributions', command=self.plot_init_dist).grid(row=14, column=1, columnspan=2, sticky = W, pady=4) Button(self.current_tab, text='Fill # Trials', command=self.fill_num_trials).grid(row=7, columnspan = 2, sticky =E, column=1, pady=4) self.fill_num_sims = Entry(self.current_tab) self.fill_num_sims.grid(row=7,column = 3,sticky =W, pady =2, padx = 2) self.fill_num_sims.config(width = 10) self.options_box = Labelframe(self.current_tab, text='Run Options:') self.options_box.grid(row = 15,column = 3, pady = 10,padx = 10) Button(self.options_box, text = "Next Variable", command=self.abort_sim).grid( row=6,columnspan = 1, column = 2, sticky=W) Button(self.options_box, text = "Abort", command=self.abort_univar_overall_fun).grid( row= 6,columnspan = 1, column = 3, sticky=W) elif self.analysis_type.get() == 'Single Point Analysis': self.current_tab = Frame(self.notebook) self.notebook.add(self.current_tab, text = 'Single Point') Label(self.current_tab, text="Save As :").grid(row=0, column= 0, sticky = E,pady = 5,padx = 5) self.save_as_entry = Entry(self.current_tab) self.save_as_entry.grid(row=0, column=1,pady = 5,padx = 5) Button(self.current_tab, text='Calculate MFSP', command=self.initialize_single_point).grid(row=7, column=1, columnspan=2, pady=4) elif self.analysis_type.get() == 'Multivariate Sensitivity': self.current_tab = Frame(self.notebook) self.notebook.add(self.current_tab,text = "Multivariate Analysis") Label(self.current_tab, text="Number of Simulations :").grid(row=3, column= 1, sticky = E,pady = 5,padx = 5) self.num_sim_entry = Entry(self.current_tab) self.num_sim_entry.grid(row=3, column=2,pady = 5,padx = 5) Label(self.current_tab, text="Save As :").grid(row=4, column= 1, sticky = E,pady = 5,padx = 5) self.save_as_entry = Entry(self.current_tab) self.save_as_entry.grid(row=4, column=2,pady = 5,padx = 5) Label(self.current_tab,text = ".csv").grid(row = 4, column = 3, sticky = W) Button(self.current_tab, text='Run Multivariate Analysis', command=self.initialize_multivar_analysis).grid(row=6, column=3, columnspan=2, sticky=W, pady=4) Button(self.current_tab, text='Display Variable Distributions', command=self.plot_init_dist).grid(row=6, column=1, columnspan=2, sticky=W, pady=4) self.load_variables_into_GUI() self.notebook.select(self.current_tab) def load_variables_into_GUI(self): sens_vars = str(self.input_csv_entry.get()) single_pt_vars = [] univariate_vars = [] multivariate_vars = [] type_of_analysis = self.analysis_type.get() with open(sens_vars) as f: reader = DictReader(f)# Skip the header row for row in reader: if row['Toggle'].lower().strip() == 'true': if type_of_analysis =='Single Point Analysis': single_pt_vars.append((row["Variable Name"], float(row["Range of Values"].split(',')[0].strip()))) elif type_of_analysis == 'Multivariate Analysis': multivariate_vars.append(row["Variable Name"]) else: univariate_vars.append(( row["Variable Name"], row["Format of Range"].strip().lower( ), row['Range of Values'].split(','))) #now populate the gui with the appropriate tab and variables stored above if type_of_analysis == 'Single Point Analysis': self.current_tab.config(width = '5c', height = '5c') self.sp_value_entries = {} # Create a frame for the canvas with non-zero row&column weights frame_canvas = Frame(self.current_tab) frame_canvas.grid(row=2, column=1, pady=(5, 0)) frame_canvas.grid_rowconfigure(0, weight=1) frame_canvas.grid_columnconfigure(0, weight=1) frame_canvas.config(height = '5c') # Add a canvas in the canvas frame canvas = Canvas(frame_canvas) canvas.grid(row=0, column=0, sticky="news") canvas.config(height = '5c') # Link a scrollbar to the canvas vsb = Scrollbar(frame_canvas, orient="vertical", command=canvas.yview) vsb.grid(row=0, column=1,sticky = 'ns') canvas.configure(yscrollcommand=vsb.set) # Create a frame to contain the variables frame_vars = Frame(canvas) canvas.create_window((0, 0), window=frame_vars, anchor='nw') frame_vars.config(height = '5c') self.sp_row_num = 0 for name,value in single_pt_vars: self.sp_row_num += 1 key = str(self.sp_row_num) Label(frame_vars, text= name).grid(row=self.sp_row_num, column= 1, sticky = E,pady = 5,padx = 5) key=Entry(frame_vars) key.grid(row=self.sp_row_num, column=2,pady = 5,padx = 5) key.delete(first=0,last=END) key.insert(0,str(value)) self.sp_value_entries[name]= key # Determine the size of the Canvas frame_vars.update_idletasks() frame_canvas.config(width='5c', height='10c') # Set the canvas scrolling region canvas.config(scrollregion=canvas.bbox("all")) if type_of_analysis == 'Univariate Sensitivity': self.univar_ntrials_entries = {} Label(self.current_tab, text= 'Variable Name').grid(row=8, column= 1,pady = 5,padx = 5, sticky= E) Label(self.current_tab, text= 'Sampling Type').grid(row=8, column= 2,pady = 5,padx = 5, sticky=E) Label(self.current_tab, text= '# of Trials').grid(row=8, column= 3,pady = 5,padx = 5) # Create a frame for the canvas with non-zero row&column weights frame_canvas1 = Frame(self.current_tab) frame_canvas1.grid(row=9, column=1, columnspan =3, pady=(5, 0)) frame_canvas1.grid_rowconfigure(0, weight=1) frame_canvas1.grid_columnconfigure(0, weight=1) frame_canvas1.config(height = '3c') # Add a canvas in the canvas frame canvas1 = Canvas(frame_canvas1) canvas1.grid(row=0, column=0, sticky="news") canvas1.config(height = '3c') # Link a scrollbar to the canvas vsb = Scrollbar(frame_canvas1, orient="vertical", command=canvas1.yview) vsb.grid(row=0, column=1,sticky = 'ns') canvas1.configure(yscrollcommand=vsb.set) # Create a frame to contain the variables frame_vars1 = Frame(canvas1) frame_vars1.config(height = '3c') canvas1.create_window((0, 0), window=frame_vars1, anchor='nw') for name, format_of_data, vals in univariate_vars: Label(frame_vars1, text= name).grid(row=self.univar_row_num, column= 1,pady = 5,padx = 5) Label(frame_vars1, text= format_of_data).grid(row=self.univar_row_num, column= 2,pady = 5,padx = 5) if not(format_of_data == 'linspace' or format_of_data == 'list'): key2=Entry(frame_vars1) key2.grid(row=self.univar_row_num, column=3,pady = 5,padx = 5) #key2.insert(0,univariate_sims) self.univar_ntrials_entries[name]= key2 else: if format_of_data == 'linspace': Label(frame_vars1,text= str(vals[2])).grid(row=self.univar_row_num, column= 3,pady = 5,padx = 5) else: Label(frame_vars1,text= str(len(vals))).grid(row=self.univar_row_num, column= 3,pady = 5,padx = 5) self.univar_row_num += 1 # Update vars frames idle tasks to let tkinter calculate variable sizes frame_vars1.update_idletasks() # Determine the size of the Canvas frame_canvas1.config(width='5c', height='5c') # Set the canvas scrolling region canvas1.config(scrollregion=canvas1.bbox("all")) def get_distributions(self): if self.analysis_type.get() == 'Univariate Sensitivity': if self.univar_ntrials_entries: max_num_sim = 0 for slot in self.univar_ntrials_entries.values(): try: cur_num_sim = int(slot.get()) except: cur_num_sim = 1 max_num_sim = max(max_num_sim, cur_num_sim) else: max_num_sim = 1 self.simulation_vars, self.simulation_dist = self.construct_distributions(ntrials=max_num_sim) for (aspen_variable, aspen_call, fortran_index), dist in self.simulation_vars.items(): if aspen_variable in self.univar_ntrials_entries: try: num_trials_per_var = int(self.univar_ntrials_entries[aspen_variable].get()) except: num_trials_per_var = 1 self.simulation_vars[(aspen_variable, aspen_call, fortran_index)] = dist[:num_trials_per_var] self.simulation_dist[aspen_variable] = dist[:num_trials_per_var] else: try: ntrials = int(self.num_sim_entry.get()) except: ntrials=1 self.simulation_vars, self.simulation_dist = self.construct_distributions(ntrials=ntrials) def construct_distributions(self, ntrials=1): ''' Given the excel input from the user in the GUI, produce a list_of_variables the user wants to change as well as their distributions that should be randomly sampled from. ''' gui_excel_input = str(self.input_csv_entry.get()) with open(gui_excel_input) as f: reader = DictReader(f)# Skip the header row simulation_vars = {} simulation_dist = {} for row in reader: if row['Toggle'].lower().strip() == 'true': dist_type = row['Format of Range'].lower() aspen_variable = row['Variable Name'] aspen_call = row['Variable Aspen Call'] bounds = row['Bounds'].split(',') lb = float(bounds[0].strip()) ub = float(bounds[1].strip()) if 'normal' in dist_type or 'gaussian' in dist_type: dist_variables = row['Range of Values'].split(',') distribution = self.sample_gauss(float(dist_variables[0].strip()), float(dist_variables[1].strip()), lb, ub, ntrials) if 'linspace' in dist_type: linspace_vars = row['Range of Values'].split(',') distribution = linspace(float(linspace_vars[0].strip()), float(linspace_vars[1].strip()), float(linspace_vars[2].strip())) if 'poisson' in dist_type: lambda_p = float(row['Range of Values'].strip()) distribution = self.sample_poisson(lambda_p, lb, ub, ntrials) if 'pareto' in dist_type: pareto_vals = row['Range of Values'].split(',') shape = float(pareto_vals[0].strip()) scale = float(pareto_vals[1].strip()) distribution = self.sample_pareto(shape, scale, lb, ub, ntrials) if 'list' in dist_type: lst = row['Range of Values'].split(',') distribution = [] for l in lst: distribution.append(float(l.strip())) if 'uniform' in dist_type: lb_ub = row['Range of Values'].split(',') lb_uniform, ub_uniform = float(lb_ub[0].strip()), float(lb_ub[1].strip()) distribution = self.sample_uniform(lb_uniform, ub_uniform, lb, ub, ntrials) simulation_dist[aspen_variable] = distribution[:] fortran_index = (0,0) if row['Fortran Call'].strip() != "": fortran_call = row['Fortran Call'] value_to_change = row['Fortran Value to Change'].strip() len_val = len(value_to_change) for i in range(len(fortran_call)): if fortran_call[i:i+len_val] == value_to_change: fortran_index = (i, i+len_val) #NOT INCLUSIVE for i, v in enumerate(distribution): distribution[i] = self.make_fortran(fortran_call, fortran_index, v) simulation_vars[(aspen_variable, aspen_call, fortran_index)] = distribution return simulation_vars, simulation_dist def sample_gauss(self,mean, std, lb, ub, ntrials): d = [] for i in range(ntrials): rand_sample = random.normal(mean,std) while(rand_sample < lb or rand_sample > ub): rand_sample = random.normal(mean,std) d.append(rand_sample) return d def sample_uniform(self,lb_uniform, ub_uniform, lb, ub, ntrials): d = [] for i in range(ntrials): rand_sample = random.uniform(lb_uniform, ub_uniform) while(rand_sample < lb or rand_sample > ub): rand_sample = random.uniform(lb_uniform, ub_uniform) d.append(rand_sample) return d def sample_poisson(self,lambda_p, lb, ub, ntrials): d = [] for i in range(ntrials): rand_sample = random.poisson(10000*lambda_p)/10000 while(rand_sample < lb or rand_sample > ub): rand_sample = random.poisson(10000*lambda_p)/10000 d.append(rand_sample) return d def sample_pareto(self, shape, scale, lb, ub, ntrials): d = [] for i in range(ntrials): rand_sample = (random.pareto(shape) + 1) * scale while(rand_sample < lb or rand_sample > ub): rand_sample = (random.pareto(shape) + 1) * scale d.append(rand_sample) return d def make_fortran(self, fortran_call, fortran_index, val): return fortran_call[:fortran_index[0]] + str(val) + fortran_call[fortran_index[1]:] def disp_sp_mfsp(self): try: if self.current_simulation.results: mfsp = self.current_simulation.results[0].at[0, 'MFSP'] if mfsp: Label(self.current_tab, text= 'MFSP = ${:.2f}'.format(mfsp)).grid( row=self.sp_row_num+1, column = 1) else: Label(self.current_tab, text= 'Aspen Failed to Converge').grid( row=self.sp_row_num+1, column = 1) else: self.after(5000, self.disp_sp_mfsp) except: self.after(5000, self.disp_sp_mfsp) def single_point_analysis(self): self.store_user_inputs() self.get_distributions() # update simulation variable values based on user input in GUI for (aspen_variable, aspen_call, fortran_index), values in self.simulation_vars.items(): self.simulation_vars[(aspen_variable, aspen_call, fortran_index)] = [float( self.sp_value_entries[aspen_variable].get())] self.create_simulation_object(self.simulation_vars, self.vars_to_change, self.output_file, self.num_trial) self.run_simulations() def run_multivar_sens(self): Button(self.current_tab, text = "Abort", command=self.abort_sim).grid( row=7,columnspan = 1, column = 3, sticky=W) self.store_user_inputs() if len(self.simulation_vars) == 0: self.get_distributions() self.create_simulation_object(self.simulation_vars, self.vars_to_change, self.output_file, self.num_trial) self.run_simulations() def run_univ_sens(self): self.store_user_inputs() if len(self.simulation_vars) == 0: self.get_distributions() for (aspen_variable, aspen_call, fortran_index), values in self.simulation_vars.items(): self.create_simulation_object({(aspen_variable, aspen_call, fortran_index): values}, [aspen_variable], self.output_file+'_'+aspen_variable, len(values)) self.run_simulations() def store_user_inputs(self): self.aspen_file = str(self.aspen_file_entry.get()) try: self.num_processes = int(self.num_processes_entry.get()) except: self.num_processes = 1 self.excel_solver_file= str(self.excel_solver_entry.get()) try: self.num_trial = int(self.num_sim_entry.get()) except: self.num_trial = 1 self.output_file = str(self.save_as_entry.get()) self.input_csv = str(self.input_csv_entry.get()) self.vars_to_change = [] with open(self.input_csv) as f: reader = DictReader(f)# Skip the header row for row in reader: if row['Toggle'].lower().strip() == 'true': self.vars_to_change.append(row["Variable Name"]) def run_simulations(self): self.start_time = time() for sim in self.simulations: self.current_simulation = sim self.current_simulation.init_sims() if self.abort_univar_overall.value: self.abort.value = True self.univar_plot_counter += 1 def parse_output_vars(self): excels_to_ignore = {} for p in process_iter(): if 'excel' in p.name().lower(): excels_to_ignore[p.pid] = 1 excel, book = open_excelCOMS(self.excel_solver_file) self.output_vars = [] row_counter = 3 while True: var_name = book.Sheets('Output').Evaluate("B" + str(row_counter)).Value if var_name: units = book.Sheets('Output').Evaluate("D" + str(row_counter)).Value column_name = var_name + ' (' + units + ')' if units else var_name self.output_vars.append(column_name) else: break row_counter += 1 self.output_value_cells = "C3:C" + str(row_counter - 1) self.output_vars += ['Aspen Errors'] for p in process_iter(): if 'excel' in p.name().lower() and p.pid not in excels_to_ignore: p.terminate() def create_simulation_object(self, simulation_vars, vars_to_change, output_file, num_trial): self.parse_output_vars() self.output_columns = vars_to_change + self.output_vars new_sim = Simulation(self.sims_completed, num_trial, simulation_vars, output_file, path.dirname(str(self.input_csv_entry.get())), self.aspen_file, self.excel_solver_file, self.abort, vars_to_change, self.output_value_cells, self.output_columns, save_freq=5, num_processes=self.num_processes) self.simulations.append(new_sim) self.tot_sim_num += num_trial def initialize_single_point(self): self.worker_thread = Thread( target=lambda: self.single_point_analysis()) self.worker_thread.start() self.after(5000, self.disp_sp_mfsp) def initialize_univar_analysis(self): self.worker_thread = Thread( target=lambda: self.run_univ_sens()) self.worker_thread.start() self.status_label = None self.time_rem_label = None self.after(5000, self.univar_gui_update) def initialize_multivar_analysis(self): self.worker_thread = Thread( target=lambda: self.run_multivar_sens()) self.worker_thread.start() self.status_label = None self.time_rem_label = None self.multivar_gui_update() def disp_status_update(self): if self.current_simulation and not self.abort.value: if len(self.current_simulation.results) == self.current_simulation.tot_sim: tmp = Label(self.current_tab, text= 'Status: Simulation Complete ') else: tmp = Label(self.current_tab, text= 'Status: Simulation Running | {} Results Collected'.format( len(self.current_simulation.results))) if self.univar_row_num != 0: row = 15 else: row = 8 tmp.grid(row=row, column = 1, sticky=W, columnspan=2) if self.status_label: self.status_label.destroy() self.status_label = tmp def disp_time_remaining(self): if self.start_time and self.sims_completed.value != self.last_update: self.last_update = self.sims_completed.value elapsed_time = time() - self.start_time if self.sims_completed.value > 0: remaining_time = ((elapsed_time / self.sims_completed.value) * (self.tot_sim_num - self.sims_completed.value))//60 hours, minutes = divmod(remaining_time, 60) tmp = Label(self.current_tab, text='Time Remaining: {} Hours, {} Minutes '.format(int(hours), int(minutes))) else: tmp = Label(self.current_tab, text='Time Remaining: N/A') if self.univar_row_num != 0: row = 16 else: row = 9 tmp.grid(row=row, column=1, columnspan=2,sticky=W) if self.time_rem_label: self.time_rem_label.destroy() self.time_rem_label = tmp def plot_on_GUI(self): if not self.current_simulation: return if len(self.current_simulation.results) == self.last_results_plotted: return self.last_results_plotted = len(self.current_simulation.results) if self.current_simulation.results: results = concat(self.current_simulation.results).sort_index() results = results[[d is not None for d in results['MFSP']]] # filter to make sure you aren't plotting None results else: results = DataFrame(columns=self.output_columns) fig_list =[] num_bins = 15 mfsp_fig = Figure(figsize = (3,3), facecolor=[240/255,240/255,237/255], tight_layout=True) b = mfsp_fig.add_subplot(111) b.hist(results['MFSP'], num_bins, facecolor='blue', edgecolor='black', alpha=1.0) b.set_title('MFSP') fig_list.append(mfsp_fig) for var, values in self.simulation_dist.items(): fig = Figure(figsize = (3,3), facecolor=[240/255,240/255,237/255], tight_layout=True) a = fig.add_subplot(111) _, bins, _ = a.hist(self.simulation_dist[var], num_bins, facecolor='white', edgecolor='black',alpha=1.0) a.hist(results[var], bins=bins, facecolor='blue',edgecolor='black', alpha=1.0) a.set_title(var) fig_list.append(fig) if self.univar_row_num != 0: row_num = 17 else: row_num = 10 frame_canvas = Frame(self.current_tab) frame_canvas.grid(row=row_num, column=1, columnspan = 3,pady=(5, 0)) frame_canvas.grid_rowconfigure(0, weight=1) frame_canvas.grid_columnconfigure(0, weight=1) frame_canvas.config(height = '10c', width='16c') main_canvas = Canvas(frame_canvas) main_canvas.grid(row=0, column=0, sticky="news") main_canvas.config(height = '10c', width='16c') vsb = Scrollbar(frame_canvas, orient="vertical", command=main_canvas.yview) vsb.grid(row=0, column=1,sticky = 'ns') main_canvas.configure(yscrollcommand=vsb.set) figure_frame = Frame(main_canvas) main_canvas.create_window((0, 0), window=figure_frame, anchor='nw') figure_frame.config(height = '10c', width='16c') row_num = 0 column = False for figs in fig_list: figure_canvas = FigureCanvasTkAgg(figs, master=figure_frame) if column: col = 4 else: col = 1 #figure_canvas.draw() figure_canvas.get_tk_widget().grid( row=row_num, column=col,columnspan=2, rowspan = 5, pady = 5,padx = 8, sticky=E) #figure_canvas._tkcanvas.grid(row=row_num, column = 0,columnspan = 10, rowspan = 10, sticky= W+E+N+S, pady = 5,padx = 5) if column: row_num += 5 column = not column figure_frame.update_idletasks() frame_canvas.config(width='16c', height='10c') # Set the canvas scrolling region main_canvas.config(scrollregion=figure_frame.bbox("all")) def plot_univ_on_GUI(self): if not self.current_simulation: return if len(self.current_simulation.results) == self.last_results_plotted: return self.last_results_plotted = len(self.current_simulation.results) current_var = self.current_simulation.vars_to_change[0] if self.current_simulation.results: results = concat(self.current_simulation.results).sort_index() results = results[[d is not None for d in results['MFSP']]] # filter to make sure you aren't plotting None results else: results = DataFrame(columns=self.output_columns) fig_list =[] var_fig = Figure(figsize = (3,3), facecolor=[240/255,240/255,237/255], tight_layout=True) a = var_fig.add_subplot(111) num_bins = 15 _, bins, _ = a.hist(self.simulation_dist[current_var], num_bins, facecolor='white',edgecolor='black', alpha=1.0) a.hist(results[current_var], bins=bins, facecolor='blue',edgecolor='black', alpha=1.0) a.set_title(current_var) fig_list.append(var_fig) mfsp_fig = Figure(figsize = (3,3), facecolor=[240/255,240/255,237/255], tight_layout=True) b = mfsp_fig.add_subplot(111) b.hist(results['MFSP'], num_bins, facecolor='blue', edgecolor='black', alpha=1.0) b.set_title('MFSP - ' + current_var) fig_list.append(mfsp_fig) figs_to_plot = self.finished_figures[:] + fig_list if len(self.current_simulation.results) == self.current_simulation.tot_sim: self.finished_figures += fig_list if self.univar_row_num != 0: row_num = 17 else: row_num = 10 frame_canvas = Frame(self.current_tab) frame_canvas.grid(row=row_num, column=1, columnspan = 3,pady=(5, 0)) frame_canvas.grid_rowconfigure(0, weight=1) frame_canvas.grid_columnconfigure(0, weight=1) frame_canvas.config(height = '10c', width='16c') main_canvas = Canvas(frame_canvas) main_canvas.grid(row=0, column=0, sticky="news") main_canvas.config(height = '10c', width='16c') vsb = Scrollbar(frame_canvas, orient="vertical", command=main_canvas.yview) vsb.grid(row=0, column=1,sticky = 'ns') main_canvas.configure(yscrollcommand=vsb.set) figure_frame = Frame(main_canvas) main_canvas.create_window((0, 0), window=figure_frame, anchor='nw') figure_frame.config(height = '10c', width='16c') row_num = 0 column = False for figs in figs_to_plot: figure_canvas = FigureCanvasTkAgg(figs, master=figure_frame) if column: col = 4 else: col = 1 #figure_canvas.draw() figure_canvas.get_tk_widget().grid( row=row_num, column=col,columnspan=2, rowspan = 5, pady = 5,padx = 8, sticky=E) #figure_canvas._tkcanvas.grid(row=row_num, column = 0,columnspan = 10, rowspan = 10, sticky= W+E+N+S, pady = 5,padx = 5) if column: row_num += 5 column = not column figure_frame.update_idletasks() frame_canvas.config(width='16c', height='10c') # Set the canvas scrolling region main_canvas.config(scrollregion=figure_frame.bbox("all")) def plot_init_dist(self): ''' This function will plot the distribution of variable calls prior to running the simulation. This will enable users to see whether the distributions are as they expected. ''' self.get_distributions() fig_list =[] for var, values in self.simulation_dist.items(): fig = Figure(figsize = (3,3), facecolor=[240/255,240/255,237/255], tight_layout=True) a = fig.add_subplot(111) num_bins = 15 a.hist(values, num_bins, facecolor='blue', edgecolor='black', alpha=1.0) a.set_title(var) fig_list.append(fig) if self.univar_row_num != 0: row_num = 17 else: row_num = 10 frame_canvas = Frame(self.current_tab) frame_canvas.grid(row=row_num, column=1, columnspan = 3,pady=(5, 0)) frame_canvas.grid_rowconfigure(0, weight=1) frame_canvas.grid_columnconfigure(0, weight=1) frame_canvas.config(height = '10c', width='16c') main_canvas = Canvas(frame_canvas) main_canvas.grid(row=0, column=0, sticky="news") main_canvas.config(height = '10c', width='16c') vsb = Scrollbar(frame_canvas, orient="vertical", command=main_canvas.yview) vsb.grid(row=0, column=2,sticky = 'ns') main_canvas.configure(yscrollcommand=vsb.set) figure_frame = Frame(main_canvas) main_canvas.create_window((0, 0), window=figure_frame, anchor='nw') figure_frame.config(height = '10c', width='16c') row_num = 0 column = False for figs in fig_list: figure_canvas = FigureCanvasTkAgg(figs, master=figure_frame) if column: col = 4 else: col = 1 figure_canvas.get_tk_widget().grid( row=row_num, column=col,columnspan=2, rowspan = 5, pady = 5,padx = 8, sticky=E) if column: row_num += 5 column = not column figure_frame.update_idletasks() frame_canvas.config(width='16c', height='10c') main_canvas.config(scrollregion=figure_frame.bbox("all")) def univar_gui_update(self): self.disp_status_update() self.disp_time_remaining() self.plot_univ_on_GUI() ####################### ADD AUTO UPDATE GRAPHS ############# self.after(10000, self.univar_gui_update) def multivar_gui_update(self): self.disp_status_update() self.disp_time_remaining() self.plot_on_GUI() ####################### ADD AUTO UPDATE GRAPHS ############# self.after(10000, self.multivar_gui_update) def fill_num_trials(self): ntrials = self.fill_num_sims.get() for name, slot in self.univar_ntrials_entries.items(): slot.delete(0, END) slot.insert(0, ntrials) def open_excel_file(self): filename = askopenfilename(title = "Select file", filetypes = (("csv files","*.csv"),("all files","*.*"))) self.input_csv_entry.delete(0, END) self.input_csv_entry.insert(0, filename) def open_aspen_file(self): filename = askopenfilename(title = "Select file", filetypes = (("Aspen Models",["*.bkp", "*.apw"]),("all files","*.*"))) self.aspen_file_entry.delete(0, END) self.aspen_file_entry.insert(0, filename) def open_solver_file(self): filename = askopenfilename(title = "Select file", filetypes = (("Excel Files","*.xlsm"),("all files","*.*"))) self.excel_solver_entry.delete(0, END) self.excel_solver_entry.insert(0, filename) def abort_sim(self): self.abort.value = True self.cleanup_thread = Thread(target=self.cleanup_processes_and_COMS) self.cleanup_thread.start() def abort_univar_overall_fun(self): self.abort_univar_overall.value = True self.abort_sim() def cleanup_processes_and_COMS(self): try: self.current_simulation.close_all_COMS() self.current_simulation.terminate_processes() save_data(self.current_simulation.output_file, self.current_simulation.results, self.current_simulation.directory) except: self.after(1000, self.cleanup_processes_and_COMS)