Version 237

This commit is contained in:
Hydrus Network Developer 2016-12-21 16:30:54 -06:00
parent 3859d7ff83
commit 33c1a0b9e2
29 changed files with 836 additions and 398 deletions

View File

@ -8,6 +8,34 @@
<div class="content">
<h3>changelog</h3>
<ul>
<li><h3>version 237</h3></li>
<ul>
<li>added 'all local files' service that spans all local file domains</li>
<li>improved trash service code</li>
<li>trashed files now report their trashed timestamp in right-click menus</li>
<li>trash views will sort oldest/newest by the trash timestamp</li>
<li>renamed 'local files' to 'my files' to reduce initial confusion</li>
<li>if you don't like 'my files', you can now rename the local files service under manage services!</li>
<li>improved how some local file service metadata is stored</li>
<li>cleaned and possibly fixed up some delete code</li>
<li>cleaned up a bunch of misc service and file service code</li>
<li>the client is more intelligent about what local files are -- you can now 'open externally' trashed files, for instance</li>
<li>on multiple monitor systems, the new sizing system now bounds itself by the appropriate monitor's dimensions (previously, it was always consulting the primary, I think)</li>
<li>if an expansion event causes a frame to grow off screen, the new sizing system will now attempt to move it up and left so it is completely visible</li>
<li>fixed an important bug in the specific service autocomplete cache that was leading to several kinds of miscount--please regen your autocomplete cache at your convenience</li>
<li>the client can now post additional messages on boot (you'll see one!)</li>
<li>improved how errors with unusual characters are applied to failed import file status objects</li>
<li>left double-click on the main gui greyspace now opens the new page chooser as well</li>
<li>restored session pages now recover more gracefully from missing services</li>
<li>shortened the 'stop after this many files' phrase, which was mis-sizing downloader panels</li>
<li>changed several bits of old jank in the 'import options - files' collapsible. it is also now thinner</li>
<li>misc gui improvements</li>
<li>updated more of the menu system code</li>
<li>the selection tags box now sizes its height more reasonably</li>
<li>fixed 'check now' and 'reset cache' buttons on edit sub dialog</li>
<li>subscriptions report better file import status on their popup</li>
<li>misc cleanup</li>
</ul>
<li><h3>version 236</h3></li>
<ul>
<li>in prep for a network https upgrade, the client can now detect and escalate to https when making connections to hydrus services</li>

View File

@ -1668,7 +1668,7 @@ class ThumbnailCache( object ):
locations_manager = display_media.GetLocationsManager()
if locations_manager.HasLocal():
if locations_manager.IsLocal():
try:
@ -2638,12 +2638,23 @@ class UndoManager( object ):
( data_type, action, row ) = content_update.ToTuple()
if data_type == HC.CONTENT_TYPE_FILES:
if action in ( HC.CONTENT_UPDATE_ADD, HC.CONTENT_UPDATE_DELETE, HC.CONTENT_UPDATE_UNDELETE, HC.CONTENT_UPDATE_RESCIND_PETITION, HC.CONTENT_UPDATE_ADVANCED ): continue
if action in ( HC.CONTENT_UPDATE_ADD, HC.CONTENT_UPDATE_DELETE, HC.CONTENT_UPDATE_UNDELETE, HC.CONTENT_UPDATE_RESCIND_PETITION, HC.CONTENT_UPDATE_ADVANCED ):
continue
elif data_type == HC.CONTENT_TYPE_MAPPINGS:
if action in ( HC.CONTENT_UPDATE_RESCIND_PETITION, HC.CONTENT_UPDATE_ADVANCED ): continue
if action in ( HC.CONTENT_UPDATE_RESCIND_PETITION, HC.CONTENT_UPDATE_ADVANCED ):
continue
else:
continue
else: continue
filtered_content_update = HydrusData.ContentUpdate( data_type, action, row )
@ -2930,4 +2941,4 @@ class WebSessionManagerClient( object ):
return cookies

View File

@ -458,7 +458,7 @@ LOCAL_BOORU_SERVICE_KEY = 'local booru'
TRASH_SERVICE_KEY = 'trash'
COMBINED_LOCAL_FILES_SERVICE_KEY = 'all local files'
COMBINED_LOCAL_FILE_SERVICE_KEY = 'all local files'
COMBINED_FILE_SERVICE_KEY = 'all known files'

View File

@ -661,6 +661,11 @@ class Controller( HydrusController.HydrusController ):
HydrusData.ShowText( 'The client has updated to version ' + str( HC.SOFTWARE_VERSION ) + '!' )
for message in self._db.GetInitialMessages():
HydrusData.ShowText( message )
def LastShutdownWasBad( self ):
@ -888,7 +893,7 @@ class Controller( HydrusController.HydrusController ):
import ClientLocalServer
self._local_service = reactor.listenTCP( port, ClientLocalServer.HydrusServiceLocal( CC.LOCAL_FILE_SERVICE_KEY, HC.LOCAL_FILE, 'This is the local file service.' ), interface = '127.0.0.1' )
self._local_service = reactor.listenTCP( port, ClientLocalServer.HydrusServiceLocal( CC.COMBINED_LOCAL_FILE_SERVICE_KEY, HC.COMBINED_LOCAL_FILE, 'This is the local file service.' ), interface = '127.0.0.1' )
try:

View File

@ -1015,15 +1015,15 @@ def GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id ):
suffix = str( file_service_id ) + '_' + str( tag_service_id )
files_table_name = 'external_caches.specific_files_cache_' + suffix
cache_files_table_name = 'external_caches.specific_files_cache_' + suffix
current_mappings_table_name = 'external_caches.specific_current_mappings_cache_' + suffix
cache_current_mappings_table_name = 'external_caches.specific_current_mappings_cache_' + suffix
pending_mappings_table_name = 'external_caches.specific_pending_mappings_cache_' + suffix
cache_pending_mappings_table_name = 'external_caches.specific_pending_mappings_cache_' + suffix
ac_cache_table_name = 'external_caches.specific_ac_cache_' + suffix
return ( files_table_name, current_mappings_table_name, pending_mappings_table_name, ac_cache_table_name )
return ( cache_files_table_name, cache_current_mappings_table_name, cache_pending_mappings_table_name, ac_cache_table_name )
class DB( HydrusDB.HydrusDB ):
@ -1033,6 +1033,8 @@ class DB( HydrusDB.HydrusDB ):
self._updates_dir = os.path.join( db_dir, 'client_updates' )
self._initial_messages = []
HydrusDB.HydrusDB.__init__( self, controller, db_dir, db_name, no_wal = no_wal )
@ -1061,13 +1063,15 @@ class DB( HydrusDB.HydrusDB ):
if len( valid_hash_ids ) > 0:
self._c.executemany( 'INSERT OR IGNORE INTO current_files VALUES ( ?, ?, ? );', ( ( service_id, hash_id, timestamp ) for ( hash_id, timestamp ) in rows if hash_id in valid_hash_ids ) )
valid_rows = [ ( hash_id, timestamp ) for ( hash_id, timestamp ) in rows if hash_id in valid_hash_ids ]
splayed_valid_hash_ids = HydrusData.SplayListForDB( valid_hash_ids )
self._c.execute( 'DELETE FROM deleted_files WHERE service_id = ? AND hash_id IN ' + splayed_valid_hash_ids + ';', ( service_id, ) )
# insert the files
num_deleted = self._GetRowCount()
self._c.executemany( 'INSERT OR IGNORE INTO current_files VALUES ( ?, ?, ? );', ( ( service_id, hash_id, timestamp ) for ( hash_id, timestamp ) in valid_rows ) )
self._c.execute( 'DELETE FROM file_transfers WHERE service_id = ? AND hash_id IN ' + splayed_valid_hash_ids + ';', ( service_id, ) )
info = self._c.execute( 'SELECT size, mime FROM files_info WHERE hash_id IN ' + splayed_valid_hash_ids + ';' ).fetchall()
@ -1077,32 +1081,39 @@ class DB( HydrusDB.HydrusDB ):
service_info_updates = []
service_info_updates.append( ( -num_deleted, service_id, HC.SERVICE_INFO_NUM_DELETED_FILES ) )
service_info_updates.append( ( delta_size, service_id, HC.SERVICE_INFO_TOTAL_SIZE ) )
service_info_updates.append( ( num_files, service_id, HC.SERVICE_INFO_NUM_FILES ) )
service_info_updates.append( ( num_inbox, service_id, HC.SERVICE_INFO_NUM_INBOX ) )
self._c.executemany( 'UPDATE service_info SET info = info + ? WHERE service_id = ? AND info_type = ?;', service_info_updates )
self._c.execute( 'DELETE FROM file_transfers WHERE service_id = ? AND hash_id IN ' + splayed_valid_hash_ids + ';', ( service_id, ) )
if service_id == self._local_file_service_id:
self._DeleteFiles( self._trash_service_id, valid_hash_ids, files_being_undeleted = True )
if service_id == self._trash_service_id:
now = HydrusData.GetNow()
self._c.executemany( 'INSERT OR IGNORE INTO file_trash ( hash_id, timestamp ) VALUES ( ?, ? );', ( ( hash_id, now ) for hash_id in valid_hash_ids ) )
# now do special stuff
service = self._GetService( service_id )
service_type = service.GetServiceType()
if service_type in ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ):
# remove any records of previous deletion
if service_id == self._combined_local_file_service_id or service_type == HC.FILE_REPOSITORY:
self._c.execute( 'DELETE FROM deleted_files WHERE service_id = ? AND hash_id IN ' + splayed_valid_hash_ids + ';', ( service_id, ) )
num_deleted = self._GetRowCount()
service_info_updates.append( ( -num_deleted, service_id, HC.SERVICE_INFO_NUM_DELETED_FILES ) )
# if we are adding to a local file domain, remove any from the trash and add to combined local file service if needed
if service_type == HC.LOCAL_FILE_DOMAIN:
self._DeleteFiles( self._trash_service_id, valid_hash_ids )
self._AddFiles( self._combined_local_file_service_id, valid_rows )
# if we track tags for this service, update the a/c cache
if service_type in HC.AUTOCOMPLETE_CACHE_SPECIFIC_FILE_SERVICES:
tag_service_ids = self._GetServiceIds( HC.TAG_SERVICES )
@ -1112,6 +1123,10 @@ class DB( HydrusDB.HydrusDB ):
# push the service updates, done
self._c.executemany( 'UPDATE service_info SET info = info + ? WHERE service_id = ? AND info_type = ?;', service_info_updates )
def _AddHydrusSession( self, service_key, session_key, expires ):
@ -1123,21 +1138,18 @@ class DB( HydrusDB.HydrusDB ):
def _AddService( self, service_key, service_type, name, info ):
if service_type in HC.LOCAL_SERVICES:
if service_type == HC.LOCAL_BOORU:
if service_type == HC.LOCAL_BOORU:
current_time_struct = time.gmtime()
( current_year, current_month ) = ( current_time_struct.tm_year, current_time_struct.tm_mon )
if 'used_monthly_data' not in info: info[ 'used_monthly_data' ] = 0
if 'max_monthly_data' not in info: info[ 'max_monthly_data' ] = None
if 'used_monthly_requests' not in info: info[ 'used_monthly_requests' ] = 0
if 'current_data_month' not in info: info[ 'current_data_month' ] = ( current_year, current_month )
if 'port' not in info: info[ 'port' ] = None
if 'upnp' not in info: info[ 'upnp' ] = None
current_time_struct = time.gmtime()
( current_year, current_month ) = ( current_time_struct.tm_year, current_time_struct.tm_mon )
if 'used_monthly_data' not in info: info[ 'used_monthly_data' ] = 0
if 'max_monthly_data' not in info: info[ 'max_monthly_data' ] = None
if 'used_monthly_requests' not in info: info[ 'used_monthly_requests' ] = 0
if 'current_data_month' not in info: info[ 'current_data_month' ] = ( current_year, current_month )
if 'port' not in info: info[ 'port' ] = None
if 'upnp' not in info: info[ 'upnp' ] = None
if service_type in HC.REMOTE_SERVICES:
@ -1228,7 +1240,7 @@ class DB( HydrusDB.HydrusDB ):
self._CacheCombinedFilesMappingsGenerate( service_id )
file_service_ids = self._GetServiceIds( ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ) )
file_service_ids = self._GetServiceIds( HC.AUTOCOMPLETE_CACHE_SPECIFIC_FILE_SERVICES )
for file_service_id in file_service_ids:
@ -1236,7 +1248,7 @@ class DB( HydrusDB.HydrusDB ):
if service_type in ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ):
if service_type in HC.AUTOCOMPLETE_CACHE_SPECIFIC_FILE_SERVICES:
tag_service_ids = self._GetServiceIds( HC.TAG_SERVICES )
@ -1964,7 +1976,7 @@ class DB( HydrusDB.HydrusDB ):
if hash_ids is None:
hash_ids = { hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM files_info, current_files USING ( hash_id ) WHERE service_id IN ' + HydrusData.SplayListForDB( ( self._local_file_service_id, self._trash_service_id ) ) + ' AND mime IN ' + HydrusData.SplayListForDB( HC.MIMES_WE_CAN_PHASH ) + ';' ) }
hash_ids = { hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM files_info, current_files USING ( hash_id ) WHERE service_id = ? AND mime IN ' + HydrusData.SplayListForDB( HC.MIMES_WE_CAN_PHASH ) + ';', ( self._combined_local_file_service_id, ) ) }
self._c.executemany( 'INSERT OR IGNORE INTO shape_maintenance_phash_regen ( hash_id ) VALUES ( ? );', ( ( hash_id, ) for hash_id in hash_ids ) )
@ -2061,9 +2073,9 @@ class DB( HydrusDB.HydrusDB ):
def _CacheSpecificMappingsAddFiles( self, file_service_id, tag_service_id, hash_ids ):
( files_table_name, current_mappings_table_name, pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
( cache_files_table_name, cache_current_mappings_table_name, cache_pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
self._c.executemany( 'INSERT OR IGNORE INTO ' + files_table_name + ' VALUES ( ? );', ( ( hash_id, ) for hash_id in hash_ids ) )
self._c.executemany( 'INSERT OR IGNORE INTO ' + cache_files_table_name + ' VALUES ( ? );', ( ( hash_id, ) for hash_id in hash_ids ) )
( current_mappings_table_name, deleted_mappings_table_name, pending_mappings_table_name, petitioned_mappings_table_name ) = GenerateMappingsTableNames( tag_service_id )
@ -2092,7 +2104,7 @@ class DB( HydrusDB.HydrusDB ):
if num_current > 0:
self._c.executemany( 'INSERT OR IGNORE INTO ' + current_mappings_table_name + ' ( hash_id, namespace_id, tag_id ) VALUES ( ?, ?, ? );', ( ( hash_id, namespace_id, tag_id ) for hash_id in current_hash_ids ) )
self._c.executemany( 'INSERT OR IGNORE INTO ' + cache_current_mappings_table_name + ' ( hash_id, namespace_id, tag_id ) VALUES ( ?, ?, ? );', ( ( hash_id, namespace_id, tag_id ) for hash_id in current_hash_ids ) )
pending_hash_ids = pending_mapping_ids_dict[ ( namespace_id, tag_id ) ]
@ -2101,7 +2113,7 @@ class DB( HydrusDB.HydrusDB ):
if num_pending > 0:
self._c.executemany( 'INSERT OR IGNORE INTO ' + pending_mappings_table_name + ' ( hash_id, namespace_id, tag_id ) VALUES ( ?, ?, ? );', ( ( hash_id, namespace_id, tag_id ) for hash_id in pending_hash_ids ) )
self._c.executemany( 'INSERT OR IGNORE INTO ' + cache_pending_mappings_table_name + ' ( hash_id, namespace_id, tag_id ) VALUES ( ?, ?, ? );', ( ( hash_id, namespace_id, tag_id ) for hash_id in pending_hash_ids ) )
if num_current > 0 or num_pending > 0:
@ -2121,7 +2133,7 @@ class DB( HydrusDB.HydrusDB ):
def _CacheSpecificMappingsAddMappings( self, file_service_id, tag_service_id, mappings_ids ):
( files_table_name, current_mappings_table_name, pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
( cache_files_table_name, cache_current_mappings_table_name, cache_pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
for ( namespace_id, tag_id, hash_ids ) in mappings_ids:
@ -2129,13 +2141,13 @@ class DB( HydrusDB.HydrusDB ):
if len( hash_ids ) > 0:
self._c.executemany( 'DELETE FROM ' + pending_mappings_table_name + ' WHERE hash_id = ? AND namespace_id = ? AND tag_id = ?;', ( ( hash_id, namespace_id, tag_id ) for hash_id in hash_ids ) )
self._c.executemany( 'DELETE FROM ' + cache_pending_mappings_table_name + ' WHERE hash_id = ? AND namespace_id = ? AND tag_id = ?;', ( ( hash_id, namespace_id, tag_id ) for hash_id in hash_ids ) )
num_pending_rescinded = self._GetRowCount()
#
self._c.executemany( 'INSERT OR IGNORE INTO ' + current_mappings_table_name + ' ( hash_id, namespace_id, tag_id ) VALUES ( ?, ?, ? );', ( ( hash_id, namespace_id, tag_id ) for hash_id in hash_ids ) )
self._c.executemany( 'INSERT OR IGNORE INTO ' + cache_current_mappings_table_name + ' ( hash_id, namespace_id, tag_id ) VALUES ( ?, ?, ? );', ( ( hash_id, namespace_id, tag_id ) for hash_id in hash_ids ) )
num_added = self._GetRowCount()
@ -2155,22 +2167,22 @@ class DB( HydrusDB.HydrusDB ):
def _CacheSpecificMappingsDrop( self, file_service_id, tag_service_id ):
( files_table_name, current_mappings_table_name, pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
( cache_files_table_name, cache_current_mappings_table_name, cache_pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
self._c.execute( 'DROP TABLE ' + files_table_name + ';' )
self._c.execute( 'DROP TABLE ' + cache_files_table_name + ';' )
self._c.execute( 'DROP TABLE ' + current_mappings_table_name + ';' )
self._c.execute( 'DROP TABLE ' + cache_current_mappings_table_name + ';' )
self._c.execute( 'DROP TABLE ' + pending_mappings_table_name + ';' )
self._c.execute( 'DROP TABLE ' + cache_pending_mappings_table_name + ';' )
self._c.execute( 'DROP TABLE ' + ac_cache_table_name + ';' )
def _CacheSpecificMappingsDeleteFiles( self, file_service_id, tag_service_id, hash_ids ):
( files_table_name, current_mappings_table_name, pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
( cache_files_table_name, cache_current_mappings_table_name, cache_pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
self._c.executemany( 'DELETE FROM ' + files_table_name + ' WHERE hash_id = ?;', ( ( hash_id, ) for hash_id in hash_ids ) )
self._c.executemany( 'DELETE FROM ' + cache_files_table_name + ' WHERE hash_id = ?;', ( ( hash_id, ) for hash_id in hash_ids ) )
ac_cache_changes = []
@ -2178,11 +2190,11 @@ class DB( HydrusDB.HydrusDB ):
splayed_group_of_hash_ids = HydrusData.SplayListForDB( group_of_hash_ids )
current_mapping_ids_raw = self._c.execute( 'SELECT namespace_id, tag_id, hash_id FROM ' + current_mappings_table_name + ' WHERE hash_id IN ' + splayed_group_of_hash_ids + ';' ).fetchall()
current_mapping_ids_raw = self._c.execute( 'SELECT namespace_id, tag_id, hash_id FROM ' + cache_current_mappings_table_name + ' WHERE hash_id IN ' + splayed_group_of_hash_ids + ';' ).fetchall()
current_mapping_ids_dict = HydrusData.BuildKeyToSetDict( [ ( ( namespace_id, tag_id ), hash_id ) for ( namespace_id, tag_id, hash_id ) in current_mapping_ids_raw ] )
pending_mapping_ids_raw = self._c.execute( 'SELECT namespace_id, tag_id, hash_id FROM ' + pending_mappings_table_name + ' WHERE hash_id IN ' + splayed_group_of_hash_ids + ';' ).fetchall()
pending_mapping_ids_raw = self._c.execute( 'SELECT namespace_id, tag_id, hash_id FROM ' + cache_pending_mappings_table_name + ' WHERE hash_id IN ' + splayed_group_of_hash_ids + ';' ).fetchall()
pending_mapping_ids_dict = HydrusData.BuildKeyToSetDict( [ ( ( namespace_id, tag_id ), hash_id ) for ( namespace_id, tag_id, hash_id ) in pending_mapping_ids_raw ] )
@ -2197,7 +2209,7 @@ class DB( HydrusDB.HydrusDB ):
if num_current > 0:
self._c.executemany( 'DELETE FROM ' + current_mappings_table_name + ' WHERE namespace_id = ? AND tag_id = ? AND hash_id = ?;', ( ( namespace_id, tag_id, hash_id ) for hash_id in current_hash_ids ) )
self._c.executemany( 'DELETE FROM ' + cache_current_mappings_table_name + ' WHERE namespace_id = ? AND tag_id = ? AND hash_id = ?;', ( ( namespace_id, tag_id, hash_id ) for hash_id in current_hash_ids ) )
pending_hash_ids = pending_mapping_ids_dict[ ( namespace_id, tag_id ) ]
@ -2206,7 +2218,7 @@ class DB( HydrusDB.HydrusDB ):
if num_pending > 0:
self._c.executemany( 'DELETE FROM ' + pending_mappings_table_name + ' WHERE namespace_id = ? AND tag_id = ? AND hash_id = ?;', ( ( namespace_id, tag_id, hash_id ) for hash_id in pending_hash_ids ) )
self._c.executemany( 'DELETE FROM ' + cache_pending_mappings_table_name + ' WHERE namespace_id = ? AND tag_id = ? AND hash_id = ?;', ( ( namespace_id, tag_id, hash_id ) for hash_id in pending_hash_ids ) )
ac_cache_changes.append( ( namespace_id, tag_id, num_current, num_pending ) )
@ -2223,7 +2235,7 @@ class DB( HydrusDB.HydrusDB ):
def _CacheSpecificMappingsDeleteMappings( self, file_service_id, tag_service_id, mappings_ids ):
( files_table_name, current_mappings_table_name, pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
( cache_files_table_name, cache_current_mappings_table_name, cache_pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
for ( namespace_id, tag_id, hash_ids ) in mappings_ids:
@ -2231,7 +2243,7 @@ class DB( HydrusDB.HydrusDB ):
if len( hash_ids ) > 0:
self._c.executemany( 'DELETE FROM ' + current_mappings_table_name + ' WHERE hash_id = ? AND namespace_id = ? AND tag_id = ?;', ( ( hash_id, namespace_id, tag_id ) for hash_id in hash_ids ) )
self._c.executemany( 'DELETE FROM ' + cache_current_mappings_table_name + ' WHERE hash_id = ? AND namespace_id = ? AND tag_id = ?;', ( ( hash_id, namespace_id, tag_id ) for hash_id in hash_ids ) )
num_deleted = self._GetRowCount()
@ -2247,20 +2259,20 @@ class DB( HydrusDB.HydrusDB ):
def _CacheSpecificMappingsFilterHashIds( self, file_service_id, tag_service_id, hash_ids ):
( files_table_name, current_mappings_table_name, pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
( cache_files_table_name, cache_current_mappings_table_name, cache_pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
return [ hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM ' + files_table_name + ' WHERE hash_id IN ' + HydrusData.SplayListForDB( hash_ids ) + ';' ) ]
return [ hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM ' + cache_files_table_name + ' WHERE hash_id IN ' + HydrusData.SplayListForDB( hash_ids ) + ';' ) ]
def _CacheSpecificMappingsGenerate( self, file_service_id, tag_service_id ):
( files_table_name, current_mappings_table_name, pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
( cache_files_table_name, cache_current_mappings_table_name, cache_pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
self._c.execute( 'CREATE TABLE ' + files_table_name + ' ( hash_id INTEGER PRIMARY KEY );' )
self._c.execute( 'CREATE TABLE ' + cache_files_table_name + ' ( hash_id INTEGER PRIMARY KEY );' )
self._c.execute( 'CREATE TABLE ' + current_mappings_table_name + ' ( hash_id INTEGER, namespace_id INTEGER, tag_id INTEGER, PRIMARY KEY( hash_id, namespace_id, tag_id ) ) WITHOUT ROWID;' )
self._c.execute( 'CREATE TABLE ' + cache_current_mappings_table_name + ' ( hash_id INTEGER, namespace_id INTEGER, tag_id INTEGER, PRIMARY KEY( hash_id, namespace_id, tag_id ) ) WITHOUT ROWID;' )
self._c.execute( 'CREATE TABLE ' + pending_mappings_table_name + ' ( hash_id INTEGER, namespace_id INTEGER, tag_id INTEGER, PRIMARY KEY( hash_id, namespace_id, tag_id ) ) WITHOUT ROWID;' )
self._c.execute( 'CREATE TABLE ' + cache_pending_mappings_table_name + ' ( hash_id INTEGER, namespace_id INTEGER, tag_id INTEGER, PRIMARY KEY( hash_id, namespace_id, tag_id ) ) WITHOUT ROWID;' )
self._c.execute( 'CREATE TABLE ' + ac_cache_table_name + ' ( namespace_id INTEGER, tag_id INTEGER, current_count INTEGER, pending_count INTEGER, PRIMARY KEY( namespace_id, tag_id ) ) WITHOUT ROWID;' )
@ -2276,7 +2288,7 @@ class DB( HydrusDB.HydrusDB ):
def _CacheSpecificMappingsGetAutocompleteCounts( self, file_service_id, tag_service_id, namespace_ids_to_tag_ids ):
( files_table_name, current_mappings_table_name, pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
( cache_files_table_name, cache_current_mappings_table_name, cache_pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
results = []
@ -2290,7 +2302,7 @@ class DB( HydrusDB.HydrusDB ):
def _CacheSpecificMappingsPendMappings( self, file_service_id, tag_service_id, mappings_ids ):
( files_table_name, current_mappings_table_name, pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
( cache_files_table_name, cache_current_mappings_table_name, cache_pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
for ( namespace_id, tag_id, hash_ids ) in mappings_ids:
@ -2298,7 +2310,7 @@ class DB( HydrusDB.HydrusDB ):
if len( hash_ids ) > 0:
self._c.executemany( 'INSERT OR IGNORE INTO ' + pending_mappings_table_name + ' ( hash_id, namespace_id, tag_id ) VALUES ( ?, ?, ? );', ( ( hash_id, namespace_id, tag_id ) for hash_id in hash_ids ) )
self._c.executemany( 'INSERT OR IGNORE INTO ' + cache_pending_mappings_table_name + ' ( hash_id, namespace_id, tag_id ) VALUES ( ?, ?, ? );', ( ( hash_id, namespace_id, tag_id ) for hash_id in hash_ids ) )
num_added = self._GetRowCount()
@ -2315,7 +2327,7 @@ class DB( HydrusDB.HydrusDB ):
def _CacheSpecificMappingsRescindPendingMappings( self, file_service_id, tag_service_id, mappings_ids ):
( files_table_name, current_mappings_table_name, pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
( cache_files_table_name, cache_current_mappings_table_name, cache_pending_mappings_table_name, ac_cache_table_name ) = GenerateSpecificMappingsCacheTableNames( file_service_id, tag_service_id )
for ( namespace_id, tag_id, hash_ids ) in mappings_ids:
@ -2323,7 +2335,7 @@ class DB( HydrusDB.HydrusDB ):
if len( hash_ids ) > 0:
self._c.executemany( 'DELETE FROM ' + pending_mappings_table_name + ' WHERE hash_id = ? AND namespace_id = ? AND tag_id = ?;', ( ( hash_id, namespace_id, tag_id ) for hash_id in hash_ids ) )
self._c.executemany( 'DELETE FROM ' + cache_pending_mappings_table_name + ' WHERE hash_id = ? AND namespace_id = ? AND tag_id = ?;', ( ( hash_id, namespace_id, tag_id ) for hash_id in hash_ids ) )
num_deleted = self._GetRowCount()
@ -2402,7 +2414,7 @@ class DB( HydrusDB.HydrusDB ):
self._controller.pub( 'message', job_key )
info = self._c.execute( 'SELECT hash_id, mime FROM current_files, files_info USING ( hash_id ) WHERE service_id IN ( ?, ? );', ( self._local_file_service_id, self._trash_service_id ) ).fetchall()
info = self._c.execute( 'SELECT hash_id, mime FROM current_files, files_info USING ( hash_id ) WHERE service_id = ?;', ( self._combined_local_file_service_id, ) ).fetchall()
missing_count = 0
deletee_hash_ids = []
@ -2464,6 +2476,7 @@ class DB( HydrusDB.HydrusDB ):
self._DeleteFiles( self._local_file_service_id, deletee_hash_ids )
self._DeleteFiles( self._trash_service_id, deletee_hash_ids )
self._DeleteFiles( self._combined_local_file_service_id, deletee_hash_ids )
final_text = 'done! '
@ -2562,9 +2575,6 @@ class DB( HydrusDB.HydrusDB ):
self._c.execute( 'CREATE TABLE file_transfers ( service_id INTEGER REFERENCES services ON DELETE CASCADE, hash_id INTEGER, PRIMARY KEY( service_id, hash_id ) );' )
self._c.execute( 'CREATE INDEX file_transfers_hash_id ON file_transfers ( hash_id );' )
self._c.execute( 'CREATE TABLE file_trash ( hash_id INTEGER PRIMARY KEY, timestamp INTEGER );' )
self._c.execute( 'CREATE INDEX file_trash_timestamp ON file_trash ( timestamp );' )
self._c.execute( 'CREATE TABLE file_petitions ( service_id INTEGER REFERENCES services ON DELETE CASCADE, hash_id INTEGER, reason_id INTEGER, PRIMARY KEY( service_id, hash_id, reason_id ) );' )
self._c.execute( 'CREATE INDEX file_petitions_hash_id_index ON file_petitions ( hash_id );' )
@ -2694,8 +2704,9 @@ class DB( HydrusDB.HydrusDB ):
init_service_info = []
init_service_info.append( ( CC.LOCAL_FILE_SERVICE_KEY, HC.LOCAL_FILE, CC.LOCAL_FILE_SERVICE_KEY ) )
init_service_info.append( ( CC.TRASH_SERVICE_KEY, HC.LOCAL_FILE, CC.TRASH_SERVICE_KEY ) )
init_service_info.append( ( CC.COMBINED_LOCAL_FILE_SERVICE_KEY, HC.COMBINED_LOCAL_FILE, CC.COMBINED_LOCAL_FILE_SERVICE_KEY ) )
init_service_info.append( ( CC.LOCAL_FILE_SERVICE_KEY, HC.LOCAL_FILE_DOMAIN, 'my files' ) )
init_service_info.append( ( CC.TRASH_SERVICE_KEY, HC.LOCAL_FILE_TRASH_DOMAIN, CC.TRASH_SERVICE_KEY ) )
init_service_info.append( ( CC.LOCAL_TAG_SERVICE_KEY, HC.LOCAL_TAG, CC.LOCAL_TAG_SERVICE_KEY ) )
init_service_info.append( ( CC.COMBINED_FILE_SERVICE_KEY, HC.COMBINED_FILE, CC.COMBINED_FILE_SERVICE_KEY ) )
init_service_info.append( ( CC.COMBINED_TAG_SERVICE_KEY, HC.COMBINED_TAG, CC.COMBINED_TAG_SERVICE_KEY ) )
@ -2727,19 +2738,23 @@ class DB( HydrusDB.HydrusDB ):
self._c.execute( 'COMMIT;' )
def _DeleteFiles( self, service_id, hash_ids, files_being_undeleted = False ):
def _DeleteFiles( self, service_id, hash_ids ):
splayed_hash_ids = HydrusData.SplayListForDB( hash_ids )
rows = self._c.execute( 'SELECT hash_id, timestamp FROM current_files WHERE service_id = ? AND hash_id IN ' + splayed_hash_ids + ';', ( service_id, ) ).fetchall()
valid_hash_ids = { row[ 0 ] for row in rows }
valid_hash_ids = { hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM current_files WHERE service_id = ? AND hash_id IN ' + splayed_hash_ids + ';', ( service_id, ) ) }
if len( valid_hash_ids ) > 0:
splayed_valid_hash_ids = HydrusData.SplayListForDB( valid_hash_ids )
info = self._c.execute( 'SELECT size, mime FROM files_info WHERE hash_id IN ' + splayed_hash_ids + ';' ).fetchall()
# remove them from the service
self._c.execute( 'DELETE FROM current_files WHERE service_id = ? AND hash_id IN ' + splayed_valid_hash_ids + ';', ( service_id, ) )
self._c.execute( 'DELETE FROM file_petitions WHERE service_id = ? AND hash_id IN ' + splayed_valid_hash_ids + ';', ( service_id, ) )
info = self._c.execute( 'SELECT size, mime FROM files_info WHERE hash_id IN ' + splayed_valid_hash_ids + ';' ).fetchall()
num_files = len( valid_hash_ids )
delta_size = sum( ( size for ( size, mime ) in info ) )
@ -2751,42 +2766,24 @@ class DB( HydrusDB.HydrusDB ):
service_info_updates.append( ( -num_files, service_id, HC.SERVICE_INFO_NUM_FILES ) )
service_info_updates.append( ( -num_inbox, service_id, HC.SERVICE_INFO_NUM_INBOX ) )
if service_id != self._trash_service_id:
# trash service doesn't keep track of what is deleted, as this is redundant
service_info_updates.append( ( num_files, service_id, HC.SERVICE_INFO_NUM_DELETED_FILES ) )
self._c.executemany( 'INSERT OR IGNORE INTO deleted_files ( service_id, hash_id ) VALUES ( ?, ? );', [ ( service_id, hash_id ) for hash_id in hash_ids ] )
self._c.executemany( 'UPDATE service_info SET info = info + ? WHERE service_id = ? AND info_type = ?;', service_info_updates )
self._c.execute( 'DELETE FROM current_files WHERE service_id = ? AND hash_id IN ' + splayed_hash_ids + ';', ( service_id, ) )
self._c.execute( 'DELETE FROM file_petitions WHERE service_id = ? AND hash_id IN ' + splayed_hash_ids + ';', ( service_id, ) )
if service_id == self._local_file_service_id:
self._AddFiles( self._trash_service_id, rows )
if service_id == self._trash_service_id:
self._c.execute( 'DELETE FROM file_trash WHERE hash_id IN ' + splayed_hash_ids + ';' )
if not files_being_undeleted:
self._ArchiveFiles( hash_ids )
self._DeletePhysicalFiles( hash_ids )
# now do special stuff
service = self._GetService( service_id )
service_type = service.GetServiceType()
if service_type in ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ):
# record the deleted row if appropriate
if service_id == self._combined_local_file_service_id or service_type == HC.FILE_REPOSITORY:
service_info_updates.append( ( num_files, service_id, HC.SERVICE_INFO_NUM_DELETED_FILES ) )
self._c.executemany( 'INSERT OR IGNORE INTO deleted_files ( service_id, hash_id ) VALUES ( ?, ? );', [ ( service_id, hash_id ) for hash_id in valid_hash_ids ] )
# if we maintain tag counts for this service, update
if service_type in HC.AUTOCOMPLETE_CACHE_SPECIFIC_FILE_SERVICES:
tag_service_ids = self._GetServiceIds( HC.TAG_SERVICES )
@ -2796,9 +2793,44 @@ class DB( HydrusDB.HydrusDB ):
# if the files are no longer in any local file services, send them to the trash
local_file_service_ids = self._GetServiceIds( ( HC.LOCAL_FILE_DOMAIN, ) )
if service_id in local_file_service_ids:
splayed_local_file_service_ids = HydrusData.SplayListForDB( local_file_service_ids )
non_orphan_hash_ids = { hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM current_files WHERE hash_id IN ' + splayed_valid_hash_ids + ' AND service_id IN ' + splayed_local_file_service_ids + ';' ) }
orphan_hash_ids = valid_hash_ids.difference( non_orphan_hash_ids )
if len( orphan_hash_ids ) > 0:
now = HydrusData.GetNow()
delete_rows = [ ( hash_id, now ) for hash_id in orphan_hash_ids ]
self._AddFiles( self._trash_service_id, delete_rows )
# if the files are being fully deleted, then physically delete them
if service_id == self._combined_local_file_service_id:
self._DeletePhysicalFiles( valid_hash_ids )
# push the info updates, notify
self._c.executemany( 'UPDATE service_info SET info = info + ? WHERE service_id = ? AND info_type = ?;', service_info_updates )
self.pub_after_commit( 'notify_new_pending' )
return valid_hash_ids
def _DeleteHydrusSessionKey( self, service_key ):
@ -2863,6 +2895,8 @@ class DB( HydrusDB.HydrusDB ):
def _DeletePhysicalFiles( self, hash_ids ):
self._ArchiveFiles( hash_ids )
hash_ids = set( hash_ids )
potentially_pending_upload_hash_ids = { hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM file_transfers;', ) }
@ -2917,7 +2951,7 @@ class DB( HydrusDB.HydrusDB ):
self._CacheCombinedFilesMappingsDrop( service_id )
file_service_ids = self._GetServiceIds( ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ) )
file_service_ids = self._GetServiceIds( HC.AUTOCOMPLETE_CACHE_SPECIFIC_FILE_SERVICES )
for file_service_id in file_service_ids:
@ -2925,7 +2959,7 @@ class DB( HydrusDB.HydrusDB ):
if service_type in ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ):
if service_type in HC.AUTOCOMPLETE_CACHE_SPECIFIC_FILE_SERVICES:
tag_service_ids = self._GetServiceIds( HC.TAG_SERVICES )
@ -3392,7 +3426,10 @@ class DB( HydrusDB.HydrusDB ):
return result
def _GetDownloads( self ): return { hash for ( hash, ) in self._c.execute( 'SELECT hash FROM file_transfers, hashes USING ( hash_id ) WHERE service_id = ?;', ( self._local_file_service_id, ) ) }
def _GetDownloads( self ):
return { hash for ( hash, ) in self._c.execute( 'SELECT hash FROM file_transfers, hashes USING ( hash_id ) WHERE service_id = ?;', ( self._combined_local_file_service_id, ) ) }
def _GetFileHashes( self, given_hashes, given_hash_type, desired_hash_type ):
@ -3444,7 +3481,10 @@ class DB( HydrusDB.HydrusDB ):
predicates = []
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 ] ] )
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_SERVICES:
service_info = self._GetServiceInfoSpecific( service_id, service_type, { HC.SERVICE_INFO_NUM_FILES } )
@ -3455,7 +3495,7 @@ class DB( HydrusDB.HydrusDB ):
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 ):
elif service_type in HC.FILE_SERVICES:
service_info = self._GetServiceInfoSpecific( service_id, service_type, { HC.SERVICE_INFO_NUM_FILES, HC.SERVICE_INFO_NUM_INBOX } )
@ -3465,7 +3505,7 @@ class DB( HydrusDB.HydrusDB ):
if service_type == HC.FILE_REPOSITORY:
( num_local, ) = self._c.execute( 'SELECT COUNT( * ) FROM current_files AS remote_current_files, current_files USING ( hash_id ) WHERE remote_current_files.service_id = ? AND current_files.service_id = ?;', ( service_id, self._local_file_service_id ) ).fetchone()
( num_local, ) = self._c.execute( 'SELECT COUNT( * ) FROM current_files AS remote_current_files, current_files USING ( hash_id ) WHERE remote_current_files.service_id = ? AND current_files.service_id = ?;', ( service_id, self._combined_local_file_service_id ) ).fetchone()
num_not_local = num_everything - num_local
@ -3919,7 +3959,7 @@ class DB( HydrusDB.HydrusDB ):
must_be_inbox = system_predicates.MustBeInbox()
must_be_archive = system_predicates.MustBeArchive()
if file_service_type == HC.LOCAL_FILE:
if file_service_type in HC.LOCAL_FILE_SERVICES:
if must_not_be_local:
@ -3928,7 +3968,7 @@ class DB( HydrusDB.HydrusDB ):
elif must_be_local or must_not_be_local:
local_hash_ids = [ id for ( id, ) in self._c.execute( 'SELECT hash_id FROM current_files WHERE service_id = ?;', ( self._local_file_service_id, ) ) ]
local_hash_ids = [ id for ( id, ) in self._c.execute( 'SELECT hash_id FROM current_files WHERE service_id = ?;', ( self._combined_local_file_service_id, ) ) ]
if must_be_local:
@ -4404,14 +4444,21 @@ class DB( HydrusDB.HydrusDB ):
def _GetHashIdStatus( self, hash_id ):
result = self._c.execute( 'SELECT 1 FROM deleted_files WHERE service_id = ? AND hash_id = ?;', ( self._local_file_service_id, hash_id ) ).fetchone()
result = self._c.execute( 'SELECT 1 FROM deleted_files WHERE service_id = ? AND hash_id = ?;', ( self._combined_local_file_service_id, hash_id ) ).fetchone()
if result is not None:
return ( CC.STATUS_DELETED, None )
result = self._c.execute( 'SELECT 1 FROM current_files WHERE service_id = ? AND hash_id = ?;', ( self._local_file_service_id, hash_id ) ).fetchone()
result = self._c.execute( 'SELECT 1 FROM current_files WHERE service_id = ? AND hash_id = ?;', ( self._trash_service_id, hash_id ) ).fetchone()
if result is not None:
return ( CC.STATUS_DELETED, None )
result = self._c.execute( 'SELECT 1 FROM current_files WHERE service_id = ? AND hash_id = ?;', ( self._combined_local_file_service_id, hash_id ) ).fetchone()
if result is not None:
@ -5152,7 +5199,7 @@ class DB( HydrusDB.HydrusDB ):
hash_ids = { hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM current_files, files_info USING ( hash_id ) WHERE mime IN ' + HydrusData.SplayListForDB( HC.MIMES_WITH_THUMBNAILS ) + ' AND service_id = ?;', ( service_id, ) ) }
hash_ids.difference_update( ( hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM current_files WHERE service_id = ?;', ( self._local_file_service_id, ) ) ) )
hash_ids.difference_update( ( hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM current_files WHERE service_id = ?;', ( self._combined_local_file_service_id, ) ) ) )
hashes = set( self._GetHashes( hash_ids ) )
@ -5280,10 +5327,14 @@ class DB( HydrusDB.HydrusDB ):
service_type = service.GetServiceType()
if service_type == HC.LOCAL_FILE:
if service_type == HC.COMBINED_LOCAL_FILE:
info_types = { HC.SERVICE_INFO_NUM_FILES, HC.SERVICE_INFO_TOTAL_SIZE, HC.SERVICE_INFO_NUM_DELETED_FILES }
elif service_type in ( HC.LOCAL_FILE_DOMAIN, HC.LOCAL_FILE_TRASH_DOMAIN ):
info_types = { HC.SERVICE_INFO_NUM_FILES, HC.SERVICE_INFO_TOTAL_SIZE }
elif service_type == HC.FILE_REPOSITORY:
info_types = { HC.SERVICE_INFO_NUM_FILES, HC.SERVICE_INFO_TOTAL_SIZE, HC.SERVICE_INFO_NUM_DELETED_FILES }
@ -5352,7 +5403,7 @@ class DB( HydrusDB.HydrusDB ):
save_it = True
if service_type in ( HC.LOCAL_FILE, HC.FILE_REPOSITORY, HC.IPFS ):
if service_type in HC.FILE_SERVICES:
if info_type in ( HC.SERVICE_INFO_NUM_PENDING_FILES, HC.SERVICE_INFO_NUM_PETITIONED_FILES ): save_it = False
@ -5577,10 +5628,10 @@ class DB( HydrusDB.HydrusDB ):
timestamp_cutoff = HydrusData.GetNow() - minimum_age
age_phrase = ' WHERE timestamp < ' + str( timestamp_cutoff ) + ' ORDER BY timestamp ASC'
age_phrase = ' AND timestamp < ' + str( timestamp_cutoff ) + ' ORDER BY timestamp ASC'
hash_ids = { hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM file_trash' + age_phrase + limit_phrase + ';' ) }
hash_ids = { hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM current_files WHERE service_id = ?' + age_phrase + limit_phrase + ';', ( self._trash_service_id, ) ) }
return self._GetHashes( hash_ids )
@ -5710,7 +5761,7 @@ class DB( HydrusDB.HydrusDB ):
self._ArchiveFiles( ( hash_id, ) )
self.pub_content_updates_after_commit( { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, set( ( hash, ) ) ) ] } )
self.pub_content_updates_after_commit( { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, set( ( hash, ) ) ) ] } )
elif status == CC.STATUS_NEW:
@ -5846,6 +5897,7 @@ class DB( HydrusDB.HydrusDB ):
self._local_file_service_id = self._GetServiceId( CC.LOCAL_FILE_SERVICE_KEY )
self._trash_service_id = self._GetServiceId( CC.TRASH_SERVICE_KEY )
self._combined_local_file_service_id = self._GetServiceId( CC.COMBINED_LOCAL_FILE_SERVICE_KEY )
self._local_tag_service_id = self._GetServiceId( CC.LOCAL_TAG_SERVICE_KEY )
self._combined_file_service_id = self._GetServiceId( CC.COMBINED_FILE_SERVICE_KEY )
self._combined_tag_service_id = self._GetServiceId( CC.COMBINED_TAG_SERVICE_KEY )
@ -5875,7 +5927,7 @@ class DB( HydrusDB.HydrusDB ):
hash_id = self._GetHashId( hash )
result = self._c.execute( 'SELECT 1 FROM current_files WHERE service_id IN ( ?, ? ) AND hash_id = ?;', ( self._local_file_service_id, self._trash_service_id, hash_id ) ).fetchone()
result = self._c.execute( 'SELECT 1 FROM current_files WHERE service_id = ? AND hash_id = ?;', ( self._combined_local_file_service_id, hash_id ) ).fetchone()
if result is None:
@ -6207,7 +6259,7 @@ class DB( HydrusDB.HydrusDB ):
( data_type, action, row ) = content_update.ToTuple()
if service_type in ( HC.FILE_REPOSITORY, HC.LOCAL_FILE, HC.IPFS ):
if service_type in HC.FILE_SERVICES:
if data_type == HC.CONTENT_TYPE_FILES:
@ -6224,7 +6276,7 @@ class DB( HydrusDB.HydrusDB ):
elif action == HC.CONTENT_UPDATE_ADD:
if service_type in ( HC.FILE_REPOSITORY, HC.LOCAL_FILE ):
if service_type in HC.LOCAL_FILE_SERVICES or service_type == HC.FILE_REPOSITORY:
( hash, size, mime, timestamp, width, height, duration, num_frames, num_words ) = row
@ -6253,7 +6305,7 @@ class DB( HydrusDB.HydrusDB ):
self._c.executemany( 'INSERT OR IGNORE INTO file_transfers ( service_id, hash_id ) VALUES ( ?, ? );', [ ( service_id, hash_id ) for hash_id in hash_ids ] )
if service_key == CC.LOCAL_FILE_SERVICE_KEY: notify_new_downloads = True
if service_key == CC.COMBINED_LOCAL_FILE_SERVICE_KEY: notify_new_downloads = True
else: notify_new_pending = True
elif action == HC.CONTENT_UPDATE_PETITION:
@ -6298,8 +6350,23 @@ class DB( HydrusDB.HydrusDB ):
if action == HC.CONTENT_UPDATE_ARCHIVE: self._ArchiveFiles( hash_ids )
elif action == HC.CONTENT_UPDATE_INBOX: self._InboxFiles( hash_ids )
elif action == HC.CONTENT_UPDATE_DELETE: self._DeleteFiles( service_id, hash_ids )
elif action == HC.CONTENT_UPDATE_UNDELETE: self._UndeleteFiles( hash_ids )
elif action == HC.CONTENT_UPDATE_DELETE:
deleted_hash_ids = self._DeleteFiles( service_id, hash_ids )
if service_id == self._trash_service_id:
self._DeleteFiles( self._combined_local_file_service_id, deleted_hash_ids )
elif action == HC.CONTENT_UPDATE_UNDELETE:
splayed_hash_ids = HydrusData.SplayListForDB( hash_ids )
rows = self._c.execute( 'SELECT hash_id, timestamp FROM current_files WHERE service_id = ? AND hash_id IN ' + splayed_hash_ids + ';', ( self._combined_local_file_service_id, ) ).fetchall()
self._AddFiles( self._local_file_service_id, rows )
elif data_type == HC.CONTENT_TYPE_DIRECTORIES:
@ -6679,8 +6746,14 @@ class DB( HydrusDB.HydrusDB ):
if do_pubsubs:
if notify_new_downloads: self.pub_after_commit( 'notify_new_downloads' )
if notify_new_pending: self.pub_after_commit( 'notify_new_pending' )
if notify_new_downloads:
self.pub_after_commit( 'notify_new_downloads' )
if notify_new_pending:
self.pub_after_commit( 'notify_new_pending' )
if notify_new_siblings:
self.pub_after_commit( 'notify_new_siblings_data' )
@ -6935,7 +7008,7 @@ class DB( HydrusDB.HydrusDB ):
self._controller.pub( 'message', job_key )
tag_service_ids = self._GetServiceIds( HC.TAG_SERVICES )
file_service_ids = self._GetServiceIds( ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ) )
file_service_ids = self._GetServiceIds( HC.AUTOCOMPLETE_CACHE_SPECIFIC_FILE_SERVICES )
for ( file_service_id, tag_service_id ) in itertools.product( file_service_ids, tag_service_ids ):
@ -7286,18 +7359,6 @@ class DB( HydrusDB.HydrusDB ):
def _UndeleteFiles( self, hash_ids ):
splayed_hash_ids = HydrusData.SplayListForDB( hash_ids )
rows = self._c.execute( 'SELECT hash_id, timestamp FROM current_files WHERE service_id = ? AND hash_id IN ' + splayed_hash_ids + ';', ( self._trash_service_id, ) ).fetchall()
if len( rows ) > 0:
self._AddFiles( self._local_file_service_id, rows )
def _UpdateDB( self, version ):
self._controller.pub( 'splash_set_title_text', 'updating db to v' + str( version + 1 ) )
@ -7684,7 +7745,7 @@ class DB( HydrusDB.HydrusDB ):
if version == 201:
file_service_ids = self._GetServiceIds( ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ) )
file_service_ids = self._GetServiceIds( ( HC.LOCAL_FILE_DOMAIN, HC.FILE_REPOSITORY ) )
tag_service_ids = self._GetServiceIds( ( HC.LOCAL_TAG, HC.TAG_REPOSITORY ) )
for ( file_service_id, tag_service_id ) in itertools.product( file_service_ids, tag_service_ids ):
@ -8606,6 +8667,62 @@ class DB( HydrusDB.HydrusDB ):
if version == 236:
self._controller.pub( 'splash_set_status_text', 'updating local files services' )
# update existing services
self._c.execute( 'UPDATE services SET name = ? WHERE service_key = ?;', ( 'my files', sqlite3.Binary( CC.LOCAL_FILE_SERVICE_KEY ) ) )
self._c.execute( 'UPDATE services SET service_type = ? WHERE service_key = ?;', ( HC.LOCAL_FILE_TRASH_DOMAIN, sqlite3.Binary( CC.TRASH_SERVICE_KEY ) ) )
# create new umbrella service that represents if we have the file or not locally
self._AddService( CC.COMBINED_LOCAL_FILE_SERVICE_KEY, HC.COMBINED_LOCAL_FILE, CC.COMBINED_LOCAL_FILE_SERVICE_KEY, {} )
combined_local_file_service_id = self._GetServiceId( CC.COMBINED_LOCAL_FILE_SERVICE_KEY )
local_file_service_id = self._GetServiceId( CC.LOCAL_FILE_SERVICE_KEY )
trash_service_id = self._GetServiceId( CC.TRASH_SERVICE_KEY )
# copy all local/trash records to the new umbrella service, and move deleted_files and pending_files responsibility over
rows = self._c.execute( 'SELECT hash_id, timestamp FROM current_files WHERE service_id IN ( ?, ? );', ( local_file_service_id, trash_service_id ) ).fetchall()
self._c.executemany( 'INSERT OR IGNORE INTO current_files VALUES ( ?, ?, ? );', ( ( combined_local_file_service_id, hash_id, timestamp ) for ( hash_id, timestamp ) in rows ) )
self._c.execute( 'UPDATE deleted_files SET service_id = ? WHERE service_id = ?;', ( combined_local_file_service_id, local_file_service_id ) )
self._c.execute( 'DELETE FROM service_info WHERE service_id = ? AND info_type = ?;', ( local_file_service_id, HC.SERVICE_INFO_NUM_DELETED_FILES ) )
self._c.execute( 'UPDATE file_transfers SET service_id = ? WHERE service_id = ?;', ( combined_local_file_service_id, local_file_service_id ) )
# now it has files, refresh the ac cache
self._controller.pub( 'splash_set_status_text', 'creating autocomplete cache for new service' )
tag_service_ids = self._GetServiceIds( HC.TAG_SERVICES )
for tag_service_id in tag_service_ids:
self._CacheSpecificMappingsDrop( combined_local_file_service_id, tag_service_id )
self._CacheSpecificMappingsGenerate( combined_local_file_service_id, tag_service_id )
# trash current_files rows can now have their own timestamp
trash_rows = self._c.execute( 'SELECT hash_id, timestamp FROM file_trash;' ).fetchall()
self._c.executemany( 'UPDATE current_files SET timestamp = ? WHERE service_id = ? AND hash_id = ?;', ( ( timestamp, trash_service_id, hash_id ) for ( hash_id, timestamp ) in rows ) )
self._c.execute( 'DROP TABLE file_trash;' )
message = 'I have fixed an important miscounting bug in the autocomplete cache. Please go database->maintenance->regenerate autocomplete cache when it is convenient.'
self.pub_initial_message( message )
self._controller.pub( 'splash_set_title_text', 'updated db to v' + str( version + 1 ) )
self._c.execute( 'UPDATE version SET version = ?;', ( version + 1, ) )
@ -8676,9 +8793,9 @@ class DB( HydrusDB.HydrusDB ):
if petitioned_mappings_ids is None: petitioned_mappings_ids = []
if petitioned_rescinded_mappings_ids is None: petitioned_rescinded_mappings_ids = []
file_service_ids = self._GetServiceIds( ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ) )
file_service_ids = self._GetServiceIds( HC.AUTOCOMPLETE_CACHE_SPECIFIC_FILE_SERVICES )
# this method grew into a monster that merged deleted, pending and current according to a heirarchy of services
# this method grew into a monster that merged deleted, pending and current according to a hierarchy of services
# this cost a lot of CPU time and was extremely difficult to maintain
# now it attempts a simpler union, not letting delete overwrite a current or pending
@ -9287,12 +9404,22 @@ class DB( HydrusDB.HydrusDB ):
self.pub_after_commit( 'content_updates_gui', service_keys_to_content_updates )
def pub_initial_message( self, message ):
self._initial_messages.append( message )
def pub_service_updates_after_commit( self, service_keys_to_service_updates ):
self.pub_after_commit( 'service_updates_data', service_keys_to_service_updates )
self.pub_after_commit( 'service_updates_gui', service_keys_to_service_updates )
def GetInitialMessages( self ):
return self._initial_messages
def GetUpdatesDir( self ):
return self._updates_dir

View File

@ -123,15 +123,30 @@ def ConvertServiceKeysToContentUpdatesToPrettyString( service_keys_to_content_up
( data_type, action, row ) = content_update.ToTuple()
if data_type == HC.CONTENT_TYPE_MAPPINGS: extra_words = ' tags for'
if data_type == HC.CONTENT_TYPE_MAPPINGS:
extra_words = ' tags for'
actions.add( HC.content_update_string_lookup[ action ] )
if action in ( HC.CONTENT_UPDATE_ARCHIVE, HC.CONTENT_UPDATE_INBOX ):
locations = set()
num_files += len( content_update.GetHashes() )
s = ', '.join( locations ) + '->' + ', '.join( actions ) + extra_words + ' ' + HydrusData.ConvertIntToPrettyString( num_files ) + ' files'
s = ''
if len( locations ) > 0:
s += ', '.join( locations ) + '->'
s += ', '.join( actions ) + extra_words + ' ' + HydrusData.ConvertIntToPrettyString( num_files ) + ' files'
return s

View File

@ -83,6 +83,7 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
self._lock = threading.Lock()
self._notebook = wx.Notebook( self )
self._notebook.Bind( wx.EVT_LEFT_DCLICK, self.EventNotebookLeftDoubleClick )
self._notebook.Bind( wx.EVT_MIDDLE_DOWN, self.EventNotebookMiddleClick )
self._notebook.Bind( wx.EVT_RIGHT_DOWN, self.EventNotebookMenu )
self.Bind( wx.EVT_NOTEBOOK_PAGE_CHANGED, self.EventNotebookPageChanged )
@ -95,7 +96,8 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
self._message_manager = ClientGUICommon.PopupMessageManager( self )
self.Bind( wx.EVT_MIDDLE_DOWN, self.EventFrameMiddleClick )
self.Bind( wx.EVT_LEFT_DCLICK, self.EventFrameNewPage )
self.Bind( wx.EVT_MIDDLE_DOWN, self.EventFrameNewPage )
self.Bind( wx.EVT_CLOSE, self.EventClose )
self.Bind( wx.EVT_MENU, self.EventMenu )
self.Bind( wx.EVT_SET_FOCUS, self.EventFocus )
@ -703,6 +705,13 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
self._controller.pub( 'notify_new_undo' )
def _DeleteGUISession( self, name ):
self._controller.Write( 'delete_serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_GUI_SESSION, name )
self._controller.pub( 'notify_new_sessions' )
def _DeletePending( self, service_key ):
service = self._controller.GetServicesManager().GetService( service_key )
@ -882,8 +891,8 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
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 Management and Preview Panels' ), p( 'Show or hide the panels on the left.' ) )
ClientGUIMenus.AppendMenuItem( menu, 'refresh', 'If the current page has a search, refresh it.', self, self._Refresh )
ClientGUIMenus.AppendMenuItem( menu, 'show/hide management and preview panels', 'Show or hide the panels on the left.', self, self._ShowHideSplitters )
menu.AppendSeparator()
@ -897,13 +906,13 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
for name in gui_session_names:
load.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'load_gui_session', name ), name )
ClientGUIMenus.AppendMenuItem( load, name, 'Close all other pages and load this session.', self, self._LoadGUISession, name )
sessions.AppendMenu( CC.ID_NULL, p( 'Load' ), load )
ClientGUIMenus.AppendMenu( sessions, load, 'load' )
sessions.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'save_gui_session' ), p( 'Save Current' ) )
ClientGUIMenus.AppendMenuItem( sessions, 'save current', 'Save the existing open pages as a session.', self, self._SaveGUISession )
if len( gui_session_names ) > 0 and gui_session_names != [ 'last session' ]:
@ -913,16 +922,18 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
if name != 'last session':
delete.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'delete_gui_session', name ), name )
ClientGUIMenus.AppendMenuItem( delete, name, 'Delete this session.', self, self._DeleteGUISession, name )
sessions.AppendMenu( CC.ID_NULL, p( 'Delete' ), delete )
ClientGUIMenus.AppendMenu( sessions, delete, 'delete' )
menu.AppendMenu( CC.ID_NULL, p( 'Sessions' ), sessions )
ClientGUIMenus.AppendMenu( menu, 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.' ) )
ClientGUIMenus.AppendMenuItem( menu, 'pick a new page', 'Choose a new page to open.', self, self._ChooseNewPage )
#
@ -938,11 +949,15 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
petition_resolve_file_services = [ repository for repository in file_repositories if repository.GetInfo( 'account' ).HasPermission( HC.RESOLVE_PETITIONS ) ]
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() + '.' ) )
ClientGUIMenus.AppendMenuItem( search_menu, 'my files', 'Open a new search tab for your files.', self, self._NewPageQuery, CC.LOCAL_FILE_SERVICE_KEY )
ClientGUIMenus.AppendMenuItem( search_menu, 'trash', 'Open a new search tab for your recently deleted files.', self, self._NewPageQuery, CC.TRASH_SERVICE_KEY )
menu.AppendMenu( CC.ID_NULL, p( 'New Search Page' ), search_menu )
for service in file_repositories:
ClientGUIMenus.AppendMenuItem( search_menu, service.GetName(), 'Open a new search tab for ' + service.GetName() + '.', self, self._NewPageQuery, service.GetServiceKey() )
ClientGUIMenus.AppendMenu( menu, search_menu, 'new search page' )
#
@ -952,63 +967,68 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
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() ) )
ClientGUIMenus.AppendMenuItem( petition_menu, service.GetName(), 'Open a new tag petition tab for ' + service.GetName() + '.', self, self._NewPagePetitions, service.GetServiceKey() )
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() ) )
ClientGUIMenus.AppendMenuItem( petition_menu, service.GetName(), 'Open a new file petition tab for ' + service.GetName() + '.', self, self._NewPagePetitions, service.GetServiceKey() )
menu.AppendMenu( CC.ID_NULL, p( 'New Petition Page' ), petition_menu )
ClientGUIMenus.AppendMenu( menu, petition_menu, 'new petition page' )
#
download_menu = wx.Menu()
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.' ) )
download_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_import_urls' ), p( '&New URL Download Page' ), p( 'Open a new tab to download some raw urls.' ) )
ClientGUIMenus.AppendMenuItem( download_menu, 'url download', 'Open a new tab to download some raw urls.', self, self._NewPageImportURLs )
ClientGUIMenus.AppendMenuItem( download_menu, 'thread watcher', 'Open a new tab to watch a thread.', self, self._NewPageImportThreadWatcher )
ClientGUIMenus.AppendMenuItem( download_menu, 'webpage of images', 'Open a new tab to download files from generic galleries or threads.', self, self._NewPageImportPageOfImages )
submenu = wx.Menu()
gallery_menu = wx.Menu()
ClientGUIMenus.AppendMenuItem( gallery_menu, 'booru', 'Open a new tab to download files from a booru.', self, self._NewPageImportBooru )
ClientGUIMenus.AppendMenuItem( gallery_menu, 'deviant art', 'Open a new tab to download files from Deviant Art.', self, self._NewPageImportGallery, ClientDownloading.GalleryIdentifier( HC.SITE_TYPE_DEVIANT_ART ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_import_booru' ), p( 'Booru' ), p( 'Open a new tab to download files from a booru.' ) )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_import_gallery', HC.SITE_TYPE_DEVIANT_ART ), p( 'Deviant Art' ), p( 'Open a new tab to download files from Deviant Art.' ) )
hf_submenu = wx.Menu()
hf_submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_import_gallery', HC.SITE_TYPE_HENTAI_FOUNDRY_ARTIST ), p( 'By Artist' ), p( 'Open a new tab to download files from Hentai Foundry.' ) )
hf_submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_import_gallery', HC.SITE_TYPE_HENTAI_FOUNDRY_TAGS ), p( 'By Tags' ), p( 'Open a new tab to download files from Hentai Foundry.' ) )
submenu.AppendMenu( CC.ID_NULL, p( '&Hentai Foundry' ), hf_submenu )
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_import_gallery', HC.SITE_TYPE_NEWGROUNDS ), p( 'Newgrounds' ), p( 'Open a new tab to download files from Newgrounds.' ) )
ClientGUIMenus.AppendMenuItem( hf_submenu, 'by artist', 'Open a new tab to download files from Hentai Foundry.', self, self._NewPageImportGallery, ClientDownloading.GalleryIdentifier( HC.SITE_TYPE_HENTAI_FOUNDRY_ARTIST ) )
ClientGUIMenus.AppendMenuItem( hf_submenu, 'by tags', 'Open a new tab to download files from Hentai Foundry.', self, self._NewPageImportGallery, ClientDownloading.GalleryIdentifier( HC.SITE_TYPE_HENTAI_FOUNDRY_TAGS ) )
ClientGUIMenus.AppendMenu( gallery_menu, hf_submenu, 'hentai foundry' )
ClientGUIMenus.AppendMenuItem( gallery_menu, 'newgrounds', 'Open a new tab to download files from Newgrounds.', self, self._NewPageImportGallery, ClientDownloading.GalleryIdentifier( HC.SITE_TYPE_NEWGROUNDS ) )
result = self._controller.Read( 'serialisable_simple', 'pixiv_account' )
if result is not None:
pixiv_submenu = wx.Menu()
pixiv_submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_import_gallery', HC.SITE_TYPE_PIXIV_ARTIST_ID ), p( 'By Artist Id' ), p( 'Open a new tab to download files from Pixiv.' ) )
pixiv_submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_import_gallery', HC.SITE_TYPE_PIXIV_TAG ), p( 'By Tag' ), p( 'Open a new tab to download files from Hentai Pixiv.' ) )
submenu.AppendMenu( CC.ID_NULL, p( '&Pixiv' ), pixiv_submenu )
ClientGUIMenus.AppendMenuItem( pixiv_submenu, 'by artist id', 'Open a new tab to download files from Pixiv.', self, self._NewPageImportGallery, ClientDownloading.GalleryIdentifier( HC.SITE_TYPE_PIXIV_ARTIST_ID ) )
ClientGUIMenus.AppendMenuItem( pixiv_submenu, 'by tag', 'Open a new tab to download files from Pixiv.', self, self._NewPageImportGallery, ClientDownloading.GalleryIdentifier( HC.SITE_TYPE_PIXIV_TAG ) )
ClientGUIMenus.AppendMenu( gallery_menu, pixiv_submenu, 'pixiv' )
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.' ) )
ClientGUIMenus.AppendMenuItem( gallery_menu, 'tumblr', 'Open a new tab to download files from tumblr.', self, self._NewPageImportGallery, ClientDownloading.GalleryIdentifier( HC.SITE_TYPE_TUMBLR ) )
download_menu.AppendMenu( CC.ID_NULL, p( '&New Gallery Download Page' ), submenu )
menu.AppendMenu( CC.ID_NULL, p( 'New Download Page' ), download_menu )
ClientGUIMenus.AppendMenu( download_menu, gallery_menu, 'gallery' )
ClientGUIMenus.AppendMenu( menu, download_menu, 'new download page' )
download_popup_menu = wx.Menu()
download_popup_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' ) )
ClientGUIMenus.AppendMenuItem( download_popup_menu, 'a youtube video', 'Enter a YouTube URL and choose which formats you would like to download', self, self._StartYoutubeDownload )
has_ipfs = len( [ service for service in services if service.GetServiceType() == HC.IPFS ] )
if has_ipfs:
download_popup_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'start_ipfs_download' ), p( '&An IPFS Multihash' ), p( 'Enter an IPFS multihash and attempt to import whatever is returned' ) )
ClientGUIMenus.AppendMenuItem( download_popup_menu, 'an ipfs multihash', 'Enter an IPFS multihash and attempt to import whatever is returned.', self, self._StartIPFSDownload )
menu.AppendMenu( CC.ID_NULL, p( 'New Download Popup' ), download_popup_menu )
ClientGUIMenus.AppendMenu( menu, download_popup_menu, 'new download popup' )
#
@ -1742,6 +1762,16 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
def _Refresh( self ):
page = self._notebook.GetCurrentPage()
if page is not None:
page.RefreshQuery()
def _RefreshStatusBar( self ):
if self._media_status_override is not None:
@ -2009,6 +2039,16 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
if page is not None: page.SetSynchronisedWait()
def _ShowHideSplitters( self ):
page = self._notebook.GetCurrentPage()
if page is not None:
page.ShowHideSplit()
def _StartIPFSDownload( self ):
ipfs_services = self._controller.GetServicesManager().GetServices( ( HC.IPFS, ) )
@ -2443,7 +2483,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
def EventFrameMiddleClick( self, event ):
def EventFrameNewPage( self, event ):
self._ChooseNewPage()
@ -2607,9 +2647,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
elif command == 'redo': self._controller.pub( 'redo' )
elif command == 'refresh':
page = self._notebook.GetCurrentPage()
if page is not None: page.RefreshQuery()
self._Refresh()
elif command == 'review_services': self._ReviewServices()
elif command == 'save_gui_session': self._SaveGUISession()
@ -2617,9 +2655,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
elif command == 'set_search_focus': self._SetSearchFocus()
elif command == 'show_hide_splitters':
page = self._notebook.GetCurrentPage()
if page is not None: page.ShowHideSplit()
self._ShowHideSplitters()
elif command == 'site': webbrowser.open( 'https://hydrusnetwork.github.io/hydrus/' )
elif command == 'start_ipfs_download': self._StartIPFSDownload()
@ -2635,6 +2671,16 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
def EventNotebookLeftDoubleClick( self, event ):
( tab_index, flags ) = self._notebook.HitTest( ( event.GetX(), event.GetY() ) )
if tab_index == wx.NOT_FOUND:
self._ChooseNewPage()
def EventNotebookMenu( self, event ):
( tab_index, flags ) = self._notebook.HitTest( ( event.GetX(), event.GetY() ) )

View File

@ -526,8 +526,11 @@ class AutoCompleteDropdownTags( AutoCompleteDropdown ):
self._current_matches = []
file_service = HydrusGlobals.client_controller.GetServicesManager().GetService( self._file_service_key )
tag_service = HydrusGlobals.client_controller.GetServicesManager().GetService( self._tag_service_key )
self._file_repo_button = ClientGUICommon.BetterButton( self._dropdown_window, file_service.GetName(), self.FileButtonHit )
self._file_repo_button.SetMinSize( ( 20, -1 ) )
@ -628,14 +631,19 @@ class AutoCompleteDropdownTags( AutoCompleteDropdown ):
services_manager = HydrusGlobals.client_controller.GetServicesManager()
services = []
services.append( services_manager.GetService( CC.COMBINED_FILE_SERVICE_KEY ) )
services.append( services_manager.GetService( CC.LOCAL_FILE_SERVICE_KEY ) )
services.append( services_manager.GetService( CC.TRASH_SERVICE_KEY ) )
services.append( services_manager.GetService( CC.COMBINED_LOCAL_FILE_SERVICE_KEY ) )
services.extend( services_manager.GetServices( ( HC.FILE_REPOSITORY, ) ) )
services.append( services_manager.GetService( CC.COMBINED_FILE_SERVICE_KEY ) )
menu = wx.Menu()
for service in services: menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'change_file_service', service.GetServiceKey() ), service.GetName() )
for service in services:
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'change_file_service', service.GetServiceKey() ), service.GetName() )
HydrusGlobals.client_controller.PopupMenu( self._file_repo_button, menu )
@ -655,13 +663,17 @@ class AutoCompleteDropdownTags( AutoCompleteDropdown ):
services_manager = HydrusGlobals.client_controller.GetServicesManager()
services = []
services.append( services_manager.GetService( CC.COMBINED_TAG_SERVICE_KEY ) )
services.append( services_manager.GetService( CC.LOCAL_TAG_SERVICE_KEY ) )
services.extend( services_manager.GetServices( ( HC.TAG_REPOSITORY, ) ) )
services.append( services_manager.GetService( CC.COMBINED_TAG_SERVICE_KEY ) )
menu = wx.Menu()
for service in services: menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'change_tag_service', service.GetServiceKey() ), service.GetName() )
for service in services:
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'change_tag_service', service.GetServiceKey() ), service.GetName() )
HydrusGlobals.client_controller.PopupMenu( self._tag_repo_button, menu )
@ -1273,4 +1285,4 @@ class AutoCompleteDropdownTagsWrite( AutoCompleteDropdownTags ):
self._BroadcastCurrentText()

