Beispiel #1
0
def styling(root):
    # tell tcl where to find the awthemes packages
    root.tk.eval("""
    set base_theme_dir awthemes/

    package ifneeded awthemes 10.2.1 \
        [list source [file join $base_theme_dir awthemes.tcl]]
    package ifneeded colorutils 4.8 \
        [list source [file join $base_theme_dir colorutils.tcl]]
    package ifneeded awdark 7.11 \
        [list source [file join $base_theme_dir awdark.tcl]]   
    
    """)

    # remove maximize/mininize button
    root.resizable(0,0)

    # load the awdark and awlight themes
    root.tk.call("package", "require", 'awdark')
    # Initialising Style and loading in a dark thene
    style = Style()
    style.theme_use('awdark')

    #configure buttons
    style.configure("TButton", padding=6, relief="flat", font=menu_font)

    # button active/hover tweaks
    style.map("C.TButton",
    foreground=[('pressed', 'black'), ('active', 'black')],
    background=[('pressed', '!disabled', 'gray'), ('active', 'gray')]
    )
Beispiel #2
0
 def _style(self) -> tuple[str, Style]:
     name = f'{self.id}.customtable.Treeview'
     tk_style = Style()
     style = self.style
     tk_style.theme_use(style.ttk_theme)
     font = style.font
     tk_style.configure(name,
                        rowheight=self.row_height or style.char_height)
     cfg_keys = ('font', 'foreground', 'background', 'fieldbackground')
     bg = style.bg.default
     if base := {
             k: v
             for k, v in zip(cfg_keys, (font, style.fg.default, bg, bg))
             if v is not None
     }:
         tk_style.configure(name, **base)
         if (selected_row_color :=
                 self.selected_row_color) and ('foreground' in base
                                               or 'background' in base):
             for i, color in enumerate(('foreground', 'background')):
                 if color in base and selected_row_color[i] is not None:
                     tk_style.map(
                         name, **{
                             color:
                             _fixed_style_map(tk_style, name, color,
                                              selected_row_color)
                         })
Beispiel #3
0
def create_protocols_tree():
    """
    创建协议导航树
    :return: 协议导航树
    """
    protocols_tree.heading('#0', text='选择网络协议', anchor='w')
    # 参数:parent, index, iid=None, **kw (父节点,插入的位置,id,显示出的文本)
    # 应用层
    applicatoin_layer_tree_entry = protocols_tree.insert("", 0, "应用层", text="应用层")  # ""表示父节点是根
    http_packet_tree_entry = protocols_tree.insert(applicatoin_layer_tree_entry, 1, "HTTP包", text="HTTP包")
    dns_packet_tree_entry = protocols_tree.insert(applicatoin_layer_tree_entry, 1, "DNS包", text="DNS包")
    # 传输层
    transfer_layer_tree_entry = protocols_tree.insert("", 1, "传输层", text="传输层")
    tcp_packet_tree_entry = protocols_tree.insert(transfer_layer_tree_entry, 0, "TCP包", text="TCP包")
    upd_packet_tree_entry = protocols_tree.insert(transfer_layer_tree_entry, 1, "UDP包", text="UDP包")
    # 网络层
    ip_layer_tree_entry = protocols_tree.insert("", 2, "网络层", text="网络层")
    ip_packet_tree_entry = protocols_tree.insert(ip_layer_tree_entry, 0, "IP包", text="IP包")
    icmp_packet_tree_entry = protocols_tree.insert(ip_layer_tree_entry, 1, "ICMP包", text="ICMP包")
    arp_packet_tree_entry = protocols_tree.insert(ip_layer_tree_entry, 2, "ARP包", text="ARP包")
    # 网络接入层
    ether_layer_tree_entry = protocols_tree.insert("", 3, "网络接入层", text="网络接入层")
    mac_frame_tree_entry = protocols_tree.insert(ether_layer_tree_entry, 1, "MAC帧", text="MAC帧")
    protocols_tree.bind('<<TreeviewSelect>>', on_click_protocols_tree)
    style = Style(tk)
    # get disabled entry colors
    disabled_bg = style.lookup("TEntry", "fieldbackground", ("disabled",))
    style.map("Treeview",
              fieldbackground=[("disabled", disabled_bg)],
              foreground=[("disabled", "gray")],
              background=[("disabled", disabled_bg)])
    protocols_tree.pack()
    return protocols_tree
Beispiel #4
0
 def createprotocolsTree(self):
     """
     生成协议导航树
     :return:
     """
     self.protocolsTree.heading('#0', text='选择发送报文类型', anchor='w')
     # 参数:parent, index, iid=NOne, **kw(父节点,插入的位置,id,显示的文本)
     # 应用层
     applicatoin_layer_tree_entry = self.protocolsTree.insert('',
                                                              0,
                                                              "应用层",
                                                              text="应用层")
     dns_packet_tree_entry = self.protocolsTree.insert(
         applicatoin_layer_tree_entry, 1, "DNS数据包", text="DNS数据包")
     # 传输层
     transfer_layer_tree_entry = self.protocolsTree.insert('',
                                                           1,
                                                           "传输层",
                                                           text="传输层")
     tcp_packet_tree_entry = self.protocolsTree.insert(
         transfer_layer_tree_entry, 0, "TCP数据包", text="TCP数据包")
     udp_packet_tree_entry = self.protocolsTree.insert(
         transfer_layer_tree_entry, 1, "UDP数据包", text="UDP数据包")
     # 网络层协议
     ip_layer_tree_entry = self.protocolsTree.insert('',
                                                     2,
                                                     "网络层",
                                                     text="网络层")
     arp_packet_tree_entry = self.protocolsTree.insert(ip_layer_tree_entry,
                                                       0,
                                                       "ARP数据包",
                                                       text="ARP数据包")
     ip_packet_tree_entry = self.protocolsTree.insert(ip_layer_tree_entry,
                                                      1,
                                                      "IP数据包",
                                                      text="IP数据包")
     icmp_packet_tree_entry = self.protocolsTree.insert(ip_layer_tree_entry,
                                                        2,
                                                        "ICMP报文",
                                                        text="ICMP报文")
     # 网络接口层协议
     ether_layer_tree_entry = self.protocolsTree.insert('',
                                                        3,
                                                        "网络接口层",
                                                        text="网络接口层")
     mac_frame_tree_entry = self.protocolsTree.insert(
         ether_layer_tree_entry, 1, "以太网MAC协议", text="以太网MAC协议")
     self.protocolsTree.bind('<<TreeviewSelect>>',
                             self.on_click_protocols_tree)
     style = Style(self)
     # get disabled entry colors
     disabled_bg = style.lookup("TEntry", "fieldbackground", ("disabled", ))
     style.map("Treeview",
               fieldbackground=[("disabled", disabled_bg)],
               foreground=[("disabled", "gray")],
               background=[("disabled", disabled_bg)])
     self.protocolsTree.pack()
     return self.protocolsTree
Beispiel #5
0
 def configure_main_treeview_style(self, style: ttk.Style, key: str, font: Tuple[str, int, str]) -> None:
     style.configure(key,
                     font=font, rowheight=font[1] * 3,
                     relief=tk.FLAT, borderwidth=0, highlightthickness=0,
                     background=self._main_background,
                     fieldbackground=self._main_background,
                     foreground=self._main_foreground)
     style.map(key,
               foreground=[('selected', self._main_foreground_selected)],
               background=[('selected', self._main_background_selected)])
Beispiel #6
0
    def __init__(self, master, env_name):
        self.ds = Dataset(source="", name="iam")
        self.RESULTS_PATH = "results/"
        self.master = master
        ##Init of the master view
        self.master.title("Handwritten flowchart with CNNs")
        self.master.configure(background="gray99")
        self.master.resizable(False, False)
        self.master.geometry("600x500")
        self.master.config(bg="#857074")
        # Predict
        self.selected_image = ""
        self.models_path = "model/training_results/"
        #training
        self.env_name = env_name
        #Header
        self.header = tk.Frame(self.master)
        self.header.config(width="1000", height="100", bg="#943340")
        self.header.pack(fill="y")
        self.header.pack_propagate(False)
        self.title = tk.Label(self.header,
                              text="3b-flowchart",
                              font=("Arial", 50),
                              bg="#943340")
        self.title.pack(pady=20)
        style = Style()
        style.map('TButton',
                  foreground=[('active', 'green')],
                  background=[('active', 'black')])
        #Buttons
        btn1 = tk.Button(self.master,
                         height=4,
                         font=("Arial", 15),
                         width=25,
                         text="Train shape model",
                         command=self.train_window)
        btn1.pack(pady=10)

        btn2 = tk.Button(self.master,
                         height=4,
                         font=("Arial", 15),
                         width=25,
                         text="Recognize flowchart",
                         command=self.recognize_flowchart_window)
        btn2.pack(pady=10)

        btn3 = tk.Button(self.master,
                         height=4,
                         font=("Arial", 15),
                         width=25,
                         text="Train text model",
                         command=self.__train_text_model)
        btn3.pack(pady=10)
        self.master.mainloop()
Beispiel #7
0
def main():
    root = Tk()
    root.resizable(0,0)
    s = Style()
    s.configure('My.TFrame', background='orange')
    s.configure('My.TButton', background='light gray')
    s.configure('My.TEntry', fieldbackground='light gray')
    s.configure('My.TRadiobutton', background='orange')
    s.map('My.TRadiobutton', background=[('active', '#FFC133')])
    root.geometry("300x125")
    t431 = T431(root)
    root.mainloop()
Beispiel #8
0
def _alert_style(style: ttk.Style, name: str, background: str):
    style.configure(
        name,
        background=background,
        padding=0,
        relief=tk.RIDGE,
        borderwidth=1,
        font="TkDefaultFont",
        foreground="black",
        highlightbackground="white",
    )
    style.map(name, background=[("!active", background), ("active", "white")])
def setup_style(style_object: ttk.Style):
    """
    All the ttk style changes go in here.
    :param style_object: style object to configure and map.
    :return:
    """
    style_object.theme_use("clam")

    style_object.configure("TFrame", background="#3a3a3a")

    style_object.configure("TNotebook",
                           lightcolor="#242424",
                           darkcolor="#242424",
                           bordercolor="#242424",
                           background="#3a3a3a",
                           relief="flat")
    style_object.configure("TNotebook.Tab",
                           background="#323232",
                           bordercolor="#2d2d2d",
                           relief="flat",
                           foreground="white")
    style_object.map("TNotebook.Tab",
                     background=[("selected", "#df4a16"),
                                 ("active", "#3c3c3c")])

    style_object.configure("TLabelframe.Label",
                           background="#3a3a3a",
                           foreground="white")
    style_object.configure("TLabelframe",
                           background="#3a3a3a",
                           darkcolor="#242424",
                           lightcolor="#242424",
                           bordercolor="#242424")

    style_object.configure("TScrollbar",
                           background="#868686",
                           troughcolor="#323232",
                           bordercolor="#323232")

    style_object.configure("TLabel", background="#3a3a3a", foreground="white")

    style_object.configure("TButton",
                           background="#393939",
                           foreground="white",
                           bordercolor="#242424",
                           darkcolor="#242424",
                           lightcolor="#242424")
    style_object.map("TButton",
                     background=[("pressed", "#202020"),
                                 ("active", "#3c3c3c")])
