Example #1
0
    def initialize(self):
        self.master.title("NENR DZ5 - Miljenko Šuflaj")
        self.pack(fill="both", expand=True)

        notebook = Notebook(self)
        notebook.pack()

        record_gestures_frame = Frame(self)
        classify_gestures_frame = Frame(self)

        notebook.add(record_gestures_frame, text="Zabilježi geste")
        notebook.add(classify_gestures_frame, text="Klasificiraj geste")

        notebook.enable_traversal()
        notebook.select(record_gestures_frame)

        gesture_classification_frame = Frame(classify_gestures_frame)
        gesture_record_frame_2 = Frame(classify_gestures_frame)

        gesture_classification_frame.pack(side="top", fill="x", expand=True)
        gesture_record_frame_2.pack(fill="both")

        # region Record gesture tab
        gesture_info_frame = Frame(record_gestures_frame)
        gesture_record_frame = Frame(record_gestures_frame)
        gesture_end_frame = Frame(record_gestures_frame)
        gesture_info_frame.pack(side="top", fill="x")
        gesture_record_frame.pack(fill="both")
        gesture_end_frame.pack(side="bottom", fill="x")

        gesture_name_menu = Menubutton(gesture_info_frame,
                                       text="Odaberi gestu za bilježenje...")
        gesture_name_menu.menu = Menu(gesture_name_menu, tearoff=0)
        gesture_name_menu["menu"] = gesture_name_menu.menu

        for i, label in enumerate(GestureWindow.labels):
            gesture_name_menu.menu.add_command(label=label,
                                               command=self.switch_record(i))

        self.__recorded_gesture_label = Label(gesture_info_frame)
        gesture_record_canvas = Canvas(gesture_record_frame,
                                       width=700,
                                       height=475,
                                       bg="white")
        gesture_record_canvas.current_coords = None
        gesture_record_canvas.records = list()
        gesture_record_save_button = Button(gesture_end_frame,
                                            text="Pohrani u .tsv",
                                            command=self.save_data)
        gesture_record_delete_button = Button(gesture_end_frame,
                                              text="Zaboravi učitane podatke",
                                              command=self.delete_internal)

        gesture_name_menu.pack(side="left",
                               fill="x",
                               padx=5,
                               pady=5,
                               expand=True)
        self.__recorded_gesture_label.pack(side="left",
                                           fill="x",
                                           padx=5,
                                           pady=5)
        gesture_record_canvas.pack(fill="both", padx=5, pady=5, expand=True)
        gesture_record_delete_button.pack(side="left",
                                          fill="x",
                                          padx=5,
                                          pady=5)
        gesture_record_save_button.pack(side="right", fill="x", padx=5, pady=5)

        self.switch_record(self.__recorded_gesture_index)()
        # endregion

        # region Classify gesture tab
        gesture_classification_frame = Frame(classify_gestures_frame)
        gesture_record_frame_2 = Frame(classify_gestures_frame)

        gesture_classification_frame.pack(side="top", fill="x", expand=True)
        gesture_record_frame_2.pack(fill="both")

        classification_labels = list()
        self.__classification_outputs = list()

        for category in GestureWindow.labels:
            classification_labels.append(
                Label(gesture_classification_frame, text=category))
            self.__classification_outputs.append(
                Label(gesture_classification_frame,
                      text=f"{0.:.01f}%",
                      font=("helvetica", 8)))
            classification_blank = Label(gesture_classification_frame)

            classification_labels[-1].pack(side="left",
                                           fill="x",
                                           padx=5,
                                           pady=5)
            self.__classification_outputs[-1].pack(side="left",
                                                   fill="x",
                                                   padx=5,
                                                   pady=5)
            classification_blank.pack(side="left", fill="x", padx=50, pady=5)

        gesture_record_canvas_2 = Canvas(gesture_record_frame_2,
                                         width=700,
                                         height=525,
                                         bg="white")
        gesture_record_canvas_2.current_coords = None
        gesture_record_canvas_2.records = list()

        gesture_record_canvas_2.pack(side="left",
                                     fill="both",
                                     padx=5,
                                     pady=5,
                                     expand=True)
        # endregion

        # region Functionality
        for record_canvas in [gesture_record_canvas, gesture_record_canvas_2]:
            draw_function = self.get_draw_on_canvas_function(record_canvas)

            record_canvas.bind("<B1-Motion>", draw_function)
            record_canvas.bind("<ButtonRelease-1>", draw_function)

        self.__root_window.bind(
            "<BackSpace>",
            self.get_delete_currently_drawn(gesture_record_canvas))
        self.__root_window.bind(
            "<Return>",
            self.get_record_gesture_function(gesture_record_canvas))

        gesture_record_canvas_2.bind(
            "<Leave>",
            self.get_evaluate_gesture_function(gesture_record_canvas_2))
        self.__root_window.bind(
            "<Delete>",
            self.get_delete_currently_drawn(gesture_record_canvas_2))
