Version 185

This commit is contained in:
Hydrus 2015-12-09 17:16:41 -06:00
parent 1ef52cff14
commit 39711a06eb
29 changed files with 2638 additions and 2317 deletions

View File

@ -8,6 +8,46 @@
<div class="content">
<h3>changelog</h3>
<ul>
<li><h3>version 185</h3></li>
<ul>
<li>right clicking on a tag/predicate in the 'selection tags' box or the 'search' list of active predicates provides new intelligent menu options to discard/require/permit/exclude the selected tags from the current search. try it out!</li>
<li>this system also works for namespace and wildcard and system predicates</li>
<li>'predicate a' and its inverse '-predicate a' are no longer considered the same!</li>
<li>namespace and wildcard predicates will now remove their inverts if they are added to the list of active predicates</li>
<li>the way inverse predicates are generated and compared is generalised and improved</li>
<li>fixed 'open a new search page for tag x', which might have been broken?</li>
<li>quick-entering a tag in the 'read' tag autocomplete entry will now always replace with a sibling if one exists</li>
<li>quick-entering a tag in the 'write' tag autocomplete entry will now not replace with a sibling--you will get the option of what you want to do</li>
<li>when this happens, the preferred sibling is labelled on the 'what do you want to do?' popup in the manage tags dialog</li>
<li>also when this happens, the affected file count for add/pend the preferred sibling should now be correct</li>
<li>fixed client support for tags that begin with ':', such as many emoticons. these should now be parsed correctly from websites and keyboard input, keep their leading colon through network and db conversions, and display correctly (for the most part!), despite a little bit of magic to make them work</li>
<li>created a new TimeDelta control to handle finer tuning of optional periods</li>
<li>improved timedelta->pretty string code to support >60s times</li>
<li>manage subscriptions dialog now supports day and hour period, with min period of four hours</li>
<li>manage export folders dialog now supports day/hour/minute period, and the parent dialog displays that time delta appropriately</li>
<li>manage import folders dialog now supports day/hour/minute period, and the parent dialog displays that time delta appropriately</li>
<li>the thread watcher now supports hour/minute/seconds check period</li>
<li>folded 'search' and 'download' menus into 'view' and renamed it 'pages'</li>
<li>'sessions' moved from 'file' to the new 'pages'</li>
<li>moved 'admin' menu to 'services->administrate services'</li>
<li>added 'forced system:limit' to options->speed and memory panel</li>
<li>if several system:limits exist in a search, the minimum will be used</li>
<li>added a checkbox to options->downloading to replace the traffic light waiting politely indicator with text</li>
<li>subscriptions with failed files will say 'x urls in cache, y failed' on their dialog panel</li>
<li>at the gui level, media that superfluously receives a 'pend tag' instruction for a tag that is already current will discard the instruction (this improves the accuracy of the pending tag count during and after the manage tag dialog)</li>
<li>and the same thing for 'petition tag' when the tag isn't already current</li>
<li>any accidentally added 'namespace:'-type tags will be deleted on update</li>
<li>fixed a bad merge in the manage tag siblings dialog's autocomplete dropdown lists</li>
<li>the thread watcher can now deal with urls with a #54951495 post anchor at the end</li>
<li>refactored some controller manager code</li>
<li>removed some useless old code</li>
<li>cleaned some misc code</li>
<li>improved some bad old orphan deletion code</li>
<li>deleted some old code</li>
<li>finished off some old media result streaming code</li>
<li>refactored a bunch of search stuff from clientdata to clientsearch</li>
<li>rewrote some subs gui/help text to be a bit clearer, and added a help link to the dialog</li>
</ul>
<li><h3>version 184</h3></li>
<ul>
<li>added external client_files storage!</li>

View File

@ -7,9 +7,9 @@
<body>
<div class="content">
<p><a href="getting_started_tags.html"><--- Back to tags</a></p>
<p class="warning">Do not try to create a subscription until you are comfortable with a normal gallery download page! Go <i>F9->download->gallery->[your preference]</i> and run some searches, just so you get a feel before you make a mistake here.</p>
<p class="warning">Do not try to create a subscription until you are comfortable with a normal gallery download page! If you haven't downloaded anything yet, go <i>F9->download->gallery->[your preference]</i> and run some searches, just so you get a feel before you make a mistake here.</p>
<h3>what are subs?</h3>
<p>Subscriptions are a way of telling the client to stay synchronised with a gallery search. The client will regularly check the gallery and download any new files behind the scenes, just as if you were running the download yourself.</p>
<p>Subscriptions are a way of telling the client to quietly and regularly repeat a gallery search. The client will sync with the gallery and download any new files behind the scenes, just as if you were running the download yourself.</p>
<p>You can set up a subscription for any of the gallery websites in the normal <i>new page->download->gallery</i> menu.</p>
<p>Here's the dialog, which is under <i>services->manage subscriptions</i>:</p>
<p><img src="subs_dialog.png" /></p>
@ -19,12 +19,11 @@
<li>It has never run before and has found as many files as the 'initial sync file limit'.</li>
<li>It has run before and discovers a url it has previously seen.</li>
</ul>
<p>Since I have set it to stop after 10, it will finish quickly, which is fine for this example.</p>
<p>Once it has found enough urls, it will go into them and strip out the file and any tags you have set it.</p>
<p>Once it has finished adding urls, it will visit each new one in turn and strip out the file and any tags you have set it to parse. <b>Urls it has checked in previous runs will not be rechecked, and tags will not be retroactively fetched.</b></p>
<h3>when they run</h3>
<p>When a subscription runs, it will show a popup message:</p>
<p><img src="subs_popup.png" /></p>
<p>You don't really have to care about this all that much; it just lets you know what it is doing. The 'show x files' button is useful just to quickly make sure it is getting what you meant it to. Once it is done, it will compress down and wait for you to dismiss it with a right click.</p>
<p>You don't really have to care about this all that much; it just lets you know what it is doing. The 'show x files' button is useful just to quickly make sure it is getting what you meant it to. Once it is done, it will collapse down and wait for you to dismiss it with a right click.</p>
<p>Serious errors, like server 404s, are recovered from as gracefully as possible. The client will retry those subscriptions the next day.</p>
<p>Here's the result of the subscription I set up above:</p>
<p><img src="subs_import_done.png" /></p>

View File

@ -39,7 +39,7 @@
<p>If you lose your admin access key, there is no way to get it back, and if you are not sqlite-proficient, you'll have to restart from the beginning by deleting your server's database files.</p>
<p>If the client can't connect to the server, it is either not running or you have a firewall/port-mapping problem. If you want a quick way to test the server's visibility, just put its host:port into your browser; if working, it should return some simple html identifying itself.</p>
<h3>set up the server</h3>
<p>You should notice a new menu, 'admin', in the client gui. This is where you control most server and service-wide stuff.</p>
<p>You should have a new submenu, 'administrate services', under 'services', in the client gui. This is where you control most server and service-wide stuff.</p>
<p><i>admin->your server->manage services</i> lets you add, edit, and delete the services your server runs. Every time you add one, you will also be added as that service's first administrator, and the admin menu will gain a new entry for it.</i>
<h3>making accounts</h3>
<p>Go <i>admin->your service->create new accounts</i> to create new registration keys. Send the registration keys to the users you want to give these new accounts. A registration key will only work once, so if you want to give several people the same account, they will have to share the access key amongst themselves once one of them has registered the account. (Or you can register the account yourself and send them all the same access key. Do what you like!)</p>

View File

@ -1350,7 +1350,7 @@ class TagParentsManager( object ):
for parent in parents:
parent_predicate = ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, parent )
parent_predicate = ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, parent )
results.append( parent_predicate )
@ -1543,7 +1543,7 @@ class TagSiblingsManager( object ):
( old_pred_type, old_value, old_inclusive ) = old_predicate.GetInfo()
new_predicate = ClientData.Predicate( old_pred_type, new_tag, inclusive = old_inclusive )
new_predicate = ClientSearch.Predicate( old_pred_type, new_tag, inclusive = old_inclusive )
tags_to_predicates[ new_tag ] = new_predicate

View File

@ -389,6 +389,11 @@ class Controller( HydrusController.HydrusController ):
return self._client_files_manager
def GetClientSessionManager( self ):
return self._client_session_manager
def GetDB( self ): return self._db
def GetGUI( self ): return self._gui
@ -425,7 +430,8 @@ class Controller( HydrusController.HydrusController ):
self._client_files_manager = ClientCaches.ClientFilesManager( self )
self._managers[ 'hydrus_sessions' ] = ClientCaches.HydrusSessionManager( self )
self._client_session_manager = ClientCaches.HydrusSessionManager( self )
self._managers[ 'local_booru' ] = ClientCaches.LocalBooruCache( self )
self._managers[ 'tag_censorship' ] = ClientCaches.TagCensorshipManager( self )
self._managers[ 'tag_siblings' ] = ClientCaches.TagSiblingsManager( self )

View File

@ -1763,50 +1763,47 @@ class DB( HydrusDB.HydrusDB ):
job_key.SetVariable( 'popup_text_1', prefix + 'deleting internal orphan information' )
perceptual_hash_ids = { hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM perceptual_hashes;' ) }
hash_ids = { hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM files_info;' ) }
perceptual_deletees = perceptual_hash_ids - hash_ids
self._c.execute( 'DELETE FROM perceptual_hashes WHERE hash_id IN ' + HydrusData.SplayListForDB( perceptual_deletees ) + ';' )
self._c.execute( 'DELETE FROM perceptual_hashes WHERE hash_id NOT IN SELECT hash_id FROM files_info;' )
job_key.SetVariable( 'popup_text_1', prefix + 'gathering thumbnail information' )
local_thumbnail_hashes = ClientFiles.GetAllThumbnailHashes()
hashes = set( self._GetHashes( hash_ids ) )
job_key.SetVariable( 'popup_text_1', prefix + 'deleting orphan thumbnails' )
for hash in local_thumbnail_hashes - hashes:
for hash in ClientFiles.IterateAllThumbnailHashes():
path = ClientFiles.GetExpectedThumbnailPath( hash, True )
resized_path = ClientFiles.GetExpectedThumbnailPath( hash, False )
hash_id = self._GetHashId( hash )
( i_paused, should_quit ) = job_key.WaitIfNeeded()
result = self._c.execute( 'SELECT 1 FROM files_info WHERE hash_id = ?;', ( hash_id, ) ).fetchone()
if should_quit:
if result is None:
return
path = ClientFiles.GetExpectedThumbnailPath( hash, True )
resized_path = ClientFiles.GetExpectedThumbnailPath( hash, False )
try:
( i_paused, should_quit ) = job_key.WaitIfNeeded()
if os.path.exists( path ):
if should_quit:
ClientData.DeletePath( path )
return
if os.path.exists( resized_path ):
try:
ClientData.DeletePath( resized_path )
if os.path.exists( path ):
ClientData.DeletePath( path )
if os.path.exists( resized_path ):
ClientData.DeletePath( resized_path )
except OSError:
HydrusData.Print( 'In trying to delete the orphan ' + path + ' or ' + resized_path + ', this error was encountered:' )
HydrusData.Print( traceback.format_exc() )
except OSError:
HydrusData.Print( 'In trying to delete the orphan ' + path + ' or ' + resized_path + ', this error was encountered:' )
HydrusData.Print( traceback.format_exc() )
@ -2009,7 +2006,7 @@ class DB( HydrusDB.HydrusDB ):
( archive_hash, ) = result
tags = { namespace + ':' + tag if namespace != '' else tag for ( namespace, tag ) in self._c.execute( 'SELECT namespace, tag FROM namespaces, ( tags, mappings USING ( tag_id ) ) USING ( namespace_id ) WHERE hash_id = ? AND service_id = ? AND status IN ( ?, ? );', ( hash_id, service_id, HC.CURRENT, HC.PENDING ) ) }
tags = { HydrusTags.CombineTag( namespace, tag ) for ( namespace, tag ) in self._c.execute( 'SELECT namespace, tag FROM namespaces, ( tags, mappings USING ( tag_id ) ) USING ( namespace_id ) WHERE hash_id = ? AND service_id = ? AND status IN ( ?, ? );', ( hash_id, service_id, HC.CURRENT, HC.PENDING ) ) }
hta.AddMappings( archive_hash, tags )
@ -2282,7 +2279,7 @@ class DB( HydrusDB.HydrusDB ):
filtered_tags = tag_censorship_manager.FilterTags( tag_service_key, tags_to_do )
predicates = [ ClientData.Predicate( HC.PREDICATE_TYPE_TAG, tag, counts = { HC.CURRENT : current_count, HC.PENDING : pending_count } ) for ( tag, current_count, pending_count ) in tag_info if tag in filtered_tags ]
predicates = [ ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, tag, counts = { HC.CURRENT : current_count, HC.PENDING : pending_count } ) for ( tag, current_count, pending_count ) in tag_info if tag in filtered_tags ]
return predicates
@ -2326,16 +2323,16 @@ class DB( HydrusDB.HydrusDB ):
predicates = []
if service_type in ( HC.COMBINED_FILE, HC.COMBINED_TAG ): predicates.extend( [ ClientData.Predicate( predicate_type, None ) for predicate_type in [ HC.PREDICATE_TYPE_SYSTEM_EVERYTHING, HC.PREDICATE_TYPE_SYSTEM_UNTAGGED, HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, HC.PREDICATE_TYPE_SYSTEM_LIMIT, HC.PREDICATE_TYPE_SYSTEM_HASH ] ] )
if service_type in ( HC.COMBINED_FILE, HC.COMBINED_TAG ): predicates.extend( [ ClientSearch.Predicate( predicate_type, None ) for predicate_type in [ HC.PREDICATE_TYPE_SYSTEM_EVERYTHING, HC.PREDICATE_TYPE_SYSTEM_UNTAGGED, HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, HC.PREDICATE_TYPE_SYSTEM_LIMIT, HC.PREDICATE_TYPE_SYSTEM_HASH ] ] )
elif service_type in ( HC.TAG_REPOSITORY, HC.LOCAL_TAG ):
service_info = self._GetServiceInfoSpecific( service_id, service_type, { HC.SERVICE_INFO_NUM_FILES } )
num_everything = service_info[ HC.SERVICE_INFO_NUM_FILES ]
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_EVERYTHING, None, counts = { HC.CURRENT : num_everything } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_EVERYTHING, None, counts = { HC.CURRENT : num_everything } ) )
predicates.extend( [ ClientData.Predicate( predicate_type, None ) for predicate_type in [ HC.PREDICATE_TYPE_SYSTEM_UNTAGGED, HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, HC.PREDICATE_TYPE_SYSTEM_LIMIT, HC.PREDICATE_TYPE_SYSTEM_HASH ] ] )
predicates.extend( [ ClientSearch.Predicate( predicate_type, None ) for predicate_type in [ HC.PREDICATE_TYPE_SYSTEM_UNTAGGED, HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, HC.PREDICATE_TYPE_SYSTEM_LIMIT, HC.PREDICATE_TYPE_SYSTEM_HASH ] ] )
elif service_type in ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ):
@ -2354,27 +2351,27 @@ class DB( HydrusDB.HydrusDB ):
num_archive = num_local - num_inbox
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_EVERYTHING, None, counts = { HC.CURRENT : num_everything } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_EVERYTHING, None, counts = { HC.CURRENT : num_everything } ) )
if num_inbox > 0:
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_INBOX, None, counts = { HC.CURRENT : num_inbox } ) )
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_ARCHIVE, None, counts = { HC.CURRENT : num_archive } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_INBOX, None, counts = { HC.CURRENT : num_inbox } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_ARCHIVE, None, counts = { HC.CURRENT : num_archive } ) )
if service_type == HC.FILE_REPOSITORY:
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_LOCAL, None, counts = { HC.CURRENT : num_local } ) )
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_NOT_LOCAL, None, counts = { HC.CURRENT : num_not_local } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_LOCAL, None, counts = { HC.CURRENT : num_local } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_NOT_LOCAL, None, counts = { HC.CURRENT : num_not_local } ) )
predicates.extend( [ ClientData.Predicate( predicate_type, None ) for predicate_type in [ HC.PREDICATE_TYPE_SYSTEM_UNTAGGED, HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, HC.PREDICATE_TYPE_SYSTEM_LIMIT, HC.PREDICATE_TYPE_SYSTEM_SIZE, HC.PREDICATE_TYPE_SYSTEM_AGE, HC.PREDICATE_TYPE_SYSTEM_HASH, HC.PREDICATE_TYPE_SYSTEM_DIMENSIONS, HC.PREDICATE_TYPE_SYSTEM_DURATION, HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS, HC.PREDICATE_TYPE_SYSTEM_MIME ] ] )
predicates.extend( [ ClientSearch.Predicate( predicate_type, None ) for predicate_type in [ HC.PREDICATE_TYPE_SYSTEM_UNTAGGED, HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, HC.PREDICATE_TYPE_SYSTEM_LIMIT, HC.PREDICATE_TYPE_SYSTEM_SIZE, HC.PREDICATE_TYPE_SYSTEM_AGE, HC.PREDICATE_TYPE_SYSTEM_HASH, HC.PREDICATE_TYPE_SYSTEM_DIMENSIONS, HC.PREDICATE_TYPE_SYSTEM_DURATION, HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS, HC.PREDICATE_TYPE_SYSTEM_MIME ] ] )
ratings_service_ids = self._GetServiceIds( HC.RATINGS_SERVICES )
if len( ratings_service_ids ) > 0: predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_RATING, None ) )
if len( ratings_service_ids ) > 0: predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_RATING, None ) )
predicates.extend( [ ClientData.Predicate( predicate_type, None ) for predicate_type in [ HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO, HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE ] ] )
predicates.extend( [ ClientSearch.Predicate( predicate_type, None ) for predicate_type in [ HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO, HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE ] ] )
return predicates
@ -3153,9 +3150,9 @@ class DB( HydrusDB.HydrusDB ):
hash_ids_to_hashes = self._GetHashIdsToHashes( hash_ids )
hash_ids_to_tags = HydrusData.BuildKeyToListDict( [ ( hash_id, ( service_id, ( status, namespace + ':' + tag ) ) ) if namespace != '' else ( hash_id, ( service_id, ( status, tag ) ) ) for ( hash_id, service_id, namespace, tag, status ) in self._c.execute( 'SELECT hash_id, service_id, namespace, tag, status FROM namespaces, ( tags, mappings USING ( tag_id ) ) USING ( namespace_id ) WHERE hash_id IN ' + splayed_hash_ids + ';' ) ] )
hash_ids_to_tags = HydrusData.BuildKeyToListDict( [ ( hash_id, ( service_id, ( status, HydrusTags.CombineTag( namespace, tag ) ) ) ) for ( hash_id, service_id, namespace, tag, status ) in self._c.execute( 'SELECT hash_id, service_id, namespace, tag, status FROM namespaces, ( tags, mappings USING ( tag_id ) ) USING ( namespace_id ) WHERE hash_id IN ' + splayed_hash_ids + ';' ) ] )
hash_ids_to_petitioned_tags = HydrusData.BuildKeyToListDict( [ ( hash_id, ( service_id, ( HC.PETITIONED, namespace + ':' + tag ) ) ) if namespace != '' else ( hash_id, ( service_id, ( HC.PETITIONED, tag ) ) ) for ( hash_id, service_id, namespace, tag ) in self._c.execute( 'SELECT hash_id, service_id, namespace, tag FROM namespaces, ( tags, mapping_petitions USING ( tag_id ) ) USING ( namespace_id ) WHERE hash_id IN ' + splayed_hash_ids + ';' ) ] )
hash_ids_to_petitioned_tags = HydrusData.BuildKeyToListDict( [ ( hash_id, ( service_id, ( HC.PETITIONED, HydrusTags.CombineTag( namespace, tag ) ) ) ) for ( hash_id, service_id, namespace, tag ) in self._c.execute( 'SELECT hash_id, service_id, namespace, tag FROM namespaces, ( tags, mapping_petitions USING ( tag_id ) ) USING ( namespace_id ) WHERE hash_id IN ' + splayed_hash_ids + ';' ) ] )
for ( hash_id, tag_data ) in hash_ids_to_petitioned_tags.items(): hash_ids_to_tags[ hash_id ].extend( tag_data )
@ -3299,7 +3296,10 @@ class DB( HydrusDB.HydrusDB ):
( tag, ) = result
if namespace_id == 1: return tag
if namespace_id == 1:
return HydrusTags.CombineTag( '', tag )
else:
result = self._c.execute( 'SELECT namespace FROM namespaces WHERE namespace_id = ?;', ( namespace_id, ) ).fetchone()
@ -3308,7 +3308,7 @@ class DB( HydrusDB.HydrusDB ):
( namespace, ) = result
return namespace + ':' + tag
return HydrusTags.CombineTag( namespace, tag )
@ -6181,6 +6181,18 @@ class DB( HydrusDB.HydrusDB ):
if version == 184:
result = self._c.execute( 'SELECT tag_id FROM tags WHERE tag = ?;', ( '', ) ).fetchone()
if result is not None:
( tag_id, ) = result
self._c.execute( 'DELETE FROM mappings WHERE tag_id = ?;', ( tag_id, ) )
self._controller.pub( 'splash_set_title_text', 'updating db to v' + str( version + 1 ) )
self._c.execute( 'UPDATE version SET version = ?;', ( version + 1, ) )

View File