Beispiel #10
0
def style_for_ok_and_close_btn() -> None:
    """
    Функция создания стилей для кнопок Ок и Отмена
    :return:
    """
    style = Style()
    style.map(
        "OK.TButton",
        foreground=[('pressed', 'white'), ('active', 'green')],
        background=[('pressed', '#5CFF5D'), ('active', '#A5FF99'),
                    ('!disabled', BUTTON_BACKGROUND)],
    )
    style.map('Close.TButton',
              foreground=[('pressed', 'black'), ('active', '#B20007')],
              background=[('pressed', '#B20007'), ('active', '#FFA3B5')])
Beispiel #11
0
 def __init__(self, master=None, **kw):
     Treeview.__init__(self, master, style='Checkbox.Treeview', **kw)
     # style (make a noticeable disabled style)
     style = Style(self)
     style.map("Checkbox.Treeview",
               fieldbackground=[("disabled", '#E6E6E6')],
               foreground=[("disabled", 'gray40')],
               background=[("disabled", '#E6E6E6')])
     # checkboxes are implemented with pictures
     self.im_checked = PhotoImage(file=IM_CHECKED, master=self)
     self.im_unchecked = PhotoImage(file=IM_UNCHECKED, master=self)
     self.im_tristate = PhotoImage(file=IM_TRISTATE, master=self)
     self.tag_configure("unchecked", image=self.im_unchecked)
     self.tag_configure("tristate", image=self.im_tristate)
     self.tag_configure("checked", image=self.im_checked)
     # check / uncheck boxes on click
     self.bind("<Button-1>", self.box_click, True)
Beispiel #12
0
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        label = tk.Label(self,
                         text="Welcome to Zoo Monitor Data Mapper",
                         font=LARGE_FONT,
                         bg=BACKGROUND_COLOR)
        label.pack(pady=10, padx=10)

        style = Style()
        style.configure('TButton', font=BUTTON_FONT, borderwidth='4')
        style.map('TButton',
                  foreground=[('active', '!disabled', 'green')],
                  background=[('active', 'black')])

        button = ttk.Button(self,
                            text="Import Spreadsheet",
                            style="TButton",
                            command=lambda: controller.get_spreadsheet())
        button.pack()

        button3 = ttk.Button(
            self,
            text="Graph Page",
            command=lambda: controller.show_frame(HeatMapPage))
        button3.pack(pady=20)

        canvas = Canvas(self, width=800,
                        height=507)  #width and height of the logo.jpg image
        canvas.pack()
        img = ImageTk.PhotoImage(PIL.Image.open('resources/logo.jpg'))
        canvas.background = img  # Keep a reference in case this code is put in a function.
        canvas.create_rectangle(0,
                                0,
                                600,
                                600,
                                fill=BACKGROUND_COLOR,
                                outline=BACKGROUND_COLOR)
        bg = canvas.create_image(0, 0, anchor=tk.NW, image=img)

        enclosure_image = Label(image="")
        enclosure_image.pack()
Beispiel #13
0
def _fixed_style_map(style: Style,
                     style_name: str,
                     option: str,
                     highlight_colors: tuple[str, str] = (None, None)):
    # Fix for setting text color for Tkinter 8.6.9
    # From: https://core.tcl.tk/tk/info/509cafafae
    default_map = [
        elm for elm in style.map('Treeview', query_opt=option)
        if '!' not in elm[0]
    ]
    custom_map = [
        elm for elm in style.map(style_name, query_opt=option)
        if '!' not in elm[0]
    ]

    if option == 'background':
        custom_map.append(('selected', highlight_colors[1]
                           or 'SystemHighlight'))
    elif option == 'foreground':
        custom_map.append(('selected', highlight_colors[0]
                           or 'SystemHighlightText'))

    return custom_map + default_map
Beispiel #14
0
class CreateStyle():
    def __init__(self, parent):
        self.parent = parent
        self.style = Style()
        #self.style.theme_create("light", parent= "clam")
        self.style.theme_use("clam")

        #self.style.configure('TButton', foreground = 'white', background = 'blue')
        self.style.configure('TFrame', background=GREY)
        self.style.configure(BGWHITE, background=WHITE)
        self.style.configure(BGDARKGREY, background=DARKGREY)
        self.style.configure("TNotebook", background=GREY, borderwidth=0)
        self.style.map("TNotebook.Tab",
                       background=[("selected", WHITE)],
                       foreground=[("selected", BLACK)])
        self.style.configure("TNotebook.Tab",
                             background=DARKGREY,
                             foreground=BLACK)
        self.style.configure("Tab", focuscolor=GREY)

        #self.parent.option_add('*Label.bg', 'red')
        self.parent.option_add('*TCombobox*Listbox.selectBackground', 'yellow')
        self.parent.option_add('*TCombobox*Listbox.selectForeground', 'black')
Beispiel #15
0
class Notification(Tk):
    def __init__(self, text=''):
        Tk.__init__(self)
        self.overrideredirect(True)
        self.withdraw()
        self.columnconfigure(0, weight=1)
        self.attributes('-type', 'notification')
        self.attributes('-alpha', 0.75)

        self.style = Style(self)
        self.style.theme_use('clam')
        self.bg = [
            CONFIG.get('Reminders', 'window_bg'),
            CONFIG.get('Reminders', 'window_bg_alternate')
        ]
        self.fg = [
            CONFIG.get('Reminders', 'window_fg'),
            CONFIG.get('Reminders', 'window_fg_alternate')
        ]
        self.active_bg = [active_color(*self.winfo_rgb(bg)) for bg in self.bg]
        self.active_bg2 = [
            active_color(*self.winfo_rgb(bg)) for bg in self.active_bg
        ]
        self.style.configure('notif.TLabel',
                             background=self.bg[0],
                             foreground=self.fg[0])
        self.style.configure('notif.TButton',
                             background=self.active_bg[0],
                             relief='flat',
                             foreground=self.fg[0])
        self.configure(bg=self.bg[0])
        self.style.map('notif.TButton',
                       background=[('active', self.active_bg2[0])])
        Label(self, text=text, style='notif.TLabel').grid(row=0,
                                                          column=0,
                                                          padx=10,
                                                          pady=10)
        Button(self, text='Ok', command=self.quit,
               style='notif.TButton').grid(row=1,
                                           column=0,
                                           padx=10,
                                           pady=(0, 10))
        self.blink_alternate = False
        self.deiconify()
        self.update_idletasks()
        self.geometry('%ix%i+0+0' %
                      (self.winfo_screenwidth(), self.winfo_height()))
        self.alarm_id = ''
        self.alarm_process = None
        self.blink_id = ''
        self.timeout_id = ''
        if CONFIG.getboolean('Reminders', 'blink'):
            self.blink_id = self.after(500, self.blink)
        if not CONFIG.getboolean("Reminders", "mute", fallback=False):
            self.alarm()
        timeout = CONFIG.getint('Reminders', 'timeout') * 60 * 1000
        if timeout > 0:
            self.timeout_id = self.after(timeout, self.quit)

    def alarm(self):
        self.alarm_process = Popen([
            CONFIG.get("General", "soundplayer"),
            CONFIG.get("Reminders", "alarm")
        ])
        self.alarm_id = self.after(500, self.repeat_alarm)

    def repeat_alarm(self):
        if self.alarm_process.poll() is None:
            self.alarm_id = self.after(500, self.repeat_alarm)
        else:  # ringing is finished
            self.alarm()

    def quit(self):
        try:
            self.after_cancel(self.alarm_id)
        except ValueError:
            pass
        try:
            self.after_cancel(self.blink_id)
        except ValueError:
            pass
        try:
            self.after_cancel(self.timeout_id)
        except ValueError:
            pass
        if self.alarm_process is not None:
            self.alarm_process.terminate()
        self.destroy()

    def blink(self):
        self.blink_alternate = not self.blink_alternate
        self.configure(bg=self.bg[self.blink_alternate])
        self.style.configure('notif.TLabel',
                             background=self.bg[self.blink_alternate],
                             foreground=self.fg[self.blink_alternate])
        self.style.configure('notif.TButton',
                             background=self.active_bg[self.blink_alternate],
                             relief='flat',
                             foreground=self.fg[self.blink_alternate])
        self.blink_id = self.after(500, self.blink)
Beispiel #16
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"
              ))
