Version 225
This commit is contained in:
parent
f35edea0fc
commit
32bc5957cd
|
@ -8,6 +8,20 @@
|
|||
<div class="content">
|
||||
<h3>changelog</h3>
|
||||
<ul>
|
||||
<li><h3>version 225</h3></li>
|
||||
<ul>
|
||||
<li>system:numtags is now much faster when applied to 'local files' or a file repository</li>
|
||||
<li>system:numtags now correctly counts same-tag-different-namespace tags as distinct (for instance, [page:1, chapter:1] was previously being counted as only one)</li>
|
||||
<li>refactored fast db integer iterable access code into a context manager</li>
|
||||
<li>media result building is faster</li>
|
||||
<li>added namespace-grouped incidental tag sorting</li>
|
||||
<li>fixed the OpenCV image loader for monochrome images</li>
|
||||
<li>fixed a thread interaction issue when drawing popup messages</li>
|
||||
<li>popup messages should no longer flicker while static</li>
|
||||
<li>popup debug test is richer</li>
|
||||
<li>fixed editing of some taglists such as in explicit tags and import tag editing</li>
|
||||
<li>SSL EOF errors are now caught by the networking engine</li>
|
||||
</ul>
|
||||
<li><h3>version 224</h3></li>
|
||||
<ul>
|
||||
<li>rewrote the static image rendering and caching pipeline -- images are now resized on the fly, and only the master image is cached</li>
|
||||
|
|
|
@ -245,6 +245,8 @@ SORT_BY_INCIDENCE_ASC = 10
|
|||
SORT_BY_INCIDENCE_DESC = 11
|
||||
SORT_BY_LEXICOGRAPHIC_NAMESPACE_ASC = 12
|
||||
SORT_BY_LEXICOGRAPHIC_NAMESPACE_DESC = 13
|
||||
SORT_BY_INCIDENCE_NAMESPACE_ASC = 14
|
||||
SORT_BY_INCIDENCE_NAMESPACE_DESC = 15
|
||||
|
||||
SORT_CHOICES = []
|
||||
|
||||
|
|
|
@ -130,17 +130,22 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
if job_key.HasVariable( 'result' ):
|
||||
|
||||
return job_key.GetVariable( 'result' )
|
||||
# result can be None, for wx_code that has no return variable
|
||||
|
||||
elif job_key.HasVariable( 'error' ):
|
||||
result = job_key.GetIfHasVariable( 'result' )
|
||||
|
||||
raise job_key.GetVariable( 'error' )
|
||||
return result
|
||||
|
||||
else:
|
||||
|
||||
error = job_key.GetIfHasVariable( 'error' )
|
||||
|
||||
if error is not None:
|
||||
|
||||
raise HydrusExceptions.ShutdownException()
|
||||
raise error
|
||||
|
||||
|
||||
raise HydrusExceptions.ShutdownException()
|
||||
|
||||
|
||||
def CheckAlreadyRunning( self ):
|
||||
|
||||
|
|
|
@ -3443,7 +3443,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
if num_tags_zero or num_tags_nonzero or tag_predicates_care_about_zero_counts:
|
||||
|
||||
nonzero_tag_query_hash_ids = self._GetHashIdsThatHaveTags( tag_service_key, include_current_tags, include_pending_tags )
|
||||
nonzero_tag_query_hash_ids = self._GetHashIdsThatHaveTags( tag_service_key, include_current_tags, include_pending_tags, query_hash_ids )
|
||||
|
||||
if num_tags_zero:
|
||||
|
||||
|
@ -3457,7 +3457,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
if len( tag_predicates ) > 0:
|
||||
|
||||
hash_id_tag_counts = self._GetHashIdsTagCounts( tag_service_key, include_current_tags, include_pending_tags )
|
||||
hash_id_tag_counts = self._GetHashIdsTagCounts( tag_service_key, include_current_tags, include_pending_tags, query_hash_ids )
|
||||
|
||||
good_tag_count_hash_ids = { id for ( id, count ) in hash_id_tag_counts if False not in ( pred( count ) for pred in tag_predicates ) }
|
||||
|
||||
|
@ -3689,7 +3689,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
return hash_ids
|
||||
|
||||
|
||||
def _GetHashIdsTagCounts( self, tag_service_key, include_current, include_pending ):
|
||||
def _GetHashIdsTagCounts( self, tag_service_key, include_current, include_pending, hash_ids = None ):
|
||||
|
||||
if tag_service_key == CC.COMBINED_TAG_SERVICE_KEY:
|
||||
|
||||
|
@ -3702,23 +3702,52 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
tags_counter = collections.Counter()
|
||||
|
||||
for search_tag_service_id in search_tag_service_ids:
|
||||
if hash_ids is None:
|
||||
|
||||
( current_mappings_table_name, deleted_mappings_table_name, pending_mappings_table_name, petitioned_mappings_table_name ) = GenerateMappingsTableNames( search_tag_service_id )
|
||||
|
||||
if include_current:
|
||||
for search_tag_service_id in search_tag_service_ids:
|
||||
|
||||
for ( id, count ) in self._c.execute( 'SELECT hash_id, COUNT( DISTINCT tag_id ) FROM ' + current_mappings_table_name + ' GROUP BY hash_id;' ):
|
||||
( current_mappings_table_name, deleted_mappings_table_name, pending_mappings_table_name, petitioned_mappings_table_name ) = GenerateMappingsTableNames( search_tag_service_id )
|
||||
|
||||
if include_current:
|
||||
|
||||
tags_counter[ id ] += count
|
||||
for ( id, count ) in self._c.execute( 'SELECT hash_id, COUNT( DISTINCT tag_id ) FROM ' + current_mappings_table_name + ' GROUP BY hash_id, namespace_id;' ):
|
||||
|
||||
tags_counter[ id ] += count
|
||||
|
||||
|
||||
|
||||
if include_pending:
|
||||
|
||||
for ( id, count ) in self._c.execute( 'SELECT hash_id, COUNT( DISTINCT tag_id ) FROM ' + pending_mappings_table_name + ' GROUP BY hash_id, namespace_id;' ):
|
||||
|
||||
tags_counter[ id ] += count
|
||||
|
||||
|
||||
|
||||
|
||||
if include_pending:
|
||||
else:
|
||||
|
||||
with HydrusDB.TemporaryIntegerTable( self._c, hash_ids, 'hash_id' ) as temp_table_name:
|
||||
|
||||
for ( id, count ) in self._c.execute( 'SELECT hash_id, COUNT( DISTINCT tag_id ) FROM ' + pending_mappings_table_name + ' GROUP BY hash_id;' ):
|
||||
for search_tag_service_id in search_tag_service_ids:
|
||||
|
||||
tags_counter[ id ] += count
|
||||
( current_mappings_table_name, deleted_mappings_table_name, pending_mappings_table_name, petitioned_mappings_table_name ) = GenerateMappingsTableNames( search_tag_service_id )
|
||||
|
||||
if include_current:
|
||||
|
||||
for ( id, count ) in self._c.execute( 'SELECT hash_id, COUNT( DISTINCT tag_id ) FROM ' + temp_table_name + ',' + current_mappings_table_name + ' USING ( hash_id ) GROUP BY hash_id, namespace_id;' ):
|
||||
|
||||
tags_counter[ id ] += count
|
||||
|
||||
|
||||
|
||||
if include_pending:
|
||||
|
||||
for ( id, count ) in self._c.execute( 'SELECT hash_id, COUNT( DISTINCT tag_id ) FROM ' + temp_table_name + ',' + pending_mappings_table_name + ' USING ( hash_id ) GROUP BY hash_id, namespace_id;' ):
|
||||
|
||||
tags_counter[ id ] += count
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -3726,7 +3755,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
return tags_counter.items()
|
||||
|
||||
|
||||
def _GetHashIdsThatHaveTags( self, tag_service_key, include_current, include_pending ):
|
||||
def _GetHashIdsThatHaveTags( self, tag_service_key, include_current, include_pending, hash_ids = None ):
|
||||
|
||||
if tag_service_key == CC.COMBINED_TAG_SERVICE_KEY:
|
||||
|
||||
|
@ -3739,21 +3768,58 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
nonzero_tag_hash_ids = set()
|
||||
|
||||
for search_tag_service_id in search_tag_service_ids:
|
||||
if hash_ids is None:
|
||||
|
||||
( current_mappings_table_name, deleted_mappings_table_name, pending_mappings_table_name, petitioned_mappings_table_name ) = GenerateMappingsTableNames( search_tag_service_id )
|
||||
for search_tag_service_id in search_tag_service_ids:
|
||||
|
||||
( current_mappings_table_name, deleted_mappings_table_name, pending_mappings_table_name, petitioned_mappings_table_name ) = GenerateMappingsTableNames( search_tag_service_id )
|
||||
'''
|
||||
if include_current and include_pending:
|
||||
|
||||
nonzero_tag_hash_ids.update( ( id for ( id, ) in self._c.execute( 'SELECT hash_id as h FROM hashes WHERE EXISTS ( SELECT 1 FROM ' + current_mappings_table_name + ' WHERE hash_id = h ) OR EXISTS ( SELECT 1 FROM ' + pending_mappings_table_name + ' WHERE hash_id = h );' ) ) )
|
||||
|
||||
elif include_current:
|
||||
|
||||
nonzero_tag_hash_ids.update( ( id for ( id, ) in self._c.execute( 'SELECT hash_id as h FROM hashes WHERE EXISTS ( SELECT 1 FROM ' + current_mappings_table_name + ' WHERE hash_id = h );' ) ) )
|
||||
|
||||
elif include_pending:
|
||||
|
||||
nonzero_tag_hash_ids.update( ( id for ( id, ) in self._c.execute( 'SELECT hash_id as h FROM hashes WHERE EXISTS ( SELECT 1 FROM ' + pending_mappings_table_name + ' WHERE hash_id = h );' ) ) )
|
||||
|
||||
'''
|
||||
|
||||
if include_current:
|
||||
|
||||
nonzero_tag_hash_ids.update( ( id for ( id, ) in self._c.execute( 'SELECT DISTINCT hash_id FROM ' + current_mappings_table_name + ';' ) ) )
|
||||
|
||||
|
||||
if include_pending:
|
||||
|
||||
nonzero_tag_hash_ids.update( ( id for ( id, ) in self._c.execute( 'SELECT DISTINCT hash_id FROM ' + pending_mappings_table_name + ';' ) ) )
|
||||
|
||||
|
||||
|
||||
if include_current and include_pending:
|
||||
else:
|
||||
|
||||
with HydrusDB.TemporaryIntegerTable( self._c, hash_ids, 'hash_id' ) as temp_table_name:
|
||||
|
||||
nonzero_tag_hash_ids.update( ( id for ( id, ) in self._c.execute( 'SELECT hash_id as h FROM hashes WHERE EXISTS ( SELECT 1 FROM ' + current_mappings_table_name + ' WHERE hash_id = h ) OR EXISTS ( SELECT 1 FROM ' + pending_mappings_table_name + ' WHERE hash_id = h );' ) ) )
|
||||
|
||||
elif include_current:
|
||||
|
||||
nonzero_tag_hash_ids.update( ( id for ( id, ) in self._c.execute( 'SELECT hash_id as h FROM hashes WHERE EXISTS ( SELECT 1 FROM ' + current_mappings_table_name + ' WHERE hash_id = h );' ) ) )
|
||||
|
||||
elif include_pending:
|
||||
|
||||
nonzero_tag_hash_ids.update( ( id for ( id, ) in self._c.execute( 'SELECT hash_id as h FROM hashes WHERE EXISTS ( SELECT 1 FROM ' + pending_mappings_table_name + ' WHERE hash_id = h );' ) ) )
|
||||
for search_tag_service_id in search_tag_service_ids:
|
||||
|
||||
( current_mappings_table_name, deleted_mappings_table_name, pending_mappings_table_name, petitioned_mappings_table_name ) = GenerateMappingsTableNames( search_tag_service_id )
|
||||
|
||||
if include_current and include_pending:
|
||||
|
||||
nonzero_tag_hash_ids.update( ( id for ( id, ) in self._c.execute( 'SELECT hash_id as h FROM ' + temp_table_name + ' WHERE EXISTS ( SELECT 1 FROM ' + current_mappings_table_name + ' WHERE hash_id = h ) OR EXISTS ( SELECT 1 FROM ' + pending_mappings_table_name + ' WHERE hash_id = h );' ) ) )
|
||||
|
||||
elif include_current:
|
||||
|
||||
nonzero_tag_hash_ids.update( ( id for ( id, ) in self._c.execute( 'SELECT hash_id as h FROM ' + temp_table_name + ' WHERE EXISTS ( SELECT 1 FROM ' + current_mappings_table_name + ' WHERE hash_id = h );' ) ) )
|
||||
|
||||
elif include_pending:
|
||||
|
||||
nonzero_tag_hash_ids.update( ( id for ( id, ) in self._c.execute( 'SELECT hash_id as h FROM ' + temp_table_name + ' WHERE EXISTS ( SELECT 1 FROM ' + pending_mappings_table_name + ' WHERE hash_id = h );' ) ) )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -3906,27 +3972,28 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
def _GetMediaResults( self, hash_ids ):
|
||||
|
||||
splayed_hash_ids = HydrusData.SplayListForDB( hash_ids )
|
||||
|
||||
# get first detailed results
|
||||
|
||||
hash_ids_to_info = { hash_id : ( size, mime, width, height, duration, num_frames, num_words ) for ( hash_id, size, mime, width, height, duration, num_frames, num_words ) in self._c.execute( 'SELECT * FROM files_info WHERE hash_id IN ' + splayed_hash_ids + ';' ) }
|
||||
|
||||
hash_ids_to_hashes = self._GetHashIdsToHashes( hash_ids )
|
||||
|
||||
hash_ids_to_current_file_service_ids_and_timestamps = HydrusData.BuildKeyToListDict( ( ( hash_id, ( service_id, timestamp ) ) for ( hash_id, service_id, timestamp ) in self._c.execute( 'SELECT hash_id, service_id, timestamp FROM current_files WHERE hash_id IN ' + splayed_hash_ids + ';' ) ) )
|
||||
|
||||
hash_ids_to_deleted_file_service_ids = HydrusData.BuildKeyToListDict( self._c.execute( 'SELECT hash_id, service_id FROM deleted_files WHERE hash_id IN ' + splayed_hash_ids + ';' ) )
|
||||
|
||||
hash_ids_to_pending_file_service_ids = HydrusData.BuildKeyToListDict( self._c.execute( 'SELECT hash_id, service_id FROM file_transfers WHERE hash_id IN ' + splayed_hash_ids + ';' ) )
|
||||
|
||||
hash_ids_to_petitioned_file_service_ids = HydrusData.BuildKeyToListDict( self._c.execute( 'SELECT hash_id, service_id FROM file_petitions WHERE hash_id IN ' + splayed_hash_ids + ';' ) )
|
||||
|
||||
hash_ids_to_urls = HydrusData.BuildKeyToListDict( self._c.execute( 'SELECT hash_id, url FROM urls WHERE hash_id IN ' + splayed_hash_ids + ';' ) )
|
||||
|
||||
hash_ids_to_service_ids_and_filenames = HydrusData.BuildKeyToListDict( ( ( hash_id, ( service_id, filename ) ) for ( hash_id, service_id, filename ) in self._c.execute( 'SELECT hash_id, service_id, filename FROM service_filenames WHERE hash_id IN ' + splayed_hash_ids + ';' ) ) )
|
||||
|
||||
hash_ids_to_local_ratings = HydrusData.BuildKeyToListDict( [ ( hash_id, ( service_id, rating ) ) for ( service_id, hash_id, rating ) in self._c.execute( 'SELECT service_id, hash_id, rating FROM local_ratings WHERE hash_id IN ' + splayed_hash_ids + ';' ) ] )
|
||||
with HydrusDB.TemporaryIntegerTable( self._c, hash_ids, 'hash_id' ) as temp_table_name:
|
||||
|
||||
hash_ids_to_info = { hash_id : ( size, mime, width, height, duration, num_frames, num_words ) for ( hash_id, size, mime, width, height, duration, num_frames, num_words ) in self._c.execute( 'SELECT * FROM files_info, ' + temp_table_name + ' USING ( hash_id );' ) }
|
||||
|
||||
hash_ids_to_hashes = self._GetHashIdsToHashes( hash_ids )
|
||||
|
||||
hash_ids_to_current_file_service_ids_and_timestamps = HydrusData.BuildKeyToListDict( ( ( hash_id, ( service_id, timestamp ) ) for ( hash_id, service_id, timestamp ) in self._c.execute( 'SELECT hash_id, service_id, timestamp FROM current_files, ' + temp_table_name + ' USING ( hash_id );' ) ) )
|
||||
|
||||
hash_ids_to_deleted_file_service_ids = HydrusData.BuildKeyToListDict( self._c.execute( 'SELECT hash_id, service_id FROM deleted_files, ' + temp_table_name + ' USING ( hash_id );' ) )
|
||||
|
||||
hash_ids_to_pending_file_service_ids = HydrusData.BuildKeyToListDict( self._c.execute( 'SELECT hash_id, service_id FROM file_transfers, ' + temp_table_name + ' USING ( hash_id );' ) )
|
||||
|
||||
hash_ids_to_petitioned_file_service_ids = HydrusData.BuildKeyToListDict( self._c.execute( 'SELECT hash_id, service_id FROM file_petitions, ' + temp_table_name + ' USING ( hash_id );' ) )
|
||||
|
||||
hash_ids_to_urls = HydrusData.BuildKeyToListDict( self._c.execute( 'SELECT hash_id, url FROM urls, ' + temp_table_name + ' USING ( hash_id );' ) )
|
||||
|
||||
hash_ids_to_service_ids_and_filenames = HydrusData.BuildKeyToListDict( ( ( hash_id, ( service_id, filename ) ) for ( hash_id, service_id, filename ) in self._c.execute( 'SELECT hash_id, service_id, filename FROM service_filenames, ' + temp_table_name + ' USING ( hash_id );' ) ) )
|
||||
|
||||
hash_ids_to_local_ratings = HydrusData.BuildKeyToListDict( [ ( hash_id, ( service_id, rating ) ) for ( service_id, hash_id, rating ) in self._c.execute( 'SELECT service_id, hash_id, rating FROM local_ratings, ' + temp_table_name + ' USING ( hash_id );' ) ] )
|
||||
|
||||
|
||||
# build it
|
||||
|
||||
|
@ -3950,6 +4017,8 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
raw_tag_ids = []
|
||||
|
||||
# now I have fast integer list access above, I should move this up to that
|
||||
# furthermore, look into pulling them from the caches instead, at least for current/pending
|
||||
for tag_service_id in tag_service_ids:
|
||||
|
||||
( current_mappings_table_name, deleted_mappings_table_name, pending_mappings_table_name, petitioned_mappings_table_name ) = GenerateMappingsTableNames( tag_service_id )
|
||||
|
@ -4262,7 +4331,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
( hash_id, ) = result
|
||||
|
||||
( media_result, ) = self._GetMediaResults( ( hash_id, ) )
|
||||
media_result = self._GetMediaResults( ( hash_id, ) )[ 0 ]
|
||||
|
||||
return media_result
|
||||
|
||||
|
@ -4286,7 +4355,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
( hash_id, ) = result
|
||||
|
||||
( media_result, ) = self._GetMediaResults( ( hash_id, ) )
|
||||
media_result = self._GetMediaResults( ( hash_id, ) )[ 0 ]
|
||||
|
||||
return media_result
|
||||
|
||||
|
@ -8201,13 +8270,10 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
for ( namespace_id, tag_id, hash_ids ) in pending_mappings_ids:
|
||||
|
||||
self._c.execute( 'CREATE TABLE mem.temp_pending_hash_ids ( hash_id INTEGER );' )
|
||||
|
||||
self._c.executemany( 'INSERT INTO temp_pending_hash_ids ( hash_id ) VALUES ( ? );', ( ( hash_id, ) for hash_id in hash_ids ) )
|
||||
|
||||
existing_current_hash_ids = { hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM temp_pending_hash_ids, ' + current_mappings_table_name + ' USING ( hash_id ) WHERE namespace_id = ? AND tag_id = ?;', ( namespace_id, tag_id ) ) }
|
||||
|
||||
self._c.execute( 'DROP TABLE mem.temp_pending_hash_ids;' )
|
||||
with HydrusDB.TemporaryIntegerTable( self._c, hash_ids, 'hash_id' ) as temp_table_name:
|
||||
|
||||
existing_current_hash_ids = { hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM ' + temp_table_name + ', ' + current_mappings_table_name + ' USING ( hash_id ) WHERE namespace_id = ? AND tag_id = ?;', ( namespace_id, tag_id ) ) }
|
||||
|
||||
|
||||
valid_hash_ids = set( hash_ids ).difference( existing_current_hash_ids )
|
||||
|
||||
|
|
|
@ -408,11 +408,6 @@ def ShowTextClient( text ):
|
|||
|
||||
def SortTagsList( tags, sort_type ):
|
||||
|
||||
if sort_type in ( CC.SORT_BY_INCIDENCE_ASC, CC.SORT_BY_INCIDENCE_DESC ):
|
||||
|
||||
sort_type = CC.SORT_BY_INCIDENCE_ASC
|
||||
|
||||
|
||||
if sort_type in ( CC.SORT_BY_LEXICOGRAPHIC_DESC, CC.SORT_BY_LEXICOGRAPHIC_NAMESPACE_DESC ):
|
||||
|
||||
reverse = True
|
||||
|
|
|
@ -2341,14 +2341,36 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
|
||||
elif command == 'debug_make_popups':
|
||||
|
||||
for i in range( 1, 9 ):
|
||||
for i in range( 1, 7 ):
|
||||
|
||||
HydrusData.ShowText( 'This is a test popup message -- ' + str( i ) )
|
||||
|
||||
|
||||
#
|
||||
|
||||
job_key = ClientThreading.JobKey( pausable = True, cancellable = True)
|
||||
|
||||
job_key.SetVariable( 'title', 'test job' )
|
||||
|
||||
job_key.SetVariable( 'popup_text_1', 'Currently processing test job 5/8' )
|
||||
job_key.SetVariable( 'popup_gauge_1', ( 5, 8 ) )
|
||||
|
||||
self._controller.pub( 'message', job_key )
|
||||
|
||||
wx.CallLater( 2000, job_key.SetVariable, 'popup_text_2', 'Pulsing subjob' )
|
||||
wx.CallLater( 2000, job_key.SetVariable, 'popup_gauge_2', ( 0, None ) )
|
||||
|
||||
#
|
||||
|
||||
e = HydrusExceptions.DataMissing( 'This is a test exception' )
|
||||
|
||||
HydrusData.ShowException( e )
|
||||
|
||||
#
|
||||
|
||||
for i in range( 1, 4 ):
|
||||
|
||||
wx.CallLater( 1000 * i, HydrusData.ShowText, 'This is a delayed popup message -- ' + str( i ) )
|
||||
wx.CallLater( 500 * i, HydrusData.ShowText, 'This is a delayed popup message -- ' + str( i ) )
|
||||
|
||||
|
||||
elif command == 'delete_all_closed_pages': self._DeleteAllClosedPages()
|
||||
|
|
|
@ -2274,7 +2274,7 @@ class ListBoxTagsStrings( ListBoxTags ):
|
|||
self._service_key = service_key
|
||||
self._show_sibling_text = show_sibling_text
|
||||
self._sort_tags = sort_tags
|
||||
self._tags = set()
|
||||
self._tags = []
|
||||
|
||||
|
||||
def _RecalcTags( self ):
|
||||
|
@ -2350,7 +2350,13 @@ class ListBoxTagsStringsAddRemove( ListBoxTagsStrings ):
|
|||
|
||||
def _RemoveTags( self, tags ):
|
||||
|
||||
self._tags.difference_update( tags )
|
||||
for tag in tags:
|
||||
|
||||
if tag in self._tags:
|
||||
|
||||
self._tags.remove( tag )
|
||||
|
||||
|
||||
|
||||
self._RecalcTags()
|
||||
|
||||
|
@ -2362,14 +2368,20 @@ class ListBoxTagsStringsAddRemove( ListBoxTagsStrings ):
|
|||
|
||||
def AddTags( self, tags ):
|
||||
|
||||
self._tags.update( tags )
|
||||
for tag in tags:
|
||||
|
||||
if tag not in self._tags:
|
||||
|
||||
self._tags.append( tag )
|
||||
|
||||
|
||||
|
||||
self._RecalcTags()
|
||||
|
||||
|
||||
def Clear( self ):
|
||||
|
||||
self._tags = set()
|
||||
self._tags = []
|
||||
|
||||
self._RecalcTags()
|
||||
|
||||
|
@ -2382,13 +2394,13 @@ class ListBoxTagsStringsAddRemove( ListBoxTagsStrings ):
|
|||
|
||||
if tag in self._tags:
|
||||
|
||||
self._tags.discard( tag )
|
||||
self._tags.remove( tag )
|
||||
|
||||
removed.add( tag )
|
||||
|
||||
else:
|
||||
|
||||
self._tags.add( tag )
|
||||
self._tags.append( tag )
|
||||
|
||||
|
||||
|
||||
|
@ -2573,7 +2585,7 @@ class ListBoxTagsSelection( ListBoxTags ):
|
|||
|
||||
self._sort = HC.options[ 'default_tag_sort' ]
|
||||
|
||||
if not include_counts and self._sort in ( CC.SORT_BY_INCIDENCE_ASC, CC.SORT_BY_INCIDENCE_DESC ):
|
||||
if not include_counts and self._sort in ( CC.SORT_BY_INCIDENCE_ASC, CC.SORT_BY_INCIDENCE_DESC, CC.SORT_BY_INCIDENCE_NAMESPACE_ASC, CC.SORT_BY_INCIDENCE_NAMESPACE_DESC ):
|
||||
|
||||
self._sort = CC.SORT_BY_LEXICOGRAPHIC_ASC
|
||||
|
||||
|
@ -2710,7 +2722,7 @@ class ListBoxTagsSelection( ListBoxTags ):
|
|||
|
||||
def _SortTags( self ):
|
||||
|
||||
if self._sort in ( CC.SORT_BY_INCIDENCE_ASC, CC.SORT_BY_INCIDENCE_DESC ):
|
||||
if self._sort in ( CC.SORT_BY_INCIDENCE_ASC, CC.SORT_BY_INCIDENCE_DESC, CC.SORT_BY_INCIDENCE_NAMESPACE_ASC, CC.SORT_BY_INCIDENCE_NAMESPACE_DESC ):
|
||||
|
||||
tags_to_count = collections.Counter()
|
||||
|
||||
|
@ -2718,28 +2730,55 @@ class ListBoxTagsSelection( ListBoxTags ):
|
|||
if self._show_deleted: tags_to_count.update( self._deleted_tags_to_count )
|
||||
if self._show_pending: tags_to_count.update( self._pending_tags_to_count )
|
||||
if self._show_petitioned: tags_to_count.update( self._petitioned_tags_to_count )
|
||||
|
||||
def key( unordered_string ):
|
||||
|
||||
return ( tags_to_count[ self._strings_to_terms[ unordered_string ] ], unordered_string )
|
||||
|
||||
|
||||
if self._sort == CC.SORT_BY_INCIDENCE_ASC:
|
||||
|
||||
def key( a ):
|
||||
|
||||
return ( tags_to_count[ self._strings_to_terms[ a ] ], a )
|
||||
|
||||
if self._sort in ( CC.SORT_BY_INCIDENCE_ASC, CC.SORT_BY_INCIDENCE_NAMESPACE_ASC ):
|
||||
|
||||
reverse = False
|
||||
|
||||
elif self._sort == CC.SORT_BY_INCIDENCE_DESC:
|
||||
elif self._sort in ( CC.SORT_BY_INCIDENCE_DESC, CC.SORT_BY_INCIDENCE_NAMESPACE_DESC ):
|
||||
|
||||
def key( a ):
|
||||
|
||||
return ( - tags_to_count[ self._strings_to_terms[ a ] ], a )
|
||||
|
||||
|
||||
reverse = False
|
||||
reverse = True
|
||||
|
||||
|
||||
self._ordered_strings.sort( key = key, reverse = reverse )
|
||||
|
||||
if self._sort in ( CC.SORT_BY_INCIDENCE_NAMESPACE_ASC, CC.SORT_BY_INCIDENCE_NAMESPACE_DESC ):
|
||||
|
||||
# python list sort is stable, so lets now sort again
|
||||
|
||||
def secondary_key( unordered_string ):
|
||||
|
||||
tag = self._strings_to_terms[ unordered_string ]
|
||||
|
||||
if ':' in tag:
|
||||
|
||||
( namespace, subtag ) = tag.split( ':', 1 )
|
||||
|
||||
else:
|
||||
|
||||
namespace = '{' # '{' is above 'z' in ascii, so this works for most situations
|
||||
|
||||
|
||||
return namespace
|
||||
|
||||
|
||||
if self._sort == CC.SORT_BY_INCIDENCE_NAMESPACE_ASC:
|
||||
|
||||
reverse = True
|
||||
|
||||
elif self._sort == CC.SORT_BY_INCIDENCE_NAMESPACE_DESC:
|
||||
|
||||
reverse = False
|
||||
|
||||
|
||||
self._ordered_strings.sort( key = secondary_key, reverse = reverse )
|
||||
|
||||
|
||||
else:
|
||||
|
||||
ClientData.SortTagsList( self._ordered_strings, self._sort )
|
||||
|
@ -3287,16 +3326,6 @@ class PopupMessage( PopupWindow ):
|
|||
self._caller_tb_text.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._caller_tb_text.Hide()
|
||||
|
||||
self._show_db_tb_button = wx.Button( self, label = 'show db traceback' )
|
||||
self._show_db_tb_button.Bind( wx.EVT_BUTTON, self.EventShowDBTBButton )
|
||||
self._show_db_tb_button.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._show_db_tb_button.Hide()
|
||||
|
||||
self._db_tb_text = FitResistantStaticText( self )
|
||||
self._db_tb_text.Wrap( 380 )
|
||||
self._db_tb_text.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._db_tb_text.Hide()
|
||||
|
||||
self._copy_tb_button = wx.Button( self, label = 'copy traceback information' )
|
||||
self._copy_tb_button.Bind( wx.EVT_BUTTON, self.EventCopyTBButton )
|
||||
self._copy_tb_button.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
|
@ -3328,8 +3357,6 @@ class PopupMessage( PopupWindow ):
|
|||
vbox.AddF( self._tb_text, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._show_caller_tb_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._caller_tb_text, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._show_db_tb_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._db_tb_text, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._copy_tb_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( hbox, CC.FLAGS_BUTTON_SIZER )
|
||||
|
||||
|
@ -3367,9 +3394,14 @@ class PopupMessage( PopupWindow ):
|
|||
|
||||
def EventCopyToClipboardButton( self, event ):
|
||||
|
||||
( title, text ) = self._job_key.GetVariable( 'popup_clipboard' )
|
||||
result = self._job_key.GetIfHasVariable( 'popup_clipboard' )
|
||||
|
||||
HydrusGlobals.client_controller.pub( 'clipboard', 'text', text )
|
||||
if result is not None:
|
||||
|
||||
( title, text ) = result
|
||||
|
||||
HydrusGlobals.client_controller.pub( 'clipboard', 'text', text )
|
||||
|
||||
|
||||
|
||||
def EventPauseButton( self, event ):
|
||||
|
@ -3404,31 +3436,18 @@ class PopupMessage( PopupWindow ):
|
|||
self.GetParent().MakeSureEverythingFits()
|
||||
|
||||
|
||||
def EventShowDBTBButton( self, event ):
|
||||
|
||||
if self._db_tb_text.IsShown():
|
||||
|
||||
self._show_db_tb_button.SetLabelText( 'show db traceback' )
|
||||
|
||||
self._db_tb_text.Hide()
|
||||
|
||||
else:
|
||||
|
||||
self._show_db_tb_button.SetLabelText( 'hide db traceback' )
|
||||
|
||||
self._db_tb_text.Show()
|
||||
|
||||
|
||||
self.GetParent().MakeSureEverythingFits()
|
||||
|
||||
|
||||
def EventShowFilesButton( self, event ):
|
||||
|
||||
hashes = self._job_key.GetVariable( 'popup_files' )
|
||||
result = self._job_key.GetIfHasVariable( 'popup_files' )
|
||||
|
||||
media_results = HydrusGlobals.client_controller.Read( 'media_results', hashes )
|
||||
|
||||
HydrusGlobals.client_controller.pub( 'new_page_query', CC.LOCAL_FILE_SERVICE_KEY, initial_media_results = media_results )
|
||||
if result is not None:
|
||||
|
||||
hashes = result
|
||||
|
||||
media_results = HydrusGlobals.client_controller.Read( 'media_results', hashes )
|
||||
|
||||
HydrusGlobals.client_controller.pub( 'new_page_query', CC.LOCAL_FILE_SERVICE_KEY, initial_media_results = media_results )
|
||||
|
||||
|
||||
|
||||
def EventShowTBButton( self, event ):
|
||||
|
@ -3473,38 +3492,58 @@ class PopupMessage( PopupWindow ):
|
|||
|
||||
def Update( self ):
|
||||
|
||||
if self._job_key.HasVariable( 'popup_title' ):
|
||||
paused = self._job_key.IsPaused()
|
||||
|
||||
title = self._job_key.GetIfHasVariable( 'popup_title' )
|
||||
|
||||
if title is not None:
|
||||
|
||||
text = self._job_key.GetVariable( 'popup_title' )
|
||||
text = title
|
||||
|
||||
if self._title.GetLabelText() != text: self._title.SetLabelText( text )
|
||||
|
||||
self._title.Show()
|
||||
|
||||
else: self._title.Hide()
|
||||
|
||||
if self._job_key.HasVariable( 'popup_text_1' ) or self._job_key.IsPaused():
|
||||
else:
|
||||
|
||||
if self._job_key.IsPaused():
|
||||
self._title.Hide()
|
||||
|
||||
|
||||
popup_text_1 = self._job_key.GetIfHasVariable( 'popup_text_1' )
|
||||
|
||||
if popup_text_1 is not None or paused:
|
||||
|
||||
if paused:
|
||||
|
||||
text = 'paused'
|
||||
|
||||
else:
|
||||
|
||||
text = self._job_key.GetVariable( 'popup_text_1' )
|
||||
text = popup_text_1
|
||||
|
||||
|
||||
if self._text_1.GetLabelText() != text: self._text_1.SetLabelText( self._ProcessText( HydrusData.ToUnicode( text ) ) )
|
||||
if self._text_1.GetLabelText() != text:
|
||||
|
||||
self._text_1.SetLabelText( self._ProcessText( HydrusData.ToUnicode( text ) ) )
|
||||
|
||||
|
||||
self._text_1.Show()
|
||||
|
||||
else: self._text_1.Hide()
|
||||
else:
|
||||
|
||||
self._text_1.Hide()
|
||||
|
||||
|
||||
if self._job_key.HasVariable( 'popup_gauge_1' ) and not self._job_key.IsPaused():
|
||||
popup_gauge_1 = self._job_key.GetIfHasVariable( 'popup_gauge_1' )
|
||||
|
||||
if popup_gauge_1 is not None and not paused:
|
||||
|
||||
( gauge_value, gauge_range ) = self._job_key.GetVariable( 'popup_gauge_1' )
|
||||
( gauge_value, gauge_range ) = popup_gauge_1
|
||||
|
||||
if gauge_range is None or gauge_value is None: self._gauge_1.Pulse()
|
||||
if gauge_range is None or gauge_value is None:
|
||||
|
||||
self._gauge_1.Pulse()
|
||||
|
||||
else:
|
||||
|
||||
self._gauge_1.SetRange( gauge_range )
|
||||
|
@ -3513,23 +3552,39 @@ class PopupMessage( PopupWindow ):
|
|||
|
||||
self._gauge_1.Show()
|
||||
|
||||
else: self._gauge_1.Hide()
|
||||
else:
|
||||
|
||||
self._gauge_1.Hide()
|
||||
|
||||
|
||||
if self._job_key.HasVariable( 'popup_text_2' ) and not self._job_key.IsPaused():
|
||||
popup_text_2 = self._job_key.GetIfHasVariable( 'popup_text_2' )
|
||||
|
||||
if popup_text_2 is not None and not paused:
|
||||
|
||||
text = self._job_key.GetVariable( 'popup_text_2' )
|
||||
text = popup_text_2
|
||||
|
||||
if self._text_2.GetLabelText() != text: self._text_2.SetLabelText( self._ProcessText( HydrusData.ToUnicode( text ) ) )
|
||||
if self._text_2.GetLabelText() != text:
|
||||
|
||||
self._text_2.SetLabelText( self._ProcessText( HydrusData.ToUnicode( text ) ) )
|
||||
|
||||
|
||||
self._text_2.Show()
|
||||
|
||||
else: self._text_2.Hide()
|
||||
else:
|
||||
|
||||
self._text_2.Hide()
|
||||
|
||||
|
||||
if self._job_key.HasVariable( 'popup_gauge_2' ) and not self._job_key.IsPaused():
|
||||
popup_gauge_2 = self._job_key.GetIfHasVariable( 'popup_gauge_2' )
|
||||
|
||||
if popup_gauge_2 is not None and not paused:
|
||||
|
||||
( gauge_value, gauge_range ) = self._job_key.GetVariable( 'popup_gauge_2' )
|
||||
( gauge_value, gauge_range ) = popup_gauge_2
|
||||
|
||||
if gauge_range is None or gauge_value is None: self._gauge_2.Pulse()
|
||||
if gauge_range is None or gauge_value is None:
|
||||
|
||||
self._gauge_2.Pulse()
|
||||
|
||||
else:
|
||||
|
||||
self._gauge_2.SetRange( gauge_range )
|
||||
|
@ -3538,11 +3593,16 @@ class PopupMessage( PopupWindow ):
|
|||
|
||||
self._gauge_2.Show()
|
||||
|
||||
else: self._gauge_2.Hide()
|
||||
|
||||
if self._job_key.HasVariable( 'popup_clipboard' ):
|
||||
else:
|
||||
|
||||
( title, text ) = self._job_key.GetVariable( 'popup_clipboard' )
|
||||
self._gauge_2.Hide()
|
||||
|
||||
|
||||
popup_clipboard = self._job_key.GetIfHasVariable( 'popup_clipboard' )
|
||||
|
||||
if popup_clipboard is not None:
|
||||
|
||||
( title, text ) = popup_clipboard
|
||||
|
||||
if self._copy_to_clipboard_button.GetLabelText() != title:
|
||||
|
||||
|
@ -3556,9 +3616,11 @@ class PopupMessage( PopupWindow ):
|
|||
self._copy_to_clipboard_button.Hide()
|
||||
|
||||
|
||||
if self._job_key.HasVariable( 'popup_files' ):
|
||||
popup_files = self._job_key.GetIfHasVariable( 'popup_files' )
|
||||
|
||||
if popup_files is not None:
|
||||
|
||||
hashes = self._job_key.GetVariable( 'popup_files' )
|
||||
hashes = popup_files
|
||||
|
||||
text = 'show ' + HydrusData.ConvertIntToPrettyString( len( hashes ) ) + ' files'
|
||||
|
||||
|
@ -3574,14 +3636,26 @@ class PopupMessage( PopupWindow ):
|
|||
self._show_files_button.Hide()
|
||||
|
||||
|
||||
if self._job_key.HasVariable( 'popup_traceback' ) or self._job_key.HasVariable( 'popup_caller_traceback' ) or self._job_key.HasVariable( 'popup_db_traceback' ): self._copy_tb_button.Show()
|
||||
else: self._copy_tb_button.Hide()
|
||||
popup_traceback = self._job_key.GetIfHasVariable( 'popup_traceback' )
|
||||
popup_caller_traceback = self._job_key.GetIfHasVariable( 'popup_traceback' )
|
||||
|
||||
if self._job_key.HasVariable( 'popup_traceback' ):
|
||||
if popup_traceback is not None or popup_caller_traceback is not None:
|
||||
|
||||
text = self._job_key.GetVariable( 'popup_traceback' )
|
||||
self._copy_tb_button.Show()
|
||||
|
||||
if self._tb_text.GetLabelText() != text: self._tb_text.SetLabelText( self._ProcessText( HydrusData.ToUnicode( text ) ) )
|
||||
else:
|
||||
|
||||
self._copy_tb_button.Hide()
|
||||
|
||||
|
||||
if popup_traceback is not None:
|
||||
|
||||
text = popup_traceback
|
||||
|
||||
if self._tb_text.GetLabelText() != text:
|
||||
|
||||
self._tb_text.SetLabelText( self._ProcessText( HydrusData.ToUnicode( text ) ) )
|
||||
|
||||
|
||||
self._show_tb_button.Show()
|
||||
|
||||
|
@ -3591,11 +3665,14 @@ class PopupMessage( PopupWindow ):
|
|||
self._tb_text.Hide()
|
||||
|
||||
|
||||
if self._job_key.HasVariable( 'popup_caller_traceback' ):
|
||||
if popup_caller_traceback is not None:
|
||||
|
||||
text = self._job_key.GetVariable( 'popup_caller_traceback' )
|
||||
text = popup_caller_traceback
|
||||
|
||||
if self._caller_tb_text.GetLabelText() != text: self._caller_tb_text.SetLabelText( self._ProcessText( HydrusData.ToUnicode( text ) ) )
|
||||
if self._caller_tb_text.GetLabelText() != text:
|
||||
|
||||
self._caller_tb_text.SetLabelText( self._ProcessText( HydrusData.ToUnicode( text ) ) )
|
||||
|
||||
|
||||
self._show_caller_tb_button.Show()
|
||||
|
||||
|
@ -3605,25 +3682,23 @@ class PopupMessage( PopupWindow ):
|
|||
self._caller_tb_text.Hide()
|
||||
|
||||
|
||||
if self._job_key.HasVariable( 'popup_db_traceback' ):
|
||||
if self._job_key.IsPausable():
|
||||
|
||||
text = self._job_key.GetVariable( 'popup_db_traceback' )
|
||||
|
||||
if self._db_tb_text.GetLabelText() != text: self._db_tb_text.SetLabelText( self._ProcessText( HydrusData.ToUnicode( text ) ) )
|
||||
|
||||
self._show_db_tb_button.Show()
|
||||
self._pause_button.Show()
|
||||
|
||||
else:
|
||||
|
||||
self._show_db_tb_button.Hide()
|
||||
self._db_tb_text.Hide()
|
||||
self._pause_button.Hide()
|
||||
|
||||
|
||||
if self._job_key.IsPausable(): self._pause_button.Show()
|
||||
else: self._pause_button.Hide()
|
||||
|
||||
if self._job_key.IsCancellable(): self._cancel_button.Show()
|
||||
else: self._cancel_button.Hide()
|
||||
if self._job_key.IsCancellable():
|
||||
|
||||
self._cancel_button.Show()
|
||||
|
||||
else:
|
||||
|
||||
self._cancel_button.Hide()
|
||||
|
||||
|
||||
|
||||
class PopupMessageManager( wx.Frame ):
|
||||
|
@ -3756,21 +3831,29 @@ class PopupMessageManager( wx.Frame ):
|
|||
|
||||
if there_is_stuff_to_display:
|
||||
|
||||
self.Fit()
|
||||
best_size = self.GetBestSize()
|
||||
|
||||
if best_size != self.GetSize():
|
||||
|
||||
self.Fit()
|
||||
|
||||
|
||||
( parent_width, parent_height ) = parent.GetClientSize()
|
||||
|
||||
( my_width, my_height ) = self.GetClientSize()
|
||||
|
||||
my_x = ( parent_width - my_width ) - 5
|
||||
my_y = ( parent_height - my_height ) - 15
|
||||
my_x = ( parent_width - my_width ) - 25
|
||||
my_y = ( parent_height - my_height ) - 5
|
||||
|
||||
self.SetPosition( parent.ClientToScreenXY( my_x, my_y ) )
|
||||
my_position = parent.ClientToScreenXY( my_x, my_y )
|
||||
|
||||
if my_position != self.GetPosition():
|
||||
|
||||
self.SetPosition( parent.ClientToScreenXY( my_x, my_y ) )
|
||||
|
||||
|
||||
self.Show()
|
||||
|
||||
self.Refresh()
|
||||
|
||||
else:
|
||||
|
||||
self.Hide()
|
||||
|
@ -5068,6 +5151,8 @@ class StaticBoxSorterForListBoxTags( StaticBox ):
|
|||
self._sorter.Append( 'lexicographic (z-a) (grouped by namespace)', CC.SORT_BY_LEXICOGRAPHIC_NAMESPACE_DESC )
|
||||
self._sorter.Append( 'incidence (desc)', CC.SORT_BY_INCIDENCE_DESC )
|
||||
self._sorter.Append( 'incidence (asc)', CC.SORT_BY_INCIDENCE_ASC )
|
||||
self._sorter.Append( 'incidence (desc) (grouped by namespace)', CC.SORT_BY_INCIDENCE_NAMESPACE_DESC )
|
||||
self._sorter.Append( 'incidence (asc) (grouped by namespace)', CC.SORT_BY_INCIDENCE_NAMESPACE_ASC )
|
||||
|
||||
if HC.options[ 'default_tag_sort' ] == CC.SORT_BY_LEXICOGRAPHIC_ASC: self._sorter.Select( 0 )
|
||||
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_LEXICOGRAPHIC_DESC: self._sorter.Select( 1 )
|
||||
|
@ -5075,6 +5160,8 @@ class StaticBoxSorterForListBoxTags( StaticBox ):
|
|||
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_LEXICOGRAPHIC_NAMESPACE_DESC: self._sorter.Select( 3 )
|
||||
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_INCIDENCE_DESC: self._sorter.Select( 4 )
|
||||
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_INCIDENCE_ASC: self._sorter.Select( 5 )
|
||||
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_INCIDENCE_NAMESPACE_DESC: self._sorter.Select( 6 )
|
||||
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_INCIDENCE_NAMESPACE_ASC: self._sorter.Select( 7 )
|
||||
|
||||
self._sorter.Bind( wx.EVT_CHOICE, self.EventSort )
|
||||
|
||||
|
|
|
@ -667,7 +667,7 @@ class ManageOptionsPanel( ManagePanel ):
|
|||
|
||||
self.SetSizer( vbox )
|
||||
|
||||
|
||||
|
||||
class _ClientFilesPanel( wx.Panel ):
|
||||
|
||||
def __init__( self, parent ):
|
||||
|
@ -2622,6 +2622,8 @@ class ManageOptionsPanel( ManagePanel ):
|
|||
self._default_tag_sort.Append( 'lexicographic (z-a) (grouped by namespace)', CC.SORT_BY_LEXICOGRAPHIC_NAMESPACE_DESC )
|
||||
self._default_tag_sort.Append( 'incidence (desc)', CC.SORT_BY_INCIDENCE_DESC )
|
||||
self._default_tag_sort.Append( 'incidence (asc)', CC.SORT_BY_INCIDENCE_ASC )
|
||||
self._default_tag_sort.Append( 'incidence (desc) (grouped by namespace)', CC.SORT_BY_INCIDENCE_NAMESPACE_DESC )
|
||||
self._default_tag_sort.Append( 'incidence (asc) (grouped by namespace)', CC.SORT_BY_INCIDENCE_NAMESPACE_ASC )
|
||||
|
||||
self._default_tag_repository = ClientGUICommon.BetterChoice( general_panel )
|
||||
|
||||
|
@ -2680,6 +2682,8 @@ class ManageOptionsPanel( ManagePanel ):
|
|||
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_LEXICOGRAPHIC_NAMESPACE_DESC: self._default_tag_sort.Select( 3 )
|
||||
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_INCIDENCE_DESC: self._default_tag_sort.Select( 4 )
|
||||
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_INCIDENCE_ASC: self._default_tag_sort.Select( 5 )
|
||||
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_INCIDENCE_NAMESPACE_DESC: self._default_tag_sort.Select( 6 )
|
||||
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_INCIDENCE_NAMESPACE_ASC: self._default_tag_sort.Select( 7 )
|
||||
|
||||
services = HydrusGlobals.client_controller.GetServicesManager().GetServices( HC.TAG_SERVICES )
|
||||
|
||||
|
@ -2837,6 +2841,110 @@ class ManageOptionsPanel( ManagePanel ):
|
|||
wx.MessageBox( traceback.format_exc() )
|
||||
|
||||
|
||||
|
||||
class ManageParsingScriptsPanel( ManagePanel ):
|
||||
|
||||
def __init__( self, parent ):
|
||||
|
||||
ManagePanel.__init__( self, parent )
|
||||
|
||||
self._scripts = ClientGUICommon.SaneListCtrl( self, 200, [ ( 'name', -1 ), ( 'query type', 50 ), ( 'starting url', 120 ) ], delete_key_callback = self.Delete, activation_callback = self.Edit, use_display_tuple_for_sort = True )
|
||||
|
||||
self._add_button = wx.Button( self, label = 'add' )
|
||||
self._add_button.Bind( wx.EVT_BUTTON, self.EventAdd )
|
||||
|
||||
self._edit_button = wx.Button( self, label = 'edit' )
|
||||
self._add_button.Bind( wx.EVT_BUTTON, self.EventEdit )
|
||||
|
||||
self._delete_button = wx.Button( self, label = 'delete' )
|
||||
self._add_button.Bind( wx.EVT_BUTTON, self.EventDelete )
|
||||
|
||||
#
|
||||
|
||||
scripts = [] # fetch all scripts from the db, populate listctrl using name column's data to store the script itself or w/e
|
||||
|
||||
for script in scripts:
|
||||
|
||||
( display_tuple, data_tuple ) = self._ConvertScriptToTuples( script )
|
||||
|
||||
self._scripts.Append( display_tuple, data_tuple )
|
||||
|
||||
|
||||
#
|
||||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
button_hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
button_hbox.AddF( self._add_button, CC.FLAGS_VCENTER )
|
||||
button_hbox.AddF( self._edit_button, CC.FLAGS_VCENTER )
|
||||
button_hbox.AddF( self._delete_button, CC.FLAGS_VCENTER )
|
||||
|
||||
vbox.AddF( self._scripts, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
vbox.AddF( button_hbox, CC.FLAGS_BUTTON_SIZER )
|
||||
|
||||
self.SetSizer( vbox )
|
||||
|
||||
|
||||
def _ConvertScriptToTuples( self, script ):
|
||||
|
||||
# fetch these vars from the script, return display/data tuples for the listctrl
|
||||
|
||||
name = 'blah'
|
||||
query_type = 'GET'
|
||||
starting_url = 'muh_booru.com'
|
||||
|
||||
return ( ( name, query_type, starting_url ), ( script, query_type, starting_url ) )
|
||||
|
||||
|
||||
def Add( self ):
|
||||
|
||||
# blank edit script dlg, append it
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def CommitChanges( self ):
|
||||
|
||||
scripts = [ script for ( script, query_type, starting_url ) in self._scripts.GetClientData() ]
|
||||
|
||||
# save them to db
|
||||
|
||||
|
||||
def Delete( self ):
|
||||
|
||||
self._scripts.RemoveAllSelected()
|
||||
|
||||
|
||||
def Edit( self ):
|
||||
|
||||
for i in self._scripts.GetAllSelected():
|
||||
|
||||
( script, query_type, starting_url ) = self._scripts.GetClientData( i )
|
||||
|
||||
# throw it at edit script dlg
|
||||
# if ok:
|
||||
|
||||
( display_tuple, data_tuple ) = self._ConvertScriptToTuples( script )
|
||||
|
||||
self._scripts.UpdateRow( i, display_tuple, data_tuple )
|
||||
|
||||
|
||||
|
||||
def EventAdd( self, event ):
|
||||
|
||||
self.Add()
|
||||
|
||||
|
||||
def EventDelete( self, event ):
|
||||
|
||||
self.Delete()
|
||||
|
||||
|
||||
def EventEdit( self, event ):
|
||||
|
||||
self.Edit()
|
||||
|
||||
|
||||
class ManageTagsPanel( ManagePanel ):
|
||||
|
||||
|
|
|
@ -64,15 +64,26 @@ def GenerateNumpyImage( path ):
|
|||
|
||||
else:
|
||||
|
||||
( im_y, im_x, depth ) = numpy_image.shape
|
||||
shape = numpy_image.shape
|
||||
|
||||
if depth == 4:
|
||||
if len( shape ) == 2:
|
||||
|
||||
convert = cv2.COLOR_BGRA2RGBA
|
||||
# monochrome image
|
||||
|
||||
convert = cv2.COLOR_GRAY2RGB
|
||||
|
||||
else:
|
||||
|
||||
convert = cv2.COLOR_BGR2RGB
|
||||
( im_y, im_x, depth ) = shape
|
||||
|
||||
if depth == 4:
|
||||
|
||||
convert = cv2.COLOR_BGRA2RGBA
|
||||
|
||||
else:
|
||||
|
||||
convert = cv2.COLOR_BGR2RGB
|
||||
|
||||
|
||||
|
||||
numpy_image = cv2.cvtColor( numpy_image, convert )
|
||||
|
|
|
@ -8,6 +8,7 @@ import os
|
|||
import requests
|
||||
import socket
|
||||
import socks
|
||||
import ssl
|
||||
import threading
|
||||
import time
|
||||
import urllib
|
||||
|
@ -425,6 +426,23 @@ class HTTPConnection( object ):
|
|||
raise
|
||||
|
||||
|
||||
except ssl.SSLEOFError:
|
||||
|
||||
time.sleep( 5 )
|
||||
|
||||
if attempt_number <= 3:
|
||||
|
||||
self._RefreshConnection()
|
||||
|
||||
return self._GetResponse( method_string, path_and_query, request_headers, body, attempt_number = attempt_number + 1 )
|
||||
|
||||
else:
|
||||
|
||||
text = 'The hydrus client\'s ssl connection to ' + HydrusData.ToUnicode( self._host ) + ' kept terminating abruptly, so the attempt was abandoned.'
|
||||
|
||||
raise HydrusExceptions.NetworkException( text )
|
||||
|
||||
|
||||
|
||||
|
||||
def _ReadResponse( self, response, report_hooks, temp_path = None ):
|
||||
|
@ -453,6 +471,10 @@ class HTTPConnection( object ):
|
|||
raise HydrusExceptions.NetworkException( 'Connection reset by remote host.' )
|
||||
|
||||
|
||||
except ssl.SSLEOFError:
|
||||
|
||||
raise HydrusExceptions.NetworkException( 'Secure connection terminated abruptly.' )
|
||||
|
||||
|
||||
return ( parsed_response, size_of_response )
|
||||
|
||||
|
|
|
@ -141,12 +141,22 @@ class JobKey( object ):
|
|||
|
||||
def Finish( self ): self._done.set()
|
||||
|
||||
def GetKey( self ): return self._key
|
||||
def GetIfHasVariable( self, name ):
|
||||
|
||||
with self._variable_lock:
|
||||
|
||||
if name in self._variables:
|
||||
|
||||
return self._variables[ name ]
|
||||
|
||||
else:
|
||||
|
||||
return None
|
||||
|
||||
|
||||
|
||||
|
||||
def GetVariable( self, name ):
|
||||
|
||||
with self._variable_lock: return self._variables[ name ]
|
||||
|
||||
def GetKey( self ): return self._key
|
||||
|
||||
def HasVariable( self, name ):
|
||||
|
||||
|
@ -242,8 +252,6 @@ class JobKey( object ):
|
|||
|
||||
if 'popup_caller_traceback' in self._variables: stuff_to_print.append( self._variables[ 'popup_caller_traceback' ] )
|
||||
|
||||
if 'popup_db_traceback' in self._variables: stuff_to_print.append( self._variables[ 'popup_db_traceback' ] )
|
||||
|
||||
|
||||
stuff_to_print = [ HydrusData.ToUnicode( s ) for s in stuff_to_print ]
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ class GIFRenderer( object ):
|
|||
|
||||
else:
|
||||
|
||||
current_frame = pil_image = HydrusImageHandling.Dequantize( self._pil_image )
|
||||
current_frame = HydrusImageHandling.Dequantize( self._pil_image )
|
||||
|
||||
if current_frame.mode == 'RGBA':
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ options = {}
|
|||
# Misc
|
||||
|
||||
NETWORK_VERSION = 17
|
||||
SOFTWARE_VERSION = 224
|
||||
SOFTWARE_VERSION = 225
|
||||
|
||||
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
||||
|
||||
|
|
|
@ -700,4 +700,31 @@ class HydrusDB( object ):
|
|||
|
||||
if synchronous: return job.GetResult()
|
||||
|
||||
|
||||
class TemporaryIntegerTable( object ):
|
||||
|
||||
def __init__( self, cursor, integer_iterable, column_name ):
|
||||
|
||||
self._cursor = cursor
|
||||
self._integer_iterable = integer_iterable
|
||||
self._column_name = column_name
|
||||
|
||||
self._table_name = 'mem.tempint' + os.urandom( 32 ).encode( 'hex' )
|
||||
|
||||
|
||||
def __enter__( self ):
|
||||
|
||||
self._cursor.execute( 'CREATE TABLE ' + self._table_name + ' ( ' + self._column_name + ' INTEGER PRIMARY KEY );' )
|
||||
|
||||
self._cursor.executemany( 'INSERT INTO ' + self._table_name + ' ( ' + self._column_name + ' ) VALUES ( ? );', ( ( i, ) for i in self._integer_iterable ) )
|
||||
|
||||
return self._table_name
|
||||
|
||||
|
||||
def __exit__( self, exc_type, exc_val, exc_tb ):
|
||||
|
||||
self._cursor.execute( 'DROP TABLE ' + self._table_name + ';' )
|
||||
|
||||
return False
|
||||
|
||||
|
|
@ -1851,7 +1851,6 @@ class JobDatabase( object ):
|
|||
self._args = args
|
||||
self._kwargs = kwargs
|
||||
|
||||
self._result = None
|
||||
self._result_ready = threading.Event()
|
||||
|
||||
|
||||
|
@ -1864,13 +1863,21 @@ class JobDatabase( object ):
|
|||
|
||||
while True:
|
||||
|
||||
if self._result_ready.wait( 2 ) == True: break
|
||||
elif HydrusGlobals.model_shutdown: raise HydrusExceptions.ShutdownException( 'Application quit before db could serve result!' )
|
||||
if self._result_ready.wait( 2 ) == True:
|
||||
|
||||
break
|
||||
|
||||
elif HydrusGlobals.model_shutdown:
|
||||
|
||||
raise HydrusExceptions.ShutdownException( 'Application quit before db could serve result!' )
|
||||
|
||||
|
||||
|
||||
if isinstance( self._result, Exception ):
|
||||
|
||||
raise self._result
|
||||
e = self._result
|
||||
|
||||
raise e
|
||||
|
||||
else:
|
||||
|
||||
|
@ -1878,7 +1885,10 @@ class JobDatabase( object ):
|
|||
|
||||
|
||||
|
||||
def GetType( self ): return self._type
|
||||
def GetType( self ):
|
||||
|
||||
return self._type
|
||||
|
||||
|
||||
def IsSynchronous( self ): return self._synchronous
|
||||
|
||||
|
|
Loading…
Reference in New Issue