@ -366,6 +366,11 @@ class ClientOptions( HydrusSerialisable.SerialisableBase ):
self._dictionary[ 'booleans' ][ 'apply_all_parents_to_all_services' ] = False
self._dictionary[ 'booleans' ][ 'apply_all_siblings_to_all_services' ] = False
self._dictionary[ 'booleans' ][ 'waiting_politely_text' ] = False
self._dictionary[ 'noneable_integers' ] = {}
self._dictionary[ 'noneable_integers' ][ 'forced_search_limit' ] = None
self._dictionary[ 'client_files_locations_ideal_weights' ] = [ ( HydrusPaths.ConvertAbsPathToPortablePath( HC.CLIENT_FILES_DIR ), 1.0 ) ]
@ -376,7 +381,14 @@ class ClientOptions( HydrusSerialisable.SerialisableBase ):
for ( key, value ) in loaded_dictionary.items():
self._dictionary[ key ] = value
if isinstance( value, dict ):
self._dictionary[ key ].update( value )
else:
self._dictionary[ key ] = value
@ -398,16 +410,19 @@ class ClientOptions( HydrusSerialisable.SerialisableBase ):
def GetClientFilesLocationsToIdealWeights( self ):
result = {}
for ( portable_path, weight ) in self._dictionary[ 'client_files_locations_ideal_weights' ]:
with self._lock:
abs_path = HydrusPaths.ConvertPortablePathToAbsPath( portable_path )
result = {}
result[ abs_path ] = weight
for ( portable_path, weight ) in self._dictionary[ 'client_files_locations_ideal_weights' ]:
abs_path = HydrusPaths.ConvertPortablePathToAbsPath( portable_path )
result[ abs_path ] = weight
return result
return result
def GetDefaultImportTagOptions( self, gallery_identifier = None ):
@ -486,6 +501,14 @@ class ClientOptions( HydrusSerialisable.SerialisableBase ):
def GetNoneableInteger( self, name ):
with self._lock:
return self._dictionary[ 'noneable_integers' ][ name ]
def SetBoolean( self, name, value ):
with self._lock:
@ -496,9 +519,12 @@ class ClientOptions( HydrusSerialisable.SerialisableBase ):
def SetClientFilesLocationsToIdealWeights( self, locations_to_weights ):
portable_locations_and_weights = [ ( HydrusPaths.ConvertAbsPathToPortablePath( location ), float( weight ) ) for ( location, weight ) in locations_to_weights.items() ]
self._dictionary[ 'client_files_locations_ideal_weights' ] = portable_locations_and_weights
with self._lock:
portable_locations_and_weights = [ ( HydrusPaths.ConvertAbsPathToPortablePath( location ), float( weight ) ) for ( location, weight ) in locations_to_weights.items() ]
self._dictionary[ 'client_files_locations_ideal_weights' ] = portable_locations_and_weights
def SetDefaultImportTagOptions( self, gallery_identifier, import_tag_options ):
@ -509,8 +535,55 @@ class ClientOptions( HydrusSerialisable.SerialisableBase ):
def SetNoneableInteger( self, name, value ):
with self._lock:
self._dictionary[ 'noneable_integers' ][ name ] = value
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_CLIENT_OPTIONS ] = ClientOptions
class CommandHandler( object ):
def __init__( self, action_cache ):
self._action_cache = action_cache
self._commands_to_callables = {}
def ProcessMenuEvent( self, menu_event ):
event_id = menu_event.GetId()
action = self._action_cache.GetAction( event_id )
if action is not None:
( command, data ) = action
if command in self._commands_to_callables:
callable = self._commands_to_callables[ command ]
if data is None:
wx.CallAfter( callable )
else:
wx.CallAfter( callable, data )
def SetCallable( self, command, callable ):
self._commands_to_callables[ command ] = callable
class Credentials( HydrusData.HydrusYAMLBase ):
yaml_tag = u'!Credentials'
@ -553,464 +626,6 @@ class Credentials( HydrusData.HydrusYAMLBase ):
def SetAccessKey( self, access_key ): self._access_key = access_key
class FileQueryResult( object ):
def __init__( self, media_results ):
self._hashes_to_media_results = { media_result.GetHash() : media_result for media_result in media_results }
self._hashes_ordered = [ media_result.GetHash() for media_result in media_results ]
self._hashes = set( self._hashes_ordered )
HydrusGlobals.client_controller.sub( self, 'ProcessContentUpdates', 'content_updates_data' )
HydrusGlobals.client_controller.sub( self, 'ProcessServiceUpdates', 'service_updates_data' )
def __iter__( self ):
for hash in self._hashes_ordered: yield self._hashes_to_media_results[ hash ]
def __len__( self ): return len( self._hashes_ordered )
def _Remove( self, hashes ):
for hash in hashes:
if hash in self._hashes_to_media_results:
del self._hashes_to_media_results[ hash ]
self._hashes_ordered.remove( hash )
self._hashes.difference_update( hashes )
def AddMediaResults( self, media_results ):
for media_result in media_results:
hash = media_result.GetHash()
if hash in self._hashes: continue # this is actually important, as sometimes we don't want the media result overwritten
self._hashes_to_media_results[ hash ] = media_result
self._hashes_ordered.append( hash )
self._hashes.add( hash )
def GetHashes( self ): return self._hashes
def GetMediaResult( self, hash ): return self._hashes_to_media_results[ hash ]
def GetMediaResults( self ): return [ self._hashes_to_media_results[ hash ] for hash in self._hashes_ordered ]
def ProcessContentUpdates( self, service_keys_to_content_updates ):
for ( service_key, content_updates ) in service_keys_to_content_updates.items():
for content_update in content_updates:
hashes = content_update.GetHashes()
if len( hashes ) > 0:
for hash in self._hashes.intersection( hashes ):
media_result = self._hashes_to_media_results[ hash ]
media_result.ProcessContentUpdate( service_key, content_update )
def ProcessServiceUpdates( self, service_keys_to_service_updates ):
for ( service_key, service_updates ) in service_keys_to_service_updates.items():
for service_update in service_updates:
( action, row ) = service_update.ToTuple()
if action == HC.SERVICE_UPDATE_DELETE_PENDING:
for media_result in self._hashes_to_media_results.values(): media_result.DeletePending( service_key )
elif action == HC.SERVICE_UPDATE_RESET:
for media_result in self._hashes_to_media_results.values(): media_result.ResetService( service_key )
class FileSearchContext( HydrusSerialisable.SerialisableBase ):
SERIALISABLE_TYPE = HydrusSerialisable.SERIALISABLE_TYPE_FILE_SEARCH_CONTEXT
SERIALISABLE_VERSION = 1
def __init__( self, file_service_key = CC.COMBINED_FILE_SERVICE_KEY, tag_service_key = CC.COMBINED_TAG_SERVICE_KEY, include_current_tags = True, include_pending_tags = True, predicates = None ):
if predicates is None: predicates = []
self._file_service_key = file_service_key
self._tag_service_key = tag_service_key
self._include_current_tags = include_current_tags
self._include_pending_tags = include_pending_tags
self._predicates = predicates
self._search_complete = False
self._InitialiseTemporaryVariables()
def _GetSerialisableInfo( self ):
serialisable_predicates = [ predicate.GetSerialisableTuple() for predicate in self._predicates ]
return ( self._file_service_key.encode( 'hex' ), self._tag_service_key.encode( 'hex' ), self._include_current_tags, self._include_pending_tags, serialisable_predicates, self._search_complete )
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
( file_service_key, tag_service_key, self._include_current_tags, self._include_pending_tags, serialisable_predicates, self._search_complete ) = serialisable_info
self._file_service_key = file_service_key.decode( 'hex' )
self._tag_service_key = tag_service_key.decode( 'hex' )
self._predicates = [ HydrusSerialisable.CreateFromSerialisableTuple( pred_tuple ) for pred_tuple in serialisable_predicates ]
self._InitialiseTemporaryVariables()
def _InitialiseTemporaryVariables( self ):
system_predicates = [ predicate for predicate in self._predicates if predicate.GetType() in HC.SYSTEM_PREDICATES ]
self._system_predicates = FileSystemPredicates( system_predicates )
tag_predicates = [ predicate for predicate in self._predicates if predicate.GetType() == HC.PREDICATE_TYPE_TAG ]
self._tags_to_include = []
self._tags_to_exclude = []
for predicate in tag_predicates:
tag = predicate.GetValue()
if predicate.GetInclusive(): self._tags_to_include.append( tag )
else: self._tags_to_exclude.append( tag )
namespace_predicates = [ predicate for predicate in self._predicates if predicate.GetType() == HC.PREDICATE_TYPE_NAMESPACE ]
self._namespaces_to_include = []
self._namespaces_to_exclude = []
for predicate in namespace_predicates:
namespace = predicate.GetValue()
if predicate.GetInclusive(): self._namespaces_to_include.append( namespace )
else: self._namespaces_to_exclude.append( namespace )
wildcard_predicates = [ predicate for predicate in self._predicates if predicate.GetType() == HC.PREDICATE_TYPE_WILDCARD ]
self._wildcards_to_include = []
self._wildcards_to_exclude = []
for predicate in wildcard_predicates:
wildcard = predicate.GetValue()
if predicate.GetInclusive(): self._wildcards_to_include.append( wildcard )
else: self._wildcards_to_exclude.append( wildcard )
def GetFileServiceKey( self ): return self._file_service_key
def GetNamespacesToExclude( self ): return self._namespaces_to_exclude
def GetNamespacesToInclude( self ): return self._namespaces_to_include
def GetPredicates( self ): return self._predicates
def GetSystemPredicates( self ): return self._system_predicates
def GetTagServiceKey( self ): return self._tag_service_key
def GetTagsToExclude( self ): return self._tags_to_exclude
def GetTagsToInclude( self ): return self._tags_to_include
def GetWildcardsToExclude( self ): return self._wildcards_to_exclude
def GetWildcardsToInclude( self ): return self._wildcards_to_include
def IncludeCurrentTags( self ): return self._include_current_tags
def IncludePendingTags( self ): return self._include_pending_tags
def IsComplete( self ): return self._search_complete
def SetComplete( self ): self._search_complete = True
def SetPredicates( self, predicates ):
self._predicates = predicates
self._InitialiseTemporaryVariables()
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_FILE_SEARCH_CONTEXT ] = FileSearchContext
class FileSystemPredicates( object ):
def __init__( self, system_predicates ):
self._inbox = False
self._archive = False
self._local = False
self._not_local = False
self._common_info = {}
self._limit = None
self._similar_to = None
self._file_services_to_include_current = []
self._file_services_to_include_pending = []
self._file_services_to_exclude_current = []
self._file_services_to_exclude_pending = []
self._ratings_predicates = []
for predicate in system_predicates:
predicate_type = predicate.GetType()
value = predicate.GetValue()
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_INBOX: self._inbox = True
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_ARCHIVE: self._archive = True
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_LOCAL: self._local = True
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_NOT_LOCAL: self._not_local = True
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_HASH:
hash = value
self._common_info[ 'hash' ] = hash
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_AGE:
( operator, years, months, days, hours ) = value
age = ( ( ( ( ( ( ( years * 12 ) + months ) * 30 ) + days ) * 24 ) + hours ) * 3600 )
now = HydrusData.GetNow()
# this is backwards because we are talking about age, not timestamp
if operator == '<': self._common_info[ 'min_timestamp' ] = now - age
elif operator == '>': self._common_info[ 'max_timestamp' ] = now - age
elif operator == u'\u2248':
self._common_info[ 'min_timestamp' ] = now - int( age * 1.15 )
self._common_info[ 'max_timestamp' ] = now - int( age * 0.85 )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_MIME:
mimes = value
if type( mimes ) == int: mimes = ( mimes, )
self._common_info[ 'mimes' ] = mimes
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_DURATION:
( operator, duration ) = value
if operator == '<': self._common_info[ 'max_duration' ] = duration
elif operator == '>': self._common_info[ 'min_duration' ] = duration
elif operator == '=': self._common_info[ 'duration' ] = duration
elif operator == u'\u2248':
if duration == 0: self._common_info[ 'duration' ] = 0
else:
self._common_info[ 'min_duration' ] = int( duration * 0.85 )
self._common_info[ 'max_duration' ] = int( duration * 1.15 )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_RATING:
( operator, value, service_key ) = value
self._ratings_predicates.append( ( operator, value, service_key ) )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_RATIO:
( operator, ratio_width, ratio_height ) = value
if operator == '=': self._common_info[ 'ratio' ] = ( ratio_width, ratio_height )
elif operator == u'\u2248':
self._common_info[ 'min_ratio' ] = ( ratio_width * 0.85, ratio_height )
self._common_info[ 'max_ratio' ] = ( ratio_width * 1.15, ratio_height )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIZE:
( operator, size, unit ) = value
size = size * unit
if operator == '<': self._common_info[ 'max_size' ] = size
elif operator == '>': self._common_info[ 'min_size' ] = size
elif operator == '=': self._common_info[ 'size' ] = size
elif operator == u'\u2248':
self._common_info[ 'min_size' ] = int( size * 0.85 )
self._common_info[ 'max_size' ] = int( size * 1.15 )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS:
( operator, num_tags ) = value
if operator == '<': self._common_info[ 'max_num_tags' ] = num_tags
elif operator == '=': self._common_info[ 'num_tags' ] = num_tags
elif operator == '>': self._common_info[ 'min_num_tags' ] = num_tags
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_WIDTH:
( operator, width ) = value
if operator == '<': self._common_info[ 'max_width' ] = width
elif operator == '>': self._common_info[ 'min_width' ] = width
elif operator == '=': self._common_info[ 'width' ] = width
elif operator == u'\u2248':
if width == 0: self._common_info[ 'width' ] = 0
else:
self._common_info[ 'min_width' ] = int( width * 0.85 )
self._common_info[ 'max_width' ] = int( width * 1.15 )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_PIXELS:
( operator, num_pixels, unit ) = value
num_pixels = num_pixels * unit
if operator == '<': self._common_info[ 'max_num_pixels' ] = num_pixels
elif operator == '>': self._common_info[ 'min_num_pixels' ] = num_pixels
elif operator == '=': self._common_info[ 'num_pixels' ] = num_pixels
elif operator == u'\u2248':
self._common_info[ 'min_num_pixels' ] = int( num_pixels * 0.85 )
self._common_info[ 'max_num_pixels' ] = int( num_pixels * 1.15 )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_HEIGHT:
( operator, height ) = value
if operator == '<': self._common_info[ 'max_height' ] = height
elif operator == '>': self._common_info[ 'min_height' ] = height
elif operator == '=': self._common_info[ 'height' ] = height
elif operator == u'\u2248':
if height == 0: self._common_info[ 'height' ] = 0
else:
self._common_info[ 'min_height' ] = int( height * 0.85 )
self._common_info[ 'max_height' ] = int( height * 1.15 )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS:
( operator, num_words ) = value
if operator == '<': self._common_info[ 'max_num_words' ] = num_words
elif operator == '>': self._common_info[ 'min_num_words' ] = num_words
elif operator == '=': self._common_info[ 'num_words' ] = num_words
elif operator == u'\u2248':
if num_words == 0: self._common_info[ 'num_words' ] = 0
else:
self._common_info[ 'min_num_words' ] = int( num_words * 0.85 )
self._common_info[ 'max_num_words' ] = int( num_words * 1.15 )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_LIMIT:
limit = value
self._limit = limit
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE:
( operator, current_or_pending, service_key ) = value
if operator == True:
if current_or_pending == HC.CURRENT: self._file_services_to_include_current.append( service_key )
else: self._file_services_to_include_pending.append( service_key )
else:
if current_or_pending == HC.CURRENT: self._file_services_to_exclude_current.append( service_key )
else: self._file_services_to_exclude_pending.append( service_key )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO:
( hash, max_hamming ) = value
self._similar_to = ( hash, max_hamming )
def GetFileServiceInfo( self ): return ( self._file_services_to_include_current, self._file_services_to_include_pending, self._file_services_to_exclude_current, self._file_services_to_exclude_pending )
def GetSimpleInfo( self ): return self._common_info
def GetLimit( self ): return self._limit
def GetRatingsPredicates( self ): return self._ratings_predicates
def GetSimilarTo( self ): return self._similar_to
def HasSimilarTo( self ): return self._similar_to is not None
def MustBeArchive( self ): return self._archive
def MustBeInbox( self ): return self._inbox
def MustBeLocal( self ): return self._local
def MustNotBeLocal( self ): return self._not_local
class Imageboard( HydrusData.HydrusYAMLBase ):
yaml_tag = u'!Imageboard'
@ -1242,387 +857,6 @@ class ImportTagOptions( HydrusSerialisable.SerialisableBase ):
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_TAG_OPTIONS ] = ImportTagOptions
class Predicate( HydrusSerialisable.SerialisableBase ):
SERIALISABLE_TYPE = HydrusSerialisable.SERIALISABLE_TYPE_PREDICATE
SERIALISABLE_VERSION = 1
def __init__( self, predicate_type = None, value = None, inclusive = True, counts = None ):
if counts is None: counts = {}
if type( value ) == list:
value = tuple( value )
self._predicate_type = predicate_type
self._value = value
self._inclusive = inclusive
self._counts = {}
self._counts[ HC.CURRENT ] = 0
self._counts[ HC.PENDING ] = 0
for ( current_or_pending, count ) in counts.items(): self.AddToCount( current_or_pending, count )
def __eq__( self, other ):
return self.__hash__() == other.__hash__()
def __hash__( self ):
return ( self._predicate_type, self._value ).__hash__()
def __ne__( self, other ):
return self.__hash__() != other.__hash__()
def __repr__( self ):
return 'Predicate: ' + HydrusData.ToUnicode( ( self._predicate_type, self._value, self._counts ) )
def _GetSerialisableInfo( self ):
if self._predicate_type in ( HC.PREDICATE_TYPE_SYSTEM_RATING, HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE ):
( operator, value, service_key ) = self._value
serialisable_value = ( operator, value, service_key.encode( 'hex' ) )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO:
( hash, max_hamming ) = self._value
serialisable_value = ( hash.encode( 'hex' ), max_hamming )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_HASH:
hash = self._value
serialisable_value = hash.encode( 'hex' )
else:
serialisable_value = self._value
return ( self._predicate_type, serialisable_value, self._inclusive )
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
( self._predicate_type, serialisable_value, self._inclusive ) = serialisable_info
if self._predicate_type in ( HC.PREDICATE_TYPE_SYSTEM_RATING, HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE ):
( operator, value, service_key ) = serialisable_value
self._value = ( operator, value, service_key.decode( 'hex' ) )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO:
( serialisable_hash, max_hamming ) = serialisable_value
self._value = ( serialisable_hash.decode( 'hex' ), max_hamming )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_HASH:
self._value = serialisable_value.decode( 'hex' )
else:
self._value = serialisable_value
if type( self._value ) == list:
self._value = tuple( self._value )
def AddToCount( self, current_or_pending, count ): self._counts[ current_or_pending ] += count
def GetCopy( self ): return Predicate( self._predicate_type, self._value, self._inclusive, self._counts )
def GetCountlessCopy( self ): return Predicate( self._predicate_type, self._value, self._inclusive )
def GetCount( self, current_or_pending = None ):
if current_or_pending is None: return sum( self._counts.values() )
else: return self._counts[ current_or_pending ]
def GetInclusive( self ):
# patch from an upgrade mess-up ~v144
if not hasattr( self, '_inclusive' ):
if self._predicate_type not in HC.SYSTEM_PREDICATES:
( operator, value ) = self._value
self._value = value
self._inclusive = operator == '+'
else: self._inclusive = True
return self._inclusive
def GetInfo( self ): return ( self._predicate_type, self._value, self._inclusive )
def GetType( self ): return self._predicate_type
def GetUnicode( self, with_count = True ):
count_text = u''
if with_count:
if self._counts[ HC.CURRENT ] > 0: count_text += u' (' + HydrusData.ConvertIntToPrettyString( self._counts[ HC.CURRENT ] ) + u')'
if self._counts[ HC.PENDING ] > 0: count_text += u' (+' + HydrusData.ConvertIntToPrettyString( self._counts[ HC.PENDING ] ) + u')'
if self._predicate_type in HC.SYSTEM_PREDICATES:
if self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_EVERYTHING: base = u'system:everything'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_INBOX: base = u'system:inbox'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_ARCHIVE: base = u'system:archive'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_UNTAGGED: base = u'system:untagged'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_LOCAL: base = u'system:local'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_NOT_LOCAL: base = u'system:not local'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_DIMENSIONS: base = u'system:dimensions'
elif self._predicate_type in ( HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, HC.PREDICATE_TYPE_SYSTEM_WIDTH, HC.PREDICATE_TYPE_SYSTEM_HEIGHT, HC.PREDICATE_TYPE_SYSTEM_DURATION, HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS ):
if self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS: base = u'system:number of tags'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_WIDTH: base = u'system:width'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_HEIGHT: base = u'system:height'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_DURATION: base = u'system:duration'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS: base = u'system:number of words'
if self._value is not None:
( operator, value ) = self._value
base += u' ' + operator + u' ' + HydrusData.ConvertIntToPrettyString( value )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_RATIO:
base = u'system:ratio'
if self._value is not None:
( operator, ratio_width, ratio_height ) = self._value
base += u' ' + operator + u' ' + str( ratio_width ) + u':' + str( ratio_height )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIZE:
base = u'system:size'
if self._value is not None:
( operator, size, unit ) = self._value
base += u' ' + operator + u' ' + str( size ) + HydrusData.ConvertIntToUnit( unit )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_LIMIT:
base = u'system:limit'
if self._value is not None:
value = self._value
base += u' is ' + HydrusData.ConvertIntToPrettyString( value )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_AGE:
base = u'system:age'
if self._value is not None:
( operator, years, months, days, hours ) = self._value
base += u' ' + operator + u' ' + str( years ) + u'y' + str( months ) + u'm' + str( days ) + u'd' + str( hours ) + u'h'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_PIXELS:
base = u'system:num_pixels'
if self._value is not None:
( operator, num_pixels, unit ) = self._value
base += u' ' + operator + u' ' + str( num_pixels ) + ' ' + HydrusData.ConvertIntToPixels( unit )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_HASH:
base = u'system:hash'
if self._value is not None:
hash = self._value
base += u' is ' + hash.encode( 'hex' )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_MIME:
base = u'system:mime'
if self._value is not None:
mimes = self._value
if set( mimes ) == set( HC.SEARCHABLE_MIMES ):
mime_text = 'anything'
elif set( mimes ) == set( HC.SEARCHABLE_MIMES ).intersection( set( HC.APPLICATIONS ) ):
mime_text = 'application'
elif set( mimes ) == set( HC.SEARCHABLE_MIMES ).intersection( set( HC.AUDIO ) ):
mime_text = 'audio'
elif set( mimes ) == set( HC.SEARCHABLE_MIMES ).intersection( set( HC.IMAGES ) ):
mime_text = 'image'
elif set( mimes ) == set( HC.SEARCHABLE_MIMES ).intersection( set( HC.VIDEO ) ):
mime_text = 'video'
else:
mime_text = ', '.join( [ HC.mime_string_lookup[ mime ] for mime in mimes ] )
base += u' is ' + mime_text
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_RATING:
base = u'system:rating'
if self._value is not None:
( operator, value, service_key ) = self._value
service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key )
base += u' for ' + service.GetName() + u' ' + operator + u' ' + HydrusData.ToUnicode( value )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO:
base = u'system:similar to'
if self._value is not None:
( hash, max_hamming ) = self._value
base += u' ' + hash.encode( 'hex' ) + u' using max hamming of ' + str( max_hamming )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE:
base = u'system:'
if self._value is None:
base += 'file service'
else:
( operator, current_or_pending, service_key ) = self._value
if operator == True: base += u'is'
else: base += u'is not'
if current_or_pending == HC.PENDING: base += u' pending to '
else: base += u' currently in '
service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key )
base += service.GetName()
base += count_text
elif self._predicate_type == HC.PREDICATE_TYPE_TAG:
tag = self._value
if not self._inclusive: base = u'-'
else: base = u''
base += tag
base += count_text
siblings_manager = HydrusGlobals.client_controller.GetManager( 'tag_siblings' )
sibling = siblings_manager.GetSibling( tag )
if sibling is not None: base += u' (will display as ' + sibling + ')'
elif self._predicate_type == HC.PREDICATE_TYPE_PARENT:
base = ' '
tag = self._value
base += tag
base += count_text
elif self._predicate_type == HC.PREDICATE_TYPE_NAMESPACE:
namespace = self._value
if not self._inclusive: base = u'-'
else: base = u''
base += namespace + u':*anything*'
elif self._predicate_type == HC.PREDICATE_TYPE_WILDCARD:
wildcard = self._value
if not self._inclusive: base = u'-'
else: base = u''
base += wildcard
return base
def GetValue( self ): return self._value
def SetInclusive( self, inclusive ): self._inclusive = inclusive
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_PREDICATE ] = Predicate
class Service( HydrusData.HydrusYAMLBase ):
yaml_tag = u'!Service'
@ -1937,7 +1171,7 @@ class Service( HydrusData.HydrusYAMLBase ):
if isinstance( e, HydrusExceptions.SessionException ):
session_manager = HydrusGlobals.client_controller.GetManager( 'hydrus_sessions' )
session_manager = HydrusGlobals.client_controller.GetClientSessionManager()
session_manager.DeleteSessionKey( self._service_key )