Beispiel #17
0
class box(gui.Tk):
    def __init__(self):
        #op = operators()
        self.op = -1
        self.b = ''
        self.a = ''
        self.first = ''
        self.second = ''
        self.action = ''
        super().__init__()
        self.title("Calculator")
        self.resizable(width=False, height=False)
        self.frame = ttk.Frame(self).grid()
        self.display = ttk.Entry(text='0',
                                 font=('Comic Sans MS', 25),
                                 foreground='#33334d',
                                 background='#e6e6e6')
        self.display.grid(row=0, columnspan=8, sticky=gui.W + gui.E)
        self.look_special = Style()
        self.look_operators = Style()
        self.look_numbers = Style()
        self.look_numbers.theme_use('alt')
        self.look_equal = Style()
        #styling buttons
        self.look_special.configure('s.TButton',
                                    relief='flat',
                                    font=('callbri', 13, 'bold'),
                                    foreground='red',
                                    ipading=0,
                                    borderwidth=1,
                                    background='#ffe6e6',
                                    focusthickness=3,
                                    focuscolor='none')
        self.look_operators.configure('op.TButton',
                                      relief='flat',
                                      font=('callbri', 13, 'bold'),
                                      foreground='blue',
                                      ipading=0,
                                      borderwidth=1,
                                      background='#ccffff',
                                      focusthickness=3,
                                      focuscolor='none')
        self.look_numbers.configure('num.TButton',
                                    relief='flat',
                                    font=('callbri', 13, 'bold'),
                                    bordercolor='black',
                                    ipading=0,
                                    foreground='black',
                                    background='#e6ffff',
                                    borderwidth=1,
                                    focusthickness=1,
                                    focuscolor='none')
        self.look_equal.configure('eq.TButton',
                                  relief='flat',
                                  font=('callbri', 13, 'bold'),
                                  foreground='#0000b3',
                                  ipading=0,
                                  borderwidth=1,
                                  background='#99d6ff',
                                  focusthickness=3,
                                  focuscolor='none')
        ##styling buttons on hover
        self.look_numbers.map('num.TButton',
                              foreground=[('pressed', 'black'),
                                          ('active', 'black')],
                              background=[('pressed', '!disabled', '#00ffff'),
                                          ('active', '#80ffff')])
        self.look_operators.map('op.TButton',
                                foreground=[('pressed', 'blue'),
                                            ('active', 'blue')],
                                background=[('pressed',
                                             '!disabled', '#00cccc'),
                                            ('active', '#4dffff')])
        self.look_special.map('s.TButton',
                              foreground=[('pressed', 'red'),
                                          ('active', 'red')],
                              background=[('pressed', '!disabled', '#ff8080'),
                                          ('active', '#ffb3b3')])
        self.look_equal.map('eq.TButton',
                            foreground=[('pressed', 'blue'),
                                        ('active', 'blue')],
                            background=[('pressed', '!disabled', '#33adff'),
                                        ('active', '#66c2ff')])

        self.buttons()

    def buttons(self):
        #printing numbers

        self.clc = ttk.Button(text="C",
                              style='s.TButton',
                              command=lambda: self.clearing())
        self.clc.grid(row=1, column=0, ipady=20, ipadx=8)

        self.div = ttk.Button(text="/",
                              style='op.TButton',
                              command=lambda: self.operate('/'))
        self.div.grid(row=1, column=1, ipady=20, ipadx=8)

        self.mul = ttk.Button(text="X",
                              style='op.TButton',
                              command=lambda: self.operate('x'))
        self.mul.grid(row=1, column=2, ipady=20, ipadx=8)

        self.back = ttk.Button(text="<-",
                               style='s.TButton',
                               command=lambda: self.backspace())
        self.back.grid(row=1, column=3, ipady=20, ipadx=8)

        self.seven = ttk.Button(text="7",
                                style='num.TButton',
                                command=lambda: self.getdata(7))
        self.seven.grid(row=2, column=0, ipady=20, ipadx=8)

        self.eighth = ttk.Button(text="8",
                                 style='num.TButton',
                                 command=lambda: self.getdata(8))
        self.eighth.grid(row=2, column=1, ipady=20, ipadx=8)

        self.nine = ttk.Button(text="9",
                               style='num.TButton',
                               command=lambda: self.getdata(9))
        self.nine.grid(row=2, column=2, ipady=20, ipadx=8)

        self.sub = ttk.Button(text="-",
                              style='op.TButton',
                              command=lambda: self.operate('-'))
        self.sub.grid(row=2, column=3, ipady=20, ipadx=8)

        self.four = ttk.Button(text="4",
                               style='num.TButton',
                               command=lambda: self.getdata(4))
        self.four.grid(row=3, column=0, ipady=20, ipadx=8)

        self.five = ttk.Button(text="5",
                               style='num.TButton',
                               command=lambda: self.getdata(5))
        self.five.grid(row=3, column=1, ipady=20, ipadx=8)

        self.six = ttk.Button(text="6",
                              style='num.TButton',
                              command=lambda: self.getdata(6))
        self.six.grid(row=3, column=2, ipady=20, ipadx=8)

        self.add = ttk.Button(text="+",
                              style='op.TButton',
                              command=lambda: self.operate('+'))
        self.add.grid(row=3, column=3, ipady=20, ipadx=8)

        self.one = ttk.Button(text="1",
                              style='num.TButton',
                              command=lambda: self.getdata(1))
        self.one.grid(row=4, column=0, ipady=20, ipadx=8)

        self.two = ttk.Button(text="2",
                              style='num.TButton',
                              command=lambda: self.getdata(2))
        self.two.grid(row=4, column=1, ipady=20, ipadx=8)

        self.three = ttk.Button(text="3",
                                style='num.TButton',
                                command=lambda: self.getdata(3))
        self.three.grid(row=4, column=2, ipady=20, ipadx=8)

        self.pow = ttk.Button(text="^",
                              style='op.TButton',
                              command=lambda: self.operate('^'))
        self.pow.grid(row=4, column=3, ipady=20, ipadx=8)

        self.equal = ttk.Button(text="=",
                                style='eq.TButton',
                                command=lambda: self.getdata('='))
        self.equal.grid(row=5, column=3, rowspan=2, ipady=50, ipadx=8)

        self.mod = ttk.Button(text="%",
                              style='op.TButton',
                              command=lambda: self.operate('%'))
        self.mod.grid(row=5, column=0, ipady=20, ipadx=8)

        self.zero = ttk.Button(text="0",
                               style='num.TButton',
                               command=lambda: self.getdata(0))
        self.zero.grid(row=5, column=1, ipady=20, ipadx=8)

        self.deci = ttk.Button(text=".",
                               style='num.TButton',
                               command=lambda: self.getdata('.'))
        self.deci.grid(row=5, column=2, ipady=20, ipadx=8)

        self.sine = ttk.Button(text="sin",
                               style='op.TButton',
                               command=lambda: self.trigno('sin'))
        self.sine.grid(row=6, column=0, ipady=20, ipadx=8)

        self.cos = ttk.Button(text="cos",
                              style='op.TButton',
                              command=lambda: self.trigno('cos'))
        self.cos.grid(row=6, column=1, ipady=20, ipadx=8)

        self.tan = ttk.Button(text="tan",
                              style='op.TButton',
                              command=lambda: self.trigno('tan'))
        self.tan.grid(row=6, column=2, ipady=20, ipadx=8)

    def clearing(self):
        self.display.delete(0, gui.END)
        self.first = ''
        self.second = ''
        self.op = -1
        self.x = ''

    def backspace(self):
        if self.op == -1:
            return
        if self.op == 0:
            self.first = str(self.first)
            self.first = self.first[:-1]
            self.display.delete(0, gui.END)
            check = type(self.first)
            if check == int:
                self.first = int(self.first)
            self.display.insert(0, self.first)

    def calc_trigno(self, x, point):
        x = float(x)
        if self.t_action == 'sin':
            self.ans = comp.sine(x)
        if self.t_action == 'tan':
            self.ans = comp.tangent(x)
        if self.t_action == 'cos':
            self.ans = comp.cosine(x)
        check = type(self.ans)
        if check == int:
            self.ans = int(self.ans)
        if point == -1:
            self.first = self.ans
            self.second = ''
            self.t_action = ""
            self.op = 3
        if point == 0:
            self.second = self.ans
            self.t_action = ''
            self.op = 2
            self.getdata('=')

        self.display.delete(0, gui.END)
        self.display.insert(0, self.ans)

    def calc(self, a, b, p):
        print(a)
        a = float(a)
        b = float(b)
        avi = ['+', '-', "/", 'x', '%', '^']
        if p in avi:
            if p == '+':
                self.ans = comp.add(a, b)
            if p == '-':
                self.ans = comp.sub(a, b)
            if p == 'x':
                self.ans = comp.multi(a, b)
            if p == '/':
                self.ans = comp.div(a, b)
            if p == '%':
                self.ans = comp.mod(a, b)
            if p == '^':
                self.ans = comp.power(a, b)

            check = type(self.ans)
            if check == int:
                self.ans = int(self.ans)
            self.first = self.ans
            self.second = ''
            self.action = ""
            self.op = 3
            self.display.delete(0, gui.END)
            self.display.insert(0, self.ans)

    def getdata(self, x):
        if self.op == 3 and self.action == '':
            self.first = ''
            self.display.delete(0, gui.END)
            self.display.insert(0, self.first)
            self.op = -1

        if self.op == 10 and x != '=':
            try:
                self.first += str(x)
                check = type(self.first)
                if check == int:
                    self.first = int(self.first)
                self.display.delete(0, gui.END)
                self.display.insert(0,
                                    str(self.t_action) + ' ' + str(self.first))

            except ValueError:
                print('first error')
                return

        if self.op == 12 and x != '=':
            try:
                self.second += str(x)
                check = type(self.second)
                if check == int:
                    self.second = int(self.second)
                self.display.delete(0, gui.END)
                self.display.insert(
                    0,
                    str(self.first) + str(self.action) + str(self.t_action) +
                    ' ' + str(self.second))

            except ValueError:
                print('first error')
                return

        if x == "=":
            if self.op == -1 or self.op == 0 or self.op == 1:
                return
            if self.op == 2:
                self.calc(self.first, self.second, self.action)
            if self.op == 10:
                self.calc_trigno(self.first, -1)
            if self.op == 12:
                self.calc_trigno(self.second, 0)

        if (self.op == -1 or self.op == 0) and x != '=':

            try:
                self.first += str(x)
                check = type(self.first)
                if check == int:
                    self.first = int(self.first)
                self.display.delete(0, gui.END)
                self.display.insert(0, self.first)
                print(self.first)
                if self.first != 0:
                    self.op = 0
            except ValueError:
                print('first error')
                return
        if (self.op == 1 or self.op == 2) and x != '=':
            try:
                self.second += str(x)
                check = type(self.second)
                if check == int:
                    self.second = int(self.second)

                self.display.delete(0, gui.END)
                self.display.insert(
                    0,
                    str(self.first) + self.action + str(self.second))

                if self.second != 0:
                    self.op = 2
            except ValueError:
                print('second error')
                return

    def operate(self, y):
        if self.op == -1:
            if y == '-' or y == '+':
                self.sign = y
                self.action = ''
                self.op = 0

        if self.op == 0:
            self.action = y
            self.op = 1
            self.display.delete(0, gui.END)
            check = type(self.first)
            if check == int:
                self.first = int(self.first)
            self.display.insert(0, str(self.first) + y)
        if self.op == 2:
            self.getdata('=')
            self.action = y
        if self.op == 3:
            self.action = y
            self.op = 1
            self.display.delete(0, gui.END)
            check = type(self.first)
            if check == int:
                self.first = int(self.first)
            self.display.insert(0, str(self.first) + y)

    def trigno(self, t):
        if self.op == -1:
            self.op = 10
            self.t_action = t
            self.display.delete(0, gui.END)
            self.display.insert(0, self.t_action)
        if self.op == 1:
            self.op = 12
            self.t_action = t
            self.display.delete(0, gui.END)
            self.display.insert(0, self.first + self.action + self.t_action)

    def run(self):
        self.mainloop()
Beispiel #18
0
class cGUI:
  def __init__(self): #accept a q for the Queue Object
    self.database = IC_Database.database(False)

    #initial IC statuses
    self.mS1 = cStatus.OFFLINE
    self.mS2 = cStatus.OFFLINE
    self.mS3 = cStatus.OFFLINE

    self.toShutdown = ['offline', 'offline', 'offline']

    #Root frame
    self.mRoot = Tk()
    self.mNote = Notebook(self.mRoot) #notebook used to create tabs

    #Gif Frames
    self.frames =[PhotoImage(file="pi.gif", format="gif -index %i" %(i)) for i in range(80)]
    self.idx1 = 0
    self.idx2 = 0
    self.idx3 = 0

    self.mRoot.title("VIEC Network System Status")  #set title
    self.mRoot.attributes("-zoomed", True)          #start in fullscreen

    #Placing Notebook and create tab frames
    self.mNote.grid(row=0, column=0)
    self.mStatusTab = Frame(self.mNote)
    self.mHelpTab = Frame(self.mNote)

    #add tabs to notebook
    self.mNote.add(self.mStatusTab, text="IC Statuses")
    self.mNote.add(self.mHelpTab, text="Help")
    self.mRoot.attributes("-alpha", 0)      #set window as transparent
    self.mRoot.update()                     #displays window
    self.mOffset = self.mNote.winfo_reqheight() #size of the tabs

    self.height, self.width = self.getScreenSize()  #get usable screen size
    self.mUsable = self.height - (2*self.mOffset) #size for status tab = screen size - tab size

