1616import time
1717import webbrowser
1818from collections .abc import Sequence
19- from itertools import zip_longest
2019from pathlib import Path
2120from queue import Queue
2221
5352 QWidget ,
5453)
5554from src .core .constants import (
56- TAG_ARCHIVED ,
57- TAG_FAVORITE ,
5855 VERSION ,
5956 VERSION_BRANCH ,
6057)
@@ -136,7 +133,7 @@ def __init__(self, backend, args):
136133 self .rm : ResourceManager = ResourceManager ()
137134 self .args = args
138135 self .filter = FilterState .show_all ()
139- self .frame_content : list [Entry ] = []
136+ self .frame_content : list [int ] = [] # List of Entry IDs on the current page
140137 self .pages_count = 0
141138
142139 self .scrollbar_pos = 0
@@ -150,9 +147,7 @@ def __init__(self, backend, args):
150147 self .thumb_job_queue : Queue = Queue ()
151148 self .thumb_threads : list [Consumer ] = []
152149 self .thumb_cutoff : float = time .time ()
153-
154- # grid indexes of selected items
155- self .selected : list [int ] = []
150+ self .selected : list [int ] = [] # Selected Entry IDs
156151
157152 self .SIGTERM .connect (self .handle_sigterm )
158153
@@ -546,11 +541,13 @@ def init_library_window(self):
546541 self .preview_panel .update_widgets ()
547542
548543 def toggle_libs_list (self , value : bool ):
549- if value :
550- self .preview_panel .libs_flow_container .show ()
551- else :
552- self .preview_panel .libs_flow_container .hide ()
553- self .preview_panel .update ()
544+ # TODO: Reimplement or remove
545+ # if value:
546+ # self.preview_panel.libs_flow_container.show()
547+ # else:
548+ # self.preview_panel.libs_flow_container.hide()
549+ # self.preview_panel.update()
550+ pass
554551
555552 def show_grid_filenames (self , value : bool ):
556553 for thumb in self .item_thumbs :
@@ -643,10 +640,12 @@ def add_tag_action_callback(self):
643640 self .modal .show ()
644641
645642 def select_all_action_callback (self ):
646- self .selected = list (range (0 , len (self .frame_content )))
647-
648- for grid_idx in self .selected :
649- self .item_thumbs [grid_idx ].thumb_button .set_selected (True )
643+ """Set the selection to all visible items."""
644+ self .selected .clear ()
645+ for item in self .item_thumbs :
646+ if item .mode and item .item_id not in self .selected :
647+ self .selected .append (item .item_id )
648+ item .thumb_button .set_selected (True )
650649
651650 self .set_macro_menu_viability ()
652651 self .preview_panel .update_widgets ()
@@ -766,14 +765,14 @@ def new_file_macros_runnable(self, new_ids):
766765 # sleep(5)
767766 # pb.deleteLater()
768767
769- def run_macros (self , name : MacroID , grid_idx : list [int ]):
768+ def run_macros (self , name : MacroID , entry_ids : list [int ]):
770769 """Run a specific Macro on a group of given entry_ids."""
771- for gid in grid_idx :
772- self .run_macro (name , gid )
770+ for entry_id in entry_ids :
771+ self .run_macro (name , entry_id )
773772
774- def run_macro (self , name : MacroID , grid_idx : int ):
773+ def run_macro (self , name : MacroID , entry_id : int ):
775774 """Run a specific Macro on an Entry given a Macro name."""
776- entry : Entry = self .frame_content [ grid_idx ]
775+ entry : Entry = self .lib . get_entry ( entry_id )
777776 full_path = self .lib .library_dir / entry .path
778777 source = "" if entry .path .parent == Path ("." ) else entry .path .parts [0 ].lower ()
779778
@@ -782,14 +781,14 @@ def run_macro(self, name: MacroID, grid_idx: int):
782781 source = source ,
783782 macro = name ,
784783 entry_id = entry .id ,
785- grid_idx = grid_idx ,
784+ grid_idx = entry_id ,
786785 )
787786
788787 if name == MacroID .AUTOFILL :
789788 for macro_id in MacroID :
790789 if macro_id == MacroID .AUTOFILL :
791790 continue
792- self .run_macro (macro_id , grid_idx )
791+ self .run_macro (macro_id , entry_id )
793792
794793 elif name == MacroID .SIDECAR :
795794 parsed_items = TagStudioCore .get_gdl_sidecar (full_path , source )
@@ -886,13 +885,12 @@ def _init_thumb_grid(self):
886885 layout .setAlignment (Qt .AlignmentFlag .AlignCenter )
887886
888887 # TODO - init after library is loaded, it can have different page_size
889- for grid_idx in range (self .filter .page_size ):
888+ for _ in range (self .filter .page_size ):
890889 item_thumb = ItemThumb (
891890 None ,
892891 self .lib ,
893892 self ,
894893 (self .thumb_size , self .thumb_size ),
895- grid_idx ,
896894 bool (
897895 self .settings .value (SettingItems .SHOW_FILENAMES , defaultValue = True , type = bool )
898896 ),
@@ -909,44 +907,55 @@ def _init_thumb_grid(self):
909907 sa .setWidgetResizable (True )
910908 sa .setWidget (self .flow_container )
911909
912- def select_item (self , grid_index : int , append : bool , bridge : bool ):
910+ def select_item (self , item_id : int , append : bool , bridge : bool ):
913911 """Select one or more items in the Thumbnail Grid."""
914- logger .info ("selecting item " , grid_index = grid_index , append = append , bridge = bridge )
912+ logger .info ("[QtDriver] Selecting Items: " , item_id = item_id , append = append , bridge = bridge )
915913 if append :
916- if grid_index not in self .selected :
917- self .selected .append (grid_index )
918- self .item_thumbs [grid_index ].thumb_button .set_selected (True )
914+ if item_id not in self .selected :
915+ self .selected .append (item_id )
916+ for it in self .item_thumbs :
917+ if it .item_id == item_id :
918+ it .thumb_button .set_selected (True )
919919 else :
920- self .selected .remove (grid_index )
921- self .item_thumbs [grid_index ].thumb_button .set_selected (False )
920+ self .selected .remove (item_id )
921+ for it in self .item_thumbs :
922+ if it .item_id == item_id :
923+ it .thumb_button .set_selected (False )
922924
923925 elif bridge and self .selected :
924- select_from = min (self .selected )
925- select_to = max (self .selected )
926-
927- if select_to < grid_index :
928- index_range = range (select_from , grid_index + 1 )
929- else :
930- index_range = range (grid_index , select_to + 1 )
931-
932- self .selected = list (index_range )
926+ contents = self .frame_content
927+ last_index = self .frame_content .index (self .selected [- 1 ])
928+ current_index = self .frame_content .index (item_id )
929+ index_range : list = contents [
930+ min (last_index , current_index ) : max (last_index , current_index ) + 1
931+ ]
932+ # Preserve bridge direction for correct appending order.
933+ if last_index < current_index :
934+ index_range .reverse ()
935+ for entry_id in index_range :
936+ for it in self .item_thumbs :
937+ if it .item_id == entry_id :
938+ it .thumb_button .set_selected (True )
939+ if entry_id not in self .selected :
940+ self .selected .append (entry_id )
933941
934- for selected_idx in self .selected :
935- self .item_thumbs [selected_idx ].thumb_button .set_selected (True )
936942 else :
937- self .selected = [grid_index ]
938- for thumb_idx , item_thumb in enumerate (self .item_thumbs ):
939- item_matched = thumb_idx == grid_index
940- item_thumb .thumb_button .set_selected (item_matched )
941-
942- # NOTE: By using the preview panel's "set_tags_updated_slot" method,
943- # only the last of multiple identical item selections are connected.
944- # If attaching the slot to multiple duplicate selections is needed,
945- # just bypass the method and manually disconnect and connect the slots.
946- if len (self .selected ) == 1 :
943+ self .selected .clear ()
944+ self .selected .append (item_id )
947945 for it in self .item_thumbs :
948- if it .item_id == id :
949- self .preview_panel .set_tags_updated_slot (it .refresh_badge )
946+ if it .item_id == item_id :
947+ it .thumb_button .set_selected (True )
948+ else :
949+ it .thumb_button .set_selected (False )
950+
951+ # # NOTE: By using the preview panel's "set_tags_updated_slot" method,
952+ # # only the last of multiple identical item selections are connected.
953+ # # If attaching the slot to multiple duplicate selections is needed,
954+ # # just bypass the method and manually disconnect and connect the slots.
955+ # if len(self.selected) == 1:
956+ # for it in self.item_thumbs:
957+ # if it.item_id == item_id:
958+ # self.preview_panel.set_tags_updated_slot(it.refresh_badge)
950959
951960 self .set_macro_menu_viability ()
952961 self .preview_panel .update_widgets ()
@@ -1043,18 +1052,26 @@ def update_thumbs(self):
10431052 self .main_window .update ()
10441053
10451054 is_grid_thumb = True
1046- # Show loading placeholder icons
1047- for entry , item_thumb in zip_longest (self .frame_content , self .item_thumbs ):
1048- if not entry :
1055+ logger .info ("[QtDriver] Loading Entries..." )
1056+ # TODO: Grab all entries at once
1057+ entries : list [Entry ] = [self .lib .get_entry_full (e_id ) for e_id in self .frame_content ]
1058+ logger .info ("[QtDriver] Building Filenames..." )
1059+ filenames : list [Path ] = [self .lib .library_dir / e .path for e in entries ]
1060+ logger .info ("[QtDriver] Done! Processing ItemThumbs..." )
1061+ for index , item_thumb in enumerate (self .item_thumbs , start = 0 ):
1062+ entry = None
1063+ try :
1064+ entry = entries [index ]
1065+ except IndexError :
10491066 item_thumb .hide ()
10501067 continue
1051-
1068+ if not entry :
1069+ continue
10521070 item_thumb .set_mode (ItemType .ENTRY )
1053- item_thumb .set_item_id (entry )
1071+ item_thumb .set_item_id (entry . id )
10541072
10551073 # TODO - show after item is rendered
10561074 item_thumb .show ()
1057-
10581075 is_loading = True
10591076 self .thumb_job_queue .put (
10601077 (
@@ -1064,29 +1081,29 @@ def update_thumbs(self):
10641081 )
10651082
10661083 # Show rendered thumbnails
1067- for idx , (entry , item_thumb ) in enumerate (
1068- zip_longest (self .frame_content , self .item_thumbs )
1069- ):
1084+ for index , item_thumb in enumerate (self .item_thumbs , start = 0 ):
1085+ entry = None
1086+ try :
1087+ entry = entries [index ]
1088+ except IndexError :
1089+ item_thumb .hide ()
1090+ continue
10701091 if not entry :
10711092 continue
10721093
1073- filepath = self .lib .library_dir / entry .path
10741094 is_loading = False
1075-
10761095 self .thumb_job_queue .put (
10771096 (
10781097 item_thumb .renderer .render ,
1079- (time .time (), filepath , base_size , ratio , is_loading , is_grid_thumb ),
1098+ (time .time (), filenames [ index ] , base_size , ratio , is_loading , is_grid_thumb ),
10801099 )
10811100 )
1082-
1083- entry_tag_ids = {tag .id for tag in entry .tags }
1084- item_thumb .assign_badge (BadgeType .ARCHIVED , TAG_ARCHIVED in entry_tag_ids )
1085- item_thumb .assign_badge (BadgeType .FAVORITE , TAG_FAVORITE in entry_tag_ids )
1101+ item_thumb .assign_badge (BadgeType .ARCHIVED , entry .is_archived )
1102+ item_thumb .assign_badge (BadgeType .FAVORITE , entry .is_favorite )
10861103 item_thumb .update_clickable (
10871104 clickable = (
1088- lambda checked = False , index = idx : self .select_item (
1089- index ,
1105+ lambda checked = False , item_id = entry . id : self .select_item (
1106+ item_id ,
10901107 append = (
10911108 QGuiApplication .keyboardModifiers ()
10921109 == Qt .KeyboardModifier .ControlModifier
@@ -1102,24 +1119,15 @@ def update_thumbs(self):
11021119 is_selected = (item_thumb .mode , item_thumb .item_id ) in self .selected
11031120 item_thumb .thumb_button .set_selected (is_selected )
11041121
1105- self .thumb_job_queue .put (
1106- (
1107- item_thumb .renderer .render ,
1108- (time .time (), filepath , base_size , ratio , False , True ),
1109- )
1110- )
1111-
1112- def update_badges (self , grid_item_ids : Sequence [int ] = None ):
1113- if not grid_item_ids :
1122+ def update_badges (self , item_ids : Sequence [int ] = None ):
1123+ if not item_ids :
11141124 # no items passed, update all items in grid
1115- grid_item_ids = range (min (len (self .item_thumbs ), len (self .frame_content )))
1116-
1117- logger .info ("updating badges for items" , grid_item_ids = grid_item_ids )
1125+ item_ids = range (min (len (self .item_thumbs ), len (self .frame_content )))
11181126
1119- for grid_idx in grid_item_ids :
1120- # get the entry from grid to avoid loading from db again
1121- entry = self . frame_content [ grid_idx ]
1122- self . item_thumbs [ grid_idx ]. refresh_badge (entry )
1127+ item_ids_ = set ( item_ids )
1128+ for it in self . item_thumbs :
1129+ if it . item_id in item_ids_ :
1130+ it . refresh_badge ()
11231131
11241132 def filter_items (self , filter : FilterState | None = None ) -> None :
11251133 if not self .lib .library_dir :
@@ -1150,7 +1158,7 @@ def filter_items(self, filter: FilterState | None = None) -> None:
11501158 )
11511159
11521160 # update page content
1153- self .frame_content = results .items
1161+ self .frame_content = [ item . id for item in results .items ]
11541162 self .update_thumbs ()
11551163
11561164 # update pagination
0 commit comments