Skip to content

Commit 6e21a19

Browse files
committed
Fix bug caused by broken links
1 parent ed580fa commit 6e21a19

5 files changed

Lines changed: 143 additions & 57 deletions

File tree

tkfilebrowser/constants.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,12 @@
6868

6969
IM_HOME = os.path.join(PATH, "images", "home.png")
7070
IM_DESKTOP = os.path.join(PATH, "images", "desktop.png")
71-
IM_FOLDER = os.path.join(PATH, "images", "dossier.png")
72-
IM_FOLDER_LINK = os.path.join(PATH, "images", "dossier_link.png")
71+
IM_FOLDER = os.path.join(PATH, "images", "folder.png")
72+
IM_FOLDER_LINK = os.path.join(PATH, "images", "folder_link.png")
7373
IM_NEW = os.path.join(PATH, "images", "new_folder.png")
7474
IM_FILE = os.path.join(PATH, "images", "file.png")
7575
IM_FILE_LINK = os.path.join(PATH, "images", "file_link.png")
76+
IM_LINK_BROKEN = os.path.join(PATH, "images", "link_broken.png")
7677
IM_DRIVE = os.path.join(PATH, "images", "drive.png")
7778
IM_RECENT = os.path.join(PATH, "images", "recent.png")
7879
IM_RECENT_24 = os.path.join(PATH, "images", "recent_24.png")
@@ -174,6 +175,8 @@ def get_modification_date(file):
174175

175176
def display_modification_date(mtime):
176177
"""Return the modDification date of file."""
178+
if isinstance(mtime, str):
179+
return mtime
177180
tps = fromtimestamp(mtime)
178181
date = locale_date(tps)
179182
if date == TODAY:
@@ -185,6 +188,8 @@ def display_modification_date(mtime):
185188

186189
def display_size(size_o):
187190
"""Return the size of file."""
191+
if isinstance(size_o, str):
192+
return size_o
188193
if size_o > 0:
189194
m = int(floor(log(size_o) / log(1024)))
190195
if m < len(SIZES):

tkfilebrowser/filebrowser.py

Lines changed: 136 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import psutil
2525
from re import search
2626
from subprocess import check_output
27-
from os import walk, mkdir, stat, access, W_OK
27+
from os import walk, mkdir, stat, access, W_OK, listdir
2828
from os.path import exists, join, getmtime, realpath, split, expanduser, \
2929
abspath, isabs, splitext, dirname, getsize, isdir, isfile, islink
3030
try:
@@ -44,6 +44,18 @@
4444
_ = cst._
4545

4646