############### STATUS TAB #####################################################################
    #setting column and row sizes for Status tab
    self.mStatusTab.grid_rowconfigure(0, weight=1, minsize=(self.mUsable/2))
    self.mStatusTab.grid_rowconfigure(1, weight=1, minsize=(self.mUsable/2))
    self.mStatusTab.grid_columnconfigure(0, weight=1, minsize=(self.width))

    #splitting status tab into two frames
    self.mTopFrame = Frame(self.mStatusTab, width=self.width, height=(self.mUsable/2))
    self.mTopFrame.grid(row=0)
    self.mTopFrame.grid_rowconfigure(0, weight=1, minsize=(self.mUsable/2))
    self.mTopFrame.grid_columnconfigure(0, weight=1, minsize=(self.width/2))
    self.mTopFrame.grid_columnconfigure(1, weight=1, minsize=(self.width/2))

    self.mBottomFrame = Frame(self.mStatusTab, width=self.width, height=(self.mUsable/2))
    self.mBottomFrame.grid(row=1)
    self.mBottomFrame.grid_rowconfigure(0, weight=1, minsize=(self.mUsable/2))
    self.mBottomFrame.grid_columnconfigure(0, weight=1, minsize=self.width)

    #IC Frames
    self.mIC1 = Frame(self.mTopFrame, width=(self.width/2), height=(self.mUsable/2))
    self.mIC1.grid(row=0, column=0)
    self.mIC1.grid_columnconfigure(0, weight=1, minsize=(self.width/2))

    self.mIC2 = Frame(self.mTopFrame, width=(self.width/2), height=(self.mUsable/2))
    self.mIC2.grid(row=0, column=1)
    self.mIC2.grid_columnconfigure(0, weight=1, minsize=(self.width/2))

    self.mIC3 = Frame(self.mBottomFrame, width=self.width, height=(self.mUsable))
    self.mIC3.grid(row=0, column=0)
    self.mIC3.grid_columnconfigure(0, weight=1, minsize=self.width)

    #IC Styles
    self.s = Style()
    self.s.configure("offline.TButton", font=(None, 15), pady=3, foreground='black', state=DISABLED)
    self.s.map('offline.TButton',foreground=[('disabled', 'black')])
    self.s.configure("runnning.TButton", font=(None, 15), pady=3, foreground='green', state=NORMAL)
    self.s.configure("caution.TButton", font=(None, 15), pady=3, foreground='yellow4', state=NORMAL)
    self.s.configure("failed.TButton", font=(None, 15), pady=3, foreground='red', state=NORMAL)

    #add IC1 widgets
    self.mIC1Label = Label(self.mIC1, text="Habitat Lighting System", font=(None, 15), pady=5)
    self.mIC1Label.grid(row=0, column=0)

    self.mIC1ImageLabel = Label(self.mIC1, image=self.frames[0], width=128, height=128)
    self.mIC1ImageLabel.grid(row=1)

    self.mIC1Status = Button(self.mIC1, text="Offline", style='offline.TButton', state=DISABLED, command=lambda app=1: self.shutdownIC(app))
    self.mIC1Status.grid(row=2)

    #add IC2 widgets
    self.mIC2Label = Label(self.mIC2, text="Environment Monitoring System",
                           font=(None, 15),pady=5)
    self.mIC2Label.grid(row=0, column=0)

    self.mIC2ImageLabel = Label(self.mIC2, image=self.frames[0], width=128, height=128)
    self.mIC2ImageLabel.grid(row=1)

    self.mIC2Status = Button(self.mIC2, text="Offline", style='offline.TButton', state=DISABLED, command=lambda app=2: self.shutdownIC(app))
    self.mIC2Status.grid(row=2, column=0)

    #add IC3 widgets
    self.mIC3Label = Label(self.mIC3, text="Reaction Control System", font=(None, 15), pady=5)
    self.mIC3Label.grid(row=0, column=0)

    self.mIC3ImageLabel = Label(self.mIC3, image=self.frames[0], width=128, height=128)
    self.mIC3ImageLabel.grid(row=1)

    self.mIC3Status = Button(self.mIC3, text="Offline", style='offline.TButton', state=DISABLED, command=lambda app = 3: self.shutdownIC(app))
    self.mIC3Status.grid(row=2)

############### HELP TAB #######################################################################

    self.mHelpTab.grid_columnconfigure(0, weight=1, minsize=self.width)
    self.mHelpTab.grid_rowconfigure(0, weight=1, minsize=self.mUsable/8)
    self.mHelpTab.grid_rowconfigure(1, weight=1, minsize=3*self.mUsable/8)
    self.mHelpTab.grid_rowconfigure(2, weight=1, minsize=1*self.mUsable/8)

    self.help =PhotoImage(file="help.gif", format="gif")

    self.mHelpTitleLabel = Label(self.mHelpTab, text="How to Replace ICs", font=(None, 20), pady=5)
    self.mHelpTitleLabel.grid(row=0, column=0)

    self.mHelpImageLabel = Label(self.mHelpTab, image=self.help, width=300, height=225)
    self.mHelpImageLabel.grid(row=1)

    self.mHelpInsLabel = Label(self.mHelpTab, text="1. Remove the Ethernet, Power, and Universal Connector\
    \n 2. Plug in new IC                                                                        "\
    , font=(None, 15), pady=5)
    self.mHelpInsLabel.grid(row=2, column=0)

############### START GUI #######################################################################

    self.mRoot.after(25, self.updateGif)
    self.mRoot.after(1000, self.update)
    self.mRoot.protocol("WM_DELETE_WINDOW", self.onClosing)
    self.shutdown = False

  def onClosing(self):
    self.shutdown = True
    tkinter.messagebox.showinfo("System Shutdown", "Shutting down... Please wait.")

  def getScreenSize(self):
    height = self.mRoot.winfo_height()      #get current height of screen
    width  = self.mRoot.winfo_width()       #get current width of screen 
    self.mRoot.attributes("-alpha", 1)      #set window as opaque
    return (height, width)

  def update(self):
    self.mS1 = self.setStatus(self.mS1, self.mIC1Status, (1,))
    self.mS2 = self.setStatus(self.mS2, self.mIC2Status, (2,))
    self.mS3 = self.setStatus(self.mS3, self.mIC3Status, (3,))
    self.mRoot.after(1000, self.update)

  def updateGif(self):    
    status1 = self.database.getStatus((1,))
    if len(status1) != 0 and (status1[0][0] == 'RUNNING' or status1[0][0] == 'CAUTION'):
        self.idx1 = (self.idx1 + 1) % 80 
        self.mIC1ImageLabel.configure(image=self.frames[self.idx1])

    status2 = self.database.getStatus((2,))
    if len(status2) != 0 and (status2[0][0] == 'RUNNING' or status2[0][0] == 'CAUTION'):
        self.idx2 = (self.idx2 + 1) % 80 
        self.mIC2ImageLabel.configure(image=self.frames[self.idx2])
    
    status3 = self.database.getStatus((3,))
    if len(status3) != 0 and (status3[0][0] == 'RUNNING' or status3[0][0] == 'CAUTION'):
        self.idx3 = (self.idx3 + 1) % 80 
        self.mIC3ImageLabel.configure(image=self.frames[self.idx3])

    self.mRoot.after(35, self.updateGif)

  def setStatus(self, oldS, label, app):
    #this is where the database will be read
    status = (self.database.getStatus(app))

    if len(status) != 0:
      if status[0][0] == 'RUNNING':   newS = cStatus.RUNNING
      elif status[0][0] == 'CAUTION': newS = cStatus.CAUTION
      elif status[0][0] == 'FAILED' : newS = cStatus.FAILED
      else: raise Exception
    else: 
      newS = cStatus.OFFLINE
      self.toShutdown[app[0]-1] = 'offline'
      
    if oldS != newS:
        self.setStatusString(newS, label)
    return newS

  def setStatusString(self, s, label):
    if s == cStatus.OFFLINE:
      label.configure(text="Offline", state=DISABLED, style='offline.TButton') #fg="black",
    elif s == cStatus.RUNNING:
      label.configure(text="Running", state=NORMAL, style='runnning.TButton')#fg="green",
    elif s == cStatus.CAUTION:
      label.configure(text="Not Responding", state=NORMAL, style='caution.TButton')#, fg="yellow4")
    else:
      label.configure(text="Failed", state=NORMAL, style='failed.TButton')#, fg="red")

  def shutdownIC(self, app): #function to trigger a shutdown sequence for a particular IC
    self.toShutdown[app-1] = 'true'