View File

@ -950,7 +950,10 @@ class Canvas( wx.Window ):
HydrusGlobals.client_controller.sub( self, 'ManageTags', 'canvas_manage_tags' )
def _Archive( self ): HydrusGlobals.client_controller.Write( 'content_updates', { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, ( self._current_display_media.GetHash(), ) ) ] } )
def _Archive( self ):
HydrusGlobals.client_controller.Write( 'content_updates', { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, ( self._current_display_media.GetHash(), ) ) ] } )
def _CopyBMPToClipboard( self ):
@ -967,7 +970,7 @@ class Canvas( wx.Window ):
else:
if self._current_display_media.GetLocationsManager().HasLocal():
if self._current_display_media.GetLocationsManager().IsLocal():
( other_hash, ) = HydrusGlobals.client_controller.Read( 'file_hashes', ( sha256_hash, ), 'sha256', hash_type )
@ -1162,7 +1165,10 @@ class Canvas( wx.Window ):
return False
def _Inbox( self ): HydrusGlobals.client_controller.Write( 'content_updates', { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_INBOX, ( self._current_display_media.GetHash(), ) ) ] } )
def _Inbox( self ):
HydrusGlobals.client_controller.Write( 'content_updates', { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_INBOX, ( self._current_display_media.GetHash(), ) ) ] } )
def _IsZoomable( self ):
@ -1543,7 +1549,7 @@ class Canvas( wx.Window ):
locations_manager = media.GetLocationsManager()
if not locations_manager.HasLocal():
if not locations_manager.IsLocal():
media = None
@ -1582,7 +1588,7 @@ class Canvas( wx.Window ):
( initial_width, initial_height ) = initial_size
if self._current_display_media.GetLocationsManager().HasLocal() and initial_width > 0 and initial_height > 0:
if self._current_display_media.GetLocationsManager().IsLocal() and initial_width > 0 and initial_height > 0:
show_action = self._GetShowAction( self._current_display_media )
@ -2501,12 +2507,12 @@ class CanvasMediaListFilter( CanvasMediaList ):
self._deleted_hashes = [ media.GetHash() for media in self._deleted ]
self._kept_hashes = [ media.GetHash() for media in self._kept ]
content_updates = []
service_keys_to_content_updates = {}
content_updates.append( HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_DELETE, self._deleted_hashes ) )
content_updates.append( HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, self._kept_hashes ) )
service_keys_to_content_updates[ CC.LOCAL_FILE_SERVICE_KEY ] = [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_DELETE, self._deleted_hashes ) ]
service_keys_to_content_updates[ CC.COMBINED_LOCAL_FILE_SERVICE_KEY ] = [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, self._kept_hashes ) ]
HydrusGlobals.client_controller.Write( 'content_updates', { CC.LOCAL_FILE_SERVICE_KEY : content_updates } )
HydrusGlobals.client_controller.Write( 'content_updates', service_keys_to_content_updates )
self._kept = set()
self._deleted = set()
@ -3248,7 +3254,10 @@ class CanvasMediaListCustomFilter( CanvasMediaListNavigable ):
HydrusGlobals.client_controller.pub( 'clipboard', 'text', path )
def _Inbox( self ): HydrusGlobals.client_controller.Write( 'content_updates', { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_INBOX, ( self._current_display_media.GetHash(), ) ) ] } )
def _Inbox( self ):
HydrusGlobals.client_controller.Write( 'content_updates', { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_INBOX, ( self._current_display_media.GetHash(), ) ) ] } )
def EventShortcuts( self, event ):
@ -3894,7 +3903,7 @@ class EmbedButton( wx.Window ):
self._canvas_bmp = wx.EmptyBitmap( x, y, 24 )
if self._media.GetLocationsManager().HasLocal() and self._media.GetMime() in HC.MIMES_WITH_THUMBNAILS:
if self._media.GetLocationsManager().IsLocal() and self._media.GetMime() in HC.MIMES_WITH_THUMBNAILS:
hash = self._media.GetHash()
@ -4024,7 +4033,7 @@ class OpenExternallyPanel( wx.Panel ):
vbox = wx.BoxSizer( wx.VERTICAL )
if self._media.GetLocationsManager().HasLocal() and self._media.GetMime() in HC.MIMES_WITH_THUMBNAILS:
if self._media.GetLocationsManager().IsLocal() and self._media.GetMime() in HC.MIMES_WITH_THUMBNAILS:
hash = self._media.GetHash()

