Пример #1
0
 class DateWidget(Frame):
     """Gets a date from the user."""
     def __init__(self, master):
         """Make boxes, register callbacks etc."""
         Frame.__init__(self, master)
         self.label = Label(self, text="När är du född?")
         self.label.pack()
         self.entry_text = StringVar()
         self.entry_text.trace("w", lambda *args: self.onEntryChanged())
         self.entry = Entry(self, width=date_entry_width,
              textvariable=self.entry_text)
         self.entry.insert(0, "ÅÅÅÅ-MM-DD")
         self.entry.pack(pady=small_pad)
         self.button = Button(self, text="Uppdatera",
              command=lambda: self.onDateChanged())
         self.button.pack()
         self.entry.focus_set()
         self.entry.select_range(0, END)
         self.entry.bind("<Return>", lambda x: self.onDateChanged())
     def setListener(self, pred_view):
         """Select whom to notify when a new date is entered."""
         self.pred_view = pred_view
     def onDateChanged(self):
         """Notifies the PredictionWidget that the date has been changed."""
         try:
             date = datetime.datetime.strptime(self.entry.get(),
                  "%Y-%m-%d").date()
             self.pred_view.update(date)
         except ValueError:
             self.entry.configure(foreground="red")
     def onEntryChanged(self):
         """Reset the text color."""
         self.entry.configure(foreground="")
Пример #2
0
    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)
Пример #3
0
    def ask_password(self):
        """Ask the master password in order to decrypt the mailbox config files."""
        def ok(event=None):
            with open(os.path.join(LOCAL_PATH, '.pwd')) as fich:
                cryptedpwd = fich.read()
            pwd = getpwd.get()
            if crypt.crypt(pwd, cryptedpwd) == cryptedpwd:
                # passwords match
                top.destroy()
                logging.info('Authentication successful')
                self.pwd = pwd
            else:
                showerror(_('Error'), _('Incorrect password!'))
                logging.warning('Authentication failed')
                getpwd.delete(0, "end")

        top = Toplevel(self, class_="CheckMails")
        top.title(_("Password"))
        top.resizable(False, False)
        Label(top, text=_("Enter password")).pack(padx=10, pady=(10, 4))
        getpwd = Entry(top, show='*', justify='center')
        getpwd.pack(padx=10, pady=4)
        Button(top, text="Ok", command=ok).pack(padx=10, pady=(4, 10))
        getpwd.bind("<Key-Return>", ok)
        getpwd.focus_set()
        self.wait_window(top)
Пример #4
0
    def set_password(self):
        """Set the master password used to encrypt the mailbox config files."""
        def ok(event=None):
            pwd = getpwd.get()
            pwd2 = confpwd.get()
            if pwd == pwd2:
                # passwords match
                cryptedpwd = crypt.crypt(pwd,
                                         crypt.mksalt(crypt.METHOD_SHA512))
                with open(os.path.join(LOCAL_PATH, '.pwd'), "w") as fich:
                    fich.write(cryptedpwd)
                top.destroy()
                self.pwd = pwd
                logging.info('New password set')
            else:
                showerror(_('Error'), _('Passwords do not match!'))

        top = Toplevel(self, class_="CheckMails")
        top.iconphoto(True, self.im_icon)
        top.title(_("Set password"))
        top.resizable(False, False)
        Label(top, text=_("Enter master password")).pack(padx=10, pady=(4, 10))
        getpwd = Entry(top, show='*', justify='center')
        getpwd.pack(padx=10, pady=4)
        Label(top, text=_("Confirm master password")).pack(padx=10, pady=4)
        confpwd = Entry(top, show='*', justify='center')
        confpwd.pack(padx=10, pady=4)
        Button(top, text="Ok", command=ok).pack(padx=10, pady=(4, 10))
        confpwd.bind("<Key-Return>", ok)
        getpwd.focus_set()
        self.wait_window(top)
Пример #5
0
class Add(Toplevel):
    def __init__(self, master):
        Toplevel.__init__(self, master, class_=APP_NAME, padx=6, pady=6)
        self.title(_("Add Feed"))
        self.grab_set()
        self.resizable(True, False)
        self.columnconfigure(1, weight=1)

        Label(self, text=_('URL')).grid(row=0,
                                        column=0,
                                        sticky='e',
                                        pady=4,
                                        padx=4)
        self.url = ""
        self.url_entry = Entry(self, width=30)
        self.url_entry.grid(row=0, column=1, sticky='ew', pady=4, padx=4)
        self.url_entry.bind('<Return>', self.validate)
        frame = Frame(self)
        frame.grid(row=1, column=0, columnspan=2)
        Button(frame, text=_('Ok'), command=self.validate).grid(row=0,
                                                                column=0,
                                                                sticky='e',
                                                                pady=4,
                                                                padx=4)

        Button(frame, text=_('Cancel'), command=self.destroy).grid(row=0,
                                                                   column=1,
                                                                   sticky='w',
                                                                   pady=4,
                                                                   padx=4)
        self.url_entry.focus_set()

    def validate(self, event=None):
        self.url = self.url_entry.get().strip()
        self.destroy()
Пример #6
0
def load_login_page():
    label_username = Label(frame_login, text="Username:"******"*", font=font)
    label_error = Label(frame_login, text="", font=font, foreground="red")
    label_password = Label(frame_login, text="Password:"******"Login",
        width=10,
        command=lambda: check_credentials(input_username.get(), input_password,
                                          label_error))
    button_login.bind(
        '<Return>', lambda _: check_credentials(input_username.get(),
                                                input_password, label_error))

    label_username.grid(column=1, row=1, pady=(0, 10))
    input_username.grid(column=2, row=1, pady=(0, 10), sticky=W)
    label_password.grid(column=1, row=2)
    input_password.grid(column=2, row=2, sticky=W)
    input_password.bind(
        '<Return>', lambda _: check_credentials(input_username.get(),
                                                input_password, label_error))

    label_error.grid(column=2, row=3, sticky=W)
    button_login.grid(column=2, row=4, pady=10, sticky=W)
    frame_login.grid()
Пример #7
0
    def add_link(self):
        def ok(eveny=None):
            lien = link.get()
            txt = text.get()
            if lien:
                if not txt:
                    txt = lien
                self.nb_links += 1
                if self.txt.tag_ranges("sel"):
                    index = self.txt.index("sel.first")
                    self.txt.delete('sel.first', 'sel.last')
                else:
                    index = "current"
                tags = self.txt.tag_names(index) + ("link",
                                                    "link#%i" % self.nb_links)
                self.txt.insert("current", txt, tags)
                if not lien[:4] == "http":
                    lien = "http://" + lien
                self.links[self.nb_links] = lien
                self.txt.tag_bind("link#%i" % self.nb_links, "<Button-1>",
                                  lambda e: open_url(lien))
            top.destroy()

        top = Toplevel(self)
        top.transient(self)
        top.update_idletasks()
        top.geometry("+%i+%i" % top.winfo_pointerxy())
        top.grab_set()
        top.resizable(True, False)
        top.title(_("Link"))
        top.columnconfigure(1, weight=1)
        text = Entry(top)
        link = Entry(top)
        if self.txt.tag_ranges('sel'):
            txt = self.txt.get('sel.first', 'sel.last')
        else:
            txt = ''
        text.insert(0, txt)
        text.icursor("end")
        Label(top, text=_("Text")).grid(row=0,
                                        column=0,
                                        sticky="e",
                                        padx=4,
                                        pady=4)
        Label(top, text=_("Link")).grid(row=1,
                                        column=0,
                                        sticky="e",
                                        padx=4,
                                        pady=4)
        text.grid(row=0, column=1, sticky="ew", padx=4, pady=4)
        link.grid(row=1, column=1, sticky="ew", padx=4, pady=4)
        Button(top, text="Ok", command=ok).grid(row=2,
                                                columnspan=2,
                                                padx=4,
                                                pady=4)

        text.focus_set()
        text.bind("<Return>", ok)
        link.bind("<Return>", ok)
Пример #8
0
    def __init__(self, parent, structure, command_stack, on_get_focus):
        tk.Frame.__init__(self, parent)
        self.command_stack = command_stack
        self._structure = structure
        self._fill_var = tk.IntVar()
        self._fill_var.set(self._structure.fill)

        (Checkbutton(self, text="Fill", variable=self._fill_var).grid(
            row=EditZone._FILL_CHECK_ROW, column=0, columnspan=2))

        self._fill_var.trace_add("write", self._set_fill)

        self._point_index = -1
        self._point_index_var = tk.StringVar()
        top_label = Label(self, textvariable=self._point_index_var)
        top_label.grid(row=EditZone._POINT_INDEX_ROW, column=0, columnspan=2)
        top_label.bind("<Button-1>", on_get_focus)

        x_label = Label(self, text="\u21d5:")
        x_label.grid(row=EditZone._X_ROW, column=0, sticky=tk.E)
        x_label.bind("<Button-1>", on_get_focus)
        y_label = Label(self, text="\u21d4:")
        y_label.grid(row=EditZone._Y_ROW, column=0, sticky=tk.E)
        y_label.bind("<Button-1>", on_get_focus)
        #the updating_ booleans allow to detect if the stringvars are edited
        #because the point is selected
        #or if the user changed their value
        self.inhibit_callbacks = True
        self.editable_x = tk.StringVar()
        self.editable_y = tk.StringVar()

        setx = Entry(self, textvariable=self.editable_x, width=6)
        setx.grid(row=EditZone._X_ROW, column=1, sticky=tk.W)
        setx.bind("<FocusIn>", on_get_focus)
        sety = Entry(self, textvariable=self.editable_y, width=6)
        sety.grid(row=EditZone._Y_ROW, column=1, sticky=tk.W)
        sety.bind("<FocusIn>", on_get_focus)

        self.editable_x.trace_add("write", self._point_edited)
        self.editable_y.trace_add("write", self._point_edited)

        (Button(self, text="Add Vertex",
                command=self._add_point).grid(row=EditZone._ADD_ROW,
                                              column=0,
                                              columnspan=2,
                                              sticky=tk.E + tk.W))
        (Button(self, text="Delete",
                command=self._delete_point).grid(row=EditZone._DEL_ROW,
                                                 column=0,
                                                 columnspan=2,
                                                 sticky=tk.E + tk.W))
        (Button(self, text="Symmetry",
                command=self._apply_symmetry).grid(row=EditZone._SYMM_ROW,
                                                   column=0,
                                                   columnspan=2,
                                                   sticky=tk.E + tk.W))
Пример #9
0
    def add_cat(self):
        """Add a category."""
        top = Toplevel(self, class_='MyNotes')
        top.transient(self)
        top.grab_set()
        top.resizable(False, False)
        top.title(_("New Category"))

        def valide(event=None):
            cats = [l.cget('text').lower() for l in self.cat_labels.values()]
            cat = name.get().strip().lower()
            if cat and cat not in cats:
                c, i = self.frame_cat.grid_size()
                self.cat_labels[cat] = Label(self.frame_cat,
                                             text="%s" % cat.capitalize())
                self.cat_labels[cat].grid(row=i, column=0, sticky="e")
                self.cat_colors[cat] = StringVar(self, _("Yellow"))
                self.cat_menus[cat] = OptionMenu(
                    self.frame_cat,
                    self.cat_colors[cat],
                    _("Yellow"),
                    *self.colors,
                    command=lambda color, c=cat: self.change_menubutton_color(
                        color, c),
                    style="%s.TMenubutton" % cat)
                self.style.configure("%s.TMenubutton" % cat,
                                     background=COLORS[_("Yellow")])
                optionmenu_patch(self.cat_menus[cat], self.cat_colors[cat])
                self.cat_menus[cat].grid(row=i, column=1, padx=4, pady=4)
                self.cat_buttons[cat] = Button(
                    self.frame_cat,
                    image=self.im_delete,
                    padding=0,
                    command=lambda c=cat: self.del_cat(c))
                self.cat_buttons[cat].grid(row=i,
                                           column=2,
                                           padx=4,
                                           pady=4,
                                           sticky='ns')
                self.cat_buttons[self.categories[0]].configure(state="normal")
                self.categories.append(cat)
                self.categories.sort()
                self.update_def_cat_menu()
                top.destroy()

        name = Entry(top, justify="center")
        name.grid(row=0, column=0, columnspan=2, sticky="ew")
        name.bind("<Return>", valide)
        name.bind("<Escape>", lambda e: top.destroy())
        name.focus_set()
        Button(top, text="Ok", command=valide).grid(row=1,
                                                    column=0,
                                                    sticky="nswe")
        Button(top, text=_("Cancel"), command=top.destroy).grid(row=1,
                                                                column=1,
                                                                sticky="nswe")
Пример #10
0
class Attribute(TwoCells):
    def __init__(self, parent, text, value, callback=None, **kwargs):
        super().__init__(parent, **kwargs)
        self.callback = callback
        self.label_text = StringVar()
        self.label_text.set(text)
        self.label = Label(self.frame, textvariable=self.label_text)
        self.label.grid(column=0, row=0, padx=5, pady=5, sticky=W)
        self.current_value = StringVar(self.frame)
        self.current_value.set(value)
        self.value = Entry(self.frame,
                           textvariable=self.current_value,
                           validate="key",
                           validatecommand=self.validate_command)
        self.value.grid(column=1, row=0, padx=5, pady=5, sticky=E)
        if self.callback:
            self.value.bind("<KeyRelease>", self._on_entry_changed)

    def _on_entry_changed(self, event):
        self.callback()

    def hide(self):
        self.label.grid_remove()
        self.value.grid_remove()
        return self

    def show(self, text):
        self.label_text.set(text)
        self.label.grid()
        self.value.grid()
        return self

    def disable(self):
        self.value.configure(state=DISABLED)
        return self

    def enable(self):
        self.value.configure(state=NORMAL)
        return self

    def set(self, value):
        self.current_value.set(value)
        if str(value) == "":
            self.disable()
        else:
            self.enable()

    def get(self):
        value = self.current_value.get()
        if self.validation_type in [
                TwoCells.INTEGERS, TwoCells.NON_NEGATIVE_INTEGERS
        ]:
            return int(value) if value not in ["", "-"] else 0
        else:
            return value
Пример #11
0
    def change_password(self):
        """
        Change the master password: decrypt all the mailbox config files
        using the old password and encrypt them with the new.
        """
        def ok(event=None):
            with open(os.path.join(LOCAL_PATH, '.pwd')) as fich:
                cryptedpwd = fich.read()
            old = oldpwd.get()
            pwd = newpwd.get()
            pwd2 = confpwd.get()
            if crypt.crypt(old, cryptedpwd) == cryptedpwd:
                # passwords match
                if pwd == pwd2:
                    # new passwords match
                    cryptedpwd = crypt.crypt(pwd,
                                             crypt.mksalt(crypt.METHOD_SHA512))
                    with open(os.path.join(LOCAL_PATH, '.pwd'), "w") as fich:
                        fich.write(cryptedpwd)
                    mailboxes = CONFIG.get(
                        "Mailboxes", "active").split(", ") + CONFIG.get(
                            "Mailboxes", "inactive").split(", ")
                    while "" in mailboxes:
                        mailboxes.remove("")
                    for mailbox in mailboxes:
                        server, login, password, folder = decrypt(mailbox, old)
                        if server is not None:
                            encrypt(mailbox, pwd, server, login, password,
                                    folder)
                    self.pwd = pwd
                    top.destroy()
                    logging.info('Password changed')
                    return pwd
                else:
                    showerror(_('Error'), _('Passwords do not match!'))
            else:
                showerror(_('Error'), _('Incorrect password!'))

        top = Toplevel(self, class_="CheckMails")
        top.iconphoto(True, self.im_icon)
        top.resizable(False, False)
        Label(top, text=_("Old password")).pack(padx=10, pady=(10, 4))
        oldpwd = Entry(top, show='*', justify='center')
        oldpwd.pack(padx=10, pady=4)
        Label(top, text=_("New password")).pack(padx=10, pady=4)
        newpwd = Entry(top, show='*', justify='center')
        newpwd.pack(padx=10, pady=4)
        Label(top, text=_("Confirm password")).pack(padx=10, pady=4)
        confpwd = Entry(top, show='*', justify='center')
        confpwd.pack(padx=10, pady=4)
        Button(top, text="Ok", command=ok).pack(padx=10, pady=(4, 10))
        confpwd.bind("<Key-Return>", ok)
        oldpwd.focus_set()
        self.wait_window(top)
Пример #12
0
class StudentIDDlg(Toplevel):
 def __init__(self, initialText, title, labeltext = '' ):
     Toplevel.__init__(self)
     self.initUI(initialText,title,labeltext)

 def initUI(self,initialText,title,labeltext=''):
     self.STID = initialText
     self.geometry("200x120")
     if len(title) > 0: 
         self.title(title)
         self.style = Style()
         self.style.theme_use("default") # default

     style = Style()
     style.configure("Exit.TButton", foreground="red", background="white")
     style.configure("MainButton.TButton", foreground="yellow", background="red")

     if len(labeltext) == 0: 
         labeltext = 'Please enter your ID..'
         self.bind("<Return>", self.ok)

     xpos = 40
     ypos = 30
     xpos2 = xpos+100
     l1 = Label(self, text=initialText, foreground = "#ff0000", background = "light blue", font = "Arial 9") # Arial 12 bold italic
     l1.place(x=xpos, y=ypos)

     self.txtID = Entry(self)
     self.txtID.place(x=xpos2, y = ypos, width=70)
     self.txtID.bind("<Return>", self.ok)
     self.txtID.bind("<Escape>", self.cancel)
     self.txtID.focus_set()

     ypos += 30

     okButton = Button(self, text="OK", background = "light blue", command=self.ok)
     #okButton.configure(style="ExitButton.TButton") # does not work
     okButton.place(x=xpos2, y=ypos)

 def getID(self):
    return self.STID

 def ok(self, event=None):
    self.STID = self.txtID.get()
    self.destroy()

 def cancel(self, event=None):
    self.destroy()
Пример #13
0
 def add(self):
     def ok(event=None):
         txt = e.get()
         txt = txt.strip().replace(" ", "\ ")
         if txt and txt not in self.exclude_list:
             self.exclude_list.append(txt)
             self.listvar.set(" ".join(self.exclude_list))
         top.destroy()
     top = Toplevel(self)
     top.transient(self)
     top.grab_set()
     e = Entry(top)
     e.pack(expand=True, fill="x", padx=10, pady=(10, 4))
     e.focus_set()
     e.bind("<Key-Return>", ok)
     Button(top, text="Ok", command=ok).pack(padx=10, pady=(4, 10))
Пример #14
0
class SelectKernel(Toplevel):
    """About Toplevel."""
    def __init__(self, master):
        """Create the Toplevel to select an existing Jupyter kernel."""
        Toplevel.__init__(self, master, class_=master.winfo_class(), padx=10, pady=10)
        self.resizable(True, False)
        self.title("Select existing kernel")
        self.columnconfigure(0, minsize=22)
        self.columnconfigure(1, weight=1)
        self.columnconfigure(2, weight=1)

        self.selected_kernel = ''

        Label(self,
              text="Select the .json connection file or enter the existing kernel's id:").grid(columnspan=4,
                                                                                               sticky='w',
                                                                                               pady=4)
        self.entry = Entry(self, width=10)
        self.entry.grid(row=1, columnspan=3, sticky='ew', pady=4)
        self.entry.bind('<Return>', lambda e: self.validate())
        Button(self, text='...', width=2, padding=0,
               command=self.select_file).grid(row=1, column=3, sticky='sn', pady=4)

        Button(self, text='Ok', command=self.validate).grid(row=2, column=1,
                                                            padx=4, pady=4,
                                                            sticky='e')
        Button(self, text='Cancel', command=self.destroy).grid(row=2, column=2,
                                                               padx=4, pady=4,
                                                               sticky='w')
        self.transient(master)
        self.entry.focus_set()
        self.update_idletasks()
        self.grab_set()

    def validate(self):
        self.selected_kernel = self.entry.get()
        self.destroy()

    def select_file(self):
        filename = askopenfilename(self, "Select connection file",
                                   initialdir=jupyter_runtime_dir(),
                                   defaultextension='.json',
                                   filetypes=[('JSON', '*.json'), ('All files', '*')])
        if filename:
            self.entry.delete(0, 'end')
            self.entry.insert(0, filename)
