示例#1
0
文件: sticky.py 项目: Vistaus/MyNotes
 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)
示例#2
0
文件: sticky.py 项目: Vistaus/MyNotes
 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'))
示例#3
0
 def update_notes(self, col_changes={}, name_changes={}):
     """Update the notes after changes in the categories."""
     categories = CONFIG.options("Categories")
     categories.sort()
     self.menu_notes.delete(0, "end")
     self.hidden_notes = {cat: {} for cat in categories}
     for key in self.note_data:
         cat = self.note_data[key]["category"]
         if cat in name_changes:
             cat = name_changes[cat]
             self.note_data[key]["category"] = cat
             if self.note_data[key]["visible"]:
                 self.notes[key].change_category(cat)
         elif cat not in categories:
             default = CONFIG.get("General", "default_category")
             default_color = CONFIG.get("Categories", default)
             if self.note_data[key]["visible"]:
                 self.notes[key].change_category(default)
             self.note_data[key]["category"] = default
             self.note_data[key]["color"] = default_color
             cat = default
         if cat in col_changes:
             old_color, new_color = col_changes[cat]
             if self.note_data[key]["color"] == old_color:
                 self.note_data[key]["color"] = new_color
                 if self.note_data[key]["visible"]:
                     self.notes[key].change_color(cst.INV_COLORS[new_color])
         if not self.note_data[key]['visible']:
             self.add_note_to_menu(key, self.note_data[key]["title"],
                                   self.note_data[key]['category'])
         else:
             self.notes[key].update_menu_cat(categories)
     self.save()
     if self.menu_notes.index("end") is not None:
         self.icon.menu.entryconfigure(4, state="normal")
     else:
         self.icon.menu.entryconfigure(4, state="disabled")
示例#4
0
文件: sticky.py 项目: Vistaus/MyNotes
 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))
示例#5
0
文件: sticky.py 项目: Vistaus/MyNotes
 def add_symbols(self):
     symbols = pick_symbol(
         self,
         CONFIG.get("Font", "text_family").replace(" ", "\ "),
         CONFIG.get("General", "symbols"))
     self.txt.insert("current", symbols)
示例#6
0
文件: sticky.py 项目: Vistaus/MyNotes
 def change_category(self, category=None):
     if category:
         self.category.set(category)
     self.color = CONFIG.get("Categories", self.category.get())
     self.save_note()
示例#7
0
文件: sticky.py 项目: Vistaus/MyNotes
    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'))
示例#8
0
    def __init__(self, master, app, **kwargs):
        Frame.__init__(self, master, **kwargs)
        self.columnconfigure(0, weight=1)

        self.app = app

        self.style = Style(self)
        self.style.theme_use("clam")

        self.im_plus = PhotoImage(file=IM_PLUS)
        self.im_moins = PhotoImage(file=IM_MOINS)

        # --- Default category
        self.frame_def_cat = Frame(self)
        self.default_category = StringVar(self.frame_def_cat,
                                          CONFIG.get("General",
                                                     "default_category").capitalize())
        Label(self.frame_def_cat, text=_("Default category ")).grid(row=0, column=0,
                                                                    sticky="e",
                                                                    padx=(4, 0))
        self.categories = CONFIG.options("Categories")
        self.categories.sort()
        categories = [cat.capitalize() for cat in self.categories]
        self.def_cat_menu = OptionMenu(self.frame_def_cat, self.default_category,
                                       CONFIG.get("General",
                                                  "default_category").capitalize(),
                                       *categories)
        optionmenu_patch(self.def_cat_menu, self.default_category)
        self.def_cat_menu.grid(row=0, column=1, sticky="w", padx=4, pady=4)

        # --- Category colors, names ...
        self.frame_cat = Frame(self)
        self.colors = list(COLORS.keys())
        self.colors.sort()
        self.images = []
        for key in self.colors:
            self.images.append(PhotoImage(key, master=self, width=16, height=16))
            fill(self.images[-1], COLORS[key])
        self.cat_colors = {}
        self.cat_labels = {}
        self.cat_menus = {}
        self.cat_buttons = {}
        for i, cat in enumerate(self.categories):
            self.cat_labels[cat] = Label(self.frame_cat,
                                         text="%s" % cat.capitalize(),
                                         anchor='e')
            self.cat_labels[cat].grid(row=i + 2, column=0, sticky="ew", padx=2)
            self.cat_labels[cat].bind('<Double-Button-1>', self.change_name)
            self.cat_colors[cat] = StringVar(self)
            color = CONFIG.get("Categories", cat)
            self.cat_menus[cat] = OptionMenu(self.frame_cat, self.cat_colors[cat],
                                             INV_COLORS[color], *self.colors,
                                             command=lambda color, c=cat: self.change_menubutton_color(color, c),
                                             style="%s.TMenubutton" % cat)
            optionmenu_patch(self.cat_menus[cat], self.cat_colors[cat])
            self.style.configure("%s.TMenubutton" % cat, background=color)
            self.cat_menus[cat].grid(row=i + 2, column=1, sticky="w", padx=4, pady=4)
            self.cat_buttons[cat] = Button(self.frame_cat, image=self.im_moins,
                                           command=lambda c=cat: self.del_cat(c))
            self.cat_buttons[cat].grid(row=i + 2, column=2, padx=4, pady=4)

        self.add_cat_button = Button(self.frame_cat, image=self.im_plus,
                                     command=self.add_cat)
        self.add_cat_button.grid(row=i + 3, column=0, pady=(0, 4))

        if len(self.categories) == 1:
            self.cat_buttons[self.categories[0]].configure(state="disabled")

        # --- placement
        self.frame_def_cat.grid(row=0, column=0, sticky="eswn")
        Separator(self, orient="horizontal").grid(row=1, columnspan=3,
                                                  pady=10, sticky="ew")
        self.frame_cat.grid(row=2, column=0, sticky="eswn")
