def test_calendar_selection(self): widget = Calendar(self.window, month=3, year=2011, day=10, maxdate=date(2013, 1, 1), mindate=date(2010, 1, 1)) widget.pack() self.assertEqual(widget.selection_get(), date(2011, 3, 10)) widget.selection_set(date(2012, 4, 11)) self.assertEqual(widget.selection_get(), date(2012, 4, 11)) self.assertEqual(widget._date, date(2012, 4, 1)) widget.selection_set(datetime(2012, 5, 11)) self.assertEqual(widget.selection_get(), date(2012, 5, 11)) self.assertNotIsInstance(widget.selection_get(), datetime) self.assertIsInstance(widget.selection_get(), date) widget.selection_set(datetime(2012, 5, 21).strftime('%x')) self.assertEqual(widget.selection_get(), date(2012, 5, 21)) self.assertNotIsInstance(widget.selection_get(), datetime) self.assertIsInstance(widget.selection_get(), date) widget.selection_set(date(2018, 4, 11)) self.assertEqual(widget.selection_get(), date(2013, 1, 1)) widget.selection_set(date(2001, 4, 11)) self.assertEqual(widget.selection_get(), date(2010, 1, 1)) widget.selection_clear() self.assertIsNone(widget.selection_get())
def test_calendar_buttons_functions(self): widget = Calendar(self.window) widget.pack() widget._prev_month() widget._next_month() widget._prev_year() widget._next_year() widget._remove_selection() widget.selection_set(format_date(date(2018, 12, 31), 'short')) self.assertEqual(widget.selection_get(), date(2018, 12, 31)) with self.assertRaises(ValueError): widget.selection_set("ab") widget.selection_set(None) self.assertIsNone(widget.selection_get()) widget.selection_set(date(2015, 12, 31)) self.assertEqual(widget.selection_get(), date(2015, 12, 31)) widget.config(selectmode='none') self.assertIsNone(widget.selection_get()) l = ttk.Label(widget, text="12") widget._on_click(TestEvent(widget=l)) self.assertIsNone(widget.selection_get()) self.window.update() widget.config(selectmode='day') l = ttk.Label(widget, text="12") widget._on_click(TestEvent(widget=l)) self.window.update() self.assertEqual(widget.selection_get(), date(2015, 12, 12)) widget.config(state='disabled') l = ttk.Label(widget, text="14") widget._on_click(TestEvent(widget=l)) self.window.update() self.assertEqual(widget.selection_get(), date(2015, 12, 12))
def test_calendar_textvariable(self): var = tk.StringVar(self.window) widget = Calendar(self.window, selectmode='day', year=2015, month=1, day=3, textvariable=var) widget.pack() self.window.update() self.assertEqual('', var.get()) self.assertEqual('', widget.get_date()) self.assertEqual(date(2015, 1, 1), widget._date) widget.selection_set(date(2018, 11, 21)) self.window.update() self.assertEqual(format_date(date(2018, 11, 21), 'short'), var.get()) self.assertEqual(format_date(date(2018, 11, 21), 'short'), widget.get_date()) widget.selection_set(None) self.window.update() self.assertEqual('', widget.get_date()) self.assertEqual('', var.get()) var.set(format_date(date(2014, 3, 2), 'short')) self.window.update() self.assertEqual(date(2014, 3, 2), widget.selection_get()) self.assertEqual(format_date(date(2014, 3, 2), 'short'), var.get()) self.assertEqual(format_date(date(2014, 3, 2), 'short'), widget.get_date()) try: var.set('a') except tk.TclError: # some versions of python raise an error because of the exception # raised inside the trace pass self.window.update() self.assertEqual(date(2014, 3, 2), widget.selection_get()) self.assertEqual(format_date(date(2014, 3, 2), 'short'), var.get()) self.assertEqual(format_date(date(2014, 3, 2), 'short'), widget.get_date()) var.set('') self.window.update() self.assertIsNone(widget.selection_get()) self.assertEqual('', var.get()) self.assertEqual('', widget.get_date()) var2 = tk.StringVar(widget, format_date(date(2011, 1, 21), 'short')) widget['textvariable'] = var2 self.window.update() self.assertEqual(widget.get_date(), var2.get()) self.assertEqual('', var.get())
def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller cryptocurrency_list = [ c[:-4] for c in controller.shared_data["cryptocurrency_list"] ] cryptocurrency_list.sort() welcome_label = tk.Label(self, text="Escolha a data", font=("Verdana", 35)) welcome_label.pack(fill=tk.X, pady=30) self.selected_day = tk.StringVar() self.cryptocurrency = tk.StringVar() self.cryptocurrency.set("Selecione a criptomoeda") self.selected_day.trace("w", self.show_predict) self.cryptocurrency.trace("w", self.show_predict) cal = Calendar(self, selectmode='day', mindate=date.today(), textvariable=self.selected_day, date_pattern="yyyy-mm-dd") cal.selection_set(date.today()) cal.pack() cryptocurrency_menu = tk.OptionMenu(self, self.cryptocurrency, *cryptocurrency_list) cryptocurrency_menu.config(font=("Verdana", 16)) cryptocurrency_menu.pack(pady=50) self.value = tk.Label(self, text="US$: ", font=("Verdana", 20, "bold")) self.value.pack(fill=tk.X, pady=30) back_button = tk.Button( self, text="Voltar", font=("Verdana", 14), height=2, width=20, command=lambda: controller.show_frame(page_list.RESULT_PAGE)) back_button.pack(pady=50)
class AUView(tk.Toplevel): def __init__(self, parent_view): super().__init__(parent_view) self.parent = parent_view self.title('AU/krank Eintragen') startdatum_label = tk.Label(self, text="von") self.startdatum_input = Calendar(self, date_pattern='MM/dd/yyyy') enddatum_label = tk.Label(self, text="bis") self.enddatum_input = Calendar(self, date_pattern='MM/dd/yyyy') self.save_button = tk.Button(self, text="Daten speichern") self.exit_button = tk.Button(self, text="Abbrechen", command=self.destroy) self.saveandnew_button = tk.Button(self, text="Daten speichern und neu") # ins Fenster packen startdatum_label.grid(row=1, column=0, sticky=tk.NW) self.startdatum_input.grid(row=1, column=1, columnspan=2, sticky=tk.NW) enddatum_label.grid(row=1, column=3, sticky=tk.NW) self.enddatum_input.grid(row=1, column=4, sticky=tk.NW) self.save_button.grid(row=15, column=0, sticky=tk.NW) self.exit_button.grid(row=15, column=1, sticky=tk.NW) self.saveandnew_button.grid(row=15, column=2, sticky=tk.NW) def set_data(self, **kwargs): self.startdatum_input.selection_set(kwargs['beginn']) self.enddatum_input.selection_set(kwargs['ende']) def get_data(self): startdatum_date_obj = datetime.strptime( self.startdatum_input.get_date(), '%m/%d/%Y') enddatum_date_obj = datetime.strptime(self.enddatum_input.get_date(), '%m/%d/%Y') return {'beginn': startdatum_date_obj, 'ende': enddatum_date_obj}
def test_calendar_textvariable(self): var = tk.StringVar(self.window,) widget = Calendar(self.window, selectmode='day', locale=None, year=2015, month=1, day=3, textvariable=var) widget.pack() self.window.update() self.assertEqual(datetime(2015, 1, 3).strftime('%x'), var.get()) self.assertEqual(datetime(2015, 1, 3).strftime('%x'), widget.get_date()) widget.selection_set(datetime(2018, 11, 21)) self.window.update() self.assertEqual(datetime(2018, 11, 21).strftime('%x'), var.get()) self.assertEqual(datetime(2018, 11, 21).strftime('%x'), widget.get_date()) widget.selection_set(None) self.window.update() self.assertEqual('', widget.get_date()) self.assertEqual('', var.get()) var.set(datetime(2014, 3, 2).strftime('%x')) self.window.update() self.assertEqual(datetime(2014, 3, 2), widget.selection_get()) self.assertEqual(datetime(2014, 3, 2).strftime('%x'), var.get()) self.assertEqual(datetime(2014, 3, 2).strftime('%x'), widget.get_date()) try: var.set('a') except tk.TclError: # some versions of python raise an error because of the exception # raised inside the trace pass self.window.update() self.assertEqual(datetime(2014, 3, 2), widget.selection_get()) self.assertEqual(datetime(2014, 3, 2).strftime('%x'), var.get()) self.assertEqual(datetime(2014, 3, 2).strftime('%x'), widget.get_date()) var.set('') self.window.update() self.assertIsNone(widget.selection_get()) self.assertEqual('', var.get()) self.assertEqual('', widget.get_date())
def test_calendar_buttons_functions(self): widget = Calendar(self.window) widget.pack() widget._prev_month() widget._next_month() widget._prev_year() widget._next_year() widget._remove_selection() widget.selection_set(datetime(2018, 12, 31).strftime('%x')) self.assertEqual(widget.selection_get(), datetime(2018, 12, 31)) with self.assertRaises(ValueError): widget.selection_set("ab") widget.selection_set(None) self.assertIsNone(widget.selection_get()) widget.selection_set(datetime(2015, 12, 31)) self.assertEqual(widget.selection_get(), datetime(2015, 12, 31)) widget.config(selectmode='none') self.assertIsNone(widget.selection_get()) l = ttk.Label(widget, text="12") widget._on_click(TestEvent(widget=l))
class AssistentNewEditView(tk.Toplevel): def __init__(self, parent): super().__init__(parent) self.parent = parent headline = tk.Label(self, text="Wer bist du denn eigentlich?") vorname_label = tk.Label(self, text="Vorname") self.vorname_input = tk.Entry(self, bd=5, width=40) name_label = tk.Label(self, text="Nachname") self.name_input = tk.Entry(self, bd=5, width=40) email_label = tk.Label(self, text="Email") self.email_input = tk.Entry(self, bd=5, width=40) strasse_label = tk.Label(self, text="Straße/Hausnummer") self.strasse_input = tk.Entry(self, bd=5, width=29) self.hausnummer_input = tk.Entry(self, bd=5, width=9) plz_label = tk.Label(self, text="Postleitzahl") self.plz_input = tk.Entry(self, bd=5, width=40) stadt_label = tk.Label(self, text="Stadt") self.stadt_input = tk.Entry(self, bd=5, width=40) einstellungsdatum_label = tk.Label( self, text="Seit wann bei ad? (tt.mm.JJJJ)") self.einstellungsdatum_input = Calendar(self) self.save_button = tk.Button(self, text="Daten speichern") self.exit_button = tk.Button(self, text="Abbrechen", command=self.destroy) # ins Fenster packen headline.grid(row=0, column=0, columnspan=3) vorname_label.grid(row=1, column=0) self.vorname_input.grid(row=1, column=1, columnspan=2) name_label.grid(row=2, column=0) self.name_input.grid(row=2, column=1, columnspan=2) email_label.grid(row=3, column=0) self.email_input.grid(row=3, column=1, columnspan=2) strasse_label.grid(row=4, column=0) self.strasse_input.grid(row=4, column=1) self.hausnummer_input.grid(row=4, column=2) plz_label.grid(row=5, column=0) self.plz_input.grid(row=5, column=1, columnspan=2) stadt_label.grid(row=6, column=0) self.stadt_input.grid(row=6, column=1, columnspan=2) einstellungsdatum_label.grid(row=7, column=0, sticky="nw") self.einstellungsdatum_input.grid(row=7, column=1) self.exit_button.grid(row=8, column=0) self.save_button.grid(row=8, column=1) def set_data(self, **kwargs): self.vorname_input.insert(0, kwargs['vorname']) self.name_input.insert(0, kwargs['name']) self.email_input.insert(0, kwargs['email']) self.strasse_input.insert(0, kwargs['strasse']) self.hausnummer_input.insert(0, kwargs['hausnummer']) self.plz_input.insert(0, kwargs['plz']) self.stadt_input.insert(0, kwargs['stadt']) self.einstellungsdatum_input.selection_set(kwargs['einstellungsdatum']) def get_data(self): einstellungsdatum_date_obj = datetime.strptime( self.einstellungsdatum_input.get_date(), '%m/%d/%y') return { 'name': self.name_input.get(), 'vorname': self.vorname_input.get(), 'email': self.email_input.get(), 'einstellungsdatum': einstellungsdatum_date_obj, 'strasse': self.strasse_input.get(), 'hausnummer': self.hausnummer_input.get(), 'plz': self.plz_input.get(), 'stadt': self.stadt_input.get() }
class ChooseIntervalPage(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller cryptocurrency_list = [ c[:-4] for c in controller.shared_data["cryptocurrency_list"] ] cryptocurrency_list.sort() welcome_label = tk.Label(self, text="Escolha a data", font=("Verdana", 35)) welcome_label.pack(fill=tk.X, pady=15) self.selected_day_start = tk.StringVar() self.selected_day_end = tk.StringVar() self.cryptocurrency = tk.StringVar() self.cryptocurrency.set("Selecione a criptomoeda") calendar_area = tk.Frame(self) calendar_area.pack() start_label = tk.Label(calendar_area, text="Data de Início", font=("Verdana", 18)) start_label.grid(row=0, column=0, padx=20) calendar_start = tk.Frame(calendar_area) calendar_start.grid(row=1, column=0, padx=20) end_label = tk.Label(calendar_area, text="Data de Término", font=("Verdana", 18)) end_label.grid(row=0, column=1, padx=20) calendar_end = tk.Frame(calendar_area) calendar_end.grid(row=1, column=1, padx=20) self.cal_start = Calendar(calendar_start, selectmode='day', mindate=date.today(), textvariable=self.selected_day_start, date_pattern="yyyy-mm-dd") self.cal_start.selection_set(date.today()) self.cal_start.pack() self.cal_end = Calendar(calendar_end, selectmode='day', mindate=date.today(), textvariable=self.selected_day_end, date_pattern="yyyy-mm-dd") self.cal_end.selection_set(date.today()) self.cal_end.pack() cryptocurrency_menu = tk.OptionMenu(self, self.cryptocurrency, *cryptocurrency_list) cryptocurrency_menu.config(font=("Verdana", 16)) cryptocurrency_menu.pack(pady=20) self.container_plot = tk.Frame(self, relief=tk.RAISED, height=350) self.container_plot.pack() button_area = tk.Frame(self) button_area.pack() back_button = tk.Button( button_area, text="Voltar", font=("Verdana", 14), height=2, width=20, command=lambda: controller.show_frame(page_list.RESULT_PAGE)) back_button.grid(row=0, column=0, padx=10, pady=10) predict_button = tk.Button(button_area, text="Fazer previsão", font=("Verdana", 14), height=2, width=20, command=lambda: self.predict()) predict_button.grid(row=0, column=1, padx=10, pady=10) self.save_table_button = tk.Button(button_area, text="Salvar\n(Tabela)", font=("Verdana", 14), height=2, width=20, state=tk.DISABLED, command=lambda: self.save_table()) self.save_table_button.grid(row=0, column=2, padx=10, pady=10) self.save_image_button = tk.Button(button_area, text="Salvar\n(Gráfico)", font=("Verdana", 14), height=2, width=20, state=tk.DISABLED, command=lambda: self.save_image()) self.save_image_button.grid(row=0, column=3, padx=10, pady=10) self.selected_day_start.trace("w", self.update_calendar) def predict(self): self.save_table_button["state"] = tk.DISABLED self.save_image_button["state"] = tk.DISABLED cryptocurrency = self.cryptocurrency.get() if cryptocurrency == "Selecione a criptomoeda": return selected_day_start = self.selected_day_start.get() selected_day_end = self.selected_day_end.get() self.predicted_values = self.controller.predict( cryptocurrency, selected_day_start, selected_day_end) self.predict_dates = [] selected_day_start = datetime.date.fromisoformat(selected_day_start) selected_day_end = datetime.date.fromisoformat(selected_day_end) delta = datetime.timedelta(days=1) while selected_day_start <= selected_day_end: self.predict_dates.append(selected_day_start.strftime('%d/%m')) selected_day_start += delta for child in self.container_plot.winfo_children(): child.destroy() fig = Figure(figsize=(7, 3.5)) a = fig.add_subplot(111) a.plot(self.predict_dates, self.predicted_values, color='blue', label='Predicted ' + cryptocurrency + ' Price') a.xaxis.set_major_locator( plt.MaxNLocator(min(10, len(self.predict_dates)))) a.set_title(cryptocurrency + ' Price Prediction') a.set_ylabel(cryptocurrency + ' Price', fontsize=14) canvas = FigureCanvasTkAgg(fig, master=self.container_plot) canvas.get_tk_widget().pack() canvas.draw() self.image = fig self.save_table_button["state"] = tk.NORMAL self.save_image_button["state"] = tk.NORMAL def save_table(self): path = filedialog.asksaveasfilename( initialdir="/", title="Selecione o Local para Salvar", filetypes=[("CSV files", "*.csv")]) if isinstance(path, tuple) or path == '': return dataframe = { "Date": self.predict_dates, "Closing Price (USD)": self.predicted_values } dataframe = pd.DataFrame(dataframe, columns=['Date', 'Closing Price (USD)']) dataframe.to_csv(path, index=False, header=True) def save_image(self): path = filedialog.asksaveasfilename( initialdir="/", title="Selecione o Local para Salvar", filetypes=[("PNG files", "*.png")]) if isinstance(path, tuple) or path == '': return self.image.savefig(path) def update_calendar(self, *args): selected_day_start = datetime.date.fromisoformat( self.selected_day_start.get()) selected_day_end = datetime.date.fromisoformat( self.selected_day_end.get()) delta = datetime.timedelta(days=1) if selected_day_end < selected_day_start: self.cal_end.selection_set(selected_day_start + delta) self.cal_end["mindate"] = selected_day_start + delta
def test_calendar_get_set(self): widget = Calendar(self.window, foreground="red", year=2010, month=1, day=3) widget.pack() self.window.update() options = [ 'cursor', 'font', 'borderwidth', 'state', 'selectmode', 'textvariable', 'locale', 'date_pattern', 'mindate', 'maxdate', 'firstweekday', 'weekenddays', 'showweeknumbers', 'showothermonthdays', 'selectbackground', 'selectforeground', 'disabledselectbackground', 'disabledselectforeground', 'normalbackground', 'normalforeground', 'background', 'foreground', 'bordercolor', 'disabledbackground', 'disabledforeground', 'othermonthforeground', 'othermonthbackground', 'othermonthweforeground', 'othermonthwebackground', 'weekendbackground', 'weekendforeground', 'headersbackground', 'headersforeground', 'disableddaybackground', 'disableddayforeground', 'tooltipbackground', 'tooltipforeground', 'tooltipalpha', 'tooltipdelay' ] self.assertEqual(sorted(widget.keys()), sorted(options)) with self.assertRaises(AttributeError): widget.cget("test") self.assertEqual(widget["foreground"], "red") widget["foreground"] = "blue" self.window.update() self.assertEqual(widget["foreground"], "blue") widget.configure({ 'foreground': 'cyan', 'background': 'green' }, background="blue", borderwidth=4) self.window.update() self.assertEqual(widget["foreground"], "cyan") self.assertEqual(widget["background"], "blue") self.assertEqual(widget["borderwidth"], 4) widget.config(locale='fr_FR') self.assertEqual(widget['locale'], 'fr_FR') self.assertEqual(widget._week_days[0].cget('text'), 'lun.') widget.config(locale='en_US') self.assertEqual(widget['locale'], 'en_US') self.assertEqual(widget._week_days[0].cget('text'), 'Mon') with self.assertRaises(UnknownLocaleError): widget.config(locale="jp") widget.config(cursor="watch") self.window.update() self.assertEqual(widget["cursor"], "watch") self.assertTrue(widget["showweeknumbers"]) self.assertNotEqual(widget._week_nbs[0].grid_info(), {}) widget.config(showweeknumbers=False) self.window.update() self.assertFalse(widget["showweeknumbers"]) self.assertEqual(widget._week_nbs[0].grid_info(), {}) self.assertFalse(widget._week_nbs[0].winfo_ismapped()) self.assertNotEqual(widget._calendar[-1][-1].cget('text'), '') self.assertTrue(widget["showothermonthdays"]) widget.config(showothermonthdays=False) self.window.update() self.assertFalse(widget["showothermonthdays"]) self.assertEqual(widget._calendar[-1][-1].cget('text'), '') widget.config(font="Arial 20 bold") self.window.update() self.assertEqual(widget["font"], "Arial 20 bold") widget.config(borderwidth=5) self.window.update() self.assertEqual(widget["borderwidth"], 5) with self.assertRaises(ValueError): widget.config(borderwidth="a") widget.config(firstweekday='sunday') self.window.update() self.assertEqual(widget["firstweekday"], 'sunday') with self.assertRaises(ValueError): widget.config(firstweekday="a") widget.config(weekenddays=[5, 7]) self.window.update() we_style = 'we.%s.TLabel' % widget._style_prefixe normal_style = 'normal.%s.TLabel' % widget._style_prefixe for i in range(7): self.assertEqual(widget._calendar[0][i].cget('style'), we_style if (i + 1) in [5, 7] else normal_style) widget["mindate"] = datetime(2018, 9, 10) self.assertEqual(widget["mindate"], date(2018, 9, 10)) widget.selection_set(date(2018, 9, 23)) self.window.update() i, j = widget._get_day_coords(date(2018, 9, 2)) self.assertIn('disabled', widget._calendar[i][j].state()) i, j = widget._get_day_coords(date(2018, 9, 21)) self.assertNotIn('disabled', widget._calendar[i][j].state()) self.assertIn('disabled', widget._l_month.state()) self.assertIn('disabled', widget._l_year.state()) i, j = widget._get_day_coords(date(2018, 9, 10)) self.assertNotIn('disabled', widget._calendar[i][j].state()) i, j = widget._get_day_coords(date(2018, 9, 9)) self.assertIn('disabled', widget._calendar[i][j].state()) with self.assertRaises(TypeError): widget.config(mindate="a") self.assertEqual(widget["mindate"], date(2018, 9, 10)) widget["mindate"] = None self.window.update() self.assertIsNone(widget["mindate"]) i, j = widget._get_day_coords(date(2018, 9, 2)) self.assertNotIn('disabled', widget._calendar[i][j].state()) self.assertNotIn('disabled', widget._l_month.state()) self.assertNotIn('disabled', widget._l_year.state()) widget["maxdate"] = datetime(2018, 9, 10) self.assertEqual(widget["maxdate"], date(2018, 9, 10)) widget.selection_set(date(2018, 9, 2)) self.window.update() i, j = widget._get_day_coords(date(2018, 9, 22)) self.assertIn('disabled', widget._calendar[i][j].state()) i, j = widget._get_day_coords(date(2018, 9, 4)) self.assertNotIn('disabled', widget._calendar[i][j].state()) self.assertIn('disabled', widget._r_month.state()) self.assertIn('disabled', widget._r_year.state()) i, j = widget._get_day_coords(date(2018, 9, 10)) self.assertNotIn('disabled', widget._calendar[i][j].state()) i, j = widget._get_day_coords(date(2018, 9, 11)) self.assertIn('disabled', widget._calendar[i][j].state()) with self.assertRaises(TypeError): widget.config(maxdate="a") self.assertEqual(widget["maxdate"], date(2018, 9, 10)) widget["maxdate"] = None self.window.update() self.assertIsNone(widget["maxdate"]) i, j = widget._get_day_coords(date(2018, 9, 22)) self.assertNotIn('disabled', widget._calendar[i][j].state()) self.assertNotIn('disabled', widget._r_month.state()) self.assertNotIn('disabled', widget._r_year.state()) widget.config(selectmode="none") self.window.update() self.assertEqual(widget["selectmode"], "none") widget.config(selectmode="day") self.window.update() self.assertEqual(widget["selectmode"], "day") with self.assertRaises(ValueError): widget.config(selectmode="a") self.assertEqual(widget.cget('state'), tk.NORMAL) with self.assertRaises(ValueError): widget.config(state="test") widget['date_pattern'] = 'MM/dd/yyyy' self.window.update() self.assertEqual(widget["date_pattern"], 'MM/dd/yyyy') with self.assertRaises(ValueError): widget.config(date_pattern="mm-dd-cc") with self.assertRaises(AttributeError): widget.config(test="test") dic = {op: "yellow" for op in options[12:-4]} widget.configure(**dic) self.window.update() for op in options[12:-4]: self.assertEqual(widget.cget(op), "yellow") widget.config(tooltipalpha=0.5) self.assertEqual(widget["tooltipalpha"], 0.5) self.assertEqual(widget.tooltip_wrapper["alpha"], 0.5) widget.config(tooltipdelay=1000) self.assertEqual(widget["tooltipdelay"], 1000) self.assertEqual(widget.tooltip_wrapper["delay"], 1000) widget.config(tooltipforeground='black') self.assertEqual(widget["tooltipforeground"], 'black') widget.config(tooltipbackground='cyan') self.assertEqual(widget["tooltipbackground"], 'cyan')
class SchichtView(tk.Toplevel): def __init__(self, parent_view, asn_liste, adressliste): super().__init__(parent_view) # unterframes zur optisch-logischen Einteilung self.asn_frame = tk.Frame(self) self.datetime_frame = tk.Frame(self) self.template_frame = tk.Frame(self.asn_frame) self.add_options_frame = tk.Frame(self) self.add_options_checkbuttons_frame = tk.Frame(self.add_options_frame) self.save_buttons_frame = tk.Frame(self) self.asn_dropdown = Combobox(self.asn_frame, values=asn_liste, width=38, state="readonly") self.asn_dropdown.set(-1) self.selected_template = tk.IntVar() self.asn_stammdaten_form = AsnStammdatenView( parent_view=self.asn_frame) self.startdatum_input = Calendar(self.datetime_frame, date_pattern='MM/dd/yyyy') # day=day, # month=month, # year=year) self.startzeit_input = TimePicker(self.datetime_frame) self.endzeit_input = TimePicker(self.datetime_frame) self.startzeit_input.bind('<FocusOut>', self.nachtschicht_durch_uhrzeit) self.endzeit_input.bind('<FocusOut>', self.nachtschicht_durch_uhrzeit) self.enddatum_input = Calendar(self.datetime_frame, date_pattern='MM/dd/yyyy') # , day=day, month=month, year=year) self.abweichende_adresse_beginn = PostadresseView( self.add_options_frame) self.abweichende_adresse_ende = PostadresseView(self.add_options_frame) self.abweichende_adresse_beginn_dropdown = Combobox( self.add_options_frame, values=adressliste, width=38, state="readonly") self.abweichende_adresse_beginn_dropdown.set(-2) self.abweichende_adresse_ende_dropdown = Combobox( self.add_options_frame, values=adressliste, width=38, state="readonly") self.abweichende_adresse_ende_dropdown.set(-2) self.ist_at = tk.IntVar() self.ist_pcg = tk.IntVar() self.ist_rb = tk.IntVar() self.ist_afg = tk.IntVar() self.ist_at_button = tk.Checkbutton( self.add_options_checkbuttons_frame, text="AT", onvalue=1, offvalue=0, variable=self.ist_at) self.ist_pcg_button = tk.Checkbutton( self.add_options_checkbuttons_frame, text="PCG", onvalue=1, offvalue=0, variable=self.ist_pcg) self.ist_rb_button = tk.Checkbutton( self.add_options_checkbuttons_frame, text="Kurzfristig (RB/BSD)", onvalue=1, offvalue=0, variable=self.ist_rb) self.ist_afg_button = tk.Checkbutton( self.add_options_checkbuttons_frame, text="Ausfallgeld", onvalue=1, offvalue=0, variable=self.ist_afg) # formbuttons self.save_button = tk.Button(self.save_buttons_frame, text="Daten speichern") self.exit_button = tk.Button(self.save_buttons_frame, text="Abbrechen") # command=self.destroy) self.saveandnew_button = tk.Button(self.save_buttons_frame, text="Daten speichern und neu") # command=lambda: self.action_save_neue_schicht(undneu=1)) def draw_templates(self, template_list): for child in self.template_frame.winfo_children(): child.destroy() if not template_list: self.add_template_text() else: for template in template_list: text = template.bezeichner text += " von " + template.beginn.strftime('%H:%M') \ + " bis " + template.ende.strftime('%H:%M') button = tk.Radiobutton( self.template_frame, text=text, variable=self.selected_template, value=template.id, command=lambda: self.change_template(template_list)) button.pack() def nachtschicht_durch_uhrzeit(self, event=None): start = time(hour=int(self.startzeit_input.hourstr.get()), minute=int(self.startzeit_input.minstr.get())) ende = time(hour=int(self.endzeit_input.hourstr.get()), minute=int(self.endzeit_input.minstr.get())) beginn = self.startdatum_input.selection_get() if ende < start: enddatum = beginn + timedelta(days=1) else: enddatum = beginn self.enddatum_input.selection_set(enddatum) def change_template(self, template_list): template_id = self.selected_template.get() for template in template_list: if template_id == template.id: self.startzeit_input.hourstr.set( template.beginn.strftime('%H')) self.startzeit_input.minstr.set(template.beginn.strftime('%M')) self.endzeit_input.hourstr.set(template.ende.strftime('%H')) self.endzeit_input.minstr.set(template.ende.strftime('%M')) self.nachtschicht_durch_uhrzeit() break def draw(self): # positionierung der Unterframes self.asn_frame.grid(row=0, column=0, sticky=tk.NW) self.datetime_frame.grid(row=0, column=1, sticky=tk.NW) self.template_frame.grid(row=1, column=0, sticky=tk.NW, columnspan=4) self.add_options_frame.grid(row=2, column=0, columnspan=2, sticky=tk.NW) self.add_options_checkbuttons_frame.grid(row=3, column=0, columnspan=2, sticky=tk.NW) self.save_buttons_frame.grid(row=3, column=0, columnspan=2, sticky=tk.NE) # asn-frame asn_label = tk.Label(self.asn_frame, text='ASN auswählen') asn_label.grid(row=0, column=0, sticky=tk.NW) self.asn_dropdown.grid(row=0, column=1, sticky=tk.NE) self.asn_stammdaten_form.grid(row=1, column=0, columnspan=2, sticky=tk.NW) # datetime-frame startdatum_label = tk.Label(self.datetime_frame, text='Beginn') startdatum_label.grid(row=0, column=0, sticky=tk.NW) self.startdatum_input.grid(row=1, column=0, sticky=tk.NW, columnspan=2) self.startzeit_input.grid(row=0, column=1, sticky=tk.NW) enddatum_label = tk.Label(self.datetime_frame, text='Ende') enddatum_label.grid(row=0, column=2, sticky=tk.NW) self.enddatum_input.grid(row=1, column=2, sticky=tk.NW, columnspan=2) self.endzeit_input.grid(row=0, column=3, sticky=tk.NW) # add-options-frame abweichende_adresse_beginn_label = tk.Label( self.add_options_frame, text="Adresse zu beginn der Schicht?") abweichende_adresse_ende_label = tk.Label( self.add_options_frame, text="Adresse zum Ende der Schicht?") abweichende_adresse_beginn_label.grid(row=0, column=0, sticky=tk.NW) self.abweichende_adresse_beginn_dropdown.grid(row=1, column=0, sticky=tk.NE) self.abweichende_adresse_beginn.grid(row=2, column=0, sticky=tk.NW) abweichende_adresse_ende_label.grid(row=0, column=1, sticky=tk.NW) self.abweichende_adresse_ende_dropdown.grid(row=1, column=1, sticky=tk.NE) self.abweichende_adresse_ende.grid(row=2, column=1, sticky=tk.NW) self.ist_at_button.grid(row=0, column=0, sticky=tk.NW) self.ist_pcg_button.grid(row=0, column=1, sticky=tk.NW) self.ist_rb_button.grid(row=0, column=2, sticky=tk.NW) self.ist_afg_button.grid(row=0, column=3, sticky=tk.NW) # save-button-frame self.save_button.grid(row=0, column=0) self.exit_button.grid(row=0, column=1) self.saveandnew_button.grid(row=0, column=2) @staticmethod def hide(frame: tk.Frame): frame.grid_remove() @staticmethod def show(frame: tk.Frame): frame.grid() def add_template_text(self): # template-frame template_text = tk.Label( self.template_frame, justify="left", text='Wenn der Assistent "Schicht-Vorlagen" hat,\n' 'stehen diese hier zur Auswahl.\n\n' 'Das ist absolut anzuraten, da es das Eintragen\n' 'von Schichten deutlich beschleunigt. \n\n' 'Die Möglichkeit dazu findest Du im Hauptfenster unter: \n' 'Bearbeiten -> ASN bearbeiten') template_text.pack() def set_data(self, **kwargs): """ parst alle daten ins Formular :param kwargs: :return: """ if 'asn' in kwargs.keys(): self.asn_dropdown.set(kwargs['asn']) if 'asn_stammdaten' in kwargs.keys(): self.asn_stammdaten_form.set_data(**kwargs['asn_stammdaten']) if 'beginn' in kwargs.keys(): self.startdatum_input.selection_set(date=kwargs['beginn']) self.startzeit_input.hourstr.set(kwargs['beginn'].strftime('%H')) self.startzeit_input.minstr.set(kwargs['beginn'].strftime('%M')) if 'ende' in kwargs.keys(): self.enddatum_input.selection_set(date=kwargs['ende']) self.endzeit_input.hourstr.set(kwargs['ende'].strftime('%H')) self.endzeit_input.minstr.set(kwargs['ende'].strftime('%M')) self.ist_at.set( 1 if 'ist_at' in kwargs.keys() and kwargs['ist_at'] else 0) self.ist_pcg.set( 1 if 'ist_pcg' in kwargs.keys() and kwargs['ist_pcg'] else 0) self.ist_rb.set( 1 if 'ist_rb' in kwargs.keys() and kwargs['ist_rb'] else 0) self.ist_afg.set( 1 if 'ist_afg' in kwargs.keys() and kwargs['ist_afg'] else 0) # TODO Zurücksetzen bei Change ASN if 'abweichende_adresse_beginn' in kwargs.keys(): if kwargs['abweichende_adresse_beginn']: self.abweichende_adresse_beginn_dropdown.set( kwargs['abweichende_adresse_beginn']) if 'abweichende_adresse_ende' in kwargs.keys(): if kwargs['abweichende_adresse_ende']: self.abweichende_adresse_ende_dropdown.set( kwargs['abweichende_adresse_ende']) def get_data(self): return { 'asn_id': self.asn_dropdown.get(), 'asn_stammdaten': self.asn_stammdaten_form.get_data(), 'startdatum': self.startdatum_input.get_date(), 'startzeit_stunde': self.startzeit_input.hourstr.get(), 'startzeit_minute': self.startzeit_input.minstr.get(), 'enddatum': self.enddatum_input.get_date(), 'endzeit_stunde': self.endzeit_input.hourstr.get(), 'endzeit_minute': self.endzeit_input.minstr.get(), 'abweichende_adresse_beginn': self.abweichende_adresse_beginn_dropdown.get(), 'abweichende_adresse_beginn_data': self.abweichende_adresse_beginn.get_data(), 'abweichende_adresse_ende': self.abweichende_adresse_ende_dropdown.get(), 'abweichende_adresse_ende_data': self.abweichende_adresse_ende.get_data(), 'ist at': self.ist_at.get(), 'ist pcg': self.ist_pcg.get(), 'ist rb': self.ist_rb.get(), 'ist afg': self.ist_afg.get() }
class app(Tk): def __init__(self, screenName=None, baseName=None, className="Doit!", useTk=1, sync=0, use=None): super().__init__(screenName=screenName, baseName=baseName, className=className, useTk=useTk, sync=sync, use=use) self.tcont = TaskContainer() self.new_description = "" self.protocol("WM_DELETE_WINDOW", self.quit_event) icon_src = os.path.dirname(os.path.realpath(__file__)) + '/doit.png' self.tk.call('wm', 'iconphoto', self._w, PhotoImage(file=icon_src)) #self.tcont.today = datetime.date.today() - datetime.timedelta(day=1) # uncomment only for debugging/testing purpose self.current_task = None self.task_list_old = [] self.task_list_wip = [] self.task_list_day = [] self.drow_menu_frame() self.drow_panel() self.drow_list() self.drow_task_frame() self.drow_reschedule_frame() self.drow_new_task_frame() self.drow_complete_frame() if len(self.tcont.task_list) > 0: self.fetch_list() if len(self.tcont.day_tasks_list) > 0: self.update_task_frame() self.task_frame.pack(fill=BOTH, expand=True) if len(self.tcont.old_list) > 0: self.fetch_old() self.tcont.export_db("./snapshot_db.json") def drow_menu_frame(self): def import_fn(): self.tcont.export_db("./snapshot_db.json") self.tcont.import_db() self.fetch_list_event() self.update_task_frame() self.task_frame.pack(fill=BOTH, expand=True) menu_frame = Frame(self, bg="gray") button_frame = Frame(menu_frame, bg="gray") Button(button_frame, text="new task", command=self.new_event).pack(side=LEFT, padx=5, pady=5) Button(button_frame, text="save", command=self.save_event).pack(side=LEFT, padx=5, pady=5) Button(button_frame, text="export", command=self.tcont.export_db).pack(side=LEFT, padx=5, pady=5) Button(button_frame, text="import", command=import_fn).pack(side=LEFT, padx=5, pady=5) button_frame.pack(side=LEFT, padx=20) filter_frame = Frame(menu_frame, bg="gray") Label(filter_frame, text="Filter:", font="LiberationMono-Bold 10", bg="gray").pack(side=LEFT, padx=5, pady=5) self.filter_mod_string = StringVar() self.filter_mod_string.set("") ttk.Combobox(filter_frame, justify=RIGHT, textvariable=self.filter_mod_string, values=[mod for mod in filtask.map_filter.keys()], state="readonly").pack(side=LEFT, padx=5, pady=5) self.filter_text_string = StringVar() self.filter_text_string.set("") filter_entry = Entry(filter_frame, width=70, textvariable=self.filter_text_string, font="LiberationMono-Bold 10") filter_entry.bind("<Return>", self.fetch_list_event) filter_entry.pack(side=LEFT, padx=5, pady=5) filter_frame.pack(side=RIGHT, padx=40) menu_frame.pack(fill=X) def drow_panel(self): self.pw = ttk.PanedWindow(self, orient=HORIZONTAL) self.pw.pack(fill=BOTH, expand=True) self.list_frame = ttk.Frame(self.pw, width=150, height=300, relief=SUNKEN) self.main_frame = ttk.Frame(self.pw, width=150, height=300, relief=SUNKEN) self.pw.add(self.list_frame, weight=1) self.pw.add(self.main_frame, weight=6) def drow_complete_frame(self): self.complete_frame = ttk.Frame(self.main_frame) self.title_complete_string = StringVar() self.title_complete_string.set("Completing task: {}") title_complete_label = Entry(self.complete_frame, textvariable=self.title_complete_string, font="Keraleeyam-Regular 16 bold", bd=0, state="readonly", justify=CENTER) comment_label = Label(self.complete_frame, text="Comment", font="LiberationMono-Bold 10") self.complete_text = Text(self.complete_frame, height=10, font="FreeMono 10") cancel_button = ttk.Button(self.complete_frame, text="cancel", command=self.cancel_event) complete_button = ttk.Button(self.complete_frame, text="Complete", command=self.complete_task_event) title_complete_label.pack(fill=BOTH, padx=10, pady=15) comment_label.pack(fill=BOTH, padx=10) self.complete_text.pack(pady=5, fill=X) complete_button.pack(side=RIGHT, pady=10) cancel_button.pack(side=RIGHT, pady=10, padx=40) def drow_reschedule_frame(self): self.reschedule_frame = ttk.Frame(self.main_frame) self.title_reschedule_string = StringVar() self.title_reschedule_string.set("Reschedule task: {}") title_reschedule_label = Entry( self.reschedule_frame, textvariable=self.title_reschedule_string, font="Keraleeyam-Regular 16 bold", bd=0, state="readonly", justify=CENTER) activity_label = Label(self.reschedule_frame, text="Description of the WIP", font="LiberationMono-Bold 10") self.reschedule_text = Text(self.reschedule_frame, height=10, font="FreeMono 10") calendar_frame = ttk.Frame(self.reschedule_frame) calendar_frame.grid_rowconfigure(0, weight=1) calendar_frame.grid_columnconfigure(0, weight=1) tomorrow = datetime.date.today() + datetime.timedelta(days=1) calendar_label = Label(calendar_frame, text="reschedule date", font="LiberationMono-Bold 10") self.calendar = Calendar(calendar_frame, date_pattern="y-mm-dd", font="Arial 8", selectmode='day', cursor="hand1", year=tomorrow.year, month=tomorrow.month, day=tomorrow.day) hour_label = Label(calendar_frame, text="expeted time to spend next next", font="LiberationMono-Bold 10") self.hour_string = StringVar() hour_box = Spinbox(calendar_frame, width=3, from_=1, to=36, textvariable=self.hour_string, command=self.update_label_reschedule_time) hour_box.bind("<Return>", self.update_label_reschedule_time) self.hour_label = Label(calendar_frame, text="0h 10m", font="LiberationMono-Bold 10") hour_eff_label = Label(calendar_frame, text="time spent today", font="LiberationMono-Bold 10") self.hour_effective_string = StringVar() hour_eff_box = Spinbox(calendar_frame, width=3, from_=1, to=144, textvariable=self.hour_effective_string, command=self.update_label_reschedule_eff_time) hour_eff_box.bind("<Return>", self.update_label_reschedule_eff_time) self.hour_eff_label = Label(calendar_frame, text="0h 10m", font="LiberationMono-Bold 10") self.stick = IntVar() stick_box = Checkbutton(calendar_frame, text="do not postpone", font="LiberationMono-Bold 10", variable=self.stick) calendar_label.grid(column=0, row=0) self.calendar.grid(column=0, row=1, rowspan=2) hour_eff_label.grid(column=1, row=1, padx=50) hour_eff_box.grid(column=2, row=1) self.hour_eff_label.grid(column=3, row=1, padx=5) hour_label.grid(column=1, row=2, padx=50) hour_box.grid(column=2, row=2) self.hour_label.grid(column=3, row=2, padx=5) stick_box.grid(column=0, row=3, pady=5) cancel_button = ttk.Button(self.reschedule_frame, text="cancel", command=self.cancel_event) reschedule_button = ttk.Button(self.reschedule_frame, text="Reschedule", command=self.reschedule_task_event) title_reschedule_label.pack(pady=15, fill=X) activity_label.pack() self.reschedule_text.pack(pady=5, fill=X) calendar_frame.pack() reschedule_button.pack(side=RIGHT, pady=10) cancel_button.pack(side=RIGHT, pady=10, padx=40) def drow_new_task_frame(self): self.new_task_frame = ttk.Frame(self.main_frame) title_label = Label(self.new_task_frame, text="New Task", font="Keraleeyam-Regular 16 bold") container_frame = ttk.Frame(self.new_task_frame) container_frame.grid_rowconfigure(0, weight=1) container_frame.grid_columnconfigure(0, weight=1) name_label = Label(container_frame, text="task name", font="LiberationMono-Bold 10") self.name_new_task_string = StringVar() self.name_new_task_string.set("") name_new_task_entry = Entry(container_frame, textvariable=self.name_new_task_string, font="Keraleeyam-Regular 10") tags_frame = ttk.Frame(self.new_task_frame) tags_label = Label(tags_frame, text="tags", font="LiberationMono-Bold 10") self.tags_new_task_string = StringVar() self.tags_new_task_string.set("") tags_new_task_entry = Entry(tags_frame, textvariable=self.tags_new_task_string, font="Keraleeyam-Regular 10") tags_new_task_entry.bind("<Return>", self.add_new_tag) self.tags_container = ttk.Frame(tags_frame) tags_label.grid(column=0, row=0) tags_new_task_entry.grid(column=1, row=0) self.tags_container.grid(column=2, row=0) description_new_label = Label(container_frame, text="Description", font="LiberationMono-Bold 10") self.description_new_text = Text(container_frame, font="FreeMono 10") calendar_frame = ttk.Frame(container_frame) calendar_frame.grid_rowconfigure(0, weight=1) calendar_frame.grid_columnconfigure(0, weight=1) day = datetime.date.today() calendar_start_label = Label(calendar_frame, text="start date", font="LiberationMono-Bold 10") self.calendar_start = Calendar(calendar_frame, date_pattern="y-mm-dd", font="Arial 8", selectmode='day', cursor="hand1", year=day.year, month=day.month, day=day.day) calendar_end_label = Label(calendar_frame, text="due date", font="LiberationMono-Bold 10") self.calendar_due = Calendar(calendar_frame, date_pattern="y-mm-dd", font="Arial 8", selectmode='day', cursor="hand1", year=day.year, month=day.month, day=day.day) self.stick_new = IntVar() stick_box = Checkbutton(calendar_frame, text="do not postpone", font="LiberationMono-Bold 10", variable=self.stick_new) calendar_start_label.grid(column=0, row=0, pady=5) self.calendar_start.grid(column=0, row=1, pady=5) calendar_end_label.grid(column=0, row=2, pady=5) self.calendar_due.grid(column=0, row=3, pady=5) stick_box.grid(column=0, row=4, pady=5) name_label.grid(column=0, row=0, padx=15) name_new_task_entry.grid(column=0, row=1, padx=15, stick=N + E + S + W) description_new_label.grid(column=0, row=2, padx=15) self.description_new_text.grid(column=0, row=3, stick=N + E + S + W, padx=15) calendar_frame.grid(column=1, row=0, rowspan=5, padx=15) label_frame = ttk.Frame(self.new_task_frame) label_frame.grid_rowconfigure(0, weight=1) label_frame.grid_columnconfigure(0, weight=1) hour_label = Label(label_frame, text="Time to spend next", font="LiberationMono-Bold 10") self.hour_new_string = StringVar() hour_box = Spinbox(label_frame, width=3, from_=1, to=36, textvariable=self.hour_new_string, command=self.update_label_new_time) hour_box.bind("<Return>", self.update_label_new_time) self.hour_new_label = Label(label_frame, text="0h 10m", font="LiberationMono-Bold 10") priority_new_label = Label(label_frame, text="priority 1-5 (1 is the highest)", font="LiberationMono-Bold 10") self.priority_new_string = StringVar() priority_new_box = Spinbox(label_frame, width=3, from_=1, to=5, textvariable=self.priority_new_string) hour_label.grid(column=0, row=0, pady=5) hour_box.grid(column=1, row=0, pady=5) self.hour_new_label.grid(column=2, row=0, pady=5) priority_new_label.grid(column=0, row=1, pady=5) priority_new_box.grid(column=1, row=1, pady=5) cancel_button = ttk.Button(self.new_task_frame, text="cancel", command=self.cancel_event) create_button = ttk.Button(self.new_task_frame, text="create", command=self.new_task_event) title_label.pack(pady=15, fill=X) container_frame.pack(fill=X, expand=True) tags_frame.pack(padx=30, pady=10, fill=X) label_frame.pack(pady=5, padx=30) create_button.pack(side=RIGHT, pady=10) cancel_button.pack(side=RIGHT, pady=10, padx=40) def drow_task_frame(self): self.task_frame = ttk.Frame(self.main_frame) self.title_string = StringVar() self.title_string.set("Empty") title_label = Entry(self.task_frame, textvariable=self.title_string, font="Keraleeyam-Regular 16 bold", bd=0, state="readonly", justify=CENTER) self.id_string = StringVar() self.id_string.set("id") id_label = Entry(self.task_frame, textvariable=self.id_string, font="FreeMono 10", bd=0, state="readonly", justify=CENTER) ldabel_text_frame = Frame(self.task_frame) self.label_created = Label(ldabel_text_frame, text="created: {}", font="LiberationMono-Bold 10") self.label_due = Label(ldabel_text_frame, text="due date: {}", font="LiberationMono-Bold 10") self.label_state = Label(ldabel_text_frame, text="state: {}", font="LiberationMono-Bold 10") self.label_priority = Label(ldabel_text_frame, text="priority: {}", font="LiberationMono-Bold 10") self.label_time = Label(ldabel_text_frame, text="time to spend next: {}", font="LiberationMono-Bold 10") self.label_created.grid(column=0, row=0, padx=20) self.label_due.grid(column=1, row=0, padx=20) self.label_state.grid(column=2, row=0, padx=20) self.label_priority.grid(column=3, row=0, padx=20) self.label_time.grid(column=4, row=0, padx=20) tags_frame = ttk.Frame(self.task_frame) tags_label = Label(tags_frame, text="tags: ", font="LiberationMono-Bold 10") self.tags_task_string = StringVar() self.tags_task_string.set("") self.tags_task_entry = Entry(tags_frame, textvariable=self.tags_task_string, font="Keraleeyam-Regular 10") self.tags_task_entry.bind("<Return>", self.add_task_tag) self.tags_frame = ttk.Frame(tags_frame) self.tags_frame.bind("<Leave>", self.save_tags) tags_label.grid(column=0, row=0) self.tags_task_entry.grid(column=1, row=0) self.tags_frame.grid(column=2, row=0) main_task_frame = ttk.Frame(self.task_frame) tabs = ttk.Notebook(main_task_frame) def myfunction(event): canvas.configure(scrollregion=canvas.bbox("all")) def onCanvasConfigure(event): canvas.itemconfigure(canvas_item, width=canvas.winfo_width() - 20) activity_frame = ttk.Frame(tabs) canvas = Canvas(activity_frame, width=20, height=20) self.activity_frame_main = Frame(canvas) scroll1 = Scrollbar(activity_frame, orient=VERTICAL, command=canvas.yview) canvas.config(yscrollcommand=scroll1.set) canvas_item = canvas.create_window((0, 0), window=self.activity_frame_main, anchor='w') self.activity_frame_main.bind("<Configure>", myfunction) canvas.bind('<Configure>', onCanvasConfigure) canvas.pack(side=LEFT, fill=BOTH, expand=True) scroll1.pack(side=RIGHT, fill=Y) def myfunction2(event): canvas_rel.configure(scrollregion=canvas_rel.bbox("all")) def onCanvasConfigure2(event): canvas_rel.itemconfigure(canvas_rel_item, width=canvas_rel.winfo_width() - 20) relation_frame = Frame(tabs) canvas_rel = Canvas(relation_frame, width=20, height=20) self.relation_frame = Frame(canvas_rel) scroll2 = Scrollbar(relation_frame, orient=VERTICAL, command=canvas.yview) canvas_rel.config(yscrollcommand=scroll2.set) canvas_rel_item = canvas_rel.create_window((0, 0), window=self.relation_frame, anchor='w') self.relation_frame.bind("<Configure>", myfunction2) canvas_rel.bind('<Configure>', onCanvasConfigure2) canvas_rel.pack(side=LEFT, fill=BOTH, expand=True) scroll2.pack(side=RIGHT, fill=Y) description_text_frame = Frame(tabs) description_text_frame.grid_rowconfigure(0, weight=1) description_text_frame.grid_columnconfigure(0, weight=1) self.description_text = Text(description_text_frame, font="FreeMono 10", wrap=WORD) self.description_text.insert('1.0', "description") self.description_text.bind('<Leave>', self.save_event) self.description_text.bind('<KeyPress>', self.save_new_desc) self.description_text.bind('<Control-z>', self.discard_text_changes) scroll = Scrollbar(description_text_frame, orient=VERTICAL, command=self.description_text.yview) self.description_text.config(yscrollcommand=scroll.set) self.description_text.grid(column=0, row=0, stick="news") scroll.grid(column=1, row=0, stick="news") tabs.add(description_text_frame, text="description") tabs.add(activity_frame, text="activities") tabs.add(relation_frame, text="related tasks") tabs.pack(fill=BOTH, expand=True) self.complete_task_frame = ttk.Frame(self.task_frame) self.complete_task_frame.grid_rowconfigure(0, weight=1) self.complete_task_frame.grid_columnconfigure(0, weight=1) self.label_completed = Label(self.complete_task_frame, text="completed at: 0000-00-00", font="LiberationMono-Bold 10") self.description_completed_text = Text(self.complete_task_frame, font="FreeMono 10", height=10, wrap=WORD) self.description_completed_text.insert("1.0", "completed") self.description_completed_text.config(state=DISABLED) self.label_completed.pack() self.description_completed_text.pack(fill=X) self.button_frame = Frame(self.task_frame) rel_button_frame = Frame(self.button_frame) self.rel_button = ttk.Button(rel_button_frame, text="Relate task", command=self.add_relationship) rel_label = Label(rel_button_frame, text="id: ", font="LiberationMono-Bold 10") self.rel_id_string = StringVar() rel_entry = Entry(rel_button_frame, width=36, textvariable=self.rel_id_string, font="Keraleeyam-Regular 10") self.rel_type_string = StringVar() combo = ttk.Combobox(rel_button_frame, width=7, textvariable=self.rel_type_string, values=("CHILD", "PARENT")) rel_label.pack(side=LEFT, padx=5) rel_entry.pack(side=LEFT, padx=5) combo.pack(side=LEFT, padx=10) self.rel_button.pack(side=LEFT, padx=10) rel_button_frame.pack(side=LEFT) self.reschedule_button = ttk.Button(self.button_frame, text="Reschedule", command=self.reschedule_event) self.complete_button = ttk.Button(self.button_frame, text="Complete", command=self.complete_event) self.reschedule_button.pack(side=RIGHT, padx=10) self.complete_button.pack(side=RIGHT, padx=10) title_label.pack(fill=X, pady=5, padx=10) id_label.pack(fill=X, pady=5, padx=10) ldabel_text_frame.pack(pady=5, padx=10) tags_frame.pack(fill=X, pady=5, padx=100) main_task_frame.pack(padx=100, pady=5, expand=True, fill=BOTH) def drow_list(self): self.tabs = ttk.Notebook(self.list_frame) self.tabs.pack(fill=BOTH, expand=True) self.list_day = Listbox(self.tabs, selectmode=SINGLE, exportselection=False) self.list_day.bind("<<ListboxSelect>>", self.update_main_frame_day) self.list_all = Listbox(self.tabs, selectmode=SINGLE, exportselection=False) self.list_all.bind("<<ListboxSelect>>", self.update_main_frame_day) self.list_old = Listbox(self.tabs, selectmode=SINGLE, exportselection=False) self.list_old.bind("<<ListboxSelect>>", self.update_main_frame_day) self.tabs.add(self.list_day, text="Today") self.tabs.add(self.list_all, text="WIP") self.tabs.add(self.list_old, text="History") def add_relationship(self): task = self.tcont.search_task([self.rel_id_string.get()])[0] task = None if task.id == self.current_task.id else task if task and self.rel_type_string.get() == "CHILD": self.current_task.childs.append(task) task.parents.append(self.current_task) self.update_task_frame() self.tcont.save() elif task and self.rel_type_string.get() == "PARENT": self.current_task.parents.append(task) task.childs.append(self.current_task) self.update_task_frame() self.tcont.save() def discard_text_changes(self, event=None): self.description_text.delete("1.0", END) self.new_description = self.current_task.description self.description_text.insert("1.0", self.new_description) def add_new_tag(self, event): if len(self.tags_container.winfo_children()) <= 5: TagLabel(self.tags_container, text=self.tags_new_task_string.get(), bg="yellow", clickdestroy=True).pack(padx=5, side=LEFT) self.tags_new_task_string.set("") def add_task_tag(self, event): if len(self.tags_frame.winfo_children()) <= 5: TagLabel(self.tags_frame, text=self.tags_task_string.get(), bg="yellow", clickdestroy=True).pack(padx=5, side=LEFT) self.tags_task_string.set("") self.save_tags() def save_event(self, event=None): self.new_description = self.description_text.get("1.0", END)[:-1] self.current_task.description = self.new_description self.tcont.save() def quit_event(self, event=None): if self.current_task: self.save_event() self.destroy() def save_tags(self, event=None): tags = [] for w in self.tags_frame.winfo_children(): tags.append(w.get_text()) self.current_task.tags = tags self.tcont.save() def save_new_desc(self, event): self.new_description = self.description_text.get("1.0", END)[:-1] def update_label_reschedule_time(self, event=None): self.hour_label.config(text="{}h {}m".format( int(int(self.hour_string.get()) / 6), int(int(self.hour_string.get()) % 6 * 10))) def update_label_reschedule_eff_time(self, event=None): self.hour_eff_label.config(text="{}h {}m".format( int(int(self.hour_effective_string.get()) / 6), int(int(self.hour_effective_string.get()) % 6 * 10))) def update_label_new_time(self, event=None): self.hour_new_label.config(text="{}h {}m".format( int(int(self.hour_new_string.get()) / 6), int(int(self.hour_new_string.get()) % 6 * 10))) def fetch_activities(self): for w in self.activity_frame_main.winfo_children(): w.destroy() hcount = 0 for activity in self.current_task.activities: hcount += activity.hour if int(hcount / 6) > 24: ttk.Label( self.activity_frame_main, text="total time spent: {}d {}h {}m".format( int(hcount / (6 * 24)), int((hcount - int(hcount / (6 * 24)) * (6 * 24)) / 6), int((hcount - int(hcount / (6 * 24)) * (6 * 24)) % 6 * 10)), font="LiberationMono-Bold 10", padding="0 10 0 0").pack(fill=X, padx=10) else: ttk.Label(self.activity_frame_main, text="total time spent: {}h {}m".format( int(hcount / 6), int(hcount % 6 * 10)), font="LiberationMono-Bold 10", padding="0 10 0 0").pack(fill=X, padx=10) for activity in self.current_task.activities: ttk.Label(self.activity_frame_main, text="date: {}\t\t\ttime spent: {}h {}m".format( activity.date, int(activity.hour / 6), int(activity.hour % 6 * 10)), font="LiberationMono-Bold 10", padding="0 25 0 10").pack(fill=X, padx=10) DText(self.activity_frame_main, activity.description, font="FreeMono 10", wrap=WORD).pack(fill=X, padx=10, expand=True) def fetch_rels(self): for w in self.relation_frame.winfo_children(): w.destroy() def bind_dclick(task): wlist = self.tabs.winfo_children() for w in wlist: w.selection_clear(0, END) self.update_task_frame(task=task) for task in self.current_task.childs: rel_frame(self.relation_frame, task, "CHILD ", bind_dclick).pack(fill=X, padx=5) for task in self.current_task.parents: rel_frame(self.relation_frame, task, "PARENT", bind_dclick).pack(fill=X, padx=5) def fetch_list_event(self, event=None): self.fetch_old() self.fetch_list() def fetch_old(self): self.list_old.delete(0, END) if self.filter_text_string.get() == "": self.task_list_old = self.tcont.old_list else: self.task_list_old = filtask.map_filter[ self.filter_mod_string.get()](self.tcont.old_list, self.filter_text_string.get()) count = 0 for item in self.task_list_old: self.list_old.insert(count, item.name) count += 1 def fetch_list(self): self.list_all.delete(0, END) self.list_day.delete(0, END) if self.filter_text_string.get() == "": self.task_list_day = self.tcont.day_tasks_list self.task_list_wip = self.tcont.task_list else: self.task_list_day = filtask.map_filter[ self.filter_mod_string.get()](self.tcont.day_tasks_list, self.filter_text_string.get()) self.task_list_wip = filtask.map_filter[ self.filter_mod_string.get()](self.tcont.task_list, self.filter_text_string.get()) count = 0 for item in self.task_list_day: self.list_day.insert(count, item.name) count += 1 count = 0 for item in self.task_list_wip: self.list_all.insert(count, item.name) count += 1 widget = self.tabs.winfo_children()[self.tabs.index( self.tabs.select())] widget.selection_set(0) def update_main_frame_day(self, event): widget = event.widget wlist = self.tabs.winfo_children() wlist.pop(self.tabs.index(self.tabs.select())) for w in wlist: w.selection_clear(0, END) if len(widget.curselection()) > 0: self.update_task_frame() for w in self.main_frame.winfo_children(): w.pack_forget() self.task_frame.pack(fill=BOTH, expand=True) def update_task_frame(self, task=None): widget = self.tabs.winfo_children()[self.tabs.index( self.tabs.select())] if len(widget.curselection()) > 0 or task: if task: self.current_task = task else: if self.tabs.index(self.tabs.select()) == 0: self.current_task = self.task_list_day[ widget.curselection()[0]] elif self.tabs.index(self.tabs.select()) == 1: self.current_task = self.task_list_wip[ widget.curselection()[0]] else: self.current_task = self.task_list_old[ widget.curselection()[0]] self.title_string.set(self.current_task.name) self.id_string.set(self.current_task.id) self.description_text.config(state=NORMAL) self.description_text.delete(1.0, END) self.new_description = self.current_task.description self.description_text.insert('1.0', self.new_description) for w in self.tags_frame.winfo_children(): w.destroy() if self.current_task.get_status() == "COMPLETED": self.description_text.config(state=DISABLED) self.button_frame.pack_forget() self.description_completed_text.config(state=NORMAL) self.description_completed_text.delete("1.0", END) self.description_completed_text.insert( "1.0", self.current_task.completed_comment) self.description_completed_text.config(state=DISABLED) self.label_completed.config(text="completed at: {}".format( self.current_task.completed_date.isoformat())) self.complete_task_frame.pack(fill=X, padx=100, pady=50) self.tags_task_entry.grid_forget() for tag in self.current_task.tags: TagLabel(self.tags_frame, text=tag, bg="yellow").pack(padx=5, side=LEFT) else: self.description_text.config(state=NORMAL) self.complete_task_frame.pack_forget() self.button_frame.pack(pady=35, padx=60, fill=X) self.tags_task_entry.grid(column=1, row=0) for tag in self.current_task.tags: TagLabel(self.tags_frame, text=tag, bg="yellow", clickdestroy=True).pack(padx=5, side=LEFT) if self.current_task.get_status() == "WAITING": self.complete_button.config(state=DISABLED) else: self.complete_button.config(state=NORMAL) self.rel_type_string.set("") self.rel_id_string.set("") self.fetch_activities() self.fetch_rels() if self.current_task.get_status( ) == "NEXT" or self.current_task.get_status() == "PENDING": self.label_state.config(text="state: {} \u2192 {}".format( self.current_task.get_status(), str(self.current_task.schedule.start_date))) else: self.label_state.config( text="state: {}".format(self.current_task.get_status())) self.label_created.config(text="created: {}".format( str(self.current_task.creation_date))) self.label_due.config(text="due date: {}".format( self.current_task.due_date.isoformat())) self.label_priority.config( text="priotity: {}".format(int(self.current_task.priority))) self.label_time.config(text="time to spend next: {}h {}m".format( int(self.current_task.schedule.hour / 6), int(self.current_task.schedule.hour % 6 * 10))) def complete_event(self): self.task_frame.pack_forget() self.title_complete_string.set("Completing task: {}".format( self.current_task.id)) self.complete_text.delete(1.0, END) self.complete_frame.pack(fill=X, padx=70) def complete_task_event(self): self.current_task.description = self.description_text.get("1.0", END)[:-1] self.current_task.complete(self.complete_text.get("1.0", END)) self.complete_frame.pack_forget() self.update_task_frame() self.tcont.refresh_day_tasks() self.fetch_list() self.task_frame.pack(fill=BOTH, expand=True) self.tcont.save() def cancel_event(self): childs = self.main_frame.winfo_children() for child in childs: child.pack_forget() self.task_frame.pack(fill=BOTH, expand=True) def new_event(self): self.name_new_task_string.set("") self.description_new_text.delete("1.0", END) self.calendar_due.selection_set(datetime.date.today()) self.calendar_start.selection_set(datetime.date.today()) self.stick_new.set(0) self.priority_new_string.set(1) self.hour_new_string.set(1) self.tags_new_task_string.set("") self.hour_new_label.config(text="{}h {}m".format( int(int(self.hour_new_string.get()) / 6), int(int(self.hour_new_string.get()) % 6 * 10))) for w in self.tags_container.winfo_children(): w.destroy() for w in self.main_frame.winfo_children(): w.pack_forget() self.new_task_frame.pack(fill=X, padx=70) def new_task_event(self): istoday = False if datetime.date.fromisoformat(self.calendar_start.get_date( )) == datetime.date.today() and datetime.date.fromisoformat( self.calendar_due.get_date()) == datetime.date.today(): istoday = True tags = [] for w in self.tags_container.winfo_children(): tags.append(w.get_text()) task = Task(name=self.name_new_task_string.get(), description=self.description_new_text.get("1.0", END), start_date=self.calendar_start.get_date(), due_date=self.calendar_due.get_date(), hour=int(self.hour_new_string.get()), priority=int(self.priority_new_string.get()), is_today=istoday, tags=tags, is_sticked=bool(self.stick_new.get())) self.tcont.add_task(task) self.tcont.save() self.fetch_list() self.new_task_frame.pack_forget() wlist = self.tabs.winfo_children() for w in wlist: w.selection_clear(0, END) self.update_task_frame(task=self.tcont.task_list[-1]) self.task_frame.pack(fill=BOTH, expand=True) def reschedule_event(self): self.title_reschedule_string.set("Reschedule task: {}".format( self.current_task.id)) tomorrow = datetime.date.today() + datetime.timedelta(days=1) self.calendar.selection_set(tomorrow) self.hour_string.set(1) self.hour_effective_string.set(1) self.hour_label.config(text="0h 10m") self.hour_eff_label.config(text="0h 10m") self.reschedule_text.delete("1.0", END) self.stick.set(0) self.task_frame.pack_forget() self.reschedule_frame.pack(fill=X, padx=70) def reschedule_task_event(self): self.current_task.reschedule(Activity( self.reschedule_text.get("1.0", END)[:-1], int(self.hour_effective_string.get())), int(self.hour_string.get()), start_date=self.calendar.get_date(), is_sticked=bool(self.stick.get())) self.reschedule_frame.pack_forget() self.update_task_frame() self.task_frame.pack(fill=BOTH, expand=True) self.tcont.refresh_day_tasks() self.fetch_list() self.tcont.save()
class Window: def __init__(self, width, height, title='Change rates', resizable=(False, False), icon=None): self.root = tk.Tk() self.root.title(title) self.root.geometry(f'{width}x{height}+200+50') self.root.resizable(resizable[0], resizable[1]) def run(self): self.create_widgets() self.root.mainloop() def create_widgets(self): # create widgets of main window self.start_date_label = tk.Label(self.root, text='Start date: ').grid( row=0, column=1, columnspan=2) self.start_date_label = tk.Label(self.root, text='End date: ').grid(row=0, column=3, columnspan=2) self.start_date = Calendar(self.root, font="Arial 8", selectmode='day', year=2000, month=1, day=1, mindate=datetime.date(2000, 1, 1), maxdate=datetime.date.today()) self.end_date = Calendar(self.root, font="Arial 8", selectmode='day', year=2000, month=1, day=2, mindate=datetime.date(2000, 1, 2), maxdate=datetime.date.today()) self.end_date.bind("<<CalendarSelected>>", self.DateCheck) self.start_date.bind("<<CalendarSelected>>", self.DateCheck) self.start_date.grid(column=1, row=1, padx=10, pady=10, columnspan=2) self.end_date.grid(column=3, row=1, padx=10, pady=10, columnspan=2) self.step = tk.Label(self.root, text='Step ').grid(row=2, column=1) # years = self.setTimeInterval(start_year, end_year) # self.yy1 = ttk.Combobox(self.root, values=years, height =10, width=5) # self.yy1.set(years[0]) # self.yy1.grid(row=1, column=2) # self.yy1['state'] = 'readonly' # self.yy1.bind("<<ComboboxSelected>>", self.YearCheck) # # months = self.setTimeInterval(1, 12) # self.mm1 = ttk.Combobox(self.root, values=months, height =12, width=3) # self.mm1.set(months[0]) # self.mm1.grid(row=1, column=3) # self.mm1['state'] = 'readonly' # self.mm1.bind("<<ComboboxSelected>>", self.CheckMonth) # # daysInMonth = calendar.monthrange(int(self.yy1.get()), int(self.mm1.get()))[1] # self.days = self.setTimeInterval(1, daysInMonth) # self.dd1 = ttk.Combobox(self.root, values = self.days, height =10, width=3) # self.dd1.set(self.days[0]) # self.dd1.grid(row=1, column=4) # self.dd1.bind("<<ComboboxSelected>>", self.DayValidate) # self.dd1['state'] = 'readonly' # # self.yy2 = ttk.Combobox(self.root, values=years, height =10, width=5) # self.yy2.set(years[0]) # self.yy2.grid(row=2, column=2) # self.yy2.bind("<<ComboboxSelected>>", self.YearCheck) # self.yy2['state'] = 'readonly' # # self.mm2 = ttk.Combobox(self.root, values=months, height =12, width=3) # self.mm2.set(months[0]) # self.mm2.grid(row=2, column=3) # self.mm2.bind("<<ComboboxSelected>>", self.CheckMonth) # self.mm2['state'] = 'readonly' # # self.dd2 = ttk.Combobox(self.root, values=self.days, height=10, width=3) # self.dd2.set(self.days[0]) # self.dd2.grid(row=2, column=4) # self.dd2.bind("<<ComboboxSelected>>", self.DayValidate) # self.dd2['state'] = 'readonly' self.interval = tk.Scale(self.root, orient='horizontal', length=300, from_=1, to=365, tickinterval=50, resolution=1) self.interval.grid(row=2, column=2, columnspan=4) self.check_dates = tk.Button(self.root, text='Get list of money', command=self.createMoneyList) self.check_dates.grid(row=4, column=2, columnspan=2, pady=10) self.quit = tk.Button(self.root, text="QUIT", fg="red", command=self.root.destroy).grid(row=4, column=4, columnspan=1, pady=10) # def setTimeInterval(self, start, end): # interval = [] # for i in range(int(start), int(end)+1): # interval.append(i) # return interval # # def YearCheck(self, event): # if int(self.yy1.get())>int(self.yy2.get()): # self.yy2.set(self.yy1.get()) # self.DayValidate() # # def CheckMonth(self, event): # if int(self.yy1.get())==int(self.yy2.get()) and int(self.mm1.get())>int(self.mm2.get()): # self.mm2.set(self.mm1.get()) # self.DayValidate() # # def DayValidate(self): # daysInMonth1 = calendar.monthrange(int(self.yy1.get()), int(self.mm1.get()))[1] # daysInMonth2 = calendar.monthrange(int(self.yy2.get()), int(self.mm2.get()))[1] # if len(self.dd1['value']) != daysInMonth1: # days = self.setTimeInterval(1, daysInMonth1) # self.dd1['value'] = days # elif len(self.dd2['value']) != daysInMonth2: # days = self.setTimeInterval(1, daysInMonth2) # self.dd2['value'] = days # else: # pass # if int(self.dd1.get()) > daysInMonth1: # self.dd1.set(daysInMonth1) # elif int(self.dd2.get()) > daysInMonth2: # self.dd2.set(daysInMonth2) # if int(self.yy1.get()) == int(self.yy2.get()) and int(self.mm1.get()) == int(self.mm2.get()) and\ # int(self.dd1.get()) == int(self.dd2.get()) and int(self.dd1.get())<daysInMonth1: # self.dd2.set(int(self.dd2.get())+1) # elif int(self.yy1.get()) == int(self.yy2.get()) and int(self.mm1.get()) == int(self.mm2.get()) and \ # int(self.dd1.get()) >= int(self.dd2.get()): # if int(self.mm2.get()) < 12: # self.mm2.set(int(self.mm2.get()) + 1) # self.dd2.set(1) # else: # self.yy2.set(int(self.yy2.get())+1) # self.mm2.set(1) # self.dd2.set(1) def DateCheck(self, event): # Function validating of Calendar delta = timedelta(days=1) if self.start_date.selection_get() == datetime.date.today(): self.start_date.selection_set(self.start_date.selection_get() - delta) if self.start_date.selection_get() >= self.end_date.selection_get(): self.end_date.selection_set(self.start_date.selection_get() + delta) def createMoneyList(self): # Function to create child window moneyList = ChildWindow(self.root, 500, 350, 'money list') start_date = self.start_date.selection_get() end_date = self.end_date.selection_get() step = timedelta(days=self.interval.get()) moneyList.run(start_date, end_date, step)
class AnimalWindow(): def __init__(self, master, conn, main_win, window_type="new", animal_id=""): self.conn = conn self.master = master self.master.withdraw() # Hide window CenterWindow(self.master) self.animal_id = animal_id self.main_win = main_win self.type = window_type self._Setup_fonts() self._build_frames() self._build_widgets() if animal_id != "" and window_type == "edit": self._populate_data(conn, self.animal_id) self.master.deiconify() # Show window def _Setup_fonts(self): # Title Font settings self.font_title = tkfont.Font(size=30, weight='bold') def _build_frames(self): # Right Frame self.right_frame = ttk.Frame(self.master, width="300") self.right_frame.pack(side="right", fill="both") # - Image frame self.image_frame = ttk.Frame(self.right_frame, width="300", height="300", style="grey.TLabel") self.image_frame.pack(side="top", fill="x") # - Set image frame self.image_button_frame = ttk.Frame(self.right_frame) self.image_button_frame.pack(side="top", anchor="c") # - Notes header frame self.note_header_frame = ttk.Frame(self.right_frame) self.note_header_frame.pack(side="top", fill="x") # - Notes frame self.notes_frame = ttk.Frame(self.right_frame) self.notes_frame.pack(side="top", fill="both", anchor="n") # - Buttons frame self.buttons_frame = ttk.Frame(self.right_frame) self.buttons_frame.pack(side="bottom", expand=True, fill="x", anchor="s") # -- Left button frame self.left_button_frame = ttk.Frame(self.buttons_frame) self.left_button_frame.pack(side="left", expand=True, fill="both", anchor="w") # -- Right button frame self.right_button_frame = ttk.Frame(self.buttons_frame) self.right_button_frame.pack(side="right", expand=True, fill="both", anchor="e") # Left frame self.left_frame = ttk.Frame(self.master) self.left_frame.pack(side="left", expand=True, fill="both") # - Title frame self.title_frame = ttk.Frame(self.left_frame) self.title_frame.pack(side="top", fill="x", ipady=10) # - Data frame (for dob, colour etc) self.data_frame = ttk.Frame(self.left_frame) self.data_frame.pack(side="top", fill="x") # -- Setting column list self.data_col = [] # -- Column setup self.col_padd = 5 self.col_paddl = self.col_padd + 1 num_of_cols = 2 # Increase to add columns. for col in range(num_of_cols): self.data_col.insert(col, [0, 1]) self.data_col[col][0] = ttk.Frame(self.data_frame) self.data_col[col][0].pack(side="left", ipadx=5, anchor="n") self.data_col[col][1] = ttk.Frame(self.data_frame) self.data_col[col][1].pack(side="left", ipadx=5, anchor="n") # -- Dob column self.dob_col = ttk.Frame(self.data_frame) self.dob_col.pack(side="left", ipadx=5, anchor="n") # --- Dob known holding frame self.dob_holding_frame = ttk.Frame(self.dob_col) self.dob_holding_frame.pack(side="top", anchor="n", fill="x") # ---- Dob known frames self.dob_known_col = [0, 1] self.dob_known_col[0] = ttk.Frame(self.dob_holding_frame) self.dob_known_col[0].pack(side="left", ipadx=5, anchor="n") self.dob_known_col[1] = ttk.Frame(self.dob_holding_frame) self.dob_known_col[1].pack(side="left", ipadx=5, anchor="n") # - Central frame self.central_frame = ttk.Frame(self.left_frame, style="brown.TFrame") self.central_frame.pack(side="top", fill="both", expand=True) # -- Medical history frame self.med_hist_frame = ttk.Frame(self.central_frame) self.med_hist_frame.pack_propagate(0) self.med_hist_frame.pack(side="top", fill="both", expand=True) # -- homing history frame self.home_hist_frame = ttk.Frame(self.central_frame) self.home_hist_frame.pack_propagate(0) self.home_hist_frame.pack(side="top", fill="both", expand=True) def _build_widgets(self): # =============== # Title widgets # =============== # - Title Labels self.id_label = ttk.Label( self.title_frame, font=self.font_title) self.id_label.pack(side="left", padx=5) self.name_entry = ttk.Entry(self.title_frame, font=self.font_title) self.name_entry.pack(side="left") # =============== # Right frame, notes widgets # =============== # - image rel_path = 'images\\thumbnails\\' + str(self.animal_id) + '.png' if check_rel_file(rel_path): thumbnail_path = rel_path else: thumbnail_path = get_full_path("config\\default_thumbnail.png") thumbnail_im = Image.open(thumbnail_path) thumbnail_ph = ImageTk.PhotoImage(thumbnail_im) self.thumbnail_img = ttk.Label(self.image_frame, image=thumbnail_ph) self.thumbnail_img.image = thumbnail_ph self.thumbnail_img.pack(side="top") # - setimage button set_img_button = ttk.Button( self.image_button_frame, text="Set Profile Photo", command=lambda c=self.animal_id: self._set_profile_image(c)) if self.animal_id != "": set_img_button.pack(side="left", anchor="c", padx=3) # - Notes items. # - Notes label self.notes_l = ttk.Label(self.note_header_frame, text="Notes:", anchor="n") self.notes_l.pack(side="top", fill="x",) # - Notes text box notes_scroll = tk.Scrollbar(self.notes_frame) self.note_text = tk.Text(self.notes_frame, width="34") notes_scroll.pack(side="right", fill="y", expand=True) self.note_text.pack(side="right", fill="both", expand=True) notes_scroll.config(command=self.note_text.yview) self.note_text.config(yscrollcommand=notes_scroll.set) # =============== # animal data widgets # =============== # - Column 0 items # - Colour self.colour_0 = ttk.Label(self.data_col[0][0], text="Colour: ") self.colour_0.pack(side="top", anchor="w", ipady=self.col_paddl) self.colour_1 = ttk.Entry(self.data_col[0][1]) self.colour_1.pack(side="top", anchor="w", pady=self.col_padd) # - Sex self.sex_0 = ttk.Label(self.data_col[0][0], text="Sex: ", anchor="w") self.sex_0.pack(side="top", anchor="w", ipady=self.col_paddl) self.sex_1 = ttk.Combobox(self.data_col[0][1], state='readonly', values=('Unknown', 'Male', 'Female')) self.sex_1.pack(side="top", anchor="w", pady=self.col_padd) # - Chip number self.chip_num_0 = ttk.Label(self.data_col[0][0], text="Chip Number: ") self.chip_num_0.pack(side="top", anchor="w", ipady=self.col_padd) self.chip_num_1 = ttk.Entry(self.data_col[0][1]) self.chip_num_1.pack(side="top", anchor="w", pady=self.col_padd) # - Hair type self.hair_type_0 = ttk.Label(self.data_col[0][0], text="Hair type: ", anchor="w") self.hair_type_0.pack(side="top", anchor="w", ipady=self.col_paddl) self.hair_type_1 = ttk.Combobox(self.data_col[0][1], state='readonly', values=('Short Hair', 'Long Hair')) self.hair_type_1.pack(side="top", anchor="w", pady=self.col_padd) # - In Rescue self.in_rescue_0 = ttk.Label(self.data_col[0][0], text="In Rescue: ", anchor="w") self.in_rescue_0.pack(side="top", anchor="w", ipady=self.col_paddl) self.in_rescue_var = tk.IntVar() self.in_rescue_1 = ttk.Checkbutton(self.data_col[0][1], variable=self.in_rescue_var) self.in_rescue_1.pack(side="top", anchor="w", pady=self.col_padd) self.in_rescue_var.set(1) # - Dob columns # - DOB known self.dob_known_0 = ttk.Label(self.dob_known_col[0], text="DOB known?: ", anchor="w") self.dob_known_0.pack(side="top", anchor="w", ipady=self.col_paddl) self.dob_known_1 = ttk.Combobox(self.dob_known_col[1], state='readonly', values=('No', 'Yes', 'Roughly')) self.dob_known_1.pack(side="top", anchor="w", pady=self.col_padd) self.dob_known_1.bind("<<ComboboxSelected>>", self._show_hide_date) # - DOB text self.dob_text_0 = ttk.Label(self.dob_known_col[0], text="Date of birth: ", anchor="w") self.dob_text_0.pack(side="top", anchor="w", ipady=self.col_paddl) self.dob_text_1 = ttk.Label(self.dob_known_col[1], anchor="w") self.dob_text_1.pack(side="top", anchor="w", ipady=self.col_padd) # DOB Cal self.dob_cal = Calendar(self.dob_col) self.dob_cal.pack(side="top", anchor="n", fill="x") # =============== # Medical history widgets # =============== # Medical history label if self.type != "new": sql_query = f""" SELECT SUM(Cost) FROM Medical where Animal_ID = {self.animal_id} """ med_spend = BasicDbQuery(self.conn, sql_query)[1][0][0] med_spend = round(med_spend, 2) med_text = f"Medical History - Total Spend = £{med_spend}" med_label = ttk.Label(self.med_hist_frame, text=med_text) med_label['font'] = self.main_win.font_sub_title med_label.pack(side="top", fill="x") # Get medical history data from view sql_query = """SELECT * FROM Animal_Page_Med_History WHERE Animal_ID = :ID""" sql_dict = {'ID': self.animal_id} med_results = AdvDbQuery(self.conn, sql_query, sql_dict) med_tree = TreeBuild(self.med_hist_frame, search=True, data=med_results[1], widths=[0, 100, 50, 1300], headings=med_results[0]) # Needed to stop linter from moaning about being un-used # It will be used at a later date med_tree # =============== # Homing history widgets # =============== # Medical history label if self.type != "new": home_label = ttk.Label(self.home_hist_frame, text="Homing History") home_label['font'] = self.main_win.font_sub_title home_label.pack(side="top", fill="x") # Temp table sql_query = """SELECT * FROM Animal_Page_Homing_History WHERE ID = :ID""" hom_results = AdvDbQuery(self.conn, sql_query, sql_dict) hom_tree = TreeBuild(self.home_hist_frame, search=True, data=hom_results[1], widths=[70, 40, 95, 120, 300, 100, 2000], headings=hom_results[0]) # Needed to stop linter from moaning about being un-used # It will be used at a later date hom_tree # =============== # bottom-right save/submit widgets # =============== # Cancel / submit / save changes buttons self.cancel = ttk.Button(self.right_button_frame, text="Cancel", command=self.close_window) self.cancel.pack(side="left", anchor="w", padx=20, pady=10) self.submit = ttk.Button( self.left_button_frame, text="Submit", command=lambda c="save": self.update_database(c)) self.save = ttk.Button( self.left_button_frame, text="Save", command=lambda c="edit": self.update_database(c)) if self.type == "edit": self.save.pack(side="right", anchor="e", padx=20, pady=10) else: self.submit.pack(side="right", anchor="e", padx=20, pady=10) def _set_profile_image(self, animal_id): # ============= # Fetch image # ============= # Need to temporarily hide root window else it changes focus # when asking for file name. Globals.root.withdraw() # Ask for file new_image_loc = askopenfilename(filetypes=[( "Images", "*.jpg *.jpeg *.png")]) # Bring animal window to front again and unhide root window Globals.root.deiconify() self.thumbnail_img.lift() self.thumbnail_img.focus_force() # ============= # Resize image to 300px in largest dimension # ============= img = cv2.imread(new_image_loc) # load image into variable # Get new width and height w = img.shape[1] h = img.shape[0] max_dimension = 300 if w <= h: nw = int(round(w / h * max_dimension, 0)) nh = max_dimension else: nh = int(round(h / w * max_dimension, 0)) nw = max_dimension dimension = (nw, nh) # Set new image new_img = cv2.resize(img, dimension, interpolation=cv2.INTER_AREA) # ============= # Store image and update on window # ============= # get path of new image rel_path = 'images\\thumbnails\\' rel_path += str(self.animal_id) + '.png' rel_folder = 'images\\thumbnails\\' # Check folder exists. Create if not check_rel_folder(rel_folder, create=True) # Save photo cv2.imwrite(rel_path, new_img, [int(cv2.IMWRITE_PNG_COMPRESSION), 0]) # Update image on page thumbnail_im = Image.open(rel_path) thumbnail_ph = ImageTk.PhotoImage(thumbnail_im) self.thumbnail_img.configure(image=thumbnail_ph) self.thumbnail_img.image = thumbnail_ph def update_database(self, sql_type=""): if sql_type == "": print("no sql type supplied") return update_dict = {} # Get values update_dict['Name'] = self.name_entry.get().rstrip() update_dict['Colour'] = self.colour_1.get().rstrip() update_dict['Sex'] = self.sex_1.get() update_dict['Chip'] = self.chip_num_1.get().rstrip() update_dict['Hair'] = self.hair_type_1.get() update_dict['DobKnown'] = self.dob_known_1.get() if update_dict['DobKnown'] != "No": temp_date = datetime.strptime(self.dob_cal.get_date(), '%d/%m/%Y') temp_date = temp_date.strftime('%Y-%m-%d') else: temp_date = "" update_dict['Dob'] = temp_date update_dict['Notes'] = self.note_text.get('1.0', 'end').rstrip() update_dict['InRescue'] = self.in_rescue_var.get() if sql_type == "edit": update_dict['ID'] = self.id_label.cget('text') sql_query = """UPDATE Animal SET Name = :Name, Chip_Num = :Chip, Date_Of_Birth = :Dob, DOB_Known = :DobKnown, Sex = :Sex, Colour = :Colour, Hair_Type = :Hair, Notes = :Notes, In_Rescue = :InRescue WHERE ID = :ID""" AdvDbQuery(self.conn, sql_query, update_dict, returnlist=False) elif sql_type == "save": next_id_qry = """SELECT ID FROM Animal ORDER BY ID DESC LIMIT 1""" next_id_returns = BasicDbQuery(self.conn, next_id_qry) next_id = int(next_id_returns[1][0][0]) + 1 update_dict['ID'] = next_id sql_query = """INSERT INTO Animal ( Name, Chip_Num, Date_Of_Birth, DOB_Known, Sex, Colour, Hair_Type, Notes, In_Rescue) VALUES ( :Name, :Chip, :Dob, :DobKnown, :Sex, :Colour, :Hair, :Notes, :InRescue )""" AdvDbQuery(self.conn, sql_query, update_dict, returnlist=False) self.close_window() self.main_win.refresh_main_tree() def close_window(self): self.master.destroy() def _show_hide_date(self, event): option = self.dob_known_1.get() if option in ("Yes", "Roughly"): self.dob_cal.pack(side="top", anchor="n", fill="x") else: self.dob_cal.pack_forget() def _populate_data(self, conn, id): populate_query = "SELECT * FROM Populate_Animal_Data WHERE ID = :ID" populate_dict = {'ID': id} results = AdvDbQuery(conn, populate_query, populate_dict) # Update widgets # ID id_text = results[1][0][results[0].index('ID')] self.id_label.configure(text=id_text) # Name name_text = results[1][0][results[0].index('Name')] self.name_entry.insert(0, name_text) # Chip num chip_num_text = results[1][0][results[0].index('Chip_Num')] self.chip_num_1.insert(0, chip_num_text) # DOB known dob_known_text = results[1][0][results[0].index('DOB_Known')] self.dob_known_1.set(dob_known_text) self._show_hide_date("") # Date of birth if dob_known_text != "No": dob_text = results[1][0][results[0].index('Date_Of_Birth')] new_date = datetime.strptime(dob_text, '%Y-%m-%d') new_date_text = new_date.strftime('%d/%m/%Y') self.dob_cal.selection_set(new_date) self.dob_text_1.configure(text=new_date_text) # Sex sex_text = results[1][0][results[0].index('Sex')] self.sex_1.set(sex_text) # Colour colour_text = results[1][0][results[0].index('Colour')] self.colour_1.insert(0, colour_text) # Hair type hair_type_text = results[1][0][results[0].index('Hair_Type')] self.hair_type_1.set(hair_type_text) # Notes notes_text = results[1][0][results[0].index('Notes')] self.note_text.insert('end', notes_text) # In rescue in_rescue_value = results[1][0][results[0].index('In_Rescue')] self.in_rescue_var.set(in_rescue_value)