Пример #15
0
    def make_entry(self):
        """construct of Entry

        Parameters
        ----------
        None

        Returns
        -------
        None
        """
        vcmd = self.lf0.register(self.is_okay)

        ent0 = Entry(self.lf0, validatecommand=(vcmd, '%P', '%S', '%i'),
                     validate='key', textvariable=self.out_var)
        ent0.bind("<Return>", self.end_input)
        ent0.grid(row=1, column=0, padx=10)
        ent0.focus()
Пример #16
0
    def add_task(self):
        def ajoute(event=None):
            task = nom.get().lower().strip()
            if task in self.tasks:
                showerror(
                    _("Error"),
                    _("The task {task} already exists.").format(task=task),
                    parent=self)

            elif task:
                coul = CMAP[(len(self.tasks) + 1) % len(CMAP)]
                i = self.task_frame.grid_size()[1] + 1
                self.tasks[task] = ColorFrame(self.task_frame, coul,
                                              task.capitalize())
                self.tasks[task].grid(row=i,
                                      column=0,
                                      sticky='e',
                                      padx=4,
                                      pady=4)
                b = Button(self.task_frame,
                           image=self.im_moins,
                           padding=2,
                           command=lambda t=task: self.del_task(t))
                b.grid(row=i, column=1, sticky='w', padx=4, pady=4)
                self._tasks_btns[task] = b
                self._tasks_btns[CONFIG.options("PomodoroTasks")[0]].state(
                    ['!disabled'])
            top.destroy()

        top = Toplevel(self)
        top.title(_("New task"))
        top.transient(self)
        top.grab_set()
        nom = Entry(top, width=20, justify='center')
        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)
Пример #17
0
    def change_name(self, event):
        """Change category name."""
        def ok(event):
            cats = [l.cget('text').lower() for l in self.cat_labels.values()]
            cat = name.get().strip().lower()
            if cat and cat not in cats:
                label.configure(text=cat.capitalize())
                if old_cat == self.default_category.get():
                    self.default_category.set(cat.capitalize())
                self.update_def_cat_menu()

            name.destroy()

        label = event.widget
        old_cat = label.cget('text')
        name = Entry(self, justify='center')
        name.insert(0, label.cget('text'))
        name.place(in_=label,
                   relx=0,
                   rely=0,
                   anchor='nw',
                   relwidth=1,
                   relheight=1)
        name.bind('<FocusOut>', lambda e: name.destroy())
        name.bind('<Escape>', lambda e: name.destroy())
        name.bind('<Return>', ok)
        name.selection_range(0, 'end')
        name.focus_set()
Пример #18
0
def _create_validation_triangle(
    widget: ttk.Entry,
    option_name: str,
    tybe: Type[_StrOrInt],
    callback: Callable[[_StrOrInt], bool],
) -> ttk.Label:

    # TODO(typeshed): master attribute
    triangle: ttk.Label = ttk.Label(
        widget.master)  # type: ignore[attr-defined]
    var = tkinter.StringVar()

    def var_changed(*junk: object) -> None:
        value_string = var.get()

        value: Optional[_StrOrInt]
        try:
            value = tybe(value_string)
        except ValueError:  # e.g. int('foo')
            value = None
        else:
            if not callback(value):
                value = None

        if value is None:
            triangle.config(image=images.get('triangle'))
        else:
            triangle.config(image=_get_blank_triangle_sized_image())
            set(option_name, value, from_config=True)

    def setting_changed(junk: object = None) -> None:
        var.set(str(_value_to_save(get(option_name, object))))

    widget.bind(f'<<SettingChanged:{option_name}>>', setting_changed, add=True)
    var.trace_add('write', var_changed)
    setting_changed()

    widget.config(textvariable=var)
    return triangle
Пример #19
0
    def initui(self):
        self.nombre = Nombre(0,10)

        self.master.title("convertisseur")
        self.pack(fill=BOTH, expand=1)
        frame1 = Frame(self, relief = RAISED, borderwidth = 1)
        frame1.pack(fill = BOTH)
        label1 = Label(frame1, text = "Valeur")
        label1.pack(side = LEFT)
        self.valeur = StringVar()
        self.ecriture = StringVar()

        disp_valeur = Entry(frame1, textvar = self.valeur )
        disp_valeur.delete(0, END)
        self.valeur.set(str(self.nombre.valeur))
#        disp_valeur.insert(0, self.nombre.valeur)
        disp_valeur.pack(side = RIGHT, expand = True)
        disp_valeur.bind("<Return>", self.update_valeur)

        frame2 = Frame(self, relief = RAISED, borderwidth = 1)
        frame2.pack(fill = BOTH)
        label2 = Label(frame2, text = "Base")
        self.base = StringVar()
        label2.pack(side = LEFT)
        disp_base = Entry(frame2, textvar = self.base)
        disp_base.delete(0, END)
        self.base.set(self.nombre.base)
#        disp_base.insert(0, self.nombre.base)
        disp_base.pack(side = RIGHT, expand=True)
        disp_base.bind("<Return>", self.update_base)


        frame3 = Frame(self, relief=RAISED, borderwidth=1)
        frame3.pack(fill=BOTH)
        self.ecriture = StringVar()
        label3 = Label(frame3, text="Ecriture")
        label3.pack(side=LEFT)
        disp_ecriture = Entry(frame3, textvar = self.ecriture)
        disp_ecriture.delete(0, END)
        self.ecriture.set(self.nombre.represente())
#        disp_base.insert(0, self.nombre.represente())
        disp_ecriture.pack(side=RIGHT, expand=True)
        disp_ecriture.bind("<Return>", self.update_ecriture)
Пример #20
0
class ClientSetUp(Frame):
    """
    Dialog box that presents 3 inputs to the user:
        Username
        Server IP
        Port

    Extends the Frame class in tkinter.
    """

    def __init__(self):
        super().__init__()
        self.name = ''
        self.ip = ''
        self.port = ''
        self.initUI()

    def initUI(self):
        """
        Initialises the dialog box. The box will contain fields for the
        username, server ip and server port. A button is used to submit
        the data.
        """
        self.master.title("Connection Details")
        self.pack(fill=BOTH, expand=True)
        # Prepare the username field
        frame1 = Frame(self)
        frame1.pack(fill=X)

        lbl1 = Label(frame1, text="Username", width=14)
        lbl1.pack(side=LEFT, padx=5, pady=10)

        self.entry1 = Entry(frame1, textvariable=self.name)
        self.entry1.pack(fill=X, padx=5, expand=True)
        # Prepare the server address field
        frame2 = Frame(self)
        frame2.pack(fill=X)

        lbl2 = Label(frame2, text="Server Address", width=14)
        lbl2.pack(side=LEFT, padx=5, pady=10)

        self.entry2 = Entry(frame2, textvariable=self.ip)
        self.entry2.pack(fill=X, padx=5, expand=True)
        # Prepare the server port field
        frame3 = Frame(self)
        frame3.pack(fill=X)

        lbl3 = Label(frame3, text="Server Port", width=14)
        lbl3.pack(side=LEFT, padx=5, pady=10)

        self.entry3 = Entry(frame3, textvariable=self.port)
        self.entry3.pack(fill=X, padx=5, expand=True)

        frame4 = Frame(self)
        frame4.pack(fill=X)

        # Command tells the form what to do when the button is clicked
        btn = Button(frame4, text="Submit", command=self.onSubmit)
        btn.pack(padx=5, pady=10)

        # Give entry1 focus
        self.entry1.focus()

        # Set up what happens when Return is pressed
        # All entries will move onto the next except port which will submit
        # Note: These didn't work if they weren't lambdas (don't know why)
        self.entry1.bind('<Return>', lambda event: self.entry2.focus())
        self.entry2.bind('<Return>', lambda event: self.entry3.focus())
        self.entry3.bind('<Return>', lambda event: self.onSubmit())

        photo = PhotoImage(file=resource_path('icon.png'))
        self.master.iconphoto(False, photo)

    def onSubmit(self):
        """
        When clicked, the user input is stored in the instance variables
        and the boxes are cleared. The widget is then destroyed.
        """
        self.name = self.entry1.get()
        self.ip = self.entry2.get()
        self.port = self.entry3.get()

        self.entry1.delete(0, END)
        self.entry2.delete(0, END)
        self.entry3.delete(0, END)
        self.quit()

    def retry(self, name='', ip='', port=''):
        """
        Used if the user enters incorrect data. It will repopulate
        the fields where the data was correct. The mainloop is started
        once the fields are populated.

        Parameters:
            name (str): Name of client
            ip (str): IP of server
            port (str): Port of server
        """
        self.entry1.insert(0, name)
        self.entry2.insert(0, ip)
        self.entry3.insert(0, port)

        self.mainloop()
        self.quit()

    def on_close(self):
        self.destroy()
        sys.exit()
Пример #21
0
class DaxModelParameter():
    '''The UI elements and logic to set model parameter values.

    For this application; all model parameters are assumed to be
    floats (or ints cast to floats). Strings and Logicals need not
    apply.
    '''

    def __init__(self, parent, label_frame, sherpa_model_parameter):
        '''Create model parameter UI element'''
        self.sherpa_par = sherpa_model_parameter
        self.parent = parent
        self.label_frame = label_frame
        self.initial_value = {'val': self.sherpa_par.val,
                              'min': self.sherpa_par.min,
                              'max': self.sherpa_par.max}
        self.render_ui()

    def _freeze_thaw(self):
        '''ACTION: set the freeze() or thaw() based on the
        checkbox value.'''
        if 1 == self.fz_box.get():
            self.sherpa_par.freeze()
        else:
            self.sherpa_par.thaw()

    @staticmethod
    def __format_val(val):
        'Format parameter values'
        retval = "{:.5g}".format(val)
        return retval

    def reset(self):
        """Reset values to original"""
        for field in ['max', 'min', 'val']:
            to_mod = getattr(self, field)
            to_mod.delete(0, END)
            to_mod.insert(0, self.__format_val(self.initial_value[field]))
            to_mod.configure(foreground="black")
            setattr(self.sherpa_par, field, self.initial_value[field])

    def update(self):
        """Reset values to original"""
        for field in ['max', 'min', 'val']:
            to_mod = getattr(self, field)
            newval = getattr(self.sherpa_par, field)
            to_mod.delete(0, END)
            to_mod.insert(0, self.__format_val(newval))
            # ~ to_mod.configure(foreground="black")
            # ~ setattr(self.sherpa_par, field, self.initial_value[field])

    def entry_callback(self, keyevt, field):
        '''ACTION: set the model parameter value when the user
        type <<Return>>.  Otherwise, when user edits value
        it turns red so user knows it hasn't been set yet.

        All values are cast|set to doubles.

        There is no validation in the UI against the min|max
        values.  Sherpa raises an exception if you try to go beyond
        the limits so the color remains red until valid value is
        entered.
        '''
        from sherpa.utils.err import ParameterErr

        # Note: use .char instead of .keysym because Return
        # and Enter on the keypad are different keysym's but both
        # generate CR. This makes sense since can remap keyboard
        # keys -- the action we want is CR, whichever key generates it.
        # Update: Unfortunately the .char field is cleared 
        # in newer versions of python in the KeyRelease callback, and
        # the Key callback doesn't work (order of callback doesn't change
        # text color correctly).  So, I'm back to using the keysym.

        to_mod = getattr(self, field)

        if keyevt.keysym in ['Return', 'KP_Enter', 'Enter']:
            try:
                fval = float(to_mod.get())
                setattr(self.sherpa_par, field, fval)
                to_mod.configure(foreground="black")
                to_mod.last_value = to_mod.get()
            except (ValueError, ParameterErr) as val_err:
                messagebox.showerror("DAX Model Editor", str(val_err))

        else:
            if to_mod.get() != to_mod.last_value:
                to_mod.configure(foreground="red")

    def render_ui(self):
        '''Render the parameter UI elements and attach bindings'''

        row = self.parent.get_row()
        win = self.label_frame

        # The parameter name
        lab = Label(win, text=self.sherpa_par.name,
                    width=12, anchor="e")
        lab.grid(row=row, column=0, padx=(5, 5), pady=2)

        # The current parameter value
        self.val_str = StringVar()
        self.val = Entry(win, textvariable=self.val_str,
                         foreground="black", width=12, justify="right")
        self.val.grid(row=row, column=1, padx=(5, 5), pady=2)
        self.val.delete(0, END)
        self.val.insert(0, self.__format_val(self.sherpa_par.val))
        self.val.last_value = self.val.get()
        self.val.bind("<KeyRelease>",
                      lambda x: self.entry_callback(x, field='val'))

        # Frozen|Thawed checkbox.  Checked if frozen.
        self.fz_box = IntVar()
        if self.sherpa_par.frozen is True:
            self.fz_box.set(1)
        else:
            self.fz_box.set(0)
        fzbtn = Checkbutton(win, text="", variable=self.fz_box,
                            command=self._freeze_thaw)
        fzbtn.grid(row=row, column=2, padx=(5, 5), pady=2)

        # The min value
        self.min_str = StringVar()
        self.min = Entry(win, textvariable=self.min_str,
                         foreground="black", width=12, justify="right")
        self.min.grid(row=row, column=3, padx=(5, 5), pady=2)
        self.min.delete(0, END)
        self.min.insert(0, self.__format_val(self.sherpa_par.min))
        self.min.last_value = self.min.get()
        self.min.bind("<KeyRelease>",
                      lambda x: self.entry_callback(x, field='min'))

        # The max value
        self.max_str = StringVar()
        self.max = Entry(win, textvariable=self.max_str,
                         foreground="black", width=12, justify="right")
        self.max.grid(row=row, column=4, padx=(5, 5), pady=2)
        self.max.delete(0, END)
        self.max.insert(0, self.__format_val(self.sherpa_par.max))
        self.max.last_value = self.max.get()
        self.max.bind("<KeyRelease>",
                      lambda x: self.entry_callback(x, field='max'))

        # The units of the parameter
        par_units = Label(win, text="{}".format(self.sherpa_par.units),
                          width=20, anchor="e")
        par_units.grid(row=row, column=5, padx=(5, 5), pady=2)
Пример #22
0
class Search(Module):
    def __init__(self, app):
        self.app = app
        self.window = None

        self.context_size = 3
        self.results = []
        self.regex = StringVar(self.app)

        # if anything ever changes the contents of any intervals
        # it should call SearchModule.loadIntervals()
        self.intervals = []
        self.loadIntervals()

    def handleClose(self, event=None):
        self.window.destroy()
        self.window = None

    def createWindow(self):
        self.window = Toplevel(self.app)
        self.window.title('Search')
        self.window.protocol("WM_DELETE_WINDOW", self.handleClose)
        self.input = Entry(self.window, textvariable=self.regex)
        self.input.grid(row=0, column=0)
        self.input.bind('<Return>', self.search)
        self.input.bind('<Escape>', lambda ev: self.window.focus())
        self.searchButton = Button(self.window,
                                   text='Search',
                                   command=self.search,
                                   takefocus=0)
        self.searchButton.grid(row=0, column=1)
        self.resultCount = Label(self.window, text='0 results')
        self.resultCount.grid(row=0, column=2)
        cols = ('File', 'Tier', 'Time', 'Text')
        self.scroll = Scrollbar(self.window, orient='vertical')
        self.resultList = Treeview(self.window,
                                   columns=cols,
                                   show="headings",
                                   yscrollcommand=self.scroll.set,
                                   selectmode='browse')
        self.scroll.config(command=self.resultList.yview)
        for col in cols:
            self.resultList.heading(col, text=col)
        self.resultList.grid(row=2, column=0, columnspan=3, sticky='news')
        self.resultList.bind('<Double-1>', self.onClick)
        Grid.rowconfigure(self.window, 2, weight=1)
        Grid.columnconfigure(self.window, 0, weight=1)
        self.scroll.grid(row=2, column=3, sticky='ns')

    def openSearch(self):
        if self.window == None:
            self.createWindow()
        self.window.lift()
        self.input.focus()

    def loadIntervals(self):
        filecount = len(self.app.Data.getTopLevel('files'))
        self.intervals = []
        for f in range(filecount):
            filename = self.app.Data.getFileLevel('name', f)
            tg = self.app.Data.checkFileLevel('.TextGrid',
                                              f,
                                              shoulderror=False)
            if tg:
                grid = self.app.TextGrid.fromFile(tg)
                for tier in grid:
                    if TextGrid.isIntervalTier(tier):
                        for el in tier:
                            if el.mark:
                                self.intervals.append(
                                    (el, tier.name, filename))

    def search(self, event=None):
        if self.regex.get() == '':
            self.results = []
        else:
            pat = re.compile(self.regex.get(),
                             re.IGNORECASE | re.MULTILINE | re.DOTALL)
            self.results = []
            for i in self.intervals:
                s = pat.search(i[0].mark)
                if s:
                    disp = i[0].mark
                    a = max(0, s.start() - self.context_size)
                    b = min(s.end() + self.context_size, len(disp))
                    self.results.append(i +
                                        (('...' if a > 0 else '') + disp[a:b] +
                                         ('...' if b < len(disp) else ''), ))
        self.resultCount.configure(text='%s results' % len(self.results))
        for kid in self.resultList.get_children():
            self.resultList.delete(kid)
        for row, res in enumerate(self.results):
            ls = (res[2], res[1], '%s-%s' % (res[0].minTime, res[0].maxTime),
                  res[3])
            self.resultList.insert('', 'end', iid=str(row), values=ls)

    def onClick(self, event=None):
        self.jumpTo(int(self.resultList.selection()[0]))

    def jumpTo(self, index):
        self.app.filesJumpTo(self.results[index][2])
        self.app.TextGrid.selectedTier.set(self.results[index][1])
        self.app.TextGrid.start = self.results[index][0].minTime
        self.app.TextGrid.end = self.results[index][0].maxTime
        for i, f in enumerate(self.app.TextGrid.frameTier):
            if f.time >= self.results[index][0].minTime:
                self.app.frameSV.set(str(i))
                self.app.framesJumpTo()
                break
        self.app.TextGrid.fillCanvases()

    def reset(self, *args, **kwargs):
        raise NotImplementedError('cannot call SearchModule::reset')

    def update(self, *args, **kwargs):
        raise NotImplementedError('cannot call SearchModule::update')

    def grid(self, *args, **kwargs):
        raise NotImplementedError('cannot call SearchModule::grid')

    def grid_remove(self, *args, **kwargs):
        raise NotImplementedError('cannot call SearchModule::grid_remove')