Example #2
0
    def __init__(self, master):
        """Create note manager to easily delete multiple notes."""
        Toplevel.__init__(self, master, class_='MyNotes')
        self.title(_("Note Manager"))
        self.minsize(width=546, height=200)
        self.grab_set()
        categories = CONFIG.options("Categories")
        categories.sort()

        self.im_del = PhotoImage(file=IM_DELETE, master=self)
        self.im_change = PhotoImage(file=IM_CHANGE, master=self)
        self.im_visible = PhotoImage(file=IM_VISIBLE_24, master=self)
        self.im_hidden = PhotoImage(file=IM_HIDDEN_24, master=self)

        tooltipwrapper = TooltipWrapper(self)

        self.notebook = Notebook(self)
        self.notebook.pack(fill='both', expand=True)

        self.texts = {}
        self.frames = {}
        self.notes = {}

        # to change notes category
        menu_cat = Menu(self, tearoff=False)
        self.category = StringVar(self)

        # create one tab per category
        for cat in categories:
            menu_cat.add_radiobutton(label=cat.capitalize(),
                                     value=cat,
                                     variable=self.category,
                                     command=self.change_cat_selection)
            self.notes[cat] = {}
            frame = Frame(self.notebook, padding=2)
            self.texts[cat] = Text(frame,
                                   width=1,
                                   height=1,
                                   bg=self.cget('bg'),
                                   relief='flat',
                                   highlightthickness=0,
                                   padx=0,
                                   pady=0,
                                   cursor='arrow')
            frame.columnconfigure(0, weight=1)
            frame.rowconfigure(1, weight=1)

            self.texts[cat].grid(row=1, column=0, sticky='ewsn')
            scrolly = Scrollbar(frame,
                                orient='vertical',
                                command=self.texts[cat].yview)
            scrolly.grid(row=1, column=1, sticky='ns', pady=(2, 0))
            scrollx = Scrollbar(frame,
                                orient='horizontal',
                                command=self.texts[cat].xview)
            scrollx.grid(row=2, column=0, sticky='ew')
            self.texts[cat].configure(xscrollcommand=scrollx.set,
                                      yscrollcommand=scrolly.set)
            self.frames[cat] = Frame(self.texts[cat],
                                     style='bg.TFrame',
                                     padding=1,
                                     height=29,
                                     width=523)
            self.frames[cat].columnconfigure(0, weight=1, minsize=170)
            headings = Frame(frame, padding=(1, 0, 1, 0))
            headings.columnconfigure(0, weight=0, minsize=20)
            headings.columnconfigure(1, weight=1, minsize=198)
            headings.columnconfigure(2, weight=1, minsize=198)
            headings.columnconfigure(3, weight=0, minsize=84)
            headings.columnconfigure(4, weight=0, minsize=22)
            Heading(headings,
                    cat,
                    'title',
                    command=self.sort_column,
                    text=_('Title')).grid(row=0, column=1, sticky='ew')
            Heading(headings,
                    cat,
                    'text',
                    command=self.sort_column,
                    text=_('Text')).grid(row=0, column=2, sticky='ew')
            Heading(headings,
                    cat,
                    'date',
                    command=self.sort_column,
                    text=_('Date')).grid(row=0, column=3, sticky='ew')
            Heading(headings,
                    cat,
                    'select_all',
                    style='select.heading.TLabel',
                    padding=0,
                    command=self.toggle_selectall).place(x=0,
                                                         y=0,
                                                         anchor='nw',
                                                         relheight=1,
                                                         width=20)
            Heading(headings, cat, 'visibility',
                    command=self.sort_column).place(relx=1,
                                                    y=0,
                                                    anchor='ne',
                                                    bordermode='outside',
                                                    width=23,
                                                    relheight=1)
            headings.place(x=0, y=2, anchor='nw')
            self.update_idletasks()
            frame.rowconfigure(0, minsize=headings.winfo_reqheight())
            self.texts[cat].window_create('1.0', window=self.frames[cat])
            b_frame = Frame(frame)
            b_frame.grid(row=3, columnspan=2)
            m = Menubutton(b_frame,
                           image=self.im_change,
                           text=_('Change category'),
                           compound='right',
                           menu=menu_cat,
                           padding=1)
            m.pack(side='left', padx=4, pady=4, fill='y')
            tooltipwrapper.add_tooltip(m,
                                       _('Change category of selected notes'))
            b_show = Button(b_frame,
                            image=self.im_visible,
                            padding=1,
                            command=self.show_selection)
            b_show.pack(side='left', padx=4, pady=4)
            tooltipwrapper.add_tooltip(b_show, _('Show selected notes'))
            b_hide = Button(b_frame,
                            image=self.im_hidden,
                            padding=1,
                            command=self.hide_selection)
            b_hide.pack(side='left', padx=4, pady=4)
            tooltipwrapper.add_tooltip(b_hide, _('Hide selected notes'))
            b_del = Button(b_frame,
                           image=self.im_del,
                           command=self.del_selection,
                           padding=1)
            b_del.pack(side='left', padx=4, pady=4, fill='y')
            tooltipwrapper.add_tooltip(b_del, _('Delete selected notes'))

            self.notebook.add(frame,
                              text=cat.capitalize(),
                              sticky="ewsn",
                              padding=0)
        # display notes by category
        for key, note_data in self.master.note_data.items():
            self.display_note(key, note_data)

        for txt in self.texts.values():
            txt.configure(state='disabled')
        self.geometry('410x450')
        self.bind("<Button-4>", lambda e: self.scroll(-1))
        self.bind("<Button-5>", lambda e: self.scroll(1))
        self.notebook.bind('<<NotebookTabChanged>>', self.on_change_tab)
