예제 #1
0
 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
예제 #2
0
 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()
예제 #3
0
 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)
예제 #4
0
    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
예제 #5
0
    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()
예제 #6
0
    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)