Version 185
This commit is contained in:
parent
1ef52cff14
commit
39711a06eb
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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, ) )
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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' )
|
||||
|
||||
|
|
|
@ -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
|
@ -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 ) ) )
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -53,7 +53,7 @@ options = {}
|
|||
# Misc
|
||||
|
||||
NETWORK_VERSION = 17
|
||||
SOFTWARE_VERSION = 184
|
||||
SOFTWARE_VERSION = 185
|
||||
|
||||
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
@ -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 = {}
|
||||
|
||||
|
|
|
@ -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, ) )
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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
15
test.py
|
@ -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 ]
|
||||
|
|
Loading…
Reference in New Issue