Beispiel #19
0
class MainFrame(Frame):

    def __init__(self, parent):
        super().__init__(parent)
        self.parent = parent

        self.parent.title("InstaDjango")

        self.pack(fill=BOTH, expand=1)
        self.size_and_center_window()

        self.style = Style()
        self.style.theme_use("clam")
        self.style.configure("TFrame", background="#808080", foreground="white")
        self.style.configure("TButton", background="#808080", foreground="white")
        self.style.configure("high.TButton", background="#8FBC8B", foreground="white")
        self.style.configure("TLabel", background="#808080", foreground="white")
        self.style.map("TButton", background=[("pressed", "#404040"), ("active", "#A0A0A0")])

        frame = Frame(self, relief=FLAT, borderwidth=1)
        frame.pack(fill=BOTH, expand=1)

        subframe_0 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_0.pack(fill=X)
        lbl_0 = Label(subframe_0, text="App's machine-readable name (used for naming folders locally and remotely):", style="TLabel")
        lbl_0.pack(fill=BOTH, padx=10, pady=10)
        entry_0 = Entry(subframe_0)
        entry_0.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_0, "")

        subframe_1 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_1.pack(fill=X)
        lbl_1 = Label(
            subframe_1, text="Where to create the app's folder locally:", style="TLabel")
        lbl_1.pack(fill=BOTH, padx=10, pady=10)
        entry_1 = Entry(subframe_1)

        def action_1():
            cdir = filedialog.askdirectory(title="Please select a directory")
            if cdir:
                self.set_entry_text(entry_1, cdir)

        button_1 = Button(subframe_1, text="Choose", command=action_1, style="TButton")
        button_1.pack(side=RIGHT, padx=10, pady=0)
        entry_1.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_1, "")

        subframe_2 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_2.pack(fill=X)
        lbl_2 = Label(subframe_2, text="Remote host:", style="TLabel")
        lbl_2.pack(fill=BOTH, padx=10, pady=10)
        entry_2 = Entry(subframe_2)
        entry_2.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_2, "")

        subframe_3 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_3.pack(fill=X)
        lbl_3 = Label(
            subframe_3, text="Remote SSH port (empty will mean the default port):", style="TLabel")
        lbl_3.pack(fill=BOTH, padx=10, pady=10)
        entry_3 = Entry(subframe_3)
        entry_3.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_3, "")

        subframe_4 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_4.pack(fill=X)
        lbl_4 = Label(subframe_4, text="Remote user:"******"TLabel")
        lbl_4.pack(fill=BOTH, padx=10, pady=10)
        entry_4 = Entry(subframe_4)
        entry_4.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_4, "")

        subframe_5 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_5.pack(fill=X)
        lbl_5 = Label(
            subframe_5, text="Local path to the SSH private key:", style="TLabel")
        lbl_5.pack(fill=BOTH, padx=10, pady=10)
        entry_5 = Entry(subframe_5)

        def action_5():
            cdir = filedialog.askopenfilename(title="Please select a private key")
            if cdir:
                self.set_entry_text(entry_5, cdir)

        button_5 = Button(subframe_5, text="Choose", command=action_5, style="TButton")
        button_5.pack(side=RIGHT, padx=10, pady=0)
        entry_5.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_5, "")

        subframe_6 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_6.pack(fill=X)
        lbl_6 = Label(
            subframe_6, text="Where to create the app's folder remotely (should not be owned by root):", style="TLabel")
        lbl_6.pack(fill=BOTH, padx=10, pady=10)
        entry_6 = Entry(subframe_6)
        entry_6.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_6, "/var/www")

        subframe_7 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_7.pack(fill=X)
        lbl_7 = Label(subframe_7, text="Sudo password:"******"TLabel")
        lbl_7.pack(fill=BOTH, padx=10, pady=10)
        entry_7 = Entry(subframe_7, show="*")
        entry_7.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_7, "")

        subframe_8 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_8.pack(fill=X)
        lbl_8 = Label(subframe_8, text="Database password:"******"TLabel")
        lbl_8.pack(fill=BOTH, padx=10, pady=10)
        entry_8 = Entry(subframe_8, show="*")
        entry_8.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_8, "")

        subframe_9 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_9.pack(fill=X)
        lbl_9 = Label(subframe_9, text="Domain:", style="TLabel")
        lbl_9.pack(fill=BOTH, padx=10, pady=10)
        entry_9 = Entry(subframe_9)
        entry_9.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_9, "dev.example.com")

        subframe_10 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_10.pack(fill=X)
        lbl_10 = Label(subframe_10, text="Django installation type (local, production, staging):", style="TLabel")
        lbl_10.pack(fill=BOTH, padx=10, pady=10)
        entry_10 = Entry(subframe_10)
        entry_10.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_10, "local")

        def go():
            setup_django_project(
                proj=entry_0.get(),
                proj_local_parent_dir=entry_1.get(),
                host=entry_2.get(),
                port=entry_3.get(),
                user=entry_4.get(),
                ssh_key=entry_5.get(),
                proj_remote_parent_dir=entry_6.get(),
                sudo_pass=entry_7.get(),
                db_pass=entry_8.get(),
                domain=entry_9.get(),
                insta_type=entry_10.get())
            self.quit()
        inst_button = Button(self, text="Go", command=go, style="high.TButton")
        inst_button.pack(side=RIGHT, padx=10, pady=10)

        quit_button = Button(self, text="Quit", command=self.quit, style="TButton")
        quit_button.pack(side=RIGHT, pady=10)

    def size_and_center_window(self):
        w = 640
        h = 850
        sw = self.parent.winfo_screenwidth()
        sh = self.parent.winfo_screenheight()
        x = (sw - w)/2
        y = (sh - h)/2
        self.parent.geometry("%dx%d+%d+%d" % (w, h, x, y))

    @staticmethod
    def set_entry_text(e, text):
        e.delete(0, END)
        e.insert(0, text)
Beispiel #20
0
class AbstractTkApp(threading.Thread):
    __metaclass__ = ABCMeta

    def __init__(self):
        super().__init__()
        self.logger = logging.getLogger(self.__class__.__name__)

        self.window = None
        self.window_title = f"{PROJECT_NAME}"
        self.window_background_text = ""

        self.style = None

        self.top_frame = None
        self.bottom_frame = None

        self.start()

    def run(self):
        try:
            self.window = Tk()

            # set style
            self.style = Style()
            self.style.configure('Bot.TButton',
                                 background=BACKGROUND_COLOR,
                                 foreground=BUTTON_TEXT_COLOR)
            self.style.map('Bot.TButton',
                           background=[('active', ACTIVE_COLOR)],
                           relief=[('pressed', '!disabled', 'sunken')])
            self.style.configure('Bot.TFrame', background=BACKGROUND_COLOR)
            self.style.configure('Bot.TLabel',
                                 background=BACKGROUND_COLOR,
                                 foreground="white")
            self.style.configure('Bot.Horizontal.TProgressbar',
                                 foreground=PROGRESS_BAR_COLOR,
                                 background=PROGRESS_BAR_COLOR)

            # window settings
            self.window.title(self.window_title)
            self.window.protocol("WM_DELETE_WINDOW", self.close_callback)
            # self.window.configure(background=BACKGROUND_COLOR)

            try:
                self.window.iconbitmap('interfaces/web/static/favicon.ico')
            except Exception as e:
                self.logger.error("Failed to load tk window icon" + str(e))

            self.window.geometry(f"{WINDOW_SIZE_WIDTH}x{WINDOW_SIZE_HEIGHT}")

            # background
            try:
                background_image = PhotoImage(
                    file="interfaces/web/static/img/octobot.png")
                background_label = tkinter.Label(
                    self.window,
                    image=background_image,
                    text=self.window_background_text,
                    compound=CENTER,
                    background=BACKGROUND_COLOR)

                background_label.place(x=0, y=0, relwidth=1, relheight=1)
            except Exception as e:
                self.logger.error("Failed to load tk window background" +
                                  str(e))

            # frames
            self.top_frame = Frame(self.window, style='Bot.TFrame')
            self.bottom_frame = Frame(self.window, style='Bot.TFrame')
            self.top_frame.pack(side="top", fill="y", expand=False)
            self.bottom_frame.pack(side="bottom", fill="y", expand=False)

            self.create_components()

            self.start_app()

        except _tkinter.TclError as e:
            self.logger.exception(f"Failed to start tk_app : {e}")

    @staticmethod
    @abstractmethod
    def close_callback():
        pass

    def create_components(self):
        pass

    def start_app(self):
        self.window.mainloop()

    def stop(self):
        self.window.quit()
Beispiel #21
0
class explorer(tk.Toplevel):
    def __init__(self, *args, **kwargs):
        tk.Toplevel.__init__(self, *args, **kwargs)
        self.geometry(f"{WIDTH}x{HEIGHT}")
        self.title("Explorer")
        """
		Map to connect the string id's of the various nodes with layout:
		{
			{"entry" : DirEntry, "built" : False},
			{"entry" : DirEntry, "built" : False},
			...
		}
		"built" indicates whether or not the node has been populated
		assuming it has children nodes.

		DirEntry is an object produced by the itterable os.scandir()
		It has several methods  it similar to those in the module os.path
		such as is_file, is_dir, and stat, and the object caches these
		values for later calls, resulting in better performance.

		The root node is mapped to "" and uses an artifical DirEntry.
		The rest are mapped to their string id's provided at the time of the node's creation.
		"""
        self.node_map = {}

        self.style = Style(self)
        #Style treeview, not styling means
        #later calls to tag_configure() don't work
        self.style.map("Treeview",
                       foreground=[("disabled", "white")],
                       background=[("disabled", "black")])

        #If a path was passed set the current dir to it
        #Otherwise set it to the user's home dir
        if "path" in args: self.current_dir = kwargs.pop("path")
        else: self.current_dir = os.path.expanduser("~")

        self.set_title(self.current_dir)
        self.file_icon = load_tk_image_from_bytes_array(file_image_bytes)
        self.folder_icon = load_tk_image_from_bytes_array(folder_image_bytes)

        self.outer_frame = LabelFrame(self)
        self.outer_frame.pack(fill="both", expand=1, padx=5, pady=5)

        #Top row, frame to add a path to enter a path and button to go to it
        self.path_frame = Frame(self.outer_frame)
        self.path_frame.pack(side="top", expand=0, fill="x")
        self.path_box = Entry(self.path_frame)
        self.path_box.pack(side="left",
                           expand=1,
                           fill="both",
                           padx=5,
                           pady=(1, 5))
        self.submit_path_button = Button(self.path_frame,
                                         text="⏎",
                                         command=self.submit_path)
        self.submit_path_button.pack(side="right",
                                     expand=0,
                                     fill="both",
                                     padx=(0, 4),
                                     pady=(0, 4))  #Buttons have weird padding

        self.tree = ScrolledTree(self.outer_frame,
                                 columns=("size", "modified"))
        self.tree.pack(side="top", expand=1, fill="both", padx=5, pady=(0, 5))
        self.tree.bind("<Double-1>", self.on_double_click)
        self.tree.bind("<<TreeviewOpen>>", self.on_open)
        self.tree.column("#0", width=150)
        self.tree.column("size", width=60, minwidth=60, stretch="no")
        self.tree.column("modified", width=150, minwidth=150, stretch="no")
        self.tree.heading("#0", text="...", anchor="w")
        self.tree.heading("size", text="Size", anchor="w")
        self.tree.heading("modified", text="Modified", anchor="w")

        self.populate(self.current_dir)

    def set_title(self, string):
        self.title(f"TK Explorer - {string}")

    def submit_path(self):
        self.populate(self.tree.selection()[0])

    def on_open(self, event):
        #Get current node and attempt to build it
        #build_node will immediately return if already built
        self.build_node(self.tree.focus())

    def populate(self, dir: os.path):
        self.current_dir = dir
        self.node_map = {}  #Clear node map
        self.tree.delete(*self.tree.get_children())
        self.set_title(self.current_dir)
        self.build_tree()
        self.outer_frame.configure(
            text=self.current_dir)  #Set frame label text

    def build_tree(self):
        """Fills the tree with the contents of the path at self.current_dir"""
        #Create entry in the node map for the tree root
        self.node_map[""] = {
            "entry": DirEntry(self.current_dir),
            "built": False
        }
        self.build_node("")  #Build tree root

    def build_node(self, node: id):
        """"""
        node_dict = self.node_map[node]
        if node_dict["built"]: return

        path = node_dict["entry"]
        self.tree.delete(*self.tree.get_children(node))
        try:
            dir_items = os.scandir(path.path)
        except PermissionError:
            dir_items = []

        files, folders_then_both = [], []
        for entry in dir_items:  #Sort files from folders
            files.append(
                entry) if entry.is_file() else folders_then_both.append(entry)
        folders_then_both.extend(files)  #Sort folders-first
        for entry in folders_then_both:
            if entry.is_file():
                size = _sizeof_fmt(os.path.getsize(
                    entry.path))  #Get friendly file size
                modified = _get_human_mtime(
                    entry.path)  #Get human modified time
            else:
                size = ""
                modified = ""

            branch = self.tree.insert(node,
                                      "end",
                                      text=entry.name,
                                      values=(size, modified, ""))
            self.build_branch(branch, entry)  #Flesh out the branch
            #Built status is set to false if it's a dir since it may have children
            self.node_map[branch] = {"entry": entry, "built": entry.is_file()}

        self.node_map[node]["built"] = True

    def build_branch(self, branch: id, entry: DirEntry):
        #Flesh out an empty branch
        #Adds an image to the branch based on its type (file or folder)
        #Also adds a + to the node if it has children
        if entry.is_dir():
            try:
                self.tree.item(branch, image=self.folder_icon)
                if os.scandir(entry.path):
                    #Insert a single empty node in the branch.
                    #This is so the branch has a clickable +,
                    #when the + is clicked build_node(branch) is called.
                    #The empty node gets erased when build_node gets called.
                    self.tree.insert(branch,
                                     "end",
                                     text=".",
                                     values=("", "", ""))
            except PermissionError:  #make folder appear empty if no permission to access it
                print(entry.path)
                pass
        else:
            self.tree.item(branch, image=self.file_icon)

    def on_double_click(self, event):
        region = self.tree.identify("region", event.x, event.y)
        column = self.tree.identify_column(event.x) == "#0"
        if region == "heading" and column:  # If clicking on the "..." on the top left
            self.populate(os.path.dirname(self.current_dir))
        else:
            node_dict = self.node_map[self.tree.selection()[0]]
            if node_dict["entry"].is_dir():
                self.populate(node_dict["entry"].path)
    # ('!disabled', '!selected', ...) filtered out.

    # style.map() returns an empty list for missing options, so this
    # should be future-safe.
    return [
        elm for elm in st1.map('Treeview', query_opt=option)
        if elm[:2] != ('!disabled', '!selected')
    ]