View File

@ -135,6 +135,11 @@ def GetImageboardThreadURLs( thread_url ):
try:
if '#' in thread_url:
( thread_url, post_anchor_gumpf ) = thread_url.split( '#', 1 )
parse_result = urlparse.urlparse( thread_url )
host = parse_result.hostname
@ -148,7 +153,10 @@ def GetImageboardThreadURLs( thread_url ):
is_4chan = '4chan.org' in host
is_8chan = '8chan.co' in host or '8ch.net' in host
if not ( is_4chan or is_8chan ): raise Exception( 'This only works for 4chan and 8chan right now!' )
if not ( is_4chan or is_8chan ):
raise Exception( 'This only works for 4chan and 8chan right now!' )
try:
@ -180,7 +188,10 @@ def GetImageboardThreadURLs( thread_url ):
file_base = 'http://8ch.net/' + board + '/src/'
except: raise Exception( 'Could not understand the board or thread id!' )
except:
raise Exception( 'Could not understand the board or thread id!' )
return ( json_url, file_base )

View File

@ -42,7 +42,7 @@ ID_TIMER_UPDATES = wx.NewId()
# Sizer Flags
MENU_ORDER = [ 'file', 'undo', 'view', 'search', 'download', 'database', 'pending', 'services', 'admin', 'help' ]
MENU_ORDER = [ 'file', 'undo', 'pages', 'database', 'pending', 'services', 'help' ]
class FrameGUI( ClientGUICommon.FrameThatResizes ):
@ -639,40 +639,6 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
menu.AppendMenu( CC.ID_NULL, p( 'Open' ), open )
menu.AppendSeparator()
gui_session_names = self._controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_GUI_SESSION )
sessions = wx.Menu()
if len( gui_session_names ) > 0:
load = wx.Menu()
for name in gui_session_names:
load.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'load_gui_session', name ), name )
sessions.AppendMenu( CC.ID_NULL, p( 'Load' ), load )
sessions.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'save_gui_session' ), p( 'Save Current' ) )
if len( gui_session_names ) > 0:
delete = wx.Menu()
for name in gui_session_names:
delete.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'delete_gui_session', name ), name )
sessions.AppendMenu( CC.ID_NULL, p( 'Delete' ), delete )
menu.AppendMenu( CC.ID_NULL, p( 'Sessions' ), sessions )
menu.AppendSeparator()
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'options' ), p( '&Options' ) )
menu.AppendSeparator()
@ -746,17 +712,50 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
return ( menu, p( '&Undo' ), show )
def view():
def pages():
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'refresh' ), p( '&Refresh' ), p( 'Refresh the current view.' ) )
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'show_hide_splitters' ), p( 'Show/Hide Splitters' ), p( 'Show or hide the current page\'s splitters.' ) )
menu.AppendSeparator()
gui_session_names = self._controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_GUI_SESSION )
sessions = wx.Menu()
if len( gui_session_names ) > 0:
load = wx.Menu()
for name in gui_session_names:
load.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'load_gui_session', name ), name )
sessions.AppendMenu( CC.ID_NULL, p( 'Load' ), load )
sessions.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'save_gui_session' ), p( 'Save Current' ) )
if len( gui_session_names ) > 0:
delete = wx.Menu()
for name in gui_session_names:
delete.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'delete_gui_session', name ), name )
sessions.AppendMenu( CC.ID_NULL, p( 'Delete' ), delete )
menu.AppendMenu( CC.ID_NULL, p( 'Sessions' ), sessions )
menu.AppendSeparator()
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_page' ), p( 'Pick a New &Page' ), p( 'Pick a new page.' ) )
return ( menu, p( '&View' ), True )
#
def search():
search_menu = wx.Menu()
services = self._controller.GetServicesManager().GetServices()
@ -768,24 +767,37 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
petition_resolve_file_services = [ repository for repository in file_repositories if repository.GetInfo( 'account' ).HasPermission( HC.RESOLVE_PETITIONS ) ]
menu = wx.Menu()
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_page_query', CC.LOCAL_FILE_SERVICE_KEY ), p( '&New Local Search' ), p( 'Open a new search tab for your files' ) )
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_page_query', CC.TRASH_SERVICE_KEY ), p( '&New Trash Search' ), p( 'Open a new search tab for your recently deleted files' ) )
for service in file_repositories: menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_page_query', service.GetServiceKey() ), p( 'New ' + service.GetName() + ' Search' ), p( 'Open a new search tab for ' + service.GetName() + '.' ) )
search_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_page_query', CC.LOCAL_FILE_SERVICE_KEY ), p( '&New Local Search' ), p( 'Open a new search tab for your files' ) )
search_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_page_query', CC.TRASH_SERVICE_KEY ), p( '&New Trash Search' ), p( 'Open a new search tab for your recently deleted files' ) )
for service in file_repositories: search_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_page_query', service.GetServiceKey() ), p( 'New ' + service.GetName() + ' Search' ), p( 'Open a new search tab for ' + service.GetName() + '.' ) )
menu.AppendMenu( CC.ID_NULL, p( 'New Search Page' ), search_menu )
#
if len( petition_resolve_tag_services ) > 0 or len( petition_resolve_file_services ) > 0:
menu.AppendSeparator()
for service in petition_resolve_tag_services: menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'petitions', service.GetServiceKey() ), p( service.GetName() + ' Petitions' ), p( 'Open a petition tab for ' + service.GetName() ) )
for service in petition_resolve_file_services: menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'petitions', service.GetServiceKey() ), p( service.GetName() + ' Petitions' ), p( 'Open a petition tab for ' + service.GetName() ) )
petition_menu = wx.Menu()
for service in petition_resolve_tag_services:
petition_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'petitions', service.GetServiceKey() ), p( service.GetName() + ' Petitions' ), p( 'Open a petition tab for ' + service.GetName() ) )
for service in petition_resolve_file_services:
petition_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'petitions', service.GetServiceKey() ), p( service.GetName() + ' Petitions' ), p( 'Open a petition tab for ' + service.GetName() ) )
menu.AppendMenu( CC.ID_NULL, p( 'New Petition Page' ), petition_menu )
return ( menu, p( '&Search' ), True )
#
def download():
download_menu = wx.Menu()
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_import_page_of_images' ), p( '&New Page of Images Download Page' ), p( 'Open a new tab to download files from generic galleries or threads.' ) )
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_import_thread_watcher' ), p( '&New Thread Watcher Page' ), p( 'Open a new tab to watch a thread.' ) )
download_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_import_page_of_images' ), p( '&New Page of Images Download Page' ), p( 'Open a new tab to download files from generic galleries or threads.' ) )
download_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_import_thread_watcher' ), p( '&New Thread Watcher Page' ), p( 'Open a new tab to watch a thread.' ) )
submenu = wx.Menu()
@ -810,13 +822,17 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_import_gallery', HC.SITE_TYPE_TUMBLR ), p( 'Tumblr' ), p( 'Open a new tab to download files from Tumblr.' ) )
menu.AppendMenu( CC.ID_NULL, p( '&New Gallery Download Page' ), submenu )
download_menu.AppendMenu( CC.ID_NULL, p( '&New Gallery Download Page' ), submenu )
menu.AppendSeparator()
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'start_youtube_download' ), p( '&A YouTube Video' ), p( 'Enter a YouTube URL and choose which formats you would like to download' ) )
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'start_url_download' ), p( '&A Raw URL' ), p( 'Enter a normal URL and attempt to import whatever is returned' ) )
download_menu.AppendSeparator()
download_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'start_youtube_download' ), p( '&A YouTube Video' ), p( 'Enter a YouTube URL and choose which formats you would like to download' ) )
download_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'start_url_download' ), p( '&A Raw URL' ), p( 'Enter a normal URL and attempt to import whatever is returned' ) )
return ( menu, p( 'Do&wnload' ), True )
menu.AppendMenu( CC.ID_NULL, p( 'New Download Page' ), download_menu )
#
return ( menu, p( '&Pages' ), True )
def database():
@ -910,6 +926,72 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
menu.AppendSeparator()
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'review_services' ), p( '&Review Services' ), p( 'Look at the services your client connects to.' ) )
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'manage_services' ), p( '&Manage Services' ), p( 'Edit the services your client connects to.' ) )
tag_repositories = self._controller.GetServicesManager().GetServices( ( HC.TAG_REPOSITORY, ) )
admin_tag_services = [ repository for repository in tag_repositories if repository.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ]
file_repositories = self._controller.GetServicesManager().GetServices( ( HC.FILE_REPOSITORY, ) )
admin_file_services = [ repository for repository in file_repositories if repository.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ]
servers_admin = self._controller.GetServicesManager().GetServices( ( HC.SERVER_ADMIN, ) )
server_admins = [ service for service in servers_admin if service.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ]
if len( admin_tag_services ) > 0 or len( admin_file_services ) > 0 or len( server_admins ) > 0:
admin_menu = wx.Menu()
for service in admin_tag_services:
submenu = wx.Menu()
service_key = service.GetServiceKey()
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_accounts', service_key ), p( 'Create New &Accounts' ), p( 'Create new accounts.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'manage_account_types', service_key ), p( '&Manage Account Types' ), p( 'Add, edit and delete account types for the tag repository.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'modify_account', service_key ), p( '&Modify an Account' ), p( 'Modify a specific account\'s type and expiration.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'account_info', service_key ), p( '&Get an Account\'s Info' ), p( 'Fetch information about an account from the tag repository.' ) )
submenu.AppendSeparator()
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'stats', service_key ), p( '&Get Stats' ), p( 'Fetch operating statistics from the tag repository.' ) )
submenu.AppendSeparator()
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'post_news', service_key ), p( '&Post News' ), p( 'Post a news item to the tag repository.' ) )
admin_menu.AppendMenu( CC.ID_NULL, p( service.GetName() ), submenu )
for service in admin_file_services:
submenu = wx.Menu()
service_key = service.GetServiceKey()
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_accounts', service_key ), p( 'Create New &Accounts' ), p( 'Create new accounts.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'manage_account_types', service_key ), p( '&Manage Account Types' ), p( 'Add, edit and delete account types for the file repository.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'modify_account', service_key ), p( '&Modify an Account' ), p( 'Modify a specific account\'s type and expiration.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'account_info', service_key ), p( '&Get an Account\'s Info' ), p( 'Fetch information about an account from the file repository.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'fetch_ip', service_key ), p( '&Get an Uploader\'s IP Address' ), p( 'Fetch an uploader\'s ip address.' ) )
submenu.AppendSeparator()
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'stats', service_key ), p( '&Get Stats' ), p( 'Fetch operating statistics from the file repository.' ) )
submenu.AppendSeparator()
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'post_news', service_key ), p( '&Post News' ), p( 'Post a news item to the file repository.' ) )
admin_menu.AppendMenu( CC.ID_NULL, p( service.GetName() ), submenu )
for service in server_admins:
submenu = wx.Menu()
service_key = service.GetServiceKey()
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'manage_server_services', service_key ), p( 'Manage &Services' ), p( 'Add, edit, and delete this server\'s services.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'backup_service', service_key ), p( 'Make a &Backup' ), p( 'Back up this server\'s database.' ) )
admin_menu.AppendMenu( CC.ID_NULL, p( service.GetName() ), submenu )
menu.AppendMenu( CC.ID_NULL, p( 'Administrate Services' ), admin_menu )
menu.AppendSeparator()
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'manage_tag_censorship' ), p( '&Manage Tag Censorship' ), p( 'Set which tags you want to see from which services.' ) )
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'manage_tag_siblings' ), p( '&Manage Tag Siblings' ), p( 'Set certain tags to be automatically replaced with other tags.' ) )
@ -935,75 +1017,6 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
return ( menu, p( '&Services' ), True )
def admin():
tag_repositories = self._controller.GetServicesManager().GetServices( ( HC.TAG_REPOSITORY, ) )
admin_tag_services = [ repository for repository in tag_repositories if repository.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ]
file_repositories = self._controller.GetServicesManager().GetServices( ( HC.FILE_REPOSITORY, ) )
admin_file_services = [ repository for repository in file_repositories if repository.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ]
servers_admin = self._controller.GetServicesManager().GetServices( ( HC.SERVER_ADMIN, ) )
server_admins = [ service for service in servers_admin if service.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ]
if len( admin_tag_services ) > 0 or len( admin_file_services ) > 0 or len( server_admins ) > 0:
show = True
for service in admin_tag_services:
submenu = wx.Menu()
service_key = service.GetServiceKey()
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_accounts', service_key ), p( 'Create New &Accounts' ), p( 'Create new accounts.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'manage_account_types', service_key ), p( '&Manage Account Types' ), p( 'Add, edit and delete account types for the tag repository.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'modify_account', service_key ), p( '&Modify an Account' ), p( 'Modify a specific account\'s type and expiration.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'account_info', service_key ), p( '&Get an Account\'s Info' ), p( 'Fetch information about an account from the tag repository.' ) )
submenu.AppendSeparator()
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'stats', service_key ), p( '&Get Stats' ), p( 'Fetch operating statistics from the tag repository.' ) )
submenu.AppendSeparator()
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'post_news', service_key ), p( '&Post News' ), p( 'Post a news item to the tag repository.' ) )
menu.AppendMenu( CC.ID_NULL, p( service.GetName() ), submenu )
for service in admin_file_services:
submenu = wx.Menu()
service_key = service.GetServiceKey()
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_accounts', service_key ), p( 'Create New &Accounts' ), p( 'Create new accounts.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'manage_account_types', service_key ), p( '&Manage Account Types' ), p( 'Add, edit and delete account types for the file repository.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'modify_account', service_key ), p( '&Modify an Account' ), p( 'Modify a specific account\'s type and expiration.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'account_info', service_key ), p( '&Get an Account\'s Info' ), p( 'Fetch information about an account from the file repository.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'fetch_ip', service_key ), p( '&Get an Uploader\'s IP Address' ), p( 'Fetch an uploader\'s ip address.' ) )
submenu.AppendSeparator()
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'stats', service_key ), p( '&Get Stats' ), p( 'Fetch operating statistics from the file repository.' ) )
submenu.AppendSeparator()
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'post_news', service_key ), p( '&Post News' ), p( 'Post a news item to the file repository.' ) )
menu.AppendMenu( CC.ID_NULL, p( service.GetName() ), submenu )
for service in server_admins:
submenu = wx.Menu()
service_key = service.GetServiceKey()
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'manage_server_services', service_key ), p( 'Manage &Services' ), p( 'Add, edit, and delete this server\'s services.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'backup_service', service_key ), p( 'Make a &Backup' ), p( 'Back up this server\'s database.' ) )
menu.AppendMenu( CC.ID_NULL, p( service.GetName() ), submenu )
else: show = False
return( menu, p( '&Admin' ), show )
def help():
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'help' ), p( '&Help' ) )
@ -1049,13 +1062,10 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
if name == 'file': return file()
elif name == 'undo': return undo()
elif name == 'view': return view()
elif name == 'download': return download()
elif name == 'pages': return pages()
elif name == 'database': return database()
elif name == 'pending': return pending()
elif name == 'search': return search()
elif name == 'services': return services()
elif name == 'admin': return admin()
elif name == 'help': return help()
@ -1360,7 +1370,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
search_enabled = len( initial_media_results ) == 0
file_search_context = ClientData.FileSearchContext( file_service_key = file_service_key, predicates = initial_predicates )
file_search_context = ClientSearch.FileSearchContext( file_service_key = file_service_key, predicates = initial_predicates )
management_controller = ClientGUIManagement.CreateManagementControllerQuery( file_service_key, file_search_context, search_enabled )
@ -2311,7 +2321,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
hamming_distance = HC.options[ 'file_system_predicates' ][ 'hamming_distance' ]
initial_predicates = [ ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO, ( hash, hamming_distance ) ) ]
initial_predicates = [ ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO, ( hash, hamming_distance ) ) ]
self._NewPageQuery( file_service_key, initial_predicates = initial_predicates )
@ -2327,18 +2337,17 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
def NotifyNewPermissions( self ):
self.RefreshMenu( 'search' )
self.RefreshMenu( 'admin' )
self.RefreshMenu( 'pages' )
self.RefreshMenu( 'services' )
def NotifyNewServices( self ):
self.RefreshMenu( 'search' )
self.RefreshMenu( 'pages' )
self.RefreshMenu( 'services' )
self.RefreshMenu( 'admin' )
def NotifyNewSessions( self ): self.RefreshMenu( 'file' )
def NotifyNewSessions( self ): self.RefreshMenu( 'pages' )
def NotifyNewUndo( self ): self.RefreshMenu( 'undo' )

View File

