Permalink
Browse files

rename 2

  • Loading branch information...
1 parent 007c820 commit 6c8257f658860634844307d7f384e134c22f41e5 @bahniks committed Oct 4, 2013
Showing with 366 additions and 0 deletions.
  1. +366 −0 Stuff/Modules/helpcmm.py
View
@@ -0,0 +1,366 @@
+"""
+Copyright 2013 Štěpán Bahník
+
+This file is part of Carousel Maze Manager.
+
+Carousel Maze Manager is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Carousel Maze Manager is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Carousel Maze Manager. If not, see <http://www.gnu.org/licenses/>.
+"""
+
+from tkinter.filedialog import askopenfilenames, asksaveasfilename, askopenfilename, askdirectory
+from tkinter import *
+from os.path import basename
+from tkinter import ttk, messagebox
+
+import os.path
+import os
+
+
+from window import placeWindow
+
+
+class HelpCM(Toplevel):
+ "help window reachable from menu"
+ def __init__(self, root):
+ if not os.path.exists(os.path.join(os.getcwd(), "Stuff", "Help")):
+ messagebox.showinfo(message = "Folder 'Help' doesn't exist in the " +
+ "'Stuff' directory!", title = "Error", icon = "error")
+ return
+
+ super().__init__(root)
+ self["padx"] = 7
+ self["pady"] = 7
+
+ self.title("Help")
+ placeWindow(self, 806, 699)
+ self.resizable(FALSE, FALSE)
+
+ self.goneThrough = [[""], 0] # variable containing lists of items gone through and their
+ # position (e.g. [["", 0], ["Parameters", 1], ["Shocks", 2]])
+ self.linkMapping = {} # variable containing texts and items that the texts refer to
+
+ # widgets
+ self.text = Text(self, width = 70, height = 40, wrap = "word", cursor = "")
+ self.text.grid(column = 1, row = 1, pady = 4)
+
+ self.scroll = ttk.Scrollbar(self, orient = VERTICAL, command = self.text.yview)
+ self.scroll.grid(column = 2, row = 1, pady = 4, sticky = (N, S, W))
+ self.text.configure(yscrollcommand = self.scroll.set)
+
+ self.buttonBar = ttk.Frame(self)
+ self.buttonBar.grid(column = 1, row = 0, pady = 4, sticky = (N, S, E, W))
+ self.buttonBar.columnconfigure(2, weight = 1)
+
+ self.searchBut = ttk.Button(self.buttonBar, text = "Search", command = self.searchFun)
+ self.searchBut.grid(column = 4, row = 0)
+
+ self.searchTerm = StringVar()
+ self.searchEntry = ttk.Entry(self.buttonBar, width = 30, justify = "left",
+ textvariable = self.searchTerm)
+ self.searchEntry.grid(column = 3, row = 0, padx = 4)
+
+ self.returnBut = ttk.Button(self.buttonBar, text = "Return", command = self.returnFun)
+ self.returnBut.grid(column = 0, row = 0, padx = 4)
+
+ self.forwardBut = ttk.Button(self.buttonBar, text = "Forward", command = self.forwardFun)
+ self.forwardBut.grid(column = 1, row = 0, padx = 4)
+
+ self.tree = ttk.Treeview(self, selectmode = "browse")
+ self.tree.grid(column = 0, row = 0, rowspan = 2, pady = 4, padx = 4,
+ sticky = (N, S, E, W))
+
+ self.makeTree()
+ self.makeText("Help") # initial text is from file 'Help'
+
+ self.tree.bind("<1>", self.treeSelect)
+
+
+ def makeTree(self):
+ "makes tree of existing help pages"
+ files = os.listdir(os.path.join(os.getcwd(), "Stuff", "Help"))
+
+ items = []
+ for file in sorted(files):
+ if file == "Help":
+ continue
+ filename = os.path.join(os.getcwd(), "Stuff", "Help", file)
+ infile = open(filename, mode = "r")
+ parent = infile.readline()[1:].rstrip()
+ if parent:
+ items.append([parent, os.path.splitext(file)[0]])
+ branches = []
+
+ # if parent of item is a number, item is inserted in the top level of the tree
+ for item in items:
+ if 47 < ord(item[0][0]) < 58:
+ self.tree.insert("", item[0], item[1], text = item[1].replace("_", " "))
+ branches.append(item[1])
+
+ # inserts children of every already inserted parent
+ for rep in range(6): # maximal number of levels of the tree
+ level = []
+ for item in items:
+ if item[1] in branches:
+ continue
+ elif item[0] in branches:
+ self.tree.insert(item[0], "end", item[1], text = item[1].replace("_", " "))
+ level.append(item[1])
+ else:
+ pass
+ branches = branches + level
+
+
+ def searchFun(self, word = "noWord"):
+ """searches for a word set in self.searchTerm variable
+ word parameter is important only for walk through pages that were already accessed
+ - which is for functions 'returnFun' and 'forwardFun'"""
+
+ files = os.listdir(os.path.join(os.getcwd(), "Stuff", "Help"))
+
+ # searched contains full search term, searchedWords contains separated words
+ if word != "noWord":
+ searched = word.lower()
+ else:
+ searched = self.searchTerm.get().lower()
+ self.goneThrough[0].append("$Search$" + searched)
+ self.goneThrough[1] += 1
+ searchedWords = searched.split()
+
+ self.text["state"] = "normal"
+ self.text.delete("1.0", "end")
+
+ self.text.insert("end", "\n")
+
+ # searched term must have at least 3 characters
+ if len(searched) < 3:
+ self.text.insert("end", " Search term is too short.")
+ self.text["state"] = "disabled"
+ return
+
+ found = [] # which items contain searched term (appended in form: [item, weight])
+
+ # search in files
+ for file in sorted(files):
+ filename = os.path.join(os.getcwd(), "Stuff", "Help", file)
+ infile = open(filename, mode = "r")
+ inText = False # is file (i.e. item) already in 'found' variable
+ maxLength = max([len(l) for l in searchedWords]) # maximum word length
+
+ for searchedWord in searchedWords:
+ # if a word is shorter than 3 characters, it doesn't count (prepositions etc.)
+ if len(searchedWord) < 3 and maxLength > 2:
+ continue
+ # if a word is in item name, 2 is added to weight
+ if searchedWord in file.lower() and len(searchedWord) > 2:
+ if inText:
+ found[-1][1] = found[-1][1] + 2
+ else:
+ inText = True
+ found.append([os.path.splitext(file)[0], 2])
+
+ for count, line in enumerate(infile):
+ # skips the first two lines (header)
+ if count < 2:
+ continue
+ # if searched term contains 2 and more words and they are in line
+ # positioned one after another, 1 is added to weight (in fact this is done
+ # for every word, consequently, 1 is added to weight for every word in
+ # searched term)
+ if len(searchedWords) > 1 and searched in line:
+ if inText:
+ found[-1][1] = found[-1][1] + 1
+ else:
+ inText = True
+ found.append([os.path.splitext(file)[0], 1])
+
+ for word in line.split():
+ # if a word is marked, it is processed accordingly
+ if len(word) and word[0] == "$":
+ splitted = word.split("$")
+ if len(splitted) > 2:
+ word = splitted[2].replace("_", " ")
+ else:
+ continue
+ # 1 is addded to weight if a searched word is contained in word
+ if searched in word.lower():
+ if inText:
+ found[-1][1] = found[-1][1] + 1
+ else:
+ inText = True
+ found.append([os.path.splitext(file)[0], 1])
+
+ found.sort(key = lambda e: e[1], reverse = True) #sorts items according to their weight
+
+ if len(found) == 0:
+ self.text.insert("end", " No match found.")
+
+ # if searched term is in item name, it is in top position
+ for count, file in enumerate(found):
+ if searched in file[0].lower():
+ self.text.insert("end", " ")
+ self.text.insert("end", file[0].replace("_", " "), ("link"))
+ self.text.insert("end", "\n\n")
+ found.pop(count)
+
+ for file in found:
+ self.text.insert("end", " ")
+ self.text.insert("end", file[0].replace("_", " "), ("link"))
+ self.text.insert("end", "\n\n")
+
+ self.text["state"] = "disabled"
+
+ self.text.tag_configure("link", foreground = "blue")
+ self.text.tag_bind("link", "<1>", link)
+
+
+ def returnFun(self):
+ "makes a step back in items gone through"
+ if self.goneThrough[1] != 0:
+ self.goneThrough[1] -= 1
+ item = self.goneThrough[0][self.goneThrough[1]]
+ if item == "":
+ self.makeText("Help")
+ self.tree.selection_set(item)
+ # show search results if last item accessed was search
+ elif len(item) > 8 and item[0:8] == "$Search$":
+ self.searchFun(word = item[8:])
+ else:
+ self.makeText(item)
+ self.tree.selection_set(item)
+
+
+ def forwardFun(self):
+ "makes a step forward in items gone through"
+ if self.goneThrough[1] != len(self.goneThrough[0]) - 1:
+ self.goneThrough[1] += 1
+ item = self.goneThrough[0][self.goneThrough[1]]
+ if len(item) > 8 and item[0:8] == "$Search$":
+ self.searchFun(word = item[8:])
+ else:
+ self.tree.selection_set(item)
+ self.makeText(item)
+
+
+ def makeText(self, item):
+ "takes text from a file and displays it in a 'text' widget (takes care of formatting)"
+ file = os.path.join(os.getcwd(), "Stuff", "Help", item.replace(" ", "_") + ".txt")
+
+ self.text["state"] = "normal"
+
+ self.text.delete("1.0", "end")
+
+ infile = open(file, mode = "r")
+
+ content = []
+ for count, line in enumerate(infile):
+ if count < 2:
+ continue
+ words = line.rstrip().split(" ")
+ content = content + words
+
+ self.text.insert("end", item.replace("_", " ") + "\n", ("header"))
+
+ for word in content:
+ if len(word) and word[0] == "$":
+ divided = word.split("$")
+ if divided[1][0] == "n": # $nn - adds new lines
+ self.text.insert("end", "\n" * divided[1].count("n"))
+ elif divided[1] and divided[1][0] in ".,';:-": # interpunctions
+ self.text.insert("end", divided[1])
+ elif divided[1] == "s": # $s$See_also: - makes subheader and new line
+ self.text.insert("end", divided[2], ("subheader"))
+ self.text.insert("end", "\n")
+ elif divided[1] == "b": # $b$Bold_text - bold formating
+ self.text.insert("end", divided[2], ("bold"))
+ self.text.insert("end", " ")
+ elif divided[1] == "l": # $l$link$Linked_item - $Linked_item not needed if
+ # link corresponds to linked item
+ self.text.insert("end", divided[2].replace("_", " "), ("link"))
+ if len(divided) == 4:
+ self.linkMapping[divided[2].replace(" ", "_").capitalize()]\
+ = divided[3]
+ self.text.insert("end", " ")
+ else:
+ word = word + " "
+ self.text.insert("end", word)
+
+ # 'See also:' is automatically added to the end
+ self.text.insert("end", "\n\n")
+ self.text.insert("end", "See also:", ("subheader"))
+
+ # first the parent is added as a link
+ if item != "Help":
+ parent = self.tree.parent(item)
+ if parent:
+ self.text.insert("end", "\n")
+ self.text.insert("end", "- ")
+ self.text.insert("end", parent.replace("_", " "), ("link"))
+ # next childen are added as links
+ children = self.tree.get_children(item)
+ if children:
+ for child in children:
+ self.text.insert("end", "\n")
+ self.text.insert("end", "+ ")
+ self.text.insert("end", child.replace("_", " "), ("link"))
+
+ # configuration of tagged text
+ self.text.tag_configure("header", font = "TkDefaultFont 10 bold")
+ self.text.tag_configure("subheader", font = "TkDefaultFont 9 bold")
+ self.text.tag_configure("link", foreground = "blue")
+ self.text.tag_configure("bold", font = "TkDefaultFont 9 bold")
+
+ self.text.tag_bind("link", "<1>", self.link)
+
+ self.text["state"] = "disabled"
+
+
+ def treeSelect(self, event):
+ "called when tree item is clicked on"
+ item = self.tree.identify("item", event.x, event.y)
+ if item:
+ self.makeText(item)
+ if self.tree.get_children(item):
+ self.tree.see(self.tree.get_children(item)[0])
+ self.goneThrough[0] = self.goneThrough[0][:self.goneThrough[1] + 1]
+ self.goneThrough[0].append(item)
+ self.goneThrough[1] += 1
+
+
+ def link(self, event):
+ "function that is called when linked term is clicked on"
+ item = self.text.get(self.text.tag_prevrange("link", "current")[0],
+ self.text.tag_prevrange("link",
+ "current")[1]).replace(" ",
+ "_").capitalize()
+ # needed for mapped links (i.e. those in format: $l$distance$Total_distance)
+ if item in self.linkMapping.keys():
+ item = self.linkMapping[item]
+ self.makeText(item)
+ self.goneThrough[0] = self.goneThrough[0][:self.goneThrough[1] + 1]
+ self.goneThrough[0].append(item)
+ self.goneThrough[1] += 1
+ self.tree.selection_set(item)
+ self.tree.see(item)
+
+
+
+
+
+
+def main():
+ os.chdir("\\".join(os.getcwd().split("\\")[:-2]))
+ testGUI = Tk()
+ HelpCM(testGUI)
+ testGUI.mainloop()
+
+if __name__ == "__main__": main()

0 comments on commit 6c8257f

Please sign in to comment.