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" ))
def __init__(self, master): Toplevel.__init__(self, master) self.protocol("WM_DELETE_WINDOW", self.quitter) self.columnconfigure(0, weight=1) self.columnconfigure(2, weight=1) self.rowconfigure(0, weight=1) self.title(_("Exclusions")) self.transient(master) self.grab_set() self.last_path = "" # last opened path self.img_open = PhotoImage(file=IM_OPEN) self.img_doc = PhotoImage(file=IM_DOC) self.img_supp = PhotoImage(file=IM_SUPP) style = Style(self) style.configure("list.TFrame", background="white", relief="sunken") frame = Frame(self) frame.columnconfigure(0, weight=1) frame.rowconfigure(0, weight=1) frame.grid(row=0, columnspan=3, sticky="eswn", padx=10, pady=(10, 4)) listbox_frame = Frame(frame, borderwidth=1, style="list.TFrame") listbox_frame.columnconfigure(0, weight=1) listbox_frame.rowconfigure(0, weight=1) listbox_frame.grid(row=0, column=0, sticky="nswe") self.listvar = StringVar(self, value=CONFIG.get("Defaults", "exclude_supp")) self.exclude_list = split(r'(?<!\\) ', CONFIG.get("Defaults", "exclude_supp")) self.listbox = Listbox(listbox_frame, highlightthickness=0, listvariable=self.listvar, selectmode='extended') self.listbox.grid(sticky="eswn") self.listbox.selection_clear(0, 'end') scroll_x = Scrollbar(frame, orient="horizontal", command=self.listbox.xview) scroll_x.grid(row=1, column=0, sticky="ew") scroll_y = Scrollbar(frame, orient="vertical", command=self.listbox.yview) scroll_y.grid(row=0, column=1, sticky="ns") self.listbox.configure(xscrollcommand=scroll_x.set, yscrollcommand=scroll_y.set) Button(self, image=self.img_doc, command=self.add_doc).grid(row=1, column=0, sticky="e", padx=(10, 4), pady=(4, 10)) Button(self, image=self.img_open, command=self.add_dir).grid(row=1, column=1, padx=4, pady=(4, 10)) Button(self, image=self.img_supp, command=self.rem).grid(row=1, column=2, sticky="w", padx=(4, 10), pady=(4, 10)) self.geometry("500x400")
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 __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 toggle_show_size(self): CONFIG.set("Defaults", "show_size", str(self.show_size.get()))
def toggle_copy_links(self): CONFIG.set("Defaults", "copy_links", str(self.copy_links.get()))
def quitter(self): CONFIG.set("Defaults", "exclude_supp", " ".join(self.exclude_list)) save_config() self.destroy()