def update_style(self): bg = CONFIG.get(self.name, 'background', fallback='grey10') fg = CONFIG.get(self.name, 'foreground', fallback='white') active_bg = active_color(*self.winfo_rgb(bg)) self.attributes('-alpha', CONFIG.get(self.name, 'alpha', fallback=0.85)) self.configure(bg=bg) self._calendar.menu.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg) self.menu.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg) self.menu_pos.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg) keys = self._calendar.keys() opts = { opt: CONFIG.get('Calendar', opt) for opt in CONFIG.options('Calendar') if opt in keys } self._calendar.configure(**opts) self._calendar['font'] = CONFIG.get('Calendar', 'font') self._calendar.update_style()
def ting(): """ joue le son marquant le changement de période """ if not CONFIG.getboolean("Pomodoro", "mute", fallback=False): Popen([ CONFIG.get("General", "soundplayer"), CONFIG.get("Pomodoro", "beep") ])
def _setup_style(self): # scrollbars for widget in ['Events', 'Tasks']: bg = CONFIG.get(widget, 'background', fallback='gray10') fg = CONFIG.get(widget, 'foreground', fallback='white') widget_bg = self.winfo_rgb(bg) widget_fg = tuple( round(c * 255 / 65535) for c in self.winfo_rgb(fg)) active_bg = active_color(*widget_bg) active_bg2 = active_color(*active_color(*widget_bg, 'RGB')) slider_vert = Image.new('RGBA', (13, 28), active_bg) slider_vert.putalpha(self._slider_alpha) slider_vert_active = Image.new('RGBA', (13, 28), widget_fg) slider_vert_active.putalpha(self._slider_alpha) slider_vert_prelight = Image.new('RGBA', (13, 28), active_bg2) slider_vert_prelight.putalpha(self._slider_alpha) self._im_trough[widget].put(" ".join( ["{" + " ".join([bg] * 15) + "}"] * 15)) self._im_slider_vert_active[widget].paste(slider_vert_active) self._im_slider_vert[widget].paste(slider_vert) self._im_slider_vert_prelight[widget].paste(slider_vert_prelight) for widget in self.widgets.values(): widget.update_style()
def settings(self): splash_supp = CONFIG.get('General', 'splash_supported', fallback=True) dialog = Settings(self) self.wait_window(dialog) self._setup_style() if splash_supp != CONFIG.get('General', 'splash_supported'): for widget in self.widgets.values(): widget.update_position()
def display_tasks(self, force=False): tasks = self.master.get_tasks() tasks.sort(key=lambda ev: ev['End']) self.display.configure(state='normal') self.display.delete('1.0', 'end') for ev in tasks: if not self.hide_completed or ev['Task'] != 'Completed': if ev["WholeDay"]: end = format_date(ev['End'], locale=CONFIG.get("General", "locale")) else: end = format_datetime(ev['End'], locale=CONFIG.get("General", "locale")) picto = TASK_STATE.get(ev['Task'], ev['Task']) txt = "\t%s\t%s [%s]\n" % (picto, ev['Summary'], end) self.display.insert('end', txt) self.display.configure(state='disabled')
def get_next_week_events(self): """Return events scheduled for the next 7 days """ locale = CONFIG.get("General", "locale") next_ev = {} today = datetime.now().date() for d in range(7): day = today + timedelta(days=d) evts = self.widgets['Calendar'].get_events(day) if evts: evts = [self.events[iid] for iid in evts] evts.sort(key=lambda ev: ev.get_start_time()) desc = [] for ev in evts: if ev["WholeDay"]: date = "" else: date = "%s - %s " % ( format_time(ev['Start'], locale=locale), format_time(ev['End'], locale=locale)) place = "(%s)" % ev['Place'] if place == "()": place = "" desc.append(("%s%s %s\n" % (date, ev['Summary'], place), ev['Description'])) next_ev[day.strftime('%A')] = desc return next_ev
def __init__(self, name, master=None, **kw): """ Create a desktop widget that sticks on the desktop. """ Toplevel.__init__(self, master) self.name = name if CONFIG.getboolean('General', 'splash_supported', fallback=True): self.attributes('-type', 'splash') else: self.attributes('-type', 'toolbar') self.style = Style(self) self._position = StringVar(self, CONFIG.get(self.name, 'position')) self._position.trace_add( 'write', lambda *x: CONFIG.set(self.name, 'position', self._position.get())) self.ewmh = EWMH() self.title('scheduler.{}'.format(self.name.lower())) self.withdraw() # control main menu checkbutton self.variable = BooleanVar(self, False) # --- menu self.menu = Menu(self, relief='sunken', activeborderwidth=0) self._populate_menu() self.create_content(**kw) self.x = None self.y = None # --- geometry geometry = CONFIG.get(self.name, 'geometry') self.update_idletasks() if geometry: self.geometry(geometry) self.update_idletasks() if CONFIG.getboolean(self.name, 'visible', fallback=True): self.show() # --- bindings self.bind('<Configure>', self._on_configure)
def update_style(self): bg = CONFIG.get(self.name, 'background', fallback='grey10') fg = CONFIG.get(self.name, 'foreground', fallback='white') active_bg = active_color(*self.winfo_rgb(bg)) self.attributes('-alpha', CONFIG.get(self.name, 'alpha', fallback=0.85)) self.configure(bg=bg) self.menu.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg) self.menu_pos.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg)
def values(self): """ return the values (Summary, Place, Start, End) to put in the main window treeview """ locale = CONFIG.get("General", "locale") if self['WholeDay']: start = format_date(self['Start'], locale=locale) end = format_date(self['End'], locale=locale) else: start = format_datetime(self['Start'], locale=locale) end = format_datetime(self['End'], locale=locale) return self['Summary'], self['Place'], start, end, self['Category']
def update_style(self): self.attributes('-alpha', CONFIG.get(self.name, 'alpha', fallback=0.85)) bg = CONFIG.get('Timer', 'background') fg = CONFIG.get('Timer', 'foreground') active_bg = active_color(*self.winfo_rgb(bg)) self.configure(bg=bg) self.menu.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg) self.menu_pos.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg) self.display.configure(font=CONFIG.get('Timer', 'font_time')) self.intervals.configure(bg=bg, fg=fg, font=CONFIG.get('Timer', 'font_intervals')) self.style.configure('timer.TButton', background=bg, relief='flat', foreground=fg, borderwidth=0) self.style.configure('timer.TLabel', background=bg, foreground=fg) self.style.configure('timer.TSizegrip', background=bg) self.style.map('timer.TSizegrip', background=[('active', active_bg)]) self.style.map('timer.TButton', background=[('disabled', bg), ('!disabled', 'active', active_bg)])
def update_style(self): bg = CONFIG.get('Events', 'background') fg = CONFIG.get('Events', 'foreground') active_bg = active_color(*self.winfo_rgb(bg)) self.attributes('-alpha', CONFIG.get(self.name, 'alpha', fallback=0.85)) self.style.configure('Events.TFrame', background=bg) self.style.configure('Events.TSizegrip', background=bg) self.style.configure('Events.TSeparator', background=bg) self.style.configure('Events.TLabel', background=bg, foreground=fg, font=CONFIG.get('Events', 'font')) self.style.configure('title.Events.TLabel', font=CONFIG.get('Events', 'font_title')) self.style.configure('day.Events.TLabel', font=CONFIG.get('Events', 'font_day')) self.style.configure('Toggle', background=bg) self.configure(bg=bg) self.menu_pos.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg) self.menu.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg) self.canvas.configure(bg=bg)
def _init_events(self): self.frames[_('Events')].columnconfigure(0, weight=1) # --- Fonts frame_font = ttk.Frame(self.frames[_('Events')]) frame_font.columnconfigure(2, weight=1) ttk.Label(frame_font, text=_('Font'), style='title.TLabel').grid(row=0, column=0, sticky='w', padx=4, pady=4) # --- --- title ttk.Label(frame_font, style='subtitle.TLabel', text=_('Title')).grid(row=1, column=0, sticky='ne', padx=4, pady=8) self.events_font_title = FontFrame(frame_font, CONFIG.get('Events', 'font_title'), True) self.events_font_title.grid(row=1, column=1, padx=4, pady=4) ttk.Separator(frame_font, orient='horizontal').grid(row=2, columnspan=3, padx=10, pady=4, sticky='ew') # --- --- day ttk.Label(frame_font, style='subtitle.TLabel', text=_('Day')).grid(row=3, column=0, sticky='ne', padx=4, pady=8) self.events_font_day = FontFrame(frame_font, CONFIG.get('Events', 'font_day'), True) self.events_font_day.grid(row=3, column=1, padx=4, pady=4) ttk.Separator(frame_font, orient='horizontal').grid(row=4, columnspan=3, padx=10, pady=4, sticky='ew') # --- --- text ttk.Label(frame_font, style='subtitle.TLabel', text=_('Text')).grid(row=5, column=0, sticky='ne', padx=4, pady=8) self.events_font = FontFrame(frame_font, CONFIG.get('Events', 'font')) self.events_font.grid(row=5, column=1, padx=4, pady=4) # --- opacity self.events_opacity = OpacityFrame( self.frames[_('Events')], CONFIG.getfloat("Events", "alpha", fallback=0.85)) # --- colors frame_color = ttk.Frame(self.frames[_('Events')]) ttk.Label(frame_color, text=_('Colors'), style='title.TLabel').grid(row=0, column=0, sticky='w', padx=8, pady=4) self.events_bg = ColorFrame(frame_color, CONFIG.get('Events', 'background'), _('Background')) self.events_bg.grid(row=0, column=1, sticky='e', padx=8, pady=4) self.events_fg = ColorFrame(frame_color, CONFIG.get('Events', 'foreground'), _('Foreground')) self.events_fg.grid(row=0, column=2, sticky='e', padx=8, pady=4) # --- placement frame_font.grid(sticky='ew') ttk.Separator(self.frames[_('Events')], orient='horizontal').grid(sticky='ew', pady=8) self.events_opacity.grid(sticky='w', padx=4) ttk.Separator(self.frames[_('Events')], orient='horizontal').grid(sticky='ew', pady=8) frame_color.grid(sticky='w')
def _init_calendar(self): # --- general config general = ttk.Frame(self.frames[_('Calendar')], padding=4) general.columnconfigure(1, weight=1) self.frames[_('Calendar')].add(general, text=_('General')) # --- --- opacity self.cal_opacity = OpacityFrame( general, CONFIG.getfloat('Calendar', 'alpha', fallback=0.85)) self.cal_opacity.grid(row=0, columnspan=2, sticky='w', padx=4) ttk.Separator(general, orient='horizontal').grid(row=1, columnspan=2, pady=10, sticky='ew') # --- --- font ttk.Label(general, text=_('Font'), style='title.TLabel').grid(row=2, sticky='nw', padx=4, pady=4) self.cal_font = FontFrame(general, CONFIG.get('Calendar', 'font')) self.cal_font.grid(row=2, column=1, sticky='w', padx=4, pady=4) # --- Colors frame_color = ttk.Frame(self.frames[_('Calendar')], padding=4) frame_color.columnconfigure(3, weight=1) self.frames[_('Calendar')].add(frame_color, text=_('Colors')) self.cal_colors = {} ttk.Label(frame_color, style='subtitle.TLabel', text=_('General')).grid(row=0, column=0, sticky='w') self.cal_bg = ColorFrame(frame_color, CONFIG.get('Calendar', 'background'), _('Background')) self.cal_fg = ColorFrame(frame_color, CONFIG.get('Calendar', 'foreground'), _('Foreground')) self.cal_bd = ColorFrame(frame_color, CONFIG.get('Calendar', 'bordercolor'), _('Border')) self.cal_bg.grid(row=0, column=1, sticky='e', padx=8, pady=4) self.cal_fg.grid(row=0, column=2, sticky='e', padx=8, pady=4) self.cal_bd.grid(row=1, column=1, sticky='e', padx=8, pady=4) cal_colors = { 'normal': _('Normal day'), 'weekend': _('Weekend'), 'othermonth': _('Other month day'), 'othermonthwe': _('Other month weekend'), 'select': _('Selected day'), 'headers': _('Headers'), 'tooltip': _('Tooltip') } for i, (name, label) in enumerate(cal_colors.items()): bg = ColorFrame(frame_color, CONFIG.get('Calendar', name + 'background'), _('Background')) fg = ColorFrame(frame_color, CONFIG.get('Calendar', name + 'foreground'), _('Foreground')) self.cal_colors[name + 'background'] = bg self.cal_colors[name + 'foreground'] = fg ttk.Separator(frame_color, orient='horizontal').grid(row=2 + 2 * i, columnspan=4, pady=10, sticky='ew') ttk.Label(frame_color, style='subtitle.TLabel', wraplength=110, text=label).grid(row=3 + 2 * i, column=0, sticky='w') bg.grid(row=3 + 2 * i, column=1, sticky='e', padx=8, pady=4) fg.grid(row=3 + 2 * i, column=2, sticky='e', padx=8, pady=4) # --- Categories categories = ttk.Frame(self.frames[_('Calendar')], padding=4) categories.columnconfigure(0, weight=1) categories.rowconfigure(0, weight=1) self.frames[_('Calendar')].add(categories, text=_('Event categories')) can = tk.Canvas(categories, bg=self['bg'], highlightthickness=0, width=1, relief='flat') scroll = AutoScrollbar(categories, orient='vertical', command=can.yview) can.configure(yscrollcommand=scroll.set) can.grid(row=0, column=0, sticky='ewns') scroll.grid(row=0, column=1, sticky='ns') ttk.Button(categories, image=self._im_plus, command=self.add_cat).grid(row=1, column=0, sticky='w', pady=4) self.cat_frame = ttk.Frame(can) can.create_window(0, 0, anchor='nw', window=self.cat_frame) self.cats = {} for i, cat in enumerate(CONFIG.options("Categories")): l = ttk.Label(self.cat_frame, text=cat, style='subtitle.TLabel') col = CONFIG.get('Categories', cat).split(', ') bg = ColorFrame(self.cat_frame, col[1].strip(), _('Background')) fg = ColorFrame(self.cat_frame, col[0].strip(), _('Foreground')) b = ttk.Button(self.cat_frame, image=self._im_moins, padding=2, command=lambda c=cat: self.del_cat(c)) self.cats[cat] = [l, bg, fg, b] l.grid(row=i, column=0, sticky='e', padx=4, pady=4) bg.grid(row=i, column=1, sticky='e', padx=4, pady=4) fg.grid(row=i, column=2, sticky='e', padx=4, pady=4) b.grid(row=i, column=3, sticky='e', padx=4, pady=4) self.update_idletasks() can.configure(width=self.cat_frame.winfo_reqwidth()) can.configure(scrollregion=can.bbox('all')) can.bind('<4>', lambda e: self._scroll(e, -1)) can.bind('<5>', lambda e: self._scroll(e, 1)) self.cat_frame.bind( '<Configure>', lambda e: can.configure(scrollregion=can.bbox('all')))
def _init_reminders(self): # --- window def toggle_window(): b = 'selected' in self.reminders_window.state() state = [b * '!' + 'disabled'] label.state(state) self.reminders_timeout.state(state) self.reminders_blink.state(state) self.reminders_sound.state(state) frame_window = ttk.Frame(self.frames[_('Reminders')]) frame_window.columnconfigure(0, weight=1) self.reminders_window = ttk.Checkbutton(frame_window, text=_('Banner'), style='title.TCheckbutton', command=toggle_window) self.reminders_window.grid(sticky='w', row=0, columnspan=2, column=0, pady=4) self.reminders_window.state( ('!alternate', '!' * (not CONFIG.getboolean('Reminders', 'window')) + 'selected')) # --- --- timeout frame_timeout = ttk.Frame(frame_window) frame_timeout.grid(sticky='w', padx=(16, 4), pady=4) label = ttk.Label(frame_timeout, text=_('Timeout (min)')) label.pack(side='left') self.reminders_timeout = ttk.Entry(frame_timeout, width=5, justify='center', validate='key', validatecommand=(self._only_nb, '%P')) self.reminders_timeout.insert(0, CONFIG.get('Reminders', 'timeout')) self.reminders_timeout.pack(side='left', padx=4) # --- --- colors frame_color = ttk.Frame(frame_window) frame_color.grid(sticky='w', padx=(16, 4), pady=4) self.reminders_window_bg = ColorFrame( frame_color, CONFIG.get('Reminders', 'window_bg'), _('Background')) self.reminders_window_bg.pack(side='left', padx=(0, 4)) self.reminders_window_fg = ColorFrame( frame_color, CONFIG.get('Reminders', 'window_fg'), _('Foreground')) self.reminders_window_fg.pack(side='left', padx=(4, 0)) # --- --- opacity self.reminders_opacity = OpacityFrame(frame_window, CONFIG.getfloat('Reminders', 'window_alpha', fallback=0.75), style='TLabel') self.reminders_opacity.grid(sticky='w', padx=(16, 4), pady=4) ttk.Separator(frame_window, orient='horizontal').grid(sticky='ew', padx=(16, 10), pady=10) # --- --- blink frame_blink = ttk.Frame(frame_window) frame_blink.grid(sticky='w', padx=(16, 4), pady=4) def toggle_blink(): b = 'selected' in self.reminders_blink.state() state = [b * '!' + 'disabled'] self.reminders_window_bg_alt.state(state) self.reminders_window_fg_alt.state(state) self.reminders_blink = ttk.Checkbutton(frame_blink, text=_('Blink'), command=toggle_blink) self.reminders_blink.pack(anchor='nw') self.reminders_blink.state( ('!alternate', '!' * (not CONFIG.getboolean('Reminders', 'blink')) + 'selected')) self.reminders_window_bg_alt = ColorFrame( frame_blink, CONFIG.get('Reminders', 'window_bg_alternate'), _('Alternate Background')) self.reminders_window_bg_alt.pack(side='left', padx=(16, 4)) self.reminders_window_fg_alt = ColorFrame( frame_blink, CONFIG.get('Reminders', 'window_fg_alternate'), _('Alternate Foreground')) self.reminders_window_fg_alt.pack(side='left', padx=10) toggle_blink() ttk.Separator(frame_window, orient='horizontal').grid(sticky='ew', padx=(16, 10), pady=10) # --- --- alarm self.reminders_sound = SoundFrame(frame_window, CONFIG.get('Reminders', 'alarm'), CONFIG.get('Reminders', 'mute'), _('Alarm')) self.reminders_sound.grid(sticky='ew', padx=(16, 10), pady=4) # --- notif frame_notif = ttk.Frame(self.frames[_('Reminders')]) self.reminders_notif = ttk.Checkbutton(frame_notif, text=_('Notification'), style='title.TCheckbutton') self.reminders_notif.grid(sticky='w', pady=4) self.reminders_notif.state( ('!alternate', '!' * (not CONFIG.getboolean('Reminders', 'notification')) + 'selected')) # --- placement frame_window.pack(anchor='nw', fill='x') ttk.Separator(self.frames[_('Reminders')], orient='horizontal').pack(fill='x', pady=10) frame_notif.pack(anchor='nw')
def _init_general(self): self.frames[_('General')].columnconfigure(0, weight=1) # --- variables self.gui = tk.StringVar(self, CONFIG.get("General", "trayicon").capitalize()) self.lang = tk.StringVar(self, LANGUAGES[CONFIG.get("General", "language")]) # --- Langue lang_frame = ttk.Frame(self.frames[_('General')]) ttk.Label(lang_frame, text=_("Language")).pack(side="left") languages = list(REV_LANGUAGES) self.cb_lang = ttk.Combobox(lang_frame, textvariable=self.lang, state='readonly', style='menu.TCombobox', exportselection=False, width=len(max(languages, key=len)) + 1, values=languages) self.cb_lang.pack(side="left", padx=4) self.cb_lang.bind('<<ComboboxSelected>>', self.change_langue) # --- gui toolkit frame_gui = ttk.Frame(self.frames[_('General')]) ttk.Label( frame_gui, text=_("GUI Toolkit for the system tray icon")).pack(side="left") self.cb_gui = ttk.Combobox( frame_gui, textvariable=self.gui, state='readonly', style='menu.TCombobox', exportselection=False, width=4, values=[t.capitalize() for (t, b) in TOOLKITS.items() if b]) self.cb_gui.pack(side="left", padx=4) self.cb_gui.bind('<<ComboboxSelected>>', self.change_gui) # --- Update checks # self.confirm_update = ttk.Checkbutton(self.frames[_('General')], # text=_("Check for updates on start-up")) # if CONFIG.getboolean('General', 'check_update', fallback=True): # self.confirm_update.state(('selected', '!alternate')) # else: # self.confirm_update.state(('!selected', '!alternate')) # --- eyes frame_eyes = ttk.Frame(self.frames[_('General')]) ttk.Label(frame_eyes, text=_("Eyes' rest"), style='title.TLabel').grid(sticky='w', padx=4, pady=4) ttk.Label(frame_eyes, text=_("Interval between two eyes' rest (min)")).grid( row=1, column=0, sticky='w', padx=4, pady=4) self.eyes_interval = ttk.Entry(frame_eyes, width=4, justify='center', validate='key', validatecommand=(self._only_nb, '%P')) self.eyes_interval.insert( 0, CONFIG.get("General", "eyes_interval", fallback='20')) self.eyes_interval.grid(row=1, column=1, sticky='w', padx=4, pady=4) # --- Splash supported self.splash_support = ttk.Checkbutton( self.frames[_('General')], text=_("Check this box if the widgets disappear when you click")) if not CONFIG.getboolean('General', 'splash_supported', fallback=True): self.splash_support.state(('selected', '!alternate')) else: self.splash_support.state(('!selected', '!alternate')) # --- Maintenance frame_maintenance = ttk.Frame(self.frames[_('General')]) ttk.Label(frame_maintenance, text=_("Maintenance"), style='title.TLabel').grid(sticky='w', padx=4, pady=4) ttk.Label(frame_maintenance, text=_("Delete all outdated events")).grid(row=1, column=0, sticky='w', padx=4, pady=4) ttk.Button(frame_maintenance, image=self._im_cleanup, padding=1, command=self.cleanup).grid(row=1, column=1, sticky='w', padx=4, pady=4) ttk.Label( frame_maintenance, text= _("Refresh scheduled reminders\n(needed after APScheduler's updates)" )).grid(row=2, column=0, sticky='w', padx=4, pady=4) ttk.Button(frame_maintenance, image=self._im_refresh, padding=1, command=self.refresh).grid(row=2, column=1, sticky='w', padx=4, pady=4) # --- placement ttk.Label(self.frames[_('General')], text=_("Interface"), style='title.TLabel').grid(sticky='w', pady=4) lang_frame.grid(pady=4, sticky="ew") frame_gui.grid(pady=4, sticky="ew") # self.confirm_update.grid(pady=4, sticky='w') self.splash_support.grid(pady=4, sticky='w') ttk.Separator(self.frames[_('General')], orient='horizontal').grid(sticky='ew', pady=10) frame_eyes.grid(pady=4, sticky="ew") ttk.Separator(self.frames[_('General')], orient='horizontal').grid(sticky='ew', pady=10) frame_maintenance.grid(pady=4, sticky="ew")
def to_datetime(date): date_format = get_date_format("short", CONFIG.get("General", "locale")).pattern dayfirst = date_format.startswith("d") yearfirst = date_format.startswith("y") return parse(date, dayfirst=dayfirst, yearfirst=yearfirst)
def valide(self): """Update config and return whether the pomodor timer should be stopped.""" old_tpsw = CONFIG.getint("Pomodoro", "work_time") old_tpsp = CONFIG.getint("Pomodoro", "break_time") old_tpsr = CONFIG.getint("Pomodoro", "rest_time") try: tpsw = int(self.travail.get()) except ValueError: # empty entry tpsw = 0 if tpsw == 0: tpsw = old_tpsw try: tpsp = int(self.pause.get()) except ValueError: tpsp = 0 if tpsp == 0: tpsp = old_tpsp try: tpsr = int(self.rest.get()) except ValueError: tpsr = 0 if tpsr == 0: tpsr = old_tpsr sound, mute = self.sound.get() font_prop = self.font.get_font() font = "{} {}".format(font_prop['family'].replace(' ', '\ '), font_prop['size']) try: legend_rows = int(self.legend_row_nb.get()) except ValueError: legend_rows = 0 if legend_rows == 0: legend_rows = CONFIG.getint("Pomodoro", "legend_max_height") if not os.path.exists(sound): showerror( _("Error"), _("The file {filepath} does not exists, the old file will be used." ).format(filepath=sound)) sound = CONFIG.get("Pomodoro", "beep") CONFIG.set("Pomodoro", "alpha", str(self.opacity.get_opacity())) CONFIG.set("Pomodoro", "font", font) CONFIG.set("Pomodoro", "background", self.bg.get_color()) CONFIG.set("Pomodoro", "foreground", self.fg.get_color()) CONFIG.set("Pomodoro", "work_time", str(tpsw)) CONFIG.set("Pomodoro", "work_bg", self.work_bg.get_color()) CONFIG.set("Pomodoro", "work_fg", self.work_fg.get_color()) CONFIG.set("Pomodoro", "break_time", str(tpsp)) CONFIG.set("Pomodoro", "break_bg", self.break_bg.get_color()) CONFIG.set("Pomodoro", "break_fg", self.break_fg.get_color()) CONFIG.set("Pomodoro", "rest_time", str(tpsr)) CONFIG.set("Pomodoro", "rest_bg", self.rest_bg.get_color()) CONFIG.set("Pomodoro", "rest_fg", self.rest_fg.get_color()) CONFIG.set("Pomodoro", "beep", sound) CONFIG.set("Pomodoro", "mute", str(mute)) CONFIG.set("Pomodoro", "legend_max_height", str(legend_rows)) for task, widget in self.tasks.items(): CONFIG.set("PomodoroTasks", task, widget.get_color()) return old_tpsw != tpsw or old_tpsp != tpsp or old_tpsr != old_tpsr
def plot_stats(self): tasks = [t.capitalize() for t in CONFIG.options("PomodoroTasks")] tasks.sort() coul = [CONFIG.get("PomodoroTasks", task) for task in tasks] stats_x = [] stats_y = [] demain = dt.date.today().toordinal() + 1 min_x = demain # récupération des données no_data = True db = sqlite3.connect(PATH_STATS) cursor = db.cursor() for i, task in enumerate(tasks): name = task.lower().replace(' ', '_') try: cursor.execute('SELECT date, work FROM {}'.format(scrub(name))) data = cursor.fetchall() except sqlite3.OperationalError: # task was never worked stats_x.append([demain - 1]) stats_y.append(np.array([0])) else: no_data = False x = [] y = [] for date, work in data: x.append(date) y.append(work / 60) min_x = min(x[0], min_x) stats_x.append(x) stats_y.append(y) db.close() # plots xx = np.arange(min_x, demain, dtype=float) yy0 = np.zeros_like(xx) # pour empiler les stats if not no_data: for (i, task), x, y in zip(enumerate(tasks), stats_x, stats_y): yy = np.array([], dtype=int) # comble les trous par des 0 # ainsi, les jours où une tâche n'a pas été travaillée correspondent # à des 0 sur le graph xxx = np.arange(min_x, x[0]) yy = np.concatenate((yy, np.zeros_like(xxx, dtype=int))) for j in range(len(x) - 1): xxx = np.arange(x[j], x[j + 1]) yy = np.concatenate( (yy, [y[j]], np.zeros(len(xxx) - 1, dtype=int))) xxx = np.arange(x[-1], demain) yy = np.concatenate( (yy, [y[-1]], np.zeros(len(xxx) - 1, dtype=int))) self.ax.bar(xx, yy, bottom=yy0, width=0.8, label=task, color=coul[i]) yy0 += yy self.ax.xaxis.set_major_formatter(DateFormatter('%x')) self.ax.set_xlim(min_x - 0.5, demain - 0.5) self.ax.set_ylabel(_("time (h)")) self.ax.set_xlabel(_("date")) self.ax.xaxis_date() rows = CONFIG.getint("Pomodoro", "legend_max_height", fallback=6) ncol = int(np.ceil(len(tasks) / rows)) lgd = self.ax.legend(fontsize=10, ncol=ncol, columnspacing=0.7, handlelength=0.9, handletextpad=0.5) try: lgd.set_draggable(True) except AttributeError: lgd.draggable(True) max_y = yy0.max() self.ax.set_ylim(0, max_y + 0.1 * max_y) self.ax.tick_params('x', rotation=70) self.update_idletasks() self.fig.tight_layout() self.figAgg.draw() self.toolbar.push_current() self.ax.set_xlim(max(demain - 30, min_x) - 0.5, demain - 0.5) self.toolbar.push_current() self.figAgg.draw()
def __init__(self): Tk.__init__(self, className='Scheduler') logging.info('Start') self.protocol("WM_DELETE_WINDOW", self.hide) self._visible = BooleanVar(self, False) self.withdraw() self.icon_img = PhotoImage(master=self, file=ICON48) self.iconphoto(True, self.icon_img) # --- systray icon self.icon = TrayIcon(ICON, fallback_icon_path=ICON_FALLBACK) # --- menu self.menu_widgets = SubMenu(parent=self.icon.menu) self.menu_eyes = Eyes(self.icon.menu, self) self.icon.menu.add_checkbutton(label=_('Manager'), command=self.display_hide) self.icon.menu.add_cascade(label=_('Widgets'), menu=self.menu_widgets) self.icon.menu.add_cascade(label=_("Eyes' rest"), menu=self.menu_eyes) self.icon.menu.add_command(label=_('Settings'), command=self.settings) self.icon.menu.add_separator() self.icon.menu.add_command(label=_('About'), command=lambda: About(self)) self.icon.menu.add_command(label=_('Quit'), command=self.exit) self.icon.bind_left_click(lambda: self.display_hide(toggle=True)) add_trace(self._visible, 'write', self._visibility_trace) self.menu = Menu(self, tearoff=False) self.menu.add_command(label=_('Edit'), command=self._edit_menu) self.menu.add_command(label=_('Delete'), command=self._delete_menu) self.right_click_iid = None self.menu_task = Menu(self.menu, tearoff=False) self._task_var = StringVar(self) menu_in_progress = Menu(self.menu_task, tearoff=False) for i in range(0, 110, 10): prog = '{}%'.format(i) menu_in_progress.add_radiobutton(label=prog, value=prog, variable=self._task_var, command=self._set_progress) for state in ['Pending', 'Completed', 'Cancelled']: self.menu_task.add_radiobutton(label=_(state), value=state, variable=self._task_var, command=self._set_progress) self._img_dot = tkPhotoImage(master=self) self.menu_task.insert_cascade(1, menu=menu_in_progress, compound='left', label=_('In Progress'), image=self._img_dot) self.title('Scheduler') self.rowconfigure(1, weight=1) self.columnconfigure(0, weight=1) self.scheduler = BackgroundScheduler(coalesce=False, misfire_grace_time=86400) self.scheduler.add_jobstore('sqlalchemy', url='sqlite:///%s' % JOBSTORE) self.scheduler.add_jobstore('memory', alias='memo') # --- style self.style = Style(self) self.style.theme_use("clam") self.style.configure('title.TLabel', font='TkdefaultFont 10 bold') self.style.configure('title.TCheckbutton', font='TkdefaultFont 10 bold') self.style.configure('subtitle.TLabel', font='TkdefaultFont 9 bold') self.style.configure('white.TLabel', background='white') self.style.configure('border.TFrame', background='white', border=1, relief='sunken') self.style.configure("Treeview.Heading", font="TkDefaultFont") bgc = self.style.lookup("TButton", "background") fgc = self.style.lookup("TButton", "foreground") bga = self.style.lookup("TButton", "background", ("active", )) self.style.map('TCombobox', fieldbackground=[('readonly', 'white'), ('readonly', 'focus', 'white')], background=[("disabled", "active", "readonly", bgc), ("!disabled", "active", "readonly", bga)], foreground=[('readonly', '!disabled', fgc), ('readonly', '!disabled', 'focus', fgc), ('readonly', 'disabled', 'gray40'), ('readonly', 'disabled', 'focus', 'gray40') ], arrowcolor=[("disabled", "gray40")]) self.style.configure('menu.TCombobox', foreground=fgc, background=bgc, fieldbackground=bgc) self.style.map('menu.TCombobox', fieldbackground=[('readonly', bgc), ('readonly', 'focus', bgc)], background=[("disabled", "active", "readonly", bgc), ("!disabled", "active", "readonly", bga)], foreground=[('readonly', '!disabled', fgc), ('readonly', '!disabled', 'focus', fgc), ('readonly', 'disabled', 'gray40'), ('readonly', 'disabled', 'focus', 'gray40') ], arrowcolor=[("disabled", "gray40")]) self.style.map('DateEntry', arrowcolor=[("disabled", "gray40")]) self.style.configure('cal.TFrame', background='#424242') self.style.configure('month.TLabel', background='#424242', foreground='white') self.style.configure('R.TButton', background='#424242', arrowcolor='white', bordercolor='#424242', lightcolor='#424242', darkcolor='#424242') self.style.configure('L.TButton', background='#424242', arrowcolor='white', bordercolor='#424242', lightcolor='#424242', darkcolor='#424242') active_bg = self.style.lookup('TEntry', 'selectbackground', ('focus', )) self.style.map('R.TButton', background=[('active', active_bg)], bordercolor=[('active', active_bg)], darkcolor=[('active', active_bg)], lightcolor=[('active', active_bg)]) self.style.map('L.TButton', background=[('active', active_bg)], bordercolor=[('active', active_bg)], darkcolor=[('active', active_bg)], lightcolor=[('active', active_bg)]) self.style.configure('txt.TFrame', background='white') self.style.layout('down.TButton', [('down.TButton.downarrow', { 'side': 'right', 'sticky': 'ns' })]) self.style.map('TRadiobutton', indicatorforeground=[('disabled', 'gray40')]) self.style.map('TCheckbutton', indicatorforeground=[('disabled', 'gray40')], indicatorbackground=[ ('pressed', '#dcdad5'), ('!disabled', 'alternate', 'white'), ('disabled', 'alternate', '#a0a0a0'), ('disabled', '#dcdad5') ]) self.style.map('down.TButton', arrowcolor=[("disabled", "gray40")]) self.style.map('TMenubutton', arrowcolor=[('disabled', self.style.lookup('TMenubutton', 'foreground', ['disabled']))]) bg = self.style.lookup('TFrame', 'background', default='#ececec') self.configure(bg=bg) self.option_add('*Toplevel.background', bg) self.option_add('*Menu.background', bg) self.option_add('*Menu.tearOff', False) # toggle text self._open_image = PhotoImage(name='img_opened', file=IM_OPENED, master=self) self._closed_image = PhotoImage(name='img_closed', file=IM_CLOSED, master=self) self._open_image_sel = PhotoImage(name='img_opened_sel', file=IM_OPENED_SEL, master=self) self._closed_image_sel = PhotoImage(name='img_closed_sel', file=IM_CLOSED_SEL, master=self) self.style.element_create( "toggle", "image", "img_closed", ("selected", "!disabled", "img_opened"), ("active", "!selected", "!disabled", "img_closed_sel"), ("active", "selected", "!disabled", "img_opened_sel"), border=2, sticky='') self.style.map('Toggle', background=[]) self.style.layout('Toggle', [('Toggle.border', { 'children': [('Toggle.padding', { 'children': [('Toggle.toggle', { 'sticky': 'nswe' })], 'sticky': 'nswe' })], 'sticky': 'nswe' })]) # toggle sound self._im_sound = PhotoImage(master=self, file=IM_SOUND) self._im_mute = PhotoImage(master=self, file=IM_MUTE) self._im_sound_dis = PhotoImage(master=self, file=IM_SOUND_DIS) self._im_mute_dis = PhotoImage(master=self, file=IM_MUTE_DIS) self.style.element_create( 'mute', 'image', self._im_sound, ('selected', '!disabled', self._im_mute), ('selected', 'disabled', self._im_mute_dis), ('!selected', 'disabled', self._im_sound_dis), border=2, sticky='') self.style.layout('Mute', [('Mute.border', { 'children': [('Mute.padding', { 'children': [('Mute.mute', { 'sticky': 'nswe' })], 'sticky': 'nswe' })], 'sticky': 'nswe' })]) self.style.configure('Mute', relief='raised') # widget scrollbar self._im_trough = {} self._im_slider_vert = {} self._im_slider_vert_prelight = {} self._im_slider_vert_active = {} self._slider_alpha = Image.open(IM_SCROLL_ALPHA) for widget in ['Events', 'Tasks']: bg = CONFIG.get(widget, 'background', fallback='gray10') fg = CONFIG.get(widget, 'foreground') widget_bg = self.winfo_rgb(bg) widget_fg = tuple( round(c * 255 / 65535) for c in self.winfo_rgb(fg)) active_bg = active_color(*widget_bg) active_bg2 = active_color(*active_color(*widget_bg, 'RGB')) slider_vert = Image.new('RGBA', (13, 28), active_bg) slider_vert_active = Image.new('RGBA', (13, 28), widget_fg) slider_vert_prelight = Image.new('RGBA', (13, 28), active_bg2) self._im_trough[widget] = tkPhotoImage(width=15, height=15, master=self) self._im_trough[widget].put(" ".join( ["{" + " ".join([bg] * 15) + "}"] * 15)) self._im_slider_vert_active[widget] = PhotoImage( slider_vert_active, master=self) self._im_slider_vert[widget] = PhotoImage(slider_vert, master=self) self._im_slider_vert_prelight[widget] = PhotoImage( slider_vert_prelight, master=self) self.style.element_create('%s.Vertical.Scrollbar.trough' % widget, 'image', self._im_trough[widget]) self.style.element_create( '%s.Vertical.Scrollbar.thumb' % widget, 'image', self._im_slider_vert[widget], ('pressed', '!disabled', self._im_slider_vert_active[widget]), ('active', '!disabled', self._im_slider_vert_prelight[widget]), border=6, sticky='ns') self.style.layout( '%s.Vertical.TScrollbar' % widget, [('%s.Vertical.Scrollbar.trough' % widget, { 'children': [('%s.Vertical.Scrollbar.thumb' % widget, { 'expand': '1' })], 'sticky': 'ns' })]) # --- tree columns = { _('Summary'): ({ 'stretch': True, 'width': 300 }, lambda: self._sort_by_desc(_('Summary'), False)), _('Place'): ({ 'stretch': True, 'width': 200 }, lambda: self._sort_by_desc(_('Place'), False)), _('Start'): ({ 'stretch': False, 'width': 150 }, lambda: self._sort_by_date(_('Start'), False)), _('End'): ({ 'stretch': False, 'width': 150 }, lambda: self._sort_by_date(_("End"), False)), _('Category'): ({ 'stretch': False, 'width': 100 }, lambda: self._sort_by_desc(_('Category'), False)) } self.tree = Treeview(self, show="headings", columns=list(columns)) for label, (col_prop, cmd) in columns.items(): self.tree.column(label, **col_prop) self.tree.heading(label, text=label, anchor="w", command=cmd) self.tree.tag_configure('0', background='#ececec') self.tree.tag_configure('1', background='white') self.tree.tag_configure('outdated', foreground='red') scroll = AutoScrollbar(self, orient='vertical', command=self.tree.yview) self.tree.configure(yscrollcommand=scroll.set) # --- toolbar toolbar = Frame(self) self.img_plus = PhotoImage(master=self, file=IM_ADD) Button(toolbar, image=self.img_plus, padding=1, command=self.add).pack(side="left", padx=4) Label(toolbar, text=_("Filter by")).pack(side="left", padx=4) # --- TODO: add filter by start date (after date) self.filter_col = Combobox( toolbar, state="readonly", # values=("",) + self.tree.cget('columns')[1:], values=("", _("Category")), exportselection=False) self.filter_col.pack(side="left", padx=4) self.filter_val = Combobox(toolbar, state="readonly", exportselection=False) self.filter_val.pack(side="left", padx=4) Button(toolbar, text=_('Delete All Outdated'), padding=1, command=self.delete_outdated_events).pack(side="right", padx=4) # --- grid toolbar.grid(row=0, columnspan=2, sticky='we', pady=4) self.tree.grid(row=1, column=0, sticky='eswn') scroll.grid(row=1, column=1, sticky='ns') # --- restore data data = {} self.events = {} self.nb = 0 try: with open(DATA_PATH, 'rb') as file: dp = Unpickler(file) data = dp.load() except Exception: l = [ f for f in os.listdir(os.path.dirname(BACKUP_PATH)) if f.startswith('data.backup') ] if l: l.sort(key=lambda x: int(x[11:])) shutil.copy(os.path.join(os.path.dirname(BACKUP_PATH), l[-1]), DATA_PATH) with open(DATA_PATH, 'rb') as file: dp = Unpickler(file) data = dp.load() self.nb = len(data) backup() now = datetime.now() for i, prop in enumerate(data): iid = str(i) self.events[iid] = Event(self.scheduler, iid=iid, **prop) self.tree.insert('', 'end', iid, values=self.events[str(i)].values()) tags = [str(self.tree.index(iid) % 2)] self.tree.item(iid, tags=tags) if not prop['Repeat']: for rid, d in list(prop['Reminders'].items()): if d < now: del self.events[iid]['Reminders'][rid] self.after_id = self.after(15 * 60 * 1000, self.check_outdated) # --- bindings self.bind_class("TCombobox", "<<ComboboxSelected>>", self.clear_selection, add=True) self.bind_class("TCombobox", "<Control-a>", self.select_all) self.bind_class("TEntry", "<Control-a>", self.select_all) self.tree.bind('<3>', self._post_menu) self.tree.bind('<1>', self._select) self.tree.bind('<Double-1>', self._edit_on_click) self.menu.bind('<FocusOut>', lambda e: self.menu.unpost()) self.filter_col.bind("<<ComboboxSelected>>", self.update_filter_val) self.filter_val.bind("<<ComboboxSelected>>", self.apply_filter) # --- widgets self.widgets = {} prop = { op: CONFIG.get('Calendar', op) for op in CONFIG.options('Calendar') } self.widgets['Calendar'] = CalendarWidget(self, locale=CONFIG.get( 'General', 'locale'), **prop) self.widgets['Events'] = EventWidget(self) self.widgets['Tasks'] = TaskWidget(self) self.widgets['Timer'] = Timer(self) self.widgets['Pomodoro'] = Pomodoro(self) self._setup_style() for item, widget in self.widgets.items(): self.menu_widgets.add_checkbutton( label=_(item), command=lambda i=item: self.display_hide_widget(i)) self.menu_widgets.set_item_value(_(item), widget.variable.get()) add_trace(widget.variable, 'write', lambda *args, i=item: self._menu_widgets_trace(i)) self.icon.loop(self) self.tk.eval(""" apply {name { set newmap {} foreach {opt lst} [ttk::style map $name] { if {($opt eq "-foreground") || ($opt eq "-background")} { set newlst {} foreach {st val} $lst { if {($st eq "disabled") || ($st eq "selected")} { lappend newlst $st $val } } if {$newlst ne {}} { lappend newmap $opt $newlst } } else { lappend newmap $opt $lst } } ttk::style map $name {*}$newmap }} Treeview """) # react to scheduler --update-date in command line signal.signal(signal.SIGUSR1, self.update_date) # update selected date in calendar and event list every day self.scheduler.add_job(self.update_date, CronTrigger(hour=0, minute=0, second=1), jobstore='memo') self.scheduler.start()
def update_style(self): cats = {cat: CONFIG.get('Categories', cat).split(', ') for cat in CONFIG.options('Categories')} for cat, (fg, bg) in cats.items(): style = 'ev_%s.%s.TLabel' % (cat, self._style_prefixe) self.style.configure(style, background=bg, foreground=fg)
def __init__(self, master, event, new=False): Toplevel.__init__(self, master) self.minsize(410, 402) if master.winfo_ismapped(): self.transient(master) self.protocol('WM_DELETE_WINDOW', self.cancel) self._only_nb = self.register(only_nb) self.event = event if new: self.title(_('New Event')) else: self.title(_('Edit Event')) self._new = new self._task = BooleanVar(self, bool(event['Task'])) self._whole_day = BooleanVar(self, event['WholeDay']) # --- style style = Style(self) active_bg = style.lookup('TEntry', 'selectbackground', ('focus', )) self.alarms = [] notebook = Notebook(self) notebook.pack(fill='both', expand=True) Button(self, text=_('Ok'), command=self.ok).pack(pady=(10, 6), padx=4) # --- event settings frame_event = Frame(notebook) notebook.add(frame_event, text=_('Event'), sticky='eswn', padding=4) frame_event.columnconfigure(1, weight=1) frame_event.rowconfigure(5, weight=1) self.img_moins = PhotoImage(master=self, file=IM_DEL) self.img_bell = PhotoImage(master=self, file=IM_BELL) Label(frame_event, text=_('Summary')).grid(row=0, column=0, padx=4, pady=6, sticky='e') Label(frame_event, text=_('Place')).grid(row=1, column=0, padx=4, pady=6, sticky='e') Label(frame_event, text=_('Start')).grid(row=2, column=0, padx=4, pady=6, sticky='e') self._end_label = Label(frame_event, text=_('End')) self._end_label.grid(row=3, column=0, padx=4, pady=6, sticky='e') frame_task = Frame(frame_event) frame_task.grid(row=4, column=1, padx=4, pady=6, sticky='w') Label(frame_event, text=_('Description')).grid(row=5, column=0, padx=4, pady=6, sticky='e') Label(frame_event, text=_('Category')).grid(row=6, column=0, padx=4, pady=6, sticky='e') Button(frame_event, image=self.img_bell, command=self.add_reminder, padding=0).grid(row=7, column=0, padx=4, pady=6, sticky='en') self.summary = Entry(frame_event, width=35) self.summary.insert(0, self.event['Summary']) self.summary.grid(row=0, column=1, padx=4, pady=6, sticky='ew') self.place = Entry(frame_event, width=35) self.place.insert(0, self.event['Place']) self.place.grid(row=1, column=1, padx=4, pady=6, sticky='ew') frame_start = Frame(frame_event) frame_start.grid(row=2, column=1, padx=4, pady=6, sticky='w') frame_end = Frame(frame_event) frame_end.grid(row=3, column=1, padx=4, pady=6, sticky='w') txt_frame = Frame(frame_event, style='txt.TFrame', border=1, relief='sunken') self.desc = Text(txt_frame, width=35, height=4, highlightthickness=0, relief='flat', selectbackground=active_bg) self.desc.insert('1.0', self.event['Description']) self.desc.pack(fill='both', expand=True) txt_frame.grid(row=5, column=1, padx=4, pady=6, sticky='ewsn') cats = list(CONFIG.options('Categories')) width = max([len(cat) for cat in cats]) self.category = Combobox(frame_event, width=width + 2, values=cats, state='readonly') self.category.set(event['Category']) self.category.grid(row=6, column=1, padx=4, pady=6, sticky='w') self.frame_alarms = Frame(frame_event) self.frame_alarms.grid(row=7, column=1, sticky='w') # --- *--- task Checkbutton(frame_task, text=_('Task'), command=self._change_label, variable=self._task).pack(side='left') self.task_progress = Combobox(frame_task, state='readonly', width=9, values=(_('Pending'), _('In Progress'), _('Completed'), _('Cancelled'))) self.task_progress.pack(side='left', padx=(8, 4)) self.in_progress = Combobox( frame_task, state='readonly', width=5, values=['{}%'.format(i) for i in range(0, 110, 10)]) self.in_progress.pack(side='left', padx=4) if not event['Task']: self.task_progress.set(_('Pending')) self.in_progress.set('0%') elif '%' in event['Task']: self.task_progress.set(_('In Progress')) self.in_progress.set(event['Task']) else: self.task_progress.set(_(event['Task'])) self.in_progress.set('0%') # calendar settings prop = { op: CONFIG.get('Calendar', op) for op in CONFIG.options('Calendar') } prop['font'] = "Liberation\ Sans 9" prop.update(selectforeground='white', selectbackground=active_bg) locale = CONFIG.get('General', 'locale') # --- *--- start date self.start_date = self.event['Start'] self.start_entry = DateEntry(frame_start, locale=locale, width=10, justify='center', year=self.start_date.year, month=self.start_date.month, day=self.start_date.day, **prop) self.start_hour = Combobox(frame_start, width=3, justify='center', state='readonly', exportselection=False, values=['%02d' % i for i in range(24)]) self.start_hour.set('%02d' % self.start_date.hour) self.start_min = Combobox(frame_start, width=3, justify='center', state='readonly', exportselection=False, values=['%02d' % i for i in range(0, 60, 5)]) self.start_min.set('%02d' % self.start_date.minute) self.start_entry.pack(side='left', padx=(0, 18)) self.start_hour.pack(side='left', padx=(4, 0)) self.start_date = self.start_date.date() Label(frame_start, text=':').pack(side='left') self.start_min.pack(side='left', padx=(0, 4)) Checkbutton(frame_start, text=_("whole day"), variable=self._whole_day, command=self._toggle_whole_day).pack(side='left', padx=4) # --- *--- end date self.end_date = self.event['End'] self.end_entry = DateEntry(frame_end, justify='center', locale=locale, width=10, year=self.end_date.year, month=self.end_date.month, day=self.end_date.day, **prop) self.end_hour = Combobox(frame_end, width=3, justify='center', state='readonly', exportselection=False, values=['%02d' % i for i in range(24)]) self.end_hour.set('%02d' % self.end_date.hour) self.end_min = Combobox(frame_end, width=3, justify='center', state='readonly', exportselection=False, values=['%02d' % i for i in range(0, 60, 5)]) self.end_min.set('%02d' % self.end_date.minute) self.end_entry.pack(side='left', padx=(0, 18)) self.end_hour.pack(side='left', padx=(4, 0)) Label(frame_end, text=':').pack(side='left') self.end_min.pack(side='left', padx=(0, 4)) self.end_date = self.end_date.date() for date in self.event['Reminders'].values(): self.add_reminder(date) self._toggle_whole_day() # --- repetition settings frame_rep = Frame(notebook) notebook.add(frame_rep, text=_('Repetition'), padding=4, sticky='eswn') frame_rep.columnconfigure(0, weight=1) frame_rep.columnconfigure(1, weight=1) frame_rep.rowconfigure(1, weight=1) self._repeat = BooleanVar(self, bool(self.event['Repeat'])) repeat = { 'Frequency': 'year', 'Limit': 'always', 'NbTimes': 1, 'EndDate': (datetime.now() + timedelta(days=1)).date(), 'WeekDays': [self.start_date.isocalendar()[2] - 1] } repeat.update(self.event['Repeat']) self._repeat_freq = StringVar(self, repeat['Frequency']) Checkbutton(frame_rep, text=_('Repeat event'), variable=self._repeat, command=self._toggle_rep).grid(row=0, column=0, columnspan=2, padx=4, pady=6, sticky='w') # --- *--- Frequency frame_freq = LabelFrame(frame_rep, text=_('Frequency')) frame_freq.grid(row=1, column=0, sticky='eswn', padx=(0, 3)) self._lfreq = Label(frame_freq, text=_('Every:')) self._lfreq.grid(row=0, column=0, padx=4, pady=2, sticky='e') self._freqs = [] for i, val in enumerate(['Year', 'Month', 'Week']): r = Radiobutton(frame_freq, text=_(val), variable=self._repeat_freq, value=val.lower(), command=self._toggle_wd) r.grid(row=i, column=1, padx=4, pady=2, sticky='nw') self._freqs.append(r) frame_days = Frame(frame_freq) frame_days.grid(row=2, column=2, padx=4, pady=2, sticky='nw') self._week_days = [] days = get_day_names("wide", locale=locale) days = [days[i] for i in range(7)] for day in days: ch = Checkbutton(frame_days, text=day) ch.pack(anchor='w') self._week_days.append(ch) for d in repeat['WeekDays']: self._week_days[int(d)].state(('selected', )) # --- *--- Limit frame_lim = LabelFrame(frame_rep, text=_('Limit')) frame_lim.grid(row=1, column=1, sticky='eswn', padx=(3, 0)) frame_lim.grid(row=1, column=1, sticky='eswn', padx=(3, 0)) self._repeat_lim = StringVar(self, repeat['Limit']) # always r1 = Radiobutton(frame_lim, text=_('Always'), value='always', variable=self._repeat_lim, command=self._toggle_lim) r1.grid(row=0, column=0, sticky='w') # until r2 = Radiobutton(frame_lim, text=_('Until'), value='until', variable=self._repeat_lim, command=self._toggle_lim) r2.grid(row=1, column=0, sticky='w') until_date = repeat['EndDate'] self.until_entry = DateEntry(frame_lim, width=10, justify='center', locale=locale, year=until_date.year, month=until_date.month, day=until_date.day, **prop) self.until_entry.grid(row=1, column=1, columnspan=2, sticky='w', padx=(4, 10), pady=2) # after r3 = Radiobutton(frame_lim, text=_('After'), value='after', variable=self._repeat_lim, command=self._toggle_lim) r3.grid(row=2, column=0, sticky='w') frame_after = Frame(frame_lim, style='txt.TFrame', relief='sunken', border=1) self.s_after = Spinbox(frame_after, from_=0, to=100, width=3, justify='center', relief='flat', highlightthickness=0, validate='key', validatecommand=(self._only_nb, '%P'), disabledbackground='white') self.s_after.pack() self.s_after.delete(0, 'end') self.s_after.insert(0, str(repeat['NbTimes'])) frame_after.grid(row=2, column=1, padx=4, pady=2, sticky='w') self._llim = Label(frame_lim, text=_('times')) self._llim.grid(row=2, column=2, padx=0, pady=2, sticky='w') self._rb_lim = [r1, r2, r3] self._toggle_rep() self._change_label() # --- bindings self.bind('<Configure>') self.task_progress.bind('<<ComboboxSelected>>', self._toggle_in_progress) self.start_entry.bind('<<DateEntrySelected>>', self._select_start) self.end_entry.bind('<<DateEntrySelected>>', self._select_end) self.start_hour.bind("<<ComboboxSelected>>", self._select_start_hour) self.start_min.bind("<<ComboboxSelected>>", self._select_start_min) self.end_min.bind("<<ComboboxSelected>>", self._select_end_time) self.end_hour.bind("<<ComboboxSelected>>", self._select_end_time) self.bind_class("TCombobox", "<<ComboboxSelected>>", self.__clear_selection, add=True) # self.wait_visibility(self) # self.grab_set() self.summary.focus_set()
def create_content(self, **kw): self.minsize(190, 190) self.on = False # is the timer on? if not CONFIG.options("Tasks"): CONFIG.set("Tasks", _("Work"), CMAP[0]) self._stats = None # --- colors self.background = { _("Work"): CONFIG.get("Pomodoro", "work_bg"), _("Break"): CONFIG.get("Pomodoro", "break_bg"), _("Rest"): CONFIG.get("Pomodoro", "rest_bg") } self.foreground = { _("Work"): CONFIG.get("Pomodoro", "work_fg"), _("Break"): CONFIG.get("Pomodoro", "break_fg"), _("Rest"): CONFIG.get("Pomodoro", "rest_fg") } self.rowconfigure(1, weight=1) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=1) # nombre de séquence de travail effectuées d'affilée (pour # faire des pauses plus longues tous les 4 cycles) self.nb_cycles = 0 self.pomodori = IntVar(self, 0) # --- images self.im_go = PhotoImage(master=self, file=IM_START) self.im_stop = PhotoImage(master=self, file=IM_STOP) self.im_tomate = PhotoImage(master=self, file=IM_POMODORO) self.im_graph = PhotoImage(master=self, file=IM_GRAPH) # --- tasks list tasks_frame = Frame(self, style='pomodoro.TFrame') tasks_frame.grid(row=3, column=0, columnspan=3, sticky="wnse") tasks = [t.capitalize() for t in CONFIG.options("PomodoroTasks")] tasks.sort() self.task = StringVar(self, tasks[0]) self.menu_tasks = Menu(tasks_frame, relief='sunken', activeborderwidth=0) self.choose_task = Menubutton(tasks_frame, textvariable=self.task, menu=self.menu_tasks, style='pomodoro.TMenubutton') Label(tasks_frame, text=_("Task: "), style='pomodoro.TLabel', font="TkDefaultFont 12", width=6, anchor="e").pack(side="left", padx=4) self.choose_task.pack(side="right", fill="x", pady=4) # --- display self.tps = [CONFIG.getint("Pomodoro", "work_time"), 0] # time: min, sec self.activite = StringVar(self, _("Work")) self.titre = Label(self, textvariable=self.activite, font='TkDefaultFont 14', style='timer.pomodoro.TLabel', anchor="center") self.titre.grid(row=0, column=0, columnspan=2, sticky="we", pady=(4, 0), padx=4) self.temps = Label(self, text="{0:02}:{1:02}".format(self.tps[0], self.tps[1]), style='timer.pomodoro.TLabel', anchor="center") self.temps.grid(row=1, column=0, columnspan=2, sticky="nswe", padx=4) self.aff_pomodori = Label(self, textvariable=self.pomodori, anchor='e', padding=(20, 4, 20, 4), image=self.im_tomate, compound="left", style='timer.pomodoro.TLabel', font='TkDefaultFont 14') self.aff_pomodori.grid(row=2, columnspan=2, sticky="ew", padx=4) # --- buttons self.b_go = Button(self, image=self.im_go, command=self.go, style='pomodoro.TButton') self.b_go.grid(row=4, column=0, sticky="ew") self.b_stats = Button(self, image=self.im_graph, command=self.display_stats, style='pomodoro.TButton') self.b_stats.grid(row=4, column=1, sticky="ew") self._corner = Sizegrip(self, style="pomodoro.TSizegrip") self._corner.place(relx=1, rely=1, anchor='se') # --- bindings self.bind('<3>', lambda e: self.menu.tk_popup(e.x_root, e.y_root)) tasks_frame.bind('<ButtonPress-1>', self._start_move) tasks_frame.bind('<ButtonRelease-1>', self._stop_move) tasks_frame.bind('<B1-Motion>', self._move) self.titre.bind('<ButtonPress-1>', self._start_move) self.titre.bind('<ButtonRelease-1>', self._stop_move) self.titre.bind('<B1-Motion>', self._move) self.temps.bind('<ButtonPress-1>', self._start_move) self.temps.bind('<ButtonRelease-1>', self._stop_move) self.temps.bind('<B1-Motion>', self._move) self.b_stats.bind('<Enter>', self._on_enter) self.b_stats.bind('<Leave>', self._on_leave)
def _init_tasks(self): self.frames[_('Tasks')].columnconfigure(0, weight=1) self.tasks_hide_comp = tk.BooleanVar( self, CONFIG.getboolean('Tasks', 'hide_completed')) # --- Fonts frame_font = ttk.Frame(self.frames[_('Tasks')]) frame_font.columnconfigure(2, weight=1) ttk.Label(frame_font, text=_('Font'), style='title.TLabel').grid(row=0, column=0, sticky='w', padx=4, pady=4) # --- --- title ttk.Label(frame_font, style='subtitle.TLabel', text=_('Title')).grid(row=1, column=0, sticky='nw', padx=4, pady=8) self.tasks_font_title = FontFrame(frame_font, CONFIG.get('Tasks', 'font_title'), True) self.tasks_font_title.grid(row=1, column=1, padx=4, pady=4) ttk.Separator(frame_font, orient='horizontal').grid(row=2, columnspan=3, padx=10, pady=4, sticky='ew') # --- --- text ttk.Label(frame_font, style='subtitle.TLabel', text=_('Text')).grid(row=5, column=0, sticky='nw', padx=4, pady=8) self.tasks_font = FontFrame(frame_font, CONFIG.get('Tasks', 'font')) self.tasks_font.grid(row=5, column=1, padx=4, pady=4) # --- opacity self.tasks_opacity = OpacityFrame( self.frames[_('Tasks')], CONFIG.getfloat("Tasks", "alpha", fallback=0.85)) # --- colors frame_color = ttk.Frame(self.frames[_('Tasks')]) ttk.Label(frame_color, text=_('Colors'), style='title.TLabel').grid(row=0, column=0, sticky='w', padx=8, pady=4) self.tasks_bg = ColorFrame(frame_color, CONFIG.get('Tasks', 'background'), _('Background')) self.tasks_bg.grid(row=0, column=1, sticky='e', padx=8, pady=4) self.tasks_fg = ColorFrame(frame_color, CONFIG.get('Tasks', 'foreground'), _('Foreground')) self.tasks_fg.grid(row=0, column=2, sticky='e', padx=8, pady=4) # --- placement frame_font.grid(sticky='ew') ttk.Separator(self.frames[_('Tasks')], orient='horizontal').grid(sticky='ew', pady=8) self.tasks_opacity.grid(sticky='w', padx=4) ttk.Separator(self.frames[_('Tasks')], orient='horizontal').grid(sticky='ew', pady=8) frame_color.grid(sticky='w') ttk.Separator(self.frames[_('Tasks')], orient='horizontal').grid(sticky='ew', pady=8) ttk.Checkbutton(self.frames[_('Tasks')], text=_('Hide completed tasks'), variable=self.tasks_hide_comp).grid(sticky='w', padx=4, pady=4)
def __init__(self, parent, **options): """ créer le Toplevel permettant de modifier les paramètres """ Frame.__init__(self, parent, **options) self.onglets = Notebook(self) self.onglets.pack(fill='both', expand=True) self.im_color = PhotoImage(master=self, file=IM_COLOR) self.im_plus = PhotoImage(master=self, file=IM_ADD) self.im_moins = PhotoImage(master=self, file=IM_DEL) self.okfct = self.register(only_nb) self.style = Style(self) self.nb_task = len(CONFIG.options("PomodoroTasks")) # --- Général (temps, police et langue) self.general = Frame(self.onglets, padding=10) self.general.columnconfigure(1, weight=1) self.onglets.add(self.general, text=_("General")) # --- --- Temps Label(self.general, text=_("Times (min)"), style='title.TLabel').grid(row=0, pady=4, padx=(2, 10), sticky="w") self.time_frame = Frame(self.general) self.time_frame.grid(row=0, column=1, sticky="w", padx=4) Label(self.time_frame, text=_("Work")).grid(row=0, padx=4, column=0) self.travail = Entry(self.time_frame, width=4, justify='center', validatecommand=(self.okfct, '%P'), validate='key') self.travail.insert(0, CONFIG.get("Pomodoro", "work_time")) self.travail.grid(row=0, column=1, padx=(0, 10)) Label(self.time_frame, text=_("Break")).grid(row=0, column=2, padx=4) self.pause = Entry(self.time_frame, width=4, justify='center', validatecommand=(self.okfct, '%P'), validate='key') self.pause.insert(0, CONFIG.get("Pomodoro", "break_time")) self.pause.grid(row=0, column=3, padx=(0, 10)) Label(self.time_frame, text=_("Rest")).grid(row=0, column=4, padx=4) self.rest = Entry(self.time_frame, width=4, justify='center', validatecommand=(self.okfct, '%P'), validate='key') self.rest.insert(0, CONFIG.get("Pomodoro", "rest_time")) self.rest.grid(row=0, column=5) Separator(self.general, orient='horizontal').grid(row=1, columnspan=2, sticky="ew", pady=10) # --- --- Police Label(self.general, text=_("Font"), style='title.TLabel').grid(row=2, sticky='nw', padx=(2, 10)) self.font = FontFrame(self.general, font=CONFIG.get('Pomodoro', 'font'), sample_text="02:17") self.font.grid(row=2, column=1, padx=4, sticky='w') Separator(self.general, orient='horizontal').grid(row=3, columnspan=2, sticky="ew", pady=10) # --- --- Opacity self.opacity = OpacityFrame(self.general) self.opacity.grid(row=5, columnspan=2, sticky='w', padx=(2, 4), pady=4) Separator(self.general, orient='horizontal').grid(row=6, columnspan=2, sticky="ew", pady=10) # --- --- Son self.sound = SoundFrame(self.general, CONFIG.get("Pomodoro", "beep"), mute=CONFIG.getboolean("Pomodoro", "mute"), label=_("Sound"), style='title.TLabel') self.sound.grid(row=7, columnspan=2, sticky='ew', pady=4) # --- Couleurs self.couleurs = Frame(self.onglets, padding=10) self.couleurs.columnconfigure(3, weight=1) self.onglets.add(self.couleurs, text=_("Colors")) self.bg = ColorFrame(self.couleurs, CONFIG.get("Pomodoro", "background"), _("Background")) self.work_bg = ColorFrame(self.couleurs, CONFIG.get("Pomodoro", "work_bg"), _("Background")) self.break_bg = ColorFrame(self.couleurs, CONFIG.get("Pomodoro", "break_bg"), _("Background")) self.rest_bg = ColorFrame(self.couleurs, CONFIG.get("Pomodoro", "rest_bg"), _("Background")) self.fg = ColorFrame(self.couleurs, CONFIG.get("Pomodoro", "foreground"), _("Foreground")) self.work_fg = ColorFrame(self.couleurs, CONFIG.get("Pomodoro", "work_fg"), _("Foreground")) self.break_fg = ColorFrame(self.couleurs, CONFIG.get("Pomodoro", "break_fg"), _("Foreground")) self.rest_fg = ColorFrame(self.couleurs, CONFIG.get("Pomodoro", "rest_fg"), _("Foreground")) Label(self.couleurs, text=_("General"), style='title.TLabel').grid(row=0, column=0, pady=4, padx=(2, 10), sticky="w") self.bg.grid(row=0, column=1, sticky='e', padx=8, pady=4) self.fg.grid(row=0, column=2, sticky='e', padx=8, pady=4) Separator(self.couleurs, orient='horizontal').grid(row=1, sticky="ew", pady=10, columnspan=4) Label(self.couleurs, text=_("Work"), style='title.TLabel').grid(row=2, column=0, pady=4, padx=(2, 10), sticky="w") self.work_bg.grid(row=2, column=1, sticky='e', padx=8, pady=4) self.work_fg.grid(row=2, column=2, sticky='e', padx=8, pady=4) Separator(self.couleurs, orient='horizontal').grid(row=3, sticky="ew", pady=10, columnspan=4) Label(self.couleurs, text=_("Break"), style='title.TLabel').grid(row=4, column=0, pady=4, padx=(2, 10), sticky="w") self.break_bg.grid(row=4, column=1, sticky='e', padx=8, pady=4) self.break_fg.grid(row=4, column=2, sticky='e', padx=8, pady=4) Separator(self.couleurs, orient='horizontal').grid(row=5, sticky="ew", pady=10, columnspan=4) Label(self.couleurs, text=_("Rest"), style='title.TLabel').grid(row=6, column=0, pady=4, padx=(2, 10), sticky="w") self.rest_bg.grid(row=6, column=1, sticky='e', padx=8, pady=4) self.rest_fg.grid(row=6, column=2, sticky='e', padx=8, pady=4) # --- Tasks self.stats = Frame(self.onglets, padding=10) self.stats.columnconfigure(0, weight=1) self.stats.rowconfigure(2, weight=1) self.onglets.add(self.stats, text=_("Tasks")) # graph legend legend_frame = Frame(self.stats) Label(legend_frame, style='title.TLabel', text=_('Maximum number of rows in the legend')).pack(side='left') self.legend_row_nb = Entry(legend_frame, width=4, justify='center', validatecommand=(self.okfct, '%P'), validate='key') self.legend_row_nb.insert( 0, CONFIG.get('Pomodoro', 'legend_max_height', fallback='6')) self.legend_row_nb.pack(side='left', padx=4) # task colors can = Canvas(self.stats, bg=self.style.lookup('TFrame', 'background'), highlightthickness=0, width=1, relief='flat') scroll = AutoScrollbar(self.stats, orient='vertical', command=can.yview) can.configure(yscrollcommand=scroll.set) self.task_frame = Frame(can) can.create_window(0, 0, anchor='nw', window=self.task_frame) tasks = CONFIG.options("PomodoroTasks") tasks.sort() cmap = [CONFIG.get("PomodoroTasks", task) for task in tasks] self.tasks = {} self._tasks_btns = {} for i, (coul, task) in enumerate(zip(cmap, tasks)): self.tasks[task] = ColorFrame(self.task_frame, coul, task.capitalize()) self.tasks[task].grid(row=i, column=0, sticky='e', padx=4, pady=4) b = Button(self.task_frame, image=self.im_moins, padding=2, command=lambda t=task: self.del_task(t)) b.grid(row=i, column=1, sticky='w', padx=4, pady=4) self._tasks_btns[task] = b if len(tasks) == 1: self._tasks_btns[tasks[0]].state(['disabled']) legend_frame.grid(row=0, columnspan=2, sticky='w', pady=4) Label(self.stats, text=_('Colors in the statistic graph'), style='title.TLabel').grid(row=1, column=0, sticky='w', pady=4) can.grid(row=2, column=0, sticky='ewns') scroll.grid(row=2, column=1, sticky='ns') Button(self.stats, image=self.im_plus, command=self.add_task).grid(row=3, column=0, sticky='w') self.update_idletasks() can.configure(width=self.task_frame.winfo_reqwidth()) can.configure(scrollregion=can.bbox('all')) can.bind('<4>', lambda e: self._scroll(e, -1)) can.bind('<5>', lambda e: self._scroll(e, 1)) self.task_frame.bind( '<Configure>', lambda e: can.configure(scrollregion=can.bbox('all')))
def _init_timer(self): self.frames[_('Timer')].columnconfigure(0, weight=1) # --- Fonts frame_font = ttk.Frame(self.frames[_('Timer')]) frame_font.columnconfigure(2, weight=1) ttk.Label(frame_font, text=_('Font'), style='title.TLabel').grid(row=0, column=0, sticky='w', padx=4, pady=4) # --- --- time ttk.Label(frame_font, style='subtitle.TLabel', text=_('Time')).grid(row=1, column=0, sticky='nw', padx=4, pady=8) self.timer_font_time = FontFrame(frame_font, CONFIG.get('Timer', 'font_time'), sample_text="02:17") self.timer_font_time.grid(row=1, column=1, padx=4, pady=4) ttk.Separator(frame_font, orient='horizontal').grid(row=2, columnspan=3, padx=10, pady=4, sticky='ew') # --- --- intervals ttk.Label(frame_font, style='subtitle.TLabel', text=_('Intervals')).grid(row=5, column=0, sticky='nw', padx=4, pady=8) self.timer_font_intervals = FontFrame(frame_font, CONFIG.get( 'Timer', 'font_intervals'), sample_text="02:17") self.timer_font_intervals.grid(row=5, column=1, padx=4, pady=4) # --- opacity self.timer_opacity = OpacityFrame( self.frames[_('Timer')], CONFIG.getfloat("Timer", "alpha", fallback=0.85)) # --- colors frame_color = ttk.Frame(self.frames[_('Timer')]) ttk.Label(frame_color, text=_('Colors'), style='title.TLabel').grid(row=0, column=0, sticky='w', padx=8, pady=4) self.timer_bg = ColorFrame(frame_color, CONFIG.get('Timer', 'background'), _('Background')) self.timer_bg.grid(row=0, column=1, sticky='e', padx=8, pady=4) self.timer_fg = ColorFrame(frame_color, CONFIG.get('Timer', 'foreground'), _('Foreground')) self.timer_fg.grid(row=0, column=2, sticky='e', padx=8, pady=4) # --- placement frame_font.grid(sticky='ew') ttk.Separator(self.frames[_('Timer')], orient='horizontal').grid(sticky='ew', pady=8) self.timer_opacity.grid(sticky='w', padx=4) ttk.Separator(self.frames[_('Timer')], orient='horizontal').grid(sticky='ew', pady=8) frame_color.grid(sticky='w')
def update_style(self): self.menu_tasks.delete(0, 'end') tasks = [t.capitalize() for t in CONFIG.options('PomodoroTasks')] tasks.sort() for task in tasks: self.menu_tasks.add_radiobutton(label=task, value=task, variable=self.task) if self.task.get() not in tasks: self.stop(False) self.task.set(tasks[0]) self.attributes('-alpha', CONFIG.get(self.name, 'alpha', fallback=0.85)) bg = CONFIG.get('Pomodoro', 'background') fg = CONFIG.get('Pomodoro', 'foreground') active_bg = active_color(*self.winfo_rgb(bg)) self.style.configure('pomodoro.TMenubutton', background=bg, relief='flat', foreground=fg, borderwidth=0, arrowcolor=fg) self.style.configure('pomodoro.TButton', background=bg, relief='flat', foreground=fg, borderwidth=0) self.style.configure('pomodoro.TLabel', background=bg, foreground=fg) self.style.configure('pomodoro.TFrame', background=bg) self.style.configure('pomodoro.TSizegrip', background=bg) self.style.map('pomodoro.TSizegrip', background=[('active', active_bg)]) self.style.map('pomodoro.TButton', background=[('disabled', bg), ('!disabled', 'active', active_bg)]) self.style.map('pomodoro.TMenubutton', background=[('disabled', bg), ('!disabled', 'active', active_bg)]) self.configure(bg=bg) self.menu.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg) self.menu_pos.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg) self.menu_tasks.configure(bg=bg, activebackground=active_bg, fg=fg, selectcolor=fg, activeforeground=fg) self.background = { _("Work"): CONFIG.get("Pomodoro", "work_bg"), _("Break"): CONFIG.get("Pomodoro", "break_bg"), _("Rest"): CONFIG.get("Pomodoro", "rest_bg") } self.foreground = { _("Work"): CONFIG.get("Pomodoro", "work_fg"), _("Break"): CONFIG.get("Pomodoro", "break_fg"), _("Rest"): CONFIG.get("Pomodoro", "rest_fg") } act = self.activite.get() self.style.configure('timer.pomodoro.TLabel', font=CONFIG.get("Pomodoro", "font"), foreground=self.foreground[act], background=self.background[act])