@ -60,7 +60,7 @@ def FlushOutPredicates( parent, predicates ):
elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_UNTAGGED:
good_predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, ( '=', 0 ) ) )
good_predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, ( '=', 0 ) ) )
else:
@ -843,7 +843,16 @@ class AutoCompleteDropdownTagsRead( AutoCompleteDropdownTags ):
search_text = HydrusTags.CleanTag( search_text )
entry_predicate = ClientData.Predicate( HC.PREDICATE_TYPE_TAG, search_text, inclusive = inclusive )
siblings_manager = HydrusGlobals.client_controller.GetManager( 'tag_siblings' )
sibling = siblings_manager.GetSibling( search_text )
if sibling is not None:
search_text = sibling
entry_predicate = ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, search_text, inclusive = inclusive )
return ( inclusive, search_text, entry_predicate )
@ -973,7 +982,7 @@ class AutoCompleteDropdownTagsRead( AutoCompleteDropdownTags ):
if self._include_current: tags_to_do.update( current_tags_to_count.keys() )
if self._include_pending: tags_to_do.update( pending_tags_to_count.keys() )
predicates = [ ClientData.Predicate( HC.PREDICATE_TYPE_TAG, tag, inclusive = inclusive, counts = { HC.CURRENT : current_tags_to_count[ tag ], HC.PENDING : pending_tags_to_count[ tag ] } ) for tag in tags_to_do ]
predicates = [ ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, tag, inclusive = inclusive, counts = { HC.CURRENT : current_tags_to_count[ tag ], HC.PENDING : pending_tags_to_count[ tag ] } ) for tag in tags_to_do ]
predicates = siblings_manager.CollapsePredicates( predicates )
@ -991,20 +1000,20 @@ class AutoCompleteDropdownTagsRead( AutoCompleteDropdownTags ):
if '*' not in self._current_namespace:
matches.insert( 0, ClientData.Predicate( HC.PREDICATE_TYPE_NAMESPACE, self._current_namespace, inclusive = inclusive ) )
matches.insert( 0, ClientSearch.Predicate( HC.PREDICATE_TYPE_NAMESPACE, self._current_namespace, inclusive = inclusive ) )
if half_complete_tag != '':
if '*' in self._current_namespace or ( '*' in half_complete_tag and half_complete_tag != '*' ):
matches.insert( 0, ClientData.Predicate( HC.PREDICATE_TYPE_WILDCARD, search_text, inclusive = inclusive ) )
matches.insert( 0, ClientSearch.Predicate( HC.PREDICATE_TYPE_WILDCARD, search_text, inclusive = inclusive ) )
elif '*' in search_text:
matches.insert( 0, ClientData.Predicate( HC.PREDICATE_TYPE_WILDCARD, search_text, inclusive = inclusive ) )
matches.insert( 0, ClientSearch.Predicate( HC.PREDICATE_TYPE_WILDCARD, search_text, inclusive = inclusive ) )
@ -1043,7 +1052,7 @@ class AutoCompleteDropdownTagsRead( AutoCompleteDropdownTags ):
def GetFileSearchContext( self ):
return ClientData.FileSearchContext( file_service_key = self._file_service_key, tag_service_key = self._tag_service_key, include_current_tags = self._include_current, include_pending_tags = self._include_pending )
return ClientSearch.FileSearchContext( file_service_key = self._file_service_key, tag_service_key = self._tag_service_key, include_current_tags = self._include_current, include_pending_tags = self._include_pending )
def IncludeCurrent( self, page_key, value ):
@ -1137,7 +1146,7 @@ class AutoCompleteDropdownTagsWrite( AutoCompleteDropdownTags ):
search_text = HydrusTags.CleanTag( raw_entry )
entry_predicate = ClientData.Predicate( HC.PREDICATE_TYPE_TAG, search_text )
entry_predicate = ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, search_text )
siblings_manager = HydrusGlobals.client_controller.GetManager( 'tag_siblings' )
@ -1145,7 +1154,7 @@ class AutoCompleteDropdownTagsWrite( AutoCompleteDropdownTags ):
if sibling is not None:
sibling_predicate = ClientData.Predicate( HC.PREDICATE_TYPE_TAG, sibling )
sibling_predicate = ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, sibling )
else:
@ -1168,14 +1177,7 @@ class AutoCompleteDropdownTagsWrite( AutoCompleteDropdownTags ):
return
if sibling_predicate is not None:
self._BroadcastChoices( { sibling_predicate } )
else:
self._BroadcastChoices( { entry_predicate } )
self._BroadcastChoices( { entry_predicate } )
def _GenerateMatches( self ):
@ -1248,42 +1250,42 @@ class AutoCompleteDropdownTagsWrite( AutoCompleteDropdownTags ):
def _PutAtTopOfMatches( self, matches, predicate ):
parents = []
try:
index = matches.index( predicate )
predicate = matches[ index ]
matches.remove( predicate )
while matches[ index ].GetType() == HC.PREDICATE_TYPE_PARENT:
parent = matches[ index ]
matches.remove( parent )
parents.append( parent )
except:
if predicate.GetType() == HC.PREDICATE_TYPE_TAG:
tag = predicate.GetValue()
parents_manager = HydrusGlobals.client_controller.GetManager( 'tag_parents' )
raw_parents = parents_manager.GetParents( self._tag_service_key, tag )
parents = [ ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, raw_parent ) for raw_parent in raw_parents ]
if self._expand_parents:
parents = []
try:
index = matches.index( predicate )
predicate = matches[ index ]
matches.remove( predicate )
while matches[ index ].GetType() == HC.PREDICATE_TYPE_PARENT:
parent = matches[ index ]
matches.remove( parent )
parents.append( parent )
except:
if predicate.GetType() == HC.PREDICATE_TYPE_TAG:
tag = predicate.GetValue()
parents_manager = HydrusGlobals.client_controller.GetManager( 'tag_parents' )
raw_parents = parents_manager.GetParents( self._tag_service_key, tag )
parents = [ ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, raw_parent ) for raw_parent in raw_parents ]
parents.reverse()
for parent in parents:
@ -2272,6 +2274,41 @@ class ListBox( wx.ScrolledWindow ):
return row_index
def _GetSelectedIncludeExcludePredicates( self ):
include_predicates = []
exclude_predicates = []
for term in self._selected_terms:
if type( term ) == ClientSearch.Predicate:
predicate_type = term.GetType()
if predicate_type in ( HC.PREDICATE_TYPE_TAG, HC.PREDICATE_TYPE_NAMESPACE, HC.PREDICATE_TYPE_WILDCARD ):
value = term.GetValue()
include_predicates.append( ClientSearch.Predicate( predicate_type, value ) )
exclude_predicates.append( ClientSearch.Predicate( predicate_type, value, inclusive = False ) )
else:
include_predicates.append( term )
else:
s = term
include_predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, term ) )
exclude_predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, term, inclusive = False ) )
return ( include_predicates, exclude_predicates )
def _GetTextColour( self, text ): return ( 0, 111, 250 )
def _Hit( self, shift, ctrl, hit_index ):
@ -2636,6 +2673,8 @@ class ListBoxTags( ListBox ):
ListBox.__init__( self, *args, **kwargs )
self._predicates_callable = None
self._background_colour = wx.Colour( *HC.options[ 'gui_colours' ][ 'tags_box' ] )
self.Bind( wx.EVT_RIGHT_DOWN, self.EventMouseRightClick )
@ -2678,13 +2717,13 @@ class ListBoxTags( ListBox ):
for term in self._selected_terms:
if isinstance( term, ClientData.Predicate ):
if isinstance( term, ClientSearch.Predicate ):
predicates.append( term )
else:
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, term ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, term ) )
@ -2696,6 +2735,11 @@ class ListBoxTags( ListBox ):
def _ProcessMenuPredicateEvent( self, command ):
pass
def EventMenu( self, event ):
action = ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetAction( event.GetId() )
@ -2706,14 +2750,13 @@ class ListBoxTags( ListBox ):
if command in ( 'copy_terms', 'copy_sub_terms', 'copy_all_tags', 'copy_all_tags_with_counts' ):
if command in ( 'copy_terms', 'copy_sub_terms' ):
texts = []
for term in self._selected_terms:
if isinstance( term, ClientData.Predicate ):
if isinstance( term, ClientSearch.Predicate ):
text = term.GetUnicode()
@ -2745,6 +2788,10 @@ class ListBoxTags( ListBox ):
HydrusGlobals.client_controller.pub( 'clipboard', 'text', text )
elif command in ( 'add_include_predicates', 'remove_include_predicates', 'add_exclude_predicates', 'remove_exclude_predicates' ):
self._ProcessMenuPredicateEvent( command )
elif command == 'new_search_page':
self._NewSearchPage()
@ -2802,35 +2849,79 @@ class ListBoxTags( ListBox ):
( term, ) = self._selected_terms
if type( term ) == ClientData.Predicate:
if type( term ) == ClientSearch.Predicate:
s = term.GetUnicode()
if term.GetType() == HC.PREDICATE_TYPE_TAG:
selection_string = '"' + term.GetValue() + '"'
else:
selection_string = '"' + term.GetUnicode() + '"'
else:
s = term
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'new_search_page' ), 'open a new search page for ' + s )
menu.AppendSeparator()
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'copy_terms' ), 'copy "' + s + '"')
if ':' in s:
sub_s = s.split( ':', 1 )[1]
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'copy_sub_terms' ), 'copy "' + sub_s + '"' )
selection_string = '"' + term + '"'
else:
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'new_search_page' ), 'open a new search page for selection' )
selection_string = 'selected'
menu.AppendSeparator()
if self._predicates_callable is not None:
current_predicates = self._predicates_callable()
( include_predicates, exclude_predicates ) = self._GetSelectedIncludeExcludePredicates()
if current_predicates is not None:
if True in ( include_predicate in current_predicates for include_predicate in include_predicates ):
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'remove_include_predicates' ), 'discard ' + selection_string + ' from current search' )
if True in ( include_predicate not in current_predicates for include_predicate in include_predicates ):
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'add_include_predicates' ), 'require ' + selection_string + ' for current search' )
if True in ( exclude_predicate in current_predicates for exclude_predicate in exclude_predicates ):
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'remove_exclude_predicates' ), 'permit ' + selection_string + ' for current search' )
if True in ( exclude_predicate not in current_predicates for exclude_predicate in exclude_predicates ):
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'add_exclude_predicates' ), 'exclude ' + selection_string + ' from current search' )
if menu.GetMenuItemCount() > 0:
menu.AppendSeparator()
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'new_search_page' ), 'open a new search page for ' + selection_string )
menu.AppendSeparator()
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'copy_terms' ), 'copy ' + selection_string )
if len( self._selected_terms ) == 1:
if ':' in selection_string:
sub_selection_string = selection_string.split( ':', 1 )[1]
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'copy_sub_terms' ), 'copy ' + sub_selection_string )
else:
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'copy_terms' ), 'copy selected tags' )
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'copy_sub_terms' ), 'copy selected subtags' )
@ -3134,7 +3225,7 @@ class ListBoxTagsCensorship( ListBoxTags ):
if tag == '': return 'unnamespaced'
elif tag == ':': return 'namespaced'
else: return tag
else: return HydrusTags.RenderTag( tag )
def _RemoveTag( self, tag ):
@ -3277,11 +3368,12 @@ class ListBoxTagsColourOptions( ListBoxTags ):
class ListBoxTagsStrings( ListBoxTags ):
def __init__( self, parent, removed_callable = None ):
def __init__( self, parent, removed_callable = None, show_sibling_text = True ):
ListBoxTags.__init__( self, parent )
self._removed_callable = removed_callable
self._show_sibling_text = show_sibling_text
self._tags = set()
@ -3293,11 +3385,14 @@ class ListBoxTagsStrings( ListBoxTags ):
for tag in self._tags:
tag_string = tag
tag_string = HydrusTags.RenderTag( tag )
sibling = siblings_manager.GetSibling( tag )
if sibling is not None: tag_string += ' (will display as ' + sibling + ')'
if self._show_sibling_text:
sibling = siblings_manager.GetSibling( tag )
if sibling is not None: tag_string += ' (will display as ' + HydrusTags.RenderTag( sibling ) + ')'
self._strings_to_terms[ tag_string ] = tag
@ -3410,6 +3505,7 @@ class ListBoxTagsPredicates( ListBoxTags ):
ListBoxTags.__init__( self, parent, min_height = 100 )
self._page_key = page_key
self._predicates_callable = self.GetPredicates
if len( initial_predicates ) > 0:
@ -3435,19 +3531,13 @@ class ListBoxTagsPredicates( ListBoxTags ):
def _EnterPredicates( self, predicates ):
def _EnterPredicates( self, predicates, permit_add = True, permit_remove = True ):
if len( predicates ) == 0:
return
inbox_predicate = ClientSearch.SYSTEM_PREDICATE_INBOX
archive_predicate = ClientSearch.SYSTEM_PREDICATE_ARCHIVE
local_predicate = ClientSearch.SYSTEM_PREDICATE_LOCAL
not_local_predicate = ClientSearch.SYSTEM_PREDICATE_NOT_LOCAL
predicates_to_be_added = set()
predicates_to_be_removed = set()
@ -3457,28 +3547,23 @@ class ListBoxTagsPredicates( ListBoxTags ):
if self._HasPredicate( predicate ):
predicates_to_be_removed.add( predicate )
if permit_remove:
predicates_to_be_removed.add( predicate )
else:
predicates_to_be_added.add( predicate )
if predicate == inbox_predicate and self._HasPredicate( archive_predicate ):
if permit_add:
predicates_to_be_removed.add( archive_predicate )
predicates_to_be_added.add( predicate )
elif predicate == archive_predicate and self._HasPredicate( inbox_predicate ):
inverse_predicate = predicate.GetInverseCopy()
predicates_to_be_removed.add( inbox_predicate )
if predicate == local_predicate and self._HasPredicate( not_local_predicate ):
predicates_to_be_removed.add( not_local_predicate )
elif predicate == not_local_predicate and self._HasPredicate( local_predicate ):
predicates_to_be_removed.add( local_predicate )
if self._HasPredicate( inverse_predicate ):
predicates_to_be_removed.add( inverse_predicate )
@ -3519,11 +3604,33 @@ class ListBoxTagsPredicates( ListBoxTags ):
def _HasPredicate( self, predicate ): return predicate in self._strings_to_terms.values()
def EnterPredicates( self, page_key, predicates ):
def _ProcessMenuPredicateEvent( self, command ):
( include_predicates, exclude_predicates ) = self._GetSelectedIncludeExcludePredicates()
if command == 'add_include_predicates':
self._EnterPredicates( include_predicates, permit_remove = False )
elif command == 'remove_include_predicates':
self._EnterPredicates( include_predicates, permit_add = False )
elif command == 'add_exclude_predicates':
self._EnterPredicates( exclude_predicates, permit_remove = False )
elif command == 'remove_exclude_predicates':
self._EnterPredicates( exclude_predicates, permit_add = False )
def EnterPredicates( self, page_key, predicates, permit_add = True, permit_remove = True ):
if page_key == self._page_key:
self._EnterPredicates( predicates )
self._EnterPredicates( predicates, permit_add = permit_add, permit_remove = permit_remove )
@ -3593,7 +3700,7 @@ class ListBoxTagsSelection( ListBoxTags ):
for tag in all_tags:
tag_string = tag
tag_string = HydrusTags.RenderTag( tag )
if self._include_counts:
@ -3615,7 +3722,7 @@ class ListBoxTagsSelection( ListBoxTags ):
if sibling is not None:
tag_string += ' (will display as ' + sibling + ')'
tag_string += ' (will display as ' + HydrusTags.RenderTag( sibling ) + ')'
@ -3734,11 +3841,12 @@ class ListBoxTagsSelectionHoverFrame( ListBoxTagsSelection ):
class ListBoxTagsSelectionManagementPanel( ListBoxTagsSelection ):
def __init__( self, parent, page_key ):
def __init__( self, parent, page_key, predicates_callable = None ):
ListBoxTagsSelection.__init__( self, parent, include_counts = True, collapse_siblings = True )
self._page_key = page_key
self._predicates_callable = predicates_callable
HydrusGlobals.client_controller.sub( self, 'SetTagsByMediaPubsub', 'new_tags_selection' )
HydrusGlobals.client_controller.sub( self, 'ChangeTagRepositoryPubsub', 'change_tag_repository' )
@ -3746,7 +3854,7 @@ class ListBoxTagsSelectionManagementPanel( ListBoxTagsSelection ):
def _Activate( self ):
predicates = [ ClientData.Predicate( HC.PREDICATE_TYPE_TAG, term ) for term in self._selected_terms ]
predicates = [ ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, term ) for term in self._selected_terms ]
if len( predicates ) > 0:
@ -3754,6 +3862,28 @@ class ListBoxTagsSelectionManagementPanel( ListBoxTagsSelection ):
def _ProcessMenuPredicateEvent( self, command ):
( include_predicates, exclude_predicates ) = self._GetSelectedIncludeExcludePredicates()
if command == 'add_include_predicates':
HydrusGlobals.client_controller.pub( 'enter_predicates', self._page_key, include_predicates, permit_remove = False )
elif command == 'remove_include_predicates':
HydrusGlobals.client_controller.pub( 'enter_predicates', self._page_key, include_predicates, permit_add = False )
elif command == 'add_exclude_predicates':
HydrusGlobals.client_controller.pub( 'enter_predicates', self._page_key, exclude_predicates, permit_remove = False )
elif command == 'remove_exclude_predicates':
HydrusGlobals.client_controller.pub( 'enter_predicates', self._page_key, exclude_predicates, permit_add = False )
def ChangeTagRepositoryPubsub( self, page_key, service_key ):
if page_key == self._page_key: self.ChangeTagRepository( service_key )
@ -5733,6 +5863,132 @@ class StaticBoxSorterForListBoxTags( StaticBox ):
self._tags_box.SetTagsByMedia( media, force_reload = force_reload )
class TimeDeltaCtrl( wx.Panel ):
def __init__( self, parent, min = 1, days = False, hours = False, minutes = False, seconds = False ):
wx.Panel.__init__( self, parent )
self._min = min
self._show_days = days
self._show_hours = hours
self._show_minutes = minutes
self._show_seconds = seconds
hbox = wx.BoxSizer( wx.HORIZONTAL )
if self._show_days:
self._days = wx.SpinCtrl( self, min = 0, max = 360, size = ( 50, -1 ) )
self._days.Bind( wx.EVT_SPINCTRL, self.EventSpin )
hbox.AddF( self._days, CC.FLAGS_MIXED )
hbox.AddF( wx.StaticText( self, label = 'days' ), CC.FLAGS_MIXED )
if self._show_hours:
self._hours = wx.SpinCtrl( self, min = 0, max = 23, size = ( 45, -1 ) )
self._hours.Bind( wx.EVT_SPINCTRL, self.EventSpin )
hbox.AddF( self._hours, CC.FLAGS_MIXED )
hbox.AddF( wx.StaticText( self, label = 'hours' ), CC.FLAGS_MIXED )
if self._show_minutes:
self._minutes = wx.SpinCtrl( self, min = 0, max = 59, size = ( 45, -1 ) )
self._minutes.Bind( wx.EVT_SPINCTRL, self.EventSpin )
hbox.AddF( self._minutes, CC.FLAGS_MIXED )
hbox.AddF( wx.StaticText( self, label = 'minutes' ), CC.FLAGS_MIXED )
if self._show_seconds:
self._seconds = wx.SpinCtrl( self, min = 0, max = 59, size = ( 45, -1 ) )
self._seconds.Bind( wx.EVT_SPINCTRL, self.EventSpin )
hbox.AddF( self._seconds, CC.FLAGS_MIXED )
hbox.AddF( wx.StaticText( self, label = 'seconds' ), CC.FLAGS_MIXED )
self.SetSizer( hbox )
def EventSpin( self, event ):
value = self.GetValue()
if value < self._min:
self.SetValue( self._min )
wx.PostEvent( self, event )
def GetValue( self ):
value = 0
if self._show_days:
value += self._days.GetValue() * 86400
if self._show_hours:
value += self._hours.GetValue() * 3600
if self._show_minutes:
value += self._minutes.GetValue() * 60
if self._show_seconds:
value += self._seconds.GetValue()
return value
def SetValue( self, value ):
if value < self._min:
value = self._min
if self._show_days:
self._days.SetValue( value / 86400 )
value %= 86400
if self._show_hours:
self._hours.SetValue( value / 3600 )
value %= 3600
if self._show_minutes:
self._minutes.SetValue( value / 60 )
value %= 60
if self._show_seconds:
self._seconds.SetValue( value )
class RadioBox( StaticBox ):
def __init__( self, parent, title, choice_pairs, initial_index = None ):
@ -5846,7 +6102,40 @@ class ShowKeys( Frame ):
class WaitingPolitely( BufferedWindow ):
class WaitingPolitelyStaticText( wx.StaticText ):
def __init__( self, parent, page_key ):
wx.StaticText.__init__( self, parent, label = 'ready ' )
self._page_key = page_key
self._waiting = False
HydrusGlobals.client_controller.sub( self, 'SetWaitingPolitely', 'waiting_politely' )
self.SetWaitingPolitely( self._page_key, False )
def SetWaitingPolitely( self, page_key, value ):
if page_key == self._page_key:
self._waiting = value
if self._waiting:
self.SetLabel( 'waiting' )
self.SetToolTipString( 'waiting before attempting another download' )
else:
self.SetLabel( 'ready ' )
self.SetToolTipString( 'ready to download' )
class WaitingPolitelyTrafficLight( BufferedWindow ):
def __init__( self, parent, page_key ):
@ -5899,4 +6188,18 @@ class WaitingPolitely( BufferedWindow ):
self.Refresh()
def GetWaitingPolitelyControl( parent, page_key ):
new_options = HydrusGlobals.client_controller.GetNewOptions()
if new_options.GetBoolean( 'waiting_politely_text' ):
return WaitingPolitelyStaticText( parent, page_key )
else:
return WaitingPolitelyTrafficLight( parent, page_key )

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,7 @@ import ClientGUIPredicates
import ClientImporting
import ClientMedia
import ClientRatings
import ClientSearch
import collections
import HydrusConstants as HC
import HydrusData
@ -1504,7 +1505,7 @@ class DialogManageExportFolders( ClientGUIDialogs.Dialog ):
export_type = HC.EXPORT_FOLDER_TYPE_REGULAR
file_search_context = ClientData.FileSearchContext( file_service_key = CC.LOCAL_FILE_SERVICE_KEY )
file_search_context = ClientSearch.FileSearchContext( file_service_key = CC.LOCAL_FILE_SERVICE_KEY )
period = 15 * 60
phrase = '{hash}'
@ -1538,7 +1539,7 @@ class DialogManageExportFolders( ClientGUIDialogs.Dialog ):
pretty_file_search_context = ', '.join( predicate.GetUnicode( with_count = False ) for predicate in file_search_context.GetPredicates() )
pretty_period = str( period / 60 ) + ' minutes'
pretty_period = HydrusData.ConvertTimeDeltaToPrettyString( period )
pretty_phrase = phrase
@ -1658,13 +1659,11 @@ class DialogManageExportFoldersEdit( ClientGUIDialogs.Dialog ):
#
self._period_box = ClientGUICommon.StaticBox( self, 'export period (minutes)' )
self._period_box = ClientGUICommon.StaticBox( self, 'export period' )
self._period = wx.SpinCtrl( self._period_box )
self._period = ClientGUICommon.TimeDeltaCtrl( self._period_box, min = 3 * 60, days = True, hours = True, minutes = True )
self._period.SetRange( 3, 60 * 24 * 30 )
self._period.SetValue( period / 60 )
self._period.SetValue( period )
#
@ -1764,7 +1763,7 @@ If you select synchronise, be careful!'''
file_search_context.SetPredicates( predicates )
period = self._period.GetValue() * 60
period = self._period.GetValue()
phrase = self._pattern.GetValue()
@ -2598,7 +2597,7 @@ class DialogManageImportFolders( ClientGUIDialogs.Dialog ):
def _GetPrettyVariables( self, check_period ):
pretty_check_period = str( check_period / 60 ) + ' minutes'
pretty_check_period = HydrusData.ConvertTimeDeltaToPrettyString( check_period )
return pretty_check_period
@ -2726,7 +2725,7 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
self._open_popup = wx.CheckBox( self._folder_box )
self._period = wx.SpinCtrl( self._folder_box, min = 3, max = 60 * 24 * 30 )
self._period = ClientGUICommon.TimeDeltaCtrl( self._folder_box, min = 3 * 60, days = True, hours = True, minutes = True )
self._paused = wx.CheckBox( self._folder_box )
@ -2785,7 +2784,7 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
self._path.SetPath( path )
self._open_popup.SetValue( open_popup )
self._period.SetValue( period / 60 )
self._period.SetValue( period )
self._paused.SetValue( paused )
self._mimes.SetInfo( mimes )
@ -2829,7 +2828,7 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
gridbox.AddF( wx.StaticText( self._folder_box, label = 'folder path: '), CC.FLAGS_MIXED )
gridbox.AddF( self._path, CC.FLAGS_EXPAND_BOTH_WAYS )
gridbox.AddF( wx.StaticText( self._folder_box, label = 'check period (mins): '), CC.FLAGS_MIXED )
gridbox.AddF( wx.StaticText( self._folder_box, label = 'check period: '), CC.FLAGS_MIXED )
gridbox.AddF( self._period, CC.FLAGS_EXPAND_BOTH_WAYS )
gridbox.AddF( wx.StaticText( self._folder_box, label = 'currently paused: '), CC.FLAGS_MIXED )
@ -3036,7 +3035,7 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
action_locations[ CC.STATUS_FAILED ] = HydrusData.ToUnicode( self._location_failed.GetPath() )
period = self._period.GetValue() * 60
period = self._period.GetValue()
open_popup = self._open_popup.GetValue()
paused = self._paused.GetValue()
@ -3058,7 +3057,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
self._listbook.AddPage( 'connection', self._ConnectionPanel( self._listbook ) )
self._listbook.AddPage( 'files and trash', self._FilesAndTrashPanel( self._listbook ) )
self._listbook.AddPage( 'speed and memory', self._SpeedAndMemoryPanel( self._listbook ) )
self._listbook.AddPage( 'speed and memory', self._SpeedAndMemoryPanel( self._listbook, self._new_options ) )
self._listbook.AddPage( 'maintenance and processing', self._MaintenanceAndProcessingPanel( self._listbook ) )
self._listbook.AddPage( 'media', self._MediaPanel( self._listbook ) )
self._listbook.AddPage( 'gui', self._GUIPanel( self._listbook ) )
@ -3070,7 +3069,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
self._listbook.AddPage( 'sort/collect', self._SortCollectPanel( self._listbook ) )
self._listbook.AddPage( 'shortcuts', self._ShortcutsPanel( self._listbook ) )
self._listbook.AddPage( 'file storage locations', self._ClientFilesPanel( self._listbook ) )
self._listbook.AddPage( 'downloading', self._DownloadingPanel( self._listbook ) )
self._listbook.AddPage( 'downloading', self._DownloadingPanel( self._listbook, self._new_options ) )
self._listbook.AddPage( 'tags', self._TagsPanel( self._listbook, self._new_options ) )
self._ok = wx.Button( self, id = wx.ID_OK, label = 'Save' )
@ -3511,16 +3510,20 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
class _DownloadingPanel( wx.Panel ):
def __init__( self, parent ):
def __init__( self, parent, new_options ):
wx.Panel.__init__( self, parent )
self._new_options = new_options
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
general = ClientGUICommon.StaticBox( self, 'general' )
self._website_download_polite_wait = wx.SpinCtrl( general, min = 1, max = 30 )
self._waiting_politely_text = wx.CheckBox( general )
#
gallery_downloader = ClientGUICommon.StaticBox( self, 'gallery downloader' )
@ -3534,12 +3537,13 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
self._thread_times_to_check = wx.SpinCtrl( thread_checker, min = 0, max = 100 )
self._thread_times_to_check.SetToolTipString( 'how many times the thread checker will check' )
self._thread_check_period = wx.SpinCtrl( thread_checker, min = 30, max = 86400 )
self._thread_check_period = ClientGUICommon.TimeDeltaCtrl( thread_checker, min = 30, hours = True, minutes = True, seconds = True )
self._thread_check_period.SetToolTipString( 'how long the checker will wait between checks' )
#
self._website_download_polite_wait.SetValue( HC.options[ 'website_download_polite_wait' ] )
self._waiting_politely_text.SetValue( self._new_options.GetBoolean( 'waiting_politely_text' ) )
self._gallery_file_limit.SetValue( HC.options[ 'gallery_file_limit' ] )
@ -3558,6 +3562,9 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
gridbox.AddF( wx.StaticText( general, label = 'seconds to politely wait between gallery/thread url requests: ' ), CC.FLAGS_MIXED )
gridbox.AddF( self._website_download_polite_wait, CC.FLAGS_MIXED )
gridbox.AddF( wx.StaticText( general, label = 'instead of the traffic light waiting politely indicator, use text: ' ), CC.FLAGS_MIXED )
gridbox.AddF( self._waiting_politely_text, CC.FLAGS_MIXED )
general.AddF( gridbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
#
@ -3572,7 +3579,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
gridbox.AddF( wx.StaticText( thread_checker, label = 'default number of times to check: ' ), CC.FLAGS_MIXED )
gridbox.AddF( self._thread_times_to_check, CC.FLAGS_MIXED )
gridbox.AddF( wx.StaticText( thread_checker, label = 'default wait in seconds between checks: ' ), CC.FLAGS_MIXED )
gridbox.AddF( wx.StaticText( thread_checker, label = 'default wait between checks: ' ), CC.FLAGS_MIXED )
gridbox.AddF( self._thread_check_period, CC.FLAGS_MIXED )
thread_checker.AddF( gridbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
@ -3591,6 +3598,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
def UpdateOptions( self ):
HC.options[ 'website_download_polite_wait' ] = self._website_download_polite_wait.GetValue()
self._new_options.SetBoolean( 'waiting_politely_text', self._waiting_politely_text.GetValue() )
HC.options[ 'gallery_file_limit' ] = self._gallery_file_limit.GetValue()
HC.options[ 'thread_checker_timings' ] = ( self._thread_times_to_check.GetValue(), self._thread_check_period.GetValue() )
@ -4582,10 +4590,12 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
class _SpeedAndMemoryPanel( wx.Panel ):
def __init__( self, parent ):
def __init__( self, parent, new_options ):
wx.Panel.__init__( self, parent )
self._new_options = new_options
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
self._thumbnail_width = wx.SpinCtrl( self, min = 20, max = 200 )
@ -4609,6 +4619,8 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
self._estimated_number_fullscreens = wx.StaticText( self, label = '' )
self._forced_search_limit = ClientGUICommon.NoneableSpinCtrl( self, '', min = 1, max = 100000 )
self._num_autocomplete_chars = wx.SpinCtrl( self, min = 1, max = 100 )
self._num_autocomplete_chars.SetToolTipString( 'how many characters you enter before the gui fetches autocomplete results from the db. (otherwise, it will only fetch exact matches)' + os.linesep + 'increase this if you find autocomplete results are slow' )
@ -4638,6 +4650,8 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
self._fullscreen_cache_size.SetValue( int( HC.options[ 'fullscreen_cache_size' ] / 1048576 ) )
self._forced_search_limit.SetValue( self._new_options.GetNoneableInteger( 'forced_search_limit' ) )
self._num_autocomplete_chars.SetValue( HC.options[ 'num_autocomplete_chars' ] )
self._fetch_ac_results_automatically.SetValue( HC.options[ 'fetch_ac_results_automatically' ] )
@ -4704,6 +4718,15 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
gridbox.AddGrowableCol( 1, 1 )
gridbox.AddF( wx.StaticText( self, label = 'Forced system:limit for all searches: ' ), CC.FLAGS_MIXED )
gridbox.AddF( self._forced_search_limit, CC.FLAGS_NONE )
vbox.AddF( gridbox, CC.FLAGS_EXPAND_PERPENDICULAR )
gridbox = wx.FlexGridSizer( 0, 2 )
gridbox.AddGrowableCol( 1, 1 )
gridbox.AddF( wx.StaticText( self, label = 'Autocomplete character threshold: ' ), CC.FLAGS_MIXED )
gridbox.AddF( self._num_autocomplete_chars, CC.FLAGS_MIXED )
@ -4792,6 +4815,8 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
HC.options[ 'preview_cache_size' ] = self._preview_cache_size.GetValue() * 1048576
HC.options[ 'fullscreen_cache_size' ] = self._fullscreen_cache_size.GetValue() * 1048576
self._new_options.SetNoneableInteger( 'forced_search_limit', self._forced_search_limit.GetValue() )
HC.options[ 'num_autocomplete_chars' ] = self._num_autocomplete_chars.GetValue()
HC.options[ 'fetch_ac_results_automatically' ] = self._fetch_ac_results_automatically.GetValue()
@ -6891,6 +6916,10 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
#
text_hbox = wx.BoxSizer( wx.HORIZONTAL )
text_hbox.AddF( wx.StaticText( self, label = 'For more information about subscriptions, please check' ), CC.FLAGS_MIXED )
text_hbox.AddF( wx.HyperlinkCtrl( self, id = -1, label = 'here', url = 'file://' + HC.HELP_DIR + '/getting_started_subscriptions.html' ), CC.FLAGS_MIXED )
add_remove_hbox = wx.BoxSizer( wx.HORIZONTAL )
add_remove_hbox.AddF( self._add, CC.FLAGS_MIXED )
add_remove_hbox.AddF( self._remove, CC.FLAGS_MIXED )
@ -6901,6 +6930,7 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
ok_hbox.AddF( self._cancel, CC.FLAGS_MIXED )
vbox = wx.BoxSizer( wx.VERTICAL )
vbox.AddF( text_hbox, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.AddF( self._listbook, CC.FLAGS_EXPAND_BOTH_WAYS )
vbox.AddF( add_remove_hbox, CC.FLAGS_SMALL_INDENT )
vbox.AddF( ok_hbox, CC.FLAGS_BUTTON_SIZER )
@ -7107,11 +7137,11 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
self._booru_selector = wx.ListBox( self._query_panel )
self._booru_selector.Bind( wx.EVT_LISTBOX, self.EventBooruSelected )
self._period_days = wx.SpinCtrl( self._query_panel, min = 1, max = 1000 )
self._period = ClientGUICommon.TimeDeltaCtrl( self._query_panel, min = 3600 * 4, days = True, hours = True )
self._info_panel = ClientGUICommon.StaticBox( self, 'info' )
self._get_tags_if_redundant = wx.CheckBox( self._info_panel, label = 'get tags even if file already in db' )
self._get_tags_if_redundant = wx.CheckBox( self._info_panel, label = 'get tags even if new file is already in db' )
self._initial_file_limit = ClientGUICommon.NoneableSpinCtrl( self._info_panel, 'initial file limit', none_phrase = 'no limit', min = 1, max = 1000000 )
self._initial_file_limit.SetToolTipString( 'If set, the first sync will add no more than this many files. Otherwise, it will get everything the gallery has.' )
@ -7145,8 +7175,7 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
hbox = wx.BoxSizer( wx.HORIZONTAL )
hbox.AddF( wx.StaticText( self._query_panel, label = 'Check subscription every ' ), CC.FLAGS_MIXED )
hbox.AddF( self._period_days, CC.FLAGS_MIXED )
hbox.AddF( wx.StaticText( self._query_panel, label = 'days' ), CC.FLAGS_MIXED )
hbox.AddF( self._period, CC.FLAGS_MIXED )
self._query_panel.AddF( self._site_type, CC.FLAGS_EXPAND_PERPENDICULAR )
self._query_panel.AddF( self._query, CC.FLAGS_EXPAND_PERPENDICULAR )
@ -7166,7 +7195,14 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
seed_cache = self._original_subscription.GetSeedCache()
seed_cache_text = str( seed_cache.GetSeedCount() ) + ' urls in cache'
seed_cache_text = HydrusData.ConvertIntToPrettyString( seed_cache.GetSeedCount() ) + ' urls in cache'
num_failed = seed_cache.GetSeedCount( CC.STATUS_FAILED )
if num_failed > 0:
seed_cache_text += ', ' + HydrusData.ConvertIntToPrettyString( num_failed ) + ' failed'
self._info_panel.AddF( wx.StaticText( self._info_panel, label = seed_cache_text ), CC.FLAGS_EXPAND_PERPENDICULAR )
self._info_panel.AddF( self._seed_cache_button, CC.FLAGS_LONE_BUTTON )
@ -7284,7 +7320,7 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
self._query.SetValue( query )
self._period_days.SetValue( period / 86400 )
self._period.SetValue( period )
self._get_tags_if_redundant.SetValue( get_tags_if_redundant )
self._initial_file_limit.SetValue( initial_file_limit )
@ -7341,7 +7377,7 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
query = self._query.GetValue()
period = self._period_days.GetValue() * 86400
period = self._period.GetValue()
get_tags_if_redundant = self._get_tags_if_redundant.GetValue()
initial_file_limit = self._initial_file_limit.GetValue()
@ -7700,8 +7736,8 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
self._tag_parents.Bind( wx.EVT_LIST_ITEM_SELECTED, self.EventItemSelected )
self._tag_parents.Bind( wx.EVT_LIST_ITEM_DESELECTED, self.EventItemSelected )
self._children = ClientGUICommon.ListBoxTagsStrings( self )
self._parents = ClientGUICommon.ListBoxTagsStrings( self )
self._children = ClientGUICommon.ListBoxTagsStrings( self, show_sibling_text = False )
self._parents = ClientGUICommon.ListBoxTagsStrings( self, show_sibling_text = False )
expand_parents = True
@ -8258,7 +8294,7 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
removed_callable = lambda tags: 1
self._old_siblings = ClientGUICommon.ListBoxTagsStrings( self )
self._old_siblings = ClientGUICommon.ListBoxTagsStrings( self, show_sibling_text = False )
self._new_sibling = wx.StaticText( self )
expand_parents = False
@ -8730,7 +8766,7 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
self._old_siblings.RemoveTags( { new } )
self._new_sibling.SetLabel( new )
self._new_sibling.SetLabel( HydrusTags.RenderTag( new ) )
self._current_new = new
@ -9175,7 +9211,7 @@ class DialogManageTags( ClientGUIDialogs.Dialog ):
if sibling_tag is not None and num_sibling_current < num_files:
choices.append( ( 'add ' + sibling_tag + ' to ' + HydrusData.ConvertIntToPrettyString( num_files - num_current ) + ' files', ( HC.CONTENT_UPDATE_ADD, sibling_tag ) ) )
choices.append( ( 'add ' + sibling_tag + ' (preferred sibling) to ' + HydrusData.ConvertIntToPrettyString( num_files - num_sibling_current ) + ' files', ( HC.CONTENT_UPDATE_ADD, sibling_tag ) ) )
@ -9202,7 +9238,7 @@ class DialogManageTags( ClientGUIDialogs.Dialog ):
if num_sibling_current + num_sibling_pending < num_files:
choices.append( ( 'pend ' + sibling_tag + ' to ' + HydrusData.ConvertIntToPrettyString( num_files - num_current ) + ' files', ( HC.CONTENT_UPDATE_PEND, sibling_tag ) ) )
choices.append( ( 'pend ' + sibling_tag + ' (preferred sibling) to ' + HydrusData.ConvertIntToPrettyString( num_files - ( num_sibling_current + num_sibling_pending ) ) + ' files', ( HC.CONTENT_UPDATE_PEND, sibling_tag ) ) )

View File

@ -1416,7 +1416,7 @@ class ManagementPanelGalleryImport( ManagementPanel ):
self._file_gauge = ClientGUICommon.Gauge( self._import_queue_panel )
self._overall_gauge = ClientGUICommon.Gauge( self._import_queue_panel )
self._waiting_politely_indicator = ClientGUICommon.WaitingPolitely( self._import_queue_panel, self._page_key )
self._waiting_politely_indicator = ClientGUICommon.GetWaitingPolitelyControl( self._import_queue_panel, self._page_key )
self._seed_cache_button = wx.BitmapButton( self._import_queue_panel, bitmap = CC.GlobalBMPs.seed_cache )
self._seed_cache_button.Bind( wx.EVT_BUTTON, self.EventSeedCache )
@ -1958,7 +1958,7 @@ class ManagementPanelPageOfImagesImport( ManagementPanel ):
self._pause_button = wx.BitmapButton( self._import_queue_panel, bitmap = CC.GlobalBMPs.pause )
self._pause_button.Bind( wx.EVT_BUTTON, self.EventPause )
self._waiting_politely_indicator = ClientGUICommon.WaitingPolitely( self._import_queue_panel, self._page_key )
self._waiting_politely_indicator = ClientGUICommon.GetWaitingPolitelyControl( self._import_queue_panel, self._page_key )
self._seed_cache_button = wx.BitmapButton( self._import_queue_panel, bitmap = CC.GlobalBMPs.seed_cache )
self._seed_cache_button.Bind( wx.EVT_BUTTON, self.EventSeedCache )
@ -2530,13 +2530,13 @@ class ManagementPanelQuery( ManagementPanel ):
file_search_context = self._management_controller.GetVariable( 'file_search_context' )
search_enabled = self._management_controller.GetVariable( 'search_enabled' )
self._search_enabled = self._management_controller.GetVariable( 'search_enabled' )
self._query_key = HydrusThreading.JobKey( cancellable = True )
initial_predicates = file_search_context.GetPredicates()
if search_enabled:
if self._search_enabled:
self._search_panel = ClientGUICommon.StaticBox( self, 'search' )
@ -2559,7 +2559,7 @@ class ManagementPanelQuery( ManagementPanel ):
self._MakeSort( vbox )
self._MakeCollect( vbox )
if search_enabled: vbox.AddF( self._search_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
if self._search_enabled: vbox.AddF( self._search_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
self._MakeCurrentSelectionTagsBox( vbox )
@ -2597,7 +2597,7 @@ class ManagementPanelQuery( ManagementPanel ):
current_predicates = self._current_predicates_box.GetPredicates()
search_context = ClientData.FileSearchContext( file_service_key, tag_service_key, include_current, include_pending, current_predicates )
search_context = ClientSearch.FileSearchContext( file_service_key, tag_service_key, include_current, include_pending, current_predicates )
self._management_controller.SetVariable( 'file_search_context', search_context )
@ -2618,6 +2618,24 @@ class ManagementPanelQuery( ManagementPanel ):
def _MakeCurrentSelectionTagsBox( self, sizer ):
tags_box = ClientGUICommon.StaticBoxSorterForListBoxTags( self, 'selection tags' )
if self._search_enabled:
t = ClientGUICommon.ListBoxTagsSelectionManagementPanel( tags_box, self._page_key, predicates_callable = self._current_predicates_box.GetPredicates )
else:
t = ClientGUICommon.ListBoxTagsSelectionManagementPanel( tags_box, self._page_key )
tags_box.SetTagsBox( t )
sizer.AddF( tags_box, CC.FLAGS_EXPAND_BOTH_WAYS )
def AddMediaResultsFromQuery( self, query_key, media_results ):
if query_key == self._query_key: self._controller.pub( 'add_media_results', self._page_key, media_results, append = False )
@ -2749,14 +2767,14 @@ class ManagementPanelThreadWatcherImport( ManagementPanel ):
self._thread_times_to_check.SetValue( times_to_check )
self._thread_times_to_check.Bind( wx.EVT_SPINCTRL, self.EventTimesToCheck )
self._thread_check_period = wx.SpinCtrl( self._options_panel, size = ( 60, -1 ), min = 30, max = 86400 )
self._thread_check_period = ClientGUICommon.TimeDeltaCtrl( self._options_panel, min = 30, hours = True, minutes = True, seconds = True )
self._thread_check_period.SetValue( check_period )
self._thread_check_period.Bind( wx.EVT_SPINCTRL, self.EventCheckPeriod )
self._thread_check_now_button = wx.Button( self._options_panel, label = 'check now' )
self._thread_check_now_button.Bind( wx.EVT_BUTTON, self.EventCheckNow )
self._waiting_politely_indicator = ClientGUICommon.WaitingPolitely( self._options_panel, self._page_key )
self._waiting_politely_indicator = ClientGUICommon.GetWaitingPolitelyControl( self._options_panel, self._page_key )
self._seed_cache_button = wx.BitmapButton( self._options_panel, bitmap = CC.GlobalBMPs.seed_cache )
self._seed_cache_button.Bind( wx.EVT_BUTTON, self.EventSeedCache )
@ -2780,7 +2798,6 @@ class ManagementPanelThreadWatcherImport( ManagementPanel ):
hbox_2.AddF( wx.StaticText( self._options_panel, label = 'check every ' ), CC.FLAGS_MIXED )
hbox_2.AddF( self._thread_check_period, CC.FLAGS_MIXED )
hbox_2.AddF( wx.StaticText( self._options_panel, label = ' seconds' ), CC.FLAGS_MIXED )
button_sizer = wx.BoxSizer( wx.HORIZONTAL )

View File

@ -1768,6 +1768,8 @@ class MediaPanelThumbnails( MediaPanel ):
def EventPaint( self, event ):
dc = wx.BufferedPaintDC( self, self._client_bmp )
( client_x, client_y ) = self.GetClientSize()
( thumbnail_span_width, thumbnail_span_height ) = self._GetThumbnailSpanDimensions()
@ -1776,14 +1778,6 @@ class MediaPanelThumbnails( MediaPanel ):
page_indices_to_display = self._CalculateVisiblePageIndices()
dc = wx.BufferedPaintDC( self, self._client_bmp )
( xUnit, yUnit ) = self.GetScrollPixelsPerUnit()
y_start = self._GetYStart()
earliest_y = y_start * yUnit
earliest_page_index_to_display = min( page_indices_to_display )
last_page_index_to_display = max( page_indices_to_display )
@ -1802,6 +1796,12 @@ class MediaPanelThumbnails( MediaPanel ):
random.shuffle( potential_clean_indices_to_steal )
( xUnit, yUnit ) = self.GetScrollPixelsPerUnit()
y_start = self._GetYStart()
earliest_y = y_start * yUnit
for page_index in page_indices_to_draw:
if page_index not in self._clean_canvas_pages:

View File

@ -1403,49 +1403,38 @@ class IMFrame( ClientGUICommon.Frame ):
def __init__( self, parent, me_account, them_account, context ):
def InitialiseControls():
self._me_label = MeLabel( self, me_account ) # maybe these two should be the same, and infer me/them status itself
self._them_label = ThemLabel( self, them_account )
self._convo_box = ConvoBox( self, context_key ) # something like this
self._text_input = ConvoTextInput( self, callable ) # callable should be private method of this, or similar!
def PopulateControls():
# could introduce last convo here, or whatever.
pass
def ArrangeControls():
hbox = wx.BoxSizer( wx.HORIZONTAL )
hbox.AddF( self._me_label, CC.FLAGS_MIXED )
hbox.AddF( wx.StaticText( self, label = ' talking to ' ), CC.FLAGS_MIXED )
hbox.AddF( self._them_label, CC.FLAGS_MIXED )
vbox = wx.BoxSizer( wx.VERTICAL )
vbox.AddF( hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
vbox.AddF( self._convo_box, CC.FLAGS_EXPAND_BOTH_WAYS )
vbox.AddF( self._text_input, CC.FLAGS_EXPAND_PERPENDICULAR )
self.SetSizer( vbox )
self.SetInitialSize( ( 400, 600 ) ) # this should be remembered, stuck in options
me_name = me_account.GetNameBlah()
them_name = them_account.GetNameBlah()
ClientGUICommon.Frame.__init__( self, parent, title = me_name + ' talking to ' + them_name )
InitialiseControls()
self._me_label = MeLabel( self, me_account ) # maybe these two should be the same, and infer me/them status itself
self._them_label = ThemLabel( self, them_account )
self._convo_box = ConvoBox( self, context_key ) # something like this
self._text_input = ConvoTextInput( self, callable ) # callable should be private method of this, or similar!
PopulateControls()
#
ArrangeControls()
# could introduce last convo here, or whatever.
pass
#
hbox = wx.BoxSizer( wx.HORIZONTAL )
hbox.AddF( self._me_label, CC.FLAGS_MIXED )
hbox.AddF( wx.StaticText( self, label = ' talking to ' ), CC.FLAGS_MIXED )
hbox.AddF( self._them_label, CC.FLAGS_MIXED )
vbox = wx.BoxSizer( wx.VERTICAL )
vbox.AddF( hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
vbox.AddF( self._convo_box, CC.FLAGS_EXPAND_BOTH_WAYS )
vbox.AddF( self._text_input, CC.FLAGS_EXPAND_PERPENDICULAR )
self.SetSizer( vbox )
self.SetInitialSize( ( 400, 600 ) ) # this should be remembered, stuck in options
self.Show( True )

View File

@ -3,6 +3,7 @@ import ClientData
import ClientGUICommon
import ClientGUIOptionsPanels
import ClientRatings
import ClientSearch
import HydrusConstants as HC
import HydrusData
import HydrusGlobals
@ -22,7 +23,7 @@ class PanelPredicateSystem( wx.Panel ):
info = self.GetInfo()
predicates = ( ClientData.Predicate( self.PREDICATE_TYPE, info ), )
predicates = ( ClientSearch.Predicate( self.PREDICATE_TYPE, info ), )
return predicates
@ -602,7 +603,7 @@ class PanelPredicateSystemRating( PanelPredicateSystem ):
infos = self.GetInfo()
predicates = [ ClientData.Predicate( self.PREDICATE_TYPE, info ) for info in infos ]
predicates = [ ClientSearch.Predicate( self.PREDICATE_TYPE, info ) for info in infos ]
return predicates

View File

@ -2593,7 +2593,7 @@ class ThreadWatcherImport( HydrusSerialisable.SerialisableBase ):
delay = self._check_period
watcher_status = 'checking again in ' + HydrusData.ConvertTimestampToPrettyPending( self._last_time_checked + delay ) + ' seconds'
watcher_status = 'checking again ' + HydrusData.ConvertTimestampToPrettyPending( self._last_time_checked + delay )
else:

View File

@ -4,6 +4,7 @@ import ClientConstants as CC
import ClientData
import ClientFiles
import ClientRatings
import ClientSearch
import HydrusConstants as HC
import HydrusTags
import os
@ -332,6 +333,81 @@ class MediaList( object ):
self._sorted_media.remove_items( singleton_media.union( collected_media ) )
def AddMedia( self, new_media, append = True ):
if append:
self._singleton_media.update( new_media )
self._sorted_media.append_items( new_media )
else:
if self._collect_by is not None:
keys_to_medias = self._CalculateCollectionKeysToMedias( self._collect_by, new_media )
new_media = []
for ( key, medias ) in keys_to_medias.items():
if key in self._collect_map_singletons:
singleton_media = self._collect_map_singletons[ key ]
self._sorted_media.remove_items( singleton_media )
self._singleton_media.discard( singleton_media )
del self._collect_map_singletons[ key ]
medias.append( singleton_media )
collected_media = self._GenerateMediaCollection( [ media.GetMediaResult() for media in medias ] )
collected_media.Sort( self._sort_by )
self._collected_media.add( collected_media )
self._collect_map_collected[ key ] = collected_media
new_media.append( collected_media )
elif key in self._collect_map_collected:
collected_media = self._collect_map_collected[ key ]
self._sorted_media.remove_items( collected_media )
collected_media.AddMedia( medias )
collected_media.Sort( self._sort_by )
new_media.append( collected_media )
elif len( medias ) == 1:
( singleton_media, ) = medias
self._singleton_media.add( singleton_media )
self._collect_map_singletons[ key ] = singleton_media
else:
collected_media = self._GenerateMediaCollection( [ media.GetMediaResult() for media in medias ] )
collected_media.Sort( self._sort_by )
self._collected_media.add( collected_media )
self._collect_map_collected[ key ] = collected_media
new_media.append( collected_media )
self._sorted_media.insert_items( new_media )
return new_media
def Collect( self, collect_by = -1 ):
if collect_by == -1: collect_by = self._collect_by
@ -587,7 +663,7 @@ class ListeningMediaList( MediaList ):
MediaList.__init__( self, file_service_key, media_results )
self._file_query_result = ClientData.FileQueryResult( media_results )
self._file_query_result = ClientSearch.FileQueryResult( media_results )
HydrusGlobals.client_controller.sub( self, 'ProcessContentUpdates', 'content_updates_gui' )
HydrusGlobals.client_controller.sub( self, 'ProcessServiceUpdates', 'service_updates_gui' )
@ -610,76 +686,7 @@ class ListeningMediaList( MediaList ):
new_media.append( self._GenerateMediaSingleton( media_result ) )
if append:
self._singleton_media.update( new_media )
self._sorted_media.append_items( new_media )
else:
if self._collect_by is not None:
keys_to_medias = self._CalculateCollectionKeysToMedias( self._collect_by, new_media )
new_media = []
for ( key, medias ) in keys_to_medias.items():
if key in self._collect_map_singletons:
singleton_media = self._collect_map_singletons[ key ]
self._sorted_media.remove_items( singleton_media )
self._singleton_media.discard( singleton_media )
del self._collect_map_singletons[ key ]
medias.append( singleton_media )
collected_media = self._GenerateMediaCollection( [ media.GetMediaResult() for media in medias ] )
collected_media.Sort( self._sort_by )
self._collected_media.add( collected_media )
self._collect_map_collected[ key ] = collected_media
new_media.append( collected_media )
elif key in self._collect_map_collected:
collected_media = self._collect_map_collected[ key ]
self._sorted_media.remove_items( collected_media )
# mediacollection needs addmediaresult with efficient recalcinternals
collected_media.MagicalAddMediasOrMediaResultsWhatever( medias )
collected_media.Sort( self._sort_by )
new_media.append( collected_media )
elif len( medias ) == 1:
( singleton_media, ) = medias
self._singleton_media.add( singleton_media )
self._collect_map_singletons[ key ] = singleton_media
else:
collected_media = self._GenerateMediaCollection( [ media.GetMediaResult() for media in medias ] )
collected_media.Sort( self._sort_by )
self._collected_media.add( collected_media )
self._collect_map_collected[ key ] = collected_media
new_media.append( collected_media )
self._sorted_media.insert_items( new_media )
self.AddMedia( new_media, append = append )
return new_media
@ -752,6 +759,13 @@ class MediaCollection( MediaList, Media ):
self._locations_manager = LocationsManager( current, deleted, pending, petitioned )
def AddMedia( self, new_media, append = True ):
MediaList.AddMedia( self, new_media, append = True )
self._RecalcInternals()
def DeletePending( self, service_key ):
MediaList.DeletePending( self, service_key )
@ -1487,9 +1501,21 @@ class TagsManager( TagsManagerSimple ):
statuses_to_tags[ HC.CURRENT ].discard( tag )
statuses_to_tags[ HC.PETITIONED ].discard( tag )
elif action == HC.CONTENT_UPDATE_PEND: statuses_to_tags[ HC.PENDING ].add( tag )
elif action == HC.CONTENT_UPDATE_PEND:
if tag not in statuses_to_tags[ HC.CURRENT ]:
statuses_to_tags[ HC.PENDING ].add( tag )
elif action == HC.CONTENT_UPDATE_RESCIND_PEND: statuses_to_tags[ HC.PENDING ].discard( tag )
elif action == HC.CONTENT_UPDATE_PETITION: statuses_to_tags[ HC.PETITIONED ].add( tag )
elif action == HC.CONTENT_UPDATE_PETITION:
if tag in statuses_to_tags[ HC.CURRENT ]:
statuses_to_tags[ HC.PETITIONED ].add( tag )
elif action == HC.CONTENT_UPDATE_RESCIND_PETITION: statuses_to_tags[ HC.PETITIONED ].discard( tag )
self._RecalcCombined()

View File

@ -26,7 +26,7 @@ def AddHydrusCredentialsToHeaders( credentials, request_headers ):
def AddHydrusSessionKeyToHeaders( service_key, request_headers ):
session_manager = HydrusGlobals.client_controller.GetManager( 'hydrus_sessions' )
session_manager = HydrusGlobals.client_controller.GetClientSessionManager()
session_key = session_manager.GetSessionKey( service_key )

View File

@ -1,7 +1,10 @@
import ClientConstants as CC
import ClientData
import HydrusConstants as HC
import HydrusData
import HydrusGlobals
import HydrusSerialisable
import HydrusTags
import re
import wx
@ -90,16 +93,893 @@ def SortPredicates( predicates ):
return predicates
SYSTEM_PREDICATE_INBOX = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_INBOX, None )
class FileQueryResult( object ):
def __init__( self, media_results ):
self._hashes_to_media_results = { media_result.GetHash() : media_result for media_result in media_results }
self._hashes_ordered = [ media_result.GetHash() for media_result in media_results ]
self._hashes = set( self._hashes_ordered )
HydrusGlobals.client_controller.sub( self, 'ProcessContentUpdates', 'content_updates_data' )
HydrusGlobals.client_controller.sub( self, 'ProcessServiceUpdates', 'service_updates_data' )
def __iter__( self ):
for hash in self._hashes_ordered: yield self._hashes_to_media_results[ hash ]
def __len__( self ): return len( self._hashes_ordered )
def _Remove( self, hashes ):
for hash in hashes:
if hash in self._hashes_to_media_results:
del self._hashes_to_media_results[ hash ]
self._hashes_ordered.remove( hash )
self._hashes.difference_update( hashes )
def AddMediaResults( self, media_results ):
for media_result in media_results:
hash = media_result.GetHash()
if hash in self._hashes: continue # this is actually important, as sometimes we don't want the media result overwritten
self._hashes_to_media_results[ hash ] = media_result
self._hashes_ordered.append( hash )
self._hashes.add( hash )
def GetHashes( self ): return self._hashes
def GetMediaResult( self, hash ): return self._hashes_to_media_results[ hash ]
def GetMediaResults( self ): return [ self._hashes_to_media_results[ hash ] for hash in self._hashes_ordered ]
def ProcessContentUpdates( self, service_keys_to_content_updates ):
for ( service_key, content_updates ) in service_keys_to_content_updates.items():
for content_update in content_updates:
hashes = content_update.GetHashes()
if len( hashes ) > 0:
for hash in self._hashes.intersection( hashes ):
media_result = self._hashes_to_media_results[ hash ]
media_result.ProcessContentUpdate( service_key, content_update )
def ProcessServiceUpdates( self, service_keys_to_service_updates ):
for ( service_key, service_updates ) in service_keys_to_service_updates.items():
for service_update in service_updates:
( action, row ) = service_update.ToTuple()
if action == HC.SERVICE_UPDATE_DELETE_PENDING:
for media_result in self._hashes_to_media_results.values(): media_result.DeletePending( service_key )
elif action == HC.SERVICE_UPDATE_RESET:
for media_result in self._hashes_to_media_results.values(): media_result.ResetService( service_key )
class FileSearchContext( HydrusSerialisable.SerialisableBase ):
SERIALISABLE_TYPE = HydrusSerialisable.SERIALISABLE_TYPE_FILE_SEARCH_CONTEXT
SERIALISABLE_VERSION = 1
def __init__( self, file_service_key = CC.COMBINED_FILE_SERVICE_KEY, tag_service_key = CC.COMBINED_TAG_SERVICE_KEY, include_current_tags = True, include_pending_tags = True, predicates = None ):
if predicates is None: predicates = []
self._file_service_key = file_service_key
self._tag_service_key = tag_service_key
self._include_current_tags = include_current_tags
self._include_pending_tags = include_pending_tags
self._predicates = predicates
self._search_complete = False
self._InitialiseTemporaryVariables()
def _GetSerialisableInfo( self ):
serialisable_predicates = [ predicate.GetSerialisableTuple() for predicate in self._predicates ]
return ( self._file_service_key.encode( 'hex' ), self._tag_service_key.encode( 'hex' ), self._include_current_tags, self._include_pending_tags, serialisable_predicates, self._search_complete )
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
( file_service_key, tag_service_key, self._include_current_tags, self._include_pending_tags, serialisable_predicates, self._search_complete ) = serialisable_info
self._file_service_key = file_service_key.decode( 'hex' )
self._tag_service_key = tag_service_key.decode( 'hex' )
self._predicates = [ HydrusSerialisable.CreateFromSerialisableTuple( pred_tuple ) for pred_tuple in serialisable_predicates ]
self._InitialiseTemporaryVariables()
def _InitialiseTemporaryVariables( self ):
system_predicates = [ predicate for predicate in self._predicates if predicate.GetType() in HC.SYSTEM_PREDICATES ]
self._system_predicates = FileSystemPredicates( system_predicates )
tag_predicates = [ predicate for predicate in self._predicates if predicate.GetType() == HC.PREDICATE_TYPE_TAG ]
self._tags_to_include = []
self._tags_to_exclude = []
for predicate in tag_predicates:
tag = predicate.GetValue()
if predicate.GetInclusive(): self._tags_to_include.append( tag )
else: self._tags_to_exclude.append( tag )
namespace_predicates = [ predicate for predicate in self._predicates if predicate.GetType() == HC.PREDICATE_TYPE_NAMESPACE ]
self._namespaces_to_include = []
self._namespaces_to_exclude = []
for predicate in namespace_predicates:
namespace = predicate.GetValue()
if predicate.GetInclusive(): self._namespaces_to_include.append( namespace )
else: self._namespaces_to_exclude.append( namespace )
wildcard_predicates = [ predicate for predicate in self._predicates if predicate.GetType() == HC.PREDICATE_TYPE_WILDCARD ]
self._wildcards_to_include = []
self._wildcards_to_exclude = []
for predicate in wildcard_predicates:
wildcard = predicate.GetValue()
if predicate.GetInclusive(): self._wildcards_to_include.append( wildcard )
else: self._wildcards_to_exclude.append( wildcard )
def GetFileServiceKey( self ): return self._file_service_key
def GetNamespacesToExclude( self ): return self._namespaces_to_exclude
def GetNamespacesToInclude( self ): return self._namespaces_to_include
def GetPredicates( self ): return self._predicates
def GetSystemPredicates( self ): return self._system_predicates
def GetTagServiceKey( self ): return self._tag_service_key
def GetTagsToExclude( self ): return self._tags_to_exclude
def GetTagsToInclude( self ): return self._tags_to_include
def GetWildcardsToExclude( self ): return self._wildcards_to_exclude
def GetWildcardsToInclude( self ): return self._wildcards_to_include
def IncludeCurrentTags( self ): return self._include_current_tags
def IncludePendingTags( self ): return self._include_pending_tags
def IsComplete( self ): return self._search_complete
def SetComplete( self ): self._search_complete = True
def SetPredicates( self, predicates ):
self._predicates = predicates
self._InitialiseTemporaryVariables()
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_FILE_SEARCH_CONTEXT ] = FileSearchContext
SYSTEM_PREDICATE_ARCHIVE = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_ARCHIVE, None )
class FileSystemPredicates( object ):
def __init__( self, system_predicates ):
self._inbox = False
self._archive = False
self._local = False
self._not_local = False
self._common_info = {}
self._limit = None
self._similar_to = None
self._file_services_to_include_current = []
self._file_services_to_include_pending = []
self._file_services_to_exclude_current = []
self._file_services_to_exclude_pending = []
self._ratings_predicates = []
new_options = HydrusGlobals.client_controller.GetNewOptions()
forced_search_limit = new_options.GetNoneableInteger( 'forced_search_limit' )
if forced_search_limit is not None:
self._limit = forced_search_limit
for predicate in system_predicates:
predicate_type = predicate.GetType()
value = predicate.GetValue()
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_INBOX: self._inbox = True
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_ARCHIVE: self._archive = True
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_LOCAL: self._local = True
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_NOT_LOCAL: self._not_local = True
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_HASH:
hash = value
self._common_info[ 'hash' ] = hash
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_AGE:
( operator, years, months, days, hours ) = value
age = ( ( ( ( ( ( ( years * 12 ) + months ) * 30 ) + days ) * 24 ) + hours ) * 3600 )
now = HydrusData.GetNow()
# this is backwards because we are talking about age, not timestamp
if operator == '<': self._common_info[ 'min_timestamp' ] = now - age
elif operator == '>': self._common_info[ 'max_timestamp' ] = now - age
elif operator == u'\u2248':
self._common_info[ 'min_timestamp' ] = now - int( age * 1.15 )
self._common_info[ 'max_timestamp' ] = now - int( age * 0.85 )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_MIME:
mimes = value
if isinstance( mimes, int ): mimes = ( mimes, )
self._common_info[ 'mimes' ] = mimes
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_DURATION:
( operator, duration ) = value
if operator == '<': self._common_info[ 'max_duration' ] = duration
elif operator == '>': self._common_info[ 'min_duration' ] = duration
elif operator == '=': self._common_info[ 'duration' ] = duration
elif operator == u'\u2248':
if duration == 0: self._common_info[ 'duration' ] = 0
else:
self._common_info[ 'min_duration' ] = int( duration * 0.85 )
self._common_info[ 'max_duration' ] = int( duration * 1.15 )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_RATING:
( operator, value, service_key ) = value
self._ratings_predicates.append( ( operator, value, service_key ) )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_RATIO:
( operator, ratio_width, ratio_height ) = value
if operator == '=': self._common_info[ 'ratio' ] = ( ratio_width, ratio_height )
elif operator == u'\u2248':
self._common_info[ 'min_ratio' ] = ( ratio_width * 0.85, ratio_height )
self._common_info[ 'max_ratio' ] = ( ratio_width * 1.15, ratio_height )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIZE:
( operator, size, unit ) = value
size = size * unit
if operator == '<': self._common_info[ 'max_size' ] = size
elif operator == '>': self._common_info[ 'min_size' ] = size
elif operator == '=': self._common_info[ 'size' ] = size
elif operator == u'\u2248':
self._common_info[ 'min_size' ] = int( size * 0.85 )
self._common_info[ 'max_size' ] = int( size * 1.15 )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS:
( operator, num_tags ) = value
if operator == '<': self._common_info[ 'max_num_tags' ] = num_tags
elif operator == '=': self._common_info[ 'num_tags' ] = num_tags
elif operator == '>': self._common_info[ 'min_num_tags' ] = num_tags
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_WIDTH:
( operator, width ) = value
if operator == '<': self._common_info[ 'max_width' ] = width
elif operator == '>': self._common_info[ 'min_width' ] = width
elif operator == '=': self._common_info[ 'width' ] = width
elif operator == u'\u2248':
if width == 0: self._common_info[ 'width' ] = 0
else:
self._common_info[ 'min_width' ] = int( width * 0.85 )
self._common_info[ 'max_width' ] = int( width * 1.15 )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_PIXELS:
( operator, num_pixels, unit ) = value
num_pixels = num_pixels * unit
if operator == '<': self._common_info[ 'max_num_pixels' ] = num_pixels
elif operator == '>': self._common_info[ 'min_num_pixels' ] = num_pixels
elif operator == '=': self._common_info[ 'num_pixels' ] = num_pixels
elif operator == u'\u2248':
self._common_info[ 'min_num_pixels' ] = int( num_pixels * 0.85 )
self._common_info[ 'max_num_pixels' ] = int( num_pixels * 1.15 )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_HEIGHT:
( operator, height ) = value
if operator == '<': self._common_info[ 'max_height' ] = height
elif operator == '>': self._common_info[ 'min_height' ] = height
elif operator == '=': self._common_info[ 'height' ] = height
elif operator == u'\u2248':
if height == 0: self._common_info[ 'height' ] = 0
else:
self._common_info[ 'min_height' ] = int( height * 0.85 )
self._common_info[ 'max_height' ] = int( height * 1.15 )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS:
( operator, num_words ) = value
if operator == '<': self._common_info[ 'max_num_words' ] = num_words
elif operator == '>': self._common_info[ 'min_num_words' ] = num_words
elif operator == '=': self._common_info[ 'num_words' ] = num_words
elif operator == u'\u2248':
if num_words == 0: self._common_info[ 'num_words' ] = 0
else:
self._common_info[ 'min_num_words' ] = int( num_words * 0.85 )
self._common_info[ 'max_num_words' ] = int( num_words * 1.15 )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_LIMIT:
limit = value
if self._limit is None:
self._limit = limit
else:
self._limit = min( limit, self._limit )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE:
( operator, current_or_pending, service_key ) = value
if operator == True:
if current_or_pending == HC.CURRENT: self._file_services_to_include_current.append( service_key )
else: self._file_services_to_include_pending.append( service_key )
else:
if current_or_pending == HC.CURRENT: self._file_services_to_exclude_current.append( service_key )
else: self._file_services_to_exclude_pending.append( service_key )
if predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO:
( hash, max_hamming ) = value
self._similar_to = ( hash, max_hamming )
def GetFileServiceInfo( self ): return ( self._file_services_to_include_current, self._file_services_to_include_pending, self._file_services_to_exclude_current, self._file_services_to_exclude_pending )
def GetSimpleInfo( self ): return self._common_info
def GetLimit( self ): return self._limit
def GetRatingsPredicates( self ): return self._ratings_predicates
def GetSimilarTo( self ): return self._similar_to
def HasSimilarTo( self ): return self._similar_to is not None
def MustBeArchive( self ): return self._archive
def MustBeInbox( self ): return self._inbox
def MustBeLocal( self ): return self._local
def MustNotBeLocal( self ): return self._not_local
class Predicate( HydrusSerialisable.SerialisableBase ):
SERIALISABLE_TYPE = HydrusSerialisable.SERIALISABLE_TYPE_PREDICATE
SERIALISABLE_VERSION = 1
def __init__( self, predicate_type = None, value = None, inclusive = True, counts = None ):
if counts is None: counts = {}
if type( value ) == list:
value = tuple( value )
self._predicate_type = predicate_type
self._value = value
self._inclusive = inclusive
self._counts = {}
self._counts[ HC.CURRENT ] = 0
self._counts[ HC.PENDING ] = 0
for ( current_or_pending, count ) in counts.items(): self.AddToCount( current_or_pending, count )
def __eq__( self, other ):
return self.__hash__() == other.__hash__()
def __hash__( self ):
return ( self._predicate_type, self._value, self._inclusive ).__hash__()
def __ne__( self, other ):
return self.__hash__() != other.__hash__()
def __repr__( self ):
return 'Predicate: ' + HydrusData.ToUnicode( ( self._predicate_type, self._value, self._inclusive, self._counts ) )
def _GetSerialisableInfo( self ):
if self._predicate_type in ( HC.PREDICATE_TYPE_SYSTEM_RATING, HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE ):
( operator, value, service_key ) = self._value
serialisable_value = ( operator, value, service_key.encode( 'hex' ) )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO:
( hash, max_hamming ) = self._value
serialisable_value = ( hash.encode( 'hex' ), max_hamming )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_HASH:
hash = self._value
serialisable_value = hash.encode( 'hex' )
else:
serialisable_value = self._value
return ( self._predicate_type, serialisable_value, self._inclusive )
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
( self._predicate_type, serialisable_value, self._inclusive ) = serialisable_info
if self._predicate_type in ( HC.PREDICATE_TYPE_SYSTEM_RATING, HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE ):
( operator, value, service_key ) = serialisable_value
self._value = ( operator, value, service_key.decode( 'hex' ) )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO:
( serialisable_hash, max_hamming ) = serialisable_value
self._value = ( serialisable_hash.decode( 'hex' ), max_hamming )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_HASH:
self._value = serialisable_value.decode( 'hex' )
else:
self._value = serialisable_value
if type( self._value ) == list:
self._value = tuple( self._value )
def AddToCount( self, current_or_pending, count ): self._counts[ current_or_pending ] += count
def GetCopy( self ): return Predicate( self._predicate_type, self._value, self._inclusive, self._counts )
def GetCountlessCopy( self ): return Predicate( self._predicate_type, self._value, self._inclusive )
def GetCount( self, current_or_pending = None ):
if current_or_pending is None: return sum( self._counts.values() )
else: return self._counts[ current_or_pending ]
def GetInclusive( self ):
# patch from an upgrade mess-up ~v144
if not hasattr( self, '_inclusive' ):
if self._predicate_type not in HC.SYSTEM_PREDICATES:
( operator, value ) = self._value
self._value = value
self._inclusive = operator == '+'
else: self._inclusive = True
return self._inclusive
def GetInfo( self ): return ( self._predicate_type, self._value, self._inclusive )
def GetInverseCopy( self ):
if self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_ARCHIVE:
return Predicate( HC.PREDICATE_TYPE_SYSTEM_INBOX )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_INBOX:
return Predicate( HC.PREDICATE_TYPE_SYSTEM_ARCHIVE )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_LOCAL:
return Predicate( HC.PREDICATE_TYPE_SYSTEM_NOT_LOCAL )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_NOT_LOCAL:
return Predicate( HC.PREDICATE_TYPE_SYSTEM_LOCAL )
elif self._predicate_type in ( HC.PREDICATE_TYPE_TAG, HC.PREDICATE_TYPE_NAMESPACE, HC.PREDICATE_TYPE_WILDCARD ):
return Predicate( self._predicate_type, self._value, not self._inclusive )
else:
return None
def GetType( self ): return self._predicate_type
def GetUnicode( self, with_count = True ):
count_text = u''
if with_count:
if self._counts[ HC.CURRENT ] > 0: count_text += u' (' + HydrusData.ConvertIntToPrettyString( self._counts[ HC.CURRENT ] ) + u')'
if self._counts[ HC.PENDING ] > 0: count_text += u' (+' + HydrusData.ConvertIntToPrettyString( self._counts[ HC.PENDING ] ) + u')'
if self._predicate_type in HC.SYSTEM_PREDICATES:
if self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_EVERYTHING: base = u'system:everything'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_INBOX: base = u'system:inbox'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_ARCHIVE: base = u'system:archive'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_UNTAGGED: base = u'system:untagged'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_LOCAL: base = u'system:local'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_NOT_LOCAL: base = u'system:not local'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_DIMENSIONS: base = u'system:dimensions'
elif self._predicate_type in ( HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, HC.PREDICATE_TYPE_SYSTEM_WIDTH, HC.PREDICATE_TYPE_SYSTEM_HEIGHT, HC.PREDICATE_TYPE_SYSTEM_DURATION, HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS ):
if self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS: base = u'system:number of tags'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_WIDTH: base = u'system:width'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_HEIGHT: base = u'system:height'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_DURATION: base = u'system:duration'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS: base = u'system:number of words'
if self._value is not None:
( operator, value ) = self._value
base += u' ' + operator + u' ' + HydrusData.ConvertIntToPrettyString( value )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_RATIO:
base = u'system:ratio'
if self._value is not None:
( operator, ratio_width, ratio_height ) = self._value
base += u' ' + operator + u' ' + str( ratio_width ) + u':' + str( ratio_height )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIZE:
base = u'system:size'
if self._value is not None:
( operator, size, unit ) = self._value
base += u' ' + operator + u' ' + str( size ) + HydrusData.ConvertIntToUnit( unit )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_LIMIT:
base = u'system:limit'
if self._value is not None:
value = self._value
base += u' is ' + HydrusData.ConvertIntToPrettyString( value )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_AGE:
base = u'system:age'
if self._value is not None:
( operator, years, months, days, hours ) = self._value
base += u' ' + operator + u' ' + str( years ) + u'y' + str( months ) + u'm' + str( days ) + u'd' + str( hours ) + u'h'
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_PIXELS:
base = u'system:num_pixels'
if self._value is not None:
( operator, num_pixels, unit ) = self._value
base += u' ' + operator + u' ' + str( num_pixels ) + ' ' + HydrusData.ConvertIntToPixels( unit )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_HASH:
base = u'system:hash'
if self._value is not None:
hash = self._value
base += u' is ' + hash.encode( 'hex' )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_MIME:
base = u'system:mime'
if self._value is not None:
mimes = self._value
if set( mimes ) == set( HC.SEARCHABLE_MIMES ):
mime_text = 'anything'
elif set( mimes ) == set( HC.SEARCHABLE_MIMES ).intersection( set( HC.APPLICATIONS ) ):
mime_text = 'application'
elif set( mimes ) == set( HC.SEARCHABLE_MIMES ).intersection( set( HC.AUDIO ) ):
mime_text = 'audio'
elif set( mimes ) == set( HC.SEARCHABLE_MIMES ).intersection( set( HC.IMAGES ) ):
mime_text = 'image'
elif set( mimes ) == set( HC.SEARCHABLE_MIMES ).intersection( set( HC.VIDEO ) ):
mime_text = 'video'
else:
mime_text = ', '.join( [ HC.mime_string_lookup[ mime ] for mime in mimes ] )
base += u' is ' + mime_text
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_RATING:
base = u'system:rating'
if self._value is not None:
( operator, value, service_key ) = self._value
service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key )
base += u' for ' + service.GetName() + u' ' + operator + u' ' + HydrusData.ToUnicode( value )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO:
base = u'system:similar to'
if self._value is not None:
( hash, max_hamming ) = self._value
base += u' ' + hash.encode( 'hex' ) + u' using max hamming of ' + str( max_hamming )
elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE:
base = u'system:'
if self._value is None:
base += 'file service'
else:
( operator, current_or_pending, service_key ) = self._value
if operator == True: base += u'is'
else: base += u'is not'
if current_or_pending == HC.PENDING: base += u' pending to '
else: base += u' currently in '
service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key )
base += service.GetName()
base += count_text
elif self._predicate_type == HC.PREDICATE_TYPE_TAG:
tag = self._value
if not self._inclusive: base = u'-'
else: base = u''
base += HydrusTags.RenderTag( tag )
base += count_text
siblings_manager = HydrusGlobals.client_controller.GetManager( 'tag_siblings' )
sibling = siblings_manager.GetSibling( tag )
if sibling is not None: base += u' (will display as ' + HydrusTags.RenderTag( sibling ) + ')'
elif self._predicate_type == HC.PREDICATE_TYPE_PARENT:
base = ' '
tag = self._value
base += HydrusTags.RenderTag( tag )
base += count_text
elif self._predicate_type == HC.PREDICATE_TYPE_NAMESPACE:
namespace = self._value
if not self._inclusive: base = u'-'
else: base = u''
base += namespace + u':*anything*'
elif self._predicate_type == HC.PREDICATE_TYPE_WILDCARD:
wildcard = self._value
if not self._inclusive: base = u'-'
else: base = u''
base += HydrusTags.RenderTag( wildcard )
return base
def GetValue( self ): return self._value
def SetInclusive( self, inclusive ): self._inclusive = inclusive
SYSTEM_PREDICATE_LOCAL = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_LOCAL, None )
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_PREDICATE ] = Predicate
SYSTEM_PREDICATE_NOT_LOCAL = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_NOT_LOCAL, None )
SYSTEM_PREDICATE_INBOX = Predicate( HC.PREDICATE_TYPE_SYSTEM_INBOX, None )
SYSTEM_PREDICATE_ARCHIVE = Predicate( HC.PREDICATE_TYPE_SYSTEM_ARCHIVE, None )
SYSTEM_PREDICATE_LOCAL = Predicate( HC.PREDICATE_TYPE_SYSTEM_LOCAL, None )
SYSTEM_PREDICATE_NOT_LOCAL = Predicate( HC.PREDICATE_TYPE_SYSTEM_NOT_LOCAL, None )

View File

@ -53,7 +53,7 @@ options = {}
# Misc
NETWORK_VERSION = 17
SOFTWARE_VERSION = 184
SOFTWARE_VERSION = 185
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )

View File

@ -263,7 +263,33 @@ def ConvertPrettyStringsToUglyNamespaces( pretty_strings ):
def ConvertTimeDeltaToPrettyString( seconds ):
if seconds > 1:
if seconds > 60:
seconds = int( seconds )
if seconds > 86400:
days = seconds / 86400
hours = ( seconds % 86400 ) / 3600
result = '%d' % days + ' days ' + '%d' % hours + ' hours'
elif seconds > 3600:
hours = seconds / 3600
minutes = ( seconds % 3600 ) / 60
result = '%d' % hours + ' hours ' + '%d' % minutes + ' minutes'
else:
minutes = seconds / 60
seconds = seconds % 60
result = '%d' % minutes + ' minutes ' + '%d' % seconds + ' seconds'
elif seconds > 1:
result = '%.1f' % seconds + ' seconds'

View File

@ -127,6 +127,8 @@ def CleanTag( tag ):
tag = re.sub( '\\A(\\s|-|system:)', '', tag, flags = re.UNICODE ) # removes spaces or garbage at the beginning
tag = re.sub( '^:(?!:)', '::', tag, flags = re.UNICODE ) # Convert anything starting with one colon to start with two i.e. :D -> ::D
except Exception as e:
text = 'Was unable to parse the tag: ' + HydrusData.ToUnicode( tag )
@ -154,3 +156,32 @@ def CleanTags( tags ):
return clean_tags
def CombineTag( namespace, tag ):
if namespace == '':
if tag.startswith( ':' ):
return ':' + tag
else:
return tag
else:
return namespace + ':' + tag
def RenderTag( tag ):
if tag.startswith( '::' ):
return tag[1:]
else:
return tag

View File

@ -302,12 +302,16 @@ class Controller( HydrusController.HydrusController ):
self.ShutdownModel()
def GetServerSessionManager( self ):
return self._server_session_manager
def InitModel( self ):
HydrusController.HydrusController.InitModel( self )
self._managers[ 'restricted_services_sessions' ] = HydrusSessions.HydrusSessionManagerServer()
self._managers[ 'messaging_sessions' ] = HydrusSessions.HydrusMessagingSessionManagerServer()
self._server_session_manager = HydrusSessions.HydrusSessionManagerServer()
self._services = {}

View File

@ -2516,6 +2516,18 @@ class DB( HydrusDB.HydrusDB ):
if version == 184:
result = self._c.execute( 'SELECT tag_id FROM tags WHERE tag = ?;', ( '', ) ).fetchone()
if result is not None:
( tag_id, ) = result
self._c.execute( 'DELETE FROM mappings WHERE tag_id = ?;', ( tag_id, ) )
HydrusData.Print( 'The server has updated to version ' + str( version + 1 ) )
self._c.execute( 'UPDATE version SET version = ?;', ( version + 1, ) )

View File

@ -32,7 +32,7 @@ class HydrusResourceCommandAccessKey( HydrusServerResources.HydrusResourceComman
registration_key = self._parseAccessKey( request )
access_key = HydrusGlobals.controller.Read( 'access_key', registration_key )
access_key = HydrusGlobals.server_controller.Read( 'access_key', registration_key )
body = yaml.safe_dump( { 'access_key' : access_key } )
@ -45,7 +45,7 @@ class HydrusResourceCommandShutdown( HydrusServerResources.HydrusResourceCommand
def _threadDoPOSTJob( self, request ):
HydrusGlobals.controller.ShutdownFromServer()
HydrusGlobals.server_controller.ShutdownFromServer()
response_context = HydrusServerResources.ResponseContext( 200 )
@ -58,7 +58,7 @@ class HydrusResourceCommandAccessKeyVerification( HydrusServerResources.HydrusRe
access_key = self._parseAccessKey( request )
verified = HydrusGlobals.controller.Read( 'verify_access_key', self._service_key, access_key )
verified = HydrusGlobals.server_controller.Read( 'verify_access_key', self._service_key, access_key )
body = yaml.safe_dump( { 'verified' : verified } )
@ -71,7 +71,7 @@ class HydrusResourceCommandInit( HydrusServerResources.HydrusResourceCommand ):
def _threadDoGETJob( self, request ):
access_key = HydrusGlobals.controller.Read( 'init' )
access_key = HydrusGlobals.server_controller.Read( 'init' )
body = yaml.safe_dump( { 'access_key' : access_key } )
@ -86,7 +86,7 @@ class HydrusResourceCommandSessionKey( HydrusServerResources.HydrusResourceComma
access_key = self._parseAccessKey( request )
session_manager = HydrusGlobals.controller.GetManager( 'restricted_services_sessions' )
session_manager = HydrusGlobals.server_controller.GetServerSessionManager()
( session_key, expires ) = session_manager.AddSession( self._service_key, access_key )
@ -154,7 +154,7 @@ class HydrusResourceCommandRestricted( HydrusServerResources.HydrusResourceComma
except: raise Exception( 'Problem parsing cookies!' )
session_manager = HydrusGlobals.controller.GetManager( 'restricted_services_sessions' )
session_manager = HydrusGlobals.server_controller.GetServerSessionManager()
account = session_manager.GetAccount( self._service_key, session_key )
@ -180,7 +180,7 @@ class HydrusResourceCommandRestricted( HydrusServerResources.HydrusResourceComma
account.RequestMade( num_bytes )
HydrusGlobals.controller.pub( 'request_made', ( account.GetAccountKey(), num_bytes ) )
HydrusGlobals.server_controller.pub( 'request_made', ( account.GetAccountKey(), num_bytes ) )
@ -211,13 +211,13 @@ class HydrusResourceCommandRestrictedAccount( HydrusResourceCommandRestricted ):
subject_identifiers = request.hydrus_args[ 'subject_identifiers' ]
subject_account_keys = { HydrusGlobals.controller.Read( 'account_key_from_identifier', self._service_key, subject_identifier ) for subject_identifier in subject_identifiers }
subject_account_keys = { HydrusGlobals.server_controller.Read( 'account_key_from_identifier', self._service_key, subject_identifier ) for subject_identifier in subject_identifiers }
kwargs = request.hydrus_args # for things like expires, title, and so on
HydrusGlobals.controller.WriteSynchronous( 'account', self._service_key, admin_account_key, action, subject_account_keys, kwargs )
HydrusGlobals.server_controller.WriteSynchronous( 'account', self._service_key, admin_account_key, action, subject_account_keys, kwargs )
session_manager = HydrusGlobals.controller.GetManager( 'restricted_services_sessions' )
session_manager = HydrusGlobals.server_controller.GetServerSessionManager()
session_manager.RefreshAccounts( self._service_key, subject_account_keys )
@ -234,9 +234,9 @@ class HydrusResourceCommandRestrictedAccountInfo( HydrusResourceCommandRestricte
subject_identifier = request.hydrus_args[ 'subject_identifier' ]
subject_account_key = HydrusGlobals.controller.Read( 'account_key_from_identifier', self._service_key, subject_identifier )
subject_account_key = HydrusGlobals.server_controller.Read( 'account_key_from_identifier', self._service_key, subject_identifier )
account_info = HydrusGlobals.controller.Read( 'account_info', self._service_key, subject_account_key )
account_info = HydrusGlobals.server_controller.Read( 'account_info', self._service_key, subject_account_key )
body = yaml.safe_dump( { 'account_info' : account_info } )
@ -252,7 +252,7 @@ class HydrusResourceCommandRestrictedAccountTypes( HydrusResourceCommandRestrict
def _threadDoGETJob( self, request ):
account_types = HydrusGlobals.controller.Read( 'account_types', self._service_key )
account_types = HydrusGlobals.server_controller.Read( 'account_types', self._service_key )
body = yaml.safe_dump( { 'account_types' : account_types } )
@ -265,7 +265,7 @@ class HydrusResourceCommandRestrictedAccountTypes( HydrusResourceCommandRestrict
edit_log = request.hydrus_args[ 'edit_log' ]
HydrusGlobals.controller.WriteSynchronous( 'account_types', self._service_key, edit_log )
HydrusGlobals.server_controller.WriteSynchronous( 'account_types', self._service_key, edit_log )
response_context = HydrusServerResources.ResponseContext( 200 )
@ -282,12 +282,12 @@ class HydrusResourceCommandRestrictedBackup( HydrusResourceCommandRestricted ):
HydrusGlobals.server_busy = True
HydrusGlobals.controller.WriteSynchronous( 'backup' )
HydrusGlobals.server_controller.WriteSynchronous( 'backup' )
HydrusGlobals.server_busy = False
HydrusGlobals.controller.CallToThread( do_it )
HydrusGlobals.server_controller.CallToThread( do_it )
response_context = HydrusServerResources.ResponseContext( 200 )
@ -302,7 +302,7 @@ class HydrusResourceCommandRestrictedIP( HydrusResourceCommandRestricted ):
hash = request.hydrus_args[ 'hash' ]
( ip, timestamp ) = HydrusGlobals.controller.Read( 'ip', self._service_key, hash )
( ip, timestamp ) = HydrusGlobals.server_controller.Read( 'ip', self._service_key, hash )
body = yaml.safe_dump( { 'ip' : ip, 'timestamp' : timestamp } )
@ -319,7 +319,7 @@ class HydrusResourceCommandRestrictedNews( HydrusResourceCommandRestricted ):
news = request.hydrus_args[ 'news' ]
HydrusGlobals.controller.WriteSynchronous( 'news', self._service_key, news )
HydrusGlobals.server_controller.WriteSynchronous( 'news', self._service_key, news )
response_context = HydrusServerResources.ResponseContext( 200 )
@ -332,7 +332,7 @@ class HydrusResourceCommandRestrictedNumPetitions( HydrusResourceCommandRestrict
def _threadDoGETJob( self, request ):
num_petitions = HydrusGlobals.controller.Read( 'num_petitions', self._service_key )
num_petitions = HydrusGlobals.server_controller.Read( 'num_petitions', self._service_key )
body = yaml.safe_dump( { 'num_petitions' : num_petitions } )
@ -347,7 +347,7 @@ class HydrusResourceCommandRestrictedPetition( HydrusResourceCommandRestricted )
def _threadDoGETJob( self, request ):
petition = HydrusGlobals.controller.Read( 'petition', self._service_key )
petition = HydrusGlobals.server_controller.Read( 'petition', self._service_key )
body = petition.DumpToNetworkString()
@ -368,7 +368,7 @@ class HydrusResourceCommandRestrictedRegistrationKeys( HydrusResourceCommandRest
if 'lifetime' in request.hydrus_args: lifetime = request.hydrus_args[ 'lifetime' ]
else: lifetime = None
registration_keys = HydrusGlobals.controller.Read( 'registration_keys', self._service_key, num, title, lifetime )
registration_keys = HydrusGlobals.server_controller.Read( 'registration_keys', self._service_key, num, title, lifetime )
body = yaml.safe_dump( { 'registration_keys' : registration_keys } )
@ -405,7 +405,7 @@ class HydrusResourceCommandRestrictedRepositoryFile( HydrusResourceCommandRestri
file_dict[ 'ip' ] = request.getClientIP()
HydrusGlobals.controller.WriteSynchronous( 'file', self._service_key, account_key, file_dict )
HydrusGlobals.server_controller.WriteSynchronous( 'file', self._service_key, account_key, file_dict )
response_context = HydrusServerResources.ResponseContext( 200 )
@ -442,7 +442,7 @@ class HydrusResourceCommandRestrictedServices( HydrusResourceCommandRestricted )
edit_log = request.hydrus_args[ 'edit_log' ]
service_keys_to_access_keys = HydrusGlobals.controller.WriteSynchronous( 'services', account_key, edit_log )
service_keys_to_access_keys = HydrusGlobals.server_controller.WriteSynchronous( 'services', account_key, edit_log )
body = yaml.safe_dump( { 'service_keys_to_access_keys' : service_keys_to_access_keys } )
@ -458,7 +458,7 @@ class HydrusResourceCommandRestrictedServicesInfo( HydrusResourceCommandRestrict
def _threadDoGETJob( self, request ):
services_info = HydrusGlobals.controller.Read( 'services_info' )
services_info = HydrusGlobals.server_controller.Read( 'services_info' )
body = yaml.safe_dump( { 'services_info' : services_info } )
@ -473,7 +473,7 @@ class HydrusResourceCommandRestrictedStats( HydrusResourceCommandRestricted ):
def _threadDoGETJob( self, request ):
stats = HydrusGlobals.controller.Read( 'stats', self._service_key )
stats = HydrusGlobals.server_controller.Read( 'stats', self._service_key )
body = yaml.safe_dump( { 'stats' : stats } )
@ -507,7 +507,7 @@ class HydrusResourceCommandRestrictedContentUpdate( HydrusResourceCommandRestric
update = request.hydrus_args[ 'update' ]
HydrusGlobals.controller.WriteSynchronous( 'update', self._service_key, account_key, update )
HydrusGlobals.server_controller.WriteSynchronous( 'update', self._service_key, account_key, update )
response_context = HydrusServerResources.ResponseContext( 200 )
@ -520,7 +520,7 @@ class HydrusResourceCommandRestrictedImmediateContentUpdate( HydrusResourceComma
def _threadDoGETJob( self, request ):
content_update = HydrusGlobals.controller.Read( 'immediate_content_update', self._service_key )
content_update = HydrusGlobals.server_controller.Read( 'immediate_content_update', self._service_key )
network_string = content_update.DumpToNetworkString()

View File

@ -117,8 +117,8 @@ class TestClientDB( unittest.TestCase ):
preds = set()
preds.add( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'car', counts = { HC.CURRENT : 1 } ) )
preds.add( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'series:cars', counts = { HC.CURRENT : 1 } ) )
preds.add( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'car', counts = { HC.CURRENT : 1 } ) )
preds.add( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'series:cars', counts = { HC.CURRENT : 1 } ) )
for p in result: self.assertEqual( p.GetCount( HC.CURRENT ), 1 )
@ -130,8 +130,8 @@ class TestClientDB( unittest.TestCase ):
preds = set()
preds.add( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'series:cars', counts = { HC.CURRENT : 1 } ) )
preds.add( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'car', counts = { HC.CURRENT : 1 } ) )
preds.add( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'series:cars', counts = { HC.CURRENT : 1 } ) )
preds.add( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'car', counts = { HC.CURRENT : 1 } ) )
for p in result: self.assertEqual( p.GetCount( HC.CURRENT ), 1 )
@ -147,7 +147,7 @@ class TestClientDB( unittest.TestCase ):
result = self._read( 'autocomplete_predicates', half_complete_tag = 'series:c' )
pred = ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'series:cars', counts = { HC.CURRENT : 1 } )
pred = ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'series:cars', counts = { HC.CURRENT : 1 } )
( read_pred, ) = result
@ -159,7 +159,7 @@ class TestClientDB( unittest.TestCase ):
result = self._read( 'autocomplete_predicates', tag = 'car' )
pred = ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'car', counts = { HC.CURRENT : 1 } )
pred = ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'car', counts = { HC.CURRENT : 1 } )
( read_pred, ) = result
@ -222,7 +222,7 @@ class TestClientDB( unittest.TestCase ):
def test_export_folders( self ):
file_search_context = ClientData.FileSearchContext(file_service_key = HydrusData.GenerateKey(), tag_service_key = HydrusData.GenerateKey(), predicates = [ ClientData.Predicate( predicate_type = HC.PREDICATE_TYPE_TAG, value = 'test' ) ] )
file_search_context = ClientSearch.FileSearchContext(file_service_key = HydrusData.GenerateKey(), tag_service_key = HydrusData.GenerateKey(), predicates = [ ClientSearch.Predicate( predicate_type = HC.PREDICATE_TYPE_TAG, value = 'test' ) ] )
export_folder = ClientFiles.ExportFolder( 'test path', export_type = HC.EXPORT_FOLDER_TYPE_REGULAR, file_search_context = file_search_context, period = 3600, phrase = '{hash}' )
@ -241,9 +241,9 @@ class TestClientDB( unittest.TestCase ):
for ( inclusive, namespace, result ) in tests:
predicates = [ ClientData.Predicate( HC.PREDICATE_TYPE_NAMESPACE, namespace, inclusive = inclusive ) ]
predicates = [ ClientSearch.Predicate( HC.PREDICATE_TYPE_NAMESPACE, namespace, inclusive = inclusive ) ]
search_context = ClientData.FileSearchContext( file_service_key = CC.LOCAL_FILE_SERVICE_KEY, predicates = predicates )
search_context = ClientSearch.FileSearchContext( file_service_key = CC.LOCAL_FILE_SERVICE_KEY, predicates = predicates )
file_query_ids = self._read( 'file_query_ids', search_context )
@ -255,9 +255,9 @@ class TestClientDB( unittest.TestCase ):
for ( predicate_type, info, result ) in tests:
predicates = [ ClientData.Predicate( predicate_type, info ) ]
predicates = [ ClientSearch.Predicate( predicate_type, info ) ]
search_context = ClientData.FileSearchContext( file_service_key = CC.LOCAL_FILE_SERVICE_KEY, predicates = predicates )
search_context = ClientSearch.FileSearchContext( file_service_key = CC.LOCAL_FILE_SERVICE_KEY, predicates = predicates )
file_query_ids = self._read( 'file_query_ids', search_context )
@ -269,9 +269,9 @@ class TestClientDB( unittest.TestCase ):
for ( inclusive, tag, result ) in tests:
predicates = [ ClientData.Predicate( HC.PREDICATE_TYPE_TAG, tag, inclusive = inclusive ) ]
predicates = [ ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, tag, inclusive = inclusive ) ]
search_context = ClientData.FileSearchContext( file_service_key = CC.LOCAL_FILE_SERVICE_KEY, predicates = predicates )
search_context = ClientSearch.FileSearchContext( file_service_key = CC.LOCAL_FILE_SERVICE_KEY, predicates = predicates )
file_query_ids = self._read( 'file_query_ids', search_context )
@ -535,10 +535,10 @@ class TestClientDB( unittest.TestCase ):
predicates = []
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_EVERYTHING, None, counts = { HC.CURRENT : 1 } ) )
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_INBOX, None, counts = { HC.CURRENT : 1 } ) )
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_ARCHIVE, None, counts = { HC.CURRENT : 0 } ) )
predicates.extend( [ ClientData.Predicate( predicate_type, None ) for predicate_type in [ HC.PREDICATE_TYPE_SYSTEM_UNTAGGED, HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, HC.PREDICATE_TYPE_SYSTEM_LIMIT, HC.PREDICATE_TYPE_SYSTEM_SIZE, HC.PREDICATE_TYPE_SYSTEM_AGE, HC.PREDICATE_TYPE_SYSTEM_HASH, HC.PREDICATE_TYPE_SYSTEM_DIMENSIONS, HC.PREDICATE_TYPE_SYSTEM_DURATION, HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS, HC.PREDICATE_TYPE_SYSTEM_MIME, HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO, HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE ] ] )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_EVERYTHING, None, counts = { HC.CURRENT : 1 } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_INBOX, None, counts = { HC.CURRENT : 1 } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_ARCHIVE, None, counts = { HC.CURRENT : 0 } ) )
predicates.extend( [ ClientSearch.Predicate( predicate_type, None ) for predicate_type in [ HC.PREDICATE_TYPE_SYSTEM_UNTAGGED, HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, HC.PREDICATE_TYPE_SYSTEM_LIMIT, HC.PREDICATE_TYPE_SYSTEM_SIZE, HC.PREDICATE_TYPE_SYSTEM_AGE, HC.PREDICATE_TYPE_SYSTEM_HASH, HC.PREDICATE_TYPE_SYSTEM_DIMENSIONS, HC.PREDICATE_TYPE_SYSTEM_DURATION, HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS, HC.PREDICATE_TYPE_SYSTEM_MIME, HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO, HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE ] ] )
self.assertEqual( result, predicates )
@ -573,31 +573,31 @@ class TestClientDB( unittest.TestCase ):
session.AddPage( 'petition page', management_controller, [] )
fsc = ClientData.FileSearchContext( file_service_key = HydrusData.GenerateKey(), predicates = [] )
fsc = ClientSearch.FileSearchContext( file_service_key = HydrusData.GenerateKey(), predicates = [] )
management_controller = ClientGUIManagement.CreateManagementControllerQuery( HydrusData.GenerateKey(), fsc, True )
session.AddPage( 'files', management_controller, [] )
fsc = ClientData.FileSearchContext( file_service_key = HydrusData.GenerateKey(), tag_service_key = HydrusData.GenerateKey(), predicates = [] )
fsc = ClientSearch.FileSearchContext( file_service_key = HydrusData.GenerateKey(), tag_service_key = HydrusData.GenerateKey(), predicates = [] )
management_controller = ClientGUIManagement.CreateManagementControllerQuery( HydrusData.GenerateKey(), fsc, False )
session.AddPage( 'files', management_controller, [ HydrusData.GenerateKey() for i in range( 200 ) ] )
fsc = ClientData.FileSearchContext( file_service_key = HydrusData.GenerateKey(), predicates = [ ClientSearch.SYSTEM_PREDICATE_ARCHIVE ] )
fsc = ClientSearch.FileSearchContext( file_service_key = HydrusData.GenerateKey(), predicates = [ ClientSearch.SYSTEM_PREDICATE_ARCHIVE ] )
management_controller = ClientGUIManagement.CreateManagementControllerQuery( HydrusData.GenerateKey(), fsc, True )
session.AddPage( 'files', management_controller, [] )
fsc = ClientData.FileSearchContext( file_service_key = HydrusData.GenerateKey(), predicates = [ ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'tag', counts = { HC.CURRENT : 1, HC.PENDING : 3 } ) ] )
fsc = ClientSearch.FileSearchContext( file_service_key = HydrusData.GenerateKey(), predicates = [ ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'tag', counts = { HC.CURRENT : 1, HC.PENDING : 3 } ) ] )
management_controller = ClientGUIManagement.CreateManagementControllerQuery( HydrusData.GenerateKey(), fsc, True )
session.AddPage( 'files', management_controller, [] )
fsc = ClientData.FileSearchContext( file_service_key = HydrusData.GenerateKey(), predicates = [ ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_RATING, ( '>', 0.2, HydrusData.GenerateKey() ) ), ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE, ( True, HC.CURRENT, HydrusData.GenerateKey() ) ) ] )
fsc = ClientSearch.FileSearchContext( file_service_key = HydrusData.GenerateKey(), predicates = [ ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_RATING, ( '>', 0.2, HydrusData.GenerateKey() ) ), ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE, ( True, HC.CURRENT, HydrusData.GenerateKey() ) ) ] )
management_controller = ClientGUIManagement.CreateManagementControllerQuery( HydrusData.GenerateKey(), fsc, True )

View File

@ -399,149 +399,149 @@ class TestTagObjects( unittest.TestCase ):
def test_predicates( self ):
p = ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'tag' )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'tag' )
self.assertEqual( p.GetUnicode(), u'tag' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'tag', counts = { HC.CURRENT : 1, HC.PENDING : 2 } )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'tag', counts = { HC.CURRENT : 1, HC.PENDING : 2 } )
self.assertEqual( p.GetUnicode( with_count = False ), u'tag' )
self.assertEqual( p.GetUnicode( with_count = True ), u'tag (1) (+2)' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'tag', inclusive = False )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'tag', inclusive = False )
self.assertEqual( p.GetUnicode(), u'-tag' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'tag', inclusive = False, counts = { HC.CURRENT : 1, HC.PENDING : 2 } )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'tag', inclusive = False, counts = { HC.CURRENT : 1, HC.PENDING : 2 } )
self.assertEqual( p.GetUnicode( with_count = False ), u'-tag' )
self.assertEqual( p.GetUnicode( with_count = True ), u'-tag (1) (+2)' )
#
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_AGE, ( '<', 1, 2, 3, 4 ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_AGE, ( '<', 1, 2, 3, 4 ) )
self.assertEqual( p.GetUnicode(), u'system:age < 1y2m3d4h' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_AGE, ( u'\u2248', 1, 2, 3, 4 ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_AGE, ( u'\u2248', 1, 2, 3, 4 ) )
self.assertEqual( p.GetUnicode(), u'system:age ' + u'\u2248' + ' 1y2m3d4h' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_AGE, ( '>', 1, 2, 3, 4 ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_AGE, ( '>', 1, 2, 3, 4 ) )
self.assertEqual( p.GetUnicode(), u'system:age > 1y2m3d4h' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_ARCHIVE, None, counts = { HC.CURRENT : 1000 } )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_ARCHIVE, None, counts = { HC.CURRENT : 1000 } )
self.assertEqual( p.GetUnicode(), u'system:archive (1,000)' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_DURATION, ( '<', 1000 ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_DURATION, ( '<', 1000 ) )
self.assertEqual( p.GetUnicode(), u'system:duration < 1,000' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_EVERYTHING, None, counts = { HC.CURRENT : 2000 } )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_EVERYTHING, None, counts = { HC.CURRENT : 2000 } )
self.assertEqual( p.GetUnicode(), u'system:everything (2,000)' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE, ( True, HC.CURRENT, CC.LOCAL_FILE_SERVICE_KEY ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE, ( True, HC.CURRENT, CC.LOCAL_FILE_SERVICE_KEY ) )
self.assertEqual( p.GetUnicode(), u'system:is currently in local files' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE, ( False, HC.PENDING, CC.LOCAL_FILE_SERVICE_KEY ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE, ( False, HC.PENDING, CC.LOCAL_FILE_SERVICE_KEY ) )
self.assertEqual( p.GetUnicode(), u'system:is not pending to local files' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_HASH, 'abcd'.decode( 'hex' ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_HASH, 'abcd'.decode( 'hex' ) )
self.assertEqual( p.GetUnicode(), u'system:hash is abcd' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_HEIGHT, ( '<', 2000 ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_HEIGHT, ( '<', 2000 ) )
self.assertEqual( p.GetUnicode(), u'system:height < 2,000' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_INBOX, None, counts = { HC.CURRENT : 1000 } )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_INBOX, None, counts = { HC.CURRENT : 1000 } )
self.assertEqual( p.GetUnicode(), u'system:inbox (1,000)' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_LIMIT, 2000 )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_LIMIT, 2000 )
self.assertEqual( p.GetUnicode(), u'system:limit is 2,000' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_LOCAL, None, counts = { HC.CURRENT : 100 } )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_LOCAL, None, counts = { HC.CURRENT : 100 } )
self.assertEqual( p.GetUnicode(), u'system:local (100)' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_MIME, set( HC.IMAGES ).intersection( HC.SEARCHABLE_MIMES ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_MIME, set( HC.IMAGES ).intersection( HC.SEARCHABLE_MIMES ) )
self.assertEqual( p.GetUnicode(), u'system:mime is image' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_MIME, ( HC.VIDEO_WEBM, ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_MIME, ( HC.VIDEO_WEBM, ) )
self.assertEqual( p.GetUnicode(), u'system:mime is video/webm' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_MIME, ( HC.VIDEO_WEBM, HC.IMAGE_GIF ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_MIME, ( HC.VIDEO_WEBM, HC.IMAGE_GIF ) )
self.assertEqual( p.GetUnicode(), u'system:mime is video/webm, image/gif' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_NOT_LOCAL, None, counts = { HC.CURRENT : 100 } )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_NOT_LOCAL, None, counts = { HC.CURRENT : 100 } )
self.assertEqual( p.GetUnicode(), u'system:not local (100)' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, ( '<', 2 ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, ( '<', 2 ) )
self.assertEqual( p.GetUnicode(), u'system:number of tags < 2' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS, ( '<', 5000 ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS, ( '<', 5000 ) )
self.assertEqual( p.GetUnicode(), u'system:number of words < 5,000' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_RATING, ( '>', 0.2, CC.LOCAL_FILE_SERVICE_KEY ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_RATING, ( '>', 0.2, CC.LOCAL_FILE_SERVICE_KEY ) )
self.assertEqual( p.GetUnicode(), u'system:rating for local files > 0.2' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_RATIO, ( '=', 16, 9 ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_RATIO, ( '=', 16, 9 ) )
self.assertEqual( p.GetUnicode(), u'system:ratio = 16:9' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO, ( 'abcd'.decode( 'hex' ), 5 ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO, ( 'abcd'.decode( 'hex' ), 5 ) )
self.assertEqual( p.GetUnicode(), u'system:similar to abcd using max hamming of 5' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_SIZE, ( '>', 5, 1048576 ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_SIZE, ( '>', 5, 1048576 ) )
self.assertEqual( p.GetUnicode(), u'system:size > 5MB' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_UNTAGGED, HC.IMAGES )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_UNTAGGED, HC.IMAGES )
self.assertEqual( p.GetUnicode(), u'system:untagged' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_WIDTH, ( '=', 1920 ) )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_WIDTH, ( '=', 1920 ) )
self.assertEqual( p.GetUnicode(), u'system:width = 1,920' )
#
p = ClientData.Predicate( HC.PREDICATE_TYPE_NAMESPACE, 'series' )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_NAMESPACE, 'series' )
self.assertEqual( p.GetUnicode(), u'series:*anything*' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'series', inclusive = False )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'series', inclusive = False )
self.assertEqual( p.GetUnicode(), u'-series' )
#
p = ClientData.Predicate( HC.PREDICATE_TYPE_WILDCARD, 'a*i:o*' )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_WILDCARD, 'a*i:o*' )
self.assertEqual( p.GetUnicode(), u'a*i:o*' )
p = ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'a*i:o*', inclusive = False )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'a*i:o*', inclusive = False )
self.assertEqual( p.GetUnicode(), u'-a*i:o*' )
#
p = ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, 'series:game of thrones' )
p = ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, 'series:game of thrones' )
self.assertEqual( p.GetUnicode(), u' series:game of thrones' )
@ -587,45 +587,45 @@ class TestTagParents( unittest.TestCase ):
predicates = []
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'grandmother', counts = { HC.CURRENT : 10 } ) )
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'grandfather', counts = { HC.CURRENT : 15 } ) )
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'not_exist', counts = { HC.CURRENT : 20 } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'grandmother', counts = { HC.CURRENT : 10 } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'grandfather', counts = { HC.CURRENT : 15 } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'not_exist', counts = { HC.CURRENT : 20 } ) )
self.assertEqual( self._tag_parents_manager.ExpandPredicates( CC.COMBINED_TAG_SERVICE_KEY, predicates ), predicates )
predicates = []
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'child', counts = { HC.CURRENT : 10 } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'child', counts = { HC.CURRENT : 10 } ) )
results = []
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'child', counts = { HC.CURRENT : 10 } ) )
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, 'mother' ) )
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, 'father' ) )
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, 'grandmother' ) )
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, 'grandfather' ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'child', counts = { HC.CURRENT : 10 } ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, 'mother' ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, 'father' ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, 'grandmother' ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, 'grandfather' ) )
self.assertEqual( set( self._tag_parents_manager.ExpandPredicates( CC.COMBINED_TAG_SERVICE_KEY, predicates ) ), set( results ) )
predicates = []
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_NAMESPACE, 'series' ) )
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'child', counts = { HC.CURRENT : 10 } ) )
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'cousin', counts = { HC.CURRENT : 5 } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_NAMESPACE, 'series' ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'child', counts = { HC.CURRENT : 10 } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'cousin', counts = { HC.CURRENT : 5 } ) )
results = []
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_NAMESPACE, 'series' ) )
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'child', counts = { HC.CURRENT : 10 } ) )
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, 'mother' ) )
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, 'father' ) )
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, 'grandmother' ) )
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, 'grandfather' ) )
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'cousin', counts = { HC.CURRENT : 5 } ) )
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, 'aunt' ) )
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, 'uncle' ) )
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, 'grandmother' ) )
results.append( ClientData.Predicate( HC.PREDICATE_TYPE_PARENT, 'grandfather' ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_NAMESPACE, 'series' ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'child', counts = { HC.CURRENT : 10 } ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, 'mother' ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, 'father' ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, 'grandmother' ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, 'grandfather' ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'cousin', counts = { HC.CURRENT : 5 } ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, 'aunt' ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, 'uncle' ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, 'grandmother' ) )
results.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_PARENT, 'grandfather' ) )
self.assertEqual( set( self._tag_parents_manager.ExpandPredicates( CC.COMBINED_TAG_SERVICE_KEY, predicates ) ), set( results ) )
@ -748,19 +748,19 @@ class TestTagSiblings( unittest.TestCase ):
predicates = []
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'chain_a', counts = { HC.CURRENT : 10 } ) )
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'chain_b', counts = { HC.CURRENT : 5 } ) )
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'chain_c', counts = { HC.CURRENT : 20 } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'chain_a', counts = { HC.CURRENT : 10 } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'chain_b', counts = { HC.CURRENT : 5 } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'chain_c', counts = { HC.CURRENT : 20 } ) )
results = [ ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'chain_c', counts = { HC.CURRENT : 35 } ) ]
results = [ ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'chain_c', counts = { HC.CURRENT : 35 } ) ]
self.assertEqual( self._tag_siblings_manager.CollapsePredicates( predicates ), results )
predicates = []
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'chain_a', counts = { HC.CURRENT : 10 } ) )
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'chain_b', counts = { HC.CURRENT : 5 } ) )
predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, 'chain_c', counts = { HC.CURRENT : 20 } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'chain_a', counts = { HC.CURRENT : 10 } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'chain_b', counts = { HC.CURRENT : 5 } ) )
predicates.append( ClientSearch.Predicate( HC.PREDICATE_TYPE_TAG, 'chain_c', counts = { HC.CURRENT : 20 } ) )
( result, ) = self._tag_siblings_manager.CollapsePredicates( predicates )

15
test.py
View File

@ -104,15 +104,14 @@ class Controller( object ):
self._services_manager = ClientCaches.ServicesManager( self )
self._client_files_manager = ClientCaches.ClientFilesManager( self )
self._client_session_manager = ClientCaches.HydrusSessionManager( self )
self._managers[ 'hydrus_sessions' ] = ClientCaches.HydrusSessionManager( self )
self._managers[ 'tag_censorship' ] = ClientCaches.TagCensorshipManager( self )
self._managers[ 'tag_siblings' ] = ClientCaches.TagSiblingsManager( self )
self._managers[ 'tag_parents' ] = ClientCaches.TagParentsManager( self )
self._managers[ 'undo' ] = ClientCaches.UndoManager( self )
self._managers[ 'web_sessions' ] = TestConstants.FakeWebSessionManager()
self._managers[ 'restricted_services_sessions' ] = HydrusSessions.HydrusSessionManagerServer()
self._managers[ 'messaging_sessions' ] = HydrusSessions.HydrusMessagingSessionManagerServer()
self._server_session_manager = HydrusSessions.HydrusSessionManagerServer()
self._managers[ 'local_booru' ] = ClientCaches.LocalBooruCache( self )
self._cookies = {}
@ -149,6 +148,11 @@ class Controller( object ):
return self._client_files_manager
def GetClientSessionManager( self ):
return self._client_session_manager
def GetHTTP( self ): return self._http
def GetNewOptions( self ):
@ -168,6 +172,11 @@ class Controller( object ):
return self._services_manager
def GetServerSessionManager( self ):
return self._server_session_manager
def GetWrite( self, name ):
write = self._writes[ name ]