View File

@ -3115,7 +3115,10 @@ class ListBoxTagsSelectionManagementPanel( ListBoxTagsSelection ):
def ChangeTagServicePubsub( self, page_key, service_key ):
if page_key == self._page_key: self.ChangeTagService( service_key )
if page_key == self._page_key:
self.ChangeTagService( service_key )
def IncrementTagsByMediaPubsub( self, page_key, media ):

View File

@ -316,7 +316,7 @@ class Dialog( wx.Dialog ):
def SetInitialSize( self, ( width, height ) ):
( display_width, display_height ) = wx.GetDisplaySize()
( display_width, display_height ) = ClientGUITopLevelWindows.GetDisplaySize( self )
width = min( display_width, width )
height = min( display_height, height )
@ -2900,6 +2900,7 @@ class DialogPageChooser( Dialog ):
entries.append( ( 'page_query', CC.LOCAL_FILE_SERVICE_KEY ) )
entries.append( ( 'page_query', CC.TRASH_SERVICE_KEY ) )
entries.append( ( 'page_query', CC.COMBINED_LOCAL_FILE_SERVICE_KEY ) )
for service in self._services:

View File

@ -2906,7 +2906,7 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
( x, y ) = self.GetEffectiveMinSize()
( max_x, max_y ) = wx.GetDisplaySize()
( max_x, max_y ) = ClientGUITopLevelWindows.GetDisplaySize( self )
x = min( x + 25, max_x )
y = min( y + 25, max_y )
@ -4006,20 +4006,16 @@ class DialogManageServices( ClientGUIDialogs.Dialog ):
#
manageable_service_types = HC.RESTRICTED_SERVICES + [ HC.LOCAL_TAG, HC.LOCAL_RATING_LIKE, HC.LOCAL_RATING_NUMERICAL, HC.LOCAL_BOORU, HC.IPFS ]
for service_type in manageable_service_types:
for service_type in HC.ALL_SERVICES:
if service_type == HC.LOCAL_RATING_LIKE: name = 'like/dislike ratings'
elif service_type == HC.LOCAL_RATING_NUMERICAL: name = 'numerical ratings'
elif service_type == HC.LOCAL_BOORU: name = 'booru'
elif service_type == HC.LOCAL_TAG: name = 'local tags'
elif service_type == HC.LOCAL_FILE_DOMAIN: name = 'local files'
elif service_type == HC.TAG_REPOSITORY: name = 'tag repositories'
elif service_type == HC.FILE_REPOSITORY: name = 'file repositories'
#elif service_type == HC.MESSAGE_DEPOT: name = 'message repositories'
elif service_type == HC.SERVER_ADMIN: name = 'administrative services'
#elif service_type == HC.RATING_LIKE_REPOSITORY: name = 'like/dislike rating repositories'
#elif service_type == HC.RATING_NUMERICAL_REPOSITORY: name = 'numerical rating repositories'
elif service_type == HC.IPFS: name = 'ipfs daemons'
else: continue
@ -4094,7 +4090,7 @@ class DialogManageServices( ClientGUIDialogs.Dialog ):
service_type = self._listbooks_to_service_types[ services_listbook ]
if service_type in HC.NONEDITABLE_SERVICES:
if service_type in HC.NONADDREMOVEABLE_SERVICES:
self._add.Disable()
self._remove.Disable()
@ -4155,9 +4151,9 @@ class DialogManageServices( ClientGUIDialogs.Dialog ):
service_key = HydrusData.GenerateKey()
service_type = self._listbooks_to_service_types[ services_listbook ]
if service_type in HC.NONEDITABLE_SERVICES:
if service_type in HC.NONADDREMOVEABLE_SERVICES:
wx.MessageBox( 'You cannot edit this type of service yet!' )
wx.MessageBox( 'You cannot add or delete this type of service yet!' )
return
@ -4421,7 +4417,7 @@ class DialogManageServices( ClientGUIDialogs.Dialog ):
#
if service_type not in HC.NONEDITABLE_SERVICES:
if service_type not in HC.NONRENAMEABLE_SERVICES:
if service_type in HC.REMOTE_SERVICES: title = 'name and credentials'
else: title = 'name'
@ -4551,7 +4547,7 @@ class DialogManageServices( ClientGUIDialogs.Dialog ):
#
if service_type not in HC.NONEDITABLE_SERVICES:
if service_type not in HC.NONRENAMEABLE_SERVICES:
self._service_name.SetValue( name )
@ -4599,7 +4595,7 @@ class DialogManageServices( ClientGUIDialogs.Dialog ):
vbox = wx.BoxSizer( wx.VERTICAL )
if service_type not in HC.NONEDITABLE_SERVICES:
if service_type not in HC.NONRENAMEABLE_SERVICES:
rows = []
@ -4894,11 +4890,14 @@ class DialogManageServices( ClientGUIDialogs.Dialog ):
info = dict( info )
if service_type not in HC.NONEDITABLE_SERVICES:
if service_type not in HC.NONRENAMEABLE_SERVICES:
name = self._service_name.GetValue()
if name == '': raise Exception( 'Please enter a name' )
if name == '':
raise Exception( 'Please enter a name' )
if service_type in HC.REMOTE_SERVICES:

