33# Created for TagStudio: https://github.com/CyanVoxel/TagStudio
44
55import logging
6+ import os
67from pathlib import Path
78import platform
89import time
@@ -98,6 +99,21 @@ def __init__(self, library: Library, driver: "QtDriver"):
9899 image_layout = QHBoxLayout (self .image_container )
99100 image_layout .setContentsMargins (0 , 0 , 0 , 0 )
100101
102+ file_label_style = "font-size: 12px"
103+ properties_style = (
104+ f"background-color:{ self .label_bg_color } ;"
105+ "color:#FFFFFF;"
106+ "font-family:Oxanium;"
107+ "font-weight:bold;"
108+ "font-size:12px;"
109+ "border-radius:3px;"
110+ "padding-top: 4px;"
111+ "padding-right: 1px;"
112+ "padding-bottom: 1px;"
113+ "padding-left: 1px;"
114+ )
115+ date_style = "font-size:12px;"
116+
101117 self .open_file_action = QAction ("Open file" , self )
102118 self .trash_term : str = "Trash"
103119 if platform .system () == "Windows" :
@@ -157,31 +173,26 @@ def __init__(self, library: Library, driver: "QtDriver"):
157173 image_layout .addWidget (self .preview_vid )
158174 image_layout .setAlignment (self .preview_vid , Qt .AlignmentFlag .AlignCenter )
159175 self .image_container .setMinimumSize (* self .img_button_size )
160- self .file_label = FileOpenerLabel ("Filename" )
176+ self .file_label = FileOpenerLabel ("filename" )
177+ self .file_label .setTextFormat (Qt .TextFormat .RichText )
161178 self .file_label .setWordWrap (True )
162179 self .file_label .setTextInteractionFlags (
163180 Qt .TextInteractionFlag .TextSelectableByMouse
164181 )
165- self .file_label .setStyleSheet ("font-weight: bold; font-size: 12px" )
182+ self .file_label .setStyleSheet (file_label_style )
166183
167- self .dimensions_label = QLabel ("Dimensions " )
168- self .dimensions_label . setWordWrap ( True )
169- # self.dim_label.setTextInteractionFlags(
170- # Qt.TextInteractionFlag.TextSelectableByMouse )
184+ self .date_created_label = QLabel ("dateCreatedLabel " )
185+ self .date_created_label . setAlignment ( Qt . AlignmentFlag . AlignLeft )
186+ self .date_created_label . setTextFormat ( Qt . TextFormat . RichText )
187+ self . date_created_label . setStyleSheet ( date_style )
171188
172- properties_style = (
173- f"background-color:{ self .label_bg_color } ;"
174- "color:#FFFFFF;"
175- "font-family:Oxanium;"
176- "font-weight:bold;"
177- "font-size:12px;"
178- "border-radius:3px;"
179- "padding-top: 4px;"
180- "padding-right: 1px;"
181- "padding-bottom: 1px;"
182- "padding-left: 1px;"
183- )
189+ self .date_modified_label = QLabel ("dateModifiedLabel" )
190+ self .date_modified_label .setAlignment (Qt .AlignmentFlag .AlignLeft )
191+ self .date_modified_label .setTextFormat (Qt .TextFormat .RichText )
192+ self .date_modified_label .setStyleSheet (date_style )
184193
194+ self .dimensions_label = QLabel ("dimensionsLabel" )
195+ self .dimensions_label .setWordWrap (True )
185196 self .dimensions_label .setStyleSheet (properties_style )
186197
187198 self .scroll_layout = QVBoxLayout ()
@@ -219,7 +230,15 @@ def __init__(self, library: Library, driver: "QtDriver"):
219230 )
220231 scroll_area .setWidget (scroll_container )
221232
233+ date_container = QWidget ()
234+ date_layout = QVBoxLayout (date_container )
235+ date_layout .setContentsMargins (0 , 2 , 0 , 0 )
236+ date_layout .setSpacing (0 )
237+ date_layout .addWidget (self .date_created_label )
238+ date_layout .addWidget (self .date_modified_label )
239+
222240 info_layout .addWidget (self .file_label )
241+ info_layout .addWidget (date_container )
223242 info_layout .addWidget (self .dimensions_label )
224243 info_layout .addWidget (scroll_area )
225244
@@ -470,6 +489,28 @@ def add_field_to_selected(self, field_list: list[QModelIndex]):
470489 for field_item in field_list :
471490 self .lib .add_field_to_entry (item_id , field_item .row ())
472491
492+ def update_date_label (self , filepath : Path | None = None ) -> None :
493+ """Update the "Date Created" and "Date Modified" file property labels."""
494+ if filepath and filepath .is_file ():
495+ created : dt = dt .fromtimestamp (filepath .stat ().st_ctime )
496+ modified : dt = dt .fromtimestamp (filepath .stat ().st_mtime )
497+ self .date_created_label .setText (
498+ f"<b>Date Created:</b> { dt .strftime (created , "%a, %x, %X" )} "
499+ )
500+ self .date_modified_label .setText (
501+ f"<b>Date Modified:</b> { dt .strftime (modified , "%a, %x, %X" )} "
502+ )
503+ self .date_created_label .setHidden (False )
504+ self .date_modified_label .setHidden (False )
505+ elif filepath :
506+ self .date_created_label .setText ("<b>Date Created:</b> <i>N/A</i>" )
507+ self .date_modified_label .setText ("<b>Date Modified:</b> <i>N/A</i>" )
508+ self .date_created_label .setHidden (False )
509+ self .date_modified_label .setHidden (False )
510+ else :
511+ self .date_created_label .setHidden (True )
512+ self .date_modified_label .setHidden (True )
513+
473514 # def update_widgets(self, item: Union[Entry, Collation, Tag]):
474515 def update_widgets (self ):
475516 """
@@ -486,11 +527,12 @@ def update_widgets(self):
486527 # 0 Selected Items
487528 if not self .driver .selected :
488529 if self .selected or not self .initialized :
489- self .file_label .setText ("No Items Selected" )
530+ self .file_label .setText ("<i> No Items Selected</i> " )
490531 self .file_label .setFilePath ("" )
491532 self .file_label .setCursor (Qt .CursorShape .ArrowCursor )
492533
493534 self .dimensions_label .setText ("" )
535+ self .update_date_label ()
494536 self .preview_img .setContextMenuPolicy (
495537 Qt .ContextMenuPolicy .NoContextMenu
496538 )
@@ -546,7 +588,17 @@ def update_widgets(self):
546588 ratio ,
547589 update_on_ratio_change = True ,
548590 )
549- self .file_label .setText ("\u200b " .join (str (filepath )))
591+ file_str : str = ""
592+ separator : str = (
593+ f"<a style='color: #777777'><b>{ os .path .sep } </a>" # Gray
594+ )
595+ for i , part in enumerate (filepath .parts ):
596+ part_ = part .strip (os .path .sep )
597+ if i != len (filepath .parts ) - 1 :
598+ file_str += f"{ "\u200b " .join (part_ )} { separator } </b>"
599+ else :
600+ file_str += f"<br><b>{ "\u200b " .join (part_ )} </b>"
601+ self .file_label .setText (file_str )
550602 self .file_label .setCursor (Qt .CursorShape .PointingHandCursor )
551603
552604 self .preview_img .setContextMenuPolicy (
@@ -675,6 +727,7 @@ def update_widgets(self):
675727 self .dimensions_label .setText (
676728 f"{ ext .upper ()[1 :]} • { format_size (filepath .stat ().st_size )} "
677729 )
730+ self .update_date_label (filepath )
678731
679732 if not filepath .is_file ():
680733 raise FileNotFoundError
@@ -684,12 +737,14 @@ def update_widgets(self):
684737 logging .info (
685738 f"[PreviewPanel][ERROR] Couldn't Render thumbnail for { filepath } (because of { e } )"
686739 )
740+ self .update_date_label ()
687741
688742 except (FileNotFoundError , cv2 .error ) as e :
689743 self .dimensions_label .setText (f"{ ext .upper ()[1 :]} " )
690744 logging .info (
691745 f"[PreviewPanel][ERROR] Couldn't Render thumbnail for { filepath } (because of { e } )"
692746 )
747+ self .update_date_label ()
693748 except (
694749 UnidentifiedImageError ,
695750 DecompressionBombError ,
@@ -700,6 +755,7 @@ def update_widgets(self):
700755 logging .info (
701756 f"[PreviewPanel][ERROR] Couldn't Render thumbnail for { filepath } (because of { e } )"
702757 )
758+ self .update_date_label (filepath )
703759
704760 # TODO: Implement a clickable label to use for the GIF preview.
705761 if self .preview_img .is_connected :
@@ -735,8 +791,11 @@ def update_widgets(self):
735791 self .preview_gif .hide ()
736792 self .preview_vid .stop ()
737793 self .preview_vid .hide ()
794+ self .update_date_label ()
738795 if self .selected != self .driver .selected :
739- self .file_label .setText (f"{ len (self .driver .selected )} Items Selected" )
796+ self .file_label .setText (
797+ f"<b>{ len (self .driver .selected )} </b> Items Selected"
798+ )
740799 self .file_label .setCursor (Qt .CursorShape .ArrowCursor )
741800 self .file_label .setFilePath ("" )
742801 self .dimensions_label .setText ("" )
0 commit comments