refactor: use entry IDs instead of objects and indices

- fixes preview panel not updating after entry edits
- fixes slow selection performance
- fixes double render call
This commit is contained in:
Travis Abendshien
2025-01-01 15:07:17 -08:00
parent a306d68f10
commit b79c59dae5
7 changed files with 188 additions and 200 deletions

View File

@@ -420,7 +420,7 @@ class Library:
return entry
def get_entry_full(self, entry_id: int) -> Entry | None:
"""Load entry an join with all joins and all tags."""
"""Load entry and join with all joins and all tags."""
with Session(self.engine) as session:
statement = select(Entry).where(Entry.id == entry_id)
statement = (
@@ -454,7 +454,9 @@ class Library:
if with_joins:
# load Entry with all joins and all tags
stmt = (
stmt.outerjoin(Entry.text_fields).outerjoin(Entry.datetime_fields)
stmt.outerjoin(Entry.text_fields)
.outerjoin(Entry.datetime_fields)
.outerjoin(Entry.tags)
# .outerjoin(Entry.tag_box_fields)
)
stmt = stmt.options(
@@ -935,6 +937,7 @@ class Library:
return None
def add_tags_to_entry(self, entry_id: int, tag_ids: int | list[int] | set[int]) -> bool:
"""Add one or more tags to an entry."""
tag_ids_ = [tag_ids] if isinstance(tag_ids, int) else tag_ids
with Session(self.engine, expire_on_commit=False) as session:
try:
@@ -943,6 +946,30 @@ class Library:
session.flush()
session.commit()
return True
except IntegrityError as e:
logger.warning("[add_tags_to_entry]", warning=e)
session.rollback()
return False
def remove_tags_from_entry(self, entry_id: int, tag_ids: int | list[int] | set[int]) -> bool:
"""Remove one or more tags from an entry."""
tag_ids_ = [tag_ids] if isinstance(tag_ids, int) else tag_ids
with Session(self.engine, expire_on_commit=False) as session:
try:
for tag_id in tag_ids_:
tag_entry = session.scalars(
select(TagEntry).where(
and_(
TagEntry.tag_id == tag_id,
TagEntry.entry_id == entry_id,
)
)
).first()
if tag_entry:
session.delete(tag_entry)
session.commit()
session.commit()
return True
except IntegrityError as e:
logger.exception(e)
session.rollback()

View File

@@ -146,7 +146,7 @@ class Entry(Base):
return fields
@property
def is_favorited(self) -> bool:
def is_favorite(self) -> bool:
return any(tag.id == TAG_FAVORITE for tag in self.tags)
@property

View File

@@ -16,7 +16,6 @@ import sys
import time
import webbrowser
from collections.abc import Sequence
from itertools import zip_longest
from pathlib import Path
from queue import Queue
@@ -53,8 +52,6 @@ from PySide6.QtWidgets import (
QWidget,
)
from src.core.constants import (
TAG_ARCHIVED,
TAG_FAVORITE,
VERSION,
VERSION_BRANCH,
)
@@ -137,7 +134,7 @@ class QtDriver(DriverMixin, QObject):
self.rm: ResourceManager = ResourceManager()
self.args = args
self.filter = FilterState.show_all()
self.frame_content: list[Entry] = []
self.frame_content: list[int] = [] # List of Entry IDs on the current page
self.pages_count = 0
self.scrollbar_pos = 0
@@ -151,9 +148,7 @@ class QtDriver(DriverMixin, QObject):
self.thumb_job_queue: Queue = Queue()
self.thumb_threads: list[Consumer] = []
self.thumb_cutoff: float = time.time()
# grid indexes of selected items
self.selected: list[int] = []
self.selected: list[int] = [] # Selected Entry IDs
self.SIGTERM.connect(self.handle_sigterm)
@@ -589,11 +584,13 @@ class QtDriver(DriverMixin, QObject):
self.preview_panel.update_widgets()
def toggle_libs_list(self, value: bool):
if value:
self.preview_panel.libs_flow_container.show()
else:
self.preview_panel.libs_flow_container.hide()
self.preview_panel.update()
# TODO: Reimplement or remove
# if value:
# self.preview_panel.libs_flow_container.show()
# else:
# self.preview_panel.libs_flow_container.hide()
# self.preview_panel.update()
pass
def show_grid_filenames(self, value: bool):
for thumb in self.item_thumbs:
@@ -695,10 +692,12 @@ class QtDriver(DriverMixin, QObject):
self.modal.show()
def select_all_action_callback(self):
self.selected = list(range(0, len(self.frame_content)))
for grid_idx in self.selected:
self.item_thumbs[grid_idx].thumb_button.set_selected(True)
"""Set the selection to all visible items."""
self.selected.clear()
for item in self.item_thumbs:
if item.mode and item.item_id not in self.selected:
self.selected.append(item.item_id)
item.thumb_button.set_selected(True)
self.set_macro_menu_viability()
self.preview_panel.update_widgets()
@@ -829,14 +828,14 @@ class QtDriver(DriverMixin, QObject):
# sleep(5)
# pb.deleteLater()
def run_macros(self, name: MacroID, grid_idx: list[int]):
def run_macros(self, name: MacroID, entry_ids: list[int]):
"""Run a specific Macro on a group of given entry_ids."""
for gid in grid_idx:
self.run_macro(name, gid)
for entry_id in entry_ids:
self.run_macro(name, entry_id)
def run_macro(self, name: MacroID, grid_idx: int):
def run_macro(self, name: MacroID, entry_id: int):
"""Run a specific Macro on an Entry given a Macro name."""
entry: Entry = self.frame_content[grid_idx]
entry: Entry = self.lib.get_entry(entry_id)
full_path = self.lib.library_dir / entry.path
source = "" if entry.path.parent == Path(".") else entry.path.parts[0].lower()
@@ -845,14 +844,14 @@ class QtDriver(DriverMixin, QObject):
source=source,
macro=name,
entry_id=entry.id,
grid_idx=grid_idx,
grid_idx=entry_id,
)
if name == MacroID.AUTOFILL:
for macro_id in MacroID:
if macro_id == MacroID.AUTOFILL:
continue
self.run_macro(macro_id, grid_idx)
self.run_macro(macro_id, entry_id)
elif name == MacroID.SIDECAR:
parsed_items = TagStudioCore.get_gdl_sidecar(full_path, source)
@@ -949,13 +948,12 @@ class QtDriver(DriverMixin, QObject):
layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
# TODO - init after library is loaded, it can have different page_size
for grid_idx in range(self.filter.page_size):
for _ in range(self.filter.page_size):
item_thumb = ItemThumb(
None,
self.lib,
self,
(self.thumb_size, self.thumb_size),
grid_idx,
bool(
self.settings.value(SettingItems.SHOW_FILENAMES, defaultValue=True, type=bool)
),
@@ -972,44 +970,55 @@ class QtDriver(DriverMixin, QObject):
sa.setWidgetResizable(True)
sa.setWidget(self.flow_container)
def select_item(self, grid_index: int, append: bool, bridge: bool):
def select_item(self, item_id: int, append: bool, bridge: bool):
"""Select one or more items in the Thumbnail Grid."""
logger.info("selecting item", grid_index=grid_index, append=append, bridge=bridge)
logger.info("[QtDriver] Selecting Items:", item_id=item_id, append=append, bridge=bridge)
if append:
if grid_index not in self.selected:
self.selected.append(grid_index)
self.item_thumbs[grid_index].thumb_button.set_selected(True)
if item_id not in self.selected:
self.selected.append(item_id)
for it in self.item_thumbs:
if it.item_id == item_id:
it.thumb_button.set_selected(True)
else:
self.selected.remove(grid_index)
self.item_thumbs[grid_index].thumb_button.set_selected(False)
self.selected.remove(item_id)
for it in self.item_thumbs:
if it.item_id == item_id:
it.thumb_button.set_selected(False)
elif bridge and self.selected:
select_from = min(self.selected)
select_to = max(self.selected)
contents = self.frame_content
last_index = self.frame_content.index(self.selected[-1])
current_index = self.frame_content.index(item_id)
index_range: list = contents[
min(last_index, current_index) : max(last_index, current_index) + 1
]
# Preserve bridge direction for correct appending order.
if last_index < current_index:
index_range.reverse()
for entry_id in index_range:
for it in self.item_thumbs:
if it.item_id == entry_id:
it.thumb_button.set_selected(True)
if entry_id not in self.selected:
self.selected.append(entry_id)
if select_to < grid_index:
index_range = range(select_from, grid_index + 1)
else:
index_range = range(grid_index, select_to + 1)
self.selected = list(index_range)
for selected_idx in self.selected:
self.item_thumbs[selected_idx].thumb_button.set_selected(True)
else:
self.selected = [grid_index]
for thumb_idx, item_thumb in enumerate(self.item_thumbs):
item_matched = thumb_idx == grid_index
item_thumb.thumb_button.set_selected(item_matched)
# NOTE: By using the preview panel's "set_tags_updated_slot" method,
# only the last of multiple identical item selections are connected.
# If attaching the slot to multiple duplicate selections is needed,
# just bypass the method and manually disconnect and connect the slots.
if len(self.selected) == 1:
self.selected.clear()
self.selected.append(item_id)
for it in self.item_thumbs:
if it.item_id == id:
self.preview_panel.set_tags_updated_slot(it.refresh_badge)
if it.item_id == item_id:
it.thumb_button.set_selected(True)
else:
it.thumb_button.set_selected(False)
# # NOTE: By using the preview panel's "set_tags_updated_slot" method,
# # only the last of multiple identical item selections are connected.
# # If attaching the slot to multiple duplicate selections is needed,
# # just bypass the method and manually disconnect and connect the slots.
# if len(self.selected) == 1:
# for it in self.item_thumbs:
# if it.item_id == item_id:
# self.preview_panel.set_tags_updated_slot(it.refresh_badge)
self.set_macro_menu_viability()
self.preview_panel.update_widgets()
@@ -1106,18 +1115,26 @@ class QtDriver(DriverMixin, QObject):
self.main_window.update()
is_grid_thumb = True
# Show loading placeholder icons
for entry, item_thumb in zip_longest(self.frame_content, self.item_thumbs):
if not entry:
logger.info("[QtDriver] Loading Entries...")
# TODO: Grab all entries at once
entries: list[Entry] = [self.lib.get_entry_full(e_id) for e_id in self.frame_content]
logger.info("[QtDriver] Building Filenames...")
filenames: list[Path] = [self.lib.library_dir / e.path for e in entries]
logger.info("[QtDriver] Done! Processing ItemThumbs...")
for index, item_thumb in enumerate(self.item_thumbs, start=0):
entry = None
try:
entry = entries[index]
except IndexError:
item_thumb.hide()
continue
if not entry:
continue
item_thumb.set_mode(ItemType.ENTRY)
item_thumb.set_item_id(entry)
item_thumb.set_item_id(entry.id)
# TODO - show after item is rendered
item_thumb.show()
is_loading = True
self.thumb_job_queue.put(
(
@@ -1127,29 +1144,29 @@ class QtDriver(DriverMixin, QObject):
)
# Show rendered thumbnails
for idx, (entry, item_thumb) in enumerate(
zip_longest(self.frame_content, self.item_thumbs)
):
for index, item_thumb in enumerate(self.item_thumbs, start=0):
entry = None
try:
entry = entries[index]
except IndexError:
item_thumb.hide()
continue
if not entry:
continue
filepath = self.lib.library_dir / entry.path
is_loading = False
self.thumb_job_queue.put(
(
item_thumb.renderer.render,
(time.time(), filepath, base_size, ratio, is_loading, is_grid_thumb),
(time.time(), filenames[index], base_size, ratio, is_loading, is_grid_thumb),
)
)
entry_tag_ids = {tag.id for tag in entry.tags}
item_thumb.assign_badge(BadgeType.ARCHIVED, TAG_ARCHIVED in entry_tag_ids)
item_thumb.assign_badge(BadgeType.FAVORITE, TAG_FAVORITE in entry_tag_ids)
item_thumb.assign_badge(BadgeType.ARCHIVED, entry.is_archived)
item_thumb.assign_badge(BadgeType.FAVORITE, entry.is_favorite)
item_thumb.update_clickable(
clickable=(
lambda checked=False, index=idx: self.select_item(
index,
lambda checked=False, item_id=entry.id: self.select_item(
item_id,
append=(
QGuiApplication.keyboardModifiers()
== Qt.KeyboardModifier.ControlModifier
@@ -1165,24 +1182,15 @@ class QtDriver(DriverMixin, QObject):
is_selected = (item_thumb.mode, item_thumb.item_id) in self.selected
item_thumb.thumb_button.set_selected(is_selected)
self.thumb_job_queue.put(
(
item_thumb.renderer.render,
(time.time(), filepath, base_size, ratio, False, True),
)
)
def update_badges(self, grid_item_ids: Sequence[int] = None):
if not grid_item_ids:
def update_badges(self, item_ids: Sequence[int] = None):
if not item_ids:
# no items passed, update all items in grid
grid_item_ids = range(min(len(self.item_thumbs), len(self.frame_content)))
item_ids = range(min(len(self.item_thumbs), len(self.frame_content)))
logger.info("updating badges for items", grid_item_ids=grid_item_ids)
for grid_idx in grid_item_ids:
# get the entry from grid to avoid loading from db again
entry = self.frame_content[grid_idx]
self.item_thumbs[grid_idx].refresh_badge(entry)
item_ids_ = set(item_ids)
for it in self.item_thumbs:
if it.item_id in item_ids_:
it.refresh_badge()
def filter_items(self, filter: FilterState | None = None) -> None:
if not self.lib.library_dir:
@@ -1217,7 +1225,7 @@ class QtDriver(DriverMixin, QObject):
)
# update page content
self.frame_content = results.items
self.frame_content = [item.id for item in results.items]
self.update_thumbs()
# update pagination

View File

@@ -24,7 +24,7 @@ from src.core.constants import (
TAG_ARCHIVED,
TAG_FAVORITE,
)
from src.core.library import Entry, ItemType, Library
from src.core.library import ItemType, Library
from src.core.media_types import MediaCategories, MediaType
from src.qt.flowlayout import FlowWidget
from src.qt.helpers.file_opener import FileOpenerHelper
@@ -118,11 +118,9 @@ class ItemThumb(FlowWidget):
library: Library,
driver: "QtDriver",
thumb_size: tuple[int, int],
grid_idx: int,
show_filename_label: bool = False,
):
super().__init__()
self.grid_idx = grid_idx
self.lib = library
self.mode: ItemType = mode
self.driver = driver
@@ -205,10 +203,10 @@ class ItemThumb(FlowWidget):
self.thumb_button = ThumbButton(self.thumb_container, thumb_size)
self.renderer = ThumbRenderer()
self.renderer.updated.connect(
lambda ts, i, s, fn, ext: (
self.update_thumb(ts, image=i),
self.update_size(ts, size=s),
self.set_filename_text(fn),
lambda timestamp, image, size, filename, ext: (
self.update_thumb(timestamp, image=image),
self.update_size(timestamp, size=size),
self.set_filename_text(filename),
self.set_extension(ext),
)
)
@@ -399,6 +397,7 @@ class ItemThumb(FlowWidget):
self.count_badge.setHidden(True)
def set_filename_text(self, filename: Path | str | None):
self.set_item_path(filename)
self.file_label.setText(str(filename))
def set_filename_visibility(self, set_visible: bool):
@@ -444,24 +443,19 @@ class ItemThumb(FlowWidget):
self.thumb_button.pressed.connect(clickable)
self.thumb_button.is_connected = True
def refresh_badge(self, entry: Entry | None = None):
def refresh_badge(self, entry_id: int | None = None):
entry = self.lib.get_entry_full(self.item_id)
if not entry:
if not self.item_id:
logger.error("missing both entry and item_id")
return None
entry = self.lib.get_entry(self.item_id)
if not entry:
logger.error("Entry not found", item_id=self.item_id)
return
return
self.assign_badge(BadgeType.ARCHIVED, entry.is_archived)
self.assign_badge(BadgeType.FAVORITE, entry.is_favorited)
self.assign_badge(BadgeType.FAVORITE, entry.is_favorite)
def set_item_id(self, entry: Entry):
filepath = self.lib.library_dir / entry.path
self.opener.set_filepath(filepath)
self.item_id = entry.id
def set_item_id(self, item_id: int):
self.item_id = item_id
def set_item_path(self, path: Path | str | None):
"""Set the absolute filepath for the item. Used for locating on disk."""
self.opener.set_filepath(path)
def assign_badge(self, badge_type: BadgeType, value: bool) -> None:
mode = self.mode
@@ -500,18 +494,15 @@ class ItemThumb(FlowWidget):
tag_id = BADGE_TAGS[badge_type]
# check if current item is selected. if so, update all selected items
if self.grid_idx in self.driver.selected:
update_items = self.driver.selected
if self.item_id in self.driver.selected:
items_to_update = self.driver.selected
else:
update_items = [self.grid_idx]
items_to_update = [self.item_id]
for idx in update_items:
entry = self.driver.frame_content[idx]
self.toggle_item_tag(entry.id, toggle_value, tag_id)
# update the entry
self.driver.frame_content[idx] = self.lib.get_entry_full(entry.id)
for item_id in items_to_update:
self.toggle_item_tag(item_id, toggle_value, tag_id)
self.driver.update_badges(update_items)
self.driver.update_badges(items_to_update)
def toggle_item_tag(
self,
@@ -524,8 +515,7 @@ class ItemThumb(FlowWidget):
if toggle_value:
self.lib.add_tags_to_entry(entry_id, tag_id)
else:
# TODO: Implement
self.lib.remove_tag_from_entry(entry_id, tag_id)
self.lib.remove_tags_from_entry(entry_id, tag_id)
if self.driver.preview_panel.is_open:
self.driver.preview_panel.update_widgets()
@@ -538,13 +528,13 @@ class ItemThumb(FlowWidget):
paths = []
mimedata = QMimeData()
selected_idxs = self.driver.selected
if self.grid_idx not in selected_idxs:
selected_idxs = [self.grid_idx]
selected_ids = self.driver.selected
if self.item_id not in selected_ids:
selected_ids = [self.item_id]
for grid_idx in selected_idxs:
id = self.driver.item_thumbs[grid_idx].item_id
entry = self.lib.get_entry(id)
for selected_id in selected_ids:
item_id = self.driver.item_thumbs[selected_id].item_id
entry = self.lib.get_entry(item_id)
if not entry:
continue
@@ -554,4 +544,4 @@ class ItemThumb(FlowWidget):
mimedata.setUrls(paths)
drag.setMimeData(mimedata)
drag.exec(Qt.DropAction.CopyAction)
logger.info("dragged files to external program", thumbnail_indexs=selected_idxs)
logger.info("dragged files to external program", thumbnail_indexs=selected_ids)

View File

@@ -119,7 +119,7 @@ class FieldContainers(QWidget):
def update_from_entry(self, entry: Entry):
"""Update tags and fields from a single Entry source."""
self.selected = [entry]
self.selected = [self.lib.get_entry_full(entry.id)]
logger.info(
"[Field Containers] Updating Selection",
entry=entry,
@@ -127,33 +127,17 @@ class FieldContainers(QWidget):
tags=entry.tags,
)
# # reload entry and fill it into the grid again
# # TODO - do this more granular
# # TODO - Entry reload is maybe not necessary
# for grid_idx in self.driver.selected:
# entry = self.driver.frame_content[grid_idx]
# results = self.lib.search_library(FilterState(id=entry.id))
# logger.info(
# "found item",
# entries=len(results.items),
# grid_idx=grid_idx,
# lookup_id=entry.id,
# )
# self.driver.frame_content[grid_idx] = results[0]
# for index in self.driver.selected:
# self.driver.frame_content[index] = self.lib.get_entry(self.selected[0].id)
for idx, field in enumerate(entry.fields):
entry_ = self.selected[0]
for idx, field in enumerate(entry_.fields):
self.write_container(idx, field, is_mixed=False)
if entry.tags:
if entry_.tags:
# TODO: Display the tag categories
pass
# Hide leftover containers
if len(self.containers) > len(entry.fields):
if len(self.containers) > len(entry_.fields):
for i, c in enumerate(self.containers):
if i > (len(entry.fields) - 1):
if i > (len(entry_.fields) - 1):
c.setHidden(True)
self.add_field_button.setHidden(False)
@@ -170,17 +154,16 @@ class FieldContainers(QWidget):
if self.add_field_button.is_connected:
self.add_field_button.clicked.disconnect()
# self.add_field_modal.done.connect(
# lambda f: (self.add_field_to_selected(f), self.update_widgets())
# )
self.add_field_modal.done.connect(
lambda f: (self.add_field_to_selected(f), self.update_from_entry(self.selected[0]))
)
self.add_field_modal.is_connected = True
self.add_field_button.clicked.connect(self.add_field_modal.show)
def add_field_to_selected(self, field_list: list):
"""Add list of entry fields to one or more selected items."""
logger.info("add_field_to_selected", selected=self.selected, fields=field_list)
for grid_idx in self.selected:
entry = self.driver.frame_content[grid_idx]
for entry in self.selected:
for field_item in field_list:
self.lib.add_entry_field_type(
entry.id,
@@ -393,12 +376,7 @@ class FieldContainers(QWidget):
def remove_field(self, field: BaseField):
"""Remove a field from all selected Entries."""
logger.info("removing field", field=field, selected=self.selected)
entry_ids = []
for grid_idx in self.selected:
entry = self.driver.frame_content[grid_idx]
entry_ids.append(entry.id)
entry_ids = [e.id for e in self.selected]
self.lib.remove_entry_field(field, entry_ids)
# # if the field is meta tags, update the badges
@@ -412,12 +390,7 @@ class FieldContainers(QWidget):
(TextField, DatetimeField), # , TagBoxField)
), f"instance: {type(field)}"
entry_ids = []
# for grid_idx in self.selected:
# entry = self.driver.frame_content[grid_idx]
# entry_ids.append(entry.id)
for entry in self.selected:
entry_ids.append(entry.id)
entry_ids = [e.id for e in self.selected]
assert entry_ids, "No entries selected"
self.lib.update_entry_field(

View File

@@ -200,7 +200,6 @@ class FileAttributes(QWidget):
# Format and display any stat variables
def add_newline(stats_label_text: str) -> str:
logger.info(stats_label_text[-2:])
if stats_label_text and stats_label_text[-2:] != "\n":
return stats_label_text + "\n"
return stats_label_text

View File

@@ -8,7 +8,7 @@ from pathlib import Path
import structlog
from PySide6.QtCore import Qt, Signal
from PySide6.QtWidgets import QHBoxLayout, QSplitter, QWidget
from PySide6.QtWidgets import QHBoxLayout, QSplitter, QVBoxLayout, QWidget
from src.core.library.alchemy.library import Library
from src.core.library.alchemy.models import Entry
from src.qt.widgets.preview.field_containers import FieldContainers
@@ -40,13 +40,15 @@ class PreviewPanel(QWidget):
self.file_attrs = FileAttributes(library, driver)
self.fields = FieldContainers(library, driver)
# info_section = QWidget()
# info_layout = QVBoxLayout(info_section)
# info_layout.setContentsMargins(0, 0, 0, 0)
# info_layout.setSpacing(6)
preview_section = QWidget()
preview_layout = QVBoxLayout(preview_section)
preview_layout.setContentsMargins(0, 0, 0, 0)
preview_layout.setSpacing(6)
# info_layout.addWidget(self.file_attrs)
# info_layout.addWidget(self.fields.scroll_area)
info_section = QWidget()
info_layout = QVBoxLayout(info_section)
info_layout.setContentsMargins(0, 0, 0, 0)
info_layout.setSpacing(6)
splitter = QSplitter()
splitter.setOrientation(Qt.Orientation.Vertical)
@@ -59,35 +61,24 @@ class PreviewPanel(QWidget):
# )
# )
# )
preview_layout.addWidget(self.thumb)
preview_layout.addWidget(self.thumb.media_player)
info_layout.addWidget(self.file_attrs)
info_layout.addWidget(self.fields)
# splitter.addWidget(self.thumb.image_container)
# splitter.addWidget(self.thumb.media_player)
splitter.addWidget(self.thumb)
splitter.addWidget(self.thumb.media_player)
splitter.addWidget(self.file_attrs)
splitter.addWidget(self.fields)
splitter.addWidget(preview_section)
splitter.addWidget(info_section)
# splitter.addWidget(self.libs_flow_container)
splitter.setStretchFactor(3, 2)
splitter.setStretchFactor(1, 2)
root_layout = QHBoxLayout(self)
root_layout.setContentsMargins(0, 0, 0, 0)
root_layout.addWidget(splitter)
def update_selected_entry(self, driver: "QtDriver"):
for grid_idx in driver.selected:
entry = driver.frame_content[grid_idx]
result = self.lib.get_entry_full(entry.id)
logger.info(
"found item",
grid_idx=grid_idx,
lookup_id=entry.id,
)
self.driver.frame_content[grid_idx] = result
def update_widgets(self) -> bool:
"""Render the panel widgets with the newest data from the Library."""
# No Items Selected
items: list[Entry] = [self.driver.frame_content[x] for x in self.driver.selected]
# items: list[Entry] = [self.driver.frame_content[x] for x in self.driver.selected]
if len(self.driver.selected) == 0:
# TODO: Clear everything to default
# self.file_attrs.update_blank()
@@ -96,7 +87,7 @@ class PreviewPanel(QWidget):
# One Item Selected
elif len(self.driver.selected) == 1:
entry: Entry = items[0]
entry: Entry = self.lib.get_entry_full(self.driver.selected[0])
filepath: Path = self.lib.library_dir / entry.path
ext: str = filepath.suffix.lower()