diff --git a/src/core.py b/src/core.py index 26b0a18..b1f9b7d 100644 --- a/src/core.py +++ b/src/core.py @@ -9,6 +9,8 @@ from fnmatch import fnmatch from re import search +from collections import defaultdict + import re import fnmatch @@ -50,6 +52,15 @@ def str_to_bytes(string): except: return -1 +def test_regexp(expr): + teststring='abc' + try: + search(expr,teststring) + except Exception as e: + return e + else: + return None + ####################################################################### data_format_version='1.0001' @@ -302,32 +313,35 @@ def find_items_rec(self, if size>size_max: continue - if name_func_to_call: - if name_func_to_call(name): - pass - else: - if is_dir and sub_dict: - self.find_items_rec( - size_min,size_max,name_func_to_call,cd_func_to_call, - sub_dict,parent_path_components + [name]) - continue - - if cd_func_to_call: - if cd: - try: - if (cd_func_to_call(cd)): - pass - else: + if is_dir : + #katalog moze spelniac kryteria naazwy pliku, nie ma rozmiaru i custom data + if name_func_to_call: + if name_func_to_call(name): + self.find_results.append(single_res) + + if sub_dict: + self.find_items_rec( + size_min,size_max,name_func_to_call,cd_func_to_call, + sub_dict,parent_path_components + [name]) + + else: + if name_func_to_call: + if not name_func_to_call(name): + continue + + if cd_func_to_call: + if cd: + try: + if not cd_func_to_call(cd): + continue + except Exception as e: + self.log.error('find_items_rec:%s on:\n%s',e,cd ) continue - except Exception as e: - print(e,'\n',cd) - self.log.error('find_items_rec:%s on:\n%s',e,cd ) - else: - continue + else: + continue - single_res = parent_path_components.copy() + [name] - #single_res.append(name) - self.find_results.append(single_res) + single_res = parent_path_components.copy() + [name] + self.find_results.append(single_res) def find_items(self, size_min,size_max, @@ -405,13 +419,28 @@ def read_records(self): else: pass + def find_items_in_all_records_check(self, + size_min,size_max, + name_expr,name_regexp,name_case_sens, + cd_expr,cd_regexp,cd_case_sens): + + if name_expr and name_regexp: + if res := test_regexp(name_expr): + return res + + if cd_expr and cd_regexp: + if res := test_regexp(cd_expr): + return res + + return None + def find_items_in_all_records(self, + range_par, size_min,size_max, name_expr,name_regexp,name_case_sens, cd_expr,cd_regexp,cd_case_sens): #print('find_items_in_all_records:',size_min,size_max,name_expr,name_regexp,name_case_sens,cd_expr,cd_regexp,cd_case_sens) - if name_expr: if name_case_sens: if name_regexp: @@ -423,23 +452,21 @@ def find_items_in_all_records(self, name_func_to_call = lambda x : search(name_expr,x,re.IGNORECASE) else: name_func_to_call = lambda x : re.compile(fnmatch.translate(name_expr), re.IGNORECASE).match(x) + + else: name_func_to_call = None if cd_expr: if cd_case_sens: if cd_regexp: - print('a1',cd_expr) cd_func_to_call = lambda x : search(cd_expr,x) else: - print('a2',cd_expr) cd_func_to_call = lambda x : fnmatch.fnmatch(x,cd_expr) else: if cd_regexp: - print('a3',cd_expr) cd_func_to_call = lambda x : search(cd_expr,x,re.IGNORECASE) else: - print('a4',cd_expr) cd_func_to_call = lambda x : re.compile(fnmatch.translate(cd_expr), re.IGNORECASE).match(x) else: cd_func_to_call = None @@ -455,20 +482,23 @@ def find_items_in_all_records(self, #cd_func_to_call = None if not cd_expr else ( lambda x : search(cd_expr,x) ) if cd_regexp else ( lambda x : fnmatch(x,cd_expr) ) - print('name_func_to_call:',name_func_to_call) - print('cd_func_to_call:',cd_func_to_call) + #self.find_res = defaultdict(set) + self.find_res = [] + sel_range = [range_par] if range_par else self.records - res = [] - for record in self.records: + for record in sel_range: sub_res = record.find_items( size_min,size_max, name_func_to_call, cd_func_to_call) if sub_res: for single_res in sub_res: - res.append( (record,single_res) ) + #self.find_res[record].add( single_res ) + self.find_res.append( (record,single_res) ) - return tuple(res) + #self.find_res + #return tuple(res) + return None def delete_record_by_id(self,rid): for record in self.records: diff --git a/src/icons/librer.png b/src/icons/librer.png index 2b27101..456006f 100644 Binary files a/src/icons/librer.png and b/src/icons/librer.png differ diff --git a/src/librer.py b/src/librer.py index ac15d14..41916e8 100644 --- a/src/librer.py +++ b/src/librer.py @@ -76,6 +76,7 @@ from tkinter import BooleanVar from tkinter.ttk import Checkbutton +from tkinter.ttk import Radiobutton from tkinter.ttk import Treeview from tkinter.ttk import Scrollbar from tkinter.ttk import Button @@ -87,7 +88,6 @@ from tkinter.filedialog import asksaveasfilename from tkinter.filedialog import askopenfilename -from collections import defaultdict from threading import Thread from traceback import format_stack @@ -119,6 +119,8 @@ CFG_KEY_SINGLE_DEVICE = 'single_device' CFG_KEY_find_size_min = 'find_size_min' +CFG_KEY_find_range_var = 'find_range_var' + CFG_KEY_find_size_max = 'find_size_max' CFG_KEY_find_name = 'find_name' @@ -136,6 +138,8 @@ CFG_KEY_EXCLUDE:'', CFG_KEY_CDE_SETTINGS:'', + CFG_KEY_find_range_var:'s', + CFG_KEY_find_size_min:'', CFG_KEY_find_size_max:'', @@ -372,7 +376,7 @@ def __init__(self,cwd,paths_to_add=None,exclude=None,exclude_regexp=None,norun=N self.ico_empty = self_ico['empty'] self.ico_delete = self_ico['delete'] - self_main.iconphoto(False, self_ico['librer']) + self_main.iconphoto(True, self_ico['librer']) self.RECORD='R' self.DIR='D' @@ -778,14 +782,12 @@ def post_close(on_main_window_dialog=True): self.find_dialog=dialogs.GenericDialog(self_main,self_ico['librer'],self.bg_color,'Find file',pre_show=pre_show,post_close=post_close) #,min_width=800,min_height=520 - (find_size_frame := LabelFrame(self.find_dialog.area_main,text='File size range',bd=2,bg=self.bg_color,takefocus=False)).grid(row=0,column=0,sticky='news',padx=4,pady=4) - find_size_frame.grid_columnconfigure(0, weight=1) - find_size_frame.grid_columnconfigure(1, weight=1) - #find_size_frame.grid_rowconfigure(2, weight=1) ############## #self.find_size_use_var = BooleanVar() + self.find_range_var = StringVar() + self.find_size_min_var = StringVar() self.find_size_max_var = StringVar() @@ -802,10 +804,12 @@ def ver_number(var): temp=core_str_to_bytes(var) if temp>0: - return str(temp) + return var else: return '' + self.find_range_var.set(self.cfg.get(CFG_KEY_find_range_var)) + self.find_size_min_var.set(ver_number(self.cfg.get(CFG_KEY_find_size_min))) self.find_size_max_var.set(ver_number(self.cfg.get(CFG_KEY_find_size_max))) @@ -830,20 +834,14 @@ def ver_number(var): self.find_cd_regexp_var.trace_add("write", lambda i,j,k : self.find_mod()) self.find_cd_case_sens_var.trace_add("write", lambda i,j,k : self.find_mod()) - Label(find_size_frame,text='min',bg=self.bg_color,anchor='w',relief='groove',bd=2).grid(row=0, column=0, sticky='we',padx=4,pady=4) - Label(find_size_frame,text='max',bg=self.bg_color,anchor='w',relief='groove',bd=2).grid(row=0, column=1, sticky='we',padx=4,pady=4) - - def validate_size_str(val): - return True if val == "" or val.isdigit() else False - #entry_validator = self.main.register(validate_size_str) + sfdma = self.find_dialog.area_main - #,validate="key",validatecommand=(entry_validator,"%P") - Entry(find_size_frame,textvariable=self.find_size_min_var).grid(row=1, column=0, sticky='we',padx=4,pady=4) - Entry(find_size_frame,textvariable=self.find_size_max_var).grid(row=1, column=1, sticky='we',padx=4,pady=4) + (find_filename_frame := LabelFrame(sfdma,text='Search range',bd=2,bg=self.bg_color,takefocus=False)).grid(row=0,column=0,sticky='news',padx=4,pady=4) + (find_range_cb1 := Radiobutton(find_filename_frame,text='Selected record',variable=self.find_range_var,value='s',command=self.find_mod)).grid(row=0, column=0, sticky='news',padx=4,pady=4) + (find_range_cb2 := Radiobutton(find_filename_frame,text='All records',variable=self.find_range_var,value='a',command=self.find_mod)).grid(row=0, column=1, sticky='news',padx=4,pady=4) - find_filename_frame = LabelFrame(self.find_dialog.area_main,text='File path and name',bd=2,bg=self.bg_color,takefocus=False) - find_filename_frame.grid(row=1,column=0,sticky='news',padx=4,pady=4) + (find_filename_frame := LabelFrame(sfdma,text='File path and name',bd=2,bg=self.bg_color,takefocus=False)).grid(row=1,column=0,sticky='news',padx=4,pady=4) (find_name_regexp_cb := Checkbutton(find_filename_frame,text='Treat as regular expression',variable=self.find_name_regexp_var,command=self.find_mod)).grid(row=1, column=0, sticky='news',padx=4,pady=4) (find_name_case_sens_cb := Checkbutton(find_filename_frame,text='Case sensitive',variable=self.find_name_case_sens_var,command=self.find_mod)).grid(row=2, column=0, sticky='news',padx=4,pady=4) @@ -851,8 +849,8 @@ def validate_size_str(val): Entry(find_filename_frame,textvariable=self.find_name_var,validate="key").grid(row=0, column=0, sticky='we',padx=4,pady=4) find_filename_frame.grid_columnconfigure(0, weight=1) - find_cd_frame = LabelFrame(self.find_dialog.area_main,text='Custom data',bd=2,bg=self.bg_color,takefocus=False) - find_cd_frame.grid(row=2,column=0,sticky='news',padx=4,pady=4) + (find_cd_frame := LabelFrame(sfdma,text='Custom data',bd=2,bg=self.bg_color,takefocus=False)).grid(row=2,column=0,sticky='news',padx=4,pady=4) + (find_cd_regexp_cb := Checkbutton(find_cd_frame,text='Treat as regular expression',variable=self.find_cd_regexp_var,command=self.find_mod)).grid(row=1, column=0, sticky='news',padx=4,pady=4) (cd_case_sens_cb := Checkbutton(find_cd_frame,text='Case sensitive',variable=self.find_cd_case_sens_var,command=self.find_mod)).grid(row=2, column=0, sticky='news',padx=4,pady=4) @@ -860,18 +858,29 @@ def validate_size_str(val): Entry(find_cd_frame,textvariable=self.find_cd_var,validate="key").grid(row=0, column=0, sticky='we',padx=4,pady=4) find_cd_frame.grid_columnconfigure(0, weight=1) + (find_size_frame := LabelFrame(sfdma,text='File size range',bd=2,bg=self.bg_color,takefocus=False)).grid(row=3,column=0,sticky='news',padx=4,pady=4) + find_size_frame.grid_columnconfigure((0,1,2,3), weight=1) - self.button_prev = Button(self.find_dialog.area_buttons, text='prev (Shift+F3)', width=14, command=self.find_prev_from_dialog ) - self.button_prev.pack(side='left', anchor='n',padx=5,pady=5) + Label(find_size_frame,text='min: ',bg=self.bg_color,anchor='e',relief='flat',bd=2).grid(row=0, column=0, sticky='we',padx=4,pady=4) + Label(find_size_frame,text='max: ',bg=self.bg_color,anchor='e',relief='flat',bd=2).grid(row=0, column=2, sticky='we',padx=4,pady=4) - self.button_next = Button(self.find_dialog.area_buttons, text='next (F3)', width=14, command=self.find_next_from_dialog ) - self.button_next.pack(side='right', anchor='n',padx=5,pady=5) + def validate_size_str(val): + return True if val == "" or val.isdigit() else False + + #entry_validator = self.main.register(validate_size_str) + #,validate="key",validatecommand=(entry_validator,"%P") + Entry(find_size_frame,textvariable=self.find_size_min_var).grid(row=0, column=1, sticky='we',padx=4,pady=4) + Entry(find_size_frame,textvariable=self.find_size_max_var).grid(row=0, column=3, sticky='we',padx=4,pady=4) - self.button_show = Button(self.find_dialog.area_buttons, text='Show results', width=14, command=self.find_show_results ) - self.button_show.pack(side='right', anchor='n',padx=5,pady=5) - self.find_dialog.area_main.grid_rowconfigure(3, weight=1) - self.find_dialog.area_main.grid_columnconfigure(0, weight=1) + Button(self.find_dialog.area_buttons, text='prev (Shift+F3)', width=14, command=self.find_prev_from_dialog ).pack(side='left', anchor='n',padx=5,pady=5) + Button(self.find_dialog.area_buttons, text='Show results', width=14, command=self.find_show_results ).pack(side='left', anchor='n',padx=5,pady=5) + Button(self.find_dialog.area_buttons, text='Save results', width=14, command=self.find_save_results ).pack(side='left', anchor='n',padx=5,pady=5) + Button(self.find_dialog.area_buttons, text='next (F3)', width=14, command=self.find_next_from_dialog ).pack(side='left', anchor='n',padx=5,pady=5) + Button(self.find_dialog.area_buttons, text='Close', width=14, command=self.find_close ).pack(side='right', anchor='n',padx=5,pady=5) + + sfdma.grid_rowconfigure(4, weight=1) + sfdma.grid_columnconfigure(0, weight=1) self.info_dialog_on_find = dialogs.LabelDialog(self.find_dialog.widget,self_ico['librer'],self.bg_color,pre_show=lambda : pre_show(False),post_close=lambda : post_close(False)) @@ -1277,6 +1286,9 @@ def finder_wrapper_show(self): self.tree_semi_focus() + def find_close(self): + self.find_dialog.hide() + def find_prev_from_dialog(self): self.find_items() self.select_find_result(-1) @@ -1292,10 +1304,20 @@ def find_next_from_dialog(self): self.find_items() self.select_find_result(1) + def find_save_results(self): + print('todo') + def find_show_results(self): self.find_items() if self.find_result: - self.text_dialog_on_find.show('test11',self.find_result) + #self.find_result + rest_txt_list = [] + for res_item in self.find_result: + record,record_result = res_item + rest_txt_list.append(f'record:{record.db.label}\n {sep.join(record_result)}') + + res_txt = '\n'.join(rest_txt_list) + self.text_dialog_on_find.show('test11',res_txt) def find_next(self): if not self.find_result: @@ -1310,6 +1332,9 @@ def find_next(self): def find_mod(self): try: + if self.cfg.get(CFG_KEY_find_range_var) != self.find_range_var.get(): + self.find_params_changed=True + if self.cfg.get(CFG_KEY_find_size_min) != self.find_size_min_var.get(): self.find_params_changed=True @@ -1348,6 +1373,8 @@ def find_mod(self): def find_items(self): if self.find_params_changed: + find_range = self.find_range_var.get() + find_size_min = self.find_size_min_var.get() find_size_max = self.find_size_max_var.get() @@ -1362,17 +1389,27 @@ def find_items(self): if find_size_min: min_num = core_str_to_bytes(find_size_min) if min_num == -1: - min_num = '' + self.info_dialog_on_find.show('min size value error',f'fix "{find_size_min}"') + return else: min_num = '' if find_size_max: max_num = core_str_to_bytes(find_size_max) if max_num == -1: - max_num = '' + self.info_dialog_on_find.show('max size value error',f'fix "{find_size_max}"') + return else: max_num = '' + if check_res := librer_core.find_items_in_all_records_check( + min_num,max_num, + find_name,find_name_regexp,find_name_case_sens, + find_cd,find_cd_regexp,find_cd_case_sens): + self.info_dialog_on_find.show('regular expression error',check_res) + return + + self.cfg.set(CFG_KEY_find_range_var,find_range) self.cfg.set(CFG_KEY_find_size_min,find_size_min) self.cfg.set(CFG_KEY_find_size_max,find_size_max) @@ -1385,10 +1422,35 @@ def find_items(self): self.cfg.set_bool(CFG_KEY_find_cd_regexp,find_cd_regexp) self.cfg.set_bool(CFG_KEY_find_cd_case_sens,find_cd_case_sens) - results = librer_core.find_items_in_all_records( - min_num,max_num, - find_name,find_name_regexp,find_name_case_sens, - find_cd,find_cd_regexp,find_cd_case_sens) + range_par = self.current_record if find_range=='s' else None + + search_thread=Thread(target=lambda : librer_core.find_items_in_all_records(range_par,min_num,max_num,find_name,find_name_regexp,find_name_case_sens,find_cd,find_cd_regexp,find_cd_case_sens),daemon=True) + search_thread.start() + + search_thread_is_alive = search_thread.is_alive + + wait_var=BooleanVar() + wait_var.set(False) + + self_hg_ico = self.hg_ico + len_self_hg_ico = len(self_hg_ico) + hr_index=0 + + while search_thread_is_alive(): + self.status_main(text=librer_core.info_line,image=self_hg_ico[hr_index]) + hr_index=(hr_index+1) % len_self_hg_ico + #self.status_main.update() + + #if librer_core.records_to_show: + # self.single_record_show(librer_core.records_to_show.pop(0)) + #else: + + self.main.after(25,lambda : wait_var.set(not wait_var.get())) + self.main.wait_variable(wait_var) + + search_thread.join + + results = librer_core.find_res results_len = len(results)