Exemple #1
0
    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)
Exemple #2
0
    def mainButtons(self):
        row = 0
        col = 0
        self.buttons = []

        mb = Menubutton(self.root, text="Select Application")
        mb.menu = Menu(mb, tearoff=0)
        mb["menu"] = mb.menu
        for app in APPLICATIONS:
            mb.menu.add_radiobutton(label=app,
                                    variable=self.appVar,
                                    command=self.onSelectApp)
        mb.grid(row=row, column=col, sticky="NEW")
        col += 1

        self.buttons.append(mb)
        otherButtons = (
            ("Run %12s" % self.appVar.get(), self.runApp),
            ("load Config", self.loadCfg),
            ("Save Config", self.saveCfg),
            ("Save Config as", self.saveCfgAs),
            ("Quit", self.root.quit),
        )

        for text, command in otherButtons:
            self.buttons.append(Button(self.root, text=text, command=command))
            self.buttons[-1].grid(row=row, column=col, sticky="NEW")
            col += 1
        return len(self.buttons)
Exemple #3
0
    def init_gui(self):
        """
        Initializes all widgets for the main screen and calls grid_widgets()
        to place them
        """
        self.title("exp_check")
        self.config(bg='black')

        style = Style()
        style.configure("TMenubutton", foreground="white", background="black")
        # setup widgets
        self.add_button = Button(self,
                                 text="Add Food",
                                 **widget_options,
                                 command=self.add_food)
        self.delete_button = Button(self,
                                    text="Delete Food",
                                    **widget_options,
                                    command=self.delete_food)

        self.search_box = Entry(self,
                                **widget_options,
                                insertbackground='white')
        self.search_box.bind("<Key>", self.search)

        self.data_display = DataDisplay(widget_options)
        vals = self.data_manager.get_keylist()
        vals.insert(0, 'name')
        menu1 = Menu(tearoff=0)
        menu1.add('radiobutton',
                  label=vals[0],
                  command=lambda: self.update_data_display(sort_key=vals[0]))
        menu1.add('radiobutton',
                  label=vals[1],
                  command=lambda: self.update_data_display(sort_key=vals[1]))
        menu1.add('radiobutton',
                  label=vals[2],
                  command=lambda: self.update_data_display(sort_key=vals[2]))

        self.sort_menu = Menubutton(self,
                                    text='sort by',
                                    menu=menu1,
                                    style="TMenubutton")

        search_icon = self.generate_icon_object("./data/search_icon.png",
                                                (20, 20))
        self.search_label = Label(image=search_icon, **widget_options)
        self.search_label.image = search_icon
        # setup message box dialog
        self.message = Label(self, text='', **widget_options)
        self.okay_button = Button(
            self,
            text="   OK   ",
            **widget_options,
            command=lambda: self.okay_button_press(self.cur_instance))

        self.grid_widgets()
 def toc_menu(self, text):
     "Create table of contents as drop-down menu."
     toc = Menubutton(self, text='TOC')
     drop = Menu(toc, tearoff=False)
     for lbl, dex in text.parser.toc:
         drop.add_command(label=lbl, command=lambda dex=dex:text.yview(dex))
     toc['menu'] = drop
     return toc
Exemple #5
0
 def __init__(self, master, type, aqua=False, label="", **options):
     self.backend = "tkinter"
     self.type = type
     self.master = master
     self.aqua = aqua
     if type == "bar":
         self.children = {}
         self.menu = _Menu(master=master, tearoff=False, **options)
         self.master.config(menu=self.menu)
     elif type == "bar_child":
         self.menu = _Menu(master=master, tearoff=False, **options)
         self.master.add_cascade(menu=self.menu, label=label)
     elif type == "cascade":
         self.menu = _Menu(master=master, tearoff=False, **options)
         self.master.add_cascade(menu=self.menu, label=label)
     elif type == "popup":
         pass
     elif type == "menubutton":
         from tkinter.ttk import Menubutton
         self.widget = Menubutton(master=master, **options)