View File

@ -126,7 +126,7 @@ def CreateManagementControllerPetitions( petition_service_key ):
petition_service_type = petition_service.GetServiceType()
if petition_service_type in ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ): file_service_key = petition_service_key
if petition_service_type in HC.LOCAL_FILE_SERVICES or petition_service_type == HC.FILE_REPOSITORY: file_service_key = petition_service_key
else: file_service_key = CC.COMBINED_FILE_SERVICE_KEY
management_controller = CreateManagementController( MANAGEMENT_TYPE_PETITIONS, file_service_key = file_service_key )
@ -534,6 +534,14 @@ class ManagementController( HydrusSerialisable.SerialisableBase ):
self._keys = { name : key.decode( 'hex' ) for ( name, key ) in serialisable_keys.items() }
if 'file_service' in self._keys:
if not HydrusGlobals.client_controller.GetServicesManager().ServiceExists( self._keys[ 'file_service' ] ):
self._keys[ 'file_service' ] = CC.COMBINED_LOCAL_FILE_SERVICE_KEY
self._simples = dict( serialisable_simples )
self._serialisables = { name : HydrusSerialisable.CreateFromSerialisableTuple( value ) for ( name, value ) in serialisables.items() }
@ -1478,9 +1486,9 @@ class ManagementPanelGalleryImport( ManagementPanel ):
self._get_tags_if_redundant = wx.CheckBox( self._gallery_downloader_panel, label = 'get tags even if file is already in db' )
self._get_tags_if_redundant.Bind( wx.EVT_CHECKBOX, self.EventGetTagsIfRedundant )
self._get_tags_if_redundant.SetToolTipString( 'only fetch tags from the gallery if the file is new' )
self._get_tags_if_redundant.SetToolTipString( 'if off, the downloader will only fetch tags from the gallery if the file is new' )
self._file_limit = ClientGUICommon.NoneableSpinCtrl( self._gallery_downloader_panel, 'stop searching once this many files are found', min = 1, none_phrase = 'no limit' )
self._file_limit = ClientGUICommon.NoneableSpinCtrl( self._gallery_downloader_panel, 'stop after this many files', min = 1, none_phrase = 'no limit' )
self._file_limit.Bind( wx.EVT_SPINCTRL, self.EventFileLimit )
self._file_limit.SetToolTipString( 'per query, stop searching the gallery once this many files has been reached' )
@ -1546,7 +1554,7 @@ class ManagementPanelGalleryImport( ManagementPanel ):
self._MakeSort( vbox )
vbox.AddF( self._gallery_downloader_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
vbox.AddF( self._gallery_downloader_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
self._MakeCurrentSelectionTagsBox( vbox )
@ -2125,7 +2133,7 @@ class ManagementPanelPageOfImagesImport( ManagementPanel ):
self._MakeSort( vbox )
vbox.AddF( self._page_of_images_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
vbox.AddF( self._page_of_images_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
self._MakeCurrentSelectionTagsBox( vbox )
@ -2461,7 +2469,7 @@ class ManagementPanelPetitions( ManagementPanel ):
self._MakeCollect( vbox )
vbox.AddF( self._petitions_info_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.AddF( self._petition_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
vbox.AddF( self._petition_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
self._MakeCurrentSelectionTagsBox( vbox )
@ -2524,7 +2532,7 @@ class ManagementPanelPetitions( ManagementPanel ):
def _ShowHashes( self, hashes ):
file_service_key = self._management_controller.GetKey( 'file_service' )
with wx.BusyCursor(): media_results = self._controller.Read( 'media_results', hashes )
panel = ClientGUIMedia.MediaPanelThumbnails( self._page, self._page_key, file_service_key, media_results )
@ -3276,7 +3284,7 @@ class ManagementPanelURLsImport( ManagementPanel ):
self._MakeSort( vbox )
vbox.AddF( self._url_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
vbox.AddF( self._url_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
self._MakeCurrentSelectionTagsBox( vbox )

View File

@ -116,7 +116,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
HydrusGlobals.client_controller.Write( 'content_updates', { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, hashes ) ] } )
HydrusGlobals.client_controller.Write( 'content_updates', { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, hashes ) ] } )
@ -150,7 +150,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
else:
if display_media.GetLocationsManager().HasLocal():
if display_media.GetLocationsManager().IsLocal():
( other_hash, ) = HydrusGlobals.client_controller.Read( 'file_hashes', ( sha256_hash, ), 'sha256', hash_type )
@ -430,6 +430,11 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
self._PublishSelectionChange()
def _Download( self, hashes ):
HydrusGlobals.client_controller.Write( 'content_updates', { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_PEND, hashes ) ] } )
def _FullScreen( self, first_media = None ):
if self._focussed_media is not None:
@ -461,7 +466,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
if first_media is None and self._focussed_media is not None: first_media = self._focussed_media
if first_media is not None and first_media.GetLocationsManager().HasLocal(): first_hash = first_media.GetDisplayMedia().GetHash()
if first_media is not None and first_media.GetLocationsManager().IsLocal(): first_hash = first_media.GetDisplayMedia().GetHash()
else: first_hash = None
canvas_frame = ClientGUICanvas.CanvasFrame( self.GetTopLevelParent() )
@ -474,7 +479,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
def _Filter( self ):
media_results = self.GenerateMediaResults( has_location = CC.LOCAL_FILE_SERVICE_KEY, selected_media = set( self._selected_media ), for_media_viewer = True )
media_results = self.GenerateMediaResults( has_location = CC.COMBINED_LOCAL_FILE_SERVICE_KEY, selected_media = set( self._selected_media ), for_media_viewer = True )
if len( media_results ) > 0:
@ -734,8 +739,14 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
else:
if not media.IsSelected(): self._DeselectSelect( self._selected_media, ( media, ) )
else: self._PublishSelectionChange()
if not media.IsSelected():
self._DeselectSelect( self._selected_media, ( media, ) )
else:
self._PublishSelectionChange()
self._SetFocussedMedia( media )
self._shift_focussed_media = media
@ -762,7 +773,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
HydrusGlobals.client_controller.Write( 'content_updates', { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_INBOX, hashes ) ] } )
HydrusGlobals.client_controller.Write( 'content_updates', { CC.COMBINED_LOCAL_FILE_SERVICE_KEY: [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_INBOX, hashes ) ] } )
@ -840,7 +851,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
if self._focussed_media is not None:
if CC.LOCAL_FILE_SERVICE_KEY in self._focussed_media.GetLocationsManager().GetCurrent():
if self._focussed_media.GetLocationsManager().IsLocal():
hash = self._focussed_media.GetHash()
mime = self._focussed_media.GetMime()
@ -904,8 +915,14 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
def _PublishSelectionChange( self, force_reload = False ):
if len( self._selected_media ) == 0: tags_media = self._sorted_media
else: tags_media = self._selected_media
if len( self._selected_media ) == 0:
tags_media = self._sorted_media
else:
tags_media = self._selected_media
HydrusGlobals.client_controller.pub( 'new_tags_selection', self._page_key, tags_media, force_reload = force_reload )
HydrusGlobals.client_controller.pub( 'new_page_status', self._page_key, self._GetPrettyStatus() )
@ -1247,7 +1264,10 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
self._PublishSelectionChange( force_reload = force_reload )
if self._focussed_media is not None: self._HitMedia( self._focussed_media, False, False )
if self._focussed_media is not None:
self._HitMedia( self._focussed_media, False, False )
def ProcessServiceUpdates( self, service_keys_to_service_updates ):
@ -2072,7 +2092,10 @@ class MediaPanelThumbnails( MediaPanel ):
self._Delete( data )
elif command == 'download': HydrusGlobals.client_controller.Write( 'content_updates', { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_PEND, self._GetSelectedHashes( discriminant = CC.DISCRIMINANT_NOT_LOCAL ) ) ] } )
elif command == 'download':
self._Download( self._GetSelectedHashes( discriminant = CC.DISCRIMINANT_NOT_LOCAL ) )
elif command == 'export_files': self._ExportFiles()
elif command == 'export_tags': self._ExportTags()
elif command == 'filter': self._Filter()
@ -2086,7 +2109,7 @@ class MediaPanelThumbnails( MediaPanel ):
elif command == 'open_externally': self._OpenExternally()
elif command == 'petition': self._PetitionFiles( data )
elif command == 'remove': self._Remove()
elif command == 'rescind_download': HydrusGlobals.client_controller.Write( 'content_updates', { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_RESCIND_PEND, self._GetSelectedHashes( discriminant = CC.DISCRIMINANT_DOWNLOADING ) ) ] } )
elif command == 'rescind_download': HydrusGlobals.client_controller.Write( 'content_updates', { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_RESCIND_PEND, self._GetSelectedHashes( discriminant = CC.DISCRIMINANT_DOWNLOADING ) ) ] } )
elif command == 'rescind_petition': self._RescindPetitionFiles( data )
elif command == 'rescind_upload': self._RescindUploadFiles( data )
elif command == 'scroll_end': self._ScrollEnd( False )
@ -2119,12 +2142,12 @@ class MediaPanelThumbnails( MediaPanel ):
locations_manager = t.GetLocationsManager()
if locations_manager.HasLocal(): self._FullScreen( t )
if locations_manager.IsLocal(): self._FullScreen( t )
elif self._file_service_key != CC.COMBINED_FILE_SERVICE_KEY:
if len( locations_manager.GetCurrentRemote() ) > 0:
HydrusGlobals.client_controller.Write( 'content_updates', { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_PEND, t.GetHashes() ) ] } )
self._Download( t.GetHashes() )
@ -2236,12 +2259,13 @@ class MediaPanelThumbnails( MediaPanel ):
all_locations_managers = [ media.GetLocationsManager() for media in self._sorted_media ]
selected_locations_managers = [ media.GetLocationsManager() for media in self._selected_media ]
selection_has_local_file_service = True in ( CC.LOCAL_FILE_SERVICE_KEY in locations_manager.GetCurrent() for locations_manager in selected_locations_managers )
selection_has_local = True in ( locations_manager.IsLocal() for locations_manager in selected_locations_managers )
selection_has_local_file_domain = True in ( CC.LOCAL_FILE_SERVICE_KEY in locations_manager.GetCurrent() for locations_manager in selected_locations_managers )
selection_has_trash = True in ( CC.TRASH_SERVICE_KEY in locations_manager.GetCurrent() for locations_manager in selected_locations_managers )
selection_has_inbox = True in ( media.HasInbox() for media in self._selected_media )
selection_has_archive = True in ( media.HasArchive() for media in self._selected_media )
media_has_local_file_service = True in ( CC.LOCAL_FILE_SERVICE_KEY in locations_manager.GetCurrent() for locations_manager in all_locations_managers )
media_has_local_file_domain = True in ( CC.LOCAL_FILE_SERVICE_KEY in locations_manager.GetCurrent() for locations_manager in all_locations_managers )
media_has_trash = True in ( CC.TRASH_SERVICE_KEY in locations_manager.GetCurrent() for locations_manager in all_locations_managers )
media_has_inbox = True in ( media.HasInbox() for media in self._sorted_media )
media_has_archive = True in ( media.HasArchive() for media in self._sorted_media )
@ -2274,9 +2298,9 @@ class MediaPanelThumbnails( MediaPanel ):
select_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'select', 'archive' ), 'archive' )
if media_has_local_file_service and media_has_trash:
if media_has_local_file_domain and media_has_trash:
select_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'select', 'local' ), 'local files' )
select_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'select', 'local' ), 'my files' )
select_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'select', 'trash' ), 'trash' )
@ -2411,7 +2435,7 @@ class MediaPanelThumbnails( MediaPanel ):
disparate_petitioned_remote_service_keys = petitioned_remote_service_keys - common_petitioned_remote_service_keys
disparate_deleted_remote_service_keys = deleted_remote_service_keys - common_deleted_remote_service_keys
some_downloading = True in ( CC.LOCAL_FILE_SERVICE_KEY in locations_manager.GetPending() for locations_manager in selected_locations_managers )
some_downloading = True in ( locations_manager.IsDownloading() for locations_manager in selected_locations_managers )
pending_file_service_keys = pending_remote_service_keys.intersection( file_service_keys )
petitioned_file_service_keys = petitioned_remote_service_keys.intersection( file_service_keys )
@ -2459,14 +2483,14 @@ class MediaPanelThumbnails( MediaPanel ):
# we can upload (set pending) to a repo_id when we have permission, a file is local, not current, not pending, and either ( not deleted or admin )
if locations_manager.HasLocal():
if locations_manager.IsLocal():
uploadable_file_service_keys.update( upload_permission_file_service_keys - locations_manager.GetCurrentRemote() - locations_manager.GetPendingRemote() - ( locations_manager.GetDeletedRemote() - admin_permission_file_service_keys ) )
# we can download (set pending to local) when we have permission, a file is not local and not already downloading and current
if not CC.LOCAL_FILE_SERVICE_KEY in locations_manager.GetCurrent() and not locations_manager.HasDownloading():
if not locations_manager.IsLocal() and not locations_manager.IsDownloading():
downloadable_file_service_keys.update( download_permission_file_service_keys & locations_manager.GetCurrentRemote() )
@ -2488,7 +2512,7 @@ class MediaPanelThumbnails( MediaPanel ):
# we can pin if a file is local, not current, not pending
if locations_manager.HasLocal():
if locations_manager.IsLocal():
pinnable_ipfs_service_keys.update( ipfs_service_keys - locations_manager.GetCurrentRemote() - locations_manager.GetPendingRemote() )
@ -2632,7 +2656,7 @@ class MediaPanelThumbnails( MediaPanel ):
#
if selection_has_local_file_service and multiple_selected:
if selection_has_local and multiple_selected:
filter_menu = wx.Menu()
@ -2670,7 +2694,7 @@ class MediaPanelThumbnails( MediaPanel ):
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'remove' ), remove_phrase )
if selection_has_local_file_service:
if selection_has_local_file_domain:
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'delete', CC.LOCAL_FILE_SERVICE_KEY ), local_delete_phrase )
@ -2685,7 +2709,7 @@ class MediaPanelThumbnails( MediaPanel ):
menu.AppendSeparator()
if selection_has_local_file_service:
if selection_has_local:
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'open_externally' ), '&open externally' )
@ -2696,7 +2720,7 @@ class MediaPanelThumbnails( MediaPanel ):
copy_menu = wx.Menu()
if selection_has_local_file_service:
if selection_has_local:
copy_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'copy_files' ), copy_phrase )
@ -2810,9 +2834,9 @@ class MediaPanelThumbnails( MediaPanel ):
select_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'select', 'archive' ), 'archive' )
if media_has_local_file_service and media_has_trash:
if media_has_local_file_domain and media_has_trash:
select_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'select', 'local' ), 'local files' )
select_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'select', 'local' ), 'my files' )
select_menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'select', 'trash' ), 'trash' )
@ -3087,7 +3111,7 @@ class Thumbnail( Selectable ):
inbox = self.HasInbox()
local = self.GetLocationsManager().HasLocal()
local = self.GetLocationsManager().IsLocal()
thumbnail_hydrus_bmp = HydrusGlobals.client_controller.GetCache( 'thumbnail' ).GetThumbnail( self )
@ -3278,7 +3302,7 @@ class Thumbnail( Selectable ):
icons_to_draw = []
if CC.LOCAL_FILE_SERVICE_KEY in locations_manager.GetPending():
if locations_manager.IsDownloading():
icons_to_draw.append( CC.GlobalBMPs.downloading )