Пример #23
0
class MemberChecker(PanedWindow):
    def __init__(self, parent):
        PanedWindow.__init__(self, parent, background="white")

        self.parent = parent
        self.init_data()
        self.init_log()
        self.init_ui()
        self.update_status()

    def init_data(self):
        self.data_store = api.DataStore()

    def init_log(self):
        self.entrance_log = entrance_log.EntranceLog()

    def init_ui(self):
        self.parent.title("Member Checker")
        self.columnconfigure(3, weight=3)
        self.pack(fill=BOTH, expand=True)

        self.input = StringVar()
        self.input_entry = Entry(self, textvariable=self.input)
        self.input_entry.bind('<Return>', self.submit)
        self.input_entry.grid(row=0, column=0, columnspan=3, sticky=E + W)

        self.result = StringVar()
        self.result_label = Label(self, textvariable=self.result)
        self.result_label.grid(row=3, column=0, columnspan=3, sticky=E + W)

        self.name = StringVar()
        name_label = Label(self, textvariable=self.name)
        name_label.grid(row=2, column=0, columnspan=3, sticky=E + W)

        self.status = StringVar()
        status_label = Label(self, textvariable=self.status)
        status_label.grid(row=4, column=0, columnspan=4, sticky=E + W)

        submit_button = Button(self, text="Submit", command=self.submit)
        submit_button.grid(row=1, column=2)

        enter_without_card_button = Button(self, text="Enter without card", command=self.enter_without_card)
        enter_without_card_button.grid(row=1, column=0)

        enter_member_without_card_button = Button(self, text="Enter member without card",
                                                  command=self.enter_member_without_card)
        enter_member_without_card_button.grid(row=1, column=1)

        self.entrance_log_list = Listbox(self)
        self.entrance_log_list.grid(row=0, column=3, rowspan=4, sticky=E + W + S + N)

        self.input_entry.focus()

    def load_data(self):
        if messagebox.askyesno("Load new API Data",
                               "Are you sure you want to load the new API data? All previous data will be removed. The program might be unresponsive for a few seconds, but don't kill it, please! It has feelings too."):
            self.data_store.load_api_data()

    def enter_by_identification(self, identification):
        member = self.data_store.find_member_by_identification(identification)
        if member is None:
            if messagebox.askyesno("Not a member",
                                   "This university identification is not registered as a member. Do you want to let them in as a non-member?"):
                self.enter_non_member_by_identification(identification)
        else:
            self.enter_member(member)

    def enter_by_barcode(self, barcode):
        member = self.data_store.find_member_by_barcode(barcode)
        if member is None:
            if messagebox.askyesno("Not a member",
                                   "This barcode is not registered as a member. Do you want to let them in as a non-member?"):
                self.enter_non_member_by_barcode(barcode)
        else:
            self.enter_member(member)

    def enter_non_member_by_identification(self, identification):
        self.entrance_log.enter_non_member_by_identification(identification)
        self.enter_non_member()

    def enter_non_member_by_barcode(self, barcode):
        self.entrance_log.enter_non_member_by_barcode(barcode)
        self.enter_non_member()

    def enter_without_card(self):
        self.clear_result()
        self.entrance_log.enter_without_card()
        self.enter_non_member()
        self.input_entry.focus()

    def enter_member(self, member):
        inside_result = self.entrance_log.is_member_inside(member)
        if inside_result[0]:
            if not messagebox.askyesno("Already inside",
                                       "This membership card has already been used to enter at {}. Are you sure you want to register it again? Normally you should let this person enter without card (and bill them accordingly).".format(
                                           inside_result[1])):
                return
        self.entrance_log.enter_member(member)
        self.result.set('Member!')
        self.result_label.configure(background='green')
        self.name.set(member['firstName'] + ' ' + member['lastName'])

        self.update_status()

    def enter_non_member(self):
        self.result.set('Not a member!')
        self.result_label.configure(background='red')
        self.name.set('Not in the database')

        self.update_status()

    def enter_member_without_card(self):
        name = self.input.get()
        if len(name) == 0:
            messagebox.showinfo('Name required', 'Please enter the name of this person!')
            return
        self.entrance_log.enter_member_without_card(name)
        self.result.set('Member without card!')
        self.result_label.configure(background="orange")
        self.name.set('')
        self.input.set('')
        self.update_status()

    def clear_result(self):
        self.result.set('')
        self.result_label.configure(background='white')
        self.name.set('')

    def submit(self, event=None):
        self.clear_result()

        entry = self.input.get()
        if helpers.is_valid_identification(entry):
            self.enter_by_identification(entry)
        elif helpers.is_valid_barcode(entry):
            self.enter_by_barcode(entry)
        else:
            messagebox.showinfo('Invalid entry',
                                'The data entered was not recognized as a valid bar code or a valid university identification. You should click \'enter without card\' to let this person in.')
            return

        self.input.set('')
        self.input_entry.focus()

    def clear_log(self):
        if messagebox.askyesno("Clear log", "Are you sure you want to clear the log of all people who entered?"):
            self.entrance_log.clear_log()
            self.update_status()

    def update_status(self):
        self.status.set("{} members inside. Total: {}".format(self.entrance_log.members_inside_count(),
                                                              self.entrance_log.inside_count()))

        logs = self.entrance_log.get_latest_logs(15)
        self.entrance_log_list.delete(0, 15)
        for l in logs:
            s = l['timestamp'] + ": "
            data = l['data']
            if 'member_id' in data:
                member = self.data_store.find_member(data['member_id'])
                s += member['firstName'] + " " + member['lastName']
            elif 'barcode' in data:
                s += data['barcode']
            elif 'identification' in data:
                s += data['identification']
            elif 'name' in data:
                s += '[no card]' + data['name']
            else:
                s += "-"
            self.entrance_log_list.insert(0, s)