Exemple #6
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")
Exemple #7
0
class MainWindow(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.grid()
        self.master.title("Simple Data Modeling")
        self.createWidgets()
        self.model_loaded = False
        self.header_bool = IntVar()

        # define model types (classification/regression)
        self.clas_models = {
            'Decision Tree Classifier':
            sklearn.tree.DecisionTreeClassifier,
            'Random Forest Classifier':
            ensemble.RandomForestClassifier,
            'Gradient Boosting Classifier':
            sklearn.ensemble.GradientBoostingClassifier
        }
        self.reg_models = {
            'Linear Model': sklearn.linear_model.LinearRegression,
            'k-Nearest Neighbors Regression':
            sklearn.neighbors.KNeighborsRegressor,
            'Decision Tree Regression': sklearn.tree.DecisionTreeRegressor,
            'Gaussian Process Regression':
            gaussian_process.GaussianProcessRegressor,
            'Neural Network': neural_network.MLPRegressor,
            'Support Vector Regression': sklearn.svm.SVR,
            'XGB Regressor': xgb.XGBRegressor,
        }

        # define metric types for evaluation (classification/regression)
        self.clas_metrics = {
            "Accuracy Classification Score": metrics.accuracy_score,
            "Balanced Accuracy": metrics.balanced_accuracy_score,
            "F1 Score": metrics.f1_score,
            "Precision": metrics.precision_score,
            "Recall": metrics.recall_score
        }
        self.reg_metrics = {
            "Mean Absolute Error": metrics.mean_absolute_error,
            "Mean Squared Error": metrics.mean_squared_error,
            "R\u00B2 (Coefficient of Determination)": metrics.r2_score
        }

    def createWidgets(self):
        top = self.winfo_toplevel()
        self.menuBar = Menu(top)
        top["menu"] = self.menuBar
        self.subMenu = Menu(self.menuBar, tearoff=0)
        self.menuBar.add_cascade(label="File", menu=self.subMenu)
        self.subMenu.add_command(label="New",
                                 command=self.readData_createWindow)
        self.subMenu.add_command(label="Load Model", command=self.laod_model)
        self.subMenu.add_separator()
        self.subMenu.add_command(label="Help", command=self.help)
        self.subMenu.add_command(label="About", command=self.about)
        self.menuBar.add_command(label="Quit", command=self.master.destroy)

    def readData_createWindow(self):
        try:
            filename = filedialog.askopenfilename()
            f = open(filename, "rb")
            self.set_header(self.header_bool)
            # f = 'http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
            header = self.header_bool.get() == 1
            self.data = pd.read_csv(f, header=0 if header else None, sep=',')
            if not header:
                self.data.columns = [
                    'var' + str(i) for i in range(len(self.data.columns))
                ]
        except AttributeError:
            pass
        except Exception as e:
            return showerror("Error", "Data could not be loaded! Make sure the data is " \
                      + "formated in a similar way as the sample data: {}.".format(e))

        self.cols = self.data.columns
        self.setUpData()
        self.bools = [
        ]  # variables for columns: first axis: which col; second axis: what type

        height = min(5, self.data.shape[0])
        width = len(self.cols)

        # data frame
        data_frame = LabelFrame(self.master, text="Data Summary", relief=RIDGE)
        data_frame.grid(row=0,
                        column=0,
                        columnspan=5,
                        sticky="EWNS",
                        padx=15,
                        pady=7.5)
        data_size = "Data size is {} kilobytes. " \
            .format(np.round(self.data.memory_usage(deep=False).sum() / 1000, 2))
        cols_rows = "The number of columns is {} and the number of rows is {}. " \
            .format(self.data.shape[1], self.data.shape[0])
        miss_data = "The data does have missing values." if self.data.isnull().values.any() \
            else "The data does not have missing values."
        Message(data_frame, text=data_size + cols_rows + miss_data, width=335) \
            .grid(row=0, column=0, columnspan=width-1, rowspan=3, sticky='NW')
        Button(data_frame, text="Data", width=13, command=self.show_data) \
               .grid(row=0, column=4, columnspan=1, padx=4, pady=4)
        Button(data_frame, text="Description", width=13, command=self.show_description) \
               .grid(row=1, column=4, columnspan=1, padx=4, pady=0)
        Button(data_frame, text="Pair Plot", width=13, command=self.pair_plot) \
               .grid(row=2, column=4, columnspan=1, padx=4, pady=4)

        # head frame
        head_frame = LabelFrame(self.master, text="Head of data", relief=RIDGE)
        head_frame.grid(row=5,
                        column=0,
                        columnspan=5,
                        sticky="EWNS",
                        padx=15,
                        pady=7.5)

        for i in range(len(self.cols)):
            self.bools.append(
                self.initBools(5, trues=[0, 3] if i < width - 1 else [1, 3]))
        table = CustomTable(main_window=self,
                            parent=head_frame,
                            dataframe=self.data.head(),
                            editable=False,
                            width=1,
                            height=120)
        config.apply_options({'fontsize': 10}, table)
        table.show()

        # modeling frame
        model_frame = LabelFrame(self.master, text="Modeling", relief=RIDGE)
        model_frame.grid(row=height + 11,
                         column=0,
                         columnspan=5,
                         sticky="EWNS",
                         padx=15,
                         pady=7.5)

        # train / test ratio
        self.train_test_ratio = 1 / 3
        self.train_test_ratio_str = StringVar(
            self.master, value=str(np.round(self.train_test_ratio, 2)))
        Button(model_frame, text="Shuffle Data", width=13, command=self.shuffle_data) \
               .grid(row=0, column=0, columnspan=1)
        Button(model_frame, text="TrainTest Ratio", width=13, command=self.set_traintest) \
               .grid(row=0, column=2, columnspan=1)
        Label(model_frame, textvariable=self.train_test_ratio_str) \
               .grid(row=0, column=3, columnspan=1, sticky="E")

        # model selection
        ttk.Style().configure("TMenubutton", background="#E1E1E1")
        self.model_btn = Menubutton(model_frame, text="Model", width=9)
        self.set_model(self.model_btn)
        self.model_btn.grid(row=1, column=0, columnspan=1, padx=0, pady=4)
        Button(model_frame, text="Parameters", width=13, command=self.set_model_parameters) \
               .grid(row=1, column=1, columnspan=1, padx=0, pady=4)
        self.metric_btn = Menubutton(model_frame, text="Metric", width=9)
        self.set_metric(self.metric_btn)
        self.metric_btn.grid(row=1, column=2, columnspan=1, padx=0, pady=4)

        # model training
        self.score = -1
        self.score_str = StringVar(self.master, value="")
        Button(model_frame, text="Train Model", width=13, command=self.startModel) \
               .grid(row=1, column=3, columnspan=width-1)
        Label(model_frame, textvariable=self.score_str) \
               .grid(row=3, columnspan=width, sticky='W')

        # Export Frame
        export_frame = LabelFrame(self.master, text="Save", relief=RIDGE)
        export_frame.grid(row=height + 15,
                          column=0,
                          columnspan=5,
                          sticky="EWNS",
                          padx=15,
                          pady=7.5)
        Button(export_frame, text="Export Data", width=13, command=self.export_data) \
               .grid(row=0, column=0, columnspan=1, padx=4, pady=4)
        Button(export_frame, text="Export Model", width=13, command=self.export_model) \
               .grid(row=0, column=1, columnspan=1, padx=0, pady=4)

    def set_header(self, header_var):
        """
        User selection if data has a header as first row.
        """
        class popupWindow(object):
            def __init__(self, master):
                top = self.top = Toplevel(master)
                top.title('Header')
                top.attributes("-topmost", True)
                top.geometry("300x65")
                top.grid()
                top.resizable(0, 0)
                self.e = Checkbutton(top,
                                     text="Data contains header",
                                     variable=header_var,
                                     onvalue=1,
                                     offvalue=0)
                self.e.grid(row=0, column=1, columnspan=1)
                Button(top, text='     Ok     ', command=self.cleanup) \
                    .grid(row=0, column=2, columnspan=1)
                top.bind('<Return>', self.cleanup)

            def cleanup(self, event=None):
                self.top.destroy()

        popup = popupWindow(self.master)
        self.master.wait_window(popup.top)

    def setUpData(self):
        self.input_cols = list(np.arange(len(self.cols) - 1))
        self.output_cols = [len(self.cols) - 1]
        self.ignore_cols = []
        self.numeric_cols = list(np.arange(len(self.cols)))
        self.categorical_cols = []

    def setColSelection(self, new_btn, col):
        new_menu = Menu(new_btn, tearoff=0)
        new_btn["menu"] = new_menu
        new_menu.add_checkbutton(label="Input",
                                 command=self.setIn(col),
                                 variable=self.bools[col][0],
                                 onvalue=1,
                                 offvalue=0)  #,
        #state='disabled' if col < len(self.cols)-1 else 'active')
        new_menu.add_checkbutton(label="Output",
                                 command=self.setOut(col),
                                 variable=self.bools[col][1])
        new_menu.add_checkbutton(label="Ignore",
                                 command=self.setIgnore(col),
                                 variable=self.bools[col][2])
        new_menu.add_separator()
        new_menu.add_checkbutton(
            label="Numeric",
            command=self.setNum(col),
            variable=self.bools[col][3])  #, state='disabled')
        new_menu.add_checkbutton(label="Categorical",
                                 command=self.setCat(col),
                                 variable=self.bools[col][4])
        return new_menu

    def initBools(self, n, trues=[0, 3]):
        return [
            BooleanVar(self.master, value=True if i in trues else False)
            for i in range(n)
        ]

    ### functions for feature settings ###
    def setIn(self, col):
        def _setIn():
            if col in self.input_cols:
                pass
            else:
                self.input_cols.append(col)
                self.input_cols = sorted(self.input_cols)
                try:
                    del self.output_cols[self.output_cols.index(col)]
                except:
                    pass
                try:
                    del self.ignore_cols[self.ignore_cols.index(col)]
                except:
                    pass
            self.bools[col][0].set(value=True)
            self.bools[col][1].set(value=False)
            self.bools[col][2].set(value=False)

        return _setIn

    def setOut(self, col):
        def _setOut():
            if col in self.output_cols:
                pass
            else:
                try:
                    del self.input_cols[self.input_cols.index(col)]
                except:
                    pass
                try:
                    del self.ignore_cols[self.ignore_cols.index(col)]
                except:
                    pass
                if len(self.output_cols) == 1:
                    self.input_cols.append(self.output_cols[0])
                    self.bools[self.output_cols[0]][0].set(value=True)
                    self.bools[self.output_cols[0]][1].set(value=False)
                self.output_cols = [col]
            self.bools[col][0].set(value=False)
            self.bools[col][1].set(value=True)
            self.bools[col][2].set(value=False)

        return _setOut

    def setIgnore(self, col):
        def _setOut():
            if col in self.ignore_cols:
                pass
            else:
                self.ignore_cols.append(col)
                self.ignore_cols = sorted(self.ignore_cols)
                try:
                    del self.input_cols[self.input_cols.index(col)]
                except:
                    pass
                try:
                    del self.output_cols[self.output_cols.index(col)]
                except:
                    pass
            self.bools[col][0].set(value=False)
            self.bools[col][1].set(value=False)
            self.bools[col][2].set(value=True)

        return _setOut

    def setNum(self, col):
        def _setNum():
            if col in self.numeric_cols:
                pass
            else:
                self.numeric_cols.append(col)
                self.numeric_cols = sorted(self.numeric_cols)
                try:
                    del self.categorical_cols[self.categorical_cols.index(col)]
                except:
                    pass
            self.bools[col][3].set(value=True)
            self.bools[col][4].set(value=False)

        return _setNum

    def setCat(self, col):
        def _setCat():
            # showinfo("Information", "Categorical variables not supported yet!")
            if col in self.categorical_cols:
                pass
            else:
                self.categorical_cols.append(col)
                self.categorical_cols = sorted(self.categorical_cols)
                try:
                    del self.numeric_cols[self.numeric_cols.index(col)]
                except:
                    pass
            self.bools[col][3].set(value=False)
            self.bools[col][4].set(value=True)

        return _setCat

    ### ------------------------------ ###

    def properties(self):
        pass

    def help(self):
        instructions = "Instructions\n" \
            + "1) Load your data which is formated as csv file.\n" \
            + "2) Make sure loading worked by checking the displayed ´Head of Data´\n" \
                + "    or pressing the ´Data´ button to see the whole dataset.\n" \
            + "3) In the ´Head of Data´ press the column names to change their type" \
                + "      and to select the output feature.\n" \
            + "4) Select your appropriate model and change its parameters if needed.\n" \
            + "5) Save your predictions and model.\n"
        showinfo("Information", instructions)

    def about(self):
        showinfo("About", "This Application is for small data modeling tasks.\n\n" \
            + "Author\t{}\nVersion\t{}".format(__author__, __version__))

    def set_traintest(self):
        train_test_ratio = self.train_test_ratio_str.get()

        class popupWindow(object):
            def __init__(self, master):
                top = self.top = Toplevel(master)
                top.title('Train-Test Ratio')
                top.attributes("-topmost", True)
                top.geometry("350x80")
                top.grid()
                top.resizable(0, 0)

                Label(top, text="Enter the ratio of training set " \
                    + "size to test set size:").grid(row=0, columnspan=6,
                    sticky='nesw', padx=15, pady=7.5)
                self.e = Entry(top)
                self.e.insert(END, str(train_test_ratio))
                self.e.grid(row=1, column=0, columnspan=5, sticky='w', padx=15)
                Button(top, text='     Ok     ', command=self.cleanup) \
                    .grid(row=1, column=5, columnspan=1, sticky='e', padx=15)
                top.bind('<Return>', self.cleanup)

            def cleanup(self, event=None):
                self.value = self.e.get()
                self.top.destroy()

        popup = popupWindow(self.master)
        self.master.wait_window(popup.top)
        try:
            train_test_ratio = float(popup.value)
            if train_test_ratio > 1 or train_test_ratio <= 0:
                showerror("Error", "Train-Test ratio must be in (0,1]!")
            else:
                self.train_test_ratio = train_test_ratio
            self.train_test_ratio_str.set(
                str(np.round(self.train_test_ratio, 2)))
        except AttributeError:
            pass
        except:
            showerror("Error", "Train-Test ratio must be a value in (0,1]!")

    def set_model(self, btn):
        new_menu = Menu(btn, tearoff=0)
        btn["menu"] = new_menu

        self.model_selection_bool = self.initBools(len(self.reg_models) +
                                                   len(self.clas_models),
                                                   trues=[])

        for i, model in enumerate(self.reg_models.keys()):
            new_menu.add_checkbutton(label=model,
                                     command=self.setModelType(i),
                                     variable=self.model_selection_bool[i])
        new_menu.add_separator()
        for i, model in enumerate(self.clas_models.keys()):
            j = len(self.reg_models) + i
            new_menu.add_checkbutton(label=model,
                                     command=self.setModelType(j),
                                     variable=self.model_selection_bool[j])

        return new_menu

    def set_metric(self, btn):
        new_menu = Menu(btn, tearoff=0)
        btn["menu"] = new_menu

        self.metric_selection_bool = self.initBools(len(self.reg_metrics) +
                                                    len(self.clas_metrics),
                                                    trues=[])

        for i, metric in enumerate(self.reg_metrics.keys()):
            new_menu.add_checkbutton(label=metric,
                                     command=self.setMetricType(i),
                                     variable=self.metric_selection_bool[i])
        new_menu.add_separator()
        for i, metric in enumerate(self.clas_metrics.keys()):
            new_menu.add_checkbutton(
                label=metric,
                command=self.setMetricType(len(self.reg_metrics) + i),
                variable=self.metric_selection_bool[len(self.reg_metrics) + i])

        return new_menu

    def setModelType(self, model_index, default_params=True):
        def _setModelType():
            if len(self.output_cols) == 0:
                showerror("Error", "No output variable selected!")
            if self.output_cols[0] in self.numeric_cols:
                if model_index >= len(self.reg_models):  # regression
                    for j in range(len(self.model_selection_bool)):
                        self.model_selection_bool[j].set(value=False)
                    return showerror("Error",
                                     "This model is for classification!")
            elif self.output_cols[0] in self.categorical_cols:
                if model_index < len(self.reg_models):
                    for j in range(len(self.model_selection_bool)):
                        self.model_selection_bool[j].set(value=False)
                    return showerror("Error", "This model is for regression!")

            for j in range(len(self.model_selection_bool)):
                self.model_selection_bool[j].set(value=False)
            self.model_selection_bool[model_index].set(value=True)

            # get selected model type
            for i, b in enumerate(self.model_selection_bool):
                if b.get():
                    self.model_int = i

            try:
                if self.output_cols[0] in self.numeric_cols:  # regression
                    model = self.reg_models[list(
                        self.reg_models.keys())[self.model_int]]
                    model_name = list(self.reg_models.keys())[self.model_int]
                elif self.output_cols[
                        0] in self.categorical_cols:  # classification
                    model_int = self.model_int - len(self.reg_models)
                    model = self.clas_models[list(
                        self.clas_models.keys())[model_int]]
                    model_name = list(self.clas_models.keys())[model_int]

            except Exception as e:
                return showerror(
                    "Error",
                    "An appropriate model has to be selected: {}".format(e))

            self.model_name = model_name
            self.model = model

            # get and set default model parameters
            if default_params:
                signature = inspect.signature(model)
                self.model_dict = {
                    k: v.default
                    for k, v in signature.parameters.items()
                    if v.default is not inspect.Parameter.empty
                }

            # transformation for regression tasks
            if self.output_cols[0] in self.numeric_cols:

                def transformedTargetRegressor(**kwargs):
                    return TransformedTargetRegressor(
                        regressor=model(**kwargs), transformer=MinMaxScaler())

                model = transformedTargetRegressor

        return _setModelType

    def set_model_parameters(self):
        """
        """
        try:
            model_name, model, model_dict = self.model_name, self.model, self.model_dict
        except Exception as e:
            return showerror("Error",
                             "An model has to be selected first: {}".format(e))

        class popupWindow(object):
            def __init__(self, master):
                top = self.top = Toplevel(master)
                top.title("Parameters")
                top.attributes("-topmost", True)
                width = str(26 * (len(model_dict) + 4))
                top.geometry("310x" + width)
                top.grid()
                top.resizable(0, 0)

                frame = LabelFrame(top,
                                   text=model_name,
                                   relief=RIDGE,
                                   width=260)
                frame.grid(row=0,
                           column=0,
                           columnspan=2,
                           sticky="EWNS",
                           padx=15,
                           pady=15)

                self.values = list()
                line = 1
                for k, v in model_dict.items():
                    Label(frame, text=k, width=20) \
                        .grid(row=line, column=0, columnspan=1, sticky='W', padx=4, pady=1)
                    e = Entry(frame, width=10)
                    e.insert(END, str(v))
                    e.grid(row=line,
                           column=1,
                           columnspan=1,
                           sticky='E',
                           padx=6,
                           pady=1)
                    self.values.append(e)
                    line += 1

                Button(frame, text='  Help  ', command=self.help) \
                    .grid(row=line+2, column=0, columnspan=1, sticky='W', padx=4, pady=4)
                Button(frame, text='   Ok   ', command=self.cleanup) \
                    .grid(row=line+2, column=1, columnspan=1, sticky='E', padx=4, pady=4)
                top.bind('<Return>', self.cleanup)

            def cleanup(self, event=None):
                for i, k in enumerate(model_dict.keys()):
                    param_type = type(model_dict[k])
                    try:
                        value = self.values[i].get()
                        if param_type in (type(tuple()), type(list())):
                            model_dict[k] = eval(value)
                        elif param_type is not type(None):
                            model_dict[k] = param_type(value)
                        elif value == 'True' or value == 'False':
                            model_dict[k] = bool(value)
                        else:  # default might be NoneType which we don't want
                            try:
                                model_dict[k] = float(value)
                            except:
                                try:
                                    model_dict[k] = int(value)
                                except:
                                    model_dict[k] = None
                        self.model_dict = model_dict
                    except Exception as e:
                        showerror("Error", "The parameter type of {} is wrong: {}." \
                            .format(k, type(e)))

                self.top.destroy()

            def help(self, event=None):
                model_class = str(model)
                start = model_class.find('\'') + 1
                end = model_class.rfind('\'')
                keyword = model_class[start:end]
                keyword = keyword.replace('.',
                                          ' ').replace('_',
                                                       ' ').replace('  ', ' ')
                webbrowser.open('https://google.com/search?q=' + keyword)

        popup = popupWindow(self.master)
        self.master.wait_window(popup.top)
        try:
            self.model_dict = popup.model_dict
        except AttributeError:
            pass

    def setMetricType(self, metric_index):
        def _setMetricType():
            if len(self.output_cols) == 0:
                showerror("Error", "No output variable selected!")
            if self.output_cols[0] in self.numeric_cols:
                if metric_index >= len(self.reg_metrics):  # regression
                    for j in range(len(self.metric_selection_bool)):
                        self.metric_selection_bool[j].set(value=False)
                    return showerror("Error",
                                     "This metric is for classification!")
            elif self.output_cols[0] in self.categorical_cols:
                if metric_index < len(self.reg_metrics):
                    for j in range(len(self.metric_selection_bool)):
                        self.metric_selection_bool[j].set(value=False)
                    return showerror("Error", "This metric is for regression!")

            for j in range(len(self.metric_selection_bool)):
                self.metric_selection_bool[j].set(value=False)
            self.metric_selection_bool[metric_index].set(value=True)

            # get selected metric type
            for i, b in enumerate(self.metric_selection_bool):
                if b.get():
                    self.metric_int = i

            # set name and metric itself
            if self.output_cols[0] in self.numeric_cols:
                self.metric_name = list(
                    self.reg_metrics.keys())[self.metric_int]
                self.metric = self.reg_metrics[self.metric_name]
            elif self.output_cols[0] in self.categorical_cols:
                metric_int = self.metric_int - len(self.reg_metrics)
                self.metric_name = list(self.clas_metrics.keys())[metric_int]
                self.metric = self.clas_metrics[self.metric_name]

        return _setMetricType

    def show_data(self):
        """
        Opens a new window showing the data.
        """
        data = self.data

        class DataFrame(Frame):
            def __init__(self, master=None):
                top = self.top = Toplevel(master)
                top.attributes("-topmost", True)
                top.geometry('600x720')
                top.title('Data')
                self.table = pt = Table(top,
                                        dataframe=data,
                                        editable=False,
                                        enable_menus=False)
                pt.show()
                return

        popup = DataFrame(self.master)
        self.master.wait_window(popup.top)

    def show_description(self):
        """
        Opens a new window showing the a description of the data.
        """
        data = self.data.describe()
        data.reset_index(level=0, inplace=True)
        data.rename(columns={"index": ""}, inplace=True)

        class DataFrame(Frame):
            def __init__(self, master=None):
                top = self.top = Toplevel(master)
                top.attributes("-topmost", True)
                top.geometry('550x220')
                top.title('Data Description')
                self.table = pt = Table(top,
                                        dataframe=data,
                                        editable=False,
                                        enable_menus=False)
                pt.show()
                return

        popup = DataFrame(self.master)
        self.master.wait_window(popup.top)

    def pair_plot(self, limit: int = 50):
        """
        Draws a seaborn pairplot of the current data selection.

        Arguments
        ---------
            limit: int, maximum number of data points to plot.

        Returns
        -------
            -
        """
        if len(self.input_cols) + len(self.output_cols) <= 1:
            return showerror("Error", "No features selected to plot.")

        if len(self.output_cols) == 1:
            hue = self.cols[self.output_cols[0]] if \
                    self.bools[self.output_cols[0]][4].get() else None
        else:
            hue = None

        if limit < self.data.shape[0]:
            showinfo("Info",
                     "Showing only the first {} entries.".format(limit))

        sns.pairplot(self.data[self.cols[self.input_cols +
                                         self.output_cols]][:limit],
                     hue=hue,
                     height=1.5,
                     aspect=1.)
        plt.gcf().canvas.set_window_title('Pair Plot of Data')
        plt.get_current_fig_manager().window.setWindowIcon(
            QtGui.QIcon(os.path.join(os.path.dirname(__file__), 'icon.ico')))
        plt.show()

    def shuffle_data(self):
        """
        Shuffle the rows of the data.
        """
        self.data = self.data.sample(frac=1)

        class Notification(Frame):
            def __init__(self, master=None):
                top = self.top = Toplevel(master)
                top.attributes("-topmost", True)
                window_height = 75
                window_width = 225
                screen_width = top.winfo_screenwidth()
                screen_height = top.winfo_screenheight()
                x_cordinate = int((screen_width / 2) - (window_width / 2))
                y_cordinate = int((screen_height / 2) - (window_height / 2))
                top.geometry("{}x{}+{}+{}".format(window_width, window_height,
                                                  x_cordinate, y_cordinate))
                top.title('')
                Label(top, text="\nShuffeld\n", anchor=CENTER).pack()
                return

        popup = Notification(self.master)
        self.after(500, lambda: popup.top.destroy())

    def startModel(self):
        """
        Main action for trainig the selected model on the data.
        """
        error_msg = ""
        if len(self.output_cols) != 1:
            error_msg += "  * There must be exactly one dependent variable.\n"
        if len(self.input_cols) < 1:
            error_msg += "  * There must be at least one independent variable.\n"
        if not hasattr(self, 'model'):
            error_msg += "  * A model has to be selected.\n"
        if not hasattr(self, 'metric_int'):
            error_msg += "  * A metric has to be selected.\n"
        if len(error_msg) > 0:
            return showerror("Error", 'Model training failed!\n' + error_msg)

        # split data
        X_train, X_test, y_train, y_test = train_test_split(
            self.data[self.cols[self.input_cols]],
            self.data[self.cols[self.output_cols]],
            test_size=self.train_test_ratio)

        numeric_transformer = Pipeline(
            steps=[('imputer', SimpleImputer(
                strategy='median')), ('scaler', StandardScaler())])
        categorical_transformer = Pipeline(
            steps=[('imputer',
                    SimpleImputer(strategy='constant', fill_value='missing')
                    ), ('onehot', OneHotEncoder(handle_unknown='ignore'))])
        preprocessor = ColumnTransformer(
            transformers=[('num', numeric_transformer, self.cols[list(
                set(self.numeric_cols) -
                set(self.ignore_cols + self.output_cols))]),
                          ('cat', categorical_transformer, self.cols[list(
                              set(self.categorical_cols) -
                              set(self.ignore_cols + self.output_cols))])])

        model = Pipeline(steps=[('preprocessor', preprocessor),
                                ('model',
                                 Model(self.master, self.model,
                                       self.model_name, self.model_dict))])

        try:
            model.fit(X_train, y_train)
        except ValueError as e:
            return showerror(
                "Error",
                "Could not train the model (ValueError): {}".format(e))
        except Exception as e:
            return showerror("Error",
                             "Could not train the model: {}.".format(e))

        # make prediction
        try:
            y_pred = model.predict(X_test)
            self.data["predictions"] = model.predict(
                self.data[self.cols[self.input_cols]])
        except Exception as e:
            return showerror("Error",
                             "Failed to calculate predictions: {}".format(e))

        # evaluate model
        try:
            self.score = np.round(self.metric(y_test, y_pred), 4)
            showinfo("Result", "The model {} scored a {} of {} on the test data." \
                .format(self.model_name, self.metric_name, self.score))
            self.score_str.set(
                "The current model scores {} on the test data.".format(
                    str(np.round(self.score, 4))) if self.score != -1 else "")
        except Exception as e:
            return showerror("Error", "Failed to evaluate the predictions with " \
                + "the specified metric: {}.".format(e))

    def export_data(self):
        """
        Save preprocessed data and predictions (if made).
        """
        try:
            export_file_path = filedialog.asksaveasfilename(
                filetypes=[("default", "*.csv")], defaultextension='.csv')
            self.data.to_csv(export_file_path, index=False, header=True)
        except FileNotFoundError:
            pass
        except Exception as e:
            showerror("Error", "Data could not be saved: {}.".format(e))

    def export_model(self):
        """
        Save the model on disk.
        """
        try:
            export_file_path = filedialog.asksaveasfilename(
                filetypes=[("default", "*.pkl")], defaultextension='.pkl')
            saving = (self.model_name, self.model_dict, self.model,
                      self.model_int, self.metric_int)
            pickle.dump(saving, open(export_file_path, "wb"))
        except (AttributeError, FileNotFoundError):
            pass
        except Exception as e:
            showerror("Error", "Failed to save model: {}.".format(e))

    def laod_model(self):
        try:
            filename = filedialog.askopenfilename(filetypes=[("default",
                                                              "*.pkl")],
                                                  defaultextension='.pkl')
            self.model_name, self.model_dict, self.model, self.model_int, \
                self.metric_int = pickle.load(open(filename, 'rb'))

            self.model_loaded = True
            self.setModelType(self.model_int, default_params=False)()
            self.setMetricType(self.metric_int)()
        except FileNotFoundError:
            pass
        except Exception as e:
            showerror("Error", "Data could not be saved: {}.".format(e))
Exemple #8
0
    def readData_createWindow(self):
        try:
            filename = filedialog.askopenfilename()
            f = open(filename, "rb")
            self.set_header(self.header_bool)
            # f = 'http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
            header = self.header_bool.get() == 1
            self.data = pd.read_csv(f, header=0 if header else None, sep=',')
            if not header:
                self.data.columns = [
                    'var' + str(i) for i in range(len(self.data.columns))
                ]
        except AttributeError:
            pass
        except Exception as e:
            return showerror("Error", "Data could not be loaded! Make sure the data is " \
                      + "formated in a similar way as the sample data: {}.".format(e))

        self.cols = self.data.columns
        self.setUpData()
        self.bools = [
        ]  # variables for columns: first axis: which col; second axis: what type

        height = min(5, self.data.shape[0])
        width = len(self.cols)

        # data frame
        data_frame = LabelFrame(self.master, text="Data Summary", relief=RIDGE)
        data_frame.grid(row=0,
                        column=0,
                        columnspan=5,
                        sticky="EWNS",
                        padx=15,
                        pady=7.5)
        data_size = "Data size is {} kilobytes. " \
            .format(np.round(self.data.memory_usage(deep=False).sum() / 1000, 2))
        cols_rows = "The number of columns is {} and the number of rows is {}. " \
            .format(self.data.shape[1], self.data.shape[0])
        miss_data = "The data does have missing values." if self.data.isnull().values.any() \
            else "The data does not have missing values."
        Message(data_frame, text=data_size + cols_rows + miss_data, width=335) \
            .grid(row=0, column=0, columnspan=width-1, rowspan=3, sticky='NW')
        Button(data_frame, text="Data", width=13, command=self.show_data) \
               .grid(row=0, column=4, columnspan=1, padx=4, pady=4)
        Button(data_frame, text="Description", width=13, command=self.show_description) \
               .grid(row=1, column=4, columnspan=1, padx=4, pady=0)
        Button(data_frame, text="Pair Plot", width=13, command=self.pair_plot) \
               .grid(row=2, column=4, columnspan=1, padx=4, pady=4)

        # head frame
        head_frame = LabelFrame(self.master, text="Head of data", relief=RIDGE)
        head_frame.grid(row=5,
                        column=0,
                        columnspan=5,
                        sticky="EWNS",
                        padx=15,
                        pady=7.5)

        for i in range(len(self.cols)):
            self.bools.append(
                self.initBools(5, trues=[0, 3] if i < width - 1 else [1, 3]))
        table = CustomTable(main_window=self,
                            parent=head_frame,
                            dataframe=self.data.head(),
                            editable=False,
                            width=1,
                            height=120)
        config.apply_options({'fontsize': 10}, table)
        table.show()

        # modeling frame
        model_frame = LabelFrame(self.master, text="Modeling", relief=RIDGE)
        model_frame.grid(row=height + 11,
                         column=0,
                         columnspan=5,
                         sticky="EWNS",
                         padx=15,
                         pady=7.5)

        # train / test ratio
        self.train_test_ratio = 1 / 3
        self.train_test_ratio_str = StringVar(
            self.master, value=str(np.round(self.train_test_ratio, 2)))
        Button(model_frame, text="Shuffle Data", width=13, command=self.shuffle_data) \
               .grid(row=0, column=0, columnspan=1)
        Button(model_frame, text="TrainTest Ratio", width=13, command=self.set_traintest) \
               .grid(row=0, column=2, columnspan=1)
        Label(model_frame, textvariable=self.train_test_ratio_str) \
               .grid(row=0, column=3, columnspan=1, sticky="E")

        # model selection
        ttk.Style().configure("TMenubutton", background="#E1E1E1")
        self.model_btn = Menubutton(model_frame, text="Model", width=9)
        self.set_model(self.model_btn)
        self.model_btn.grid(row=1, column=0, columnspan=1, padx=0, pady=4)
        Button(model_frame, text="Parameters", width=13, command=self.set_model_parameters) \
               .grid(row=1, column=1, columnspan=1, padx=0, pady=4)
        self.metric_btn = Menubutton(model_frame, text="Metric", width=9)
        self.set_metric(self.metric_btn)
        self.metric_btn.grid(row=1, column=2, columnspan=1, padx=0, pady=4)

        # model training
        self.score = -1
        self.score_str = StringVar(self.master, value="")
        Button(model_frame, text="Train Model", width=13, command=self.startModel) \
               .grid(row=1, column=3, columnspan=width-1)
        Label(model_frame, textvariable=self.score_str) \
               .grid(row=3, columnspan=width, sticky='W')

        # Export Frame
        export_frame = LabelFrame(self.master, text="Save", relief=RIDGE)
        export_frame.grid(row=height + 15,
                          column=0,
                          columnspan=5,
                          sticky="EWNS",
                          padx=15,
                          pady=7.5)
        Button(export_frame, text="Export Data", width=13, command=self.export_data) \
               .grid(row=0, column=0, columnspan=1, padx=4, pady=4)
        Button(export_frame, text="Export Model", width=13, command=self.export_model) \
               .grid(row=0, column=1, columnspan=1, padx=0, pady=4)
Exemple #9
0
    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
Exemple #10
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()
Exemple #11
0
    def __init__(self, master):
        Toplevel.__init__(self, master, class_="CheckMails")
        self.title(_("Preferences"))

        style = Style(self)
        style.map("TCombobox",
                  fieldbackground=[('readonly', 'white')],
                  selectbackground=[('readonly', 'white')],
                  selectforeground=[('readonly', 'black')],
                  foreground=[('readonly', 'black')])

        # validation of the entries : only numbers are allowed
        self._validate_entry_nb = self.register(self.validate_entry_nb)

        # --- Times
        Label(self,
              text=_("Time between two checks")).grid(row=0, column=0,
                                                      padx=(10, 4), pady=(10, 4),
                                                      sticky="e")
        Label(self, justify="right",
              text=_("Maximum time allowed for login or check\n\
(then the connection is reset)")).grid(row=1, column=0, padx=(10, 4), pady=4, sticky="e")
        self.time_entry = Entry(self, width=5, justify="center",
                                validate="key",
                                validatecommand=(self._validate_entry_nb, "%P"))
        self.time_entry.grid(row=0, column=1, padx=(4, 0), pady=(10, 4))
        self.time_entry.insert(0, "%g" % (CONFIG.getint("General", "time") / 60000))
        self.timeout_entry = Entry(self, width=5, justify="center",
                                   validate="key",
                                   validatecommand=(self._validate_entry_nb, "%P"))
        self.timeout_entry.grid(row=1, column=1, padx=(4, 0), pady=4)
        self.timeout_entry.insert(0, "%g" % (CONFIG.getint("General", "timeout") / 60000))
        Label(self, text="min").grid(row=0, column=2, padx=(0, 10), pady=(10, 4))
        Label(self, text="min").grid(row=1, column=2, padx=(0, 10), pady=4)

        frame = Frame(self)
        frame.grid(row=2, columnspan=3, padx=6, pady=(0, 6))

        # --- Language
        Label(frame, text=_("Language")).grid(row=0, column=0,
                                              padx=8, pady=4, sticky="e")
        lang = {"fr": "Français", "en": "English"}
        self.lang = StringVar(self, lang[CONFIG.get("General", "language")])
        menu_lang = Menu(frame, tearoff=False)
        Menubutton(frame, menu=menu_lang, width=9,
                   textvariable=self.lang).grid(row=0, column=1,
                                                padx=8, pady=4, sticky="w")
        menu_lang.add_radiobutton(label="English", value="English",
                                  variable=self.lang, command=self.translate)
        menu_lang.add_radiobutton(label="Français", value="Français",
                                  variable=self.lang, command=self.translate)
        # --- gui toolkit
        Label(frame,
              text=_("GUI Toolkit for the system tray icon")).grid(row=1, column=0,
                                                                   padx=8, pady=4,
                                                                   sticky="e")
        self.gui = StringVar(self, CONFIG.get("General", "trayicon").capitalize())
        menu_gui = Menu(frame, tearoff=False)
        Menubutton(frame, menu=menu_gui, width=9,
                   textvariable=self.gui).grid(row=1, column=1,
                                               padx=8, pady=4, sticky="w")
        for toolkit, b in TOOLKITS.items():
            if b:
                menu_gui.add_radiobutton(label=toolkit.capitalize(),
                                         value=toolkit.capitalize(),
                                         variable=self.gui,
                                         command=self.change_gui)
        # --- Font
        self.preview_path = tempfile.mktemp(".png", "checkmails_preview")
        w = max([len(f) for f in TTF_FONTS])
        self.fonts = sorted(TTF_FONTS)
        self.font = Combobox(frame, values=self.fonts, width=(w * 2) // 3,
                             exportselection=False, state="readonly")
        current_font = CONFIG.get("General", "font")
        if current_font in self.fonts:
            i = self.fonts.index(current_font)
        else:
            i = 0
        self.font.current(i)
        self.img_prev = PhotoImage(master=self, file=IMAGE)
        Label(frame, text=_("Font")).grid(row=2, column=0,
                                          padx=8, pady=4, sticky="e")
        self.font.grid(row=2, column=1, padx=8, pady=4, sticky="w")
        self.prev = Label(frame, image=self.img_prev)
        self.prev.grid(row=2, column=2, padx=8, pady=4)
        self.update_preview()
        self.font.bind('<<ComboboxSelected>>', self.update_preview)
        self.font.bind_class("ComboboxListbox", '<KeyPress>', self.key_nav)

        # --- Ok/Cancel
        frame_button = Frame(self)
        frame_button.grid(row=3, columnspan=3, padx=6, pady=(0, 6))
        Button(frame_button, text="Ok",
               command=self.ok).grid(row=2, column=0, padx=8, pady=4)
        Button(frame_button, text=_("Cancel"),
               command=self.destroy).grid(row=2, column=1, padx=4, pady=4)
Exemple #12
0
    def __init__(self, master):
        Toplevel.__init__(self, master)
        self.title(_("Preferences"))
        self.grab_set()
        self.resizable(False, False)
        self.protocol("WM_DELETE_WINDOW", self.quit)
        self.changes = {}, {}

        # --- style
        style = Style(self)
        style.theme_use("clam")
        style.configure("TScale", sliderlength=20)
        style.map("TCombobox",
                  fieldbackground=[('readonly', 'white')],
                  selectbackground=[('readonly', 'white')],
                  selectforeground=[('readonly', 'black')])
        style.configure("prev.TLabel", background="white")
        style.map("prev.TLabel", background=[("active", "white")])
        color = CONFIG.get("Categories",
                           CONFIG.get("General", "default_category"))
        style.configure("titlebar.TFrame", background=color)
        style.configure("titlebar.TLabel", background=color)
        style.configure("text.TFrame", background="white")

        # --- body
        self.notebook = Notebook(self)
        okcancel_frame = Frame(self)
        okcancel_frame.columnconfigure(0, weight=1)
        okcancel_frame.columnconfigure(1, weight=1)
        self.notebook.pack(expand=True, fill="both")
        okcancel_frame.pack(fill="x", expand=True)

        # --- * General settings
        general_settings = Frame(self.notebook)
        general_settings.columnconfigure(0, weight=1)
        self.notebook.add(general_settings,
                          text=_("General"),
                          sticky="ewsn",
                          padding=4)

        # --- *-- language
        lang = {"fr": "Français", "en": "English"}
        self.lang = StringVar(self, lang[CONFIG.get("General", "language")])
        lang_frame = Frame(general_settings)
        Label(lang_frame, text=_("Language")).grid(row=0,
                                                   sticky="w",
                                                   padx=4,
                                                   pady=4)
        menu_lang = Menu(lang_frame, tearoff=False)
        Menubutton(lang_frame, menu=menu_lang, width=9,
                   textvariable=self.lang).grid(row=0,
                                                column=1,
                                                padx=8,
                                                pady=4)
        menu_lang.add_radiobutton(label="English",
                                  value="English",
                                  variable=self.lang,
                                  command=self.translate)
        menu_lang.add_radiobutton(label="Français",
                                  value="Français",
                                  variable=self.lang,
                                  command=self.translate)
        # --- *-- opacity
        self.opacity_scale = Scale(general_settings,
                                   orient="horizontal",
                                   length=200,
                                   from_=0,
                                   to=100,
                                   value=CONFIG.get("General", "opacity"),
                                   command=self.display_label)
        self.opacity_label = Label(
            general_settings,
            text="{val}%".format(val=self.opacity_scale.get()))
        # --- *-- position
        frame_position = Frame(general_settings)
        self.position = StringVar(self, CONFIG.get("General", "position"))
        Label(frame_position,
              text=_("Default position of the notes")).grid(row=0,
                                                            columnspan=3,
                                                            sticky="w",
                                                            padx=4,
                                                            pady=4)
        Radiobutton(frame_position,
                    text=_("Always above"),
                    value="above",
                    variable=self.position).grid(row=1, column=0)
        Radiobutton(frame_position,
                    text=_("Always below"),
                    value="below",
                    variable=self.position).grid(row=1, column=1)
        Radiobutton(frame_position,
                    text=_("Normal"),
                    value="normal",
                    variable=self.position).grid(row=1, column=2)
        # --- *-- titlebar
        self.titlebar_disposition = StringVar(
            self, CONFIG.get("General", "buttons_position"))
        font_title = "%s %s" % (CONFIG.get("Font", "title_family").replace(
            " ", "\ "), CONFIG.get("Font", "title_size"))
        style = CONFIG.get("Font", "title_style").split(",")
        if style:
            font_title += " "
            font_title += " ".join(style)

        frame_titlebar = Frame(general_settings)
        frame_titlebar.columnconfigure(1, weight=1)
        frame_titlebar.columnconfigure(3, weight=1)
        Label(frame_titlebar,
              text=_("Title bar disposition")).grid(row=0,
                                                    columnspan=4,
                                                    sticky="w",
                                                    padx=4,
                                                    pady=4)
        Radiobutton(frame_titlebar,
                    value="right",
                    variable=self.titlebar_disposition).grid(row=1, column=0)
        right = Frame(frame_titlebar, style="titlebar.TFrame")
        right.grid(row=1, column=1, sticky="ew")

        def select_right(event):
            self.titlebar_disposition.set("right")

        Label(right,
              text=_("Title"),
              style="titlebar.TLabel",
              anchor="center",
              font=font_title).pack(side="left", fill="x", expand=True)
        Label(right, image="img_close",
              style="titlebar.TLabel").pack(side="right")
        Label(right, image="img_roll",
              style="titlebar.TLabel").pack(side="right")
        for ch in right.children.values():
            ch.bind("<Button-1>", select_right)
        Radiobutton(frame_titlebar,
                    value="left",
                    variable=self.titlebar_disposition).grid(row=1, column=2)
        left = Frame(frame_titlebar, style="titlebar.TFrame")
        left.grid(row=1, column=3, sticky="ew")

        def select_left(event):
            self.titlebar_disposition.set("left")

        Label(left, image="img_close",
              style="titlebar.TLabel").pack(side="left")
        Label(left, image="img_roll",
              style="titlebar.TLabel").pack(side="left")
        Label(left,
              text=_("Title"),
              style="titlebar.TLabel",
              anchor="center",
              font=font_title).pack(side="right", fill="x", expand=True)
        for ch in left.children.values():
            ch.bind("<Button-1>", select_left)
        # --- *-- placement
        lang_frame.grid(sticky="w")
        Separator(general_settings, orient="horizontal").grid(sticky="ew",
                                                              pady=10)
        Label(general_settings, text=_("Opacity")).grid(sticky="w",
                                                        padx=4,
                                                        pady=4)
        self.opacity_scale.grid(padx=4, pady=(4, 10))
        self.opacity_label.place(in_=self.opacity_scale,
                                 relx=1,
                                 rely=0.5,
                                 anchor="w",
                                 bordermode="outside")
        Separator(general_settings, orient="horizontal").grid(sticky="ew",
                                                              pady=10)
        frame_position.grid(sticky="ew")
        Separator(general_settings, orient="horizontal").grid(sticky="ew",
                                                              pady=10)
        frame_titlebar.grid(sticky="ew", pady=4)
        if LATEX:
            Separator(general_settings, orient="horizontal").grid(sticky="ew",
                                                                  pady=10)
            Button(general_settings,
                   text=_('Delete unused LaTex data'),
                   command=self.cleanup).grid(padx=4, pady=4, sticky='w')

        # --- * Font settings
        font_settings = Frame(self.notebook)
        font_settings.columnconfigure(0, weight=1)
        self.notebook.add(font_settings,
                          text=_("Font"),
                          sticky="ewsn",
                          padding=4)

        # --- *-- title
        fonttitle_frame = Frame(font_settings)

        title_size = CONFIG.get("Font", "title_size")
        title_family = CONFIG.get("Font", "title_family")

        self.sampletitle = Label(fonttitle_frame,
                                 text=_("Sample text"),
                                 anchor="center",
                                 style="prev.TLabel",
                                 relief="groove")

        self.sampletitle.grid(row=2,
                              columnspan=2,
                              padx=4,
                              pady=6,
                              ipadx=4,
                              ipady=4,
                              sticky="eswn")
        self.fonts = list(set(font.families()))
        self.fonts.append("TkDefaultFont")
        self.fonts.sort()
        w = max([len(f) for f in self.fonts])
        self.sizes = [
            "%i" % i for i in (list(range(6, 17)) + list(range(18, 32, 2)))
        ]

        self.fonttitle_family = Combobox(fonttitle_frame,
                                         values=self.fonts,
                                         width=(w * 2) // 3,
                                         exportselection=False,
                                         validate="key")
        self._validate_title_size = self.register(
            lambda *args: self.validate_font_size(self.fonttitle_size, *args))
        self._validate_title_family = self.register(
            lambda *args: self.validate_font_family(self.fonttitle_family, *
                                                    args))
        self.fonttitle_family.configure(
            validatecommand=(self._validate_title_family, "%d", "%S", "%i",
                             "%s", "%V"))
        self.fonttitle_family.current(self.fonts.index(title_family))
        self.fonttitle_family.grid(row=0, column=0, padx=4, pady=4)
        self.fonttitle_size = Combobox(
            fonttitle_frame,
            values=self.sizes,
            width=5,
            exportselection=False,
            validate="key",
            validatecommand=(self._validate_title_size, "%d", "%P", "%V"))
        self.fonttitle_size.current(self.sizes.index(title_size))
        self.fonttitle_size.grid(row=0, column=1, padx=4, pady=4)

        frame_title_style = Frame(fonttitle_frame)
        frame_title_style.grid(row=1, columnspan=2, padx=4, pady=6)
        self.is_bold = Checkbutton(frame_title_style,
                                   text=_("Bold"),
                                   command=self.update_preview_title)
        self.is_italic = Checkbutton(frame_title_style,
                                     text=_("Italic"),
                                     command=self.update_preview_title)
        self.is_underlined = Checkbutton(frame_title_style,
                                         text=_("Underline"),
                                         command=self.update_preview_title)
        style = CONFIG.get("Font", "title_style")
        if "bold" in style:
            self.is_bold.state(("selected", ))
        if "italic" in style:
            self.is_italic.state(("selected", ))
        if "underline" in style:
            self.is_underlined.state(("selected", ))
        self.is_bold.pack(side="left")
        self.is_italic.pack(side="left")
        self.is_underlined.pack(side="left")

        self.update_preview_title()
        # --- *-- text
        size = CONFIG.get("Font", "text_size")
        family = CONFIG.get("Font", "text_family")

        font_frame = Frame(font_settings)
        self.sample = Label(font_frame,
                            text=_("Sample text"),
                            anchor="center",
                            style="prev.TLabel",
                            relief="groove")
        self.sample.grid(row=1,
                         columnspan=2,
                         padx=4,
                         pady=6,
                         ipadx=4,
                         ipady=4,
                         sticky="eswn")

        self.font_family = Combobox(font_frame,
                                    values=self.fonts,
                                    width=(w * 2) // 3,
                                    exportselection=False,
                                    validate="key")
        self._validate_family = self.register(
            lambda *args: self.validate_font_family(self.font_family, *args))
        self._validate_size = self.register(
            lambda *args: self.validate_font_size(self.font_size, *args))
        self.font_family.configure(validatecommand=(self._validate_family,
                                                    "%d", "%S", "%i", "%s",
                                                    "%V"))
        self.font_family.current(self.fonts.index(family))
        self.font_family.grid(row=0, column=0, padx=4, pady=4)
        self.font_size = Combobox(font_frame,
                                  values=self.sizes,
                                  width=5,
                                  exportselection=False,
                                  validate="key",
                                  validatecommand=(self._validate_size, "%d",
                                                   "%P", "%V"))
        self.font_size.current(self.sizes.index(size))
        self.font_size.grid(row=0, column=1, padx=4, pady=4)

        self.update_preview()

        # --- *-- placement
        Label(font_settings, text=_("Title")).grid(row=0,
                                                   padx=4,
                                                   pady=4,
                                                   sticky="w")
        fonttitle_frame.grid(row=1)
        Separator(font_settings, orient="horizontal").grid(row=2,
                                                           sticky="ew",
                                                           pady=10)
        Label(font_settings, text=_("Text")).grid(row=3,
                                                  padx=4,
                                                  pady=4,
                                                  sticky="w")
        font_frame.grid(row=4)

        # --- * Categories
        self.category_settings = CategoryManager(self.notebook, master)
        self.notebook.add(self.category_settings,
                          text=_("Categories"),
                          sticky="ewsn",
                          padding=4)
        # --- * Symbols
        symbols_settings = Frame(self.notebook)
        self.notebook.add(symbols_settings,
                          text=_("Symbols"),
                          sticky="ewsn",
                          padding=4)
        txt_frame = Frame(symbols_settings,
                          relief="sunken",
                          borderwidth=1,
                          style="text.TFrame")
        self.symbols = Text(txt_frame,
                            width=1,
                            height=1,
                            highlightthickness=0,
                            spacing2=5,
                            spacing1=5,
                            relief="flat",
                            padx=4,
                            pady=4,
                            font="%s %s" % (family.replace(" ", "\ "), size))
        self.symbols.insert("1.0", CONFIG.get("General", "symbols"))
        Label(symbols_settings, text=_("Available symbols")).pack(padx=4,
                                                                  pady=4)
        txt_frame.pack(fill="both", expand=True, padx=4, pady=4)
        self.symbols.pack(fill="both", expand=True)
        Button(symbols_settings, text=_('Reset'),
               command=self.reset_symbols).pack(padx=4, pady=4)

        # --- Ok/Cancel buttons
        Button(okcancel_frame, text="Ok", command=self.ok).grid(row=1,
                                                                column=0,
                                                                padx=4,
                                                                pady=10,
                                                                sticky="e")
        Button(okcancel_frame, text=_("Cancel"),
               command=self.destroy).grid(row=1,
                                          column=1,
                                          padx=4,
                                          pady=10,
                                          sticky="w")
        # --- bindings
        self.font_family.bind('<<ComboboxSelected>>', self.update_preview)
        self.font_family.bind('<Return>', self.update_preview)
        self.font_size.bind('<<ComboboxSelected>>',
                            self.update_preview,
                            add=True)
        self.font_size.bind('<Return>', self.update_preview, add=True)
        self.fonttitle_family.bind('<<ComboboxSelected>>',
                                   self.update_preview_title)
        self.fonttitle_size.bind('<<ComboboxSelected>>',
                                 self.update_preview_title,
                                 add=True)
        self.fonttitle_family.bind('<Return>', self.update_preview_title)
        self.fonttitle_size.bind('<Return>',
                                 self.update_preview_title,
                                 add=True)
Exemple #13
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))
Exemple #14
0
class ExpCheckGUI(Tk):
    def __init__(self, data_manager):
        super().__init__()
        self.data_manager = data_manager
        self.searching = False
        self.good_chars = printable[:-5] + '\x08'
        self.add_gui = AddFoodGUI(self)
        self.init_gui()

    def init_gui(self):
        """
        Initializes all widgets for the main screen and calls grid_widgets()
        to place them
        """
        self.title("exp_check")
        self.config(bg='black')

        style = Style()
        style.configure("TMenubutton", foreground="white", background="black")
        # setup widgets
        self.add_button = Button(self,
                                 text="Add Food",
                                 **widget_options,
                                 command=self.add_food)
        self.delete_button = Button(self,
                                    text="Delete Food",
                                    **widget_options,
                                    command=self.delete_food)

        self.search_box = Entry(self,
                                **widget_options,
                                insertbackground='white')
        self.search_box.bind("<Key>", self.search)

        self.data_display = DataDisplay(widget_options)
        vals = self.data_manager.get_keylist()
        vals.insert(0, 'name')
        menu1 = Menu(tearoff=0)
        menu1.add('radiobutton',
                  label=vals[0],
                  command=lambda: self.update_data_display(sort_key=vals[0]))
        menu1.add('radiobutton',
                  label=vals[1],
                  command=lambda: self.update_data_display(sort_key=vals[1]))
        menu1.add('radiobutton',
                  label=vals[2],
                  command=lambda: self.update_data_display(sort_key=vals[2]))

        self.sort_menu = Menubutton(self,
                                    text='sort by',
                                    menu=menu1,
                                    style="TMenubutton")

        search_icon = self.generate_icon_object("./data/search_icon.png",
                                                (20, 20))
        self.search_label = Label(image=search_icon, **widget_options)
        self.search_label.image = search_icon
        # setup message box dialog
        self.message = Label(self, text='', **widget_options)
        self.okay_button = Button(
            self,
            text="   OK   ",
            **widget_options,
            command=lambda: self.okay_button_press(self.cur_instance))

        self.grid_widgets()

    def grid_widgets(self):
        """
        Places initialized widgets on screen
        """
        self.title("exp_check")
        self.cur_instance = self
        self.columnconfigure(0, weight=1)
        self.columnconfigure(1, weight=1)
        self.rowconfigure(2, weight=1)
        grid_options = {"padx": 3, "pady": 3}
        self.add_button.grid(row=0, column=0, **grid_options)
        self.delete_button.grid(row=0, column=1, **grid_options)
        self.data_display.grid(row=2,
                               column=0,
                               **grid_options,
                               columnspan=6,
                               sticky=N + S + E + W)
        self.search_label.grid(row=0, column=3)
        self.search_box.grid(row=0, column=4, **grid_options)
        self.sort_menu.grid(row=0, column=5, **grid_options)
        self.update_data_display()

    def generate_icon_object(self, path, size):
        """
        Initializes the an icon with @param path so it is ready to be placed
            inside a label widget to be placed on screen
        """
        image = Image.open(path)
        image.convert("RGBA")
        image.thumbnail(size, Image.ANTIALIAS)
        return ImageTk.PhotoImage(image)

    def update_data_display(self,
                            event=None,
                            sort_key='name',
                            key_list=None,
                            search_string=None):
        """
        Synchronizes the data display with the database from the data manager
        """
        if key_list is None: key_list = self.data_manager.get_keylist()
        self.data_display.delete(0, END)
        for item in self.data_manager.get_database(key_list=key_list,
                                                   sort_key=sort_key):

            item_str = "{} {} {}".format(*item)
            if  search_string is None or\
                search_string in item_str.lower():
                item[1] = format_string.format(item[1])
                item[2] = format_string.format(item[2])
                self.data_display.insert(END, item)

    def search(self, event=None):
        """
        Updates the data display with whatever is in the search box. Will run
        any time a key is pressed while focused on the search box.
        """
        search_string = self.search_box.get()
        if event is None or event.char not in self.good_chars:
            newchar = ""
        elif event.char == '\x08':
            search_string = search_string[:-1]
            newchar = ""
        else:
            newchar = event.char

        search_string += newchar
        search_string = search_string.lower()

        self.update_data_display(search_string=search_string)

    def un_grid_widgets(self, event=None):
        """
        Removes all the current widgets
        """
        self.add_button.grid_forget()
        self.delete_button.grid_forget()
        self.data_display.grid_forget()
        self.search_label.grid_forget()
        self.search_box.grid_forget()
        self.sort_menu.grid_forget()

    def add_food(self, event=None):
        """
        Removes all the current widgets and draws draws the add_food_gui widgets
        on the window.
        """
        self.un_grid_widgets()
        self.add_gui.grid_widgets()

    def delete_food(self, event=None):
        """
        Selects and deletes a food from the database by calling the data manager
        """
        selection = self.data_display.get(ACTIVE).split()
        if not selection: return
        name = ' '.join(
            selection[0:-2]) if len(selection) > 3 else selection[0]
        msg = self.data_manager.delete_entry(name)
        if msg is not None:
            self.msg_box_init(self, msg)
            return
        self.update_data_display()

    def msg_box_init(self, instance, msg='a message'):
        """
        Creates a message box after deleting all removing all widgets from 
            the screen
        """
        instance.un_grid_widgets()
        self.message['text'] = msg
        self.message.grid(row=0, column=0)
        self.okay_button.grid(row=1, column=0)

    def okay_button_press(self, instance, event=None):
        """
        On pressing the okay button, replaces all changed widgets
        """
        self.message.grid_forget()
        self.okay_button.grid_forget()
        instance.grid_widgets()