View File

@ -202,15 +202,17 @@ class OptionsPanelImportFiles( OptionsPanel ):
self._auto_archive = wx.CheckBox( self, label = 'archive all imports' )
self._auto_archive.Bind( wx.EVT_CHECKBOX, self.EventChanged )
self._auto_archive.SetToolTipString( 'If this is set, all successful imports will be automatically archived rather than sent to the inbox.' )
self._exclude_deleted = wx.CheckBox( self, label = 'exclude already deleted files' )
self._exclude_deleted.Bind( wx.EVT_CHECKBOX, self.EventChanged )
self._exclude_deleted.SetToolTipString( 'If this is set and an incoming file has already been seen and deleted before by this client, the import will be abandoned. This is useful to make sure you do not keep importing and deleting the same bad files over and over. Files currently in the trash count as deleted.' )
self._min_size = ClientGUICommon.NoneableSpinCtrl( self, 'minimum size (KB): ', multiplier = 1024 )
self._min_size = ClientGUICommon.NoneableSpinCtrl( self, 'size', unit = 'KB', multiplier = 1024 )
self._min_size.SetValue( 5120 )
self._min_size.Bind( wx.EVT_SPINCTRL, self.EventChanged )
self._min_resolution = ClientGUICommon.NoneableSpinCtrl( self, 'minimum resolution: ', num_dimensions = 2 )
self._min_resolution = ClientGUICommon.NoneableSpinCtrl( self, 'resolution', num_dimensions = 2 )
self._min_resolution.SetValue( ( 50, 50 ) )
self._min_resolution.Bind( wx.EVT_SPINCTRL, self.EventChanged )
@ -218,6 +220,7 @@ class OptionsPanelImportFiles( OptionsPanel ):
vbox.AddF( self._auto_archive, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.AddF( self._exclude_deleted, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.AddF( wx.StaticText( self, label = 'minimum:' ), CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.AddF( self._min_size, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.AddF( self._min_resolution, CC.FLAGS_EXPAND_PERPENDICULAR )
@ -569,4 +572,4 @@ class OptionsPanelTags( OptionsPanel ):
self._service_keys_to_explicit_button_info = new_service_keys_to_explicit_button_info

View File

@ -147,7 +147,7 @@ class PanelPredicateSystemFileService( PanelPredicateSystem ):
self._sign.SetSelection( 0 )
self._current_pending.SetSelection( 0 )
services = HydrusGlobals.client_controller.GetServicesManager().GetServices( ( HC.FILE_REPOSITORY, HC.LOCAL_FILE, HC.IPFS ) )
services = HydrusGlobals.client_controller.GetServicesManager().GetServices( HC.FILE_SERVICES )
for service in services: self._file_service_key.Append( service.GetName(), service.GetServiceKey() )
self._file_service_key.SetSelection( 0 )
@ -788,4 +788,4 @@ class PanelPredicateSystemWidth( PanelPredicateSystem ):
return info

View File

@ -686,7 +686,7 @@ class EditSubscriptionPanel( ClientGUIScrolledPanels.EditPanel ):
wx.CallAfter( self.ProcessEvent, event )
def CheckNow( self, event ):
def CheckNow( self ):
self._check_now = True
@ -760,7 +760,7 @@ class EditSubscriptionPanel( ClientGUIScrolledPanels.EditPanel ):
return subscription
def ResetCache( self, event ):
def ResetCache( self ):
message = '''Resetting this subscription's cache will delete ''' + HydrusData.ConvertIntToPrettyString( self._original_subscription.GetSeedCache().GetSeedCount() ) + ''' remembered urls, meaning when the subscription next runs, it will try to download those all over again. This may be expensive in time and data. Only do it if you are willing to wait. Do you want to do it?'''

View File

@ -1965,7 +1965,7 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
def EventFullscreensUpdate( self, event ):
( width, height ) = wx.GetDisplaySize()
( width, height ) = ClientGUITopLevelWindows.GetDisplaySize( self )
estimated_bytes_per_fullscreen = 3 * width * height

View File

@ -61,28 +61,28 @@ class ReviewServicesPanel( ClientGUIScrolledPanels.ReviewPanel ):
if service_type in HC.LOCAL_SERVICES: parent_listbook = self._local_listbook
else: parent_listbook = self._remote_listbook
if service_type not in listbook_dict:
if service_type == HC.TAG_REPOSITORY: name = 'tag repositories'
elif service_type == HC.FILE_REPOSITORY: name = 'file repositories'
elif service_type == HC.MESSAGE_DEPOT: name = 'message depots'
elif service_type == HC.SERVER_ADMIN: name = 'administrative servers'
elif service_type == HC.LOCAL_FILE: name = 'files'
elif service_type == HC.LOCAL_TAG: name = 'tags'
elif service_type == HC.LOCAL_RATING_LIKE: name = 'like/dislike ratings'
elif service_type == HC.LOCAL_RATING_NUMERICAL: name = 'numerical ratings'
elif service_type == HC.LOCAL_BOORU: name = 'booru'
elif service_type == HC.IPFS: name = 'ipfs'
else: continue
if service_type == HC.TAG_REPOSITORY: name = 'tag repositories'
elif service_type == HC.FILE_REPOSITORY: name = 'file repositories'
elif service_type == HC.MESSAGE_DEPOT: name = 'message depots'
elif service_type == HC.SERVER_ADMIN: name = 'administrative servers'
elif service_type in HC.LOCAL_FILE_SERVICES: name = 'files'
elif service_type == HC.LOCAL_TAG: name = 'tags'
elif service_type == HC.LOCAL_RATING_LIKE: name = 'like/dislike ratings'
elif service_type == HC.LOCAL_RATING_NUMERICAL: name = 'numerical ratings'
elif service_type == HC.LOCAL_BOORU: name = 'booru'
elif service_type == HC.IPFS: name = 'ipfs'
else: continue
if name not in listbook_dict:
listbook = ClientGUICommon.ListBook( parent_listbook )
listbook_dict[ service_type ] = listbook
listbook_dict[ name ] = listbook
parent_listbook.AddPage( name, name, listbook )
listbook = listbook_dict[ service_type ]
listbook = listbook_dict[ name ]
name = service.GetName()
@ -166,11 +166,11 @@ class ReviewServicesPanel( ClientGUIScrolledPanels.ReviewPanel ):
self._info_panel = ClientGUICommon.StaticBox( self, 'service information' )
if service_type in ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ):
if service_type in HC.FILE_SERVICES:
self._files_text = wx.StaticText( self._info_panel, style = wx.ALIGN_CENTER | wx.ST_NO_AUTORESIZE )
if self._service_key != CC.TRASH_SERVICE_KEY:
if service_type in ( HC.COMBINED_LOCAL_FILE, HC.FILE_REPOSITORY ):
self._deleted_files_text = wx.StaticText( self._info_panel, style = wx.ALIGN_CENTER | wx.ST_NO_AUTORESIZE )
@ -196,10 +196,6 @@ class ReviewServicesPanel( ClientGUIScrolledPanels.ReviewPanel ):
self._bytes_text = wx.StaticText( self._info_panel, style = wx.ALIGN_CENTER | wx.ST_NO_AUTORESIZE )
elif service_type == HC.IPFS:
self._files_text = wx.StaticText( self._info_panel, style = wx.ALIGN_CENTER | wx.ST_NO_AUTORESIZE )
if service_type in HC.RESTRICTED_SERVICES:
@ -280,7 +276,7 @@ class ReviewServicesPanel( ClientGUIScrolledPanels.ReviewPanel ):
self._service_wide_update.Bind( wx.EVT_BUTTON, self.EventServiceWideUpdate )
if self._service_key == CC.LOCAL_FILE_SERVICE_KEY:
if self._service_key == CC.COMBINED_LOCAL_FILE_SERVICE_KEY:
self._delete_local_deleted = wx.Button( self, label = 'clear deleted file record' )
self._delete_local_deleted.SetToolTipString( 'Make the client forget which files it has deleted from local files, resetting all the \'exclude already deleted files\' checks.' )
@ -318,11 +314,11 @@ class ReviewServicesPanel( ClientGUIScrolledPanels.ReviewPanel ):
if service_type in HC.REPOSITORIES + HC.LOCAL_SERVICES + [ HC.IPFS ]:
if service_type in ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ):
if service_type in HC.FILE_SERVICES:
self._info_panel.AddF( self._files_text, CC.FLAGS_EXPAND_PERPENDICULAR )
if self._service_key != CC.TRASH_SERVICE_KEY:
if service_type in ( HC.COMBINED_LOCAL_FILE, HC.FILE_REPOSITORY ):
self._info_panel.AddF( self._deleted_files_text, CC.FLAGS_EXPAND_PERPENDICULAR )
@ -346,10 +342,6 @@ class ReviewServicesPanel( ClientGUIScrolledPanels.ReviewPanel ):
self._info_panel.AddF( self._bytes, CC.FLAGS_EXPAND_PERPENDICULAR )
self._info_panel.AddF( self._bytes_text, CC.FLAGS_EXPAND_PERPENDICULAR )
elif service_type == HC.IPFS:
self._info_panel.AddF( self._files_text, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.AddF( self._info_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
@ -407,11 +399,11 @@ class ReviewServicesPanel( ClientGUIScrolledPanels.ReviewPanel ):
vbox.AddF( self._ipfs_shares_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
if service_type in HC.RESTRICTED_SERVICES + [ HC.LOCAL_TAG ] or self._service_key in ( CC.LOCAL_FILE_SERVICE_KEY, CC.TRASH_SERVICE_KEY ):
if service_type in HC.RESTRICTED_SERVICES + [ HC.LOCAL_TAG ] or self._service_key in ( CC.COMBINED_LOCAL_FILE_SERVICE_KEY, CC.TRASH_SERVICE_KEY ):
repo_buttons_hbox = wx.BoxSizer( wx.HORIZONTAL )
if self._service_key == CC.LOCAL_FILE_SERVICE_KEY:
if self._service_key == CC.COMBINED_LOCAL_FILE_SERVICE_KEY:
repo_buttons_hbox.AddF( self._delete_local_deleted, CC.FLAGS_VCENTER )
@ -595,14 +587,14 @@ class ReviewServicesPanel( ClientGUIScrolledPanels.ReviewPanel ):
service_info = self._controller.Read( 'service_info', self._service_key )
if service_type in ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ):
if service_type in HC.FILE_SERVICES:
num_files = service_info[ HC.SERVICE_INFO_NUM_FILES ]
total_size = service_info[ HC.SERVICE_INFO_TOTAL_SIZE ]
self._files_text.SetLabelText( HydrusData.ConvertIntToPrettyString( num_files ) + ' files, totalling ' + HydrusData.ConvertIntToBytes( total_size ) )
if self._service_key != CC.TRASH_SERVICE_KEY:
if service_type in ( HC.COMBINED_LOCAL_FILE, HC.FILE_REPOSITORY ):
num_deleted_files = service_info[ HC.SERVICE_INFO_NUM_DELETED_FILES ]
@ -636,13 +628,6 @@ class ReviewServicesPanel( ClientGUIScrolledPanels.ReviewPanel ):
self._num_shares.SetLabelText( HydrusData.ConvertIntToPrettyString( num_shares ) + ' shares currently active' )
elif service_type == HC.IPFS:
num_files = service_info[ HC.SERVICE_INFO_NUM_FILES ]
total_size = service_info[ HC.SERVICE_INFO_TOTAL_SIZE ]
self._files_text.SetLabelText( HydrusData.ConvertIntToPrettyString( num_files ) + ' files, totalling ' + HydrusData.ConvertIntToBytes( total_size ) )
if service_type == HC.LOCAL_BOORU:
@ -1083,4 +1068,4 @@ class ReviewServicesPanel( ClientGUIScrolledPanels.ReviewPanel ):

View File

@ -9,6 +9,36 @@ import wx
CHILD_POSITION_PADDING = 50
FUZZY_PADDING = 30
def GetDisplayPosition( window ):
display_index = wx.Display.GetFromWindow( window )
if display_index == wx.NOT_FOUND:
display_index = 0 # default to primary
display = wx.Display( display_index )
rect = display.GetClientArea()
return rect.GetPosition()
def GetDisplaySize( window ):
display_index = wx.Display.GetFromWindow( window )
if display_index == wx.NOT_FOUND:
display_index = 0 # default to primary
display = wx.Display( display_index )
rect = display.GetClientArea()
return rect.GetSize()
def GetSafePosition( position ):
( p_x, p_y ) = position
@ -67,7 +97,7 @@ def GetSafeSize( tlw, min_size, gravity ):
( display_width, display_height ) = wx.GetDisplaySize()
( display_width, display_height ) = GetDisplaySize( tlw )
width = min( display_width, width )
height = min( display_height, height )
@ -86,15 +116,16 @@ def ExpandTLWIfPossible( tlw, frame_key, desired_size_delta ):
( desired_delta_width, desired_delta_height ) = desired_size_delta
min_width = current_width + desired_delta_width + FUZZY_PADDING
min_height = current_height + desired_delta_height + FUZZY_PADDING
desired_width = current_width + desired_delta_width + FUZZY_PADDING
desired_height = current_height + desired_delta_height + FUZZY_PADDING
( width, height ) = GetSafeSize( tlw, ( min_width, min_height ), default_gravity )
( width, height ) = GetSafeSize( tlw, ( desired_width, desired_height ), default_gravity )
if width > current_width or height > current_height:
tlw.SetSize( ( width, height ) )
SlideOffScreenTLWUpAndLeft( tlw )
def SaveTLWSizeAndPosition( tlw, frame_key ):
@ -197,6 +228,31 @@ def SetTLWSizeAndPosition( tlw, frame_key ):
wx.CallAfter( tlw.ShowFullScreen, True, wx.FULLSCREEN_ALL )
def SlideOffScreenTLWUpAndLeft( tlw ):
( tlw_width, tlw_height ) = tlw.GetSize()
( tlw_x, tlw_y ) = tlw.GetPosition()
tlw_right = tlw_x + tlw_width
tlw_bottom = tlw_y + tlw_height
( display_width, display_height ) = GetDisplaySize( tlw )
( display_x, display_y ) = GetDisplayPosition( tlw )
display_right = display_x + display_width
display_bottom = display_y + display_height
move_x = tlw_right > display_right
move_y = tlw_bottom > display_bottom
if move_x or move_y:
delta_x = min( display_right - tlw_right, 0 )
delta_y = min( display_bottom - tlw_bottom, 0 )
tlw.SetPosition( ( tlw_x + delta_x, tlw_y + delta_y ) )
class NewDialog( wx.Dialog ):
def __init__( self, parent, title ):

View File

@ -2006,7 +2006,7 @@ class SeedCache( HydrusSerialisable.SerialisableBase ):
note = first_line + u'\u2026 (Copy note to see full error)'
note += os.linesep
note += traceback.format_exc()
note += HydrusData.ToUnicode( traceback.format_exc() )
HydrusData.Print( 'Error when processing ' + seed + '!' )
HydrusData.Print( traceback.format_exc() )
@ -2215,8 +2215,18 @@ class Subscription( HydrusSerialisable.SerialisableBaseNamed ):
if status == CC.STATUS_SUCCESSFUL:
job_key.SetVariable( 'popup_text_1', x_out_of_y + 'import successful' )
successful_hashes.add( hash )
elif status == CC.STATUS_DELETED:
job_key.SetVariable( 'popup_text_1', x_out_of_y + 'previously deleted' )
elif status == CC.STATUS_REDUNDANT:
job_key.SetVariable( 'popup_text_1', x_out_of_y + 'already in db' )
finally:
@ -2252,6 +2262,8 @@ class Subscription( HydrusSerialisable.SerialisableBaseNamed ):
status = CC.STATUS_FAILED
job_key.SetVariable( 'popup_text_1', x_out_of_y + 'file failed' )
self._seed_cache.UpdateSeedStatus( url, status, exception = e )
time.sleep( 10 )

View File

@ -80,7 +80,7 @@ def MergeTagsManagers( tags_managers ):
class LocationsManager( object ):
LOCAL_LOCATIONS = { CC.LOCAL_FILE_SERVICE_KEY, CC.TRASH_SERVICE_KEY }
LOCAL_LOCATIONS = { CC.LOCAL_FILE_SERVICE_KEY, CC.TRASH_SERVICE_KEY, CC.COMBINED_LOCAL_FILE_SERVICE_KEY }
def __init__( self, current, deleted, pending, petitioned, urls = None, service_keys_to_filenames = None, current_to_timestamps = None ):
@ -217,9 +217,9 @@ class LocationsManager( object ):
return self._urls
def HasDownloading( self ): return CC.LOCAL_FILE_SERVICE_KEY in self._pending
def IsDownloading( self ): return CC.COMBINED_LOCAL_FILE_SERVICE_KEY in self._pending
def HasLocal( self ): return len( self._current.intersection( self.LOCAL_LOCATIONS ) ) > 0
def IsLocal( self ): return CC.COMBINED_LOCAL_FILE_SERVICE_KEY in self._current
def ProcessContentUpdate( self, service_key, content_update ):
@ -235,6 +235,14 @@ class LocationsManager( object ):
if service_key == CC.LOCAL_FILE_SERVICE_KEY:
self._current.discard( CC.TRASH_SERVICE_KEY )
self._pending.discard( CC.COMBINED_LOCAL_FILE_SERVICE_KEY )
if CC.COMBINED_LOCAL_FILE_SERVICE_KEY not in self._current:
self._current.add( CC.COMBINED_LOCAL_FILE_SERVICE_KEY )
self._current_to_timestamps[ CC.COMBINED_LOCAL_FILE_SERVICE_KEY ] = HydrusData.GetNow()
self._current_to_timestamps[ service_key ] = HydrusData.GetNow()
@ -250,17 +258,20 @@ class LocationsManager( object ):
self._current.add( CC.TRASH_SERVICE_KEY )
self._current_to_timestamps[ CC.TRASH_SERVICE_KEY ] = self._current_to_timestamps[ CC.LOCAL_FILE_SERVICE_KEY ]
self._current_to_timestamps[ CC.TRASH_SERVICE_KEY ] = HydrusData.GetNow()
elif service_key == CC.TRASH_SERVICE_KEY:
self._current.discard( CC.COMBINED_LOCAL_FILE_SERVICE_KEY )
elif action == HC.CONTENT_UPDATE_UNDELETE:
self._current.discard( CC.TRASH_SERVICE_KEY )
self._deleted.discard( CC.LOCAL_FILE_SERVICE_KEY )
self._current.add( CC.LOCAL_FILE_SERVICE_KEY )
self._current_to_timestamps[ CC.LOCAL_FILE_SERVICE_KEY ] = self._current_to_timestamps[ CC.TRASH_SERVICE_KEY ]
elif action == HC.CONTENT_UPDATE_PEND:
if service_key not in self._current: self._pending.add( service_key )
@ -269,8 +280,14 @@ class LocationsManager( object ):
if service_key not in self._deleted: self._petitioned.add( service_key )
elif action == HC.CONTENT_UPDATE_RESCIND_PEND: self._pending.discard( service_key )
elif action == HC.CONTENT_UPDATE_RESCIND_PETITION: self._petitioned.discard( service_key )
elif action == HC.CONTENT_UPDATE_RESCIND_PEND:
self._pending.discard( service_key )
elif action == HC.CONTENT_UPDATE_RESCIND_PETITION:
self._petitioned.discard( service_key )
def ResetService( self, service_key ):
@ -411,8 +428,24 @@ class MediaList( object ):
elif sort_by_data == CC.SORT_BY_LARGEST: sort_function = lambda x: -deal_with_none( x.GetSize() )
elif sort_by_data == CC.SORT_BY_SHORTEST: sort_function = lambda x: deal_with_none( x.GetDuration() )
elif sort_by_data == CC.SORT_BY_LONGEST: sort_function = lambda x: -deal_with_none( x.GetDuration() )
elif sort_by_data == CC.SORT_BY_OLDEST: sort_function = lambda x: deal_with_none( x.GetTimestamp( self._file_service_key ) )
elif sort_by_data == CC.SORT_BY_NEWEST: sort_function = lambda x: -deal_with_none( x.GetTimestamp( self._file_service_key ) )
elif sort_by_data in ( CC.SORT_BY_OLDEST, CC.SORT_BY_NEWEST ):
file_service = HydrusGlobals.client_controller.GetServicesManager().GetService( self._file_service_key )
file_service_type = file_service.GetServiceType()
if file_service_type == HC.LOCAL_FILE_DOMAIN:
file_service_key = CC.COMBINED_LOCAL_FILE_SERVICE_KEY
else:
file_service_key = self._file_service_key
if sort_by_data == CC.SORT_BY_OLDEST: sort_function = lambda x: deal_with_none( x.GetTimestamp( file_service_key ) )
elif sort_by_data == CC.SORT_BY_NEWEST: sort_function = lambda x: -deal_with_none( x.GetTimestamp( file_service_key ) )
elif sort_by_data == CC.SORT_BY_MIME: sort_function = lambda x: x.GetMime()
elif sort_by_type == 'namespaces':
@ -647,11 +680,14 @@ class MediaList( object ):
locations_manager = media.GetLocationsManager()
inbox_failed = discriminant == CC.DISCRIMINANT_INBOX and not media.HasInbox()
local_failed = discriminant == CC.DISCRIMINANT_LOCAL and not locations_manager.HasLocal()
not_local_failed = discriminant == CC.DISCRIMINANT_NOT_LOCAL and locations_manager.HasLocal()
downloading_failed = discriminant == CC.DISCRIMINANT_DOWNLOADING and CC.LOCAL_FILE_SERVICE_KEY not in locations_manager.GetPending()
local_failed = discriminant == CC.DISCRIMINANT_LOCAL and not locations_manager.IsLocal()
not_local_failed = discriminant == CC.DISCRIMINANT_NOT_LOCAL and locations_manager.IsLocal()
downloading_failed = discriminant == CC.DISCRIMINANT_DOWNLOADING and not locations_manager.IsDownloading()
if inbox_failed or local_failed or not_local_failed or downloading_failed: continue
if inbox_failed or local_failed or not_local_failed or downloading_failed:
continue
if unrated is not None:
@ -725,7 +761,10 @@ class MediaList( object ):
hashes = content_update.GetHashes()
for media in self._GetMedia( hashes, 'collections' ): media.ProcessContentUpdate( service_key, content_update )
for media in self._GetMedia( hashes, 'collections' ):
media.ProcessContentUpdate( service_key, content_update )
if data_type == HC.CONTENT_TYPE_FILES:
@ -754,7 +793,10 @@ class MediaList( object ):
for ( service_key, content_updates ) in service_keys_to_content_updates.items():
for content_update in content_updates: self.ProcessContentUpdate( service_key, content_update )
for content_update in content_updates:
self.ProcessContentUpdate( service_key, content_update )
@ -1071,7 +1113,7 @@ class MediaSingleton( Media ):
locations_manager = self._media_result.GetLocationsManager()
if ( discriminant == CC.DISCRIMINANT_INBOX and not inbox ) or ( discriminant == CC.DISCRIMINANT_ARCHIVE and inbox ) or ( discriminant == CC.DISCRIMINANT_LOCAL and not locations_manager.HasLocal() ) or ( discriminant == CC.DISCRIMINANT_NOT_LOCAL and locations_manager.HasLocal() ):
if ( discriminant == CC.DISCRIMINANT_INBOX and not inbox ) or ( discriminant == CC.DISCRIMINANT_ARCHIVE and inbox ) or ( discriminant == CC.DISCRIMINANT_LOCAL and not locations_manager.IsLocal() ) or ( discriminant == CC.DISCRIMINANT_NOT_LOCAL and locations_manager.IsLocal() ):
if ordered:
@ -1171,9 +1213,9 @@ class MediaSingleton( Media ):
current_service_keys = locations_manager.GetCurrent()
if CC.LOCAL_FILE_SERVICE_KEY in current_service_keys:
if CC.COMBINED_LOCAL_FILE_SERVICE_KEY in current_service_keys:
timestamp = locations_manager.GetTimestamp( CC.LOCAL_FILE_SERVICE_KEY )
timestamp = locations_manager.GetTimestamp( CC.COMBINED_LOCAL_FILE_SERVICE_KEY )
lines.append( 'imported ' + HydrusData.ConvertTimestampToPrettyAgo( timestamp ) )
@ -1182,12 +1224,12 @@ class MediaSingleton( Media ):
timestamp = locations_manager.GetTimestamp( CC.TRASH_SERVICE_KEY )
lines.append( 'imported ' + HydrusData.ConvertTimestampToPrettyAgo( timestamp ) + ', now in the trash' )
lines.append( 'trashed ' + HydrusData.ConvertTimestampToPrettyAgo( timestamp ) )
for service_key in current_service_keys:
if service_key in ( CC.LOCAL_FILE_SERVICE_KEY, CC.TRASH_SERVICE_KEY ):
if service_key in ( CC.COMBINED_LOCAL_FILE_SERVICE_KEY, CC.LOCAL_FILE_SERVICE_KEY, CC.TRASH_SERVICE_KEY ):
continue
@ -1365,8 +1407,14 @@ class MediaResult( object ):
service_type = service.GetServiceType()
if service_type == HC.TAG_REPOSITORY: tags_manager.DeletePending( service_key )
elif service_type in ( HC.FILE_REPOSITORY, HC.LOCAL_FILE ): locations_manager.DeletePending( service_key )
if service_type in HC.TAG_SERVICES:
tags_manager.DeletePending( service_key )
elif service_type in HC.FILE_SERVICES:
locations_manager.DeletePending( service_key )
def Duplicate( self ):
@ -1418,9 +1466,11 @@ class MediaResult( object ):
tags_manager.ProcessContentUpdate( service_key, content_update )
elif service_type in ( HC.FILE_REPOSITORY, HC.LOCAL_FILE, HC.IPFS ):
elif service_type in HC.FILE_SERVICES:
if service_type == HC.LOCAL_FILE:
previously_local = CC.COMBINED_LOCAL_FILE_SERVICE_KEY in locations_manager.GetCurrent()
if service_type in HC.LOCAL_FILE_SERVICES:
if action == HC.CONTENT_UPDATE_ARCHIVE:
@ -1431,26 +1481,34 @@ class MediaResult( object ):
inbox = True
if service_key == CC.LOCAL_FILE_SERVICE_KEY:
if service_type == CC.COMBINED_LOCAL_FILE_SERVICE_KEY:
if action == HC.CONTENT_UPDATE_ADD and CC.TRASH_SERVICE_KEY not in locations_manager.GetCurrent():
if action == HC.CONTENT_UPDATE_ADD:
inbox = True
elif service_key == CC.TRASH_SERVICE_KEY:
if action == HC.CONTENT_UPDATE_DELETE:
elif action == HC.CONTENT_UPDATE_DELETE:
inbox = False
self._tuple = ( hash, inbox, size, mime, width, height, duration, num_frames, num_words, tags_manager, locations_manager, ratings_manager )
locations_manager.ProcessContentUpdate( service_key, content_update )
subsequently_local = CC.COMBINED_LOCAL_FILE_SERVICE_KEY in locations_manager.GetCurrent()
if not previously_local and subsequently_local:
inbox = True
if previously_local and not subsequently_local:
inbox = False
self._tuple = ( hash, inbox, size, mime, width, height, duration, num_frames, num_words, tags_manager, locations_manager, ratings_manager )
elif service_type in HC.RATINGS_SERVICES:
ratings_manager.ProcessContentUpdate( service_key, content_update )
@ -1868,8 +1926,14 @@ class TagsManager( TagsManagerSimple ):
( data_type, action, row ) = content_update.ToTuple()
if action == HC.CONTENT_UPDATE_PETITION: ( tag, hashes, reason ) = row
else: ( tag, hashes ) = row
if action == HC.CONTENT_UPDATE_PETITION:
( tag, hashes, reason ) = row
else:
( tag, hashes ) = row
if action == HC.CONTENT_UPDATE_ADD:
@ -1892,7 +1956,10 @@ class TagsManager( TagsManagerSimple ):
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_RESCIND_PEND:
statuses_to_tags[ HC.PENDING ].discard( tag )
elif action == HC.CONTENT_UPDATE_PETITION:
if tag in statuses_to_tags[ HC.CURRENT ]:
@ -1914,4 +1981,4 @@ class TagsManager( TagsManagerSimple ):
self._combined_is_calculated = False

View File

@ -254,6 +254,18 @@ class FileSearchContext( HydrusSerialisable.SerialisableBase ):
self._file_service_key = file_service_key.decode( 'hex' )
self._tag_service_key = tag_service_key.decode( 'hex' )
services_manager = HydrusGlobals.client_controller.GetServicesManager()
if not services_manager.ServiceExists( self._file_service_key ):
self._file_service_key = CC.COMBINED_LOCAL_FILE_SERVICE_KEY
if not services_manager.ServiceExists( self._tag_service_key ):
self._tag_service_key = CC.COMBINED_TAG_SERVICE_KEY
self._predicates = [ HydrusSerialisable.CreateFromSerialisableTuple( pred_tuple ) for pred_tuple in serialisable_predicates ]
self._InitialiseTemporaryVariables()

View File

@ -46,7 +46,7 @@ options = {}
# Misc
NETWORK_VERSION = 17
SOFTWARE_VERSION = 236
SOFTWARE_VERSION = 237
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )
@ -145,7 +145,7 @@ permissions_string_lookup[ UNKNOWN_PERMISSION ] = 'unknown'
TAG_REPOSITORY = 0
FILE_REPOSITORY = 1
LOCAL_FILE = 2
LOCAL_FILE_DOMAIN = 2
MESSAGE_DEPOT = 3
LOCAL_TAG = 5
LOCAL_RATING_NUMERICAL = 6
@ -156,6 +156,8 @@ COMBINED_TAG = 10
COMBINED_FILE = 11
LOCAL_BOORU = 12
IPFS = 13
LOCAL_FILE_TRASH_DOMAIN = 14
COMBINED_LOCAL_FILE = 15
SERVER_ADMIN = 99
NULL_SERVICE = 100
@ -163,7 +165,9 @@ service_string_lookup = {}
service_string_lookup[ TAG_REPOSITORY ] = 'hydrus tag repository'
service_string_lookup[ FILE_REPOSITORY ] = 'hydrus file repository'
service_string_lookup[ LOCAL_FILE ] = 'hydrus local file service'
service_string_lookup[ LOCAL_FILE_DOMAIN ] = 'hydrus local file domain'
service_string_lookup[ LOCAL_FILE_TRASH_DOMAIN ] = 'hydrus trash domain'
service_string_lookup[ COMBINED_LOCAL_FILE ] = 'hydrus local file service'
service_string_lookup[ MESSAGE_DEPOT ] = 'hydrus message depot'
service_string_lookup[ LOCAL_TAG ] = 'local tag service'
service_string_lookup[ LOCAL_RATING_NUMERICAL ] = 'local numerical rating service'
@ -177,16 +181,23 @@ service_string_lookup[ IPFS ] = 'ipfs daemon'
service_string_lookup[ SERVER_ADMIN ] = 'hydrus server administration'
service_string_lookup[ NULL_SERVICE ] = 'null service'
LOCAL_FILE_SERVICES = [ LOCAL_FILE_DOMAIN, LOCAL_FILE_TRASH_DOMAIN, COMBINED_LOCAL_FILE ]
LOCAL_TAG_SERVICES = [ LOCAL_TAG ]
LOCAL_SERVICES = list( LOCAL_FILE_SERVICES ) + list( LOCAL_TAG_SERVICES ) + [ LOCAL_RATING_LIKE, LOCAL_RATING_NUMERICAL, LOCAL_BOORU ]
RATINGS_SERVICES = [ LOCAL_RATING_LIKE, LOCAL_RATING_NUMERICAL, RATING_LIKE_REPOSITORY, RATING_NUMERICAL_REPOSITORY ]
REPOSITORIES = [ TAG_REPOSITORY, FILE_REPOSITORY, RATING_LIKE_REPOSITORY, RATING_NUMERICAL_REPOSITORY ]
RESTRICTED_SERVICES = list( REPOSITORIES ) + [ SERVER_ADMIN, MESSAGE_DEPOT ]
REMOTE_SERVICES = list( RESTRICTED_SERVICES ) + [ IPFS ]
FILE_SERVICES = list( LOCAL_FILE_SERVICES ) + [ FILE_REPOSITORY, IPFS ]
TAG_SERVICES = [ LOCAL_TAG, TAG_REPOSITORY ]
LOCAL_SERVICES = [ LOCAL_FILE, LOCAL_TAG, LOCAL_RATING_LIKE, LOCAL_RATING_NUMERICAL, LOCAL_BOORU, COMBINED_FILE, COMBINED_TAG ]
NONEDITABLE_SERVICES = [ LOCAL_BOORU, LOCAL_FILE, LOCAL_TAG ]
ALL_SERVICES = list( REMOTE_SERVICES ) + list( LOCAL_SERVICES )
NONADDREMOVEABLE_SERVICES = [ LOCAL_BOORU, LOCAL_FILE_DOMAIN, LOCAL_FILE_TRASH_DOMAIN, LOCAL_TAG ]
NONRENAMEABLE_SERVICES = [ LOCAL_BOORU, LOCAL_FILE_TRASH_DOMAIN, LOCAL_TAG ]
AUTOCOMPLETE_CACHE_SPECIFIC_FILE_SERVICES = [ LOCAL_FILE_DOMAIN, LOCAL_FILE_TRASH_DOMAIN, COMBINED_LOCAL_FILE, FILE_REPOSITORY ]
ALL_SERVICES = list( REMOTE_SERVICES ) + list( LOCAL_SERVICES ) + [ COMBINED_FILE, COMBINED_TAG ]
SERVICES_WITH_THUMBNAILS = [ FILE_REPOSITORY, LOCAL_FILE ]
SERVICES_WITH_THUMBNAILS = [ FILE_REPOSITORY, LOCAL_FILE_DOMAIN ]
DELETE_FILES_PETITION = 0
DELETE_TAG_PETITION = 1

View File

@ -112,7 +112,7 @@ class HydrusResourceWelcome( Resource ):
Resource.__init__( self )
if service_type == HC.LOCAL_FILE: body = CLIENT_ROOT_MESSAGE
if service_type == HC.COMBINED_LOCAL_FILE: body = CLIENT_ROOT_MESSAGE
else: body = ROOT_MESSAGE_BEGIN + message + ROOT_MESSAGE_END
self._body = HydrusData.ToByteString( body )
@ -604,4 +604,4 @@ class ResponseContext( object ):
def HasPath( self ): return self._path is not None
def IsJSON( self ): return self._is_json

View File

@ -117,12 +117,12 @@ class TestManagers( unittest.TestCase ):
hash_2 = HydrusData.GenerateKey()
hash_3 = HydrusData.GenerateKey()
command_1 = { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, { hash_1 } ) ] }
command_2 = { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_INBOX, { hash_2 } ) ] }
command_3 = { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, { hash_1, hash_3 } ) ] }
command_1 = { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, { hash_1 } ) ] }
command_2 = { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_INBOX, { hash_2 } ) ] }
command_3 = { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, { hash_1, hash_3 } ) ] }
command_1_inverted = { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_INBOX, { hash_1 } ) ] }
command_2_inverted = { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, { hash_2 } ) ] }
command_1_inverted = { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_INBOX, { hash_1 } ) ] }
command_2_inverted = { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, { hash_2 } ) ] }
undo_manager = ClientCaches.UndoManager( HydrusGlobals.client_controller )
@ -130,15 +130,15 @@ class TestManagers( unittest.TestCase ):
undo_manager.AddCommand( 'content_updates', command_1 )
self.assertEqual( ( u'undo local files->archive 1 files', None ), undo_manager.GetUndoRedoStrings() )
self.assertEqual( ( u'undo archive 1 files', None ), undo_manager.GetUndoRedoStrings() )
undo_manager.AddCommand( 'content_updates', command_2 )
self.assertEqual( ( u'undo local files->inbox 1 files', None ), undo_manager.GetUndoRedoStrings() )
self.assertEqual( ( u'undo inbox 1 files', None ), undo_manager.GetUndoRedoStrings() )
undo_manager.Undo()
self.assertEqual( ( u'undo local files->archive 1 files', u'redo local files->inbox 1 files' ), undo_manager.GetUndoRedoStrings() )
self.assertEqual( ( u'undo archive 1 files', u'redo inbox 1 files' ), undo_manager.GetUndoRedoStrings() )
self.assertEqual( HydrusGlobals.test_controller.GetWrite( 'content_updates' ), [ ( ( command_2_inverted, ), {} ) ] )
@ -146,7 +146,7 @@ class TestManagers( unittest.TestCase ):
self.assertEqual( HydrusGlobals.test_controller.GetWrite( 'content_updates' ), [ ( ( command_2, ), {} ) ] )
self.assertEqual( ( u'undo local files->inbox 1 files', None ), undo_manager.GetUndoRedoStrings() )
self.assertEqual( ( u'undo inbox 1 files', None ), undo_manager.GetUndoRedoStrings() )
undo_manager.Undo()
@ -156,10 +156,10 @@ class TestManagers( unittest.TestCase ):
self.assertEqual( HydrusGlobals.test_controller.GetWrite( 'content_updates' ), [ ( ( command_1_inverted, ), {} ) ] )
self.assertEqual( ( None, u'redo local files->archive 1 files' ), undo_manager.GetUndoRedoStrings() )
self.assertEqual( ( None, u'redo archive 1 files' ), undo_manager.GetUndoRedoStrings() )
undo_manager.AddCommand( 'content_updates', command_3 )
self.assertEqual( ( u'undo local files->archive 2 files', None ), undo_manager.GetUndoRedoStrings() )
self.assertEqual( ( u'undo archive 2 files', None ), undo_manager.GetUndoRedoStrings() )

