def create_content(self, **kw): self.rowconfigure(2, weight=1) self.columnconfigure(0, weight=1) self.minsize(50, 50) self.hide_completed = CONFIG.getboolean('Tasks', 'hide_completed') # --- elements label = Label(self, text=_('Tasks').upper(), style='title.Tasks.TLabel', anchor='center') label.grid(row=0, columnspan=2, pady=4, sticky='ew') Separator(self, style='Tasks.TSeparator').grid(row=1, columnspan=2, sticky='we') self.display = Text(self, width=20, height=10, relief='flat', cursor='arrow', wrap='word', highlightthickness=0, state='disabled', spacing1=5, tabs=('35', 'right', '45', 'left')) self.display.grid(sticky='nsew', row=2, column=0, padx=2, pady=2) scroll = AutoScrollbar(self, orient='vertical', style='Tasks.Vertical.TScrollbar', command=self.display.yview) scroll.grid(row=2, column=1, sticky='ns', pady=(2, 16)) self.display.configure(yscrollcommand=scroll.set) self.display_tasks() corner = Sizegrip(self, style="Tasks.TSizegrip") corner.place(relx=1, rely=1, anchor='se') # --- bindings self.bind('<3>', lambda e: self.menu.tk_popup(e.x_root, e.y_root)) label.bind('<ButtonPress-1>', self._start_move) label.bind('<ButtonRelease-1>', self._stop_move) label.bind('<B1-Motion>', self._move)
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 __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_position(self): if self._position.get() == 'normal': if CONFIG.getboolean('General', 'splash_supported', fallback=True): self.attributes('-type', 'splash') else: self.attributes('-type', 'toolbar') if self.variable.get(): self.withdraw() self.deiconify()
def show(self): ''' make widget sticky ''' self.deiconify() self.update_idletasks() splash_supp = CONFIG.getboolean('General', 'splash_supported', fallback=True) try: pos = self._position.get() for w in self.ewmh.getClientList(): if w.get_wm_name() == self.title(): if pos == 'above': self.attributes('-type', 'dock') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_ABOVE') self.ewmh.setWmState(w, 0, '_NET_WM_STATE_BELOW') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_STICKY') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_SKIP_TASKBAR') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_SKIP_PAGER') elif pos == 'below': self.attributes('-type', 'desktop') self.ewmh.setWmState(w, 0, '_NET_WM_STATE_ABOVE') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_BELOW') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_STICKY') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_SKIP_TASKBAR') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_SKIP_PAGER') else: if splash_supp: self.attributes('-type', 'splash') else: self.attributes('-type', 'toolbar') self.ewmh.setWmState(w, 0, '_NET_WM_STATE_BELOW') self.ewmh.setWmState(w, 0, '_NET_WM_STATE_ABOVE') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_STICKY') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_SKIP_TASKBAR') self.ewmh.setWmState(w, 1, '_NET_WM_STATE_SKIP_PAGER') self.ewmh.display.flush() if not splash_supp: self.withdraw() self.deiconify() CONFIG.set(self.name, 'visible', 'True') self.variable.set(True) save_config() except TypeError: pass
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_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 __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')))