Skip to content

Commit bb85172

Browse files
committed
skipping hidden files/folders by default (+ option)
fix of finding files on non-default showing mode
1 parent 9f87a43 commit bb85172

File tree

4 files changed

+80
-32
lines changed

4 files changed

+80
-32
lines changed

src/core.py

+26-6
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@
3636
from time import sleep,strftime,localtime,time,perf_counter
3737

3838
from os import stat,scandir,sep,symlink,link,cpu_count,name as os_name,rename as os_rename,remove as os_remove
39+
from stat import FILE_ATTRIBUTE_HIDDEN as stat_FILE_ATTRIBUTE_HIDDEN
3940

40-
from os.path import dirname,relpath,normpath,join as path_join,abspath as abspath,exists as path_exists,isdir as path_isdir
41+
from os.path import dirname,relpath,normpath,basename,join as path_join,abspath as abspath,exists as path_exists,isdir as path_isdir
4142

4243
if os_name=='nt':
4344
from subprocess import CREATE_NO_WINDOW
@@ -194,6 +195,16 @@ def join(self):
194195
self.log.info('CRCThreadedCalc %s join',self)
195196
self.thread.join()
196197

198+
windows = bool(os_name=='nt')
199+
200+
def is_hidden_win(filepath):
201+
return bool(stat(filepath).st_file_attributes & stat_FILE_ATTRIBUTE_HIDDEN)
202+
203+
def is_hidden_lin(filepath):
204+
return basename(abspath(filepath)).startswith('.')
205+
206+
is_hidden = is_hidden_win if windows else is_hidden_lin
207+
197208
MODE_CRC = 0
198209
MODE_SIMILARITY = 1
199210
MODE_GPS = 2
@@ -334,7 +345,7 @@ def convert_to_degrees(value):
334345
return None
335346

336347
scan_update_info_path_nr=None
337-
def scan(self,operation_mode,file_min_size_int=0,file_max_size_int=0):
348+
def scan(self,operation_mode,file_min_size_int=0,file_max_size_int=0,include_hidden=False):
338349
from PIL.Image import open as image_open
339350

340351
self.log.info('')
@@ -369,6 +380,7 @@ def scan(self,operation_mode,file_min_size_int=0,file_max_size_int=0):
369380
use_max_size = bool(file_max_size_int!=0)
370381
use_size = use_min_size or use_max_size
371382

383+
is_hidden_loc=is_hidden
372384
#############################################################################################
373385
if operation_mode in (MODE_SIMILARITY,MODE_GPS):
374386

@@ -420,14 +432,18 @@ def scan(self,operation_mode,file_min_size_int=0,file_max_size_int=0):
420432
if entry.is_symlink() :
421433
skipping_action('skippping link: %s / %s',path,entry.name)
422434
else:
435+
fullpath=path_join(path,entry.name)
436+
if not include_hidden and is_hidden_loc(fullpath):
437+
skipping_action('skipping hidden Mask:%s',fullpath)
438+
continue
439+
423440
if any_exclude_list:
424-
fullpath=path_join(path,entry.name)
425441
if any({self_excl_fn(expr,fullpath) for expr in self_exclude_list}):
426442
skipping_action('skipping by Exclude Mask:%s',fullpath)
427443
continue
428444

429445
if entry.is_dir():
430-
loop_list_append(path_join(path,entry.name))
446+
loop_list_append(fullpath)
431447
elif entry.is_file():
432448
try:
433449
stat_res = stat(entry)
@@ -537,14 +553,18 @@ def scan(self,operation_mode,file_min_size_int=0,file_max_size_int=0):
537553
if entry.is_symlink() :
538554
skipping_action('skippping link: %s / %s',path,entry.name)
539555
else:
556+
fullpath=path_join(path,entry.name)
557+
if not include_hidden and is_hidden_loc(fullpath):
558+
skipping_action('skipping hidden Mask:%s',fullpath)
559+
continue
560+
540561
if any_exclude_list:
541-
fullpath=path_join(path,entry.name)
542562
if any({self_excl_fn(expr,fullpath) for expr in self_exclude_list}):
543563
skipping_action('skipping by Exclude Mask:%s',fullpath)
544564
continue
545565

546566
if entry.is_dir():
547-
loop_list_append(path_join(path,entry.name))
567+
loop_list_append(fullpath)
548568
elif entry.is_file():
549569
try:
550570
stat_res = stat(entry)