root = Tk()
st1 = Style()
st1.theme_use('default')

st1.map('Treeview',
        foreground=fixed_map('foreground'),
        background=fixed_map('background'))

fact = font.Font(font="TkDefaultFont").metrics('linespace')
st1.configure('font.Treeview',
              rowheight=fact,
              font=font.nametofont("TkDefaultFont"))

# determine Heading font based on TkDefaultFont
def_font = font.nametofont('TkDefaultFont')
font_family = def_font.actual()['family']
font_size = def_font.actual()['size'] + 1
# st1.configure('font.Treeview.Heading', font='TkHeadingFont')
st1.configure('font.Treeview.Heading', font=(font_family, font_size, 'bold'))

Beispiel #23
0
def Tree(fr,outVar):
    s = Style()
    s.theme_use('default')

    s.map('Treeview', foreground=fixed_map(s,'foreground'),
            background=fixed_map(s,'background'))

    test_length = font.Font(family="Times", size=12, weight="bold").measure('Test')
    fact = int(test_length / 30 * 20.45) # 30 is the length of Test in Idle

    s.configure('Treeview', rowheight= fact)

    s.configure('font.Treeview', font='TkDefaultFont')
    # determine Heading font based on TkDefaultFont
    s.configure('font.Treeview', font='TkDefaultFont')
    def_font = font.nametofont('TkDefaultFont')
    font_family = def_font.actual()['family']
    font_size = def_font.actual()['size'] + 1
    s.configure('font.Treeview.Heading', font=(font_family,font_size,'bold'))

    # function to enable selection
    def selectItem(evt):
        curItem = tree.focus()
        lvar.set(tree.item(curItem)['values'])
        outVar.set(tree.item(curItem)['values'])

    def sortBy(tree, col, descending):
        # When a column is clicked on sort tree contents .
        # grab values to sort
        data = [(tree.set(child, col), child) for child in tree.get_children('')]

        # reorder data
        data.sort(reverse=descending)
        for indx, item in enumerate(data):
            tree.move(item[1], '', indx)

        # switch the heading so that it will sort in the opposite direction
        tree.heading(col, command=lambda col=col: sortBy(tree, col, int(not descending)))

        # reconfigure tags after ordering
        list_of_items = tree.get_children('')
        for i in range(len(list_of_items)):
            tree.tag_configure(list_of_items[i], background=backg[i%2])

    # headings and data
    treeColumns = ['Colours', 'Hash', 'RGB', 'Extra long header']

    treeData = (('red', '#FF0000', (255,0,0)),
            ('yellow', '#FFFF00', (255,255,0)),
            ('blue', '#0000FF', (0,0,255)),
            ('green', '#00FF00', (0,255,0)),
            ('magenta', '#FF00FF', (255,0,255)),
            ('cyan', '#00FFFF', (0,255,255)),
            ('foo', 'bar', 'bong', 'ding a ling ping'))

    backg = ["white",'#f0f0ff']

    # create Treeview widget
    tree = Treeview(fr, column=treeColumns, show='headings',style='font.Treeview')
    tree.grid(column=0, row=0, sticky='nsew')
    tree.bind("<<TreeviewSelect>>", selectItem)

    vsb = Scrollbar(fr,orient="vertical", command=tree.yview)
    vsb.grid(column=1, row=0, sticky='ns')
    hsb = Scrollbar(fr,orient="horizontal", command=tree.xview)
    hsb.grid(column=0, row=1,  sticky='ew')

    tree.configure(xscrollcommand=hsb.set,yscrollcommand=vsb.set)
    fr.grid_columnconfigure(0, weight=1)
    fr.grid_rowconfigure(0, weight=1)

    # insert header, data and tag configuration
    for ix,col in enumerate(treeColumns):
        tree.heading(col, text=col.title(),
            command=lambda c=col: sortBy(tree, c, 0))
        #tree.column(col,stretch=True)
        #tree.column(col,width=font.nametofont('TkHeadingFont').measure(col.title()),
                #stretch=False)
        tree.column(col,width=font.Font(family=font_family,size=font_size, weight="bold").measure(col.title()) + 10,
                stretch=False)
        #print(tree.column(col))

    # insert data row by row, then measure each items' width
    for ix, item in enumerate(treeData):
        itemID = tree.insert('', 'end', values=item)
        tree.item(itemID, tags=itemID)
        tree.tag_configure(itemID, background=backg[ix%2])

        for indx, val in enumerate(item):
            #ilen = font.Font(family="Segoe UI", size=10, weight="normal").measure(val)
            ilen = font.nametofont('TkDefaultFont').measure(val)
            if tree.column(treeColumns[indx], width=None) < ilen +10:
                tree.column(treeColumns[indx], width=ilen + 10)
            # you should see the widths adjust
            #print('col',tree.column(treeColumns[indx]),ilen)

    # display selection
    lvar = StringVar()
    lbl = Label(fr, textvariable=lvar, text="Ready")
    lbl.grid(column=0, row=2, sticky='nsew')
