Skip to content

Commit 9a78bf3

Browse files
authored
feat(ui): show file creation/modified dates + restyle path label (#430)
* feat(ui): show file dates, change path look * use `os.path.sep` * refactor: simplify file label cases
1 parent 1c53f05 commit 9a78bf3

File tree

1 file changed

+80
-21
lines changed

1 file changed

+80
-21
lines changed

tagstudio/src/qt/widgets/preview_panel.py

Lines changed: 80 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio
44

55
import logging
6+
import os
67
from pathlib import Path
78
import platform
89
import 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

Comments
 (0)