16
16
import time
17
17
import webbrowser
18
18
from collections .abc import Sequence
19
- from itertools import zip_longest
20
19
from pathlib import Path
21
20
from queue import Queue
22
21
53
52
QWidget ,
54
53
)
55
54
from src .core .constants import (
56
- TAG_ARCHIVED ,
57
- TAG_FAVORITE ,
58
55
VERSION ,
59
56
VERSION_BRANCH ,
60
57
)
@@ -136,7 +133,7 @@ def __init__(self, backend, args):
136
133
self .rm : ResourceManager = ResourceManager ()
137
134
self .args = args
138
135
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
140
137
self .pages_count = 0
141
138
142
139
self .scrollbar_pos = 0
@@ -150,9 +147,7 @@ def __init__(self, backend, args):
150
147
self .thumb_job_queue : Queue = Queue ()
151
148
self .thumb_threads : list [Consumer ] = []
152
149
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
156
151
157
152
self .SIGTERM .connect (self .handle_sigterm )
158
153
@@ -546,11 +541,13 @@ def init_library_window(self):
546
541
self .preview_panel .update_widgets ()
547
542
548
543
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
554
551
555
552
def show_grid_filenames (self , value : bool ):
556
553
for thumb in self .item_thumbs :
@@ -643,10 +640,12 @@ def add_tag_action_callback(self):
643
640
self .modal .show ()
644
641
645
642
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 )
650
649
651
650
self .set_macro_menu_viability ()
652
651
self .preview_panel .update_widgets ()
@@ -766,14 +765,14 @@ def new_file_macros_runnable(self, new_ids):
766
765
# sleep(5)
767
766
# pb.deleteLater()
768
767
769
- def run_macros (self , name : MacroID , grid_idx : list [int ]):
768
+ def run_macros (self , name : MacroID , entry_ids : list [int ]):
770
769
"""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 )
773
772
774
- def run_macro (self , name : MacroID , grid_idx : int ):
773
+ def run_macro (self , name : MacroID , entry_id : int ):
775
774
"""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 )
777
776
full_path = self .lib .library_dir / entry .path
778
777
source = "" if entry .path .parent == Path ("." ) else entry .path .parts [0 ].lower ()
779
778
@@ -782,14 +781,14 @@ def run_macro(self, name: MacroID, grid_idx: int):
782
781
source = source ,
783
782
macro = name ,
784
783
entry_id = entry .id ,
785
- grid_idx = grid_idx ,
784
+ grid_idx = entry_id ,
786
785
)
787
786
788
787
if name == MacroID .AUTOFILL :
789
788
for macro_id in MacroID :
790
789
if macro_id == MacroID .AUTOFILL :
791
790
continue
792
- self .run_macro (macro_id , grid_idx )
791
+ self .run_macro (macro_id , entry_id )
793
792
794
793
elif name == MacroID .SIDECAR :
795
794
parsed_items = TagStudioCore .get_gdl_sidecar (full_path , source )
@@ -886,13 +885,12 @@ def _init_thumb_grid(self):
886
885
layout .setAlignment (Qt .AlignmentFlag .AlignCenter )
887
886
888
887
# 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 ):
890
889
item_thumb = ItemThumb (
891
890
None ,
892
891
self .lib ,
893
892
self ,
894
893
(self .thumb_size , self .thumb_size ),
895
- grid_idx ,
896
894
bool (
897
895
self .settings .value (SettingItems .SHOW_FILENAMES , defaultValue = True , type = bool )
898
896
),
@@ -909,44 +907,55 @@ def _init_thumb_grid(self):
909
907
sa .setWidgetResizable (True )
910
908
sa .setWidget (self .flow_container )
911
909
912
- def select_item (self , grid_index : int , append : bool , bridge : bool ):
910
+ def select_item (self , item_id : int , append : bool , bridge : bool ):
913
911
"""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 )
915
913
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 )
919
919
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 )
922
924
923
925
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 )
933
941
934
- for selected_idx in self .selected :
935
- self .item_thumbs [selected_idx ].thumb_button .set_selected (True )
936
942
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 )
947
945
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)
950
959
951
960
self .set_macro_menu_viability ()
952
961
self .preview_panel .update_widgets ()
@@ -1043,18 +1052,26 @@ def update_thumbs(self):
1043
1052
self .main_window .update ()
1044
1053
1045
1054
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 :
1049
1066
item_thumb .hide ()
1050
1067
continue
1051
-
1068
+ if not entry :
1069
+ continue
1052
1070
item_thumb .set_mode (ItemType .ENTRY )
1053
- item_thumb .set_item_id (entry )
1071
+ item_thumb .set_item_id (entry . id )
1054
1072
1055
1073
# TODO - show after item is rendered
1056
1074
item_thumb .show ()
1057
-
1058
1075
is_loading = True
1059
1076
self .thumb_job_queue .put (
1060
1077
(
@@ -1064,29 +1081,29 @@ def update_thumbs(self):
1064
1081
)
1065
1082
1066
1083
# 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
1070
1091
if not entry :
1071
1092
continue
1072
1093
1073
- filepath = self .lib .library_dir / entry .path
1074
1094
is_loading = False
1075
-
1076
1095
self .thumb_job_queue .put (
1077
1096
(
1078
1097
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 ),
1080
1099
)
1081
1100
)
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 )
1086
1103
item_thumb .update_clickable (
1087
1104
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 ,
1090
1107
append = (
1091
1108
QGuiApplication .keyboardModifiers ()
1092
1109
== Qt .KeyboardModifier .ControlModifier
@@ -1102,24 +1119,15 @@ def update_thumbs(self):
1102
1119
is_selected = (item_thumb .mode , item_thumb .item_id ) in self .selected
1103
1120
item_thumb .thumb_button .set_selected (is_selected )
1104
1121
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 :
1114
1124
# 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 )))
1118
1126
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 ()
1123
1131
1124
1132
def filter_items (self , filter : FilterState | None = None ) -> None :
1125
1133
if not self .lib .library_dir :
@@ -1150,7 +1158,7 @@ def filter_items(self, filter: FilterState | None = None) -> None:
1150
1158
)
1151
1159
1152
1160
# update page content
1153
- self .frame_content = results .items
1161
+ self .frame_content = [ item . id for item in results .items ]
1154
1162
self .update_thumbs ()
1155
1163
1156
1164
# update pagination
0 commit comments