View File

@ -424,7 +424,7 @@ class TestClientDB( unittest.TestCase ):
service_keys_to_content_updates = {}
service_keys_to_content_updates[ CC.LOCAL_FILE_SERVICE_KEY ] = ( HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, ( hash, ) ), )
service_keys_to_content_updates[ CC.COMBINED_LOCAL_FILE_SERVICE_KEY ] = ( HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, ( hash, ) ), )
service_keys_to_content_updates[ CC.LOCAL_TAG_SERVICE_KEY ] = ( HydrusData.ContentUpdate( HC.CONTENT_TYPE_MAPPINGS, HC.CONTENT_UPDATE_ADD, ( 'car', ( hash, ) ) ), )
self._write( 'content_updates', service_keys_to_content_updates )
@ -957,7 +957,7 @@ class TestClientDB( unittest.TestCase ):
service_keys_to_content_updates = {}
service_keys_to_content_updates[ CC.LOCAL_FILE_SERVICE_KEY ] = ( HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_PEND, ( hash, ) ), )
service_keys_to_content_updates[ CC.COMBINED_LOCAL_FILE_SERVICE_KEY ] = ( HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_PEND, ( hash, ) ), )
self._write( 'content_updates', service_keys_to_content_updates )
@ -973,7 +973,7 @@ class TestClientDB( unittest.TestCase ):
service_keys_to_content_updates = {}
service_keys_to_content_updates[ CC.LOCAL_FILE_SERVICE_KEY ] = ( HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_RESCIND_PEND, ( hash, ) ), )
service_keys_to_content_updates[ CC.COMBINED_LOCAL_FILE_SERVICE_KEY ] = ( HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_RESCIND_PEND, ( hash, ) ), )
self._write( 'content_updates', service_keys_to_content_updates )
@ -986,11 +986,11 @@ class TestClientDB( unittest.TestCase ):
def test_services( self ):
result = self._read( 'services', ( HC.LOCAL_FILE, HC.LOCAL_TAG ) )
result = self._read( 'services', ( HC.LOCAL_FILE_DOMAIN, HC.LOCAL_FILE_TRASH_DOMAIN, HC.COMBINED_LOCAL_FILE, HC.LOCAL_TAG ) )
result_service_keys = { service.GetServiceKey() for service in result }
self.assertItemsEqual( { CC.TRASH_SERVICE_KEY, CC.LOCAL_FILE_SERVICE_KEY, CC.LOCAL_TAG_SERVICE_KEY }, result_service_keys )
self.assertItemsEqual( { CC.TRASH_SERVICE_KEY, CC.LOCAL_FILE_SERVICE_KEY, CC.COMBINED_LOCAL_FILE_SERVICE_KEY, CC.LOCAL_TAG_SERVICE_KEY }, result_service_keys )
#