Пример #24
0
class Sync(Tk):
    """FolderSync main window."""
    def __init__(self):
        Tk.__init__(self, className='FolderSync')
        self.title("FolderSync")
        self.geometry("%ix%i" %
                      (self.winfo_screenwidth(), self.winfo_screenheight()))
        self.protocol("WM_DELETE_WINDOW", self.quitter)
        self.icon = PhotoImage(master=self, file=IM_ICON)
        self.iconphoto(True, self.icon)
        self.rowconfigure(2, weight=1)
        self.columnconfigure(0, weight=1)

        # --- icons
        self.img_about = PhotoImage(master=self, file=IM_ABOUT)
        self.img_open = PhotoImage(master=self, file=IM_OPEN)
        self.img_plus = PhotoImage(master=self, file=IM_PLUS)
        self.img_moins = PhotoImage(master=self, file=IM_MOINS)
        self.img_sync = PhotoImage(master=self, file=IM_SYNC)
        self.img_prev = PhotoImage(master=self, file=IM_PREV)
        self.img_expand = PhotoImage(master=self, file=IM_EXPAND)
        self.img_collapse = PhotoImage(master=self, file=IM_COLLAPSE)

        self.original = ""
        self.sauvegarde = ""
        # list of files / folders to delete before starting the copy because
        # they are not of the same type on the original and the backup
        self.pb_chemins = []
        self.err_copie = False
        self.err_supp = False

        # --- init log files
        l = [f for f in listdir(PATH) if match(r"foldersync[0-9]+.pid", f)]
        nbs = []
        for f in l:
            with open(join(PATH, f)) as fich:
                old_pid = fich.read().strip()
            if exists("/proc/%s" % old_pid):
                nbs.append(int(search(r"[0-9]+", f).group()))
            else:
                remove(join(PATH, f))
        if not nbs:
            i = 0
        else:
            nbs.sort()
            i = 0
            while i in nbs:
                i += 1
        self.pidfile = PID_FILE % i
        open(self.pidfile, 'w').write(str(getpid()))

        self.log_copie = LOG_COPIE % i
        self.log_supp = LOG_SUPP % i

        self.logger_copie = setup_logger("copie", self.log_copie)
        self.logger_supp = setup_logger("supp", self.log_supp)
        date = datetime.now().strftime('%d/%m/%Y %H:%M')
        self.logger_copie.info("\n###  %s  ###\n" % date)
        self.logger_supp.info("\n###  %s  ###\n" % date)

        # --- filenames and extensions that will not be copied
        exclude_list = split(r'(?<!\\) ',
                             CONFIG.get("Defaults", "exclude_copie"))
        self.exclude_names = []
        self.exclude_ext = []
        for elt in exclude_list:
            if elt:
                if elt[:2] == "*.":
                    self.exclude_ext.append(elt[1:])
                else:
                    self.exclude_names.append(elt.replace("\ ", " "))

        # --- paths that will not be deleted
        self.exclude_path_supp = [
            ch.replace("\ ", " ") for ch in split(
                r'(?<!\\) ', CONFIG.get("Defaults", "exclude_supp")) if ch
        ]
        #        while "" in self.exclude_path_supp:
        #            self.exclude_path_supp.remove("")

        self.q_copie = Queue()
        self.q_supp = Queue()
        # True if a copy / deletion is running
        self.is_running_copie = False
        self.is_running_supp = False

        self.style = Style(self)
        self.style.theme_use("clam")
        self.style.configure("TProgressbar",
                             troughcolor='lightgray',
                             background='#387EF5',
                             lightcolor="#5D95F5",
                             darkcolor="#2758AB")
        self.style.map("TProgressbar",
                       lightcolor=[("disabled", "white")],
                       darkcolor=[("disabled", "gray")])
        self.style.configure("folder.TButton", padding=0)
        # --- menu
        self.menu = Menu(self, tearoff=False)
        self.configure(menu=self.menu)

        # -------- recents
        self.menu_recent = Menu(self.menu, tearoff=False)
        if RECENT:
            for ch_o, ch_s in RECENT:
                self.menu_recent.add_command(
                    label="%s -> %s" % (ch_o, ch_s),
                    command=lambda o=ch_o, s=ch_s: self.open(o, s))
        else:
            self.menu.entryconfigure(0, state="disabled")

        # -------- favorites
        self.menu_fav = Menu(self.menu, tearoff=False)
        self.menu_fav_del = Menu(self.menu_fav, tearoff=False)
        self.menu_fav.add_command(label=_("Add"),
                                  image=self.img_plus,
                                  compound="left",
                                  command=self.add_fav)
        self.menu_fav.add_cascade(label=_("Remove"),
                                  image=self.img_moins,
                                  compound="left",
                                  menu=self.menu_fav_del)
        for ch_o, ch_s in FAVORIS:
            label = "%s -> %s" % (ch_o, ch_s)
            self.menu_fav.add_command(
                label=label, command=lambda o=ch_o, s=ch_s: self.open(o, s))
            self.menu_fav_del.add_command(
                label=label, command=lambda nom=label: self.del_fav(nom))
        if not FAVORIS:
            self.menu_fav.entryconfigure(1, state="disabled")

        # -------- log files
        menu_log = Menu(self.menu, tearoff=False)
        menu_log.add_command(label=_("Copy"), command=self.open_log_copie)
        menu_log.add_command(label=_("Removal"),
                             command=self.open_log_suppression)

        # -------- settings
        menu_params = Menu(self.menu, tearoff=False)
        self.copy_links = BooleanVar(self,
                                     value=CONFIG.getboolean(
                                         "Defaults", "copy_links"))
        self.show_size = BooleanVar(self,
                                    value=CONFIG.getboolean(
                                        "Defaults", "show_size"))
        menu_params.add_checkbutton(label=_("Copy links"),
                                    variable=self.copy_links,
                                    command=self.toggle_copy_links)
        menu_params.add_checkbutton(label=_("Show total size"),
                                    variable=self.show_size,
                                    command=self.toggle_show_size)
        self.langue = StringVar(self, CONFIG.get("Defaults", "language"))
        menu_lang = Menu(menu_params, tearoff=False)
        menu_lang.add_radiobutton(label="English",
                                  value="en",
                                  variable=self.langue,
                                  command=self.change_language)
        menu_lang.add_radiobutton(label="Français",
                                  value="fr",
                                  variable=self.langue,
                                  command=self.change_language)
        menu_params.add_cascade(label=_("Language"), menu=menu_lang)
        menu_params.add_command(label=_("Exclude from copy"),
                                command=self.exclusion_copie)
        menu_params.add_command(label=_("Exclude from removal"),
                                command=self.exclusion_supp)

        self.menu.add_cascade(label=_("Recents"), menu=self.menu_recent)
        self.menu.add_cascade(label=_("Favorites"), menu=self.menu_fav)
        self.menu.add_cascade(label=_("Log"), menu=menu_log)
        self.menu.add_cascade(label=_("Settings"), menu=menu_params)
        self.menu.add_command(image=self.img_prev,
                              compound="center",
                              command=self.list_files_to_sync)
        self.menu.add_command(image=self.img_sync,
                              compound="center",
                              state="disabled",
                              command=self.synchronise)
        self.menu.add_command(image=self.img_about,
                              compound="center",
                              command=lambda: About(self))
        # --- tooltips
        wrapper = TooltipMenuWrapper(self.menu)
        wrapper.add_tooltip(4, _('Preview'))
        wrapper.add_tooltip(5, _('Sync'))
        wrapper.add_tooltip(6, _('About'))

        # --- path selection
        frame_paths = Frame(self)
        frame_paths.grid(row=0, sticky="ew", pady=(10, 0))
        frame_paths.columnconfigure(0, weight=1)
        frame_paths.columnconfigure(1, weight=1)
        f1 = Frame(frame_paths, height=26)
        f2 = Frame(frame_paths, height=26)
        f1.grid(row=0, column=0, sticky="ew")
        f2.grid(row=0, column=1, sticky="ew")
        f1.grid_propagate(False)
        f2.grid_propagate(False)
        f1.columnconfigure(1, weight=1)
        f2.columnconfigure(1, weight=1)

        # -------- path to original
        Label(f1, text=_("Original")).grid(row=0, column=0, padx=(10, 4))
        f11 = Frame(f1)
        f11.grid(row=0, column=1, sticky="nsew", padx=(4, 0))
        self.entry_orig = Entry(f11)
        self.entry_orig.place(x=1, y=0, bordermode='outside', relwidth=1)
        self.b_open_orig = Button(f1,
                                  image=self.img_open,
                                  style="folder.TButton",
                                  command=self.open_orig)
        self.b_open_orig.grid(row=0, column=2, padx=(0, 7))
        # -------- path to backup
        Label(f2, text=_("Backup")).grid(row=0, column=0, padx=(8, 4))
        f22 = Frame(f2)
        f22.grid(row=0, column=1, sticky="nsew", padx=(4, 0))
        self.entry_sauve = Entry(f22)
        self.entry_sauve.place(x=1, y=0, bordermode='outside', relwidth=1)
        self.b_open_sauve = Button(f2,
                                   image=self.img_open,
                                   width=2,
                                   style="folder.TButton",
                                   command=self.open_sauve)
        self.b_open_sauve.grid(row=0, column=5, padx=(0, 10))

        paned = PanedWindow(self, orient='horizontal')
        paned.grid(row=2, sticky="eswn")
        paned.rowconfigure(0, weight=1)
        paned.columnconfigure(1, weight=1)
        paned.columnconfigure(0, weight=1)

        # --- left side
        frame_left = Frame(paned)
        paned.add(frame_left, weight=1)
        frame_left.rowconfigure(3, weight=1)
        frame_left.columnconfigure(0, weight=1)

        # -------- files to copy
        f_left = Frame(frame_left)
        f_left.columnconfigure(2, weight=1)
        f_left.grid(row=2,
                    columnspan=2,
                    pady=(4, 2),
                    padx=(10, 4),
                    sticky="ew")

        Label(f_left, text=_("To copy")).grid(row=0, column=2)
        frame_copie = Frame(frame_left)
        frame_copie.rowconfigure(0, weight=1)
        frame_copie.columnconfigure(0, weight=1)
        frame_copie.grid(row=3,
                         column=0,
                         sticky="eswn",
                         columnspan=2,
                         pady=(2, 4),
                         padx=(10, 4))
        self.tree_copie = CheckboxTreeview(frame_copie,
                                           selectmode='none',
                                           show='tree')
        self.b_expand_copie = Button(f_left,
                                     image=self.img_expand,
                                     style="folder.TButton",
                                     command=self.tree_copie.expand_all)
        TooltipWrapper(self.b_expand_copie, text=_("Expand all"))
        self.b_expand_copie.grid(row=0, column=0)
        self.b_expand_copie.state(("disabled", ))
        self.b_collapse_copie = Button(f_left,
                                       image=self.img_collapse,
                                       style="folder.TButton",
                                       command=self.tree_copie.collapse_all)
        TooltipWrapper(self.b_collapse_copie, text=_("Collapse all"))
        self.b_collapse_copie.grid(row=0, column=1, padx=4)
        self.b_collapse_copie.state(("disabled", ))
        self.tree_copie.tag_configure("warning", foreground="red")
        self.tree_copie.tag_configure("link",
                                      font="tkDefaultFont 9 italic",
                                      foreground="blue")
        self.tree_copie.tag_bind("warning", "<Button-1>", self.show_warning)
        self.tree_copie.grid(row=0, column=0, sticky="eswn")
        self.scroll_y_copie = Scrollbar(frame_copie,
                                        orient="vertical",
                                        command=self.tree_copie.yview)
        self.scroll_y_copie.grid(row=0, column=1, sticky="ns")
        self.scroll_x_copie = Scrollbar(frame_copie,
                                        orient="horizontal",
                                        command=self.tree_copie.xview)
        self.scroll_x_copie.grid(row=1, column=0, sticky="ew")
        self.tree_copie.configure(yscrollcommand=self.scroll_y_copie.set,
                                  xscrollcommand=self.scroll_x_copie.set)
        self.pbar_copie = Progressbar(frame_left,
                                      orient="horizontal",
                                      mode="determinate")
        self.pbar_copie.grid(row=4,
                             columnspan=2,
                             sticky="ew",
                             padx=(10, 4),
                             pady=4)
        self.pbar_copie.state(("disabled", ))

        # --- right side
        frame_right = Frame(paned)
        paned.add(frame_right, weight=1)
        frame_right.rowconfigure(3, weight=1)
        frame_right.columnconfigure(0, weight=1)

        # -------- files to delete
        f_right = Frame(frame_right)
        f_right.columnconfigure(2, weight=1)
        f_right.grid(row=2,
                     columnspan=2,
                     pady=(4, 2),
                     padx=(4, 10),
                     sticky="ew")
        Label(f_right, text=_("To remove")).grid(row=0, column=2)
        frame_supp = Frame(frame_right)
        frame_supp.rowconfigure(0, weight=1)
        frame_supp.columnconfigure(0, weight=1)
        frame_supp.grid(row=3,
                        columnspan=2,
                        sticky="eswn",
                        pady=(2, 4),
                        padx=(4, 10))
        self.tree_supp = CheckboxTreeview(frame_supp,
                                          selectmode='none',
                                          show='tree')
        self.b_expand_supp = Button(f_right,
                                    image=self.img_expand,
                                    style="folder.TButton",
                                    command=self.tree_supp.expand_all)
        TooltipWrapper(self.b_expand_supp, text=_("Expand all"))
        self.b_expand_supp.grid(row=0, column=0)
        self.b_expand_supp.state(("disabled", ))
        self.b_collapse_supp = Button(f_right,
                                      image=self.img_collapse,
                                      style="folder.TButton",
                                      command=self.tree_supp.collapse_all)
        TooltipWrapper(self.b_collapse_supp, text=_("Collapse all"))
        self.b_collapse_supp.grid(row=0, column=1, padx=4)
        self.b_collapse_supp.state(("disabled", ))
        self.tree_supp.grid(row=0, column=0, sticky="eswn")
        self.scroll_y_supp = Scrollbar(frame_supp,
                                       orient="vertical",
                                       command=self.tree_supp.yview)
        self.scroll_y_supp.grid(row=0, column=1, sticky="ns")
        self.scroll_x_supp = Scrollbar(frame_supp,
                                       orient="horizontal",
                                       command=self.tree_supp.xview)
        self.scroll_x_supp.grid(row=1, column=0, sticky="ew")
        self.tree_supp.configure(yscrollcommand=self.scroll_y_supp.set,
                                 xscrollcommand=self.scroll_x_supp.set)
        self.pbar_supp = Progressbar(frame_right,
                                     orient="horizontal",
                                     mode="determinate")
        self.pbar_supp.grid(row=4,
                            columnspan=2,
                            sticky="ew",
                            padx=(4, 10),
                            pady=4)
        self.pbar_supp.state(("disabled", ))

        # --- bindings
        self.entry_orig.bind("<Key-Return>", self.list_files_to_sync)
        self.entry_sauve.bind("<Key-Return>", self.list_files_to_sync)

    def exclusion_supp(self):
        excl = ExclusionsSupp(self)
        self.wait_window(excl)
        # paths that will not be deleted
        self.exclude_path_supp = [
            ch.replace("\ ", " ") for ch in split(
                r'(?<!\\) ', CONFIG.get("Defaults", "exclude_supp")) if ch
        ]

    def exclusion_copie(self):
        excl = ExclusionsCopie(self)
        self.wait_window(excl)
        exclude_list = CONFIG.get("Defaults", "exclude_copie").split(" ")
        self.exclude_names = []
        self.exclude_ext = []
        for elt in exclude_list:
            if elt:
                if elt[:2] == "*.":
                    self.exclude_ext.append(elt[2:])
                else:
                    self.exclude_names.append(elt)

    def toggle_copy_links(self):
        CONFIG.set("Defaults", "copy_links", str(self.copy_links.get()))

    def toggle_show_size(self):
        CONFIG.set("Defaults", "show_size", str(self.show_size.get()))

    def open_log_copie(self):
        open_file(self.log_copie)

    def open_log_suppression(self):
        open_file(self.log_supp)

    def quitter(self):
        rep = True
        if self.is_running_copie or self.is_running_supp:
            rep = askokcancel(
                _("Confirmation"),
                _("A synchronization is ongoing, do you really want to quit?"),
                parent=self)
        if rep:
            self.destroy()

    def del_fav(self, nom):
        self.menu_fav.delete(nom)
        self.menu_fav_del.delete(nom)
        FAVORIS.remove(tuple(nom.split(" -> ")))
        save_config()
        if not FAVORIS:
            self.menu_fav.entryconfigure(1, state="disabled")

    def add_fav(self):
        sauvegarde = self.entry_sauve.get()
        original = self.entry_orig.get()
        if original != sauvegarde and original and sauvegarde:
            if exists(original) and exists(sauvegarde):
                if not (original, sauvegarde) in FAVORIS:
                    FAVORIS.append((original, sauvegarde))
                    save_config()
                    label = "%s -> %s" % (original, sauvegarde)
                    self.menu_fav.entryconfigure(1, state="normal")
                    self.menu_fav.add_command(label=label,
                                              command=lambda o=original, s=
                                              sauvegarde: self.open(o, s))
                    self.menu_fav_del.add_command(
                        label=label,
                        command=lambda nom=label: self.del_fav(nom))

    def open(self, ch_o, ch_s):
        self.entry_orig.delete(0, "end")
        self.entry_orig.insert(0, ch_o)
        self.entry_sauve.delete(0, "end")
        self.entry_sauve.insert(0, ch_s)
        self.list_files_to_sync()

    def open_sauve(self):
        sauvegarde = askdirectory(self.entry_sauve.get(), parent=self)
        if sauvegarde:
            self.entry_sauve.delete(0, "end")
            self.entry_sauve.insert(0, sauvegarde)

    def open_orig(self):
        original = askdirectory(self.entry_orig.get(), parent=self)
        if original:
            self.entry_orig.delete(0, "end")
            self.entry_orig.insert(0, original)

    def sync(self, original, sauvegarde):
        """ peuple tree_copie avec l'arborescence des fichiers d'original à copier
            vers sauvegarde et tree_supp avec celle des fichiers de sauvegarde à
            supprimer """
        errors = []
        copy_links = self.copy_links.get()
        excl_supp = [
            path for path in self.exclude_path_supp
            if commonpath([path, sauvegarde]) == sauvegarde
        ]

        def get_name(elt):
            return elt.name.lower()

        def lower(char):
            return char.lower()

        def arbo(tree, parent, n):
            """ affiche l'arborescence complète de parent et renvoie la longueur
                maximale des items (pour gérer la scrollbar horizontale) """
            m = 0
            try:
                with scandir(parent) as content:
                    l = sorted(content, key=get_name)
                for item in l:
                    chemin = item.path
                    nom = item.name
                    if item.is_symlink():
                        if copy_links:
                            tree.insert(parent,
                                        'end',
                                        chemin,
                                        text=nom,
                                        tags=("whole", "link"))
                            m = max(m, len(nom) * 9 + 20 * (n + 1))
                    elif ((nom not in self.exclude_names)
                          and (splitext(nom)[-1] not in self.exclude_ext)):
                        tree.insert(parent,
                                    'end',
                                    chemin,
                                    text=nom,
                                    tags=("whole", ))
                        m = max(m, len(nom) * 9 + 20 * (n + 1))
                        if item.is_dir():
                            m = max(m, arbo(tree, chemin, n + 1))
            except NotADirectoryError:
                pass
            except Exception as e:
                errors.append(str(e))
            return m

        def aux(orig, sauve, n, search_supp):
            m_copie = 0
            m_supp = 0
            try:
                lo = listdir(orig)
                ls = listdir(sauve)
            except Exception as e:
                errors.append(str(e))
                lo = []
                ls = []
            lo.sort(key=lambda x: x.lower())
            ls.sort(key=lambda x: x.lower())
            supp = False
            copie = False
            if search_supp:
                for item in ls:
                    chemin_s = join(sauve, item)
                    if chemin_s not in excl_supp and item not in lo:
                        supp = True
                        self.tree_supp.insert(sauve,
                                              'end',
                                              chemin_s,
                                              text=item,
                                              tags=("whole", ))
                        m_supp = max(m_supp, int(len(item) * 9 + 20 * (n + 1)),
                                     arbo(self.tree_supp, chemin_s, n + 1))

            for item in lo:
                chemin_o = join(orig, item)
                chemin_s = join(sauve, item)
                if ((item not in self.exclude_names)
                        and (splitext(item)[-1] not in self.exclude_ext)):
                    if item not in ls:
                        # le dossier / fichier n'est pas dans la sauvegarde
                        if islink(chemin_o):
                            if copy_links:
                                copie = True
                                self.tree_copie.insert(orig,
                                                       'end',
                                                       chemin_o,
                                                       text=item,
                                                       tags=("whole", "link"))
                                m_copie = max(
                                    m_copie,
                                    (int(len(item) * 9 + 20 * (n + 1))))
                        else:
                            copie = True
                            self.tree_copie.insert(orig,
                                                   'end',
                                                   chemin_o,
                                                   text=item,
                                                   tags=("whole", ))
                            m_copie = max(
                                m_copie, (int(len(item) * 9 + 20 * (n + 1))),
                                arbo(self.tree_copie, chemin_o, n + 1))
                    elif islink(chemin_o) and exists(chemin_o):
                        # checking the existence prevent from copying broken links
                        if copy_links:
                            if not islink(chemin_s):
                                self.pb_chemins.append(chemin_o)
                                tags = ("whole", "warning", "link")
                            else:
                                tags = ("whole", "link")
                            self.tree_copie.insert(orig,
                                                   'end',
                                                   chemin_o,
                                                   text=item,
                                                   tags=tags)
                            m_copie = max(m_copie,
                                          int(len(item) * 9 + 20 * (n + 1)))
                            copie = True
                    elif isfile(chemin_o):
                        # first check if chemin_s is also a file
                        if isfile(chemin_s):
                            if getmtime(chemin_o) // 60 > getmtime(
                                    chemin_s) // 60:
                                # le fichier f a été modifié depuis la dernière sauvegarde
                                copie = True
                                self.tree_copie.insert(orig,
                                                       'end',
                                                       chemin_o,
                                                       text=item,
                                                       tags=("whole", ))
                        else:
                            self.pb_chemins.append(chemin_o)
                            self.tree_copie.insert(orig,
                                                   'end',
                                                   chemin_o,
                                                   text=item,
                                                   tags=("whole", "warning"))
                    elif isdir(chemin_o):
                        # to avoid errors due to unrecognized item types (neither file nor folder nor link)
                        if isdir(chemin_s):
                            self.tree_copie.insert(orig,
                                                   'end',
                                                   chemin_o,
                                                   text=item)
                            self.tree_supp.insert(sauve,
                                                  'end',
                                                  chemin_s,
                                                  text=item)
                            c, s, mc, ms = aux(
                                chemin_o, chemin_s, n + 1, search_supp
                                and (chemin_s not in excl_supp))
                            supp = supp or s
                            copie = copie or c
                            if not c:
                                # nothing to copy
                                self.tree_copie.delete(chemin_o)
                            else:
                                m_copie = max(
                                    m_copie, mc,
                                    int(len(item) * 9 + 20 * (n + 1)))
                            if not s:
                                # nothing to delete
                                self.tree_supp.delete(chemin_s)
                            else:
                                m_supp = max(m_supp, ms,
                                             int(len(item) * 9 + 20 * (n + 1)))
                        else:
                            copie = True
                            self.pb_chemins.append(chemin_o)
                            self.tree_copie.insert(orig,
                                                   'end',
                                                   chemin_o,
                                                   text=item,
                                                   tags=("whole", "warning"))
                            m_copie = max(
                                m_copie, (int(len(item) * 9 + 20 * (n + 1))),
                                arbo(self.tree_copie, chemin_o, n + 1))
            return copie, supp, m_copie, m_supp

        self.tree_copie.insert("",
                               0,
                               original,
                               text=original,
                               tags=("checked", ),
                               open=True)
        self.tree_supp.insert("",
                              0,
                              sauvegarde,
                              text=sauvegarde,
                              tags=("checked", ),
                              open=True)
        c, s, mc, ms = aux(original, sauvegarde, 1, True)
        if not c:
            self.tree_copie.delete(original)
            self.tree_copie.column("#0", minwidth=0, width=0)
        else:
            mc = max(len(original) * 9 + 20, mc)
            self.tree_copie.column("#0", minwidth=mc, width=mc)
        if not s:
            self.tree_supp.delete(sauvegarde)
            self.tree_supp.column("#0", minwidth=0, width=0)
        else:
            ms = max(len(sauvegarde) * 9 + 20, mc)
            self.tree_supp.column("#0", minwidth=ms, width=ms)
        return errors

    def show_warning(self, event):
        if "disabled" not in self.b_open_orig.state():
            x, y = event.x, event.y
            elem = event.widget.identify("element", x, y)
            if elem == "padding":
                orig = self.tree_copie.identify_row(y)
                sauve = orig.replace(self.original, self.sauvegarde)
                showwarning(
                    _("Warning"),
                    _("%(original)s and %(backup)s are not of the same kind (folder/file/link)"
                      ) % {
                          'original': orig,
                          'backup': sauve
                      },
                    master=self)

    def list_files_to_sync(self, event=None):
        """Display in a treeview the file to copy and the one to delete."""
        self.pbar_copie.configure(value=0)
        self.pbar_supp.configure(value=0)
        self.sauvegarde = self.entry_sauve.get()
        self.original = self.entry_orig.get()
        if self.original != self.sauvegarde and self.original and self.sauvegarde:
            if exists(self.original) and exists(self.sauvegarde):
                o_s = (self.original, self.sauvegarde)
                if o_s in RECENT:
                    RECENT.remove(o_s)
                    self.menu_recent.delete("%s -> %s" % o_s)
                RECENT.insert(0, o_s)
                self.menu_recent.insert_command(
                    0,
                    label="%s -> %s" % o_s,
                    command=lambda o=self.original, s=self.sauvegarde: self.
                    open(o, s))
                if len(RECENT) == 10:
                    del (RECENT[-1])
                    self.menu_recent.delete(9)
                save_config()
                self.menu.entryconfigure(0, state="normal")
                self.configure(cursor="watch")
                self.toggle_state_gui()
                self.update_idletasks()
                self.update()
                self.efface_tree()
                err = self.sync(self.original, self.sauvegarde)
                self.configure(cursor="")
                self.toggle_state_gui()
                c = self.tree_copie.get_children("")
                s = self.tree_supp.get_children("")
                if not (c or s):
                    self.menu.entryconfigure(5, state="disabled")
                    self.b_collapse_copie.state(("disabled", ))
                    self.b_expand_copie.state(("disabled", ))
                    self.b_collapse_supp.state(("disabled", ))
                    self.b_expand_supp.state(("disabled", ))
                elif not c:
                    self.b_collapse_copie.state(("disabled", ))
                    self.b_expand_copie.state(("disabled", ))
                elif not s:
                    self.b_collapse_supp.state(("disabled", ))
                    self.b_expand_supp.state(("disabled", ))
                if err:
                    showerror(_("Errors"), "\n".join(err), master=self)
                notification_send(_("Scan is finished."))
                warnings = self.tree_copie.tag_has('warning')
                if warnings:
                    showwarning(
                        _("Warning"),
                        _("Some elements to copy (in red) are not of the same kind on the original and the backup."
                          ),
                        master=self)
            else:
                showerror(_("Error"), _("Invalid path!"), master=self)

    def efface_tree(self):
        """Clear both trees."""
        c = self.tree_copie.get_children("")
        for item in c:
            self.tree_copie.delete(item)
        s = self.tree_supp.get_children("")
        for item in s:
            self.tree_supp.delete(item)
        self.b_collapse_copie.state(("disabled", ))
        self.b_expand_copie.state(("disabled", ))
        self.b_collapse_supp.state(("disabled", ))
        self.b_expand_supp.state(("disabled", ))

    def toggle_state_gui(self):
        """Toggle the state (normal/disabled) of key elements of the GUI."""
        if "disabled" in self.b_open_orig.state():
            state = "!disabled"
            for i in range(7):
                self.menu.entryconfigure(i, state="normal")
        else:
            state = "disabled"
            for i in range(7):
                self.menu.entryconfigure(i, state="disabled")
        self.tree_copie.state((state, ))
        self.tree_supp.state((state, ))
        self.entry_orig.state((state, ))
        self.entry_sauve.state((state, ))
        self.b_expand_copie.state((state, ))
        self.b_collapse_copie.state((state, ))
        self.b_expand_supp.state((state, ))
        self.b_collapse_supp.state((state, ))
        self.b_open_orig.state((state, ))
        self.b_open_sauve.state((state, ))

    def update_pbar(self):
        """
        Dislay the progress of the copy and deletion and put the GUI back in
        normal state once both processes are done.
        """
        if not self.is_running_copie and not self.is_running_supp:
            notification_send(_("Sync is finished."))
            self.toggle_state_gui()
            self.pbar_copie.configure(value=self.pbar_copie.cget("maximum"))
            self.pbar_supp.configure(value=self.pbar_supp.cget("maximum"))
            self.menu.entryconfigure(5, state="disabled")
            self.configure(cursor="")
            self.efface_tree()
            msg = ""
            if self.err_copie:
                msg += _(
                    "There were errors during the copy, see %(file)s for more details.\n"
                ) % {
                    'file': self.log_copie
                }
            if self.err_supp:
                msg += _(
                    "There were errors during the removal, see %(file)s for more details.\n"
                ) % {
                    'file': self.log_supp
                }
            if msg:
                showerror(_("Error"), msg, master=self)
        else:
            if not self.q_copie.empty():
                self.pbar_copie.configure(value=self.q_copie.get())
            if not self.q_supp.empty():
                self.pbar_supp.configure(value=self.q_supp.get())
            self.update()
            self.after(50, self.update_pbar)

    @staticmethod
    def get_list(tree):
        """Return the list of files/folders to copy/delete (depending on the tree)."""
        selected = []

        def aux(item):
            tags = tree.item(item, "tags")
            if "checked" in tags and "whole" in tags:
                selected.append(item)
            elif "checked" in tags or "tristate" in tags:
                ch = tree.get_children(item)
                for c in ch:
                    aux(c)

        ch = tree.get_children("")
        for c in ch:
            aux(c)
        return selected

    def synchronise(self):
        """
        Display the list of files/folders that will be copied / deleted
        and launch the copy and deletion if the user validates the sync.
        """
        # get files to delete and folder to delete if they are empty
        a_supp = self.get_list(self.tree_supp)
        # get files to copy
        a_copier = self.get_list(self.tree_copie)
        a_supp_avant_cp = []
        for ch in self.pb_chemins:
            if ch in a_copier:
                a_supp_avant_cp.append(
                    ch.replace(self.original, self.sauvegarde))
        if a_supp or a_copier:
            Confirmation(self, a_copier, a_supp, a_supp_avant_cp,
                         self.original, self.sauvegarde, self.show_size.get())

    def copie_supp(self, a_copier, a_supp, a_supp_avant_cp):
        """Launch sync."""
        self.toggle_state_gui()
        self.configure(cursor="watch")
        self.update()
        self.pbar_copie.state(("!disabled", ))
        self.pbar_supp.state(("!disabled", ))
        nbtot_copie = len(a_copier) + len(a_supp_avant_cp)
        self.pbar_copie.configure(maximum=nbtot_copie, value=0)
        nbtot_supp = len(a_supp)
        self.pbar_supp.configure(maximum=nbtot_supp, value=0)
        self.is_running_copie = True
        self.is_running_supp = True
        process_copie = Thread(target=self.copie,
                               name="copie",
                               daemon=True,
                               args=(a_copier, a_supp_avant_cp))
        process_supp = Thread(target=self.supp,
                              daemon=True,
                              name="suppression",
                              args=(a_supp, ))
        process_copie.start()
        process_supp.start()
        self.pbar_copie.configure(value=0)
        self.pbar_supp.configure(value=0)
        self.update_pbar()

    def copie(self, a_copier, a_supp_avant_cp):
        """
        Copie tous les fichiers/dossiers de a_copier de original vers
        sauvegarde en utilisant la commande système cp. Les erreurs
        rencontrées au cours du processus sont inscrites dans
        ~/.foldersync/copie.log
        """
        self.err_copie = False
        orig = abspath(self.original) + "/"
        sauve = abspath(self.sauvegarde) + "/"
        chdir(orig)
        self.logger_copie.info(
            _("\n###### Copy: %(original)s -> %(backup)s\n") % {
                'original': self.original,
                'backup': self.sauvegarde
            })
        n = len(a_supp_avant_cp)
        self.logger_copie.info(_("Removal before copy:"))
        for i, ch in zip(range(1, n + 1), a_supp_avant_cp):
            self.logger_copie.info(ch)
            p_copie = run(["rm", "-r", ch], stderr=PIPE)
            self.q_copie.put(i)
            err = p_copie.stderr.decode()
            if err:
                self.err_copie = True
                self.logger_copie.error(err.strip())
        self.logger_copie.info(_("Copy:"))
        for i, ch in zip(range(n + 1, n + 1 + len(a_copier)), a_copier):
            ch_o = ch.replace(orig, "")
            self.logger_copie.info("%s -> %s" % (ch_o, sauve))
            p_copie = run(["cp", "-ra", "--parents", ch_o, sauve], stderr=PIPE)
            self.q_copie.put(i)
            err = p_copie.stderr.decode()
            if err:
                self.err_copie = True
                self.logger_copie.error(err.strip())
        self.is_running_copie = False

    def supp(self, a_supp):
        """
        Supprime tous les fichiers/dossiers de a_supp de original vers
        sauvegarde en utilisant la commande système rm. Les erreurs
        rencontrées au cours du processus sont inscrites dans
        ~/.foldersync/suppression.log.
        """
        self.err_supp = False
        self.logger_supp.info(
            _("\n###### Removal:  %(original)s -> %(backup)s\n") % {
                'original': self.original,
                'backup': self.sauvegarde
            })
        for i, ch in enumerate(a_supp):
            self.logger_supp.info(ch)
            p_supp = run(["rm", "-r", ch], stderr=PIPE)
            self.q_supp.put(i + 1)
            err = p_supp.stderr.decode()
            if err:
                self.logger_supp.error(err.strip())
                self.err_supp = True
        self.is_running_supp = False

    def unlink(self):
        """Unlink pidfile."""
        unlink(self.pidfile)

    def change_language(self):
        """Change app language."""
        CONFIG.set("Defaults", "language", self.langue.get())
        showinfo(
            _("Information"),
            _("The language setting will take effect after restarting the application"
              ))
