MainApplication.__init__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
c 2
b 0
f 0
dl 0
loc 13
rs 9.4285
1
import logging
2
import os
3
import tkinter
4
import tkinter.filedialog
5
6
import yaml
7
8
from msquaredc import persistence
9
from msquaredc import utils
10
from msquaredc.ui.gui.widgets import ScaleWidget
11
12
13
class MainFrame(object):  # pragma no cover
14
    def __init__(self, widgets):
15
        self.widgets = widgets
16
        self.tk = tkinter.Tk()
17
        self.tk.title("msquaredc")
18
        self.q = self.a = None
19
        self.__is_fullscreen = False
20
        self.frame = tkinter.Frame(self.tk)
21
        self.frame.grid(row=0, column=0)
22
        self.init_keybindings()
23
        self.init_menubar()
24
        self.init_content()
25
        self.open_files = {"save": None, "open": None}
26
        self.__input = None
27
        self.showResults("<No file loaded!>", "<Please open a file!>")
28
        self.act = None
29
        self.prev = []
30
        self.user = None
31
32
    def init(self):
33
        # Show NameDialog
34
        # validate output
35
        # draw gui
36
        pass
37
38
    def init_menubar(self):
39
        menubar = tkinter.Menu(self.tk)
40
        self.tk.config(menu=menubar)
41
42
        fileMenu = tkinter.Menu(menubar)
43
44
        fileMenu.add_command(label="Open", command=persistence.open_file)
45
        fileMenu.add_command(label="Save", command=self.save_file)
46
47
        fileMenu.add_separator()
48
49
        fileMenu.add_command(label="Exit", underline=0, command=self.onExit)
50
        menubar.add_cascade(label="File", underline=0, menu=fileMenu)
51
52
    def showResults(self, q, a):
53
        self.q = tkinter.Label(self.tk, text=q)
54
        self.q.grid(column=2, row=1, sticky=tkinter.NSEW, columnspan=1)
55
        self.a = tkinter.Label(self.tk, text=a)
56
        self.a.grid(column=2, row=2, sticky=tkinter.NSEW, columnspan=1)
57
58
    def init_content(self):
59
        for i, j in enumerate(self.widgets):
60
            j.draw(self.tk, i + 3)
61
        self.tk.grid_rowconfigure(0, weight=1)
62
        self.tk.grid_rowconfigure(len(self.widgets) + 3, weight=1)
63
        self.tk.grid_columnconfigure(0, weight=1)
64
        self.tk.grid_columnconfigure(len(self.widgets) + 3, weight=1)
65
66
    def init_keybindings(self):
67
        self.tk.bind("<F11>", self.toggle_fullscreen)
68
        self.tk.bind("<Escape>", self.end_fullscreen)
69
70
    def toggle_fullscreen(self, event=None):
71
        self.__is_fullscreen = not self.__is_fullscreen  # Just toggling the boolean
72
        self.tk.attributes('-fullscreen', self.__is_fullscreen)
73
        self.tk.overrideredirect(self.__is_fullscreen)
74
        return "break"
75
76
    def end_fullscreen(self, event=None):
77
        self.__is_fullscreen = False
78
        self.tk.attributes("-fullscreen", False)
79
        self.tk.overrideredirect(False)
80
        return "break"
81
82
    def save_file(self):
83
        filename = tkinter.filedialog.asksaveasfilename()
84
        try:
85
            file = open(filename, 'w')
86
            self.open_files["save"].append(file)
87
        except FileNotFoundError:
88
            pass
89
90
    def onExit(self):
91
        for category in self.open_files:
92
            self.open_files[category].close()
93
        self.tk.quit()
94
95
    def start(self):
96
        self.tk.mainloop()
97
98
99
class MainApplication(tkinter.Frame):  # pragma no cover
100
    def __init__(self, parent, *args, **kwargs):
101
        tkinter.Frame.__init__(self, parent, *args, **kwargs)
102
        self.parent = parent
103
        self.callbacks = {}
104
        self.statusbar = StatusBar(self)
105
        self.toolbar = ToolBar(parent, self)
106
        self.navbar = NavBar(self)
107
        self.main = Main(self, "config.yml", "jerome.txt")
108
109
        self.statusbar.pack(side="bottom", fill="x")
110
        # self.toolbar.pack(side="top", fill="x")
111
        self.navbar.pack(side="bottom", anchor="se")
112
        self.main.pack(side="top", expand=True)  # fill removed
113
114
    def add_callback(self, name, function):
115
        callbacks = self.get_callbacks(name)
116
        callbacks.append(function)
117
        self.callbacks[name] = callbacks
118
119
    def get_callbacks(self, name):