View File

@ -71,7 +71,7 @@ class TestServer( unittest.TestCase ):
def TWISTEDSetup():
reactor.listenTCP( HC.DEFAULT_SERVER_ADMIN_PORT, ServerServer.HydrusServiceAdmin( self._admin_service.GetServiceKey(), HC.SERVER_ADMIN, 'hello' ) )
reactor.listenTCP( HC.DEFAULT_LOCAL_FILE_PORT, ClientLocalServer.HydrusServiceLocal( CC.LOCAL_FILE_SERVICE_KEY, HC.LOCAL_FILE, 'hello' ) )
reactor.listenTCP( HC.DEFAULT_LOCAL_FILE_PORT, ClientLocalServer.HydrusServiceLocal( CC.COMBINED_LOCAL_FILE_SERVICE_KEY, HC.COMBINED_LOCAL_FILE, 'hello' ) )
reactor.listenTCP( HC.DEFAULT_LOCAL_BOORU_PORT, ClientLocalServer.HydrusServiceBooru( CC.LOCAL_BOORU_SERVICE_KEY, HC.LOCAL_BOORU, 'hello' ) )
reactor.listenTCP( HC.DEFAULT_SERVICE_PORT, ServerServer.HydrusServiceRepositoryFile( self._file_service.GetServiceKey(), HC.FILE_REPOSITORY, 'hello' ) )
reactor.listenTCP( HC.DEFAULT_SERVICE_PORT + 1, ServerServer.HydrusServiceRepositoryTag( self._tag_service.GetServiceKey(), HC.TAG_REPOSITORY, 'hello' ) )