Пример #25
0
    """
    print(text)
    index = int(index)
    if text.isupper() and index == 0:
        return True
    if input in (",", ".", "'", " ") and index > 0:
        return True
    if inp.isalnum() and index > 0:
        return True
    if text == "":
        return True
    else:
        return False


vcmd = root.register(is_okay)

entsv = StringVar()
ent0 = Entry(lf0,
             validate='key',
             validatecommand=(vcmd, '%P', '%S', '%i'),
             textvariable=entsv)
ent0.bind("<Return>", end_input)
ent0.grid(row=1, column=0, padx=10)
ent0.focus()

mess_lbl = Label(lf0, text='Start with capital letter, <Return> to confirm')
mess_lbl.grid(row=2, column=0, pady=10, padx=10)

root.mainloop()
Пример #26
0
class SettingsUI:
    
    def __init__(self, mainFrame):
        "initiates settings and creates the interface"
        self.playerList = []
        self.gameList = ("301", "501", "Clock")
        self.initUI(mainFrame)
        
    
    def buildPlayerHeaderString(self):
        """Build a connection string from a dictionary of parameters.
    
        Returns string."""
        return "Players: " + ", ".join(["%s" % player.name for player in self.playerList])
    
    def addPlayerText(self, name):
        self.playerList.append(Player(name))
        
        #bind add player click event
    def onAddPlayerClick(self, event):
        "callback method for the add player button"
        self.addPlayer()
    
    def onAddPlayerEnter(self, event):
        "callback method for the add player button"
        if event.keycode == 13:
            self.addPlayer()
            
    def addPlayer(self):
        name = self.playerNameEntry.get()
        if name:
            self.addPlayerText(name)
            self.playerString.set(self.buildPlayerHeaderString())
            self.nameFieldVar.set("")
            self.playerNameEntry.focus()
        return("break")
     
    def initUI(self, mainFrame):
        """initialize the User Interface"""
        
        # styles
        style = Style()
        style.configure("GRN.TLabel", background="#ACF059")
        style.configure("GRN.TFrame", background="#ACF059")
        style.configure("BLK.TFrame", background="#595959")
        
        
        # create top frame
        topFrame = Frame(mainFrame, style="GRN.TFrame", padding=8)
        topFrame.pack(fill=BOTH, side=TOP)
        
        # create black border
        borderFrame = Frame(mainFrame, style="BLK.TFrame")
        borderFrame.pack(fill=BOTH, side=TOP)
        
        # create add player frame
        addPlayerFrame = Frame(mainFrame, padding=8)
        addPlayerFrame.pack(side=TOP)
        
        # create text field for add button
        self.nameFieldVar = StringVar()
        self.playerNameEntry = Entry(addPlayerFrame, textvariable = self.nameFieldVar)
        self.playerNameEntry.pack(side=LEFT)
        # create add player button
        addButton = Button(addPlayerFrame, text="Add player")
        addButton.pack(side=LEFT)
        
        # create choose game list
        self.currentGame = StringVar()
        self.currentGame.set(self.gameList[0])
        gameDropDown = OptionMenu(mainFrame, self.currentGame, self.gameList[0], *self.gameList)
        gameDropDown.pack(side=TOP)

        # create start game button
        startGameButton = Button(mainFrame, text="Start")
        
        startGameButton.bind("<Button-1>", self.startGame)
        startGameButton.pack(side=TOP)
        
        # create label and set text
        self.playerString = StringVar()
        self.playerString.set(self.buildPlayerHeaderString())
        headerLabel = Label(topFrame, textvariable=self.playerString, style="GRN.TLabel")
        headerLabel.pack(side=TOP)     
        addButton.bind("<Button-1>", self.onAddPlayerClick)
        self.playerNameEntry.bind("<Key>", self.onAddPlayerEnter)
        
        #set focus
        self.playerNameEntry.focus()
        
    def startGame(self,event):
        "starts the selected game"
        if self.playerList:
            mainFrame.pack_forget()
            gameFrame = Frame(root)
            gameFrame.pack(fill=BOTH, expand=1)
                
            game = self.currentGame.get()
            if game == "301":
                gameX01.GameX01(gameFrame, self.playerList)
            elif game == "501":                    
                gameX01.GameX01(gameFrame, self.playerList, 501)
            elif game == "Clock":
                gameClock.GameClock(gameFrame, self.playerList)
            else:
                gameX01.GameX01(gameFrame, self.playerList)
Пример #27
0
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.player = StringVar()
        self.character = StringVar()
        self.dm = StringVar()
        self.str = StringVar()
        self.int = StringVar()
        self.wis = StringVar()
        self.dex = StringVar()
        self.con = StringVar()
        self.cha = StringVar()
        self.JPpoison = StringVar()
        self.JPwands = StringVar()
        self.JPparalysis = StringVar()
        self.JPbreath = StringVar()
        self.JPspell = StringVar()
        self.class_ = StringVar()
        self.race = StringVar()
        self.align = StringVar()
        self.AC = StringVar()
        self.HP = StringVar()
        self.maxHP = StringVar()
        self.XP_to_add = StringVar()
        self.XPbonus = StringVar()
        self.XPtotal = IntVar()
        self.level = StringVar()

        self.init_once()

        (
            self.baseXP,
            self.mainCarRace,
            self.mainCarClass) = self.classDifferenciation()
        self.remainingXP = StringVar()
        self.remainingXP.set(self.getRemainingXP())
        self.bonusXP = StringVar()
        self.bonusXP.set(self.getBonusXP())

        self.freeze = IntVar()
        self.freeze.set(1)

        Label(self, text="Player Name:").grid(row=0, column=0, columnspan=2)
        Label(self, text="Character Name :").grid(
            row=0, column=4, columnspan=2)
        Label(self, text="DM Name:").grid(row=0, column=8, columnspan=2)
        Label(self, text="STR:").grid(row=1, column=0)
        Label(self, text="INT:").grid(row=2, column=0)
        Label(self, text="WIS:").grid(row=3, column=0)
        Label(self, text="DEX:").grid(row=4, column=0)
        Label(self, text="CON:").grid(row=5, column=0)
        Label(self, text="CHA:").grid(row=6, column=0)
        Label(self, text="Poison/Deathray:").grid(row=1, column=2)
        Label(self, text="Wands:").grid(row=2, column=2)
        Label(self, text="Paralysis:").grid(row=3, column=2)
        Label(self, text="Dragon Breath:").grid(row=4, column=2)
        Label(self, text="Spells:").grid(row=5, column=2)
        Label(self, text="Armor Class").grid(row=1, column=4, columnspan=1)
        Label(self, text="Health Points").grid(row=1, column=5, columnspan=3)
        Label(self, text="  /  ").grid(row=2, column=6)
        Label(self, text="Class :").grid(row=3, column=4)
        Label(self, text="Race :").grid(row=4, column=4)
        Label(self, text="XP to add :").grid(row=7, column=0)
        Label(self, text="Remaining :").grid(row=8, column=0)
        Label(self, text="Bonus :").grid(row=7, column=2)
        Label(self, text="Alignment :").grid(row=3, column=6)
        Label(self, text="Level :").grid(row=9, column=0, columnspan=2)
        self.remainingLabel = Label(
            self,
            textvariable=self.remainingXP,
            relief=SUNKEN,
            width=5)
        self.remainingLabel.grid(row=8, column=1)
        self.bonusLabel = Label(
            self,
            textvariable=self.bonusXP,
            relief=SUNKEN,
            width=5)
        self.bonusLabel.grid(row=7, column=3)
        self.levelLabel = Label(
            self,
            textvariable=self.level,
            relief=SUNKEN,
            width=5)
        self.levelLabel.grid(row=9, column=2, columnspan=2)

        Eplayer = Entry(self, textvariable=self.player)
        Eplayer.grid(row=0, column=2, columnspan=2)
        Eplayer.bind(sequence='<KeyRelease>', func=self.refresh)

        Echaracter = Entry(self, textvariable=self.character)
        Echaracter.grid(row=0, column=6, columnspan=2)
        Echaracter.bind(sequence='<KeyRelease>', func=self.refresh)

        EDM = Entry(self, textvariable=self.dm)
        EDM.grid(row=0, column=10, columnspan=2)
        EDM.bind(sequence='<KeyRelease>', func=self.refresh)

        Estr = Entry(self, textvariable=self.str)
        Estr.grid(row=1, column=1)
        Estr.bind(sequence='<KeyRelease>', func=self.refresh)

        Eint = Entry(self, textvariable=self.int)
        Eint.grid(row=2, column=1)
        Eint.bind(sequence='<KeyRelease>', func=self.refresh)

        Ewis = Entry(self, textvariable=self.wis)
        Ewis.grid(row=3, column=1)
        Ewis.bind(sequence='<KeyRelease>', func=self.refresh)

        Edex = Entry(self, textvariable=self.dex)
        Edex.grid(row=4, column=1)
        Edex.bind(sequence='<KeyRelease>', func=self.refresh)

        Econ = Entry(self, textvariable=self.con)
        Econ.grid(row=5, column=1)
        Econ.bind(sequence='<KeyRelease>', func=self.refresh)

        Echa = Entry(self, textvariable=self.cha)
        Echa.grid(row=6, column=1)
        Echa.bind(sequence='<KeyRelease>', func=self.refresh)

        Entry(self, textvariable=self.JPpoison).grid(row=1, column=3)
        Entry(self, textvariable=self.JPwands).grid(row=2, column=3)
        Entry(self, textvariable=self.JPparalysis).grid(row=3, column=3)
        Entry(self, textvariable=self.JPbreath).grid(row=4, column=3)
        Entry(self, textvariable=self.JPspell).grid(row=5, column=3)
        Entry(self, textvariable=self.AC).grid(row=2, column=4)
        Entry(self, textvariable=self.HP).grid(row=2, column=5)
        Entry(self, textvariable=self.maxHP).grid(row=2, column=7)

        EXP = Entry(self, textvariable=self.XP_to_add)
        EXP.grid(row=7, column=1)
        EXP.bind(sequence='<KeyPress-Return>', func=self.addXP)

        OptionMenu(
            self, self.class_,
            "Class",
            "Warrior",
            "Wizard",
            "Thief",
            "Cleric").grid(row=3, column=5)
        OptionMenu(
            self, self.align,
            "Alignment",
            "Lawful Good",
            "Lawful Neutral",
            "Lawful Evil",
            "Neutral Good",
            "Neutral Neutral",
            "Neutral Evil",
            "Chaotic Good",
            "Chaotic Neutral",
            "Chaotic Evil").grid(row=3, column=7)
        OptionMenu(
            self, self.race,
            "Race",
            "Human",
            "Elf",
            "Dwarf",
            "Halfelin").grid(row=4, column=5)

        Button(
            self,
            text="Add XP",
            command=self.refresh,
            width=6).grid(row=10, column=3)
Пример #28
0
def _gui():
  try:
    from tkinter import Tk, ttk, filedialog, messagebox, StringVar, IntVar
    from tkinter.ttk import Button, Entry, Frame, Label, LabelFrame, Notebook, Radiobutton, Style
  except:
    sys.exit("Unable to load tkinter. Aborting.")
  
  def _check_single(): #check the input and accordingly give the output... for the f_single tab
    if txt_f_single_entry.get()=="":
      lbl_f_single_result.config(text="", style="TLabel")
    elif check_afm(txt_f_single_entry.get()):
      lbl_f_single_result.config(text="Έγκυρο ΑΦΜ.", style="valid.TLabel")
    else:
      lbl_f_single_result.config(text="Άκυρο ΑΦΜ.", style="invalid.TLabel")
  
  def _select_input_file():
    strv_f_file_input.set(filedialog.askopenfilename(title="Άνοιγμα αρχείου"))
    if strv_f_file_input.get() != "" and strv_f_file_output.get() != "":
      btn_f_file_submit.config(state="normal")
    else: btn_f_file_submit.config(state="disabled")
#TODO a much better mechanism to enable / disable btn_f_file_submit is needed.
  def _select_output_file():
    strv_f_file_output.set(filedialog.asksaveasfilename(title="Αποθήκευση ως..."))
    if strv_f_file_input.get() != "" and strv_f_file_output.get() != "":
      btn_f_file_submit.config(state="normal")
    else: btn_f_file_submit.config(state="disabled")
  
  def _check_file():#TODO this could / should be merged with the TUI version...
    input_filepath = strv_f_file_input.get()
    output_filepath = strv_f_file_output.get()
    filter_output = intvar_filter_sel.get()
    try:
      input_file = open(input_filepath, "r")
      output_file = open(output_filepath, "w")
    except:
      messagebox.showerror(title="Σφάλμα", message="Αδυναμία διαχείρησης των αρχείων που ορίσατε.\n\nΠαρακαλώ επιβεβαιώστε πως το αρχείο με τα δεδομένα υπάρχει, πως έχετε δικαιώματα ανάγνωσης, και πως έχετε δικαιώματα εγγραφής στον κατάλογο εξαγωγής των αποτελεσμάτων.")
      return
    counter = {True:0, False:0}
    for entry in input_file:
      validation = check_afm(entry.strip())
      counter[validation]+=1
      if filter_output == 3 and validation == False:
        output_file.write(entry)
      elif filter_output == 2 and validation == True:
        output_file.write(entry)
      elif filter_output == 1:
        output_file.write(entry.strip() + "\t" + str(validation) + "\n\r")
    lbl_f_file_result.config(text="Σύνολο: "+str(counter[True]+counter[False])+"\nΈγκυρα: "+str(counter[True])+"\nΆκυρα: "+str(counter[False]))

  #create the window
  main_window = Tk()
  main_window.title("Έλεγχος εγκυρότητας Α.Φ.Μ. (v 2.0)")
  main_window.geometry("600x180")
  main_window.minsize(600,180)

  #fool arround with styling
  style = ttk.Style()
  style.configure("valid.TLabel", background="green")
  style.configure("empty.TLabel", background="white")
  style.configure("invalid.TLabel", background="red")
  style.configure("TNotebook", padding = 10)
  
  #create the Notebook
  tabs = Notebook(main_window)
  f_single = Frame(tabs)
  f_file = Frame(tabs)
  tabs.add(f_single, text="Μεμονομένα Α.Φ.Μ.")
  tabs.add(f_file, text="Λίστα από αρχείο")#add state="disabled" prior to git push until ready
  tabs.pack(anchor="nw")
  
  #add some widgets in f_single tab
  lbl_f_single_instructions = Label(f_single, text="Εισάγετε έναν ΑΦΜ για έλεγχο")
  lbl_f_single_instructions.grid(column=0, row=0)

  lbl_f_single_result = Label(f_single, text="", width=10, justify="center")
  lbl_f_single_result.grid(column=1, row=0, rowspan=2, sticky="ewns")

  txt_f_single_entry = Entry(f_single, width=11)
  txt_f_single_entry.focus()
  txt_f_single_entry.bind("<KeyRelease>", lambda e: _check_single() )
  txt_f_single_entry.grid(column=0,row=1)

  #btn_f_single_submit = Button(f_single, text="Έλεγχος", command=_check_single)
  #btn_f_single_submit.grid(column=0,row=2)
    
  #add some widgets in f_file tab
  lbl_f_file_finput = Label(f_file, text="Άνοιγμα...")
  lbl_f_file_finput.grid(column=0, row=0)
  strv_f_file_input = StringVar()
  txt_f_file_finput = Entry(f_file, textvariable = strv_f_file_input)
  txt_f_file_finput.grid(column=1, row=0)
  btn_f_file_finput = Button(f_file, text="...", width=3, command=_select_input_file)
  btn_f_file_finput.grid(column=2, row=0, sticky="W")
  
  lbl_f_file_foutput = Label(f_file, text="Αποθήκευση ως...")
  lbl_f_file_foutput.grid(column=0, row=1)
  strv_f_file_output = StringVar()
  txt_f_file_foutput = Entry(f_file, textvariable = strv_f_file_output)
  txt_f_file_foutput.grid(column=1, row=1)
  btn_f_file_foutput = Button(f_file, text="...", width=3, command=_select_output_file)
  btn_f_file_foutput.grid(column=2, row=1, sticky="W")
  
  lf_filter = LabelFrame(f_file, text="Επιστροφή")
  lf_filter.grid(column=3, row=0, rowspan=2, sticky="ewns")
  intvar_filter_sel = IntVar()
  rb_filter_all = Radiobutton(lf_filter, text="Όλων", variable=intvar_filter_sel, value=1) #TODO maybe add command
  rb_filter_all.pack(anchor="w")
  rb_filter_all.invoke()
  rb_filter_true = Radiobutton(lf_filter, text="Έγκυρων", variable=intvar_filter_sel, value=2)
  rb_filter_true.pack(anchor="w")
  rb_filter_false = Radiobutton(lf_filter, text="Άκυρων", variable=intvar_filter_sel, value=3)
  rb_filter_false.pack(anchor="w")
  
  lf_result = LabelFrame(f_file, text="Σύνοψη")
  lf_result.grid(column=4, row=0, rowspan=2, sticky="ewns")
  lbl_f_file_result = Label(lf_result, text="", width=12)#TODO bring results
  lbl_f_file_result.pack()
  
  btn_f_file_submit = Button(f_file, text="Επεξεργασία", state="disabled", command=_check_file)
  btn_f_file_submit.grid(column=0, row=2, columnspan=3)
  
  btn_main_exit = Button(main_window, text="Έξοδος", command=sys.exit)
  btn_main_exit.pack(anchor="se")

  main_window.mainloop()
    def __init__(self):
        """__init__ creates the tkinter gui"""
        self.__settings = {}
        self.__importer = CsvXmlImporter()

        # ***--*** main window and menu band ***---***
        self.__root = ThemedTk(theme=theme)
        self.__root.title("Csv/Xml Importer")
        self.__root.minsize(560, 1)
        menu = Menu(self.__root)
        self.__root.config(menu=menu)

        filemenu = Menu(menu, tearoff=0)
        menu.add_cascade(label="File", menu=filemenu)
        filemenu.add_command(label="Add Files", command=self.add_files)
        filemenu.add_command(label="Remove All", command=self.remove_all)
        filemenu.add_separator()
        filemenu.add_command(label="Add xsl File", command=self.add_xslfile)
        filemenu.add_separator()
        filemenu.add_command(label="Exit", command=self.exit)

        helpmenu = Menu(menu, tearoff=0)
        menu.add_cascade(label="Help", menu=helpmenu)
        helpmenu.add_command(label="?", command=self.ask_help)
        helpmenu.add_command(label="About", command=self.ask_about)

        # ***---*** source file frame dialog ***---***
        srcfilesframe = LabelFrame(self.__root, text="Sourcefiles")
        buttonframe = Frame(srcfilesframe)
        addbutton = Button(buttonframe,
                           text="Add Files",
                           command=self.add_files)
        addbutton.pack(fill=X)
        removefilesbutton = Button(buttonframe,
                                   text="Remove Selected",
                                   command=self.remove_files)
        removefilesbutton.pack(fill=X)
        removeallbutton = Button(buttonframe,
                                 text="Remove All",
                                 command=self.remove_all)
        removeallbutton.pack(fill=X)
        buttonframe.grid(column=1, row=1)
        self.__srcfileslistbox = Listbox(srcfilesframe,
                                         selectmode="extended",
                                         width=100,
                                         height=5)
        self.__srcfileslistbox.grid(column=2, row=1)

        Label(srcfilesframe, text="Encoding").grid(column=1, row=2, sticky=E)
        self.__settings["encoding"] = StringVar()
        self.__settings["encoding"].trace_add("write", self.update_settings)
        encCombobox = Combobox(srcfilesframe,
                               textvariable=self.__settings["encoding"],
                               values=encodings,
                               state="readonly")
        encCombobox.bind("<FocusOut>", self.update_settings)
        encCombobox.grid(column=2, row=2, pady=10)
        srcfilesframe.pack(fill=X)

        # ***---*** xsl file dialog ***---***
        xslfileframe = LabelFrame(self.__root, text="XSL-File")
        Button(xslfileframe, text="Add .xsl",
               command=self.add_xslfile).grid(column=1, row=1)
        self.__xsllistbox = Listbox(xslfileframe, width=100, height=1)
        self.__xsllistbox.grid(column=2, row=1, sticky="w")
        buttonframe = Frame(xslfileframe)
        Button(buttonframe,
               text="Apply Parameter",
               command=self.apply_xslparameter).pack(fill=X)
        Button(buttonframe,
               text="Restore Default",
               command=self.reset_xslparameter).pack(fill=X)
        buttonframe.grid(column=1, row=2)
        box = Frame(xslfileframe)
        self.__xslparametertext = Text(box, height=3, width=75)
        self.__xslparametertext.grid(column=0, row=1, sticky="nsew")
        scrollbar = Scrollbar(box, command=self.__xslparametertext.yview)
        scrollbar.grid(column=0, row=1, sticky="nse")
        box.grid(column=2, row=2, sticky="we")
        self.__xslparametertext["yscrollcommand"] = scrollbar.set
        xslfileframe.pack(fill=X)

        # ***---*** file format settings dialog ***---***
        # small help function
        def limit_character(entry_text):
            """limit_characters cuts down the characters of an entry text to one"""
            if len(entry_text.get()) > 0:
                # take only last input character and throw away the rest
                entry_text.set(entry_text.get()[-1])

        fileformatsettingsframe = LabelFrame(self.__root,
                                             text="File Format Settings")

        Label(fileformatsettingsframe, text="Delimiter").grid(column=1,
                                                              row=1,
                                                              sticky=E)
        self.__settings["delimiter"] = StringVar()
        seperatorentry = Entry(fileformatsettingsframe,
                               textvariable=self.__settings["delimiter"],
                               width=1)
        self.__settings["delimiter"].trace_add(
            "write", lambda *_: limit_character(self.__settings["delimiter"]))
        seperatorentry.bind("<Return>", self.update_settings)
        seperatorentry.bind("<FocusOut>", self.update_settings)
        seperatorentry.grid(column=2, row=1, sticky=W, padx=15)

        Label(fileformatsettingsframe, text="Quotechar").grid(column=1,
                                                              row=2,
                                                              sticky=E)
        self.__settings["quotechar"] = StringVar()
        quotecharentry = Entry(fileformatsettingsframe,
                               textvariable=self.__settings["quotechar"],
                               width=1)
        self.__settings["quotechar"].trace_add(
            "write", lambda *_: limit_character(self.__settings["quotechar"]))
        quotecharentry.bind("<Return>", self.update_settings)
        quotecharentry.bind("<FocusOut>", self.update_settings)
        quotecharentry.grid(column=2, row=2, sticky=W, padx=15)

        Label(fileformatsettingsframe, text="Doublequote").grid(column=1,
                                                                row=3,
                                                                sticky=E)
        self.__settings["doublequote"] = BooleanVar()
        Checkbutton(fileformatsettingsframe,
                    variable=self.__settings["doublequote"],
                    command=self.update_settings).grid(column=2,
                                                       row=3,
                                                       sticky=W,
                                                       padx=10)

        Label(fileformatsettingsframe, text="Quoting").grid(column=1,
                                                            row=5,
                                                            sticky=E)
        quotingopt = {"minimal": 0, "all": 1, "non numeric": 2, "none": 3}
        self.__settings["quoting"] = IntVar()
        for i, (key, value) in enumerate(quotingopt.items()):
            Radiobutton(
                fileformatsettingsframe,
                text=key,
                value=value,
                variable=self.__settings["quoting"],
                command=self.update_settings,
            ).grid(
                column=2 + i,
                row=5,
                padx=10,
                sticky=W,
            )

        Label(fileformatsettingsframe,
              text="Ignore spaces at beginning").grid(column=1,
                                                      row=6,
                                                      sticky=E)
        self.__settings["skipinitialspace"] = BooleanVar()
        self.__settings["skipinitialspace"].set(False)
        Checkbutton(fileformatsettingsframe,
                    variable=self.__settings["skipinitialspace"],
                    command=self.update_settings).grid(column=2,
                                                       row=6,
                                                       sticky=W,
                                                       padx=10)

        fileformatsettingsframe.pack(fill=X)

        # ***---*** preview frame ***---***
        previewframe = LabelFrame(self.__root, text="Preview")
        self.__pdtable = Table(parent=previewframe,
                               dataframe=self.__importer.dfx)
        self.__pdtable.show()
        previewframe.pack(fill="both", expand=True)

        # ***---*** export button ***---***
        exportframe = LabelFrame(self.__root, text="Export")
        Button(exportframe, text="Export",
               command=self.create_exportdialog).pack()
        exportframe.pack(fill="both", expand=True)

        # save settings to check for changes on update
        self.__prevsettings = self.__unpack_settings(self.__settings)
Пример #30
0
def entry_float(parent, lf_text, l_limit, u_limit, mess_text, out_var):
    """Float layout for entry

    Parameters
    ----------
    parent : str
        parent handle
    lf_text : str
        text on LabelFrame
    l_limit : float
        lower limit
    u_limit : float
        upper limit
    mess_text : str
        message
    out_var : float
        tkvar handle

    Returns
    -------
    float
    """
    st1 = Style()
    st1.theme_use('default')

    st1.configure('brown.TLabelframe', background='#C9B99B')
    st1.configure('brown.TLabelframe.Label', background='#EDEF77')
    st1.configure('brown.TLabel', background='#EDEF77')
    st1.configure('lowr.TLabel', background='lightblue')
    st1.configure('upr.TLabel', background='red')

    lf0 = Labelframe(parent, text=lf_text, style='brown.TLabelframe')
    lf0.grid(row=0, column=0, padx=10, pady=10)

    ulab = Label(lf0,
                 text=str(u_limit) + "  upper limit",
                 style='brown.TLabel')
    ulab.grid(row=0, column=1, padx=10)
    llab = Label(lf0,
                 text=str(l_limit) + "  lower limit",
                 style='brown.TLabel')
    llab.grid(row=2, column=1, padx=10)

    def end_input(_evt):
        """limit on float

        Parameters
        ----------
        evt : str
            bind handle

        Returns
        -------
        None
        """
        ulab['style'] = 'brown.TLabel'
        llab['style'] = 'brown.TLabel'
        if l_limit < entsv.get() < u_limit:
            messlbl['text'] = "That's OK"
            out_var.set(entsv.get())
        elif l_limit >= entsv.get():
            messlbl['text'] = "Input below lower limit"
            llab['style'] = 'lowr.TLabel'
        else:
            messlbl['text'] = "Input above upper limit"
            ulab['style'] = 'upr.TLabel'

    def is_okay(text):
        """ validation function

        Parameters
        ----------
        text : str
            text if allowed

        Returns
        -------
        boolean
        """
        if text in ("", "-", ".", "-."):
            return True
        try:
            float(text)
        except ValueError:
            return False
        return True

    vcmd = lf0.register(is_okay)

    entsv = DoubleVar()
    ent0 = Entry(lf0,
                 validate='key',
                 validatecommand=(vcmd, '%P'),
                 textvariable=entsv)
    ent0.bind("<Return>", end_input)
    ent0.grid(row=1, column=0, padx=10)
    ent0.focus()

    messlbl = Label(lf0, text=mess_text, style='brown.TLabel')
    messlbl.grid(row=2, column=0, pady=10, padx=10)
Пример #31
0
class Sticky(Toplevel):
    """ Sticky note class """
    def __init__(self, master, key, **kwargs):
        """ Create a new sticky note.
            master: main app
            key: key identifying this note in master.note_data
            kwargs: dictionnary of the other arguments
            (title, txt, category, color, tags, geometry, locked, checkboxes,
             images, rolled)
        """
        Toplevel.__init__(self, master)
        # --- window properties
        self.id = key
        self.is_locked = not (kwargs.get("locked", False))
        self.images = []
        self.links = {}
        self.latex = {}
        self.nb_links = 0
        self.title('mynotes%s' % key)
        self.attributes("-type", "splash")
        self.attributes("-alpha", CONFIG.getint("General", "opacity") / 100)
        self.focus_force()
        # window geometry
        self.update_idletasks()
        self.geometry(kwargs.get("geometry", '220x235'))
        self.save_geometry = kwargs.get("geometry", '220x235')
        self.update()
        self.rowconfigure(1, weight=1)
        self.minsize(10, 10)
        self.protocol("WM_DELETE_WINDOW", self.hide)

        # --- style
        self.style = Style(self)
        self.style.configure(self.id + ".TCheckbutton", selectbackground="red")
        self.style.map('TEntry', selectbackground=[('!focus', '#c3c3c3')])
        selectbg = self.style.lookup('TEntry', 'selectbackground', ('focus', ))
        self.style.configure("sel.TCheckbutton", background=selectbg)
        self.style.map("sel.TCheckbutton", background=[("active", selectbg)])

        # --- note elements
        # title
        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)

        self.title_var = StringVar(master=self,
                                   value=kwargs.get("title", _("Title")))
        self.title_label = Label(self,
                                 textvariable=self.title_var,
                                 anchor="center",
                                 style=self.id + ".TLabel",
                                 font=font_title)
        self.title_entry = Entry(self,
                                 textvariable=self.title_var,
                                 exportselection=False,
                                 justify="center",
                                 font=font_title)
        # buttons/icons
        self.roll = Label(self, image="img_roll", style=self.id + ".TLabel")
        self.close = Label(self, image="img_close", style=self.id + ".TLabel")
        self.im_lock = PhotoImage(master=self, file=IM_LOCK)
        self.cadenas = Label(self, style=self.id + ".TLabel")
        # corner grip
        self.corner = Sizegrip(self, style=self.id + ".TSizegrip")
        # texte
        font_text = "%s %s" % (CONFIG.get("Font", "text_family").replace(
            " ", "\ "), CONFIG.get("Font", "text_size"))
        self.txt = Text(self,
                        wrap='word',
                        undo=True,
                        selectforeground='white',
                        inactiveselectbackground=selectbg,
                        selectbackground=selectbg,
                        tabs=(10, 'right', 21, 'left'),
                        relief="flat",
                        borderwidth=0,
                        highlightthickness=0,
                        font=font_text)
        # tags
        self.txt.tag_configure("bold", font="%s bold" % font_text)
        self.txt.tag_configure("italic", font="%s italic" % font_text)
        self.txt.tag_configure("bold-italic",
                               font="%s bold italic" % font_text)
        self.txt.tag_configure("underline",
                               underline=True,
                               selectforeground="white")
        self.txt.tag_configure("overstrike",
                               overstrike=True,
                               selectforeground="white")
        self.txt.tag_configure("center", justify="center")
        self.txt.tag_configure("left", justify="left")
        self.txt.tag_configure("right", justify="right")
        self.txt.tag_configure("link",
                               foreground="blue",
                               underline=True,
                               selectforeground="white")
        self.txt.tag_configure("list",
                               lmargin1=0,
                               lmargin2=21,
                               tabs=(10, 'right', 21, 'left'))
        self.txt.tag_configure("todolist",
                               lmargin1=0,
                               lmargin2=21,
                               tabs=(10, 'right', 21, 'left'))
        margin = 2 * Font(self, font=font_text).measure("m")
        self.txt.tag_configure("enum",
                               lmargin1=0,
                               lmargin2=margin + 5,
                               tabs=(margin, 'right', margin + 5, 'left'))

        for coul in TEXT_COLORS.values():
            self.txt.tag_configure(coul,
                                   foreground=coul,
                                   selectforeground="white")
            self.txt.tag_configure(coul + "-underline",
                                   foreground=coul,
                                   selectforeground="white",
                                   underline=True)
            self.txt.tag_configure(coul + "-overstrike",
                                   foreground=coul,
                                   overstrike=True,
                                   selectforeground="white")
        # --- menus
        # --- * menu on title
        self.menu = Menu(self, tearoff=False)
        # note color
        menu_note_color = Menu(self.menu, tearoff=False)
        colors = list(COLORS.keys())
        colors.sort()
        for coul in colors:
            menu_note_color.add_command(
                label=coul, command=lambda key=coul: self.change_color(key))
        # category
        self.category = StringVar(
            self,
            kwargs.get("category", CONFIG.get("General", "default_category")))
        self.menu_categories = Menu(self.menu, tearoff=False)
        categories = CONFIG.options("Categories")
        categories.sort()
        for cat in categories:
            self.menu_categories.add_radiobutton(label=cat.capitalize(),
                                                 value=cat,
                                                 variable=self.category,
                                                 command=self.change_category)
        # position: normal, always above, always below
        self.position = StringVar(
            self, kwargs.get("position", CONFIG.get("General", "position")))
        menu_position = Menu(self.menu, tearoff=False)
        menu_position.add_radiobutton(label=_("Always above"),
                                      value="above",
                                      variable=self.position,
                                      command=self.set_position_above)
        menu_position.add_radiobutton(label=_("Always below"),
                                      value="below",
                                      variable=self.position,
                                      command=self.set_position_below)
        menu_position.add_radiobutton(label=_("Normal"),
                                      value="normal",
                                      variable=self.position,
                                      command=self.set_position_normal)
        # mode: note, list, todo list
        menu_mode = Menu(self.menu, tearoff=False)
        self.mode = StringVar(self, kwargs.get("mode", "note"))
        menu_mode.add_radiobutton(label=_("Note"),
                                  value="note",
                                  variable=self.mode,
                                  command=self.set_mode_note)
        menu_mode.add_radiobutton(label=_("List"),
                                  value="list",
                                  variable=self.mode,
                                  command=self.set_mode_list)
        menu_mode.add_radiobutton(label=_("ToDo List"),
                                  value="todolist",
                                  variable=self.mode,
                                  command=self.set_mode_todolist)
        menu_mode.add_radiobutton(label=_("Enumeration"),
                                  value="enum",
                                  variable=self.mode,
                                  command=self.set_mode_enum)

        self.menu.add_command(label=_("Delete"), command=self.delete)
        self.menu.add_cascade(label=_("Category"), menu=self.menu_categories)
        self.menu.add_cascade(label=_("Color"), menu=menu_note_color)
        self.menu.add_command(label=_("Lock"), command=self.lock)
        self.menu.add_cascade(label=_("Position"), menu=menu_position)
        self.menu.add_cascade(label=_("Mode"), menu=menu_mode)

        # --- * menu on main text
        self.menu_txt = Menu(self.txt, tearoff=False)
        # style
        menu_style = Menu(self.menu_txt, tearoff=False)
        menu_style.add_command(label=_("Bold"),
                               command=lambda: self.toggle_text_style("bold"))
        menu_style.add_command(
            label=_("Italic"),
            command=lambda: self.toggle_text_style("italic"))
        menu_style.add_command(label=_("Underline"),
                               command=self.toggle_underline)
        menu_style.add_command(label=_("Overstrike"),
                               command=self.toggle_overstrike)
        # text alignment
        menu_align = Menu(self.menu_txt, tearoff=False)
        menu_align.add_command(label=_("Left"),
                               command=lambda: self.set_align("left"))
        menu_align.add_command(label=_("Right"),
                               command=lambda: self.set_align("right"))
        menu_align.add_command(label=_("Center"),
                               command=lambda: self.set_align("center"))
        # text color
        menu_colors = Menu(self.menu_txt, tearoff=False)
        colors = list(TEXT_COLORS.keys())
        colors.sort()
        for coul in colors:
            menu_colors.add_command(label=coul,
                                    command=lambda key=coul: self.
                                    change_sel_color(TEXT_COLORS[key]))

        # insert
        menu_insert = Menu(self.menu_txt, tearoff=False)
        menu_insert.add_command(label=_("Symbols"), command=self.add_symbols)
        menu_insert.add_command(label=_("Checkbox"), command=self.add_checkbox)
        menu_insert.add_command(label=_("Image"), command=self.add_image)
        menu_insert.add_command(label=_("Date"), command=self.add_date)
        menu_insert.add_command(label=_("Link"), command=self.add_link)
        if LATEX:
            menu_insert.add_command(label="LaTex", command=self.add_latex)

        self.menu_txt.add_cascade(label=_("Style"), menu=menu_style)
        self.menu_txt.add_cascade(label=_("Alignment"), menu=menu_align)
        self.menu_txt.add_cascade(label=_("Color"), menu=menu_colors)
        self.menu_txt.add_cascade(label=_("Insert"), menu=menu_insert)

        # --- restore note content/appearence
        self.color = kwargs.get("color",
                                CONFIG.get("Categories", self.category.get()))
        self.txt.insert('1.0', kwargs.get("txt", ""))
        self.txt.edit_reset()  # clear undo stack
        # restore inserted objects (images and checkboxes)
        # we need to restore objects with increasing index to avoid placment errors
        indexes = list(kwargs.get("inserted_objects", {}).keys())
        indexes.sort(key=sorting)
        for index in indexes:
            kind, val = kwargs["inserted_objects"][index]
            if kind == "checkbox":
                ch = Checkbutton(self.txt,
                                 takefocus=False,
                                 style=self.id + ".TCheckbutton")
                if val:
                    ch.state(("selected", ))
                self.txt.window_create(index, window=ch)

            elif kind == "image":
                if os.path.exists(val):
                    self.images.append(PhotoImage(master=self.txt, file=val))
                    self.txt.image_create(index,
                                          image=self.images[-1],
                                          name=val)
        # restore tags
        for tag, indices in kwargs.get("tags", {}).items():
            if indices:
                self.txt.tag_add(tag, *indices)

        for link in kwargs.get("links", {}).values():
            self.nb_links += 1
            self.links[self.nb_links] = link
            self.txt.tag_bind("link#%i" % self.nb_links,
                              "<Button-1>",
                              lambda e, l=link: open_url(l))

        for img, latex in kwargs.get("latex", {}).items():
            self.latex[img] = latex
            if LATEX:
                self.txt.tag_bind(img,
                                  '<Double-Button-1>',
                                  lambda e, im=img: self.add_latex(im))
        mode = self.mode.get()
        if mode != "note":
            self.txt.tag_add(mode, "1.0", "end")
        self.txt.focus_set()
        self.lock()
        if kwargs.get("rolled", False):
            self.rollnote()
        if self.position.get() == "above":
            self.set_position_above()
        elif self.position.get() == "below":
            self.set_position_below()

        # --- placement
        # titlebar
        if CONFIG.get("General", "buttons_position") == "right":
            # right = lock icon - title - roll - close
            self.columnconfigure(1, weight=1)
            self.roll.grid(row=0, column=2, sticky="e")
            self.close.grid(row=0, column=3, sticky="e", padx=(0, 2))
            self.cadenas.grid(row=0, column=0, sticky="w")
            self.title_label.grid(row=0, column=1, sticky="ew", pady=(1, 0))
        else:
            # left = close - roll - title - lock icon
            self.columnconfigure(2, weight=1)
            self.roll.grid(row=0, column=1, sticky="w")
            self.close.grid(row=0, column=0, sticky="w", padx=(2, 0))
            self.cadenas.grid(row=0, column=3, sticky="e")
            self.title_label.grid(row=0, column=2, sticky="ew", pady=(1, 0))
        # body
        self.txt.grid(row=1,
                      columnspan=4,
                      column=0,
                      sticky="ewsn",
                      pady=(1, 4),
                      padx=4)
        self.corner.lift(self.txt)
        self.corner.place(relx=1.0, rely=1.0, anchor="se")

        # --- bindings
        self.bind("<FocusOut>", self.save_note)
        self.bind('<Configure>', self.bouge)
        self.bind('<Button-1>', self.change_focus, True)
        self.close.bind("<Button-1>", self.hide)
        self.close.bind("<Enter>", self.enter_close)
        self.close.bind("<Leave>", self.leave_close)
        self.roll.bind("<Button-1>", self.rollnote)
        self.roll.bind("<Enter>", self.enter_roll)
        self.roll.bind("<Leave >", self.leave_roll)
        self.title_label.bind("<Double-Button-1>", self.edit_title)
        self.title_label.bind("<ButtonPress-1>", self.start_move)
        self.title_label.bind("<ButtonRelease-1>", self.stop_move)
        self.title_label.bind("<B1-Motion>", self.move)
        self.title_label.bind('<Button-3>', self.show_menu)
        self.title_entry.bind("<Return>",
                              lambda e: self.title_entry.place_forget())
        self.title_entry.bind("<FocusOut>",
                              lambda e: self.title_entry.place_forget())
        self.title_entry.bind("<Escape>",
                              lambda e: self.title_entry.place_forget())
        self.txt.tag_bind("link", "<Enter>",
                          lambda event: self.txt.configure(cursor="hand1"))
        self.txt.tag_bind("link", "<Leave>",
                          lambda event: self.txt.configure(cursor=""))
        self.txt.bind("<FocusOut>", self.save_note)
        self.txt.bind('<Button-3>', self.show_menu_txt)
        # add binding to the existing class binding so that the selected text
        # is erased on pasting
        self.txt.bind("<Control-v>", self.paste)
        self.corner.bind('<ButtonRelease-1>', self.resize)

        # --- keyboard shortcuts
        self.txt.bind('<Control-b>', lambda e: self.toggle_text_style('bold'))
        self.txt.bind('<Control-i>',
                      lambda e: self.toggle_text_style('italic'))
        self.txt.bind('<Control-u>', lambda e: self.toggle_underline())
        self.txt.bind('<Control-r>', lambda e: self.set_align('right'))
        self.txt.bind('<Control-l>', lambda e: self.set_align('left'))

    def __setattr__(self, name, value):
        object.__setattr__(self, name, value)
        if name == "color":
            self.style.configure(self.id + ".TSizegrip", background=self.color)
            self.style.configure(self.id + ".TLabel", background=self.color)
            self.style.configure("close" + self.id + ".TLabel",
                                 background=self.color)
            self.style.configure("roll" + self.id + ".TLabel",
                                 background=self.color)
            self.style.map(self.id + ".TLabel",
                           background=[("active", self.color)])
            self.style.configure(self.id + ".TCheckbutton",
                                 background=self.color)
            self.style.map(self.id + ".TCheckbutton",
                           background=[("active", self.color),
                                       ("disabled", self.color)])
            self.style.map("close" + self.id + ".TLabel",
                           background=[("active", self.color)])
            self.style.map("roll" + self.id + ".TLabel",
                           background=[("active", self.color)])
            self.configure(bg=self.color)
            self.txt.configure(bg=self.color)

    def paste(self, event):
        """ delete selected text before pasting """
        if self.txt.tag_ranges("sel"):
            self.txt.delete("sel.first", "sel.last")

    def delete(self, confirmation=True):
        """ Delete this note """
        if confirmation:
            rep = askokcancel(_("Confirmation"), _("Delete the note?"))
        else:
            rep = True
        if rep:
            del (self.master.note_data[self.id])
            del (self.master.notes[self.id])
            self.master.save()
            self.destroy()

    def lock(self):
        """ Put note in read-only mode to avoid unwanted text insertion """
        if self.is_locked:
            selectbg = self.style.lookup('TEntry', 'selectbackground',
                                         ('focus', ))
            self.txt.configure(state="normal",
                               selectforeground='white',
                               selectbackground=selectbg,
                               inactiveselectbackground=selectbg)
            self.style.configure("sel.TCheckbutton", background=selectbg)
            self.style.map("sel.TCheckbutton",
                           background=[("active", selectbg)])
            self.is_locked = False
            for checkbox in self.txt.window_names():
                ch = self.txt.children[checkbox.split(".")[-1]]
                ch.configure(state="normal")
            self.cadenas.configure(image="")
            self.menu.entryconfigure(3, label=_("Lock"))
            self.title_label.bind("<Double-Button-1>", self.edit_title)
            self.txt.bind('<Button-3>', self.show_menu_txt)
        else:
            self.txt.configure(state="disabled",
                               selectforeground='black',
                               inactiveselectbackground='#c3c3c3',
                               selectbackground='#c3c3c3')
            self.style.configure("sel.TCheckbutton", background='#c3c3c3')
            self.style.map("sel.TCheckbutton",
                           background=[("active", '#c3c3c3')])
            self.cadenas.configure(image=self.im_lock)
            for checkbox in self.txt.window_names():
                ch = self.txt.children[checkbox.split(".")[-1]]
                ch.configure(state="disabled")
            self.is_locked = True
            self.menu.entryconfigure(3, label=_("Unlock"))
            self.title_label.unbind("<Double-Button-1>")
            self.txt.unbind('<Button-3>')
        self.save_note()

    def save_info(self):
        """ Return the dictionnary containing all the note data """
        data = {}
        data["txt"] = self.txt.get("1.0", "end")[:-1]
        data["tags"] = {}
        for tag in self.txt.tag_names():
            if tag not in ["sel", "todolist", "list", "enum"]:
                data["tags"][tag] = [
                    index.string for index in self.txt.tag_ranges(tag)
                ]
        data["title"] = self.title_var.get()
        data["geometry"] = self.save_geometry
        data["category"] = self.category.get()
        data["color"] = self.color
        data["locked"] = self.is_locked
        data["mode"] = self.mode.get()
        data["inserted_objects"] = {}
        data["rolled"] = not self.txt.winfo_ismapped()
        data["position"] = self.position.get()
        data["links"] = {}
        for i, link in self.links.items():
            if self.txt.tag_ranges("link#%i" % i):
                data["links"][i] = link
        data["latex"] = {}
        for img, latex in self.latex.items():
            if self.txt.tag_ranges(img):
                data["latex"][img] = latex
        for image in self.txt.image_names():
            data["inserted_objects"][self.txt.index(image)] = (
                "image", image.split('#')[0])
        for checkbox in self.txt.window_names():
            ch = self.txt.children[checkbox.split(".")[-1]]
            data["inserted_objects"][self.txt.index(checkbox)] = (
                "checkbox", "selected" in ch.state())
        return data

    def change_color(self, key):
        self.color = COLORS[key]
        self.save_note()

    def change_category(self, category=None):
        if category:
            self.category.set(category)
        self.color = CONFIG.get("Categories", self.category.get())
        self.save_note()

    def set_position_above(self):
        e = ewmh.EWMH()
        for w in e.getClientList():
            if w.get_wm_name() == 'mynotes%s' % self.id:
                e.setWmState(w, 1, '_NET_WM_STATE_ABOVE')
                e.setWmState(w, 0, '_NET_WM_STATE_BELOW')
        e.display.flush()
        self.save_note()

    def set_position_below(self):
        e = ewmh.EWMH()
        for w in e.getClientList():
            if w.get_wm_name() == 'mynotes%s' % self.id:
                e.setWmState(w, 0, '_NET_WM_STATE_ABOVE')
                e.setWmState(w, 1, '_NET_WM_STATE_BELOW')
        e.display.flush()
        self.save_note()

    def set_position_normal(self):
        e = ewmh.EWMH()
        for w in e.getClientList():
            if w.get_wm_name() == 'mynotes%s' % self.id:
                e.setWmState(w, 0, '_NET_WM_STATE_BELOW')
                e.setWmState(w, 0, '_NET_WM_STATE_ABOVE')
        e.display.flush()
        self.save_note()

    def set_mode_note(self):
        self.txt.tag_remove("list", "1.0", "end")
        self.txt.tag_remove("todolist", "1.0", "end")
        self.txt.tag_remove("enum", "1.0", "end")
        self.save_note()

    def set_mode_list(self):
        end = int(self.txt.index("end").split(".")[0])
        lines = self.txt.get("1.0", "end").splitlines()
        for i, l in zip(range(1, end), lines):
            # remove checkboxes
            try:
                ch = self.txt.window_cget("%i.0" % i, "window")
                self.txt.children[ch.split('.')[-1]].destroy()
                self.txt.delete("%i.0" % i)
            except TclError:
                # there is no checkbox
                # remove enumeration
                res = re.match('^\t[0-9]+\.\t', l)
                if res:
                    self.txt.delete("%i.0" % i, "%i.%i" % (i, res.end()))
            if self.txt.get("%i.0" % i, "%i.3" % i) != "\t•\t":
                self.txt.insert("%i.0" % i, "\t•\t")
        self.txt.tag_add("list", "1.0", "end")
        self.txt.tag_remove("todolist", "1.0", "end")
        self.txt.tag_remove("enum", "1.0", "end")
        self.save_note()

    def set_mode_enum(self):
        self.txt.configure(autoseparators=False)
        self.txt.edit_separator()
        end = int(self.txt.index("end").split(".")[0])
        lines = self.txt.get("1.0", "end").splitlines()
        for i, l in zip(range(1, end), lines):
            # remove checkboxes
            try:
                ch = self.txt.window_cget("%i.0" % i, "window")
                self.txt.children[ch.split('.')[-1]].destroy()
                self.txt.delete("%i.0" % i)
            except TclError:
                # there is no checkbox
                # remove bullets
                if self.txt.get("%i.0" % i, "%i.3" % i) == "\t•\t":
                    self.txt.delete("%i.0" % i, "%i.3" % i)
            if not re.match('^\t[0-9]+\.', l):
                self.txt.insert("%i.0" % i, "\t0.\t")
        self.txt.tag_add("enum", "1.0", "end")
        self.txt.tag_remove("todolist", "1.0", "end")
        self.txt.tag_remove("list", "1.0", "end")
        self.update_enum()
        self.txt.configure(autoseparators=True)
        self.txt.edit_separator()
        self.save_note()

    def set_mode_todolist(self):
        end = int(self.txt.index("end").split(".")[0])
        lines = self.txt.get("1.0", "end").splitlines()
        for i, l in zip(range(1, end), lines):
            res = re.match('^\t[0-9]+\.\t', l)
            if res:
                self.txt.delete("%i.0" % i, "%i.%i" % (i, res.end()))
            elif self.txt.get("%i.0" % i, "%i.3" % i) == "\t•\t":
                self.txt.delete("%i.0" % i, "%i.3" % i)
            try:
                ch = self.txt.window_cget("%i.0" % i, "window")
            except TclError:
                ch = Checkbutton(self.txt,
                                 takefocus=False,
                                 style=self.id + ".TCheckbutton")
                self.txt.window_create("%i.0" % i, window=ch)
        self.txt.tag_remove("enum", "1.0", "end")
        self.txt.tag_remove("list", "1.0", "end")
        self.txt.tag_add("todolist", "1.0", "end")
        self.save_note()

    # --- bindings
    def enter_roll(self, event):
        """ mouse is over the roll icon """
        self.roll.configure(image="img_rollactive")

    def leave_roll(self, event):
        """ mouse leaves the roll icon """
        self.roll.configure(image="img_roll")

    def enter_close(self, event):
        """ mouse is over the close icon """
        self.close.configure(image="img_closeactive")

    def leave_close(self, event):
        """ mouse leaves the close icon """
        self.close.configure(image="img_close")

    def change_focus(self, event):
        if not self.is_locked:
            event.widget.focus_force()

    def show_menu(self, event):
        self.menu.tk_popup(event.x_root, event.y_root)

    def show_menu_txt(self, event):
        self.menu_txt.tk_popup(event.x_root, event.y_root)

    def resize(self, event):
        self.save_geometry = self.geometry()

    def bouge(self, event):
        geo = self.geometry().split("+")[1:]
        self.save_geometry = self.save_geometry.split("+")[0] \
                             + "+%s+%s" % tuple(geo)

    def edit_title(self, event):
        self.title_entry.place(x=self.title_label.winfo_x() + 5,
                               y=self.title_label.winfo_y(),
                               anchor="nw",
                               width=self.title_label.winfo_width() - 10)

    def start_move(self, event):
        self.x = event.x
        self.y = event.y
        self.configure(cursor='fleur')

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

    def move(self, event):
        if self.x is not None and self.y is not None:
            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 save_note(self, event=None):
        data = self.save_info()
        data["visible"] = True
        self.master.note_data[self.id] = data
        self.master.save()

    def rollnote(self, event=None):
        if self.txt.winfo_ismapped():
            self.txt.grid_forget()
            self.corner.place_forget()
            self.geometry("%sx22" % self.winfo_width())
        else:
            self.txt.grid(row=1,
                          columnspan=4,
                          column=0,
                          sticky="ewsn",
                          pady=(1, 4),
                          padx=4)
            self.corner.place(relx=1.0, rely=1.0, anchor="se")
            self.geometry(self.save_geometry)
        self.save_note()

    def hide(self, event=None):
        """ Hide note (can be displayed again via app menu) """
        cat = self.category.get()
        self.master.add_note_to_menu(self.id,
                                     self.title_var.get().strip(), cat)
        data = self.save_info()
        data["visible"] = False
        self.master.note_data[self.id] = data
        del (self.master.notes[self.id])
        self.master.save()
        self.destroy()

    # --- Settings update
    def update_title_font(self):
        font = "%s %s" % (CONFIG.get("Font", "title_family").replace(
            " ", "\ "), CONFIG.get("Font", "title_size"))
        style = CONFIG.get("Font", "title_style").split(",")
        if style:
            font += " "
            font += " ".join(style)
        self.title_label.configure(font=font)

    def update_text_font(self):
        font = "%s %s" % (CONFIG.get("Font", "text_family").replace(
            " ", "\ "), CONFIG.get("Font", "text_size"))
        self.txt.configure(font=font)
        self.txt.tag_configure("bold", font="%s bold" % font)
        self.txt.tag_configure("italic", font="%s italic" % font)
        self.txt.tag_configure("bold-italic", font="%s bold italic" % font)
        margin = 2 * Font(self, font=font).measure("m")
        self.txt.tag_configure("enum",
                               lmargin1=0,
                               lmargin2=margin + 5,
                               tabs=(margin, 'right', margin + 5, 'left'))

    def update_menu_cat(self, categories):
        """ Update the category submenu """
        self.menu_categories.delete(0, "end")
        for cat in categories:
            self.menu_categories.add_radiobutton(label=cat.capitalize(),
                                                 value=cat,
                                                 variable=self.category,
                                                 command=self.change_category)

    def update_titlebar(self):
        if CONFIG.get("General", "buttons_position") == "right":
            # right = lock icon - title - roll - close
            self.columnconfigure(1, weight=1)
            self.columnconfigure(2, weight=0)
            self.roll.grid_configure(row=0, column=2, sticky="e")
            self.close.grid_configure(row=0, column=3, sticky="e", padx=(0, 2))
            self.cadenas.grid_configure(row=0, column=0, sticky="w")
            self.title_label.grid_configure(row=0,
                                            column=1,
                                            sticky="ew",
                                            pady=(1, 0))
        else:
            # left = close - roll - title - lock icon
            self.columnconfigure(2, weight=1)
            self.columnconfigure(1, weight=0)
            self.roll.grid_configure(row=0, column=1, sticky="w")
            self.close.grid_configure(row=0, column=0, sticky="w", padx=(2, 0))
            self.cadenas.grid_configure(row=0, column=3, sticky="e")
            self.title_label.grid_configure(row=0,
                                            column=2,
                                            sticky="ew",
                                            pady=(1, 0))

    # --- Text edition
    def add_link(self):
        def ok(eveny=None):
            lien = link.get()
            txt = text.get()
            if lien:
                if not txt:
                    txt = lien
                self.nb_links += 1
                if self.txt.tag_ranges("sel"):
                    index = self.txt.index("sel.first")
                    self.txt.delete('sel.first', 'sel.last')
                else:
                    index = "current"
                tags = self.txt.tag_names(index) + ("link",
                                                    "link#%i" % self.nb_links)
                self.txt.insert("current", txt, tags)
                if not lien[:4] == "http":
                    lien = "http://" + lien
                self.links[self.nb_links] = lien
                self.txt.tag_bind("link#%i" % self.nb_links, "<Button-1>",
                                  lambda e: open_url(lien))
            top.destroy()

        top = Toplevel(self)
        top.transient(self)
        top.update_idletasks()
        top.geometry("+%i+%i" % top.winfo_pointerxy())
        top.grab_set()
        top.resizable(True, False)
        top.title(_("Link"))
        top.columnconfigure(1, weight=1)
        text = Entry(top)
        link = Entry(top)
        if self.txt.tag_ranges('sel'):
            txt = self.txt.get('sel.first', 'sel.last')
        else:
            txt = ''
        text.insert(0, txt)
        text.icursor("end")
        Label(top, text=_("Text")).grid(row=0,
                                        column=0,
                                        sticky="e",
                                        padx=4,
                                        pady=4)
        Label(top, text=_("Link")).grid(row=1,
                                        column=0,
                                        sticky="e",
                                        padx=4,
                                        pady=4)
        text.grid(row=0, column=1, sticky="ew", padx=4, pady=4)
        link.grid(row=1, column=1, sticky="ew", padx=4, pady=4)
        Button(top, text="Ok", command=ok).grid(row=2,
                                                columnspan=2,
                                                padx=4,
                                                pady=4)

        text.focus_set()
        text.bind("<Return>", ok)
        link.bind("<Return>", ok)

    def add_checkbox(self):
        ch = Checkbutton(self.txt,
                         takefocus=False,
                         style=self.id + ".TCheckbutton")
        self.txt.window_create("current", window=ch)

    def add_date(self):
        self.txt.insert("current", strftime("%x"))

    def add_latex(self, img_name=None):
        def ok(event):
            latex = r'%s' % text.get()
            if latex:
                if img_name is None:
                    l = [
                        int(os.path.splitext(f)[0])
                        for f in os.listdir(PATH_LATEX)
                    ]
                    l.sort()
                    if l:
                        i = l[-1] + 1
                    else:
                        i = 0
                    img = "%i.png" % i
                    self.txt.tag_bind(img, '<Double-Button-1>',
                                      lambda e: self.add_latex(img))
                    self.latex[img] = latex

                else:
                    img = img_name
                im = os.path.join(PATH_LATEX, img)
                try:
                    math_to_image(latex,
                                  im,
                                  fontsize=CONFIG.getint("Font", "text_size") -
                                  2)
                    self.images.append(PhotoImage(file=im, master=self))
                    if self.txt.tag_ranges("sel"):
                        index = self.txt.index("sel.first")
                        self.txt.delete('sel.first', 'sel.last')
                    else:
                        index = self.txt.index("current")
                    self.txt.image_create(index,
                                          image=self.images[-1],
                                          name=im)
                    self.txt.tag_add(img, index)
                    top.destroy()

                except Exception as e:
                    showerror(_("Error"), str(e))

        top = Toplevel(self)
        top.transient(self)
        top.update_idletasks()
        top.geometry("+%i+%i" % top.winfo_pointerxy())
        top.grab_set()
        top.resizable(True, False)
        top.title("LaTex")
        text = Entry(top, justify='center')
        if img_name is not None:
            text.insert(0, self.latex[img_name])
        else:
            if self.txt.tag_ranges('sel'):
                text.insert(0, self.txt.get('sel.first', 'sel.last'))
            else:
                text.insert(0, '$$')
                text.icursor(1)

        text.pack(fill='x', expand=True)
        text.bind('<Return>', ok)
        text.focus_set()

    def add_image(self):
        fichier = askopenfilename(defaultextension=".png",
                                  filetypes=[("PNG", "*.png")],
                                  initialdir="",
                                  initialfile="",
                                  title=_('Select PNG image'))
        if os.path.exists(fichier):
            self.images.append(PhotoImage(master=self.txt, file=fichier))
            self.txt.image_create("current",
                                  image=self.images[-1],
                                  name=fichier)
        elif fichier:
            showerror("Erreur", "L'image %s n'existe pas" % fichier)

    def add_symbols(self):
        symbols = pick_symbol(
            self,
            CONFIG.get("Font", "text_family").replace(" ", "\ "),
            CONFIG.get("General", "symbols"))
        self.txt.insert("current", symbols)

    def toggle_text_style(self, style):
        '''Toggle the style of the selected text'''
        if self.txt.tag_ranges("sel"):
            current_tags = self.txt.tag_names("sel.first")
            if style in current_tags:
                # first char is in style so 'unstyle' the range
                self.txt.tag_remove(style, "sel.first", "sel.last")
            elif style == "bold" and "bold-italic" in current_tags:
                self.txt.tag_remove("bold-italic", "sel.first", "sel.last")
                self.txt.tag_add("italic", "sel.first", "sel.last")
            elif style == "italic" and "bold-italic" in current_tags:
                self.txt.tag_remove("bold-italic", "sel.first", "sel.last")
                self.txt.tag_add("bold", "sel.first", "sel.last")
            elif style == "bold" and "italic" in current_tags:
                self.txt.tag_remove("italic", "sel.first", "sel.last")
                self.txt.tag_add("bold-italic", "sel.first", "sel.last")
            elif style == "italic" and "bold" in current_tags:
                self.txt.tag_remove("bold", "sel.first", "sel.last")
                self.txt.tag_add("bold-italic", "sel.first", "sel.last")
            else:
                # first char is normal, so apply style to the whole selection
                self.txt.tag_add(style, "sel.first", "sel.last")

    def toggle_underline(self):
        if self.txt.tag_ranges("sel"):
            current_tags = self.txt.tag_names("sel.first")
            if "underline" in current_tags:
                # first char is in style so 'unstyle' the range
                self.txt.tag_remove("underline", "sel.first", "sel.last")
                for coul in TEXT_COLORS.values():
                    self.txt.tag_remove(coul + "-underline", "sel.first",
                                        "sel.last")
            else:
                self.txt.tag_add("underline", "sel.first", "sel.last")
                for coul in TEXT_COLORS.values():
                    r = text_ranges(self.txt, coul, "sel.first", "sel.last")
                    if r:
                        for deb, fin in zip(r[::2], r[1::2]):
                            self.txt.tag_add(coul + "-underline", "sel.first",
                                             "sel.last")

    def toggle_overstrike(self):
        if self.txt.tag_ranges("sel"):
            current_tags = self.txt.tag_names("sel.first")
            if "overstrike" in current_tags:
                # first char is in style so 'unstyle' the range
                self.txt.tag_remove("overstrike", "sel.first", "sel.last")
                for coul in TEXT_COLORS.values():
                    self.txt.tag_remove(coul + "-overstrike", "sel.first",
                                        "sel.last")
            else:
                self.txt.tag_add("overstrike", "sel.first", "sel.last")
                for coul in TEXT_COLORS.values():
                    r = text_ranges(self.txt, coul, "sel.first", "sel.last")
                    if r:
                        for deb, fin in zip(r[::2], r[1::2]):
                            self.txt.tag_add(coul + "-overstrike", "sel.first",
                                             "sel.last")

    def change_sel_color(self, color):
        """ change the color of the selection """
        if self.txt.tag_ranges("sel"):
            for coul in TEXT_COLORS.values():
                self.txt.tag_remove(coul, "sel.first", "sel.last")
                self.txt.tag_remove(coul + "-overstrike", "sel.first",
                                    "sel.last")
                self.txt.tag_remove(coul + "-underline", "sel.first",
                                    "sel.last")
            if not color == "black":
                self.txt.tag_add(color, "sel.first", "sel.last")
                underline = text_ranges(self.txt, "underline", "sel.first",
                                        "sel.last")
                overstrike = text_ranges(self.txt, "overstrike", "sel.first",
                                         "sel.last")

                for deb, fin in zip(underline[::2], underline[1::2]):
                    self.txt.tag_add(color + "-underline", deb, fin)
                for deb, fin in zip(overstrike[::2], overstrike[1::2]):
                    self.txt.tag_add(color + "-overstrike", deb, fin)

    def set_align(self, alignment):
        """ Align the text according to alignment (left, right, center) """
        if self.txt.tag_ranges("sel"):
            line = self.txt.index("sel.first").split(".")[0]
            line2 = self.txt.index("sel.last").split(".")[0]
            deb, fin = line + ".0", line2 + ".end"
            if not "\t" in self.txt.get(deb, fin):
                # tabulations don't support right/center alignment
                # remove old alignment tag
                self.txt.tag_remove("left", deb, fin)
                self.txt.tag_remove("right", deb, fin)
                self.txt.tag_remove("center", deb, fin)
                # set new alignment tag
                self.txt.tag_add(alignment, deb, fin)

    def update_enum(self):
        """ update enumeration numbers """
        lines = self.txt.get("1.0", "end").splitlines()
        indexes = []
        for i, l in enumerate(lines):
            res = re.match('^\t[0-9]+\.\t', l)
            res2 = re.match('^\t[0-9]+\.', l)
            if res:
                indexes.append((i, res.end()))
            elif res2:
                indexes.append((i, res2.end()))
        for j, (i, end) in enumerate(indexes):
            self.txt.delete("%i.0" % (i + 1), "%i.%i" % (i + 1, end))
            self.txt.insert("%i.0" % (i + 1), "\t%i.\t" % (j + 1))
        self.txt.tag_add("enum", "1.0", "end")
Пример #32
0
class Register(Frame):
    def __init__(self, master):
        super().__init__(master=master)
        self.layout_components()
        # Setup Callbacks
        self.show_sign_in: Callable = None
        self.sign_in: Callable = None
        self.search_email: Callable = None
        self.search_username: Callable = None
        self.search_password: Callable = None
        self.register: Callable = None

        self.username_valid: bool = False
        self.email_valid: bool = False
        self.password_valid: bool = False
        self.passcnfm_valid: bool = False
        # Refocus to Email Entry
        self.email_Entry.focus()

    def layout_components(self):
        self.pack(fill=tk.BOTH, expand=False, padx=PADX, pady=PADY)
        error_font = font.Font(family="Ariel", size=8)

        # Variables
        self.username = tk.StringVar()
        self.username.set("")

        self.email = tk.StringVar()
        self.email.set("")

        self.password = tk.StringVar()
        self.password.set("")

        self.passcnfm = tk.StringVar()
        self.passcnfm.set("")

        # Email Row
        email_Frame = Frame(self)
        email_Frame.pack(fill=tk.X)
        email_Label = Label(email_Frame, text="Email:", width=LABEL_WIDTH)
        email_Label.pack(side=tk.LEFT, padx=PADX, pady=PADY)
        self.email_Entry = Entry(email_Frame,
                                 width=ENTRY_WIDTH,
                                 textvariable=self.email)
        self.email_Entry.pack(fill=tk.X, padx=PADX, pady=PADY, expand=True)
        self.email_Entry.bind("<FocusOut>", self._validate_email)
        # Email Error Row
        email_errFrame = Frame(self)
        email_errFrame.pack(fill=tk.X)
        self.email_errLabel = Label(email_errFrame,
                                    text="",
                                    foreground="red",
                                    font=error_font)
        self.email_errLabel.pack(side=tk.LEFT,
                                 anchor="center",
                                 expand=True,
                                 padx=PADX,
                                 pady=PADY)

        # Username Row
        user_Frame = Frame(self)
        user_Frame.pack(fill=tk.X)
        user_Label = Label(user_Frame, text="Username:"******"<FocusOut>", self._validate_username)

        # Username Error Row
        user_errFrame = Frame(self)
        user_errFrame.pack(fill=tk.X)
        self.user_errLabel = Label(user_errFrame,
                                   text="",
                                   foreground="red",
                                   font=error_font)
        self.user_errLabel.pack(side=tk.LEFT,
                                anchor="center",
                                expand=True,
                                padx=PADX,
                                pady=PADY)

        # Original Password Row
        pass_Frame = Frame(self)
        pass_Frame.pack(fill=tk.X)
        pass_Label = Label(pass_Frame, text="Password:"******"*")
        self.pass_Entry.pack(fill=tk.X, padx=PADX, pady=PADY, expand=True)
        self.pass_Entry.bind("<FocusOut>", self._validate_password)
        # Confirming Password Row
        pass_cnfmFrame = Frame(self)
        pass_cnfmFrame.pack(fill=tk.X)
        pass_cnfmLabel = Label(pass_cnfmFrame,
                               text="Confirm:",
                               width=LABEL_WIDTH)
        pass_cnfmLabel.pack(side=tk.LEFT, padx=PADX, pady=PADY)
        self.pass_cnfmEntry = Entry(pass_cnfmFrame,
                                    width=ENTRY_WIDTH,
                                    textvariable=self.passcnfm,
                                    show="*")
        self.pass_cnfmEntry.pack(fill=tk.X, padx=PADX, pady=PADY, expand=True)
        self.pass_cnfmEntry.bind("<FocusOut>", self._validate_password)
        # Password Error Row
        pass_errFrame = Frame(self)
        pass_errFrame.pack(fill=tk.X)
        self.pass_errLabel = Label(pass_errFrame,
                                   text="",
                                   foreground="red",
                                   font=error_font)
        self.pass_errLabel.pack(side=tk.LEFT,
                                anchor="center",
                                expand=True,
                                padx=PADX,
                                pady=PADY)

        # Button Row
        button_Frame = Frame(self)
        button_Frame.pack(fill=tk.X)
        # Cancel Button
        cncl_Button = Button(button_Frame, text="Cancel", command=self.cancel)
        cncl_Button.pack(side=tk.RIGHT, padx=PADX, pady=PADY, expand=False)
        # Register Button
        self.register_Button = Button(button_Frame,
                                      text="Register",
                                      state="disabled",
                                      command=self._register)
        self.register_Button.pack(side=tk.RIGHT,
                                  padx=PADX,
                                  pady=PADY,
                                  expand=False)
        # View Password Button
        self.view_pass_Button = Button(button_Frame,
                                       text="View Password",
                                       command=self.view_password)
        self.view_pass_Button.pack(side=tk.LEFT, padx=PADX, pady=PADY)

        # Go Back Button Row
        gbck_Frame = Frame(self)
        gbck_Frame.pack(fill=tk.X)
        gbck_Label = Label(gbck_Frame, text="Have an Account? Go Ahead and ")
        gbck_Label.pack(side=tk.LEFT, padx=PADX, pady=PADY, expand=False)
        gbck_Button = Button(gbck_Frame,
                             text="Sign In",
                             command=self._show_sign_in)
        gbck_Button.pack(side=tk.RIGHT, padx=PADX, pady=PADY, expand=False)

    def cancel(self):
        self.email.set("")
        self.username.set("")
        self.password.set("")
        self.passcnfm.set("")
        self.email_Entry.focus()
        self.email_errLabel.configure(text="")
        self.user_errLabel.configure(text="")
        self.pass_errLabel.configure(text="")

    def view_password(self):
        self.pass_Entry.configure(show="")
        self.pass_cnfmEntry.configure(show="")
        self.view_pass_Button.configure(text="Hide Password",
                                        command=self.hide_password)

    def hide_password(self):
        self.pass_Entry.configure(show="*")
        self.pass_cnfmEntry.configure(show="*")
        self.view_pass_Button.configure(text="View Passwrod",
                                        command=self.view_password)

    def _show_sign_in(self):
        if self.show_sign_in is not None:
            self.show_sign_in()
            self.cancel()

    def _register(self):
        if self.register is not None:
            self.register()

    def _validate_email(self, event):
        email = self.email.get()
        if len(email) == 0:
            self.email_errLabel.configure(text="Email Must not be Empty...")
            self.email_valid = False
        elif not validate_email(email):
            self.email_errLabel.configure(text="Email Format Invalide...")
            self.email_valid = False
        elif self.search_email is not None and not self.search_email(email):
            self.email_errLabel.configure(text="Email Already Registered...")
            self.email_valid = False
        else:
            self.email_errLabel.configure(text="")
            self.email_valid = True
        self.enable_register()

    def _validate_username(self, event):
        username = self.username.get()
        if len(username) == 0:
            self.user_errLabel.configure(text="Username Must not be Empty...")
            self.username_valid = False
        elif self.search_username is not None and not self.search_username(
                username):
            self.username_valid = False
        else:
            self.user_errLabel.configure(text="")
            self.username_valid = True
        self.enable_register()

    def _validate_password(self, event):
        password = self.password.get()
        passcnfm = self.passcnfm.get()
        if len(password) == 0:
            self.pass_errLabel.configure(text="Password Must Not be Empty...")
            self.password_valid = False
        elif len(password) < 8:
            self.pass_errLabel.configure(
                text="Password Must be Longer than 8 Characters...")
            self.password_valid = False
        elif password != passcnfm:
            self.pass_errLabel.configure(text="Password Must Match...   ")
            self.passcnfm_valid = False
        elif self.search_password is not None and not self.search_password(
                password):
            self.pass_errLabel.configure(text="")
            self.password_valid = False
        else:
            self.pass_errLabel.configure(text="")
            self.passcnfm_valid = True
            self.password_valid = True
        self.enable_register()

    def enable_register(self):
        if (self.email_valid and self.username_valid and self.password_valid
                and self.passcnfm_valid):
            self.register_Button.configure(state="normal")

    def failed_register(self):
        self.email.set("")
        self.username.set("")
        self.pass_errLabel.configure(text="Email or Username Already used")
        self.email_Entry.focus()
Пример #33
0
    def add_latex(self, img_name=None):
        def ok(event):
            latex = r'%s' % text.get()
            if latex:
                if img_name is None:
                    l = [
                        int(os.path.splitext(f)[0])
                        for f in os.listdir(PATH_LATEX)
                    ]
                    l.sort()
                    if l:
                        i = l[-1] + 1
                    else:
                        i = 0
                    img = "%i.png" % i
                    self.txt.tag_bind(img, '<Double-Button-1>',
                                      lambda e: self.add_latex(img))
                    self.latex[img] = latex

                else:
                    img = img_name
                im = os.path.join(PATH_LATEX, img)
                try:
                    math_to_image(latex,
                                  im,
                                  fontsize=CONFIG.getint("Font", "text_size") -
                                  2)
                    self.images.append(PhotoImage(file=im, master=self))
                    if self.txt.tag_ranges("sel"):
                        index = self.txt.index("sel.first")
                        self.txt.delete('sel.first', 'sel.last')
                    else:
                        index = self.txt.index("current")
                    self.txt.image_create(index,
                                          image=self.images[-1],
                                          name=im)
                    self.txt.tag_add(img, index)
                    top.destroy()

                except Exception as e:
                    showerror(_("Error"), str(e))

        top = Toplevel(self)
        top.transient(self)
        top.update_idletasks()
        top.geometry("+%i+%i" % top.winfo_pointerxy())
        top.grab_set()
        top.resizable(True, False)
        top.title("LaTex")
        text = Entry(top, justify='center')
        if img_name is not None:
            text.insert(0, self.latex[img_name])
        else:
            if self.txt.tag_ranges('sel'):
                text.insert(0, self.txt.get('sel.first', 'sel.last'))
            else:
                text.insert(0, '$$')
                text.icursor(1)

        text.pack(fill='x', expand=True)
        text.bind('<Return>', ok)
        text.focus_set()
Пример #34
0
class Notifier(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        self.text_clicked = False
        self.time_clicked = False
        self.running = False
        self.afterv = []
        self.max_tries = 5
        self.initUI()

    def initUI(self):
        # Establish frames
        self.pack(side="top", fill="both", expand=True)

        self.top_frame = Frame(self)
        self.bottom_frame = Frame(self)
        self.top_frame.pack(side="top", fill="both", expand=False)
        self.bottom_frame.pack(side="bottom", fill="both", expand=True)

        self.top_top_frame = Frame(self.top_frame)
        self.top_top_frame.pack(side="top", fill="both", expand=False)
        self.bottom_top_frame = Frame(self.top_frame)
        self.bottom_top_frame.pack(side="bottom", fill="both", expand=False)

        # Entry combo box

        self.cboxv = StringVar(self.top_top_frame)
        self.cbox = Combobox(self.top_top_frame, value=self.cboxv, width=40)
        self.cbox['values'] = ("all", "FreeGamesOnSteam", "funny", "news")
        self.cbox.current(0)
        self.cbox.bind("<Button-1>", self.text_callback)
        self.cbox.bind("<Tab>", self.time_callback)
        self.cbox.pack(side="left", padx=10, pady=10, expand=True)

        # Entry time box
        self.tentry = Entry(self.top_top_frame, width=8, foreground='gray')
        self.tentry.bind("<Button-1>", self.time_callback)
        self.tentry.insert(0, "Time(s)")
        self.tentry.pack(side="left", padx=10, pady=10, expand=True)

        # Category drop-down menu
        self.category = StringVar(self.top_top_frame)
        self.category.set("hot")  # default value

        self.omenu = OptionMenu(self.top_top_frame, self.category, "hot",
                                "new", "top", "controversial", "rising")
        self.omenu.pack(side="right", padx=10, pady=10, expand=True)

        # Limit drop-down menu
        self.limit = IntVar(self.top_top_frame)
        self.limit.set(5)  # default value

        self.lmenu = OptionMenu(self.top_top_frame, self.limit,
                                *list(range(10)))
        self.lmenu.pack(side="right", padx=10, pady=10, expand=True)

        # Scan button
        self.scanb = Button(self.bottom_top_frame,
                            text="Scan",
                            command=self.scan_subreddit)
        self.scanb.pack(side="left", padx=10, pady=10, expand=True)
        self.parent.bind("<Return>", lambda x: self.scan_subreddit())

        # Popup check
        self.checkvar = BooleanVar()
        self.check = Checkbutton(self.bottom_top_frame,
                                 text="Popup",
                                 variable=self.checkvar)
        self.check.pack(side="left", padx=10, pady=10, expand=True)

        # Continuous check
        self.contvar = BooleanVar()
        self.contb = Checkbutton(self.bottom_top_frame,
                                 text="Continuous",
                                 variable=self.contvar)
        self.contb.pack(side="left", padx=10, pady=10, expand=True)

        # Stop button
        self.stopb = Button(self.bottom_top_frame,
                            text="Stop",
                            command=self.stop_scanning,
                            state="disabled")
        self.stopb.pack(side="right", padx=10, pady=10, expand=True)
        self.parent.bind("<Escape>", lambda x: self.stop_scanning())

        # Results text box
        self.text = CustomText(self.bottom_frame, height=10, width=50)
        self.text.configure(state="disabled")
        self.text.pack(side="top", padx=10, pady=10, expand=True, fill="both")

    def text_callback(self, event=None):
        if not self.text_clicked:
            self.cbox.delete(0, "end")
            self.text_clicked = True

    def time_callback(self, event=None):
        if not self.time_clicked:
            self.tentry.delete(0, "end")
            self.tentry.config(foreground="black")
            self.time_clicked = True

    def scan_subreddit(self):
        self.running = True
        self.scanb.config(state="disabled")
        self.stopb.config(state="normal")
        self.omenu.config(state="disabled")
        self.lmenu.config(state="disabled")
        self.cbox.config(state="disabled")
        self.tentry.config(state="disabled")
        self.check.config(state="disabled")
        self.contb.config(state="disabled")

        self.parent.unbind("<Return>")
        # Clean text box
        self.text.config(state="normal")
        self.text.delete(1.0, 'end')
        self.text.config(state="disabled")

        # Get values from boxes
        sub_name = self.cbox.get()
        cat = self.category.get()
        self.slimit = self.limit.get()
        self.popup = self.checkvar.get()
        self.cont = self.contvar.get()

        try:
            subreddit = reddit.subreddit(sub_name)
        except Exception:
            self.text.tinsert("Error: insert a subreddit" + '\n')
            self.stop_scanning()
            return

        try:
            self.stime = max(0, int(self.tentry.get()))
        except Exception:
            self.text.tinsert("Error: time must be a number" + '\n')
            self.stop_scanning()
            return

        self.text.tinsert("Info: getting " + cat + " posts from /r/" +
                          sub_name + '\n')

        self.subcat = get_subreddit_cat(subreddit, cat)
        self.tries = 0
        self.done_trying = False
        self.started_managing = False
        self.done_managing = False
        self.submissions = None
        self.get_results()

    def stop_scanning(self):
        self.running = False
        self.scanb.config(state="normal")
        self.stopb.config(state="disabled")
        self.omenu.config(state="normal")
        self.lmenu.config(state="normal")
        self.cbox.config(state="normal")
        self.tentry.config(state="normal")
        self.check.config(state="normal")
        self.contb.config(state="normal")
        self.parent.bind("<Return>", lambda x: self.scan_subreddit())
        for a in self.afterv:
            self.parent.after_cancel(a)
        del self.afterv[:]

    def get_results(self):
        if self.running:
            now = time.time()
            if not self.done_trying:
                if self.tries < self.max_tries:
                    try:
                        self.submissions = [
                            x for x in self.subcat(limit=self.slimit)
                            if (now - x.created_utc) < self.stime
                        ]
                        self.done_trying = True
                    except Exception:
                        self.text.tinsert("Error: [" + nows() + "] try n. " +
                                          str(self.tries + 1) +
                                          ", cannot access subreddit" + '\n')
                        self.tries += 1
                        self.afterv.append(
                            self.parent.after(5000, self.get_results))
                else:
                    self.text.tinsert(
                        "Error: [" + nows() +
                        "] couldn't access subreddit. Stopping scan." + '\n')
                    self.stop_scanning()
                    self.done_trying = True
                self.tries = 0

            if self.done_trying:
                if not self.submissions:
                    if not self.started_managing:
                        self.text.tinsert("Info: [" + nows() +
                                          "] no results found"
                                          '\n')
                    self.done_managing = True
                else:
                    if not self.started_managing:
                        self.text.tinsert("Info: [" + nows() + "] " +
                                          str(len(self.submissions)) +
                                          " results found"
                                          '\n')
                        self.started_managing = True
                    s = self.submissions[0]
                    self.text.tinsert("Title: " + convert65536(s.title) + '\n')
                    self.text.tinsert("Url: " + s.url + '\n')
                    self.text.tinsert("Created: " + pretty_date(s) + '\n\n')
                    self.parent.update_idletasks()
                    if self.popup:
                        if sys.platform.startswith('win'):
                            import winsound
                            winsound.PlaySound("media/jamaica.wav",
                                               winsound.SND_FILENAME)
                        Dialog(self.parent, s.url, s.title)
                    self.submissions = self.submissions[1:]
                    self.afterv.append(
                        self.parent.after(1000, self.get_results))

                if self.done_managing:
                    if self.cont:
                        self.text.tinsert(
                            "Info: [" + nows() +
                            "] continuous mode, will check again in " +
                            str(self.stime) + " seconds\n\n")
                        self.afterv.append(
                            self.parent.after(self.stime * 1000,
                                              self.get_results))
                        self.done_trying = False
                        self.started_managing = False
                        self.done_managing = False
                    else:
                        self.text.tinsert("Info: [" + nows() +
                                          "] scanning finished"
                                          '\n')
                        self.stop_scanning()