Exemple #15
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()
Exemple #16
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)
Exemple #17
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)
Exemple #18
0
    def _init_general(self):
        frame_general = Frame(self)
        self.notebook.add(frame_general, text=_("General"))
        # --- Language
        Label(frame_general, text=_("Language")).grid(row=0,
                                                      column=0,
                                                      padx=8,
                                                      pady=4,
                                                      sticky="e")

        menu_lang = Menu(frame_general, tearoff=False, background=self._bg)
        mb = Menubutton(frame_general, menu=menu_lang, textvariable=self.lang)
        mb.grid(row=0, column=1, padx=8, pady=4, sticky="w")
        for lang in LANGUAGES:
            language = LANGUAGES[lang]
            menu_lang.add_radiobutton(label=language,
                                      value=language,
                                      variable=self.lang,
                                      command=self.translate)

        # --- gui toolkit
        Label(frame_general,
              text=_("GUI Toolkit for the system tray icon")).grid(row=2,
                                                                   column=0,
                                                                   padx=8,
                                                                   pady=4,
                                                                   sticky="e")

        menu_gui = Menu(frame_general, tearoff=False, background=self._bg)
        Menubutton(frame_general,
                   menu=menu_gui,
                   width=9,
                   textvariable=self.gui).grid(row=2,
                                               column=1,
                                               padx=8,
                                               pady=4,
                                               sticky="w")
        for toolkit, b in TOOLKITS.items():
            if b:
                menu_gui.add_radiobutton(label=toolkit.capitalize(),
                                         value=toolkit.capitalize(),
                                         variable=self.gui,
                                         command=self.change_gui)
        # --- Update delay
        Label(frame_general,
              text=_("Feed update delay (min)")).grid(row=4,
                                                      column=0,
                                                      padx=8,
                                                      pady=4,
                                                      sticky="e")
        self.entry_delay = Entry(frame_general,
                                 width=10,
                                 justify='center',
                                 validate='key',
                                 validatecommand=(self._validate, '%P'))
        self.entry_delay.grid(row=4, column=1, padx=8, pady=4, sticky='w')
        self.entry_delay.insert(
            0,
            CONFIG.getint('General', 'update_delay') // 60000)
        # --- image loading timeout
        Label(frame_general,
              text=_("Image loading timeout (s)")).grid(row=5,
                                                        column=0,
                                                        padx=8,
                                                        pady=4,
                                                        sticky="e")
        self.entry_timeout = Entry(frame_general,
                                   width=10,
                                   justify='center',
                                   validate='key',
                                   validatecommand=(self._validate, '%P'))
        self.entry_timeout.grid(row=5, column=1, padx=8, pady=4, sticky='w')
        self.entry_timeout.insert(
            0, CONFIG.getint('General', 'img_timeout', fallback=10))
        # --- Notifications
        self.notifications = Checkbutton(frame_general,
                                         text=_("Activate notifications"))
        self.notifications.grid(row=6,
                                column=0,
                                padx=8,
                                pady=4,
                                columnspan=2,
                                sticky='w')
        if CONFIG.getboolean('General', 'notifications', fallback=True):
            self.notifications.state(('selected', '!alternate'))
        else:
            self.notifications.state(('!selected', '!alternate'))

        # --- Confirm remove feed
        self.confirm_feed_rem = Checkbutton(
            frame_general,
            text=_("Show confirmation dialog before removing feed"))
        self.confirm_feed_rem.grid(row=7,
                                   column=0,
                                   padx=8,
                                   pady=4,
                                   columnspan=2,
                                   sticky='w')
        if CONFIG.getboolean('General', 'confirm_feed_remove', fallback=True):
            self.confirm_feed_rem.state(('selected', '!alternate'))
        else:
            self.confirm_feed_rem.state(('!selected', '!alternate'))
        # --- Confirm remove cat
        self.confirm_cat_rem = Checkbutton(
            frame_general,
            text=_("Show confirmation dialog before removing category"))
        self.confirm_cat_rem.grid(row=8,
                                  column=0,
                                  padx=8,
                                  pady=4,
                                  columnspan=2,
                                  sticky='w')
        if CONFIG.getboolean('General', 'confirm_cat_remove', fallback=True):
            self.confirm_cat_rem.state(('selected', '!alternate'))
        else:
            self.confirm_cat_rem.state(('!selected', '!alternate'))
        # --- Confirm update
        self.confirm_update = Checkbutton(
            frame_general, text=_("Check for updates on start-up"))
        self.confirm_update.grid(row=9,
                                 column=0,
                                 padx=8,
                                 pady=4,
                                 columnspan=2,
                                 sticky='w')
        if CONFIG.getboolean('General', 'check_update', fallback=True):
            self.confirm_update.state(('selected', '!alternate'))
        else:
            self.confirm_update.state(('!selected', '!alternate'))

        # --- Splash supported
        self.splash_support = Checkbutton(
            frame_general,
            text=_("Check this box if the widgets disappear when you click"))
        self.splash_support.grid(row=10,
                                 column=0,
                                 padx=8,
                                 pady=4,
                                 columnspan=2,
                                 sticky='w')
        if not CONFIG.getboolean('General', 'splash_supported', fallback=True):
            self.splash_support.state(('selected', '!alternate'))
        else:
            self.splash_support.state(('!selected', '!alternate'))
Exemple #19
0
    def _init_general(self):
        general_settings = Frame(self.notebook, padding=4)
        general_settings.columnconfigure(0, weight=1)
        self.notebook.add(general_settings,
                          text=_("General"),
                          sticky="ewsn",
                          padding=4)

        # ---- language

        self.lang = StringVar(self,
                              LANGUAGES[CONFIG.get("General", "language")])
        lang_frame = Frame(general_settings)
        Label(lang_frame, text=_("Language")).grid(row=0,
                                                   sticky="w",
                                                   padx=4,
                                                   pady=4)
        menu_lang = Menu(lang_frame, tearoff=False)
        Menubutton(lang_frame, menu=menu_lang, width=9,
                   textvariable=self.lang).grid(row=0,
                                                column=1,
                                                padx=8,
                                                pady=4)
        for lang in LANGUAGES.values():
            menu_lang.add_radiobutton(variable=self.lang,
                                      label=lang,
                                      value=lang,
                                      command=self.translate)
        # ---- gui toolkit
        self.gui = StringVar(self,
                             CONFIG.get("General", "trayicon").capitalize())
        gui_frame = Frame(general_settings)
        Label(gui_frame,
              text=_("GUI Toolkit for the system tray icon")).grid(row=0,
                                                                   column=0,
                                                                   padx=4,
                                                                   pady=4,
                                                                   sticky="w")
        menu_gui = Menu(gui_frame, tearoff=False)
        Menubutton(gui_frame, menu=menu_gui, width=9,
                   textvariable=self.gui).grid(row=0,
                                               column=1,
                                               padx=4,
                                               pady=4,
                                               sticky="w")
        for toolkit, b in TOOLKITS.items():
            if b:
                menu_gui.add_radiobutton(label=toolkit.capitalize(),
                                         value=toolkit.capitalize(),
                                         variable=self.gui,
                                         command=self.change_gui)
        # ---- opacity
        self.opacity = OpacityFrame(general_settings,
                                    CONFIG.getint("General", "opacity"))
        # ---- position
        frame_position = Frame(general_settings)
        self.position = StringVar(self, CONFIG.get("General", "position"))
        Label(frame_position,
              text=_("Default position of the notes")).grid(row=0,
                                                            columnspan=3,
                                                            sticky="w",
                                                            padx=4,
                                                            pady=4)
        Radiobutton(frame_position,
                    text=_("Always above"),
                    value="above",
                    variable=self.position).grid(row=1, column=0, padx=4)
        Radiobutton(frame_position,
                    text=_("Always below"),
                    value="below",
                    variable=self.position).grid(row=1, column=1, padx=4)
        Radiobutton(frame_position,
                    text=_("Normal"),
                    value="normal",
                    variable=self.position).grid(row=1, column=2, padx=4)
        # ---- titlebar
        self.titlebar_disposition = StringVar(
            self, CONFIG.get("General", "buttons_position"))
        self.title_var = StringVar(
            self)  # to add date if date_in_title is true
        font_title = "%s %s" % (CONFIG.get("Font", "title_family").replace(
            " ", "\ "), CONFIG.get("Font", "title_size"))
        style = CONFIG.get("Font", "title_style").split(",")
        if style:
            font_title += " "
            font_title += " ".join(style)

        frame_titlebar = Frame(general_settings)
        frame_titlebar.columnconfigure(1, weight=1)
        frame_titlebar.columnconfigure(3, weight=1)
        Label(frame_titlebar,
              text=_("Title bar disposition")).grid(row=0,
                                                    columnspan=4,
                                                    sticky="w",
                                                    padx=4,
                                                    pady=4)
        Radiobutton(frame_titlebar,
                    value="right",
                    variable=self.titlebar_disposition).grid(row=1,
                                                             column=0,
                                                             padx=4)
        right = Frame(frame_titlebar, style="titlebar.TFrame")
        right.grid(row=1, column=1, sticky="ew", padx=4)

        def select_right(event):
            self.titlebar_disposition.set("right")

        Label(right,
              textvariable=self.title_var,
              style="titlebar.TLabel",
              anchor="center",
              font=font_title).pack(side="left", fill="x", expand=True)
        Label(right, image="img_close",
              style="titlebar.TLabel").pack(side="right")
        Label(right, image="img_roll",
              style="titlebar.TLabel").pack(side="right")
        for ch in right.children.values():
            ch.bind("<Button-1>", select_right)
        Radiobutton(frame_titlebar,
                    value="left",
                    variable=self.titlebar_disposition).grid(row=1, column=2)
        left = Frame(frame_titlebar, style="titlebar.TFrame")
        left.grid(row=1, column=3, sticky="ew")

        def select_left(event):
            self.titlebar_disposition.set("left")

        Label(left, image="img_close",
              style="titlebar.TLabel").pack(side="left")
        Label(left, image="img_roll",
              style="titlebar.TLabel").pack(side="left")
        Label(left,
              textvariable=self.title_var,
              style="titlebar.TLabel",
              anchor="center",
              font=font_title).pack(side="right", fill="x", expand=True)
        for ch in left.children.values():
            ch.bind("<Button-1>", select_left)

        self.date_in_title = BooleanVar(
            self, CONFIG.getboolean('General', 'date_in_title', fallback=True))
        date_in_title = Checkbutton(frame_titlebar,
                                    variable=self.date_in_title,
                                    text=_('Display creation date in title'),
                                    command=self.toggle_date)
        date_in_title.grid(row=2, columnspan=4, sticky='w', pady=4, padx=4)
        self.toggle_date()
        # ---- placement
        lang_frame.grid(sticky="w")
        Separator(general_settings, orient="horizontal").grid(sticky="ew",
                                                              pady=10)
        gui_frame.grid(sticky="w")
        Separator(general_settings, orient="horizontal").grid(sticky="ew",
                                                              pady=10)
        # opacity_frame.grid(sticky='w')
        self.opacity.grid(sticky='w', padx=4)
        Separator(general_settings, orient="horizontal").grid(sticky="ew",
                                                              pady=10)
        frame_position.grid(sticky="ew")
        Separator(general_settings, orient="horizontal").grid(sticky="ew",
                                                              pady=10)
        frame_titlebar.grid(sticky="ew", pady=4)

        # ---- clean local data
        Separator(general_settings, orient="horizontal").grid(sticky="ew",
                                                              pady=10)
        Button(general_settings,
               text=_('Delete unused local data'),
               command=self.cleanup).grid(padx=4, pady=4, sticky='w')

        # ---- splash supported
        Separator(general_settings, orient="horizontal").grid(sticky="ew",
                                                              pady=10)
        self.splash_support = Checkbutton(
            general_settings,
            text=_("Check this box if the notes disappear when you click"))
        self.splash_support.grid(padx=4, pady=4, sticky='w')
        if not CONFIG.getboolean('General', 'splash_supported', fallback=True):
            self.splash_support.state(('selected', '!alternate'))
        else:
            self.splash_support.state(('!selected', '!alternate'))
Exemple #20
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)
Exemple #21
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