View File

@ -85,9 +85,13 @@ class Controller( object ):
self._reads[ 'options' ] = ClientDefaults.GetClientDefaultOptions()
services = []
services.append( ClientData.GenerateService( CC.LOCAL_BOORU_SERVICE_KEY, HC.LOCAL_BOORU, CC.LOCAL_BOORU_SERVICE_KEY, { 'max_monthly_data' : None, 'used_monthly_data' : 0 } ) )
services.append( ClientData.GenerateService( CC.LOCAL_FILE_SERVICE_KEY, HC.LOCAL_FILE, CC.LOCAL_FILE_SERVICE_KEY, {} ) )
services.append( ClientData.GenerateService( CC.COMBINED_LOCAL_FILE_SERVICE_KEY, HC.COMBINED_LOCAL_FILE, CC.COMBINED_LOCAL_FILE_SERVICE_KEY, {} ) )
services.append( ClientData.GenerateService( CC.LOCAL_FILE_SERVICE_KEY, HC.LOCAL_FILE_DOMAIN, CC.LOCAL_FILE_SERVICE_KEY, {} ) )
services.append( ClientData.GenerateService( CC.TRASH_SERVICE_KEY, HC.LOCAL_FILE_TRASH_DOMAIN, CC.LOCAL_FILE_SERVICE_KEY, {} ) )
services.append( ClientData.GenerateService( CC.LOCAL_TAG_SERVICE_KEY, HC.LOCAL_TAG, CC.LOCAL_TAG_SERVICE_KEY, {} ) )
self._reads[ 'services' ] = services
client_files_locations = {}
@ -366,4 +370,4 @@ if __name__ == '__main__':
print( 'This was version ' + str( HC.SOFTWARE_VERSION ) )
raw_input()