120
        return self.callbacks.get(name, [])
121
122
    def handle_callback(self, name):
123
        if self.get_callbacks(name):
124
            for i in self.get_callbacks(name):
125
                i()
126
        else:
127
            self.notice("".join(["The event ", name, " has been unhandled!"]))
128
129
    def notice(self, string):
130
        logging.log(logging.INFO, string)
131
        self.statusbar.variable.set(string)
132
133
134
class StatusBar(tkinter.Frame):  # pragma no cover
135
    def __init__(self, master):
136
        tkinter.Frame.__init__(self, master)
137
        self.variable = tkinter.StringVar()
138
        self.label = tkinter.Label(self, bd=1, relief=tkinter.SUNKEN, anchor=tkinter.W,
139
                                   textvariable=self.variable,
140
                                   font=('arial', 10, 'normal'))
141
        self.variable.set('Status Bar')
142
        self.label.pack(fill=tkinter.X)
143
144
145
class NavBar(tkinter.Frame):  # pragma no cover
146
    def __init__(self, master):
147
        tkinter.Frame.__init__(self, master)
148
        self.next = tkinter.Button(text="Next >", command=lambda: master.handle_callback("next"))
149
        self.prev = tkinter.Button(text="< Previous", command=lambda: master.handle_callback("prev"))
150
        self.prev.grid(column=0, row=0, in_=self, pady=5)
151
        self.next.grid(column=1, row=0, in_=self, padx=5, pady=5)
152
153
154
class ToolBar(tkinter.Menu):  # pragma no cover
155
    def __init__(self, master, handler):
156
        tkinter.Menu.__init__(self, master)
157
        master.config(menu=self)
158
159
        fileMenu = tkinter.Menu(self, tearoff=False)
160
161
        fileMenu.add_command(label="Open", command=lambda: handler.handle_callback("open"))
162
        fileMenu.add_command(label="Save", command=lambda: handler.handle_callback("save"))
163
164
        fileMenu.add_separator()
165
166
        fileMenu.add_command(label="Exit", underline=0, command=lambda: handler.handle_callback("exit"))
167
        self.add_cascade(label="File", underline=0, menu=fileMenu)
168
169
170
class Main(tkinter.Frame):  # pragma no cover
171
    def __init__(self, master, paper, data):
172
        tkinter.Frame.__init__(self, master)
173
        master.add_callback("next", lambda: Main.get_next(self))
174
        self.master = master
175
        # Get paper information
176
        ci = None
177
        with open(paper) as stream:
178
            ci = yaml.load(stream)
179
        self.questions = ci["questions"]
180
        self.title = ci["title"]
181
        self.order = ci["order"]
182
        self.show = ci["show"]
183
        self.user = ci["user"]
184
185
        # Get Data
186
        self.data = persistence.obtain(data)
187
188
        self.infofield = InfoField(self)
189
        self.infofield.grid(row=0)
190
        self.infofield.title = self.title
191
        self.widgetfield = WidgetField(self, {})
192
193
        self.current_question_index = 0
194
        self.current_answerer_index = 0
195
        self.start()
196
197
    def run(self):
198
        questions = [i["text"] for i in self.questions]
199
        for i, question in enumerate(self.questions):
200
            # Collect answers to code
201
            # coded = []
202
            if "out{}.txt".format(i) in os.listdir(os.getcwd()):
203
                # coded = persistence.obtain("out{}.txt".format(i))
204
                pass
205
            for answerer in self.data:
206
                for column in answerer:
207
                    if column not in questions:
208
                        pass
209
210
    def start(self):
211
        # Pick question + solution
212
213
        # Build and display
214
        self.infofield.question = self.questions[self.current_question_index]["text"]
215
        self.infofield.answer = self.data[self.current_answerer_index][self.infofield.question]
216
217
        self.widgetfield = WidgetField(self, self.questions[self.current_question_index]["coding"])
218
        self.widgetfield.show()
219
        self.widgetfield.grid(row=1)
220
221
    def get_next(self):
222
        # store previous
223
        used = [i["text"] for i in self.questions]
224
        sample = {i: self.data[self.current_answerer_index][i] for i in self.data[self.current_answerer_index]
225
                  if i not in used}
226
        sample["question"] = self.questions[self.current_question_index]["text"]
227
228
        sample.update(self.widgetfield.get_res_dict())
229
        print(sample)
230
        persistence.persist("out{}.txt".format(self.current_question_index), sample, "a+")
231
232
        self.current_answerer_index += 1
233
        if self.current_answerer_index >= len(self.data):
234
            self.current_answerer_index = 0
235
            self.current_question_index += 1
236
        # Check for resumables