47+
class Stats:
48+
"""Fake stats class to create dummy stats for broken links."""
49+
def __init__(self, **kwargs):
50+
self._prop = kwargs
51+
52+
def __getattr__(self, attr):
53+
if attr not in self._prop:
54+
raise AttributeError("Stats has no attribute %s." % attr)
55+
else:
56+
return self._prop[attr]
57+
58+
4759
class FileBrowser(tk.Toplevel):
4860
"""Filebrowser dialog class."""
4961
def __init__(self, parent, initialdir="", initialfile="", mode="openfile",
@@ -52,9 +64,9 @@ def __init__(self, parent, initialdir="", initialfile="", mode="openfile",
5264
foldercreation=True, **kw):
5365
"""
5466
Create a filebrowser dialog.
55-
67+
5668
Arguments:
57-
69+
5870
parent : Tk or Toplevel instance
5971
parent window
6072
@@ -66,15 +78,15 @@ def __init__(self, parent, initialdir="", initialfile="", mode="openfile",
6678
6779
initialfile : str
6880
initially selected item (just the name, not the full path)
69-
70-
mode : str
81+
82+
mode : str
7183
kind of dialog: "openfile", "opendir" or "save"
72-
84+
7385
multiple_selection : bool
7486
whether to allow multiple items selection (open modes only)
75-
87+
7688
defaultext : str (e.g. '.png')
77-
extension added to filename if none is given (default is none)
89+
extension added to filename if none is given (default is none)
7890
7991
filetypes : list ``[("name", "*.ext1|*.ext2|.."), ...]``
8092
only the files of given filetype will be displayed,
@@ -194,6 +206,7 @@ def __init__(self, parent, initialdir="", initialfile="", mode="openfile",
194206
self.im_folder = cst.PhotoImage(file=cst.IM_FOLDER, master=self)
195207
self.im_desktop = cst.PhotoImage(file=cst.IM_DESKTOP, master=self)
196208
self.im_file_link = cst.PhotoImage(file=cst.IM_FILE_LINK, master=self)
209+
self.im_link_broken = cst.PhotoImage(file=cst.IM_LINK_BROKEN, master=self)
197210
self.im_folder_link = cst.PhotoImage(file=cst.IM_FOLDER_LINK, master=self)
198211
self.im_new = cst.PhotoImage(file=cst.IM_NEW, master=self)
199212
self.im_drive = cst.PhotoImage(file=cst.IM_DRIVE, master=self)
@@ -401,6 +414,7 @@ def __init__(self, parent, initialdir="", initialfile="", mode="openfile",
401414
self.right_tree.tag_configure("file", image=self.im_file)
402415
self.right_tree.tag_configure("folder_link", image=self.im_folder_link)
403416
self.right_tree.tag_configure("file_link", image=self.im_file_link)
417+
self.right_tree.tag_configure("link_broken", image=self.im_link_broken)
404418
if mode == "opendir":
405419
self.right_tree.tag_configure("file", foreground="gray")
406420
self.right_tree.tag_configure("file_link", foreground="gray")
@@ -961,6 +975,100 @@ def _update_path_bar(self, path):
961975
self.path_bar_buttons.append(b)
962976
b.grid(row=0, column=i + 2, sticky="ns")
963977

978+
def _display_folder_listdir(self, folder, reset=True, update_bar=True):
979+
"""
980+
Display the content of folder in self.right_tree.
981+
Arguments:
982+
* reset (boolean): forget all the part of the history right of self._hist_index
983+
* update_bar (boolean): update the buttons in path bar
984+
"""
985+
print('listdir')
986+
# remove trailing / if any
987+
folder = abspath(folder)
988+
# reorganize display if previous was 'recent'
989+
if not self.path_bar.winfo_ismapped():
990+
self.path_bar.grid()
991+
self.right_tree.configure(displaycolumns=("size", "date"))
992+
w = self.right_tree.winfo_width() - 205
993+
if w < 0:
994+
w = 250
995+
self.right_tree.column("#0", width=w)
996+
self.right_tree.column("size", stretch=False, width=85)
997+
self.right_tree.column("date", width=120)
998+
if self.foldercreation:
999+
self.b_new_folder.grid()
1000+
# reset history
1001+
if reset:
1002+
if not self._hist_index == -1:
1003+
self.history = self.history[:self._hist_index + 1]
1004+
self._hist_index = -1
1005+
self.history.append(folder)
1006+
# update path bar
1007+
if update_bar:
1008+
self._update_path_bar(folder)
1009+
self.path_var.set(folder)
1010+
# disable new folder creation if no write access
1011+
if self.foldercreation:
1012+
if access(folder, W_OK):
1013+
self.b_new_folder.state(('!disabled',))
1014+
else:
1015+
self.b_new_folder.state(('disabled',))
1016+
# clear self.right_tree
1017+
self.right_tree.delete(*self.right_tree.get_children(""))
1018+
self.right_tree.delete(*self.hidden)
1019+
self.hidden = ()
1020+
root = folder
1021+
extension = self.filetypes[self.filetype.get()]
1022+
content = listdir(folder)
1023+
i = 0
1024+
for f in content:
1025+
p = join(root, f)
1026+
if f[0] == ".":
1027+
tags = ("hidden",)
1028+
if not self.hide:
1029+
tags = (str(i % 2),)
1030+
i += 1
1031+
else:
1032+
tags = (str(i % 2),)
1033+
i += 1
1034+
if isfile(p):
1035+
if extension == r".*$" or search(extension, f):
1036+
if islink(p):
1037+
tags = tags + ("file_link",)
1038+
else:
1039+
tags = tags + ("file",)
1040+
try:
1041+
stats = stat(p)
1042+
except OSError:
1043+
self.right_tree.insert("", "end", p, text=f, tags=tags,
1044+
values=("", "??", "??"))
1045+
else:
1046+
self.right_tree.insert("", "end", p, text=f, tags=tags,
1047+
values=("",
1048+
display_size(stats.st_size),
1049+
display_modification_date(stats.st_mtime)))
1050+
elif isdir(p):
1051+
if islink(p):
1052+
tags = tags + ("folder_link",)
1053+
else:
1054+
tags = tags + ("folder",)
1055+
1056+
self.right_tree.insert("", "end", p, text=f, tags=tags,
1057+
values=("", "", get_modification_date(p)))
1058+
else: # broken link
1059+
tags = tags + ("link_broken",)
1060+
self.right_tree.insert("", "end", p, text=f, tags=tags,
1061+
values=("", "??", "??"))
1062+
1063+
items = self.right_tree.get_children("")
1064+
if items:
1065+
self.right_tree.focus_set()
1066+
self.right_tree.focus(items[0])
1067+
if self.hide:
1068+
self.hidden = self.right_tree.tag_has("hidden")
1069+
self.right_tree.detach(*self.right_tree.tag_has("hidden"))
1070+
self._sort_files_by_name(False)
1071+
9641072
def _display_folder_walk(self, folder, reset=True, update_bar=True):
9651073
"""
9661074
Display the content of folder in self.right_tree.
@@ -1026,13 +1134,18 @@ def _display_folder_walk(self, folder, reset=True, update_bar=True):
10261134
# display files
10271135
files.sort(key=lambda n: n.lower())
10281136
extension = self.filetypes[self.filetype.get()]
1029-
if extension == ".*":
1030-
for f in files:
1137+
for f in files:
1138+
if extension == r".*$" or search(extension, f):
10311139
p = join(root, f)
10321140
if islink(p):
10331141
tags = ("file_link",)
10341142
else:
10351143
tags = ("file",)
1144+
try:
1145+
stats = stat(p)
1146+
except FileNotFoundError:
1147+
stats = Stats(st_size="??", st_mtime="??")
1148+
tags = ("link_broken",)
10361149
if f[0] == ".":
10371150
tags = tags + ("hidden",)
10381151
if not self.hide:
@@ -1042,47 +1155,10 @@ def _display_folder_walk(self, folder, reset=True, update_bar=True):
10421155
tags = tags + (str(i % 2),)
10431156
i += 1
10441157

1045-
try:
1046-
stats = stat(p)
1047-
except OSError:
1048-
self.right_tree.insert("", "end", p, text=f, tags=tags,
1049-
values=("",
1050-
display_size(0),
1051-
display_modification_date(cst.TODAY)))
1052-
else:
1053-
self.right_tree.insert("", "end", p, text=f, tags=tags,
1054-
values=("",
1055-
display_size(stats.st_size),
1056-
display_modification_date(stats.st_mtime)))
1057-
else:
1058-
for f in files:
1059-
if extension == r".*$" or search(extension, f):
1060-
p = join(root, f)
1061-
if islink(p):
1062-
tags = ("file_link",)
1063-
else:
1064-
tags = ("file",)
1065-
if f[0] == ".":
1066-
tags = tags + ("hidden",)
1067-
if not self.hide:
1068-
tags = tags + (str(i % 2),)
1069-
i += 1
1070-
else:
1071-
tags = tags + (str(i % 2),)
1072-
i += 1
1073-
1074-
try:
1075-
stats = stat(p)
1076-
except OSError:
1077-
self.right_tree.insert("", "end", p, text=f, tags=tags,
1078-
values=("",
1079-
display_size(0),
1080-
display_modification_date(cst.TODAY)))
1081-
else:
1082-
self.right_tree.insert("", "end", p, text=f, tags=tags,
1083-
values=("",
1084-
display_size(stats.st_size),
1085-
display_modification_date(stats.st_mtime)))
1158+
self.right_tree.insert("", "end", p, text=f, tags=tags,
1159+
values=("",
1160+
display_size(stats.st_size),
1161+
display_modification_date(stats.st_mtime)))
10861162
items = self.right_tree.get_children("")
10871163
if items:
10881164
self.right_tree.focus_set()
@@ -1091,7 +1167,7 @@ def _display_folder_walk(self, folder, reset=True, update_bar=True):
10911167
self.hidden = self.right_tree.tag_has("hidden")
10921168
self.right_tree.detach(*self.right_tree.tag_has("hidden"))
10931169
except StopIteration:
1094-
self._display_folder_walk(expanduser('~'), reset, update_bar)
1170+
self._display_folder_listdir(folder, reset, update_bar)
10951171

10961172
def _display_folder_scandir(self, folder, reset=True, update_bar=True):
10971173
"""
@@ -1139,11 +1215,17 @@ def _display_folder_scandir(self, folder, reset=True, update_bar=True):
11391215
try:
11401216
content = sorted(scandir(folder), key=key_sort_files)
11411217
i = 0
1142-
tags_array = [["folder", "folder_link"], ["file", "file_link"]]
1218+
tags_array = [["folder", "folder_link"],
1219+
["file", "file_link"]]
11431220
for f in content:
11441221
b_file = f.is_file()
11451222
name = f.name
1146-
tags = (tags_array[b_file][f.is_symlink()],)
1223+
try:
1224+
stats = f.stat()
1225+
tags = (tags_array[b_file][f.is_symlink()],)
1226+
except FileNotFoundError:
1227+
stats = Stats(st_size="??", st_mtime="??")
1228+
tags = ("link_broken",)
11471229
if name[0] == '.':
11481230
tags = tags + ("hidden",)
11491231
if not self.hide:
@@ -1152,7 +1234,6 @@ def _display_folder_scandir(self, folder, reset=True, update_bar=True):
11521234
else:
11531235
tags = tags + (str(i % 2),)
11541236
i += 1
1155-
stats = f.stat()
11561237
if b_file:
11571238
if extension == r".*$" or search(extension, name):
11581239
self.right_tree.insert("", "end", f.path, text=name, tags=tags,
6.46 KB
Loading

0 commit comments

Comments
 (0)