def init_progress(progress_widget: ttk.Progressbar, max_level: int): '''Initialize a progress bar. Arguments: progress_widget {ttk.Progressbar} -- The progress bar to be initialized. max_level {int} -- The maximum level for the progress bar. ''' progress_widget.configure(maximum=max_level) progress_widget["value"] = 0 progress_widget.update_idletasks()
class Loading_class: def __init__(self): self.top = Tk() self.top.geometry("791x376+268+88") self.top.title("BANKING SOLUTIONS") self.top.configure(background="#FFFFCC") self.Label1 = Label(self.top) self.Label1.place(relx=0.24, rely=0.0, height=82, width=443) self.Label1.configure(background="#FFFFCC") img1 = ImageTk.PhotoImage(Image.open("images/rahul2.jpg")) self.Label1.configure(image=img1) self.v1 = IntVar() #it will hold the current value of progress bar self.Label2 = Label(self.top) self.Label2.place(relx=0.08, rely=0.43, height=41, width=374) self.Label2.configure(background="#FFFFCC") self.Label2.configure(width=374) self.pb = Progressbar(self.top, orient=HORIZONTAL) self.pb.config(mode='determinate', maximum=100) self.pb.config(variable=self.v1) self.pb.place(relx=0.08, rely=0.56, relwidth=0.87, relheight=0.0, height=22) self.pb.configure(length="690") tup = (101, ) self.t1 = threading.Thread(target=self.move, args=tup, name='first') self.t1.start() self.top.after(500, self.check) self.top.mainloop() def move(self, a): for i in range(a): self.v1.set(i) self.Label2.configure(text='LOADING ' + str(self.v1.get()) + '%') time.sleep(.05) def check(self): if self.v1.get() != 100: self.top.after(500, self.check) else: self.top.destroy() o1 = Login.Login_Class() #obj = Loading_class()
class load_class: def __init__(self): self.rt = Tk() self.rt.title("YOUR BANKING SOLUTIONS") self.rt.config(background="#ccffcc") self.rt.geometry("1145x500+160+100") #self.rt.geometry("920x450+200+180") self.l1 = Label(self.rt) self.l1.place(relx=0.25, rely=0.0, height=200, width=650) self.l1.config(background="#ccffcc") img1 = ImageTk.PhotoImage(Image.open("bank_images/load.gif")) self.l1.configure(image=img1) self.label1 = Label(self.rt) self.label1.place(relx=0.26, rely=0.29, height=200, width=650) self.label1.config(background="#ccffcc") imgq = ImageTk.PhotoImage(Image.open("bank_images/l.gif")) self.label1.configure(image=imgq) self.v1 = IntVar() #has the current value of progressbar self.l2 = Label(self.rt) self.l2.place(relx=0.06, rely=0.71, height=40, width=380) self.l2.configure(background="#ccffcc") self.l2.configure(width=380) self.pb = Progressbar(self.rt, orient=HORIZONTAL) self.pb.configure(mode='determinate', maximum=100) self.pb.configure(variable=self.v1) self.pb.place(relx=0.08, rely=0.80, relwidth=0.90, relheight=0.0, height=49) self.pb.configure(length="650") tup = (101, ) self.t1 = threading.Thread(target=self.move, args=tup, name='first') self.t1.start() self.rt.after(500, self.check) self.rt.mainloop() def move(self, a): for i in range(a): self.v1.set(i) self.l2.configure(text="Loading " + str(self.v1.get()) + "%") time.sleep(0.01) def check(self): if self.v1.get() != 100: self.rt.after(500, self.check) else: self.rt.destroy() object = Login_new.Login_Class() #ob=load_class()
class StatusBar(Frame): def __init__(self, master, progressMax=100, **kwargs): Frame.__init__(self, master, **kwargs) self.label = Label(self, text="Ready...") self.label.pack(anchor=Tkc.W) self.progressVar = IntVar() self.progress = Progressbar(self, mode='determinate', maximum=abs(progressMax), length="150", variable=self.progressVar) def showText(self, message): self.label.configure(text=message) self.progress.stop() self.progress.pack_forget() self.label.pack(anchor=Tkc.W) def showProgress(self): self.progress.configure(mode='determinate') self.label.pack_forget() self.progress.pack(anchor=Tkc.W) self.update_idletasks() def setProgress(self, value): self.progressVar.set(value) self.update_idletasks() def setProgressMax(self, value): self.progress.configure(maximum=abs(value)) def showActivity(self): self.progress.configure(mode='indeterminate') self.progress.start() self.showProgress()
class waitWindowProgressBar(Toplevel): def __init__(self, parent=None): """ Initialises the calculate wait window. Waits for other processes to finish, then packs everything. messages, setup_dataset and stop are the functions that change the layout of the frame. """ super().__init__(parent) self.title("Setting up.......") #self.attributes("-topmost", True) self.pb_val = IntVar(self) self.pb_val.set(0) self.pb = Progressbar(self, length=400, variable=self.pb_val) self.pb.pack(pady=20, padx=20) self.pb.configure(maximum=10) self.labeltext = StringVar() self.labeltext.set("Waiting for other process.....") self.waiting_label = Label(self, textvariable=self.labeltext) self.waiting_label.configure(anchor="center") self.waiting_label.pack(pady=20, padx=20, fill='both', expand=True) self.stopbutton = Button(self, text="Stop!", compound="bottom", command=self.stop) self.stopbutton.pack(side="left", fill="x", expand=True) self.stopflag = 0 self.update() def stop(self): """ Sets the stopflag to 1, thus stopping the calculation. """ self.stopflag = 1 def setup_dataset(self, dataset): """ Sets up the calculation wait window for the different stages of calculation. """ self.dataset = dataset self.title("Calculating Dataset %s" % os.path.basename(dataset.path)) self.waiting_label.pack(pady=20, padx=20) self.update() def errormessage(self, dataset): messagebox.showwarning( "Invalid parameters", "Dataset %s was skipped in the computation because of invalid parameters. Please configure Cut-off frequency and / or Filter type." % os.path.basename(dataset.path)) def return_function(self): """ Returns two functions for further use in the model. """ @ri.rternalize def messages(i, r, each): """ Messages function given to the R environment. Gives feedback on the state of the Monte-Carlo simulation. """ self.pb.step() count = np.asarray((i, r)) if (count[0] == -1): self.title("Computation for Dataset %s" % os.path.basename(self.dataset.path)) self.pb.pack(pady=20, padx=20) self.pb_val.set(0) self.stopbutton["state"] = "normal" if self.dataset.metadata[ "Method"] == "HILDE-Homogeneous" or self.dataset.metadata[ "Method"] == "HILDE-Heterogeneous": self.pb.configure(maximum=int( self.dataset.metadata["Repetitions_Hilde"])) else: self.pb.configure( maximum=int(self.dataset.metadata["Repetitions"])) self.labeltext.set( "Currently computing quantile for Dataset:\n%s \n Press Stop! button to stop computation for current dataset." % os.path.basename(self.dataset.path)) if (count[0] == -2): self.pb.pack_forget() self.labeltext.set( "Calculating fit for Dataset:\n%s\nThis computation cannot be interrupted and may take a few minutes." % os.path.basename(self.dataset.path)) self.stopbutton["state"] = "disabled" self.waiting_label.pack(pady=20, padx=20) self.update() return self.stopflag return messages, self.setup_dataset, self.errormessage
class RedditApp(Frame): def __init__(self, master=None): """ Initialize the main application Frame and load it with other widgets. """ super().__init__(master) self.root = master self.pack() self.setup_main_frame() self.create_menubar() self.create_widgets() def setup_main_frame(self): self.root.resizable(0, 0) self.root.wm_title('(sub)Reddit Downloader') def create_menubar(self): menubar = Menu(self.root) menubar.add_command(label='About', command=AboutWindow.about) menubar.add_command(label='Exit', command=self.root.quit) self.root.config(menu=menubar) def create_widgets(self): """ Create widgets to populate the applications frame. """ # URL, Pages, Destination paths_frame = Frame(self) lbl_url = Label(paths_frame, text='URL:') lbl_pages = Label(paths_frame, text='Pages:') lbl_destination = Label(paths_frame, text='Destination:') lbl_pages_help = Label(paths_frame, text='(Leave zero to crawl all pages)') self.url_var = StringVar() self.pages_var = IntVar() self.destination_var = StringVar() url = Entry(paths_frame, textvariable=self.url_var) pages = Entry(paths_frame, textvariable=self.pages_var) destination = Entry(paths_frame, textvariable=self.destination_var) btn_chooser = Button(paths_frame, text='Destination', command=self.choose_directory) pad_x = 5 pad_y = 7 r = 0 lbl_url.grid(row=r, column=0, sticky=E, padx=pad_x, pady=pad_y) url.grid(row=r, column=1) r += 1 lbl_pages.grid(row=r, column=0, sticky=E) pages.grid(row=r, column=1, padx=pad_x, pady=pad_y) lbl_pages_help.grid(row=r, column=2) r += 1 lbl_destination.grid(row=r, column=0, sticky=E) destination.grid(row=r, column=1, padx=pad_x, pady=pad_y) btn_chooser.grid(row=r, column=2, sticky=E + W) paths_frame.pack(side=TOP, padx=10, pady=10) # Download button download_frame = Frame(self) self.btn_download = Button(download_frame, text='Download', command=self.download_reddit) self.btn_download.pack(padx=10, pady=10) download_frame.pack(side=TOP) # Progress label progress_info = Frame(self) self.lbl_progress_info = Label(progress_info, text='') self.lbl_progress_info.pack(padx=10, pady=10) progress_info.pack(side=TOP) def add_progress_bar(self): """ Add progress bar to root frame. """ self.progress_frame = Frame(self) self.progress_bar = Progressbar(self.progress_frame, orient='horizontal', length=400, mode='indeterminate') self.progress_bar.pack(padx=10, pady=10) self.progress_frame.pack(side=TOP) def remove_progress_bar(self): """ Remove progress bare from root frame. """ self.progress_bar.destroy() self.progress_frame.destroy() def change_progress_label(self, text): """ Change text of progress bar label. """ self.lbl_progress_info.configure(text=text, fg='red', font=(font.BOLD)) def choose_directory(self): """ Update the destination path entry filed with the chosen path. """ destination_path = filedialog.askdirectory(initialdir='~') self.destination_var.set(destination_path) def download_reddit(self): """ Download images from subreddit. """ try: self.reddit = Reddit(self.url_var.get(), self.pages_var.get()) except RedditException: messagebox.showerror('Error', 'Please input valid link') return except TclError: messagebox.showerror('Error', 'Please input only whole numbers') return except Exception as e: print(e) messagebox.showerror('Error', 'Something went wrong with Reddit.') return try: self.downloader = Downloader(self.reddit, self.destination_var.get()) except DownloaderException: messagebox.showerror('Error', 'Invalid download path') return except Exception as e: print(e) messagebox.showerror('Error', 'Something went wrong with Downloader.') return self.btn_download.configure(text='Cancel', command=self.cancel_download) self.change_progress_label('Fetching data...') self.add_progress_bar() self.progress_bar.start() self.queue = Queue() self.reddit_listener = RedditListener() self.reddit.register(self.reddit_listener) self.downloader_listener = DownloaderListener() self.downloader.register(self.downloader_listener) DownloadThread(self.queue, self.reddit, self.downloader).start() self.root.after(100, self.process_queue) def process_queue(self): """ Stop the progress bar if the thread has yielded control. If download was canceled, re-enable download button only after thread has yielded control. Reset progress bar and download button, and unregister all listeners when downloading is finished or canceled. """ try: msg = self.queue.get(0) if self.btn_download['text'] == 'Cancel': # self.reddit.fetch = True # self.downloader.downloading = True self.btn_download.configure(text='Download', command=self.download_reddit) self.remove_progress_bar() self.change_progress_label('Download finished.') if self.btn_download['state'] == DISABLED: self.btn_download.configure(state=NORMAL) self.reddit.unregister() self.downloader.unregister() print(msg) except queue.Empty: if getattr(self.reddit_listener, 'fetched', None): print(self.reddit_listener.maximum) self.progress_bar.configure(mode='determinate') self.progress_bar['value'] = 0 self.progress_bar['maximum'] = self.reddit_listener.maximum self.reddit_listener.fetched = False if (getattr(self.downloader_listener, 'currently_at', None) and self.downloader.downloading): print(self.downloader_listener.currently_at) self.progress_bar[ 'value'] = self.downloader_listener.currently_at self.root.after(100, self.process_queue) def cancel_download(self): """ Cancel fetching or downloading process. """ self.reddit.fetch = False self.downloader.downloading = False self.btn_download.configure(text='Download', command=self.download_reddit) self.remove_progress_bar() self.change_progress_label('Download canceled.') self.btn_download.configure(state=DISABLED)
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" ))
class App: def __init__(self, mc): self.mc = mc self.window = Tk() self.window.title("Екатеринбург") self.window.geometry("1800x1000") self.result = '' self.n_1 = self.m_1 = None self.modes = ('fwd', 'bwd', 'fwd_bwd') self.load = Image.open("./images/Ekb_graph_cropped.png") self.image = ImageTk.PhotoImage(self.load) self.img = Label(self.window, image=self.image) self.img.grid(column=3, columnspan=100, row=1, rowspan=100) Label(self.window, text='').grid(row=0) Label(self.window, text='', width=10).grid(column=0) Label(self.window, width=10).grid(column=2) Button(self.window, text='Показать Екатеринбург', command=partial(self.set_image, "Ekb_graph_cropped")).grid(column=1, row=1, pady=3) Label(self.window, text='').grid(column=1, row=2) Label(self.window, text='Часть 1').grid(column=1, row=3) Label(self.window, text='M = ').grid(column=0, row=4, sticky=E) self.m_1_input = Spinbox(self.window, width=5, from_=1, to=10) self.m_1_input.grid(column=1, row=4, sticky=W) Label(self.window, text='N = ').grid(column=0, row=5, sticky=E) self.n_1_input = Spinbox(self.window, width=5, from_=1, to=100) self.n_1_input.grid(column=1, row=5, sticky=W) Button(self.window, text='Выбрать', command=self.set_m_n_1).grid(column=1, row=6, sticky=W, pady=1) self.show_chosen_1 = Button(self.window, text='Показать выбранные', command=partial(self.set_image, "points_for_1_part")) Label(self.window, text='mode(1): ').grid(column=0, row=8, sticky=E) self.mode_1 = Combobox(self.window, width=15) self.mode_1.grid(column=1, row=8, sticky=W) self.mode_1['values'] = ("Туда", "Обратно", "Туда-обратно") self.mode_1.current(0) self.task_1_1_a = Button(self.window, text='Рассчитать 1а', command=self.count_first_a) self.show_1_1_a = Button(self.window, text='Show', command=partial(self.set_image, 'task_1_a')) Label(self.window, text='X = ').grid(column=0, row=9, sticky=E) self.x = Entry(self.window, width=7) self.x.grid(column=1, row=9, sticky=W) self.task_1_1_b = Button(self.window, text='1б', command=self.count_first_b) self.show_1_1_b = Button(self.window, text='Show', command=partial(self.set_image, 'task_1_b')) Label(self.window, text='mode(2): ').grid(column=0, row=10, sticky=E) self.mode_2 = Combobox(self.window, width=15) self.mode_2.grid(column=1, row=10, sticky=W) self.mode_2['values'] = ("Туда", "Обратно", "Туда-обратно") self.mode_2.current(0) self.task_1_2 = Button(self.window, text='п. 2', command=self.count_second) self.show_1_2 = Button(self.window, text='Show', command=partial(self.set_image, 'task_2')) self.task_1_3 = Button(self.window, text='п. 3', command=self.count_third) self.show_1_3 = Button(self.window, text='Show', command=partial(self.set_image, 'task_3')) self.task_1_4 = Button(self.window, text='п. 4', command=self.count_fourth) self.show_1_4 = Button(self.window, text='Show', command=partial(self.set_image, 'task_4')) Label(self.window, text='', height=1).grid(column=1, row=13) self.wait_first = Label(self.window, text='', fg='red') self.wait_first.grid(column=1, row=14) Label(self.window, text='', height=2).grid(column=1, row=15) Label(self.window, text='Часть 2').grid(column=1, row=16) Button(self.window, text='Показать карту инфраструктурных объектов', command=partial(self.set_image, "inf_objs")).grid(column=1, row=17, pady=2) Label(self.window, text='N = ').grid(column=1, row=18) self.n_input = Spinbox(self.window, from_=1, to=100, width=5) self.n_input.grid(column=1, row=18, sticky=E) Label(self.window, text='Индекс инф. объекта: ').grid(column=1, row=19) self.inf_index = Spinbox(self.window, from_=0, to=21, width=5) self.inf_index.grid(column=1, row=19, sticky=E) Button(self.window, text='Рассчитать', command=self.count_sp).grid(column=1, row=20) Label(self.window, text='', height=2).grid(column=1, row=21) self.progress = Progressbar(self.window, orient=HORIZONTAL, length=0, mode='determinate') self.progress.grid(column=1, row=22) self.progress_info = Label(self.window, text='') self.progress_info.grid(column=1, row=23) Label(self.window, text='', height=2).grid(column=1, row=24) self.combo = Combobox(self.window, width=30) self.combo['values'] = ( "Дерево кратчайших путей", "Дендрограмма", "Разделение на 2 кластера", "Деревья 2 центроид", "Дерево от 2 центроид до объекта", "Разделение на 3 кластера", "Деревья 3 центроид", "Дерево от 3 центроид до объекта", "Разделение на 5 кластеров", "Деревья 5 центроид", "Дерево от 5 центроид до объекта" ) self.combo.current(0) self.show_btn = Button(self.window, text='Показать', command=self.set_combo_image) self.add_recount = Button(self.window, text='Добавить пункт назначения и пересчитать', command=self.add_and_recount) Label(self.window, text='Test').grid(column=1, row=29, pady=3, sticky=W) Label(self.window, text='File:').grid(column=0, row=30, pady=1, sticky=E) self.filename = Entry(self.window, width=15) self.filename.grid(column=1, row=30, sticky=W) Label(self.window, text='Start:').grid(column=0, row=31, pady=1, sticky=E) self.start_id = Entry(self.window, width=5) self.start_id.grid(column=1, row=31, sticky=W) Label(self.window, text='Dest:').grid(column=0, row=32, pady=1, sticky=E) self.dest_id = Entry(self.window, width=5) self.dest_id.grid(column=1, row=32, sticky=W) self.count_test = Button(self.window, text='count', command=self.count_test) self.count_test.grid(column=1, row=33, pady=2, sticky=W) Button(self.window, text='exit', command=partial(sys.exit, 0)).grid(column=1, row=34, pady=5) def count_test(self): try: start = int(self.start_id.get()) dest = int(self.dest_id.get()) file = './{}.csv'.format(self.filename.get()) print(file) res = find_min_path(file, start, dest) messagebox.showinfo('result', 'length: {}\npath: {}'.format(res[0], res[1])) self.window.mainloop() except ValueError: messagebox.showinfo('error', 'check your input') def toggle_waiting(self, on): if on: self.wait_first.configure(text='wait please...') else: self.wait_first.configure(text='') self.window.update() def set_m_n_1(self): try: n_1 = int(self.n_1_input.get()) m_1 = int(self.m_1_input.get()) self.toggle_waiting(True) self.hide_info() self.mc.set_objs(n_1, m=m_1) self.set_image('points_for_1_part') self.show_first_part() self.toggle_waiting(False) self.window.mainloop() except ValueError: messagebox.showinfo('m n', 'M|N should be numeric') def show_first_part(self): self.show_chosen_1.grid(column=1, row=7, pady=1) self.task_1_1_a.grid(column=1, row=8, sticky=E) self.task_1_1_b.grid(column=1, row=9, sticky=E) self.task_1_2.grid(column=1, row=10, sticky=E) self.task_1_3.grid(column=1, row=11, pady=3, sticky=E) self.task_1_4.grid(column=1, row=12, sticky=E) def hide_first_part(self): self.show_chosen_1.grid_forget() self.task_1_1_a.grid_forget() self.task_1_1_b.grid_forget() self.task_1_2.grid_forget() self.task_1_3.grid_forget() self.task_1_4.grid_forget() self.show_1_1_a.grid_forget() self.show_1_1_b.grid_forget() self.show_1_2.grid_forget() self.show_1_3.grid_forget() self.show_1_4.grid_forget() def count_first_a(self): self.toggle_waiting(True) index = self.mode_1['values'].index(self.mode_1.get()) res, t = self.mc.nearest(self.modes[index]) self.set_image('task_1_a') self.show_1_1_a.grid(column=2, row=8, padx=1, sticky=W) self.toggle_waiting(False) messagebox.showinfo('1a', '{}\ntime: {}'.format(res, t)) self.window.mainloop() def count_first_b(self): index = self.mode_1['values'].index(self.mode_1.get()) try: x = int(self.x.get()) self.toggle_waiting(True) res, t = self.mc.closer_than_x(x, self.modes[index]) self.set_image('task_1_b') self.show_1_1_b.grid(column=2, row=9, padx=1, sticky=W) self.toggle_waiting(False) messagebox.showinfo('1б', '{}\ntime: {}'.format(res, t)) self.window.mainloop() except ValueError: messagebox.showinfo('error', 'x should be numeric') return def count_second(self): self.toggle_waiting(True) index = self.mode_2['values'].index(self.mode_2.get()) min_, min_id, t = self.mc.min_furthest_for_inf(self.modes[index]) self.set_image('task_2') self.show_1_2.grid(column=2, row=10, padx=1, sticky=W) self.toggle_waiting(False) messagebox.showinfo('2', '{}\ntime: {}'.format(min_, t)) self.window.mainloop() def count_third(self): self.toggle_waiting(True) min_, min_id, t = self.mc.closest_inf_in_summary() self.set_image('task_3') self.show_1_3.grid(column=2, row=11, padx=1, sticky=W) self.toggle_waiting(False) messagebox.showinfo('3', '{}\ntime: {}'.format(min_, t)) self.window.mainloop() def count_fourth(self): self.toggle_waiting(True) min_, min_id, t = self.mc.min_weight_tree() self.set_image('task_4') self.show_1_4.grid(column=2, row=12, padx=1, sticky=W) self.toggle_waiting(False) messagebox.showinfo('4', '{}\ntime: {}'.format(min_, t)) self.window.mainloop() def set_image(self, name): self.load = Image.open("./images/{}.png".format(name)) self.image = ImageTk.PhotoImage(self.load) self.img.configure(image=self.image) def set_combo_image(self): img_names = ( "routes_to_random_inf", "dendrogram", "2_clusters", "2_clusters_trees", "2_centroids_tree", "3_clusters", "3_clusters_trees", "3_centroids_tree", "5_clusters", "5_clusters_trees", "5_centroids_tree", ) index = self.combo['values'].index(self.combo.get()) self.set_image(img_names[index]) def count_sp(self): self.hide_first_part() n = int(self.n_input.get()) inf_obj_i = int(self.inf_index.get()) self.mc.set_objs(n) self.mc.set_inf_obj(inf_obj_i) self.second_part() def add_and_recount(self): self.mc.add_obj() self.n_input.selection_adjust(5) self.second_part() def second_part(self): self.progress.configure(length=200) self.hide_info() time_wt_plot = 0 start = time.time() self.update_progress(0, 'saving to csv...') self.mc.save_chosen_objs_to_csv() self.update_progress(11, 'counting tree...') sum_, weight, routes_list, o_w_r, tree_time = self.mc.list_to_obj_tree(self.mc.chosen_objs, self.mc.chosen_inf_obj, filename='./csv/min_tree.csv') time_wt_plot += tree_time # messagebox.showinfo('1', 'sum: {}\nweight: {}'.format(sum_, weight)) self.update_progress(22, 'saving tree...') self.mc.save_tree_plot(routes_list, [self.mc.graph.nodes[routes_list[0][0]]], 'routes_to_random_inf', o_w_r) self.set_image('routes_to_random_inf') self.update_progress(33, 'researching clusters...') clusters, history, t = self.mc.objs_into_clusters(1, write=True) time_wt_plot += t self.update_progress(44, 'creating dendrogram...') self.mc.dendrogram(clusters, history) self.set_image('dendrogram') self.update_progress(55, 'working with 2 clusters...') cs_2, w_2, cs_2_c, w_2_c, t = self.mc.work_with_clusters(history, 2) time_wt_plot += t self.set_image('2_clusters') self.update_progress(70, 'working with 3 clusters...') cs_3, w_3, cs_3_c, w_3_c, t = self.mc.work_with_clusters(history, 3) time_wt_plot += t self.set_image('3_clusters') self.update_progress(85, 'working with 5 clusters...') cs_5, w_5, cs_5_c, w_5_c, t = self.mc.work_with_clusters(history, 5) time_wt_plot += t self.set_image('5_clusters') self.update_progress(100, 'done!') result = "min weight tree: \n\tsum: {}\n\tweight {}\n" \ "2 centroids tree: \n\tsum: {}\n\tweight {}\n\tcentroid_sum: {}\n\tcentroid_weight: {}\n" \ "3 centroids tree: \n\tsum: {}\n\tweight {}\n\tcentroid_sum: {}\n\tcentroid_weight: {}\n" \ "5 centroids tree: \n\tsum: {}\n\tweight {}\n\tcentroid_sum: {}\n\tcentroid_weight: {}\n" \ "tree time: {}\ntime without plotting: {}\ntime: {}"\ .format(sum_, weight, cs_2, w_2, cs_2_c, w_2_c, cs_3, w_3, cs_3_c, w_3_c, cs_5, w_5, cs_5_c, w_5_c, tree_time, time_wt_plot, time.time() - start) self.set_image('routes_to_random_inf') messagebox.showinfo('result', result) self.show_info() self.window.mainloop() def update_progress(self, val, info): self.progress['value'] = val self.progress_info.configure(text=info) self.window.update() def hide_info(self): self.progress['value'] = 0 self.combo.grid_forget() self.show_btn.grid_forget() self.add_recount.grid_forget() self.progress_info.configure(text='') self.window.update() def show_info(self): self.combo.grid(column=1, row=26) self.show_btn.grid(column=1, row=27) self.add_recount.grid(column=1, row=28, pady=5) self.window.update() def start_loop(self): self.window.mainloop()
class PlayerControlPanel(Frame, IPlayerStateListener): def __init__(self, parent): super().__init__(parent) self.trackNameLabel: Label = None self.volumeScale: Scale = None self.muted = False self.__initView() def __initView(self): self.configure(borderwidth=3, relief=RIDGE) self.configure(height=HEIGHT) ################################################################################### image = Image.open(PLAY_ICON) image = image.resize((32, 32), Image.ANTIALIAS) self.play_icon = PhotoImage(image=image) image = Image.open(PAUSE_ICON) image = image.resize((32, 32), Image.ANTIALIAS) self.pause_icon = PhotoImage(image=image) self.playPauseButton = Button(self, image=self.play_icon) self.playPauseButton.grid(row=0, column=0) ################################################################################### image = Image.open(NEXT_TRACK_ICON) image = image.resize((32, 32), Image.ANTIALIAS) self.next_track_icon = PhotoImage(image=image) self.nextTrackButton = Button(self, image=self.next_track_icon) self.nextTrackButton.grid(row=0, column=1) ################################################################################### image = Image.open(LINEAR_ICON) image = image.resize((32, 32), Image.ANTIALIAS) self.linear_icon = PhotoImage(image=image) image = Image.open(REPEAT_ICON) image = image.resize((32, 32), Image.ANTIALIAS) self.repeat_icon = PhotoImage(image=image) self.musicSelectionModeButton = Button(self, image=self.next_track_icon) self.musicSelectionModeButton.grid(row=0, column=2) ################################################################################### image = Image.open(MUTE_ICON) image = image.resize((32, 32), Image.ANTIALIAS) self.mute_icon = PhotoImage(image=image) image = Image.open(UNMUTE_ICON) image = image.resize((32, 32), Image.ANTIALIAS) self.unmute_icon = PhotoImage(image=image) self.muteButton = Button(self, image=self.mute_icon, command=self.__muteButtonPressed) self.muteButton.grid(row=0, column=3) ################################################################################### self.volumeScale = Scale(self, from_=0, to=100, orient=HORIZONTAL) self.volumeScale.set(50) self.volumeScale.grid(row=0, column=4) ################################################################################### self.trackProgressBar = Progressbar(self, orient=HORIZONTAL, length=300, mode='determinate', maximum=MAXIMUM) self.trackProgressBar.grid(row=0, column=5) ################################################################################### self.timeLabel = Label(self, text='--:--/--:--') self.timeLabel.grid(row=0, column=6) self.trackNameLabel = Label(self) self.trackNameLabel.grid(row=0, column=7) def onPlayerStateUpdated(self, state: PlayerState): self.trackNameLabel.configure(text=state.trackName) if state.trackType is TrackType.MUSIC: self.trackProgressBar.configure(value=int(MAXIMUM * state.trackPosition)) self.playPauseButton.configure(state=NORMAL) else: self.trackProgressBar.configure(value=0) self.playPauseButton.configure(state=DISABLED) if state.playbackState is PlaybackState.PLAYING: self.playPauseButton.configure(image=self.pause_icon) else: self.playPauseButton.configure(image=self.play_icon) if state.musicSelectionMode is MusicSelectionMode.LINEAR: self.musicSelectionModeButton.configure(image=self.linear_icon) else: self.musicSelectionModeButton.configure(image=self.repeat_icon) self.__displayTime(state) def __displayTime(self, state: PlayerState): trackMinutes = int(state.trackLength / 60) trackSeconds = state.trackLength % 60 played = int(state.trackPosition * state.trackLength) playedMinutes = int(played / 60) playedSeconds = played % 60 if state.trackType is not TrackType.MUSIC: self.timeLabel.configure(text='--:--/--:--') else: self.timeLabel.configure( text= f'{playedMinutes:02d}:{playedSeconds:02d}/{trackMinutes:02d}:{trackSeconds:02d}' ) def setPlayerController(self, playerController: IPlayerController): self.playerController = playerController self.volumeScale.configure(command=lambda v: self.__sendVolume()) self.__sendVolume() self.trackProgressBar.bind( "<Button-1>", lambda e: self.onProgressBarClicked(e, playerController)) self.playPauseButton.configure( command=playerController.onPlayPauseClicked) self.nextTrackButton.configure( command=playerController.nextTrackClicked) self.musicSelectionModeButton.configure( command=playerController.changeMusicSelectionModeClicked) def __sendVolume(self): if self.playerController is None: return if self.muted: self.playerController.onVolumeSelected(0) else: self.playerController.onVolumeSelected(self.volumeScale.get()) def __muteButtonPressed(self): self.muted = not self.muted if self.muted: self.muteButton.configure(image=self.unmute_icon) else: self.muteButton.configure(image=self.mute_icon) self.__sendVolume() def onProgressBarClicked(self, event, playerController: IPlayerController): percentage = event.x / event.widget.winfo_width() playerController.seekTo(percentage) def onPlayerEndReached(self): pass
class Window: def __init__(self, width, height, title="MyWindow", resizable=(False, False), icon=r"resources/feather.ico"): self.root = Tk() self.root.title(title) # self.root.geometry(f"{width}x{height}+200+200") self.root.geometry("+600+300") # self.root.resizable(resizable[0], resizable[1]) if icon: self.root.iconbitmap(icon) self.pb = Progressbar(self.root, orient=HORIZONTAL, mode="indeterminate", length=200) self.sb = Spinbox(self.root, from_=0, to=100, state='readonly', command=self.change_pb) def run(self): self.draw_widgets() self.root.mainloop() def draw_widgets(self): self.draw_menu() self.sb.pack() self.pb.pack() # self.pb.configure(maximum=3) # self.pb.configure(value=1) # from time import sleep # for i in range(101): # self.pb.configure(value=i) # self.pb.update() # sleep(0.05) # self.pb.configure(value=0) Button(self.root, text="StartPB", command=self.pb.start).pack() Button(self.root, text="StopPB", command=self.pb.stop).pack() value = self.pb["value"] self.pb["value"] = 20 def draw_menu(self): menu_bar = Menu(self.root) file_menu = Menu(menu_bar, tearoff=0) file_menu.add_separator() file_menu.add_command(label="Выйти", command=self.exit) info_menu = Menu(menu_bar, tearoff=0) info_menu.add_command(label="О приложении", command=self.show_info) menu_bar.add_cascade(label="Файл", menu=file_menu) menu_bar.add_cascade(label="Справка", menu=info_menu) self.root.configure(menu=menu_bar) def change_pb(self): self.pb.configure(value=self.sb.get()) self.pb.update() def show_info(self): mb.showinfo("Информация", "Лучшее графическое приложение на свете") def exit(self): choice = mb.askyesno("Quit", "Do you want to quit?") if choice: self.root.destroy() def create_child(self, width, height, title="Child", resizable=(False, False), icon=None): ChildWindow(self.root, width, height, title, resizable, icon)
class InstallWindow: def __init__(self, setpath, installpath, systemwide, type='install'): global root self.setpath = setpath self.installpath = installpath self.systemwide = systemwide self.type = type self.master = Toplevel(root) self.master.withdraw() self.master.protocol('WM_DELETE_WINDOW', self.close) self.master.iconbitmap(imgdir) self.master.title('Adb & Fastboot installer - By @Pato05') self.master.geometry("600x400") self.master.resizable(False, False) frame = Frame(self.master, relief=FLAT) frame.pack(padx=10, pady=5, fill=BOTH) Label(frame, text='Please wait while Adb and Fastboot are getting %s...' % ( 'updated' if type == 'update' else 'installed on your PC')).pack(fill=X) self.mode = 'unksize' self.progressbar = Progressbar( frame, orient=HORIZONTAL, length=100, mode='indeterminate') self.progressbar.pack(fill=X) self.progressbar.start(20) self.downloaded = 0 self.progressv = Text(frame, bd=0, insertborderwidth=0, state='disabled', background='#f0f0ed', font=('Segoe UI', 10)) self.progressv.pack(fill=BOTH, pady=(10, 5)) self.master.deiconify() self.downloading = threading.Thread(target=self.download) self.downloading.start() def download_progress(self, count, block_size, total_size): if total_size != -1 and self.mode != 'ksize': self.mode = 'ksize' self.progressbar.stop() self.progressbar.configure(mode='determinate', maximum=total_size) elif total_size == -1 and self.mode != 'unksize': self.mode = 'unksize' self.progressbar.configure(mode='indeterminate') if self.mode == 'ksize': self.downloaded += block_size self.progressbar.step(block_size) if self.downloaded == total_size: self.progress('Download ended.') def download(self): self.pathres = False self.progress('Downloading Adb and Fastboot...', False) from urllib.request import urlretrieve import urllib.error workingdir = scriptdir download = os.path.join(workingdir, 'pt.zip') try: urlretrieve('https://dl.google.com/android/repository/platform-tools-latest-windows.zip', download, self.download_progress) except (urllib.error.HTTPError, urllib.error.URLError) as e: messagebox.showerror(title='Adb & Fastboot Uninstaller', message='Failed while trying to download Adb and Fastboot. Are you connected to the internet?\nError: %s' % e) self.error_close() return False self.progressbar.configure( mode='indeterminate', maximum=150, length=400, value=0) self.progressbar.start(20) self.progress('Extracting Adb and Fastboot...') from zipfile import ZipFile with ZipFile(download) as z: z.extractall(workingdir) os.remove(download) self.progress('Moving Adb and Fastboot to destination folder...') if(os.path.isdir(self.installpath)): rmtree(self.installpath) sleep(0.1) os.mkdir(self.installpath) for file in ['adb.exe', 'AdbWinApi.dll', 'AdbWinUsbApi.dll', 'fastboot.exe']: self.progress("Moving %s..." % file) copyfile(os.path.join(workingdir, 'platform-tools', file), os.path.join(self.installpath, file)) rmtree(os.path.join(workingdir, 'platform-tools')) if self.setpath == 1: self.progress('Adding Adb & Fastboot into %s\'s path' % ('system' if self.systemwide == 1 else 'user')) self.pathres = addToPath(self.installpath, self.systemwide == 1) self.progress( 'Successfully added Adb & Fastboot into path' if self.pathres else 'Failed to add Adb & Fastboot into path') self.progressbar.stop() self.finish() def finish(self): self.app = FinishWindow( self.setpath, self.pathres, self.installpath, self.type) self.master.destroy() def progress(self, what, lb=True): self.progressv.configure(state='normal') self.progressv.insert(END, ('\r\n' if lb else '')+what) self.progressv.configure(state='disabled') def error_close(self): global root root.destroy() def close(self): pass
class Worker(Frame): """ Worker gui elements, does all the actual work to the images with the watermarker class and contains progressbar and startbutton """ def __init__(self, file_selector, options_pane, master=None): super().__init__(master) self.running = False self.image_que = queue.Queue() self.file_selector = file_selector self.option_pane = options_pane self.watermarker = WaterMarker self.progress_var = IntVar() self.file_count = IntVar() self.counter_frame = Frame(self) self.progress_bar = Progressbar(self, orient="horizontal", mode="determinate", length=600) self.time_tracker = RemainingTime(self.counter_frame) self.button_frame = Frame(self) self.start_button = Button(self.button_frame, text="Start", command=self.apply_watermarks, width=10) self.stop_button = Button(self.button_frame, text="Stop", command=self.stop_work, width=10) self.create_widgets() def create_widgets(self): """Create GUI""" self.counter_frame.pack() self.time_tracker.pack(side=LEFT, padx=(0, 10)) Label(self.counter_frame, textvariable=self.progress_var).pack(side=LEFT) Label(self.counter_frame, text="/").pack(side=LEFT) Label(self.counter_frame, textvariable=self.file_count).pack(side=LEFT) self.progress_bar.pack() self.stop_button.config(state=DISABLED) self.start_button.pack(side=LEFT, padx=15) self.stop_button.pack(side=LEFT) self.button_frame.pack(pady=10) def fill_que(self): """ Fill the worker que from the files in file selector, and prepare te progress bar """ files = self.file_selector.get_file_paths() self.file_count.set(len(files)) self.progress_bar.configure(maximum=len(files)) self.time_tracker.set_max(len(files)) for file in files: self.image_que.put(file) def is_existing_files(self): """ Check if there's existing files which will be overwritten by the watermarker :return: True/False """ out = self.option_pane.get_output_path() for _file in self.file_selector.get_file_paths(): if os.path.isfile(self.option_pane.create_output_path(_file, out)): return True return False def apply_watermarks(self): """ Fill the que, then prepare the watermarker before spawning workers """ if len(self.file_selector.files) < 1: messagebox.showerror('Nothing to mark', 'Please choose one or more files ' 'to mark.') return if self.is_existing_files(): kwargs = {"title": "Overwrite files?", "message": "Files already exists, want to overwrite?"} overwrite = messagebox.askyesno(**kwargs) else: # Shouldn't matter since there's no files. overwrite = False try: self.watermarker = WaterMarker(self.option_pane.get_watermark_path(), overwrite=overwrite) except Exception as e: self.handle_error(e) return self.stop_button.config(state=NORMAL) self.start_button.config(state=DISABLED) self.fill_que() self.start_work() def start_work(self): """ The baby factory, spawns worker thread to apply the watermark to the images. Also locks the buttons and output selector """ try: kwargs = {"pos": self.option_pane.get_watermark_pos(), "padding": self.option_pane.get_padding(), "scale": self.option_pane.should_scale(), "opacity": self.option_pane.get_opacity()} output = self.option_pane.get_output_path() print(output) except BadOptionError as e: self.handle_error(e) return self.running = True self.option_pane.output_selector.lock() thread = threading.Thread(target=self.work, kwargs=kwargs, args=(output, )) self.time_tracker.start() thread.start() def reset(self): """ Reset the worker, emptying queue, resetting vars and buttons and stuff. """ self.image_que = queue.Queue() self.watermarker = WaterMarker self.progress_var.set(0) self.progress_bar.stop() self.time_tracker.stop() self.file_count.set(0) self.start_button.config(state=NORMAL) self.stop_button.config(state=DISABLED) self.option_pane.output_selector.unlock() def handle_error(self, e): """ Handle an error, showing the callback to the user. Is meant to be primarily used with BadOption error with a custom text. :param e: Error object. """ self.reset() messagebox.showerror("Error", str(e)) def work(self, outpath, **kwargs): """ Work instructions for the child workers keep grabbing a new image path and then apply free_mark with the watermarker, using option pane to create paths. Controls progress bar and timer_tracker as well """ while self.running: try: input_path = self.image_que.get(block=False) except queue.Empty: self.start_button.config(state=NORMAL) self.stop_button.config(state=DISABLED) self.option_pane.output_selector.unlock() self.progress_var.set(0) self.file_count.set(0) self.running = False return try: self.watermarker.apply_watermark(input_path, self.option_pane.create_output_path(input_path, outpath), **kwargs) except BadOptionError as e: self.handle_error(e) print("Bad config, stopping\n", e) return except Exception as e: print("Error!\n", type(e), "\n", e) self.progress_bar.step(amount=1) self.time_tracker.step() self.progress_var.set(self.progress_var.get()+1) self.reset() def stop_work(self): self.running = False