示例#9
0
    def ok(self):
        family = self.font_family.get()
        if family not in self.fonts:
            l = [i for i in self.fonts if i[:len(family)] == family]
            if l:
                family = l[0]
            else:
                family = 'TkDefaultFont'
        size = self.font_size.get()
        familytitle = self.fonttitle_family.get()
        if familytitle not in self.fonts:
            l = [i for i in self.fonts if i[:len(familytitle)] == familytitle]
            if l:
                familytitle = l[0]
            else:
                familytitle = 'TkDefaultFont'
        sizetitle = self.fonttitle_size.get()
        opacity = "%i" % float(self.opacity_scale.get())
        language = self.lang.get().lower()[:2]
        style = ""
        if self.is_bold.instate(("selected", )):
            style += "bold,"
        if self.is_italic.instate(("selected", )):
            style += "italic,"
        if self.is_underlined.instate(("selected", )):
            style += "underline,"
        if style:
            style = style[:-1]

        symbols = [
            l.strip() for l in self.symbols.get("1.0", "end").splitlines()
        ]

        CONFIG.set("General", "default_category",
                   self.category_settings.default_category.get().lower())
        CONFIG.set("General", "language", language)
        CONFIG.set("General", "opacity", opacity)
        CONFIG.set("General", "position", self.position.get())
        CONFIG.set("General", "buttons_position",
                   self.titlebar_disposition.get())
        CONFIG.set("General", "symbols", "".join(symbols))
        CONFIG.set("Font", "text_size", size)
        CONFIG.set("Font", "text_family", family)
        CONFIG.set("Font", "title_family", familytitle)
        CONFIG.set("Font", "title_size", sizetitle)
        CONFIG.set("Font", "title_style", style)

        col_changes = {}
        name_changes = {}
        for cat in self.category_settings.categories:
            new_name = self.category_settings.get_name(cat)
            if cat in CONFIG.options("Categories"):
                old_color = CONFIG.get("Categories", cat)
                new_color = COLORS[self.category_settings.get_color(cat)]
                if new_name != cat:
                    name_changes[cat] = new_name
                    CONFIG.remove_option("Categories", cat)
                    CONFIG.set("Categories", new_name, new_color)
                if old_color != new_color:
                    col_changes[new_name] = (old_color, new_color)
                    CONFIG.set("Categories", new_name, new_color)

            else:
                CONFIG.set("Categories", new_name,
                           COLORS[self.category_settings.get_color(cat)])
        save_config()
        self.changes = col_changes, name_changes
        self.destroy()
示例#10
0
    def __init__(self, master):
        Toplevel.__init__(self, master)
        self.title(_("Preferences"))
        self.grab_set()
        self.resizable(False, False)
        self.protocol("WM_DELETE_WINDOW", self.quit)
        self.changes = {}, {}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.update_preview()

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

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

        # --- Ok/Cancel buttons
        Button(okcancel_frame, text="Ok", command=self.ok).grid(row=1,
                                                                column=0,
                                                                padx=4,
                                                                pady=10,
                                                                sticky="e")
        Button(okcancel_frame, text=_("Cancel"),
               command=self.destroy).grid(row=1,
                                          column=1,
                                          padx=4,
                                          pady=10,
                                          sticky="w")
        # --- bindings
        self.font_family.bind('<<ComboboxSelected>>', self.update_preview)
        self.font_family.bind('<Return>', self.update_preview)
        self.font_size.bind('<<ComboboxSelected>>',
                            self.update_preview,
                            add=True)
        self.font_size.bind('<Return>', self.update_preview, add=True)
        self.fonttitle_family.bind('<<ComboboxSelected>>',
                                   self.update_preview_title)
        self.fonttitle_size.bind('<<ComboboxSelected>>',
                                 self.update_preview_title,
                                 add=True)
        self.fonttitle_family.bind('<Return>', self.update_preview_title)
        self.fonttitle_size.bind('<Return>',
                                 self.update_preview_title,
                                 add=True)