237
238
        if self.current_question_index >= len(self.questions):
239
            self.infofield.question = "Finished"
240
            self.infofield.answer = "You may now leave"
241
        else:
242
            self.infofield.question = self.questions[self.current_question_index]["text"]
243
            if self.infofield.question in self.data[self.current_answerer_index]:
244
                self.infofield.answer = self.data[self.current_answerer_index][self.infofield.question]
245
            else:
246
                best = -1
247
                element = None
248
                for i in self.data[self.current_answerer_index]:
249
                    res = utils.lcs(i, self.infofield.question)
250
                    if len(res) > best:
251
                        element = i
252
                        best = len(res)
253
                self.infofield.answer = self.data[self.current_answerer_index][element]
254
            self.widgetfield.grid_forget()
255
            self.widgetfield.destroy()
256
            self.widgetfield = WidgetField(self, self.questions[self.current_question_index]["coding"])
257
            self.widgetfield.show()
258
            self.widgetfield.grid(row=1)
259
260
261
class InfoField(tkinter.Frame):  # pragma no cover
262
    def __init__(self, master):
263
        font = ("serif", 16)
264
        tkinter.Frame.__init__(self, master)
265
        self.__titlevar = tkinter.StringVar(self, "Title")
266
        self.__title = tkinter.Label(master, textvariable=self.__titlevar, font=("Helvetica", 18), pady=10)
267
        self.__questionvar = tkinter.StringVar(self, "Question")
268
        self.__question = tkinter.Label(master, textvariable=self.__questionvar, anchor=tkinter.W,
269
                                        font=("serif", 16, "bold"),
270
                                        pady=5)
271
        self.__answervar = tkinter.StringVar(self, "Answer")
272
        self.__answer = tkinter.Label(master, textvariable=self.__answervar, anchor=tkinter.W, font=("Times", 16),
273
                                      pady=5,
274
                                      relief="groove")
275
        self.__lengthvar = tkinter.StringVar(self, "Length")
276
        self.__length = tkinter.Label(master, textvariable=self.__lengthvar, anchor=tkinter.W, font=font, pady=5)
277
        self.q = tkinter.Label(self, text="Question:", anchor=tkinter.E, font=font, pady=5)
278
        self.a = tkinter.Label(self, text="Answer:", anchor=tkinter.E, font=font, pady=10)
279
        self.length_label = tkinter.Label(self, text="Length:", anchor=tkinter.E, font=font, pady=5)
280
        self.__title.grid(in_=self, row=0, columnspan=2)
281
        self.q.grid(in_=self, column=0, row=1)
282
        self.__question.grid(in_=self, column=1, row=1)
283
        self.a.grid(in_=self, column=0, row=2)
284
        self.__answer.grid(in_=self, column=1, row=2)
285
        # self.l.grid(in_=self,column=0,row=3)
286
        # self.__length.grid(in_=self,column=1,row=3)
287
288
    @property
289
    def title(self):
290
        return self.__titlevar.get()
291
292
    @title.setter
293
    def title(self, value):
294
        self.__titlevar.set(value)
295
296
    @property
297
    def question(self):
298
        return self.__questionvar.get()
299
300
    @question.setter
301
    def question(self, value):
302
        self.__questionvar.set(value)
303
304
    @property
305
    def answer(self):
306
        return self.__answervar.get()
307
308
    @answer.setter
309
    def answer(self, value):
310
        self.__answervar.set(value)
311
        self.__lengthvar.set(" ".join(["Symbols", str(len(self.answer)), "Words", str(len(self.answer.split(" ")))]))
312
313
    @property
314
    def length(self):
315
        return self.__lengthvar.get()
316
317
    @length.setter
318
    def length(self, value):
319
        self.__lengthvar.set(value)
320
321
322
class WidgetField(tkinter.Frame):  # pragma no cover
323
    def __init__(self, master, criterias):
324
        tkinter.Frame.__init__(self, master)
325
        self.criterias = criterias
326
        self.widgets = []
327
        for i in criterias:
328
            self.widgets.append(ScaleWidget(master, i["criteria"], i["min"], i["max"]))
329
330
    def show(self):
331
        for i, element in enumerate(self.widgets):
332
            element.variables[0].grid(column=0, row=i, in_=self)
333
        for i, element in enumerate(self.widgets):
334
            element.label.grid(column=1, row=i, in_=self)
335
        for i, element in enumerate(self.widgets):
336
            index = 2
337
            for k, j in enumerate(element.variables[1:]):
338
                j.grid(column=index + k, row=i, in_=self)
339
340
    def get_res_dict(self):
341
        return {element.label.cget('text'): element.variables[0].get() for element in self.widgets}
342