aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeonard Kugis <leonard@kug.is>2023-04-09 05:40:53 +0200
committerLeonard Kugis <leonard@kug.is>2023-04-09 05:40:53 +0200
commit4b67f639061911f07442f05484114f0c4cddc64e (patch)
treef79a617b9025caca6d0d87a858d2eab2e2dbf5cc
parent1433cd6f2dccb6b981209a2cc2a3ac6a45156387 (diff)
Implemented metadata tagging
-rw-r--r--file-tagger.py25
-rw-r--r--gui.py37
2 files changed, 45 insertions, 17 deletions
diff --git a/file-tagger.py b/file-tagger.py
index 9708dfa..67e1102 100644
--- a/file-tagger.py
+++ b/file-tagger.py
@@ -9,6 +9,7 @@ from tmsu import *
from util import *
from predictor import *
from PIL import Image
+import datetime
'''
Walk over all files for the given base directory and all subdirectories recursively.
@@ -54,6 +55,28 @@ def walk(tmsu, args):
if args["open_system"]:
open_system(file_path)
+ if args["tag_metadata"]:
+ # Base name and extension
+ base = os.path.splitext(os.path.basename(file_path))
+ if base[1]:
+ tags.update({base[0], base[1]})
+ else:
+ tags.update({base[0]})
+ # File creation and modification time
+ time_c = datetime.datetime.fromtimestamp(os.path.getctime(file_path))
+ time_m = datetime.datetime.fromtimestamp(os.path.getmtime(file_path))
+ tags.update({time_c.strftime("%Y-%m-%d"),
+ time_c.strftime("%Y"),
+ time_c.strftime("%B"),
+ time_c.strftime("%A"),
+ time_c.strftime("%Hh")})
+ if time_c != time_m:
+ tags.update({time_m.strftime("%Y-%m-%d"),
+ time_m.strftime("%Y"),
+ time_m.strftime("%B"),
+ time_m.strftime("%A"),
+ time_m.strftime("%Hh")})
+
# Detect MIME-type for file
mime_type = mime.from_file(file_path)
@@ -106,6 +129,7 @@ if __name__ == "__main__":
parser.add_argument('-f', '--file-dir', nargs='?', default='.', type=dir_path, help='File directory for walking (default: %(default)s)')
parser.add_argument('-g', '--gui', nargs='?', const=1, default=False, type=bool, help='Show main GUI (default: %(default)s)')
parser.add_argument('--tmsu-command', nargs='?', const=1, default="tmsu", type=str, help='TMSU command override (default: %(default)s)')
+ parser.add_argument('--tag-metadata', nargs='?', const=1, default=True, type=bool, help='Use metadata as default tags (default: %(default)s)')
parser.add_argument('--predict-images', nargs='?', const=1, default=False, type=bool, help='Use prediction for image tagging (default: %(default)s)')
parser.add_argument('--predict-images-backend', nargs='?', const=1, choices=["torch", "tensorflow", "keras"], default="torch", type=str.lower, help='Determines which backend should be used for keyword prediction (default: %(default)s)')
parser.add_argument('--predict-images-top', nargs='?', const=1, default=10, type=int, help='Defines how many top prediction keywords should be used (default: %(default)s)')
@@ -135,6 +159,7 @@ if __name__ == "__main__":
"file_dir": args.file_dir,
"gui": args.gui,
"tmsu_command": args.tmsu_command,
+ "tag_metadata": args.tag_metadata,
"predict_images": args.predict_images,
"predict_images_backend": args.predict_images_backend,
"predict_images_top": args.predict_images_top,
diff --git a/gui.py b/gui.py
index 7bd30ad..8f2ad4c 100644
--- a/gui.py
+++ b/gui.py
@@ -13,6 +13,7 @@ class GuiMain(object):
self.__args = args
self.__base = StringVar(self.__master, value=args["base"])
self.__file_dir = StringVar(self.__master, value=args["file_dir"])
+ self.__tag_metadata = BooleanVar(self.__master, value=args["tag_metadata"])
self.__predict_images = BooleanVar(self.__master, value=args["predict_images"])
self.__predict_images_backend = StringVar(self.__master, value=str(args["predict_images_backend"]))
self.__predict_images_top = StringVar(self.__master, value=str(args["predict_images_top"]))
@@ -33,29 +34,31 @@ class GuiMain(object):
Label(self.__master, text="File directory for walking:").grid(row=1, column=0)
Entry(self.__master, textvariable=self.__file_dir).grid(row=1, column=1, columnspan=2)
Button(self.__master, text="Browse", command=lambda: self.__browse(self.__file_dir)).grid(row=1, column=3)
- Checkbutton(self.__master, text="Use prediction for image tagging", variable=self.__predict_images).grid(row=2, column=0, columnspan=4, sticky=W)
- Label(self.__master, text="Image prediction backend:").grid(row=3, column=0)
- ttk.Combobox(self.__master, textvariable=self.__predict_images_backend, values=("torch", "tensorflow", "keras"), state="readonly").grid(row=3, column=1)
- Label(self.__master, text="Number of top results:").grid(row=4, column=0)
- Entry(self.__master, textvariable=self.__predict_images_top, validate='all', validatecommand=(validate_number, '%P')).grid(row=4, column=1, columnspan=1)
- Checkbutton(self.__master, text="Skip detail scan in image prediction", variable=self.__predict_images_skip_detail).grid(row=5, column=0, columnspan=4, sticky=W)
- Label(self.__master, text="Width factor for detail scan:").grid(row=6, column=0)
- Entry(self.__master, textvariable=self.__predict_images_detail_factor, validate='all', validatecommand=(validate_number, '%P')).grid(row=6, column=1, columnspan=1)
- Checkbutton(self.__master, text="Show GUI for tagging", variable=self.__gui_tag).grid(row=7, column=0, columnspan=4, sticky=W)
- Label(self.__master, text="Image GUI preview size:").grid(row=8, column=0)
- Entry(self.__master, textvariable=self.__gui_image_length, validate='all', validatecommand=(validate_number, '%P')).grid(row=8, column=1, columnspan=1)
- Checkbutton(self.__master, text="Open all files with system default", variable=self.__open_system).grid(row=9, column=0, columnspan=4, sticky=W)
- Checkbutton(self.__master, text="Skip prompt for file tags", variable=self.__skip_prompt).grid(row=10, column=0, columnspan=4, sticky=W)
- Checkbutton(self.__master, text="Skip already tagged files", variable=self.__skip_tagged).grid(row=11, column=0, columnspan=4, sticky=W)
- Label(self.__master, text="Start at index:").grid(row=12, column=0)
- Entry(self.__master, textvariable=self.__index, validate='all', validatecommand=(validate_number, '%P')).grid(row=12, column=1, columnspan=1)
- Button(self.__master, text="Start", command=self.__master.destroy).grid(row=13, column=0, columnspan=4)
+ Checkbutton(self.__master, text="Use metadata as default tags", variable=self.__tag_metadata).grid(row=2, column=0, columnspan=4, sticky=W)
+ Checkbutton(self.__master, text="Use prediction for image tagging", variable=self.__predict_images).grid(row=3, column=0, columnspan=4, sticky=W)
+ Label(self.__master, text="Image prediction backend:").grid(row=4, column=0)
+ ttk.Combobox(self.__master, textvariable=self.__predict_images_backend, values=("torch", "tensorflow", "keras"), state="readonly").grid(row=4, column=1)
+ Label(self.__master, text="Number of top results:").grid(row=5, column=0)
+ Entry(self.__master, textvariable=self.__predict_images_top, validate='all', validatecommand=(validate_number, '%P')).grid(row=5, column=1, columnspan=1)
+ Checkbutton(self.__master, text="Skip detail scan in image prediction", variable=self.__predict_images_skip_detail).grid(row=6, column=0, columnspan=4, sticky=W)
+ Label(self.__master, text="Width factor for detail scan:").grid(row=7, column=0)
+ Entry(self.__master, textvariable=self.__predict_images_detail_factor, validate='all', validatecommand=(validate_number, '%P')).grid(row=7, column=1, columnspan=1)
+ Checkbutton(self.__master, text="Show GUI for tagging", variable=self.__gui_tag).grid(row=8, column=0, columnspan=4, sticky=W)
+ Label(self.__master, text="Image GUI preview size:").grid(row=9, column=0)
+ Entry(self.__master, textvariable=self.__gui_image_length, validate='all', validatecommand=(validate_number, '%P')).grid(row=9, column=1, columnspan=1)
+ Checkbutton(self.__master, text="Open all files with system default", variable=self.__open_system).grid(row=10, column=0, columnspan=4, sticky=W)
+ Checkbutton(self.__master, text="Skip prompt for file tags", variable=self.__skip_prompt).grid(row=11, column=0, columnspan=4, sticky=W)
+ Checkbutton(self.__master, text="Skip already tagged files", variable=self.__skip_tagged).grid(row=12, column=0, columnspan=4, sticky=W)
+ Label(self.__master, text="Start at index:").grid(row=13, column=0)
+ Entry(self.__master, textvariable=self.__index, validate='all', validatecommand=(validate_number, '%P')).grid(row=13, column=1, columnspan=1)
+ Button(self.__master, text="Start", command=self.__master.destroy).grid(row=14, column=0, columnspan=4)
def loop(self):
self.__master.mainloop()
self.__args["base"] = self.__base.get()
self.__args["file_dir"] = self.__file_dir.get()
+ self.__args["tag_metadata"] = self.__tag_metadata.get()
self.__args["predict_images"] = self.__predict_images.get()
self.__args["predict_images_backend"] = self.__predict_images_backend.get()
self.__args["predict_images_top"] = int(self.__predict_images_top.get())