Beispiel #24
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")
Beispiel #25
0
    def __init__(self, master):
        """Create Config dialog."""
        Toplevel.__init__(self, master, class_='MyNotes')
        self.title(_("Preferences"))
        self.grab_set()
        self.protocol("WM_DELETE_WINDOW", self.quit)
        self.changes = {}, {}, False, False
        self.minsize(width=430, height=450)

        # --- 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)
        okcancel_frame.pack(fill="x", side='bottom')
        self.notebook.pack(expand=True, fill="both")

        # --- * General settings
        self._init_general()

        # --- * Font settings
        self._init_font()

        # --- * Categories
        self.category_settings = CategoryManager(self.notebook, master)
        self.notebook.add(self.category_settings,
                          text=_("Categories"),
                          sticky="ewsn",
                          padding=4)
        # --- * Symbols
        size = CONFIG.get("Font", "text_size")
        family = CONFIG.get("Font", "text_family")
        symbols_settings = Frame(self.notebook, padding=4)
        self.notebook.add(symbols_settings,
                          text=_("Symbols"),
                          sticky="ewsn",
                          padding=4)
        txt_frame = Frame(symbols_settings,
                          relief="sunken",
                          borderwidth=1,
                          style="text.TFrame")
        txt_frame.rowconfigure(0, weight=1)
        txt_frame.columnconfigure(0, weight=1)
        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))
        scroll_y = AutoScrollbar(txt_frame,
                                 orient='vertical',
                                 command=self.symbols.yview)
        self.symbols.configure(yscrollcommand=scroll_y.set)

        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.grid(sticky='ewns')
        scroll_y.grid(row=0, column=1, sticky='ns')
        Button(symbols_settings, text=_('Reset'),
               command=self.reset_symbols).pack(padx=4, pady=4)

        # --- * AutoCorrect
        self.autocorrect_settings = AutoCorrectConfig(self.notebook, master)
        self.notebook.add(self.autocorrect_settings,
                          text=_("AutoCorrect"),
                          sticky="ewsn",
                          padding=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")
Beispiel #26
0
    def __init__(self,
                 master,
                 columns,
                 data=None,
                 command=None,
                 sort=True,
                 select_mode=None,
                 heading_anchor=CENTER,
                 cell_anchor=W,
                 style=None,
                 height=None,
                 padding=None,
                 adjust_heading_to_content=False,
                 stripped_rows=None,
                 selection_background=None,
                 selection_foreground=None,
                 field_background=None,
                 heading_font=None,
                 heading_background=None,
                 heading_foreground=None,
                 cell_pady=2,
                 cell_background=None,
                 cell_foreground=None,
                 cell_font=None,
                 headers=True):

        self._stripped_rows = stripped_rows

        self._columns = columns

        self._number_of_rows = 0
        self._number_of_columns = len(columns)

        self.row = self.List_Of_Rows(self)
        self.column = self.List_Of_Columns(self)

        s = Style()

        if style is None:
            style_name = "Multicolumn_Listbox%s.Treeview" % self._style_index
            self._style_index += 1
        else:
            style_name = style

        style_map = {}
        if selection_background is not None:
            style_map["background"] = [('selected', selection_background)]

        if selection_foreground is not None:
            style_map["foeground"] = [('selected', selection_foreground)]

        if style_map:
            s.map(style_name, **style_map)

        style_config = {}
        if cell_background is not None:
            style_config["background"] = cell_background

        if cell_foreground is not None:
            style_config["foreground"] = cell_foreground

        if cell_font is None:
            font_name = s.lookup(style_name, "font")
            cell_font = nametofont(font_name)
        else:
            if not isinstance(cell_font, Font):
                if isinstance(cell_font, basestring):
                    cell_font = nametofont(cell_font)
                else:
                    if len(Font) == 1:
                        cell_font = Font(family=cell_font[0])
                    elif len(Font) == 2:
                        cell_font = Font(family=cell_font[0],
                                         size=cell_font[1])

                    elif len(Font) == 3:
                        cell_font = Font(family=cell_font[0],
                                         size=cell_font[1],
                                         weight=cell_font[2])
                    else:
                        raise ValueError(
                            "Not possible more than 3 values for font")

            style_config["font"] = cell_font

        self._cell_font = cell_font

        self._rowheight = cell_font.metrics("linespace") + cell_pady
        style_config["rowheight"] = self._rowheight

        if field_background is not None:
            style_config["fieldbackground"] = field_background

        s.configure(style_name, **style_config)

        heading_style_config = {}
        if heading_font is not None:
            heading_style_config["font"] = heading_font
        if heading_background is not None:
            heading_style_config["background"] = heading_background
        if heading_foreground is not None:
            heading_style_config["foreground"] = heading_foreground

        heading_style_name = style_name + ".Heading"
        s.configure(heading_style_name, **heading_style_config)

        treeview_kwargs = {"style": style_name}

        if height is not None:
            treeview_kwargs["height"] = height

        if padding is not None:
            treeview_kwargs["padding"] = padding

        if headers:
            treeview_kwargs["show"] = "headings"
        else:
            treeview_kwargs["show"] = ""

        if select_mode is not None:
            treeview_kwargs["selectmode"] = select_mode

        self.interior = Treeview(master, columns=columns, **treeview_kwargs)

        if command is not None:
            self._command = command
            self.interior.bind("<<TreeviewSelect>>", self._on_select)

        for i in range(0, self._number_of_columns):

            if sort:
                self.interior.heading(
                    i,
                    text=columns[i],
                    anchor=heading_anchor,
                    command=lambda col=i: self.sort_by(col, descending=False))
            else:
                self.interior.heading(i,
                                      text=columns[i],
                                      anchor=heading_anchor)

            if adjust_heading_to_content:
                self.interior.column(i, width=Font().measure(columns[i]))

            self.interior.column(i, anchor=cell_anchor)

        if data is not None:
            for row in data:
                self.insert_row(row)
Beispiel #27
0
  """

from tkinter import Tk, Frame, StringVar, font, Label
from tkinter.ttk import Notebook, Button, Style
import sys
sys.path.insert(1, '../treeview/')
from tree_function import Tree

root = Tk()
st1 = Style()
st1.theme_use('default')
st1.configure(
    'green.TNotebook.Tab',
    background='light green',
    foreground='blue')
st1.map('green.TNotebook.Tab', background=[
        ('disabled', '#d9d9d9'), ('selected', '#bceebc')])

test_size = font.Font(family="Times", size=12, weight="bold").measure('Test')
mult = int(test_size / 30)

def tab_changed(event):
    """notebook handler changes width and height after a tab is selected

    Parameters
    ----------
    event : str
        bind event
    """
    event.widget.update_idletasks()
    tc1 = event.widget.nametowidget(event.widget.select())
    event.widget.configure(
Beispiel #28
0
class MainFrame(Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.parent = parent

        self.parent.title("InstaDjango")

        self.pack(fill=BOTH, expand=1)
        self.size_and_center_window()

        self.style = Style()
        self.style.theme_use("clam")
        self.style.configure("TFrame",
                             background="#808080",
                             foreground="white")
        self.style.configure("TButton",
                             background="#808080",
                             foreground="white")
        self.style.configure("high.TButton",
                             background="#8FBC8B",
                             foreground="white")
        self.style.configure("TLabel",
                             background="#808080",
                             foreground="white")
        self.style.map("TButton",
                       background=[("pressed", "#404040"),
                                   ("active", "#A0A0A0")])

        frame = Frame(self, relief=FLAT, borderwidth=1)
        frame.pack(fill=BOTH, expand=1)

        subframe_0 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_0.pack(fill=X)
        lbl_0 = Label(
            subframe_0,
            text=
            "App's machine-readable name (used for naming folders locally and remotely):",
            style="TLabel")
        lbl_0.pack(fill=BOTH, padx=10, pady=10)
        entry_0 = Entry(subframe_0)
        entry_0.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_0, "")

        subframe_1 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_1.pack(fill=X)
        lbl_1 = Label(subframe_1,
                      text="Where to create the app's folder locally:",
                      style="TLabel")
        lbl_1.pack(fill=BOTH, padx=10, pady=10)
        entry_1 = Entry(subframe_1)

        def action_1():
            cdir = filedialog.askdirectory(title="Please select a directory")
            if cdir:
                self.set_entry_text(entry_1, cdir)

        button_1 = Button(subframe_1,
                          text="Choose",
                          command=action_1,
                          style="TButton")
        button_1.pack(side=RIGHT, padx=10, pady=0)
        entry_1.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_1, "")

        subframe_2 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_2.pack(fill=X)
        lbl_2 = Label(subframe_2, text="Remote host:", style="TLabel")
        lbl_2.pack(fill=BOTH, padx=10, pady=10)
        entry_2 = Entry(subframe_2)
        entry_2.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_2, "")

        subframe_3 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_3.pack(fill=X)
        lbl_3 = Label(
            subframe_3,
            text="Remote SSH port (empty will mean the default port):",
            style="TLabel")
        lbl_3.pack(fill=BOTH, padx=10, pady=10)
        entry_3 = Entry(subframe_3)
        entry_3.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_3, "")

        subframe_4 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_4.pack(fill=X)
        lbl_4 = Label(subframe_4, text="Remote user:"******"TLabel")
        lbl_4.pack(fill=BOTH, padx=10, pady=10)
        entry_4 = Entry(subframe_4)
        entry_4.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_4, "")

        subframe_5 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_5.pack(fill=X)
        lbl_5 = Label(subframe_5,
                      text="Local path to the SSH private key:",
                      style="TLabel")
        lbl_5.pack(fill=BOTH, padx=10, pady=10)
        entry_5 = Entry(subframe_5)

        def action_5():
            cdir = filedialog.askopenfilename(
                title="Please select a private key")
            if cdir:
                self.set_entry_text(entry_5, cdir)

        button_5 = Button(subframe_5,
                          text="Choose",
                          command=action_5,
                          style="TButton")
        button_5.pack(side=RIGHT, padx=10, pady=0)
        entry_5.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_5, "")

        subframe_6 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_6.pack(fill=X)
        lbl_6 = Label(
            subframe_6,
            text=
            "Where to create the app's folder remotely (should not be owned by root):",
            style="TLabel")
        lbl_6.pack(fill=BOTH, padx=10, pady=10)
        entry_6 = Entry(subframe_6)
        entry_6.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_6, "/var/www")

        subframe_7 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_7.pack(fill=X)
        lbl_7 = Label(subframe_7, text="Sudo password:"******"TLabel")
        lbl_7.pack(fill=BOTH, padx=10, pady=10)
        entry_7 = Entry(subframe_7, show="*")
        entry_7.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_7, "")

        subframe_8 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_8.pack(fill=X)
        lbl_8 = Label(subframe_8, text="Database password:"******"TLabel")
        lbl_8.pack(fill=BOTH, padx=10, pady=10)
        entry_8 = Entry(subframe_8, show="*")
        entry_8.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_8, "")

        subframe_9 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_9.pack(fill=X)
        lbl_9 = Label(subframe_9, text="Domain:", style="TLabel")
        lbl_9.pack(fill=BOTH, padx=10, pady=10)
        entry_9 = Entry(subframe_9)
        entry_9.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_9, "dev.example.com")

        subframe_10 = Frame(frame, relief=FLAT, borderwidth=0)
        subframe_10.pack(fill=X)
        lbl_10 = Label(
            subframe_10,
            text="Django installation type (local, production, staging):",
            style="TLabel")
        lbl_10.pack(fill=BOTH, padx=10, pady=10)
        entry_10 = Entry(subframe_10)
        entry_10.pack(fill=X, padx=10, ipady=5)
        self.set_entry_text(entry_10, "local")

        def go():
            setup_django_project(proj=entry_0.get(),
                                 proj_local_parent_dir=entry_1.get(),
                                 host=entry_2.get(),
                                 port=entry_3.get(),
                                 user=entry_4.get(),
                                 ssh_key=entry_5.get(),
                                 proj_remote_parent_dir=entry_6.get(),
                                 sudo_pass=entry_7.get(),
                                 db_pass=entry_8.get(),
                                 domain=entry_9.get(),
                                 insta_type=entry_10.get())
            self.quit()

        inst_button = Button(self, text="Go", command=go, style="high.TButton")
        inst_button.pack(side=RIGHT, padx=10, pady=10)

        quit_button = Button(self,
                             text="Quit",
                             command=self.quit,
                             style="TButton")
        quit_button.pack(side=RIGHT, pady=10)

    def size_and_center_window(self):
        w = 640
        h = 850
        sw = self.parent.winfo_screenwidth()
        sh = self.parent.winfo_screenheight()
        x = (sw - w) / 2
        y = (sh - h) / 2
        self.parent.geometry("%dx%d+%d+%d" % (w, h, x, y))

    @staticmethod
    def set_entry_text(e, text):
        e.delete(0, END)
        e.insert(0, text)
Beispiel #29
0
    def __init__(self, master):
        Toplevel.__init__(self, master, class_="CheckMails")
        self.title(_("Preferences"))

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

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

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

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

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

        # --- Ok/Cancel
        frame_button = Frame(self)
        frame_button.grid(row=3, columnspan=3, padx=6, pady=(0, 6))
        Button(frame_button, text="Ok",
               command=self.ok).grid(row=2, column=0, padx=8, pady=4)
        Button(frame_button, text=_("Cancel"),
               command=self.destroy).grid(row=2, column=1, padx=4, pady=4)
Beispiel #30
0
    hashtags = f.readlines()

## GUI Tkinter

_bgcolor = '#d9d9d9'  # X11 color: 'gray85'
_fgcolor = '#000000'  # X11 color: 'black'
_compcolor = '#d9d9d9'  # X11 color: 'gray85'
_ana1color = '#d9d9d9'  # X11 color: 'gray85'
_ana2color = '#d9d9d9'  # X11 color: 'gray85'
styl = Style()
styl.theme_use('clam')
styl.configure('.', background=_bgcolor)
styl.configure('.', foreground=_fgcolor)
styl.configure('.', sliderthickness='20')
styl.configure('.', font="TkDefaultFont")
styl.map('.', background=[('selected', _compcolor), ('active', _ana2color)])

Frame1 = Frame(root)
Frame1.place(relx=0.02, rely=0.02, relheight=0.27, relwidth=0.46)
Frame1.configure(relief=GROOVE)
Frame1.configure(borderwidth="2")
Frame1.configure(relief=GROOVE)
Frame1.configure(width=285)

Checkbutton1 = Checkbutton(Frame1)
Checkbutton1.place(relx=0.07, rely=0.43, relheight=0.22, relwidth=0.34)
Checkbutton1.configure(text='''Profile photo''')
Checkbutton1.configure(variable=check1)

Checkbutton3 = Checkbutton(Frame1)
Checkbutton3.place(relx=0.07, rely=0.7, relheight=0.22, relwidth=0.35)
Beispiel #31
0
    def _criar_estilo(self):
        '''
        Define o estilo dos widgets.
        '''
        cor_1 = '#C7E0DD'
        cor_2 = '#76B0AC'
        cor_3 = '#6C8BA7'
        cor_4 = '#CBB6B4'
        cor_5 = '#E5D4D0'
        cor_6 = '#EAE8E6'

        estilo = Style()

        # frame
        estilo.configure('TFrame', background=cor_4)

        # botao
        estilo.configure('TButton',
                         background=cor_3,
                         foreground=cor_6,
                         font=('Georgia', 14, 'normal'),
                         relief='flat')

        estilo.map('TButton',
                   background=[('active', cor_2)],
                   foreground=[('active', cor_6)])

        # label
        estilo.configure('TLabel',
                         background=cor_4,
                         font=('Gergia', 14, 'normal'))

        # entry
        estilo.configure('TEntry', fieldbackground=cor_6)

        #notebook
        estilo.configure('TNotebook.Tab',
                         background=cor_3,
                         foreground=cor_6,
                         font=('Arial', 14, 'bold'),
                         relief='raised',
                         borderwidth=5)

        estilo.map('TNotebook.Tab',
                   background=[('active', cor_2)],
                   foreground=[('active', cor_6)])

        # option menu
        estilo.configure('TMenubutton',
                         background=cor_6,
                         font=('Georgia', 14, 'normal'),
                         relief='flat')

        estilo.map('TMenubutton', background=[('active', cor_2)])

        # scales
        estilo.configure('TScale', background=cor_3)

        estilo.map('TScale', background=[('active', cor_2)])

        # spinboxs
        estilo.configure('TSpinbox',
                         arrowsize=20,
                         relief='flat',
                         background=cor_3,
                         fieldbackground=cor_6)

        estilo.map('TSpinbox', background=[('active', cor_2)])
Beispiel #32
0
    def __init__(self, file=None):
        Tk.__init__(self, className="Sudoku-Tk")
        self.title("Sudoku-Tk")
        self.resizable(0, 0)
        self.protocol("WM_DELETE_WINDOW", self.quitter)
        cst.set_icon(self)
        self.columnconfigure(3, weight=1)

        # --- style
        bg = '#dddddd'
        activebg = '#efefef'
        pressedbg = '#c1c1c1'
        lightcolor = '#ededed'
        darkcolor = '#cfcdc8'
        bordercolor = '#888888'
        focusbordercolor = '#5E5E5E'
        disabledfg = '#999999'
        disabledbg = bg

        button_style_config = {'bordercolor': bordercolor,
                               'background': bg,
                               'lightcolor': lightcolor,
                               'darkcolor': darkcolor}

        button_style_map = {'background': [('active', activebg),
                                           ('disabled', disabledbg),
                                           ('pressed', pressedbg)],
                            'lightcolor': [('pressed', darkcolor)],
                            'darkcolor': [('pressed', lightcolor)],
                            'bordercolor': [('focus', focusbordercolor)],
                            'foreground': [('disabled', disabledfg)]}

        style = Style(self)
        style.theme_use(cst.STYLE)
        style.configure('TFrame', background=bg)
        style.configure('TLabel', background=bg)
        style.configure('TScrollbar', gripcount=0, troughcolor=pressedbg,
                        **button_style_config)
        style.map('TScrollbar', **button_style_map)
        style.configure('TButton', **button_style_config)
        style.map('TButton', **button_style_map)
        style.configure('TCheckutton', **button_style_config)
        style.map('TCheckutton', **button_style_map)
        self.option_add('*Toplevel.background', bg)
        self.option_add('*Menu.background', bg)
        self.option_add('*Menu.activeBackground', activebg)
        self.option_add('*Menu.activeForeground', "black")
        self.configure(bg=bg)

        style.configure("bg.TFrame", background="grey")
        style.configure("case.TFrame", background="white")
        style.configure("case.TLabel", background="white", foreground="black")
        style.configure("case_init.TFrame", background="lightgrey")
        style.configure("case_init.TLabel", background="lightgrey", foreground="black")
        style.configure("erreur.TFrame", background="white")
        style.configure("erreur.TLabel", background="white", foreground="red")
        style.configure("solution.TFrame", background="white")
        style.configure("solution.TLabel", background="white", foreground="blue")
        style.configure("pause.TLabel", foreground="grey", background='white')

        # --- images
        self.im_erreur = open_image(cst.ERREUR)
        self.im_pause = open_image(cst.PAUSE)
        self.im_restart = open_image(cst.RESTART)
        self.im_play = open_image(cst.PLAY)
        self.im_info = open_image(cst.INFO)
        self.im_undo = open_image(cst.UNDO)
        self.im_redo = open_image(cst.REDO)
        self.im_question = open_image(cst.QUESTION)

        # --- timer
        self.chrono = [0, 0]
        self.tps = Label(self, text=" %02i:%02i" % tuple(self.chrono),
                         font="Arial 16")
        self.debut = False  # la partie a-t-elle commencée ?
        self.chrono_on = False  # le chrono est-il en marche ?

        # --- buttons
        self.b_pause = Button(self, state="disabled", image=self.im_pause,
                              command=self.play_pause)
        self.b_restart = Button(self, state="disabled", image=self.im_restart,
                                command=self.recommence)
        self.b_undo = Button(self, image=self.im_undo, command=self.undo)
        self.b_redo = Button(self, image=self.im_redo, command=self.redo)

        # --- tooltips
        self.tooltip_wrapper = TooltipWrapper(self)
        self.tooltip_wrapper.add_tooltip(self.b_pause, _("Pause game"))
        self.tooltip_wrapper.add_tooltip(self.b_restart, _("Restart game"))
        self.tooltip_wrapper.add_tooltip(self.b_undo, _("Undo"))
        self.tooltip_wrapper.add_tooltip(self.b_redo, _("Redo"))

        # --- numbers
        frame_nb = Frame(self, style='bg.TFrame', width=36)
        self.progression = []
        for i in range(1, 10):
            self.progression.append(Progression(frame_nb, i))
            self.progression[-1].pack(padx=1, pady=1)

        # --- level indication
        frame = Frame(self)
        frame.grid(row=0, columnspan=5, padx=(30, 10), pady=10)
        Label(frame, text=_("Level") + ' - ', font="Arial 16").pack(side='left')
        self.label_level = Label(frame, font="Arial 16", text=_("Unknown"))
        self.label_level.pack(side='left')
        self.level = "unknown"  # puzzle level

        # --- frame contenant la grille de sudoku
        self.frame_puzzle = Frame(self, style="bg.TFrame")
        self.frame_pause = Frame(self, style="case.TFrame")
        self.frame_pause.grid_propagate(False)
        self.frame_pause.columnconfigure(0, weight=1)
        self.frame_pause.rowconfigure(0, weight=1)
        Label(self.frame_pause, text='PAUSE', style='pause.TLabel',
              font='Arial 30 bold').grid()

        # --- placement
        frame_nb.grid(row=1, column=6, sticky='en', pady=0, padx=(0, 30))
        self.frame_puzzle.grid(row=1, columnspan=5, padx=(30, 15))
        self.tps.grid(row=2, column=0, sticky="e", padx=(30, 10), pady=30)
        self.b_pause.grid(row=2, column=1, sticky="w", padx=2, pady=30)
        self.b_restart.grid(row=2, column=2, sticky="w", padx=2, pady=30)
        self.b_undo.grid(row=2, column=3, sticky="e", pady=30, padx=2)
        self.b_redo.grid(row=2, column=4, sticky="w", pady=30, padx=(2, 10))

        # --- menu
        menu = Menu(self, tearoff=0)

        menu_nouveau = Menu(menu, tearoff=0)

        menu_levels = Menu(menu_nouveau, tearoff=0)
        menu_levels.add_command(label=_("Easy"), command=self.new_easy)
        menu_levels.add_command(label=_("Medium"), command=self.new_medium)
        menu_levels.add_command(label=_("Difficult"), command=self.new_difficult)

        menu_nouveau.add_cascade(label=_("Level"), menu=menu_levels)
        menu_nouveau.add_command(label=_("Generate a puzzle"),
                                 command=self.genere_grille,
                                 accelerator="Ctrl+G")
        menu_nouveau.add_command(label=_("Empty grid"),
                                 command=self.grille_vide,
                                 accelerator="Ctrl+N")

        menu_ouvrir = Menu(menu, tearoff=0)
        menu_ouvrir.add_command(label=_("Game"), command=self.import_partie,
                                accelerator="Ctrl+O")
        menu_ouvrir.add_command(label=_("Puzzle"), command=self.import_grille,
                                accelerator="Ctrl+Shift+O")

        menu_game = Menu(menu, tearoff=0)
        menu_game.add_command(label=_("Restart"), command=self.recommence)
        menu_game.add_command(label=_("Solve"), command=self.resolution)
        menu_game.add_command(label=_("Save"), command=self.sauvegarde,
                              accelerator="Ctrl+S")
        menu_game.add_command(label=_("Export"), command=self.export_impression,
                              accelerator="Ctrl+E")
        menu_game.add_command(label=_("Evaluate level"),
                              command=self.evaluate_level)

        menu_language = Menu(menu, tearoff=0)
        self.langue = StringVar(self)
        self.langue.set(cst.LANGUE[:2])
        menu_language.add_radiobutton(label="Français",
                                      variable=self.langue,
                                      value="fr", command=self.translate)
        menu_language.add_radiobutton(label="English", variable=self.langue,
                                      value="en", command=self.translate)

        menu_help = Menu(menu, tearoff=0)
        menu_help.add_command(label=_("Help"), command=self.aide, accelerator='F1')
        menu_help.add_command(label=_("About"), command=self.about)

        menu.add_cascade(label=_("New"), menu=menu_nouveau)
        menu.add_cascade(label=_("Open"), menu=menu_ouvrir)
        menu.add_cascade(label=_("Game"), menu=menu_game)
        menu.add_cascade(label=_("Language"), menu=menu_language)
        menu.add_command(label=_("Statistics"), command=self.show_stat)
        menu.add_cascade(label=_("Help"), menu=menu_help)

        self.configure(menu=menu)

        # --- clavier popup
        self.clavier = None

        # --- cases
        self.nb_cases_remplies = 0
        self.blocs = np.zeros((9, 9), dtype=object)
        for i in range(9):
            for j in range(9):
                self.blocs[i, j] = Case(self.frame_puzzle, i, j, self.update_nbs, width=50, height=50)
                px, py = 1, 1
                if i % 3 == 2 and i != 8:
                    py = (1, 3)
                if j % 3 == 2 and j != 8:
                    px = (1, 3)
                self.blocs[i, j].grid(row=i, column=j, padx=px, pady=py)
                self.blocs[i, j].grid_propagate(0)

        # --- undo/redo stacks
        self._undo_stack = []
        self._redo_stack = []

        # --- raccourcis clavier et actions de la souris
        self.bind("<Button>", self.edit_case)
        self.bind("<Control-z>", lambda e: self.undo())
        self.bind("<Control-y>", lambda e: self.redo())
        self.bind("<Control-s>", lambda e: self.sauvegarde())
        self.bind("<Control-e>", lambda e: self.export_impression())
        self.bind("<Control-o>", lambda e: self.import_partie())
        self.bind("<Control-Shift-O>", lambda e: self.import_grille())
        self.bind("<Control-n>", lambda e: self.grille_vide())
        self.bind("<Control-g>", lambda e: self.genere_grille())
        self.bind("<FocusOut>", self.focus_out)
        self.bind("<F1>", self.aide)

        # --- open game
        if file:
            try:
                self.load_sudoku(file)
            except FileNotFoundError:
                one_button_box(self, _("Error"),
                               _("The file %(file)r does not exist.") % file,
                               image=self.im_erreur)
            except (KeyError, EOFError, UnpicklingError):
                try:
                    self.load_grille(file)
                except Exception:
                    one_button_box(self, _("Error"),
                                   _("This file is not a valid sudoku file."),
                                   image=self.im_erreur)
        elif exists(cst.PATH_SAVE):
            self.load_sudoku(cst.PATH_SAVE)
            remove(cst.PATH_SAVE)