diff --git a/docs/old_changelog.html b/docs/old_changelog.html
index c007fa33b..5afe1bbcc 100644
--- a/docs/old_changelog.html
+++ b/docs/old_changelog.html
@@ -38,7 +38,7 @@
the new asynchronous siblings and parent dialogs
- - the `tags->manage tag siblings/parents` dialogs now load quickly. rather than fetching all known pairs on every open, they now only load pertinent pairs as they are needed. if you type in tag A in the left or right side, all the pairs that involve A directly or point to a pair that involves A directly or indirectly are loaded in the background (usually so fast it seems instant). the dialog can still do 'ah, that would cause a conflict, what do you want to do?' logic, but it only fetches what it needs
+ - the `tags-$gt;manage tag siblings/parents` dialogs now load quickly. rather than fetching all known pairs on every open, they now only load pertinent pairs as they are needed. if you type in tag A in the left or right side, all the pairs that involve A directly or point to a pair that involves A directly or indirectly are loaded in the background (usually so fast it seems instant). the dialog can still do 'ah, that would cause a conflict, what do you want to do?' logic, but it only fetches what it needs
- the main edit operations in this dialog are now 'asynchronous', which means there is actually a short delay between the action firing and the UI updating. most of the time it is so fast it isn't noticeable, and in general because of other cleanup it tends to be faster about everything it does
- the dialogs now have a sticky workspace 'memory'. when you type tags in, the dialog still shows the related rows as normal, but now it does not clear those rows away once you actually enter those new pairs. the 'workspace' shows anything related to anything you have typed until you hit the new 'wipe workspace' button, which will reset back to a blank view. I hope this makes it less frustrating to work on a large group--it now stays in view the whole time, rather than the 'current' stuff jumping in and out of view vs the pending/petitioned as you type and submit stuff. the 'wipe workspace' button also has the current workspace tags in its tooltip
- the 'show all pairs' checkbox remains. it may well take twenty seconds to load up the hundreds of thousands of pairs from the PTR, but you can do it
diff --git a/hydrus/client/db/ClientDBTagParents.py b/hydrus/client/db/ClientDBTagParents.py
index f53ec563c..1bd1cad20 100644
--- a/hydrus/client/db/ClientDBTagParents.py
+++ b/hydrus/client/db/ClientDBTagParents.py
@@ -572,39 +572,47 @@ def GetTagParentsIdsChains( self, service_id, tag_ids ):
while len( next_tag_ids ) > 0:
- tag_ids_seen_this_round = set()
+ this_loop_tag_ids = set( next_tag_ids )
- ideal_tag_ids = self.modules_tag_siblings.GetIdealTagIds( ClientTags.TAG_DISPLAY_DISPLAY_IDEAL, service_id, next_tag_ids )
+ next_tag_ids = set()
- tag_ids_seen_this_round.update( self.modules_tag_siblings.GetChainsMembersFromIdeals( ClientTags.TAG_DISPLAY_DISPLAY_IDEAL, service_id, ideal_tag_ids ) )
+ ideal_tag_ids = self.modules_tag_siblings.GetIdealTagIds( ClientTags.TAG_DISPLAY_DISPLAY_IDEAL, service_id, this_loop_tag_ids )
- with self._MakeTemporaryIntegerTable( next_tag_ids, 'tag_id' ) as temp_next_tag_ids_table_name:
+ this_loop_tag_ids.update( self.modules_tag_siblings.GetChainsMembersFromIdeals( ClientTags.TAG_DISPLAY_DISPLAY_IDEAL, service_id, ideal_tag_ids ) )
+
+ # I _think_ this is always a no-op?
+ this_loop_tag_ids.difference_update( searched_tag_ids )
+
+ with self._MakeTemporaryIntegerTable( this_loop_tag_ids, 'tag_id' ) as temp_this_loop_tag_ids_table_name:
- searched_tag_ids.update( next_tag_ids )
+ searched_tag_ids.update( this_loop_tag_ids )
# keep these separate--older sqlite can't do cross join to an OR ON
+ # ALSO ditching UNION, which perhaps was not helping!
# temp tag_ids to parents
queries = [
- 'SELECT status, child_tag_id, parent_tag_id FROM {} CROSS JOIN tag_parents ON ( child_tag_id = tag_id ) WHERE service_id = ?'.format( temp_next_tag_ids_table_name ),
- 'SELECT status, child_tag_id, parent_tag_id FROM {} CROSS JOIN tag_parents ON ( parent_tag_id = tag_id ) WHERE service_id = ?'.format( temp_next_tag_ids_table_name ),
- 'SELECT status, child_tag_id, parent_tag_id FROM {} CROSS JOIN tag_parent_petitions ON ( child_tag_id = tag_id ) WHERE service_id = ?'.format( temp_next_tag_ids_table_name ),
- 'SELECT status, child_tag_id, parent_tag_id FROM {} CROSS JOIN tag_parent_petitions ON ( parent_tag_id = tag_id ) WHERE service_id = ?'.format( temp_next_tag_ids_table_name )
+ 'SELECT status, child_tag_id, parent_tag_id FROM {} CROSS JOIN tag_parents ON ( service_id = ? AND child_tag_id = tag_id );'.format( temp_this_loop_tag_ids_table_name ),
+ 'SELECT status, child_tag_id, parent_tag_id FROM {} CROSS JOIN tag_parents ON ( service_id = ? AND parent_tag_id = tag_id );'.format( temp_this_loop_tag_ids_table_name ),
+ 'SELECT status, child_tag_id, parent_tag_id FROM {} CROSS JOIN tag_parent_petitions ON ( service_id = ? AND child_tag_id = tag_id );'.format( temp_this_loop_tag_ids_table_name ),
+ 'SELECT status, child_tag_id, parent_tag_id FROM {} CROSS JOIN tag_parent_petitions ON ( service_id = ? AND parent_tag_id = tag_id );'.format( temp_this_loop_tag_ids_table_name )
]
- query = ' UNION '.join( queries )
-
- for row in self._Execute( query, ( service_id, service_id, service_id, service_id ) ):
-
- result_rows.add( row )
-
- ( status, child_tag_id, parent_tag_id ) = row
+ for query in queries:
- tag_ids_seen_this_round.update( ( child_tag_id, parent_tag_id ) )
+ for row in self._Execute( query, ( service_id, ) ):
+
+ result_rows.add( row )
+
+ ( status, child_tag_id, parent_tag_id ) = row
+
+ next_tag_ids.add( child_tag_id )
+ next_tag_ids.add( parent_tag_id )
+
- next_tag_ids = tag_ids_seen_this_round.difference( searched_tag_ids )
+ next_tag_ids.difference_update( searched_tag_ids )
unsorted_statuses_to_pair_ids = HydrusData.BuildKeyToListDict( ( status, ( child_tag_id, parent_tag_id ) ) for ( status, child_tag_id, parent_tag_id ) in result_rows )
diff --git a/hydrus/client/db/ClientDBTagSiblings.py b/hydrus/client/db/ClientDBTagSiblings.py
index bcb7db8b0..14618276b 100644
--- a/hydrus/client/db/ClientDBTagSiblings.py
+++ b/hydrus/client/db/ClientDBTagSiblings.py
@@ -799,46 +799,46 @@ def GetTagSiblingsIds( self, service_id ):
def GetTagSiblingsIdsChains( self, service_id, tag_ids ):
- done_tag_ids = set()
+ searched_tag_ids = set()
next_tag_ids = set( tag_ids )
result_rows = set()
while len( next_tag_ids ) > 0:
- with self._MakeTemporaryIntegerTable( next_tag_ids, 'tag_id' ) as temp_next_tag_ids_table_name:
-
- done_tag_ids.update( next_tag_ids )
+ loop_tag_ids = set( next_tag_ids )
+ next_tag_ids = set()
+
+ with self._MakeTemporaryIntegerTable( loop_tag_ids, 'tag_id' ) as temp_next_tag_ids_table_name:
- next_tag_ids = set()
+ searched_tag_ids.update( loop_tag_ids )
# keep these separate--older sqlite can't do cross join to an OR ON
+ # ALSO ditching UNION, which perhaps was not helping!
# temp tag_ids to siblings
queries = [
- 'SELECT status, bad_tag_id, good_tag_id FROM {} CROSS JOIN tag_siblings ON ( bad_tag_id = tag_id ) WHERE service_id = ?'.format( temp_next_tag_ids_table_name ),
- 'SELECT status, bad_tag_id, good_tag_id FROM {} CROSS JOIN tag_siblings ON ( good_tag_id = tag_id ) WHERE service_id = ?'.format( temp_next_tag_ids_table_name ),
- 'SELECT status, bad_tag_id, good_tag_id FROM {} CROSS JOIN tag_sibling_petitions ON ( bad_tag_id = tag_id ) WHERE service_id = ?'.format( temp_next_tag_ids_table_name ),
- 'SELECT status, bad_tag_id, good_tag_id FROM {} CROSS JOIN tag_sibling_petitions ON ( good_tag_id = tag_id ) WHERE service_id = ?'.format( temp_next_tag_ids_table_name )
+ 'SELECT status, bad_tag_id, good_tag_id FROM {} CROSS JOIN tag_siblings ON ( service_id = ? AND bad_tag_id = tag_id );'.format( temp_next_tag_ids_table_name ),
+ 'SELECT status, bad_tag_id, good_tag_id FROM {} CROSS JOIN tag_siblings ON ( service_id = ? AND good_tag_id = tag_id );'.format( temp_next_tag_ids_table_name ),
+ 'SELECT status, bad_tag_id, good_tag_id FROM {} CROSS JOIN tag_sibling_petitions ON ( service_id = ? AND bad_tag_id = tag_id );'.format( temp_next_tag_ids_table_name ),
+ 'SELECT status, bad_tag_id, good_tag_id FROM {} CROSS JOIN tag_sibling_petitions ON ( service_id = ? AND good_tag_id = tag_id );'.format( temp_next_tag_ids_table_name )
]
- query = ' UNION '.join( queries )
-
- for row in self._Execute( query, ( service_id, service_id, service_id, service_id ) ):
-
- result_rows.add( row )
+ for query in queries:
- ( status, bad_tag_id, good_tag_id ) = row
-
- for tag_id in ( bad_tag_id, good_tag_id ):
+ for row in self._Execute( query, ( service_id, ) ):
+
+ result_rows.add( row )
- if tag_id not in done_tag_ids:
-
- next_tag_ids.add( tag_id )
-
+ ( status, bad_tag_id, good_tag_id ) = row
+
+ next_tag_ids.add( bad_tag_id )
+ next_tag_ids.add( good_tag_id )
+ next_tag_ids.difference_update( searched_tag_ids )
+
unsorted_statuses_to_pair_ids = HydrusData.BuildKeyToListDict( ( status, ( bad_tag_id, good_tag_id ) ) for ( status, bad_tag_id, good_tag_id ) in result_rows )
diff --git a/hydrus/client/gui/metadata/ClientGUITagActions.py b/hydrus/client/gui/metadata/ClientGUITagActions.py
index 191e371e9..f36c583ea 100644
--- a/hydrus/client/gui/metadata/ClientGUITagActions.py
+++ b/hydrus/client/gui/metadata/ClientGUITagActions.py
@@ -506,6 +506,8 @@ def wait_for_preload():
self._notify_new_tags_info.wait( 0.5 )
+ self._notify_new_tags_info.clear()
+
CG.client_controller.CallAfterQtSafe( widget, 'add tag pairs (after preload)', do_it_qt_and_lock )