Example #3
0
class Timer(Tk):
    """ Chronométre de temps de travail pour plus d'efficacité """
    def __init__(self):
        Tk.__init__(self, className="WorkHourGlass")
        self.on = False  # is the timer on?

        if not CONFIG.options("Tasks"):
            CONFIG.set("Tasks", _("Work"), CMAP[0])
        # colors
        self.background = {
            _("Work"): CONFIG.get("Work", "bg"),
            _("Break"): CONFIG.get("Break", "bg"),
            _("Rest"): CONFIG.get("Rest", "bg")
        }
        self.foreground = {
            _("Work"): CONFIG.get("Work", "fg"),
            _("Break"): CONFIG.get("Break", "fg"),
            _("Rest"): CONFIG.get("Rest", "fg")
        }
        # window configuration
        if PL[0] == "w":
            self.iconbitmap(ICON_WIN, default=ICON_WIN)
        else:
            self.icon = PhotoImage(master=self, file=ICON)
            self.iconphoto(True, self.icon)

        self.title("WorkHourGlass")
        self.protocol("WM_DELETE_WINDOW", self.exit)
        self.rowconfigure(1, weight=1)
        self.columnconfigure(0, weight=1)
        self.columnconfigure(1, weight=1)
        self.minsize(181, 190)
        self.geometry("200x190+%i+%i" %
                      ((self.winfo_screenwidth() - 200) // 2,
                       (self.winfo_screenheight() - 190) // 2))
        self.configure(background=self.background[_("Work")])

        # style
        self.style = Style(self)
        self.style.theme_use(STYLE)
        self.style.configure('fen.TLabel',
                             foreground=self.foreground[_("Work")],
                             background=self.background[_("Work")])

        # 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=GO)
        self.im_stop = PhotoImage(master=self, file=STOP)
        self.im_plus = PhotoImage(master=self, file=PLUS)
        self.im_moins = PhotoImage(master=self, file=MOINS)
        self.im_params = PhotoImage(master=self, file=PARAMS)
        self.im_tomate = PhotoImage(master=self, file=TOMATE)
        self.im_graph = PhotoImage(master=self, file=GRAPH)

        # tasks list
        tasks_frame = Frame(self)
        tasks_frame.grid(row=3, column=0, columnspan=3, sticky="wnse")
        tasks = [t.capitalize() for t in CONFIG.options("Tasks")]
        self.task = StringVar(self, tasks[0])
        self.menu_tasks = Menu(tasks_frame, tearoff=False)
        for task in tasks:
            self.menu_tasks.add_radiobutton(label=task,
                                            value=task,
                                            variable=self.task)
        self.menu_tasks.add_command(label=_("New task"),
                                    image=self.im_plus,
                                    compound="left",
                                    command=self.add_task)
        self.menu_tasks.add_command(label=_("Remove task"),
                                    image=self.im_moins,
                                    compound="left",
                                    command=self.del_task)
        self.menu_tasks.add_command(label=_("Statistics"),
                                    image=self.im_graph,
                                    compound="left",
                                    command=self.display_stats)
        self.choose_task = Menubutton(tasks_frame,
                                      textvariable=self.task,
                                      menu=self.menu_tasks)
        Label(tasks_frame,
              text=_("Task: "),
              font="CMU\ Sans\ Serif\ Demi\ Condensed 12",
              width=6,
              anchor="e").pack(side="left")
        self.choose_task.pack(side="right", fill="x")

        # display
        self.tps = [CONFIG.getint("Work", "time"), 0]  # time: min, sec
        self.activite = StringVar(self, _("Work"))
        self.titre = Label(self,
                           textvariable=self.activite,
                           font='CMU\ Sans\ Serif\ Demi\ Condensed 14',
                           style='fen.TLabel',
                           anchor="center")
        self.titre.grid(row=0, column=0, columnspan=2, sticky="we")
        self.temps = Label(
            self,
            text="{0:02}:{1:02}".format(self.tps[0], self.tps[1]),
            font="%s %i" % (CONFIG.get(
                "General", "font"), CONFIG.getint("General", "fontsize")),
            style='fen.TLabel',
            anchor="center")
        self.temps.grid(row=1,
                        column=0,
                        columnspan=2,
                        sticky="nswe",
                        pady=(0, 10))

        self.aff_pomodori = Label(self,
                                  textvariable=self.pomodori,
                                  image=self.im_tomate,
                                  compound="left",
                                  style='fen.TLabel',
                                  font='CMU\ Sans\ Serif\ Demi\ Condensed 14')
        self.aff_pomodori.grid(row=2, columnspan=2, sticky="e", padx=20)

        # buttons
        self.b_go = Button(self, image=self.im_go, command=self.go)
        self.b_go.grid(row=4, column=0, sticky="ew")
        self.b_params = Button(self, image=self.im_params, command=self.params)
        self.b_params.grid(row=4, column=1, sticky="ew")

        # --- make window sticky
        self.update_idletasks()
        e = EWMH()
        try:
            for w in e.getClientList():
                if w.get_wm_name() == self.title():
                    e.setWmState(w, 1, '_NET_WM_STATE_STICKY')
            e.display.flush()
        except ewmh.display.error.BadWindow:
            pass

    def set_config(self):
        self.background = {
            _("Work"): CONFIG.get("Work", "bg"),
            _("Break"): CONFIG.get("Break", "bg"),
            _("Rest"): CONFIG.get("Rest", "bg")
        }
        self.foreground = {
            _("Work"): CONFIG.get("Work", "fg"),
            _("Break"): CONFIG.get("Break", "fg"),
            _("Rest"): CONFIG.get("Rest", "fg")
        }
        act = self.activite.get()
        self.configure(background=self.background[act])
        self.style.configure('fen.TLabel',
                             foreground=self.foreground[act],
                             background=self.background[act])
        self.temps.configure(font="%s %i" %
                             (CONFIG.get("General", "font"),
                              CONFIG.getint("General", "fontsize")))

    def add_task(self):
        def ajoute(event=None):
            task = nom.get()
            if task and not CONFIG.has_option("Tasks", task):
                index = len(CONFIG.options("Tasks"))
                self.menu_tasks.insert_radiobutton(index,
                                                   label=task,
                                                   value=task,
                                                   variable=self.task)
                CONFIG.set("Tasks", task, CMAP[index % len(CMAP)])
                top.destroy()
                with open(PATH_CONFIG, "w") as file:
                    CONFIG.write(file)
                self.menu_tasks.invoke(index)
            else:
                nom.delete(0, "end")

        top = Toplevel(self)
        top.title(_("New task"))
        top.transient(self)
        top.grab_set()
        nom = Entry(top, width=20)
        nom.grid(row=0, columnspan=2, sticky="ew")
        nom.focus_set()
        nom.bind('<Key-Return>', ajoute)
        Button(top, text=_("Cancel"), command=top.destroy).grid(row=1,
                                                                column=0)
        Button(top, text=_("Ok"), command=ajoute).grid(row=1, column=1)
        top.wait_window(top)

    def del_task(self):
        """ Suppression de tâches """
        def supprime():
            rep = askyesno(_("Confirmation"),
                           _("Are you sure you want to delete these tasks?"))
            if rep:
                for i in range(len(boutons) - 1, -1, -1):
                    # l'ordre de parcours permet de supprimer les derniers
                    # éléments en premier afin de ne pas modifier les index des
                    # autres éléments lors des suppressions
                    task = tasks[i]
                    if "selected" in boutons[i].state():
                        # suppression de la tâche de la liste des tâches
                        CONFIG.remove_option("Tasks", task)
                        tasks.remove(task)
                        # suppression de l'entrée correspondante dans le menu
                        self.menu_tasks.delete(i)
                        if not tasks:
                            CONFIG.set("Tasks", _("Work"), CMAP[0])
                            tasks.append(_("Work"))
                            self.menu_tasks.insert_radiobutton(
                                0,
                                label=_("Work"),
                                value=_("Work"),
                                variable=self.task)
                        if self.task.get() == task:
                            self.task.set(tasks[0])
                        # suppression des stats associées
                        chemin = PATH_STATS + "_" + "_".join(task.split(" "))
                        if os.path.exists(chemin):
                            os.remove(chemin)

                top.destroy()
                with open(PATH_CONFIG, "w") as file:
                    CONFIG.write(file)
            else:
                top.destroy()

        tasks = [t.capitalize() for t in CONFIG.options("Tasks")]
        top = Toplevel(self)
        top.title(_("Remove task"))
        top.transient(self)
        top.grab_set()
        style = Style(top)
        style.theme_use(STYLE)
        boutons = []
        for i, task in enumerate(tasks):
            boutons.append(Checkbutton(top, text=task))
            boutons[-1].grid(row=i, columnspan=2, sticky="w")
        Button(top, text=_("Cancel"), command=top.destroy).grid(row=i + 1,
                                                                column=0)
        Button(top, text=_("Delete"), command=supprime).grid(row=i + 1,
                                                             column=1)

    def stats(self):
        """ Enregistre la durée de travail (en min) effectuée ce jour pour la
            tâche qui vient d'être interrompue.
            Seul les pomodori complets sont pris en compte. """
        # TODO: translate, correct date/time format
        pom = self.pomodori.get()
        if pom:
            # la tâche en cours a été travaillée, il faut enregistrer les stats
            date = dt.date.today()
            task = self.task.get()
            chemin = PATH_STATS + "_" + "_".join(task.split(" "))
            if not os.path.exists(chemin):
                with open(chemin, 'w') as fich:
                    fich.write(
                        "# tâche : %s\n# jour\tmois\tannée\ttemps de travail (min)\n"
                        % task)
            with open(chemin, 'r') as fich:
                stats = fich.readlines()
            if len(stats) > 2:
                last = stats[-1][:10], stats[-1][:-1].split("\t")[-1]
            else:
                last = "", 0
            if last[0] != date.strftime("%d\t%m\t%Y"):
                with open(chemin, 'a') as fich:
                    fich.write("%s\t%i\n" % (date.strftime("%d\t%m\t%Y"), pom *
                                             CONFIG.getint("Work", "time")))
            else:
                # un nombre a déjà été enregistré plus tôt dans la journée
                # il faut les additioner
                with open(chemin, 'w') as fich:
                    fich.writelines(stats[:-1])
                    fich.write(
                        "%s\t%i\n" %
                        (date.strftime("%d\t%m\t%Y"),
                         pom * CONFIG.getint("Work", "time") + int(last[1])))

    def display_stats(self):
        """ affiche les statistiques """
        plt.figure("Statistiques")
        tasks = [t.capitalize() for t in CONFIG.options("Tasks")]
        coul = [CONFIG.get("Tasks", 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
        for i, task in enumerate(tasks):
            chemin = PATH_STATS + "_" + "_".join(task.split(" "))
            if os.path.exists(chemin):
                no_data = False
                stat = loadtxt(chemin, dtype=int)
                if len(stat.shape) == 1:
                    stat = stat.reshape(1, 4)
                x = [
                    dt.date(an, mois, jour).toordinal()
                    for jour, mois, an in stat[:, :3]
                ]
                y = stat[:, -1] / 60  # temps de travail
                min_x = min(x[0], min_x)
                stats_x.append(x)
                stats_y.append(y)
            else:
                # la taĉhe n'a jamais été travaillée
                stats_x.append([demain - 1])
                stats_y.append(array([0]))

        # plots
        xx = arange(min_x, demain, dtype=float)
        yy0 = zeros_like(xx)  # pour empiler les stats
        if not no_data:
            for (i, task), x, y in zip(enumerate(tasks), stats_x, stats_y):
                ax0 = plt.subplot(111)
                plt.ylabel(_("time (h)"))
                plt.xlabel(_("date"))
                yy = 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 = arange(min_x, x[0])
                yy = concatenate((yy, zeros_like(xxx, dtype=int)))
                for j in range(len(x) - 1):
                    xxx = arange(x[j], x[j + 1])
                    yy = concatenate((yy, [y[j]], zeros(len(xxx) - 1,
                                                        dtype=int)))
                xxx = arange(x[-1], demain)
                yy = concatenate((yy, [y[-1]], zeros(len(xxx) - 1, dtype=int)))
                plt.bar(xx - 0.4,
                        yy,
                        bottom=yy0,
                        width=0.8,
                        label=task,
                        color=coul[i])
                yy0 += yy
            axx = array(
                [int(xt) for xt in ax0.get_xticks() if xt.is_integer()])
            ax0.set_xticks(axx)
            ax0.set_xticklabels(
                [dt.date.fromordinal(i).strftime("%x") for i in axx])
            plt.gcf().autofmt_xdate()
            ax0.set_xlim(min_x - 0.5, demain - 0.5)
            lgd = plt.legend(fontsize=10)
            lgd.draggable()
            plt.subplots_adjust(top=0.95)
            max_y = yy0.max()
            ax0.set_ylim(0, max_y + 0.1 * max_y)
        plt.show()

    def go(self):
        if self.on:
            self.on = False
            if self.activite.get() == _("Work"):
                #                rep = askyesno(title=_("Confirmation"),
                #                               message=_("You should not interrupt your work if you want to be efficient. Do you still want to suspend the timer?"),
                #                               icon="warning")
                #            else:
                #                rep = True
                self.stop()
#            if rep:
#                self.b_go.configure(image=self.im_go)
#            else:
#                self.on = True
#                self.affiche()
        else:
            self.on = True
            self.choose_task.config(state="disabled")
            self.b_go.configure(image=self.im_stop)
            self.after(1000, self.affiche)

    def stop(self, confirmation=True):
        """ Arrête le décompte du temps et le réinitialise,
            demande une confirmation avant de le faire si confirmation=True """
        self.on = False
        if confirmation:
            rep = askyesno(
                title=_("Confirmation"),
                message=_(
                    "Are you sure you want to give up the current session?"))
        else:
            rep = True
        if rep:
            self.stats()
            self.pomodori.set(0)
            self.nb_cycles = 0
            self.b_go.configure(image=self.im_go)
            self.tps = [CONFIG.getint("Work", "time"), 0]
            self.temps.configure(
                text="{0:02}:{1:02}".format(self.tps[0], self.tps[1]))
            act = _("Work")
            self.activite.set(act)
            self.style.configure('fen.TLabel',
                                 background=self.background[act],
                                 foreground=self.foreground[act])
            self.configure(background=self.background[act])
            self.choose_task.config(state="normal")
        else:
            self.on = True
            self.affiche()

    def ting(self):
        """ joue le son marquant le changement de période """
        if not CONFIG.getboolean("Sound", "mute", fallback=False):
            if PL[0] == "w":
                Popen([
                    "powershell", "-c",
                    '(New-Object Media.SoundPlayer "%s").PlaySync();' %
                    (CONFIG.get("Sound", "beep"))
                ])
            else:
                Popen([
                    CONFIG.get("Sound", "player"),
                    CONFIG.get("Sound", "beep")
                ])

    def affiche(self):
        if self.on:
            self.tps[1] -= 1
            if self.tps[1] == 0:
                if self.tps[0] == 0:
                    self.ting()
                    if self.activite.get() == _("Work"):
                        self.pomodori.set(self.pomodori.get() + 1)
                        self.nb_cycles += 1
                        if self.nb_cycles % 4 == 0:
                            # pause longue
                            self.activite.set(_("Rest"))
                            self.tps = [CONFIG.getint("Rest", "time"), 0]
                        else:
                            # pause courte
                            self.activite.set(_("Break"))
                            self.tps = [CONFIG.getint("Break", "time"), 0]
                    else:
                        self.activite.set(_("Work"))
                        self.tps = [CONFIG.getint("Work", "time"), 0]
                    act = self.activite.get()
                    self.style.configure('fen.TLabel',
                                         background=self.background[act],
                                         foreground=self.foreground[act])
                    self.configure(background=self.background[act])
            elif self.tps[1] == -1:
                self.tps[0] -= 1
                self.tps[1] = 59
            self.temps.configure(
                text="{0:02}:{1:02}".format(self.tps[0], self.tps[1]))
            self.after(1000, self.affiche)

    def params(self):
        on = self.on
        self.on = False
        self.b_go.configure(image=self.im_go)
        p = Params(self)
        self.wait_window(p)
        if on:
            self.on = True
            self.choose_task.config(state="disabled")
            self.b_go.configure(image=self.im_stop)
            self.after(1000, self.affiche)

    def exit(self):
        self.stats()
        plt.close()
        self.destroy()
Example #4
0
    def __init__(self, parent, **options):
        """ créer le Toplevel permettant de modifier les paramètres """
        Toplevel.__init__(self, parent, **options)
        self.grab_set()
        self.transient(parent)
        self.title(_("Settings"))
        self.resizable(0, 0)

        self.onglets = Notebook(self)
        self.onglets.grid(row=0,column=0,columnspan=2)
        self.im_color = PhotoImage(master=self, file=COLOR)

        self.style = Style(self)
        self.style.theme_use(STYLE)
        self.style.configure('title.TLabel', font='CMU\ Sans\ Serif\ Demi\ Condensed 12')

        self.okfct = self.register(valide_entree_nb)

        self.nb_task = len(CONFIG.options("Tasks"))

        # Général (temps, police et langue)
        self.general = Frame(self.onglets, padding=10)
        self.general.pack(fill="both", expand=True, padx=10, pady=10)
        self.onglets.add(self.general, text=_("General"))

        # Temps
        Label(self.general, text=_("Times:"),
              style='title.TLabel').grid(row=0, pady=4, sticky="w")
        self.time_frame = Frame(self.general)
        self.time_frame.grid(row=1, sticky="ew")
        Label(self.time_frame, text=_("Work: ")).grid(row=0, column=0)
        self.travail = Entry(self.time_frame, width=4, justify='center',
                             validatecommand=(self.okfct, '%d', '%S'),
                             validate='key')
        self.travail.insert(0, CONFIG.get("Work", "time"))
        self.travail.grid(row=0, column=1, padx=(0,10))
        Label(self.time_frame, text=_("Break: ")).grid(row=0, column=2)
        self.pause = Entry(self.time_frame, width=4, justify='center',
                           validatecommand=(self.okfct, '%d', '%S'),
                           validate='key')
        self.pause.insert(0, CONFIG.get("Break", "time"))
        self.pause.grid(row=0, column=3, padx=(0,10))
        Label(self.time_frame, text=_("Rest: ")).grid(row=0, column=4)
        self.rest = Entry(self.time_frame, width=4, justify='center',
                          validatecommand=(self.okfct, '%d', '%S'),
                          validate='key')
        self.rest.insert(0, CONFIG.get("Rest", "time"))
        self.rest.grid(row=0, column=5)

        Separator(self.general,
                  orient='horizontal').grid(row=2, sticky="ew", pady=10)

              # Police
        self.font_frame = Frame(self.general)
        self.font_frame.grid(row=3, pady=4, sticky="ew")
        Label(self.font_frame, text=_("Font:"),
              style='title.TLabel').pack(anchor="n", side="left")
        self.exemple = Label(self.font_frame, text="02:17", anchor="center",
                             font="%s %i" % (CONFIG.get("General", "font"), CONFIG.getint("General", "fontsize")),
                             relief="groove")
        self.exemple.pack(side="right")
        self.font_frame2 = Frame(self.general)
        self.font_frame2.grid(row=4)
        Label(self.font_frame2, text=_("Family: ")).grid(row=0, column=0, sticky="e")
        self.font = Entry(self.font_frame2, justify='center')
        self.font.insert(0, CONFIG.get("General", "font"))
        self.font.grid(row=0, column=1, padx=(0,10), sticky="ew")
        self.font.bind('<FocusOut>', self.actualise_police)
        self.font.bind('<Key-Return>', self.actualise_police, True)
        Label(self.font_frame2, text=_("Size: ")).grid(row=0, column=2, sticky="e")
        self.size = Entry(self.font_frame2, width=4, justify='center',
                          validatecommand=(self.okfct, '%d', '%S'),
                          validate='key')
        self.size.insert(0, CONFIG.getint("General", "fontsize"))
        self.size.grid(row=0, column=3, pady=2, sticky="w")
        self.size.bind('<FocusOut>', self.actualise_police)
        self.size.bind('<Key-Return>', self.actualise_police, True)

        Separator(self.general,
                  orient='horizontal').grid(row=5, sticky="ew", pady=10)

            # Langues
        self.lang_frame = Frame(self.general)
        self.lang_frame.grid(row=6, pady=4, sticky="ew")
        Label(self.lang_frame, text=_("Language:"),
              style='title.TLabel').pack(side="left")
        self.lang = StringVar(self.lang_frame, LANGUES[CONFIG.get("General", "language")])
        b_lang = Menubutton(self.lang_frame, textvariable=self.lang)
        menu = Menu(b_lang, tearoff=False)
        menu.add_radiobutton(label="English", variable=self.lang,
                             value="English", command=self.change_langue)
        menu.add_radiobutton(label="Français", variable=self.lang,
                             value="Français", command=self.change_langue)
        b_lang.configure(menu=menu)
        b_lang.pack(side="right")

        # Son
        self.im_son = PhotoImage(master=self, file=SON)
        self.im_mute = PhotoImage(master=self, file=MUTE)

        self.son = Frame(self.onglets, padding=10)
        self.son.pack(fill="both", expand=True, padx=10, pady=10)
        self.son.columnconfigure(1, weight=1)
        self.onglets.add(self.son, text=_("Sound"))

        Label(self.son, text=_("Sound:"),
              style='title.TLabel').grid(row=0, pady=4, sticky="w")
        self.mute = BooleanVar(self)
        self.mute.set(not CONFIG.get("Sound", "mute"))

        def mute_unmute():
            if self.mute.get():
                self.mute.set(False)
                b_son.configure(image=self.im_son)
            else:
                self.mute.set(True)
                b_son.configure(image=self.im_mute)

        b_son = Button(self.son, command=mute_unmute)
        mute_unmute()
        b_son.grid(row=0, column=1, sticky="e", pady=4)
        self.son_frame = Frame(self.son)
        self.son_frame.grid(row=1, sticky="ew", columnspan=2)
        self.bip = Entry(self.son_frame, justify='center')
        self.bip.insert(0, CONFIG.get("Sound", "beep"))
        self.bip.pack(side="left", fill="both", expand=True)
        Button(self.son_frame, text="...", width=2,
               command=self.choix_son).pack(side="right", padx=(2,0))

        if PL[0] != "w":
            Separator(self.son, orient='horizontal').grid(row=2, columnspan=2,
                                                          sticky="ew", pady=10)
            son_frame2 = Frame(self.son)
            son_frame2.grid(row=3, sticky="ew", columnspan=2)
            Label(son_frame2, text=_("Audio player: "),
                  style='title.TLabel').pack(side="left")
            self.player = Entry(son_frame2, justify='center')
            self.player.insert(0, CONFIG.get("Sound", "player"))
            self.player.pack(side="right", fill="both", expand=True)


        # Couleurs
        self.couleurs = Frame(self.onglets, padding=10)
        self.couleurs.pack(fill="both", expand=True, padx=10, pady=10)
        self.onglets.add(self.couleurs, text=_("Colors"))

        # style des boutons de choix des couleurs
        self.style.configure("fond_w.TButton", background=CONFIG.get("Work", "bg"))
        self.style.configure("fond_p.TButton", background=CONFIG.get("Break", "bg"))
        self.style.configure("fond_r.TButton", background=CONFIG.get("Rest", "bg"))
        self.style.configure("texte_w.TButton", background=CONFIG.get("Work", "fg"))
        self.style.configure("texte_p.TButton", background=CONFIG.get("Break", "fg"))
        self.style.configure("texte_r.TButton", background=CONFIG.get("Rest", "fg"))
        self.couleurs.grid_columnconfigure(3, weight=3)
        self.couleurs.grid_rowconfigure(0, weight=1)
        Label(self.couleurs, text=_("Work: "),
              style='title.TLabel').grid(row=0, column=0, pady=4,
                                         padx=(2,10), sticky="w")
        Label(self.couleurs, text=_("Background: ")).grid(row=0, column=1,
                                                          sticky="e", pady=(6,4))
        Button(self.couleurs, width=2, command=lambda: self.choix_couleur("fond_w"),
               style='fond_w.TButton').grid(row=0, column=2, pady=4)
        Label(self.couleurs, text=_("Text: ")).grid(row=1, column=1, sticky="e")
        Button(self.couleurs, width=2, command=lambda: self.choix_couleur("texte_w"),
               style='texte_w.TButton').grid(row=1, column=2, pady=4)

        Separator(self.couleurs, orient='horizontal').grid(row=2, sticky="ew",
                                                           pady=10, columnspan=4)

        Label(self.couleurs, text=_("Break: "),
              style='title.TLabel').grid(row=3, column=0, pady=4,
                                         padx=(2,10), sticky="w")
        Label(self.couleurs, text=_("Background: ")).grid(row=3, column=1,
                                                          sticky="e", pady=(6,4))
        Button(self.couleurs, width=2, command=lambda: self.choix_couleur("fond_p"),
               style='fond_p.TButton').grid(row=3, column=2, pady=4)
        Label(self.couleurs, text=_("Text: ")).grid(row=4, column=1, sticky="e")
        Button(self.couleurs, width=2, command=lambda: self.choix_couleur("texte_p"),
               style='texte_p.TButton').grid(row=4, column=2, 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,
                                         sticky="w", padx=(2,10))
        Label(self.couleurs, text=_("Background: ")).grid(row=6, column=1,
                                                          sticky="e", pady=(6,4))
        Button(self.couleurs, width=2, command=lambda: self.choix_couleur("fond_r"),
               style='fond_r.TButton').grid(row=6, column=2, pady=4)
        Label(self.couleurs, text=_("Text: ")).grid(row=7, column=1, sticky="e")
        Button(self.couleurs, width=2, command=lambda: self.choix_couleur("texte_r"),
               style='texte_r.TButton').grid(row=7, column=2, pady=4)

        # Stats
        self.stats = Frame(self.onglets, padding=10)
        self.stats.pack(fill="both", expand=True, padx=10, pady=10)
        self.stats.grid_columnconfigure(2, weight=1)
        self.onglets.add(self.stats, text=_("Statistics"))

        Label(self.stats, text=_("Statistics:"),
              style='title.TLabel').grid(row=0, column=0, pady=4, sticky="w")

        tasks = [t.capitalize() for t in CONFIG.options("Tasks")]
        cmap = [CONFIG.get("Tasks", task) for task in tasks]
        for i, coul, task in zip(range(self.nb_task), cmap , tasks):
            Label(self.stats, text=task).grid(row=i + 1, column=0, sticky="e",
                                              padx=4, pady=4)
            self.style.configure("t%i.TButton" % i, background=coul)
            Button(self.stats, style="t%i.TButton" % i, width=2,
                   command=lambda j=i: self.coul_stat(j)).grid(row=i + 1,
                                                               column=1, pady=4)

        # Validation
        Button(self, text="Ok", command=self.valide).grid(row=1,column=1, sticky="we")
        Button(self, text=_("Cancel"), command=self.destroy).grid(row=1,column=0, sticky="we")
Example #5
0
    def __init__(self, master, note_data):
        """Create export dialog."""
        Toplevel.__init__(self, master, class_='MyNotes')
        self.title(_("Export"))
        self.minsize(350, 250)
        self.grab_set()
        self.columnconfigure(0, weight=1)
        self.rowconfigure(3, weight=1)

        self.note_data = note_data
        self.categories = CONFIG.options("Categories")
        self.categories.sort()
        self.notes_to_export = []
        self.export_type = None
        self.export_data = False

        # export type
        self.type = StringVar(self, _("Notes (.notes)"))

        type_frame = Frame(self)
        menu_type = Menu(self, tearoff=False)
        for etype in EXT_DICT:
            menu_type.add_radiobutton(label=etype, value=etype, variable=self.type)
        mb = Menubutton(type_frame, menu=menu_type, textvariable=self.type, width=max([int(len(key) * 0.8) for key in EXT_DICT]))
        Label(type_frame, text=_('Export to')).pack(side='left', padx=4)
        mb.pack(side='left', padx=4)
        type_frame.grid(row=0, columnspan=2, sticky='w', pady=4)

        Separator(self).grid(columnspan=2, sticky="ew", padx=4, pady=4)

        # export only visible notes checkbutton
        self.ch_only_visible = Checkbutton(self, text=_("Only visible notes"),
                                           command=self.select_only_visible)
        self.ch_only_visible.grid(columnspan=2, sticky="w", padx=4, pady=4)

        # note selection
        self.tree = CheckboxTreeview(self, show='tree')
        self.tree.grid(row=3, sticky="nsew", padx=4, pady=4)
        scroll = Scrollbar(self, orient='vertical', command=self.tree.yview)
        self.tree.configure(yscrollcommand=scroll.set)
        scroll.grid(row=3, column=1, sticky='ns')

        self.tree.insert('', 'end', 'root', text=_('Categories'))
        for cat in self.categories:
            self.tree.insert('root', 'end', cat, text=cat.capitalize())
        for key, data in self.note_data.items():
            self.tree.insert(data['category'], 'end', key,
                             text='{} - {}'.format(data['title'], data.get('date', '??')),
                             tags=['visible'] if data['visible'] else [])
        for cat in self.categories:
            if not self.tree.get_children(cat):
                self.tree.detach(cat)
        self.tree.bind('<<Checked>>', self.toggle_select_visible)
        self.tree.bind('<<Unchecked>>', self.toggle_select_visible)

        Separator(self).grid(sticky="ew", columnspan=2, padx=4, pady=4)
        self.ch_export_data = Checkbutton(self, text=_('Export data (pictures and linked files)'))
        self.ch_export_data.grid(sticky="w", columnspan=2, padx=4, pady=4)

        frame = Frame(self)
        frame.grid(columnspan=2)

        Button(frame, text="Ok",
               command=self.ok).grid(row=0, column=0, sticky="w", padx=4, pady=4)
        Button(frame, text=_("Cancel"),
               command=self.destroy).grid(row=0, column=1, sticky="e", padx=4, pady=4)
        self.tree.check_item('root')
        self.tree.expand_all()
        self.toggle_select_visible()
Example #6
0
class Pomodoro(BaseWidget):
    """ Chronometre de temps de travail pour plus d'efficacité """
    def __init__(self, master):
        BaseWidget.__init__(self, 'Pomodoro', master)

    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 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])

    def _on_enter(self, event=None):
        self._corner.state(('active', ))

    def _on_leave(self, event=None):
        self._corner.state(('!active', ))

    def _start_move(self, event):
        self.x = event.x
        self.y = event.y

    def _stop_move(self, event):
        self.x = None
        self.y = None
        self.configure(cursor='arrow')

    def _move(self, event):
        if self.x is not None and self.y is not None:
            self.configure(cursor='fleur')
            deltax = event.x - self.x
            deltay = event.y - self.y
            x = self.winfo_x() + deltax
            y = self.winfo_y() + deltay
            self.geometry("+%s+%s" % (x, y))

    def hide(self):
        if self._stats is not None:
            self._stats.destroy()
        BaseWidget.hide(self)

    def stats(self, time=None):
        """Save stats."""
        if time is None:
            time = CONFIG.getint("Pomodoro", "work_time")
        today = dt.date.today().toordinal()
        task = self.task.get().lower().replace(' ', '_')
        db = sqlite3.connect(PATH_STATS)
        cursor = db.cursor()
        try:
            cursor.execute('SELECT * FROM {} ORDER BY id DESC LIMIT 1'.format(
                scrub(task)))
            key, date, work = cursor.fetchone()
        except sqlite3.OperationalError:
            cursor.execute('''CREATE TABLE {} (id INTEGER PRIMARY KEY,
                                               date INTEGER,
                                               work INTEGER)'''.format(
                scrub(task)))
            cursor.execute(
                'INSERT INTO {}(date, work) VALUES (?, ?)'.format(scrub(task)),
                (today, time))
        else:
            if today != date:
                cursor.execute(
                    'INSERT INTO {}(date, work) VALUES (?, ?)'.format(
                        scrub(task)), (today, time))
            else:  # update day's value
                cursor.execute(
                    'UPDATE {} SET work=? WHERE id=?'.format(scrub(task)),
                    (work + time, key))
        finally:
            db.commit()
            db.close()

    def display_stats(self):
        """ affiche les statistiques """
        if self._stats is None:
            self._stats = Stats(self)
            self._stats.bind('<Destroy>', self._on_close_stats)
        else:
            self._stats.lift()

    def _on_close_stats(self, event):
        self._stats = None

    def go(self):
        if self.on:
            self.stop()
        else:
            self.on = True
            self.choose_task.state(["disabled"])
            self.b_go.configure(image=self.im_stop)
            self.after(1000, self.affiche)
            logging.info('Start work cycle for task ' + self.task.get())

    def stop(self, confirmation=True):
        """ Arrête le décompte du temps et le réinitialise,
            demande une confirmation avant de le faire si confirmation=True """
        tps = int(
            CONFIG.getint("Pomodoro", "work_time") - self.tps[0] -
            self.tps[1] / 60)
        self.on = False
        rep = True
        if confirmation:
            rep = askyesno(
                title=_("Confirmation"),
                message=_(
                    "Are you sure you want to give up the current session?"))
        if rep:
            self.choose_task.state(["!disabled"])
            self.b_go.configure(image=self.im_go)
            if self.activite.get() == _("Work"):
                self.stats(tps)
            self.pomodori.set(0)
            self.nb_cycles = 0
            self.tps = [CONFIG.getint("Pomodoro", "work_time"), 0]
            self.temps.configure(
                text="{0:02}:{1:02}".format(self.tps[0], self.tps[1]))
            act = _("Work")
            self.activite.set(act)
            self.style.configure('timer.pomodoro.TLabel',
                                 background=self.background[act],
                                 foreground=self.foreground[act])
            logging.info('Pomodoro session interrupted.')
        else:
            self.on = True
            self.affiche()
        return rep

    @staticmethod
    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 affiche(self):
        if self.on:
            self.tps[1] -= 1
            if self.tps[1] == 0:
                if self.tps[0] == 0:
                    self.ting()
                    if self.activite.get() == _("Work"):
                        self.pomodori.set(self.pomodori.get() + 1)
                        self.nb_cycles += 1
                        self.choose_task.state(["!disabled"])
                        logging.info(
                            'Pomodoro: completed work session for task ' +
                            self.task.get())
                        if self.nb_cycles % 4 == 0:
                            # pause longue
                            self.stats()
                            self.activite.set(_("Rest"))
                            self.tps = [
                                CONFIG.getint("Pomodoro", "rest_time"), 0
                            ]
                        else:
                            # pause courte
                            self.stats()
                            self.activite.set(_("Break"))
                            self.tps = [
                                CONFIG.getint("Pomodoro", "break_time"), 0
                            ]
                    else:
                        self.choose_task.state(["disabled"])
                        self.activite.set(_("Work"))
                        self.tps = [CONFIG.getint("Pomodoro", "work_time"), 0]
                    act = self.activite.get()
                    self.style.configure('timer.pomodoro.TLabel',
                                         background=self.background[act],
                                         foreground=self.foreground[act])
            elif self.tps[1] == -1:
                self.tps[0] -= 1
                self.tps[1] = 59
            self.temps.configure(text="{0:02}:{1:02}".format(*self.tps))
            self.after(1000, self.affiche)
Example #7
0
class PlaylistHandlerSet(Frame):
    def __init__(self, w: PlaylistControl, *args, **kwargs):
        self.EMPTY_MENUBTN = _("Select Playlist")  #After defined _ by gettext

        self.playlist = w.playlist
        self.playlist_control = w

        super().__init__(w, *args, **kwargs)

        #___

        self.menubtn = Menubutton(self,
                                  direction="above",
                                  width=13,
                                  text=config.general["playlist"])
        self.menubtn.pack()

        self.menu = Menu(self.menubtn,
                         bg=config.colors["BG"],
                         activebackground=config.colors["TV_BG_HOVER"],
                         activeforeground=config.colors["FG"],
                         tearoff=False)

        self.menu.add_command(label=_("Import Playlist"),
                              command=self._newPlaylist)
        self.menu.add_separator()
        for playlist in config.user_config["Playlists"]:
            #https://stackoverflow.com/questions/11723217/python-lambda-doesnt-remember-argument-in-for-loop
            func_get_set_playlist = lambda playlist=playlist: self.setPlaylist(
                playlist)
            self.menu.add_command(label=playlist,
                                  command=func_get_set_playlist)

        self.menubtn.configure(menu=self.menu)

    #__________________________________________________

    def _newPlaylist(self):
        folder: str = filedialog.askdirectory(
            title=_("Select folder for new playlist"))
        if folder == "": return

        playlist = os.path.basename(folder)

        if playlist not in config.user_config["Playlists"]:
            config.user_config["Playlists"][playlist] = {
                "path": os.path.normcase(folder),
                "orderby": ["title", 1],
                "filter": ""
            }

            self.menu.add_command(label=playlist,
                                  command=lambda: self.setPlaylist(playlist))

        self.setPlaylist(playlist)

    def setPlaylist(self, playlist: str):
        '''
        There will be no playlist when starting the application
        if the playlist had been destroyed with "self.delPlaylist()"
        and closed without selecting one playlist
        '''
        if playlist == "":
            self.menubtn["text"] = self.EMPTY_MENUBTN
            return

        playlist_path = config.user_config["Playlists"][playlist]["path"]

        if not os.path.exists(playlist_path):
            messagebox.showerror(_("Load failed"),
                                 _("The folder does not to exist"))
            self.delPlaylist(playlist)
            return

        config.general["playlist"] = playlist
        config.playlist = config.user_config["Playlists"][playlist]

        self.menubtn["text"] = playlist
        self.playlist.setPlaylist(playlist_path)
        self.playlist_control.sortPlaylistForced(config.playlist["orderby"][0],
                                                 config.playlist["orderby"][1])
        self.playlist_control.setSearch(config.playlist["filter"])

    def delPlaylist(self, playlist: str, in_tv: bool = True):
        config.user_config["Playlists"].pop(playlist)
        self.menu.delete(playlist)

        if in_tv:
            config.general["playlist"] = ""
            self.menubtn["text"] = self.EMPTY_MENUBTN
            self.playlist.delPlaylist()

    def renamePlaylist(self, playlist_new: str, playlist_new_path: str):
        playlist_old = config.general["playlist"]
        config.general["playlist"] = playlist_new
        config.user_config["Playlists"][playlist_new] = config.user_config[
            "Playlists"].pop(playlist_old)
        config.playlist = config.user_config["Playlists"][playlist_new]
        config.playlist["path"] = playlist_new_path

        self.menu.entryconfig(self.menu.index(playlist_old),
                              label=playlist_new,
                              command=lambda: self.setPlaylist(playlist_new))
        self.menubtn["text"] = playlist_new

        #Change the path of each song in the playlist
        for song in self.playlist.getAllSongs():
            song.path = os.path.join(playlist_new_path,
                                     song.name) + song.extension