src/dialogs.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ def __init__(self,parent,icon,bg_color,pre_show=None,post_close=None,min_width=1
411411
Label(self.area_dummy, width=22,bg=self.bg_color).pack(side='right', anchor='e',padx=5,pady=5)
412412
Label(self.area_dummy, width=8,bg=self.bg_color).pack(side='right', anchor='e',padx=5,pady=5)
413413

414-
self.focus=self.cancel_button
414+
self.focus = self.cancel_button
415415

416416
def key_press_f3(self,event):
417417
self.find_next_prev(1)
@@ -516,7 +516,7 @@ def show(self,title='',message='',uplabel_text=''):
516516
self.copy_button.configure(state='normal')
517517

518518
self.find_key_binding()
519-
self.focus = self_text
519+
520520
super().show()
521521

522522
class TextDialogQuestion(TextDialogInfo):
@@ -529,7 +529,7 @@ def __init__(self,parent,icon,bg_color,pre_show=None,post_close=None,min_width=8
529529
self.ok_button=Button(self.area_buttons, text='OK', width=14, command=self.ok,image=image, compound='left' )
530530
self.ok_button.pack(side='right', anchor='n',padx=5,pady=5,fill='both')
531531

532-
self.focus=self.cancel_button
532+
self.focus=self.ok_button
533533

534534
def ok (self):
535535
self.res_bool=True

src/dude.py

+43-23
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
###########################################################################################################################################
8787

8888
CFG_THEME='theme'
89+
CFG_KEY_include_hidden = 'include_hidden'
8990
CFG_KEY_FULL_CRC='show_full_crc'
9091
CFG_KEY_SHOW_TOOLTIPS_INFO='show_tooltips_info'
9192
CFG_KEY_SHOW_TOOLTIPS_HELP='show_tooltips_help'
@@ -132,6 +133,7 @@
132133

133134
cfg_defaults={
134135
CFG_THEME:'Vista' if windows else 'Clam',
136+
CFG_KEY_include_hidden:False,
135137
CFG_KEY_FULL_CRC:False,
136138
CFG_KEY_SHOW_TOOLTIPS_INFO:True,
137139
CFG_KEY_SHOW_TOOLTIPS_HELP:True,
@@ -1805,6 +1807,7 @@ def get_settings_dialog(self):
18051807
self.settings_dialog=GenericDialog(self.main,self.main_icon_tuple,self.bg_color,STR('Settings'),pre_show=self.pre_show_settings,post_close=self.post_close)
18061808

18071809
self.theme = StringVar()
1810+
self.scan_hidden_var = BooleanVar()
18081811
self.show_full_crc = BooleanVar()
18091812
self.show_tooltips_info = BooleanVar()
18101813
self.show_tooltips_help = BooleanVar()
@@ -1830,6 +1833,7 @@ def get_settings_dialog(self):
18301833
self.folders_open_wrapper_params = StringVar()
18311834

18321835
self.settings = [
1836+
(self.scan_hidden_var,CFG_KEY_include_hidden),
18331837
(self.show_full_crc,CFG_KEY_FULL_CRC),
18341838
(self.show_tooltips_info,CFG_KEY_SHOW_TOOLTIPS_INFO),
18351839
(self.show_tooltips_help,CFG_KEY_SHOW_TOOLTIPS_HELP),
@@ -1886,6 +1890,11 @@ def get_settings_dialog(self):
18861890

18871891
label_frame.grid_columnconfigure((0,1,2), weight=1)
18881892

1893+
label_frame=LabelFrame(self.settings_dialog.area_main, text=STR("Scan options"),borderwidth=2,bg=self.bg_color)
1894+
label_frame.grid(row=row,column=0,sticky='wens',padx=3,pady=3) ; row+=1
1895+
1896+
(cb_1:=Checkbutton(label_frame, text = ' ' + STR('Include hidden files / folders in scan'), variable=self.scan_hidden_var)).grid(row=0,column=0,sticky='wens',padx=3,pady=2)
1897+
18891898
label_frame=LabelFrame(self.settings_dialog.area_main, text=STR("Main panels and dialogs"),borderwidth=2,bg=self.bg_color)
18901899
label_frame.grid(row=row,column=0,sticky='wens',padx=3,pady=3) ; row+=1
18911900

@@ -2664,8 +2673,9 @@ def find_prev_from_dialog(self,expression,use_reg_expr):
26642673
self.select_find_result(-1)
26652674

26662675
def find_prev(self):
2667-
if not self.find_result or self.find_tree!=self.sel_tree:
2676+
if not self.find_result or self.find_tree!=self.sel_tree or self.find_params_changed:
26682677
self.find_params_changed=True
2678+
self.find_result_index=0
26692679
self.finder_wrapper_show()
26702680
else:
26712681
self.select_find_result(-1)
@@ -2675,8 +2685,9 @@ def find_next_from_dialog(self,expression,use_reg_expr):
26752685
self.select_find_result(1)
26762686

26772687
def find_next(self):
2678-
if not self.find_result or self.find_tree!=self.sel_tree:
2688+
if not self.find_result or self.find_tree!=self.sel_tree or self.find_params_changed:
26792689
self.find_params_changed=True
2690+
self.find_result_index=0
26802691
self.finder_wrapper_show()
26812692
else:
26822693
self.select_find_result(1)
@@ -2698,7 +2709,13 @@ def find_mod(self,expression,use_reg_expr):
26982709
def find_items(self,expression,use_reg_expr):
26992710
self.status(STR('finding ...'))
27002711

2712+
self_files_of_groups_filtered_by_mode = self.files_of_groups_filtered_by_mode
2713+
2714+
crc_shown = list(self_files_of_groups_filtered_by_mode.keys())
2715+
27012716
if self.find_params_changed or self.find_tree != self.sel_tree:
2717+
self.find_result=()
2718+
27022719
self.find_tree=self.sel_tree
27032720

27042721
items=[]
@@ -2712,10 +2729,15 @@ def find_items(self,expression,use_reg_expr):
27122729

27132730
try:
27142731
for crc_item in crc_range:
2715-
for item in self.tree_children_sub[crc_item]:
2716-
fullpath = self_item_full_path(item)
2717-
if (use_reg_expr and search(expression,fullpath)) or (not use_reg_expr and fnmatch(fullpath,expression) ):
2718-
items_append(item)
2732+
if crc_item in crc_shown:
2733+
sub_items = self_files_of_groups_filtered_by_mode[crc_item]
2734+
2735+
for item in self.tree_children_sub[crc_item]:
2736+
fullpath = self_item_full_path(item)
2737+
if (use_reg_expr and search(expression,fullpath)) or (not use_reg_expr and fnmatch(fullpath,expression) ):
2738+
kind,size,crc, (pathnr,path,file,ctime,dev,inode) = self.groups_tree_item_to_data[item]
2739+
if (dev,inode) in sub_items:
2740+
items_append(item)
27192741
except Exception as e:
27202742
try:
27212743
self.info_dialog_on_find[self.find_tree].show('Error',str(e))
@@ -2742,15 +2764,12 @@ def find_items(self,expression,use_reg_expr):
27422764

27432765
def select_find_result(self,mod):
27442766
if self.find_result:
2767+
#print(f'{self.find_result=}')
27452768
items_len=len(self.find_result)
27462769
self.find_result_index+=mod
27472770
next_item=self.find_result[self.find_result_index%items_len]
27482771

2749-
if self.find_dialog_shown:
2750-
#focus is still on find dialog
2751-
self.semi_selection(self.find_tree,next_item)
2752-
else:
2753-
self.semi_selection(self.find_tree,next_item)
2772+
self.semi_selection(self.find_tree,next_item)
27542773

27552774
self.tree_see_wrapper(self.find_tree,next_item)
27562775

@@ -2816,7 +2835,6 @@ def goto_next_prev_crc(self,direction):
28162835

28172836
if tree_set(current_item,'kind')==self_CRC:
28182837
self.crc_select_and_focus_child(current_item)
2819-
28202838
self.status(status)
28212839

28222840
break
@@ -2875,14 +2893,8 @@ def key_release(self,event):
28752893

28762894
if key=="Next":
28772895
item=tree.focus()
2878-
#tree.yview_moveto(tree.bbox(item)[1] / tree.winfo_height())
28792896
children=tree.get_children(item)
28802897
children_len=len(children)
2881-
2882-
#if children_len>=3:
2883-
# tree.see(children[2])
2884-
#elif children_len:
2885-
# tree.see(children[-1])
28862898
except Exception as e :
28872899
#print(e)
28882900
pass
@@ -4113,9 +4125,12 @@ def scan(self):
41134125
if file_max_size_int==-1:
41144126
file_max_size_int=0
41154127

4128+
#################
4129+
include_hidden = self.cfg_get_bool(CFG_KEY_include_hidden)
4130+
41164131
#################
41174132

4118-
scan_thread=Thread(target=lambda : dude_core.scan(operation_mode,file_min_size_int,file_max_size_int),daemon=True)
4133+
scan_thread=Thread(target=lambda : dude_core.scan(operation_mode,file_min_size_int,file_max_size_int,include_hidden),daemon=True)
41194134
scan_thread.start()
41204135

41214136
self_progress_dialog_on_scan.lab_l1.configure(text=STR('Total space:'))
@@ -4625,6 +4640,9 @@ def settings_ok(self):
46254640
if not need_restart:
46264641
self.get_info_dialog_on_settings().show(STR('Theme Changed'),STR('Application restart required\nfor changes to take effect'))
46274642

4643+
if self.cfg_get_bool(CFG_KEY_include_hidden)!=self.scan_hidden_var.get():
4644+
self.cfg.set_bool(CFG_KEY_include_hidden,self.scan_hidden_var.get())
4645+
46284646
if self.cfg_get_bool(CFG_KEY_FULL_CRC)!=self.show_full_crc.get():
46294647
self.cfg.set_bool(CFG_KEY_FULL_CRC,self.show_full_crc.get())
46304648
update1=True
@@ -4647,6 +4665,8 @@ def settings_ok(self):
46474665

46484666
if self.cfg_get(CFG_KEY_SHOW_MODE)!=self.show_mode.get():
46494667
self.cfg.set(CFG_KEY_SHOW_MODE,self.show_mode.get())
4668+
self.find_params_changed=True
4669+
self.find_result_index=0
46504670
update0=True
46514671

46524672
if self.cfg_get_bool(CFG_KEY_REL_SYMLINKS)!=self.create_relative_symlinks.get():
@@ -4940,12 +4960,13 @@ def groups_show(self):
49404960
#kind,crc,(pathnr,path,file,ctime,dev,inode)
49414961
self_groups_tree_item_to_data[group_item]=(self_CRC,size,crc,(None,None,None,None,None,None) )
49424962

4963+
files_of_groups_filtered_by_mode_group_index_add = files_of_groups_filtered_by_mode[group_index].add
49434964
for pathnr,path,file,ctime,dev,inode,size in sorted(items_set,key=lambda x : (x[6],x[0],x[1],x[2]),reverse=True):
49444965
if show_mode_same_dir:
49454966
if hist[(pathnr,path)]==1:
49464967
continue
49474968

4948-
files_of_groups_filtered_by_mode[group_index].add( (dev,inode) )
4969+
files_of_groups_filtered_by_mode_group_index_add( (dev,inode) )
49494970

49504971
#print(pathnr,path,file,mtime,ctime,dev,inode,size)
49514972
iid=self_idfunc(inode,dev)
@@ -4998,13 +5019,14 @@ def groups_show(self):
49985019
#kind,crc,index_tuple
49995020
#kind,crc,(pathnr,path,file,ctime,dev,inode)
50005021
self_groups_tree_item_to_data[crc_item]=(self_CRC,size,crc,(None,None,None,None,None,None) )
5022+
files_of_groups_filtered_by_mode_crc_add = files_of_groups_filtered_by_mode[crc].add
50015023

50025024
for pathnr,path,file,ctime,dev,inode in sorted(crc_dict,key = lambda x : x[0]):
50035025
if show_mode_same_dir:
50045026
if hist[(pathnr,path)]==1:
50055027
continue
50065028

5007-
files_of_groups_filtered_by_mode[crc].add( (dev,inode) )
5029+
files_of_groups_filtered_by_mode_crc_add( (dev,inode) )
50085030

50095031
iid=self_idfunc(inode,dev)
50105032
self_iid_to_size[iid]=size
@@ -5106,8 +5128,6 @@ def tree_folder_update(self,arbitrary_path=None):
51065128

51075129
current_path=arbitrary_path if arbitrary_path else self.sel_path_full
51085130

5109-
#print('current_path:',current_path)
5110-
51115131
if not current_path:
51125132
return False
51135133

src/text.py

+8
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,14 @@ class LANGUAGES:
755755
'it': 'Somiglianza tra immagini',
756756
'fr': 'Similitude des images',
757757
},
758+
'Include hidden files / folders in scan': {
759+
'pl': "Uwzględniaj pliki/foldery ukryte",
760+
'es': "Incluir archivos/carpetas ocultos en el escaneo",
761+
'ru': "Включить скрытые файлы/папки в сканирование",
762+
'de': "Versteckte Dateien/Ordner in den Scan einbeziehen",
763+
'it': "Includi file/cartelle nascosti nella scansione",
764+
'fr': "Inclure les fichiers/dossiers cachés dans l'analyse",
765+
},
758766
'Information': {
759767
'pl': 'Informacja',
760768
'es': 'Información',

0 commit comments

Comments
 (0)