Version 138
This commit is contained in:
parent
ddcf0181fd
commit
71b68f1f2c
|
@ -8,6 +8,25 @@
|
|||
<div class="content">
|
||||
<h3>changelog</h3>
|
||||
<ul>
|
||||
<li><h3>version 138</h3></li>
|
||||
<ul>
|
||||
<li>created new 'maintenance and memory' options page in the manage options dialog, and moved some things over from 'files and memory', which is now 'files and thumbnails'</li>
|
||||
<li>added options for idle, vacuum, and delete orphans periods to the 'maintenance and memory' page in the manage options dialog</li>
|
||||
<li>fixed the incredibly annoying animated scanbar delayed-frame bug, where a click on the scanbar would not draw the new frame until the old frame's expected delay was complete. scanbar scanning is a lot smoother all around, now</li>
|
||||
<li>animations now show their current frame number in the animation scanbar</li>
|
||||
<li>status bar now shows inbox/archived counts on any selection</li>
|
||||
<li>reworked static image zoom code so they resize beautifully, without jaggies, at the cost of a bit of CPU and memory</li>
|
||||
<li>created new flexible message pathway</li>
|
||||
<li>moved most messages to new pathway</li>
|
||||
<li>improved a bunch of message and job_key related code</li>
|
||||
<li>btw: messages will no longer close themselves; their end state is now to report what happened until you dismiss them. if this turns out to be annoying, I'll change it</li>
|
||||
<li>fixed the pending menu not updating its count when files imported and added tags via archive sync</li>
|
||||
<li>improved the logic behind the 'computer just woke from sleep' calculation</li>
|
||||
<li>improved the accuracy of the 'client is currently idle' calculation</li>
|
||||
<li>improved database vacuum so the .db-wal file is flushed afterwards, for both client and server</li>
|
||||
<li>because of better vacuuming, server db backup no longer needs to create a bloated .db-wal backup</li>
|
||||
<li>removed a very common superfluous empty tag upload packet in normal tag uploads</li>
|
||||
</ul>
|
||||
<li><h3>version 137</h3></li>
|
||||
<ul>
|
||||
<li>eliminated a loophole in the tag-pending process that allowed zero-length subtags through during archive sync</li>
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
<p>All of a server's files and options are stored in its accompanying .db file and respective subdirectories, which are created on first startup (just like with the client). You can backup and restore these files just by copying them about, but you have to be careful how you do it with a server; when it is running, it has a live connection to its database, and all sorts of things could be written or read at any time. If you just try to copy the .db somewhere and someone uploads a file, something might break. Instead, you have two options:</p>
|
||||
<ul>
|
||||
<li>Shut down the server, copy the .db files, then restart it. This is the only way, currently, to restore a db.</li>
|
||||
<li>Hit admin->your server->make a backup. This will lock the db server-side while it makes a copy right in the /db directory. The .db file will be tidied up and copied to .db.backup and the subdirectories will be copied to _backup as well. When the operation is complete, you can ftp/batch-copy/whatever these backup files wherever you like.</li>
|
||||
<li>Hit admin->your server->make a backup on your client. This will lock the db server-side while it makes a copy right in the /db directory. The .db file will be tidied up and copied to .db.backup and the subdirectories will be copied to _backup as well. When the operation is complete, you can ftp/batch-copy/whatever these backup files wherever you like.</li>
|
||||
</ul>
|
||||
<h3>OMG EVERYTHING WENT WRONG</h3>
|
||||
<p>If you get to a point where you can no longer boot the repository, try running SQLite Studio and opening server.db. If the issue is simple—like manually changing the port number—you may be in luck. Send me an email if it is tricky.</p>
|
||||
|
|
|
@ -193,6 +193,9 @@ CLIENT_DEFAULT_OPTIONS[ 'gui_capitalisation' ] = False
|
|||
CLIENT_DEFAULT_OPTIONS[ 'default_gui_session' ] = 'just a blank page'
|
||||
CLIENT_DEFAULT_OPTIONS[ 'ac_timings' ] = ( 3, 500, 250 )
|
||||
CLIENT_DEFAULT_OPTIONS[ 'thread_checker_timings' ] = ( 3, 1200 )
|
||||
CLIENT_DEFAULT_OPTIONS[ 'idle_period' ] = 60 * 30
|
||||
CLIENT_DEFAULT_OPTIONS[ 'maintenance_delete_orphans_period' ] = 86400 * 3
|
||||
CLIENT_DEFAULT_OPTIONS[ 'maintenance_vacuum_period' ] = 86400 * 5
|
||||
|
||||
system_predicates = {}
|
||||
|
||||
|
@ -328,7 +331,9 @@ def CatchExceptionClient( etype, value, tb ):
|
|||
info[ 'caller_traceback' ] = caller_traceback
|
||||
info[ 'db_traceback' ] = db_traceback
|
||||
|
||||
message = HC.Message( HC.MESSAGE_TYPE_DB_ERROR, info )
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
message = HC.Message( HC.MESSAGE_TYPE_DB_ERROR, job_key, info )
|
||||
|
||||
else:
|
||||
|
||||
|
@ -336,7 +341,9 @@ def CatchExceptionClient( etype, value, tb ):
|
|||
|
||||
trace = ''.join( trace_list )
|
||||
|
||||
message = HC.Message( HC.MESSAGE_TYPE_ERROR, { 'error' : ( etype, value, trace ) } )
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
message = HC.Message( HC.MESSAGE_TYPE_ERROR, job_key, { 'error' : ( etype, value, trace ) } )
|
||||
|
||||
|
||||
HC.pubsub.pub( 'message', message )
|
||||
|
@ -789,7 +796,9 @@ def ShowExceptionClient( e ):
|
|||
info[ 'caller_traceback' ] = caller_traceback
|
||||
info[ 'db_traceback' ] = db_traceback
|
||||
|
||||
message = HC.Message( HC.MESSAGE_TYPE_DB_ERROR, info )
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
message = HC.Message( HC.MESSAGE_TYPE_DB_ERROR, job_key, info )
|
||||
|
||||
else:
|
||||
|
||||
|
@ -804,13 +813,21 @@ def ShowExceptionClient( e ):
|
|||
|
||||
else: trace = ''.join( traceback.format_exception( etype, value, tb ) )
|
||||
|
||||
message = HC.Message( HC.MESSAGE_TYPE_ERROR, { 'error' : ( etype, value, trace ) } )
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
message = HC.Message( HC.MESSAGE_TYPE_ERROR, job_key, { 'error' : ( etype, value, trace ) } )
|
||||
|
||||
|
||||
HC.pubsub.pub( 'message', message )
|
||||
|
||||
def ShowTextClient( text ): HC.pubsub.pub( 'message', HC.Message( HC.MESSAGE_TYPE_TEXT, { 'text' : text } ) )
|
||||
|
||||
def ShowTextClient( text ):
|
||||
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
job_key.SetVariable( 'popup_message_text_1', text )
|
||||
|
||||
HC.pubsub.pub( 'message', job_key )
|
||||
|
||||
class AutocompleteMatches( object ):
|
||||
|
||||
def __init__( self, matches ):
|
||||
|
|
|
@ -35,6 +35,15 @@ MAINTENANCE_PERIOD = 5 * 60
|
|||
|
||||
class Controller( wx.App ):
|
||||
|
||||
def _CheckIfJustWokeFromSleep( self ):
|
||||
|
||||
last_maintenance_time = self._timestamps[ 'last_maintenance_time' ]
|
||||
|
||||
# this tests if we probably just woke up from a sleep
|
||||
if HC.GetNow() - last_maintenance_time > MAINTENANCE_PERIOD + ( 5 * 60 ): self._just_woke_from_sleep = True
|
||||
else: self._just_woke_from_sleep = False
|
||||
|
||||
|
||||
def _Read( self, action, *args, **kwargs ): return self._db.Read( action, HC.HIGH_PRIORITY, *args, **kwargs )
|
||||
|
||||
def _Write( self, action, priority, synchronous, *args, **kwargs ): return self._db.Write( action, priority, synchronous, *args, **kwargs )
|
||||
|
@ -155,7 +164,12 @@ class Controller( wx.App ):
|
|||
|
||||
|
||||
|
||||
def CurrentlyIdle( self ): return HC.GetNow() - self._timestamps[ 'last_user_action' ] > 30 * 60 # 30 mins since last canvas media swap
|
||||
def CurrentlyIdle( self ):
|
||||
|
||||
if HC.options[ 'idle_period' ] == 0: return False
|
||||
|
||||
return HC.GetNow() - self._timestamps[ 'last_user_action' ] > HC.options[ 'idle_period' ]
|
||||
|
||||
|
||||
def EventPubSub( self, event ):
|
||||
|
||||
|
@ -292,7 +306,12 @@ class Controller( wx.App ):
|
|||
self._db.StartDaemons()
|
||||
|
||||
|
||||
def JustWokeFromSleep( self ): return self._just_woke_from_sleep
|
||||
def JustWokeFromSleep( self ):
|
||||
|
||||
if not self._just_woke_from_sleep: self._CheckIfJustWokeFromSleep()
|
||||
|
||||
return self._just_woke_from_sleep
|
||||
|
||||
|
||||
def MaintainDB( self ):
|
||||
|
||||
|
@ -302,8 +321,15 @@ class Controller( wx.App ):
|
|||
|
||||
shutdown_timestamps = self.Read( 'shutdown_timestamps' )
|
||||
|
||||
if now - shutdown_timestamps[ CC.SHUTDOWN_TIMESTAMP_VACUUM ] > 86400 * 5: self.Write( 'vacuum' )
|
||||
if now - shutdown_timestamps[ CC.SHUTDOWN_TIMESTAMP_DELETE_ORPHANS ] > 86400 * 3: self.Write( 'delete_orphans' )
|
||||
if HC.options[ 'maintenance_vacuum_period' ] != 0:
|
||||
|
||||
if now - shutdown_timestamps[ CC.SHUTDOWN_TIMESTAMP_VACUUM ] > HC.options[ 'maintenance_vacuum_period' ]: self.Write( 'vacuum' )
|
||||
|
||||
|
||||
if HC.options[ 'maintenance_delete_orphans_period' ] != 0:
|
||||
|
||||
if now - shutdown_timestamps[ CC.SHUTDOWN_TIMESTAMP_DELETE_ORPHANS ] > HC.options[ 'maintenance_delete_orphans_period' ]: self.Write( 'delete_orphans' )
|
||||
|
||||
|
||||
if now - self._timestamps[ 'last_service_info_cache_fatten' ] > 60 * 20:
|
||||
|
||||
|
@ -592,13 +618,9 @@ class Controller( wx.App ):
|
|||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
|
||||
last_time_this_ran = self._timestamps[ 'last_check_idle_time' ]
|
||||
self._CheckIfJustWokeFromSleep()
|
||||
|
||||
self._timestamps[ 'last_check_idle_time' ] = HC.GetNow()
|
||||
|
||||
# this tests if we probably just woke up from a sleep
|
||||
if HC.GetNow() - last_time_this_ran > MAINTENANCE_PERIOD + ( 5 * 60 ): self._just_woke_from_sleep = True
|
||||
else: self._just_woke_from_sleep = False
|
||||
self._timestamps[ 'last_maintenance_time' ] = HC.GetNow()
|
||||
|
||||
if not self._just_woke_from_sleep and self.CurrentlyIdle(): self.MaintainDB()
|
||||
|
||||
|
|
|
@ -1456,9 +1456,9 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, prefix_string + 'preparing', job_key )
|
||||
job_key.SetVariable( 'popup_message_text_1', prefix_string + 'preparing' )
|
||||
|
||||
HC.pubsub.pub( 'message', message )
|
||||
HC.pubsub.pub( 'message', job_key )
|
||||
|
||||
info = self._c.execute( 'SELECT hash_id, mime FROM files_info WHERE service_id = ?;', ( self._local_file_service_id, ) ).fetchall()
|
||||
|
||||
|
@ -1468,10 +1468,8 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
if i % 100 == 0:
|
||||
|
||||
message.SetInfo( 'range', len( info ) )
|
||||
message.SetInfo( 'value', i )
|
||||
message.SetInfo( 'text', prefix_string + HC.ConvertIntToPrettyString( i ) + '/' + HC.ConvertIntToPrettyString( len( info ) ) )
|
||||
message.SetInfo( 'mode', 'gauge' )
|
||||
job_key.SetVariable( 'popup_message_text_1', prefix_string + HC.ConvertIntToPrettyString( i ) + '/' + HC.ConvertIntToPrettyString( len( info ) ) )
|
||||
job_key.SetVariable( 'popup_message_gauge_1', ( i, len( info ) ) )
|
||||
|
||||
|
||||
hash = self._GetHash( hash_id )
|
||||
|
@ -1492,12 +1490,17 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
|
||||
|
||||
message.SetInfo( 'text', prefix_string + 'deleting the incorrect records' )
|
||||
message.SetInfo( 'mode', 'text' )
|
||||
job_key.DeleteVariable( 'popup_message_gauge_1' )
|
||||
job_key.SetVariable( 'popup_message_text_1', prefix_string + 'deleting the incorrect records' )
|
||||
|
||||
self._DeleteFiles( self._local_file_service_id, deletee_hash_ids )
|
||||
|
||||
message.SetInfo( 'text', prefix_string + 'done! ' + HC.ConvertIntToPrettyString( len( deletee_hash_ids ) ) + ' files deleted!' )
|
||||
text = prefix_string + 'done! '
|
||||
|
||||
if len( deletee_hash_ids ) == 0: text += 'all files ok!'
|
||||
else: text += HC.ConvertIntToPrettyString( len( deletee_hash_ids ) ) + ' files deleted!'
|
||||
|
||||
job_key.SetVariable( 'popup_message_text_1', text )
|
||||
|
||||
|
||||
def _DeleteFiles( self, service_id, hash_ids ):
|
||||
|
@ -1643,7 +1646,12 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
self.pub_service_updates_after_commit( { service_key : [ HC.ServiceUpdate( HC.SERVICE_UPDATE_DELETE_PENDING ) ] } )
|
||||
|
||||
|
||||
def _DeleteServiceInfo( self ): self._c.execute( 'DELETE FROM service_info;' )
|
||||
def _DeleteServiceInfo( self ):
|
||||
|
||||
self._c.execute( 'DELETE FROM service_info;' )
|
||||
|
||||
self.pub_after_commit( 'notify_new_pending' )
|
||||
|
||||
|
||||
def _DeleteYAMLDump( self, dump_type, dump_name = None ):
|
||||
|
||||
|
@ -1675,9 +1683,9 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, prefix_string + 'preparing', job_key )
|
||||
job_key.SetVariable( 'popup_message_text_1', prefix_string + 'preparing' )
|
||||
|
||||
HC.pubsub.pub( 'message', message )
|
||||
HC.pubsub.pub( 'message', job_key )
|
||||
|
||||
service_id = self._GetServiceId( service_key )
|
||||
|
||||
|
@ -1698,10 +1706,8 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
if i % 1000 == 0:
|
||||
|
||||
message.SetInfo( 'range', len( hash_ids ) )
|
||||
message.SetInfo( 'value', i )
|
||||
message.SetInfo( 'text', prefix_string + HC.ConvertIntToPrettyString( i ) + '/' + HC.ConvertIntToPrettyString( len( hash_ids ) ) )
|
||||
message.SetInfo( 'mode', 'gauge' )
|
||||
job_key.SetVariable( 'popup_message_text_1', prefix_string + HC.ConvertIntToPrettyString( i ) + '/' + HC.ConvertIntToPrettyString( len( hash_ids ) ) )
|
||||
job_key.SetVariable( 'popup_message_gauge_1', ( i, len( hash_ids ) ) )
|
||||
|
||||
|
||||
if hash_type == HydrusTagArchive.HASH_TYPE_SHA256: archive_hash = self._GetHash( hash_id )
|
||||
|
@ -1723,12 +1729,12 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
hta.AddMappings( archive_hash, tags )
|
||||
|
||||
|
||||
message.SetInfo( 'text', prefix_string + 'commiting the change and vacuuming the archive' )
|
||||
message.SetInfo( 'mode', 'text' )
|
||||
job_key.DeleteVariable( 'popup_message_gauge_1' )
|
||||
job_key.SetVariable( 'popup_message_text_1', prefix_string + 'committing the change and vacuuming the archive' )
|
||||
|
||||
hta.CommitBigJob()
|
||||
|
||||
message.SetInfo( 'text', prefix_string + 'done!' )
|
||||
job_key.SetVariable( 'popup_message_text_1', prefix_string + 'done!' )
|
||||
|
||||
|
||||
def _FattenAutocompleteCache( self ):
|
||||
|
@ -1928,6 +1934,8 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
def _GetFileQueryIds( self, search_context ):
|
||||
|
||||
HC.app.ResetIdleTimer()
|
||||
|
||||
system_predicates = search_context.GetSystemPredicates()
|
||||
|
||||
file_service_key = search_context.GetFileServiceKey()
|
||||
|
@ -2714,21 +2722,21 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
pending = [ ( ( self._GetNamespaceTag( old_namespace_id, old_tag_id ), self._GetNamespaceTag( new_namespace_id, new_tag_id ) ), self._GetReason( reason_id ) ) for ( old_namespace_id, old_tag_id, new_namespace_id, new_tag_id, reason_id ) in self._c.execute( 'SELECT old_namespace_id, old_tag_id, new_namespace_id, new_tag_id, reason_id FROM tag_sibling_petitions WHERE service_id = ? AND status = ?;', ( service_id, HC.PENDING ) ).fetchall() ]
|
||||
|
||||
content_data[ HC.CONTENT_DATA_TYPE_TAG_SIBLINGS ][ HC.CONTENT_UPDATE_PENDING ] = pending
|
||||
if len( pending ) > 0: content_data[ HC.CONTENT_DATA_TYPE_TAG_SIBLINGS ][ HC.CONTENT_UPDATE_PENDING ] = pending
|
||||
|
||||
petitioned = [ ( ( self._GetNamespaceTag( old_namespace_id, old_tag_id ), self._GetNamespaceTag( new_namespace_id, new_tag_id ) ), self._GetReason( reason_id ) ) for ( old_namespace_id, old_tag_id, new_namespace_id, new_tag_id, reason_id ) in self._c.execute( 'SELECT old_namespace_id, old_tag_id, new_namespace_id, new_tag_id, reason_id FROM tag_sibling_petitions WHERE service_id = ? AND status = ?;', ( service_id, HC.PETITIONED ) ).fetchall() ]
|
||||
|
||||
content_data[ HC.CONTENT_DATA_TYPE_TAG_SIBLINGS ][ HC.CONTENT_UPDATE_PETITION ] = petitioned
|
||||
if len( petitioned ) > 0: content_data[ HC.CONTENT_DATA_TYPE_TAG_SIBLINGS ][ HC.CONTENT_UPDATE_PETITION ] = petitioned
|
||||
|
||||
# tag parents
|
||||
|
||||
pending = [ ( ( self._GetNamespaceTag( child_namespace_id, child_tag_id ), self._GetNamespaceTag( parent_namespace_id, parent_tag_id ) ), self._GetReason( reason_id ) ) for ( child_namespace_id, child_tag_id, parent_namespace_id, parent_tag_id, reason_id ) in self._c.execute( 'SELECT child_namespace_id, child_tag_id, parent_namespace_id, parent_tag_id, reason_id FROM tag_parent_petitions WHERE service_id = ? AND status = ?;', ( service_id, HC.PENDING ) ).fetchall() ]
|
||||
|
||||
content_data[ HC.CONTENT_DATA_TYPE_TAG_PARENTS ][ HC.CONTENT_UPDATE_PENDING ] = pending
|
||||
if len( pending ) > 0: content_data[ HC.CONTENT_DATA_TYPE_TAG_PARENTS ][ HC.CONTENT_UPDATE_PENDING ] = pending
|
||||
|
||||
petitioned = [ ( ( self._GetNamespaceTag( child_namespace_id, child_tag_id ), self._GetNamespaceTag( parent_namespace_id, parent_tag_id ) ), self._GetReason( reason_id ) ) for ( child_namespace_id, child_tag_id, parent_namespace_id, parent_tag_id, reason_id ) in self._c.execute( 'SELECT child_namespace_id, child_tag_id, parent_namespace_id, parent_tag_id, reason_id FROM tag_parent_petitions WHERE service_id = ? AND status = ?;', ( service_id, HC.PETITIONED ) ).fetchall() ]
|
||||
|
||||
content_data[ HC.CONTENT_DATA_TYPE_TAG_PARENTS ][ HC.CONTENT_UPDATE_PETITION ] = petitioned
|
||||
if len( petitioned ) > 0: content_data[ HC.CONTENT_DATA_TYPE_TAG_PARENTS ][ HC.CONTENT_UPDATE_PETITION ] = petitioned
|
||||
|
||||
if len( content_data ) > 0:
|
||||
|
||||
|
@ -3865,7 +3873,11 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
text = name + ' at ' + time.ctime( timestamp ) + ':' + os.linesep * 2 + post
|
||||
|
||||
self.pub_after_commit( 'message', HC.Message( HC.MESSAGE_TYPE_TEXT, { 'text' : text } ) )
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
job_key.SetVariable( 'popup_message_text_1', text )
|
||||
|
||||
self.pub_after_commit( 'message', job_key )
|
||||
|
||||
|
||||
|
||||
|
@ -4023,7 +4035,7 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
|
||||
|
||||
def _SyncFileToTagArchive( self, hash_id, archive_name, namespaces, service_key ):
|
||||
def _SyncFileToTagArchive( self, hash_id, archive_name, namespaces, service_key, pub_immediate = False ):
|
||||
|
||||
hta = self._tag_archives[ archive_name ]
|
||||
|
||||
|
@ -4056,7 +4068,7 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
service_keys_to_content_updates = { service_key : content_updates }
|
||||
|
||||
self._ProcessContentUpdates( service_keys_to_content_updates, pub_immediate = True )
|
||||
self._ProcessContentUpdates( service_keys_to_content_updates, pub_immediate = pub_immediate )
|
||||
|
||||
|
||||
|
||||
|
@ -4066,28 +4078,26 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, prefix_string + 'preparing', job_key )
|
||||
job_key.SetVariable( 'popup_message_text_1', prefix_string + 'preparing' )
|
||||
|
||||
HC.pubsub.pub( 'message', message )
|
||||
HC.pubsub.pub( 'message', job_key )
|
||||
|
||||
hash_ids = [ hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM files_info WHERE service_id = ?;', ( self._local_file_service_id, ) ) ]
|
||||
|
||||
for ( i, hash_id ) in enumerate( hash_ids ):
|
||||
|
||||
try: self._SyncFileToTagArchive( hash_id, archive_name, namespaces, service_key )
|
||||
try: self._SyncFileToTagArchive( hash_id, archive_name, namespaces, service_key, pub_immediate = True )
|
||||
except: pass
|
||||
|
||||
if i % 100 == 0:
|
||||
|
||||
message.SetInfo( 'range', len( hash_ids ) )
|
||||
message.SetInfo( 'value', i )
|
||||
message.SetInfo( 'text', prefix_string + HC.ConvertIntToPrettyString( i ) + '/' + HC.ConvertIntToPrettyString( len( hash_ids ) ) )
|
||||
message.SetInfo( 'mode', 'gauge' )
|
||||
job_key.SetVariable( 'popup_message_text_1', prefix_string + HC.ConvertIntToPrettyString( i ) + '/' + HC.ConvertIntToPrettyString( len( hash_ids ) ) )
|
||||
job_key.SetVariable( 'popup_message_gauge_1', ( i, len( hash_ids ) ) )
|
||||
|
||||
|
||||
|
||||
message.SetInfo( 'text', prefix_string + 'done!' )
|
||||
message.SetInfo( 'mode', 'text' )
|
||||
job_key.DeleteVariable( 'popup_message_gauge_1' )
|
||||
job_key.SetVariable( 'popup_message_text_1', prefix_string + 'done!' )
|
||||
|
||||
self.pub_after_commit( 'notify_new_pending' )
|
||||
|
||||
|
@ -4520,9 +4530,11 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
if message is None:
|
||||
|
||||
message = HC.Message( HC.MESSAGE_TYPE_TEXT, { 'text' : 'updating services: deleting tag data' } )
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
job_key.SetVariable( 'popup_message_text_1', 'updating services: deleting tag data' )
|
||||
|
||||
HC.pubsub.pub( 'message', message )
|
||||
HC.pubsub.pub( 'message', job_key )
|
||||
|
||||
|
||||
|
||||
|
@ -4603,11 +4615,11 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
if recalc_combined_mappings:
|
||||
|
||||
message.SetInfo( 'text', 'updating services: recalculating combined tag data' )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'updating services: recalculating combined tag data' )
|
||||
|
||||
self._RecalcCombinedMappings()
|
||||
|
||||
message.SetInfo( 'text', 'updating services: done!' )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'updating services: done!' )
|
||||
|
||||
|
||||
self.pub_after_commit( 'notify_new_pending' )
|
||||
|
@ -5027,9 +5039,11 @@ class DB( ServiceDB ):
|
|||
|
||||
prefix = 'deleting old resized thumbnails: '
|
||||
|
||||
message = HC.Message( HC.MESSAGE_TYPE_TEXT, { 'text' : prefix + 'initialising' } )
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
HC.pubsub.pub( 'message', message )
|
||||
job_key.SetVariable( 'popup_message_text_1', prefix + 'initialising' )
|
||||
|
||||
HC.pubsub.pub( 'message', job_key )
|
||||
|
||||
thumbnail_paths = ( path for path in CC.IterateAllThumbnailPaths() if path.endswith( '_resized' ) )
|
||||
|
||||
|
@ -5037,12 +5051,12 @@ class DB( ServiceDB ):
|
|||
|
||||
os.remove( path )
|
||||
|
||||
if i % 100 == 0: message.SetInfo( 'text', prefix + 'done ' + HC.ConvertIntToPrettyString( i ) )
|
||||
if i % 100 == 0: job_key.SetVariable( 'popup_message_text_1', prefix + 'done ' + HC.ConvertIntToPrettyString( i ) )
|
||||
|
||||
|
||||
self.pub_after_commit( 'thumbnail_resize' )
|
||||
|
||||
message.SetInfo( 'text', prefix + 'done!' )
|
||||
job_key.SetVariable( 'popup_message_text_1', prefix + 'done!' )
|
||||
|
||||
|
||||
self.pub_after_commit( 'notify_new_options' )
|
||||
|
@ -5773,6 +5787,11 @@ class DB( ServiceDB ):
|
|||
|
||||
self._c.execute( 'REPLACE INTO shutdown_timestamps ( shutdown_type, timestamp ) VALUES ( ?, ? );', ( CC.SHUTDOWN_TIMESTAMP_VACUUM, HC.GetNow() ) )
|
||||
|
||||
self._c.close()
|
||||
self._db.close()
|
||||
|
||||
self._InitDBCursor()
|
||||
|
||||
HC.ShowText( 'Database maintenance: vacuumed successfully.' )
|
||||
|
||||
|
||||
|
@ -6262,7 +6281,12 @@ def DAEMONCheckImportFolders():
|
|||
|
||||
text = HC.u( len( successful_hashes ) ) + ' files imported from ' + folder_path
|
||||
|
||||
HC.pubsub.pub( 'message', HC.Message( HC.MESSAGE_TYPE_FILES, { 'text' : text, 'hashes' : successful_hashes } ) )
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
job_key.SetVariable( 'popup_message_text_1', text )
|
||||
job_key.SetVariable( 'popup_message_files', successful_hashes )
|
||||
|
||||
HC.pubsub.pub( 'message', job_key )
|
||||
|
||||
|
||||
details[ 'last_checked' ] = now
|
||||
|
@ -6975,11 +6999,11 @@ def DAEMONSynchroniseSubscriptions():
|
|||
|
||||
try:
|
||||
|
||||
job_key = HC.JobKey( pausable = True, cancellable = False )
|
||||
job_key = HC.JobKey( pausable = True, cancellable = True )
|
||||
|
||||
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, 'checking ' + name + ' subscription', job_key )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'checking ' + name + ' subscription' )
|
||||
|
||||
HC.pubsub.pub( 'message', message )
|
||||
HC.pubsub.pub( 'message', job_key )
|
||||
|
||||
do_tags = len( advanced_tag_options ) > 0
|
||||
|
||||
|
@ -7045,28 +7069,38 @@ def DAEMONSynchroniseSubscriptions():
|
|||
|
||||
while job_key.IsPaused():
|
||||
|
||||
message.SetInfo( 'text', 'paused' )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'paused' )
|
||||
|
||||
time.sleep( 1 )
|
||||
|
||||
if HC.shutdown: return
|
||||
|
||||
if message.IsClosed(): return
|
||||
if job_key.IsCancelled():
|
||||
|
||||
job_key.SetVariable( 'popup_message_text_1', name + ' check was cancelled' )
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
while HC.options[ 'pause_subs_sync' ]:
|
||||
|
||||
message.SetInfo( 'text', 'subscriptions paused' )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'subscriptions paused' )
|
||||
|
||||
time.sleep( 5 )
|
||||
|
||||
if HC.shutdown: return
|
||||
|
||||
if message.IsClosed(): return
|
||||
if job_key.IsCancelled():
|
||||
|
||||
job_key.SetVariable( 'popup_message_text_1', name + ' check was cancelled' )
|
||||
|
||||
return
|
||||
|
||||
|
||||
if HC.subs_changed:
|
||||
|
||||
message.Close()
|
||||
job_key.SetVariable( 'popup_message_text_1', 'subscriptions were changed during processing; this job was abandoned' )
|
||||
|
||||
HC.pubsub.pub( 'notify_restart_subs_sync_daemon' )
|
||||
|
||||
|
@ -7092,7 +7126,7 @@ def DAEMONSynchroniseSubscriptions():
|
|||
|
||||
all_url_args.extend( fresh_url_args )
|
||||
|
||||
message.SetInfo( 'text', 'found ' + HC.ConvertIntToPrettyString( len( all_url_args ) ) + ' new files for ' + name )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'found ' + HC.ConvertIntToPrettyString( len( all_url_args ) ) + ' new files for ' + name )
|
||||
|
||||
|
||||
|
||||
|
@ -7101,32 +7135,28 @@ def DAEMONSynchroniseSubscriptions():
|
|||
if len( downloaders ) == 0: break
|
||||
|
||||
|
||||
message.SetInfo( 'range', len( all_url_args ) )
|
||||
message.SetInfo( 'value', 0 )
|
||||
message.SetInfo( 'mode', 'gauge' )
|
||||
|
||||
all_url_args.reverse() # to do oldest first, which means we can save incrementally
|
||||
|
||||
i = 1
|
||||
|
||||
num_new = 0
|
||||
|
||||
successful_hashes = set()
|
||||
|
||||
for url_args in all_url_args:
|
||||
for ( i, url_args ) in enumerate( all_url_args ):
|
||||
|
||||
while HC.options[ 'pause_subs_sync' ]:
|
||||
|
||||
message.SetInfo( 'text', 'subscriptions paused' )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'subscriptions paused' )
|
||||
|
||||
time.sleep( 5 )
|
||||
|
||||
if HC.shutdown: return
|
||||
|
||||
if job_key.IsCancelled(): return
|
||||
|
||||
if HC.subs_changed:
|
||||
|
||||
message.Close()
|
||||
|
||||
job_key.SetVariable( 'popup_message_text_1', 'subscriptions were changed during processing; this job was abandoned' )
|
||||
|
||||
HC.pubsub.pub( 'notify_restart_subs_sync_daemon' )
|
||||
|
||||
return
|
||||
|
@ -7143,8 +7173,8 @@ def DAEMONSynchroniseSubscriptions():
|
|||
|
||||
x_out_of_y = HC.ConvertIntToPrettyString( i ) + '/' + HC.ConvertIntToPrettyString( len( all_url_args ) )
|
||||
|
||||
message.SetInfo( 'value', i )
|
||||
message.SetInfo( 'text', name + ': ' + x_out_of_y + ' : checking url status' )
|
||||
job_key.SetVariable( 'popup_message_text_1', name + ': ' + x_out_of_y + ' : checking url status' )
|
||||
job_key.SetVariable( 'popup_message_gauge_1', ( i, len( all_url_args ) ) )
|
||||
|
||||
( status, hash ) = HC.app.ReadDaemon( 'url_status', url )
|
||||
|
||||
|
@ -7156,7 +7186,7 @@ def DAEMONSynchroniseSubscriptions():
|
|||
|
||||
try:
|
||||
|
||||
message.SetInfo( 'text', name + ': ' + x_out_of_y + ' : found file in db, fetching tags' )
|
||||
job_key.SetVariable( 'popup_message_text_1', name + ': ' + x_out_of_y + ' : found file in db, fetching tags' )
|
||||
|
||||
tags = downloader.GetTags( *url_args )
|
||||
|
||||
|
@ -7173,7 +7203,7 @@ def DAEMONSynchroniseSubscriptions():
|
|||
|
||||
num_new += 1
|
||||
|
||||
message.SetInfo( 'text', name + ': ' + x_out_of_y + ' : downloading file' )
|
||||
job_key.SetVariable( 'popup_message_text_1', name + ': ' + x_out_of_y + ' : downloading file' )
|
||||
|
||||
if do_tags: ( temp_path, tags ) = downloader.GetFileAndTags( *url_args )
|
||||
else:
|
||||
|
@ -7185,7 +7215,7 @@ def DAEMONSynchroniseSubscriptions():
|
|||
|
||||
service_keys_to_tags = HydrusDownloading.ConvertTagsToServiceKeysToTags( tags, advanced_tag_options )
|
||||
|
||||
message.SetInfo( 'text', name + ': ' + x_out_of_y + ' : importing file' )
|
||||
job_key.SetVariable( 'popup_message_text_1', name + ': ' + x_out_of_y + ' : importing file' )
|
||||
|
||||
( status, hash ) = HC.app.WriteSynchronous( 'import_file', temp_path, advanced_import_options = advanced_import_options, service_keys_to_tags = service_keys_to_tags, url = url )
|
||||
|
||||
|
@ -7202,8 +7232,6 @@ def DAEMONSynchroniseSubscriptions():
|
|||
HC.ShowException( e )
|
||||
|
||||
|
||||
i += 1
|
||||
|
||||
if i % 20 == 0:
|
||||
|
||||
info[ 'site_type' ] = site_type
|
||||
|
@ -7223,24 +7251,25 @@ def DAEMONSynchroniseSubscriptions():
|
|||
HC.app.WaitUntilGoodTimeToUseGUIThread()
|
||||
|
||||
|
||||
job_key.DeleteVariable( 'popup_message_gauge_1' )
|
||||
|
||||
if len( successful_hashes ) > 0:
|
||||
|
||||
text = HC.u( len( successful_hashes ) ) + ' files imported from ' + name
|
||||
job_key.SetVariable( 'popup_message_text_1', HC.u( len( successful_hashes ) ) + ' files imported from ' + name )
|
||||
job_key.SetVariable( 'popup_message_files', successful_hashes )
|
||||
|
||||
message.SetInfo( 'text', text )
|
||||
message.SetInfo( 'hashes', successful_hashes )
|
||||
message.SetInfo( 'mode', 'files' )
|
||||
else:
|
||||
|
||||
job_key.SetPausable( False )
|
||||
job_key.SetVariable( 'popup_message_text_1', name + 'subscription checked, but no new files' )
|
||||
|
||||
else: message.Close()
|
||||
|
||||
job_key.SetPausable( False )
|
||||
job_key.SetCancellable( False )
|
||||
|
||||
last_checked = now
|
||||
|
||||
except Exception as e:
|
||||
|
||||
if 'message' in locals(): message.Close()
|
||||
|
||||
last_checked = now + HC.UPDATE_DURATION
|
||||
|
||||
HC.ShowText( 'Problem with ' + name + ':' )
|
||||
|
|
|
@ -146,9 +146,9 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
|||
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, 'gathering pending and petitioned', job_key )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'gathering pending and petitioned' )
|
||||
|
||||
HC.pubsub.pub( 'message', message )
|
||||
HC.pubsub.pub( 'message', job_key )
|
||||
|
||||
result = HC.app.Read( 'pending', service_key )
|
||||
|
||||
|
@ -163,30 +163,17 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
|||
|
||||
media_results = HC.app.Read( 'media_results', HC.LOCAL_FILE_SERVICE_KEY, upload_hashes )
|
||||
|
||||
num_uploads = len( media_results )
|
||||
|
||||
num_other_messages = 1
|
||||
|
||||
if not update.IsEmpty(): num_other_messages += 1
|
||||
|
||||
gauge_range = num_uploads + num_other_messages
|
||||
|
||||
i = 1
|
||||
|
||||
message.SetInfo( 'range', gauge_range )
|
||||
message.SetInfo( 'value', i )
|
||||
message.SetInfo( 'text', 'connecting to repository' )
|
||||
message.SetInfo( 'mode', 'cancelable gauge' )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'connecting to repository' )
|
||||
|
||||
good_hashes = []
|
||||
|
||||
error_messages = set()
|
||||
|
||||
for media_result in media_results:
|
||||
for ( i, media_result ) in enumerate( media_results ):
|
||||
|
||||
if job_key.IsCancelled():
|
||||
|
||||
message.Close()
|
||||
job_key.SetVariable( 'popup_message_text_1', 'upload cancelled' )
|
||||
|
||||
return
|
||||
|
||||
|
@ -196,8 +183,8 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
|||
hash = media_result.GetHash()
|
||||
mime = media_result.GetMime()
|
||||
|
||||
message.SetInfo( 'value', i )
|
||||
message.SetInfo( 'text', 'Uploading file ' + HC.ConvertIntToPrettyString( i ) + ' of ' + HC.ConvertIntToPrettyString( num_uploads ) )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'Uploading file ' + HC.ConvertIntToPrettyString( i + 1 ) + ' of ' + HC.ConvertIntToPrettyString( len( media_results ) ) )
|
||||
job_key.SetVariable( 'popup_message_gauge_1', ( i, len( media_results ) ) )
|
||||
|
||||
try:
|
||||
|
||||
|
@ -233,8 +220,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
|||
|
||||
i += 1
|
||||
|
||||
message.SetInfo( 'value', i )
|
||||
message.SetInfo( 'text', 'uploading petitions' )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'uploading petitions' )
|
||||
|
||||
service.Request( HC.POST, 'update', { 'update' : update } )
|
||||
|
||||
|
@ -247,32 +233,19 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
|||
|
||||
updates = result
|
||||
|
||||
num_updates = len( updates )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'connecting to repository' )
|
||||
|
||||
num_other_messages = 1
|
||||
|
||||
gauge_range = num_updates + num_other_messages + 1
|
||||
|
||||
i = 1
|
||||
|
||||
message.SetInfo( 'range', gauge_range )
|
||||
message.SetInfo( 'value', i )
|
||||
message.SetInfo( 'text', 'connecting to repository' )
|
||||
message.SetInfo( 'mode', 'cancelable gauge' )
|
||||
|
||||
for update in updates:
|
||||
for ( i, update ) in enumerate( updates ):
|
||||
|
||||
if job_key.IsCancelled():
|
||||
|
||||
message.Close()
|
||||
job_key.SetVariable( 'popup_message_text_1', 'upload cancelled' )
|
||||
|
||||
return
|
||||
|
||||
|
||||
i += 1
|
||||
|
||||
message.SetInfo( 'value', i )
|
||||
message.SetInfo( 'text', 'posting update' )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'posting update: ' + HC.ConvertIntToPrettyString( i + 1 ) + '/' + HC.ConvertIntToPrettyString( len( updates ) ) )
|
||||
job_key.SetVariable( 'popup_message_gauge_1', ( i, len( updates ) ) )
|
||||
|
||||
service.Request( HC.POST, 'update', { 'update' : update } )
|
||||
|
||||
|
@ -285,11 +258,12 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
|||
HC.app.WaitUntilGoodTimeToUseGUIThread()
|
||||
|
||||
|
||||
|
||||
|
||||
except Exception as e: HC.ShowException( e )
|
||||
|
||||
message.SetInfo( 'text', 'upload done' )
|
||||
message.SetInfo( 'mode', 'text' )
|
||||
job_key.DeleteVariable( 'popup_message_gauge_1' )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'upload done!' )
|
||||
|
||||
HC.pubsub.pub( 'notify_new_pending' )
|
||||
|
||||
|
@ -1474,9 +1448,11 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
|||
|
||||
prefix = 'regenerating thumbnails: '
|
||||
|
||||
message = HC.Message( HC.MESSAGE_TYPE_TEXT, { 'text' : prefix + 'creating directories' } )
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
HC.pubsub.pub( 'message', message )
|
||||
job_key.SetVariable( 'popup_message_text_1', prefix + 'creating directories' )
|
||||
|
||||
HC.pubsub.pub( 'message', job_key )
|
||||
|
||||
if not os.path.exists( HC.CLIENT_THUMBNAILS_DIR ): os.mkdir( HC.CLIENT_THUMBNAILS_DIR )
|
||||
|
||||
|
@ -1499,7 +1475,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
|||
|
||||
if mime in HC.MIMES_WITH_THUMBNAILS:
|
||||
|
||||
if i % 100 == 0: message.SetInfo( 'text', prefix + HC.ConvertIntToPrettyString( i ) + ' done' )
|
||||
if i % 100 == 0: job_key.SetVariable( 'popup_message_text_1', prefix + HC.ConvertIntToPrettyString( i ) + ' done' )
|
||||
|
||||
( base, filename ) = os.path.split( path )
|
||||
|
||||
|
@ -1531,8 +1507,8 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
|||
|
||||
|
||||
|
||||
if num_broken > 0: message.SetInfo( 'text', prefix + 'done! ' + HC.ConvertIntToPrettyString( num_broken ) + ' files caused errors, which have been written to the log.' )
|
||||
else: message.SetInfo( 'text', prefix + 'done!' )
|
||||
if num_broken > 0: job_key.SetVariable( 'popup_message_text_1', prefix + 'done! ' + HC.ConvertIntToPrettyString( num_broken ) + ' files caused errors, which have been written to the log.' )
|
||||
else: job_key.SetVariable( 'popup_message_text_1', prefix + 'done!' )
|
||||
|
||||
|
||||
HydrusThreading.CallToThread( THREADRegenerateThumbnails )
|
||||
|
@ -1646,11 +1622,9 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, url_string, job_key )
|
||||
HC.pubsub.pub( 'message', job_key )
|
||||
|
||||
HC.pubsub.pub( 'message', message )
|
||||
|
||||
HydrusThreading.CallToThread( HydrusDownloading.THREADDownloadURL, message, url, url_string )
|
||||
HydrusThreading.CallToThread( HydrusDownloading.THREADDownloadURL, job_key, url, url_string )
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -219,6 +219,9 @@ class Animation( wx.Window ):
|
|||
if self._video_container.HasFrame( self._current_frame_index ): self._DrawFrame()
|
||||
else: self._DrawWhite()
|
||||
|
||||
self._timer_video.Start( 0, wx.TIMER_ONE_SHOT )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -228,15 +231,26 @@ class Animation( wx.Window ):
|
|||
|
||||
self._current_frame_index = frame_index
|
||||
|
||||
self._video_container.SetFramePosition( self._current_frame_index )
|
||||
|
||||
self._current_frame_drawn_at = 0.0
|
||||
self._current_frame_drawn = False
|
||||
|
||||
self._video_container.SetFramePosition( self._current_frame_index )
|
||||
if self._video_container.HasFrame( self._current_frame_index ): self._DrawFrame()
|
||||
else: self._DrawWhite()
|
||||
|
||||
self._timer_video.Start( 0, wx.TIMER_ONE_SHOT )
|
||||
|
||||
|
||||
self._paused = True
|
||||
|
||||
|
||||
def Play( self ): self._paused = False
|
||||
def Play( self ):
|
||||
|
||||
self._paused = False
|
||||
|
||||
self._timer_video.Start( 0, wx.TIMER_ONE_SHOT )
|
||||
|
||||
|
||||
def SetAnimationBar( self, animation_bar ): self._animation_bar = animation_bar
|
||||
|
||||
|
@ -266,11 +280,14 @@ class Animation( wx.Window ):
|
|||
|
||||
if not self._current_frame_drawn and self._video_container.HasFrame( self._current_frame_index ): self._DrawFrame()
|
||||
|
||||
ms_since_current_frame_drawn = int( 1000.0 * ( HC.GetNowPrecise() - self._current_frame_drawn_at ) )
|
||||
|
||||
ms_until_next_frame = max( MIN_TIMER_TIME, self._video_container.GetDuration( self._current_frame_index ) - ms_since_current_frame_drawn )
|
||||
|
||||
self._timer_video.Start( ms_until_next_frame, wx.TIMER_ONE_SHOT )
|
||||
if not self._current_frame_drawn or not self._paused:
|
||||
|
||||
ms_since_current_frame_drawn = int( 1000.0 * ( HC.GetNowPrecise() - self._current_frame_drawn_at ) )
|
||||
|
||||
ms_until_next_frame = max( MIN_TIMER_TIME, self._video_container.GetDuration( self._current_frame_index ) - ms_since_current_frame_drawn )
|
||||
|
||||
self._timer_video.Start( ms_until_next_frame, wx.TIMER_ONE_SHOT )
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -316,10 +333,24 @@ class AnimationBar( wx.Window ):
|
|||
|
||||
dc.DrawRectangle( 0, 0, my_width, ANIMATED_SCANBAR_HEIGHT )
|
||||
|
||||
#
|
||||
|
||||
dc.SetBrush( wx.Brush( wx.SystemSettings.GetColour( wx.SYS_COLOUR_SCROLLBAR ) ) )
|
||||
|
||||
dc.DrawRectangle( int( float( my_width - ANIMATED_SCANBAR_CARET_WIDTH ) * float( self._current_frame_index ) / float( self._num_frames - 1 ) ), 0, ANIMATED_SCANBAR_CARET_WIDTH, ANIMATED_SCANBAR_HEIGHT )
|
||||
|
||||
#
|
||||
|
||||
dc.SetFont( wx.SystemSettings.GetFont( wx.SYS_DEFAULT_GUI_FONT ) )
|
||||
|
||||
dc.SetTextForeground( wx.BLACK )
|
||||
|
||||
s = HC.ConvertIntToPrettyString( self._current_frame_index + 1 ) + '/' + HC.ConvertIntToPrettyString( self._num_frames )
|
||||
|
||||
( x, y ) = dc.GetTextExtent( s )
|
||||
|
||||
dc.DrawText( s, my_width - x - 3, 3 )
|
||||
|
||||
|
||||
def EventMouse( self, event ):
|
||||
|
||||
|
@ -4031,19 +4062,20 @@ class StaticImage( wx.Window ):
|
|||
|
||||
( frame_width, frame_height ) = hydrus_bitmap.GetSize()
|
||||
|
||||
x_scale = my_width / float( frame_width )
|
||||
y_scale = my_height / float( frame_height )
|
||||
|
||||
dc.SetUserScale( x_scale, y_scale )
|
||||
|
||||
wx_bitmap = hydrus_bitmap.GetWxBitmap()
|
||||
if frame_height != my_height:
|
||||
|
||||
image = hydrus_bitmap.GetWxImage()
|
||||
|
||||
image = image.Scale( my_width, my_height, wx.IMAGE_QUALITY_HIGH )
|
||||
|
||||
wx_bitmap = wx.BitmapFromImage( image )
|
||||
|
||||
else: wx_bitmap = hydrus_bitmap.GetWxBitmap()
|
||||
|
||||
dc.DrawBitmap( wx_bitmap, 0, 0 )
|
||||
|
||||
wx.CallAfter( wx_bitmap.Destroy )
|
||||
|
||||
dc.SetUserScale( 1.0, 1.0 )
|
||||
|
||||
self._timer_render_wait.Stop()
|
||||
|
||||
|
||||
|
|
|
@ -2424,6 +2424,327 @@ class PopupDismissAll( PopupWindow ):
|
|||
|
||||
def SetNumMessages( self, num_messages_pending ): self._text.SetLabel( HC.ConvertIntToPrettyString( num_messages_pending ) + ' more messages' )
|
||||
|
||||
class PopupMessageNew( PopupWindow ):
|
||||
|
||||
def __init__( self, parent, job_key ):
|
||||
|
||||
PopupWindow.__init__( self, parent )
|
||||
|
||||
self._job_key = job_key
|
||||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
self._title = FitResistantStaticText( self, style = wx.ALIGN_CENTER )
|
||||
self._title.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._title.Hide()
|
||||
|
||||
self._text_1 = FitResistantStaticText( self )
|
||||
self._text_1.Wrap( 380 )
|
||||
self._text_1.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._text_1.Hide()
|
||||
|
||||
self._gauge_1 = Gauge( self, size = ( 380, -1 ) )
|
||||
self._gauge_1.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._gauge_1.Hide()
|
||||
|
||||
self._text_2 = FitResistantStaticText( self )
|
||||
self._text_2.Wrap( 380 )
|
||||
self._text_2.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._text_2.Hide()
|
||||
|
||||
self._gauge_2 = Gauge( self, size = ( 380, -1 ) )
|
||||
self._gauge_2.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._gauge_2.Hide()
|
||||
|
||||
self._show_files_button = wx.Button( self )
|
||||
self._show_files_button.Bind( wx.EVT_BUTTON, self.EventShowFilesButton )
|
||||
self._show_files_button.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._show_files_button.Hide()
|
||||
|
||||
self._error_text = FitResistantStaticText( self )
|
||||
self._error_text.Wrap( 380 )
|
||||
self._error_text.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._error_text.Hide()
|
||||
|
||||
self._show_tb_button = wx.Button( self, label = 'show traceback' )
|
||||
self._show_tb_button.Bind( wx.EVT_BUTTON, self.EventShowTBButton )
|
||||
self._show_tb_button.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._show_tb_button.Hide()
|
||||
|
||||
self._tb_text = FitResistantStaticText( self )
|
||||
self._tb_text.Wrap( 380 )
|
||||
self._tb_text.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._tb_text.Hide()
|
||||
|
||||
self._show_caller_tb_button = wx.Button( self, label = 'show caller traceback' )
|
||||
self._show_caller_tb_button.Bind( wx.EVT_BUTTON, self.EventShowCallerTBButton )
|
||||
self._show_caller_tb_button.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._show_caller_tb_button.Hide()
|
||||
|
||||
self._caller_tb_text = FitResistantStaticText( self )
|
||||
self._caller_tb_text.Wrap( 380 )
|
||||
self._caller_tb_text.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._caller_tb_text.Hide()
|
||||
|
||||
self._show_db_tb_button = wx.Button( self, label = 'show db traceback' )
|
||||
self._show_db_tb_button.Bind( wx.EVT_BUTTON, self.EventShowDBTBButton )
|
||||
self._show_db_tb_button.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._show_db_tb_button.Hide()
|
||||
|
||||
self._db_tb_text = FitResistantStaticText( self )
|
||||
self._db_tb_text.Wrap( 380 )
|
||||
self._db_tb_text.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._db_tb_text.Hide()
|
||||
|
||||
self._copy_tb_button = wx.Button( self, label = 'copy traceback information' )
|
||||
self._copy_tb_button.Bind( wx.EVT_BUTTON, self.EventCopyTBButton )
|
||||
self._copy_tb_button.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._copy_tb_button.Hide()
|
||||
|
||||
self._pause_button = wx.Button( self, label = 'pause' )
|
||||
self._pause_button.Bind( wx.EVT_BUTTON, self.EventPauseButton )
|
||||
self._pause_button.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._pause_button.Hide()
|
||||
|
||||
self._cancel_button = wx.Button( self, label = 'cancel' )
|
||||
self._cancel_button.Bind( wx.EVT_BUTTON, self.EventCancelButton )
|
||||
self._cancel_button.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||
self._cancel_button.Hide()
|
||||
|
||||
hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
hbox.AddF( self._pause_button, FLAGS_MIXED )
|
||||
hbox.AddF( self._cancel_button, FLAGS_MIXED )
|
||||
|
||||
vbox.AddF( self._title, FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._text_1, FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._gauge_1, FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._text_2, FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._gauge_2, FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._show_files_button, FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._error_text, FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._show_tb_button, FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._tb_text, FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._show_caller_tb_button, FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._caller_tb_text, FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._show_db_tb_button, FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._db_tb_text, FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._copy_tb_button, FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( hbox, FLAGS_BUTTON_SIZER )
|
||||
|
||||
self.SetSizer( vbox )
|
||||
|
||||
|
||||
def _ProcessText( self, text ):
|
||||
|
||||
if len( text ) > TEXT_CUTOFF:
|
||||
|
||||
new_text = 'Some text arrived that is too long to display here. Here is the start of it (the rest is printed to the log):'
|
||||
|
||||
new_text += os.linesep * 2
|
||||
|
||||
new_text += text[:TEXT_CUTOFF]
|
||||
|
||||
text = new_text
|
||||
|
||||
|
||||
return text
|
||||
|
||||
|
||||
def Dismiss( self ):
|
||||
|
||||
if self._job_key.IsCancellable():
|
||||
|
||||
import ClientGUIDialogs
|
||||
|
||||
message = 'Do you want to continue in the background, or stop right now?'
|
||||
|
||||
with ClientGUIDialogs.DialogYesNo( self, message, title = 'Choose if the job continues in the background.', yes_label = 'continue', no_label = 'stop' ) as dlg:
|
||||
|
||||
result = dlg.ShowModal()
|
||||
|
||||
if result == wx.ID_CANCEL: return
|
||||
elif result == wx.ID_NO: self._job_key.Cancel()
|
||||
|
||||
|
||||
|
||||
if self._job_key.IsPaused(): self._job_key.Cancel()
|
||||
|
||||
PopupWindow.Dismiss( self )
|
||||
|
||||
|
||||
def EventCancelButton( self, event ):
|
||||
|
||||
self._job_key.Cancel()
|
||||
|
||||
self._cancel_button.Disable()
|
||||
|
||||
|
||||
def EventCopyTBButton( self, event ): HC.pubsub.pub( 'clipboard', 'text', self._tb_copy_text )
|
||||
|
||||
def EventPauseButton( self, event ):
|
||||
|
||||
if self._job_key.IsPaused():
|
||||
|
||||
self._job_key.Resume()
|
||||
|
||||
self._pause_button.SetLabel( 'pause' )
|
||||
|
||||
else:
|
||||
|
||||
self._job_key.Pause()
|
||||
|
||||
self._pause_button.SetLabel( 'resume' )
|
||||
|
||||
|
||||
|
||||
def EventShowCallerTBButton( self, event ):
|
||||
|
||||
if self._caller_tb_text.IsShown():
|
||||
|
||||
self._show_caller_tb_button.SetLabel( 'show caller traceback' )
|
||||
|
||||
self._caller_tb_text.Hide()
|
||||
|
||||
else:
|
||||
|
||||
self._show_caller_tb_button.SetLabel( 'hide caller traceback' )
|
||||
|
||||
self._caller_tb_text.Show()
|
||||
|
||||
|
||||
self.GetParent().MakeSureEverythingFits()
|
||||
|
||||
|
||||
def EventShowDBTBButton( self, event ):
|
||||
|
||||
if self._db_tb_text.IsShown():
|
||||
|
||||
self._show_db_tb_button.SetLabel( 'show db traceback' )
|
||||
|
||||
self._db_tb_text.Hide()
|
||||
|
||||
else:
|
||||
|
||||
self._show_db_tb_button.SetLabel( 'hide db traceback' )
|
||||
|
||||
self._db_tb_text.Show()
|
||||
|
||||
|
||||
self.GetParent().MakeSureEverythingFits()
|
||||
|
||||
|
||||
def EventShowFilesButton( self, event ):
|
||||
|
||||
hashes = self._job_key.GetVariable( 'popup_message_files' )
|
||||
|
||||
media_results = HC.app.Read( 'media_results', HC.LOCAL_FILE_SERVICE_KEY, hashes )
|
||||
|
||||
HC.pubsub.pub( 'new_page_query', HC.LOCAL_FILE_SERVICE_KEY, initial_media_results = media_results )
|
||||
|
||||
|
||||
def EventShowTBButton( self, event ):
|
||||
|
||||
if self._tb_text.IsShown():
|
||||
|
||||
self._show_tb_button.SetLabel( 'show traceback' )
|
||||
|
||||
self._tb_text.Hide()
|
||||
|
||||
else:
|
||||
|
||||
self._show_tb_button.SetLabel( 'hide traceback' )
|
||||
|
||||
self._tb_text.Show()
|
||||
|
||||
|
||||
self.GetParent().MakeSureEverythingFits()
|
||||
|
||||
|
||||
def Update( self ):
|
||||
|
||||
if self._job_key.HasVariable( 'popup_message_title' ):
|
||||
|
||||
text = self._job_key.GetVariable( 'popup_message_title' )
|
||||
|
||||
if self._title.GetLabel() != text: self._title.SetLabel( text )
|
||||
|
||||
self._title.Show()
|
||||
|
||||
else: self._title.Hide()
|
||||
|
||||
if self._job_key.HasVariable( 'popup_message_text_1' ):
|
||||
|
||||
text = self._job_key.GetVariable( 'popup_message_text_1' )
|
||||
|
||||
if self._text_1.GetLabel() != text: self._text_1.SetLabel( self._ProcessText( HC.u( text ) ) )
|
||||
|
||||
self._text_1.Show()
|
||||
|
||||
else: self._text_1.Hide()
|
||||
|
||||
if self._job_key.HasVariable( 'popup_message_gauge_1' ):
|
||||
|
||||
( value, range ) = self._job_key.GetVariable( 'popup_message_gauge_1' )
|
||||
|
||||
if range is None or value is None: self._gauge_1.Pulse()
|
||||
else:
|
||||
|
||||
self._gauge_1.SetRange( range )
|
||||
self._gauge_1.SetValue( value )
|
||||
|
||||
|
||||
self._gauge_1.Show()
|
||||
|
||||
else: self._gauge_1.Hide()
|
||||
|
||||
if self._job_key.HasVariable( 'popup_message_text_2' ):
|
||||
|
||||
text = self._job_key.GetVariable( 'popup_message_text_2' )
|
||||
|
||||
if self._text_2.GetLabel() != text: self._text_2.SetLabel( self._ProcessText( HC.u( text ) ) )
|
||||
|
||||
self._text_2.Show()
|
||||
|
||||
else: self._text_2.Hide()
|
||||
|
||||
if self._job_key.HasVariable( 'popup_message_gauge_2' ):
|
||||
|
||||
( value, range ) = self._job_key.GetVariable( 'popup_message_gauge_2' )
|
||||
|
||||
if range is None or value is None: self._gauge_2.Pulse()
|
||||
else:
|
||||
|
||||
self._gauge_2.SetRange( range )
|
||||
self._gauge_2.SetValue( value )
|
||||
|
||||
|
||||
self._gauge_2.Show()
|
||||
|
||||
else: self._gauge_2.Hide()
|
||||
|
||||
if self._job_key.HasVariable( 'popup_message_files' ):
|
||||
|
||||
hashes = self._job_key.GetVariable( 'popup_message_files' )
|
||||
|
||||
text = 'show ' + HC.ConvertIntToPrettyString( len( hashes ) ) + ' files'
|
||||
|
||||
if self._show_files_button.GetLabel() != text: self._show_files_button.SetLabel( text )
|
||||
|
||||
self._show_files_button.Show()
|
||||
|
||||
else: self._show_files_button.Hide()
|
||||
|
||||
#vbox.AddF( self._error_text, FLAGS_EXPAND_PERPENDICULAR )
|
||||
#vbox.AddF( self._show_tb_button, FLAGS_EXPAND_PERPENDICULAR )
|
||||
#vbox.AddF( self._tb_text, FLAGS_EXPAND_PERPENDICULAR )
|
||||
#vbox.AddF( self._show_caller_tb_button, FLAGS_EXPAND_PERPENDICULAR )
|
||||
#vbox.AddF( self._caller_tb_text, FLAGS_EXPAND_PERPENDICULAR )
|
||||
#vbox.AddF( self._show_db_tb_button, FLAGS_EXPAND_PERPENDICULAR )
|
||||
#vbox.AddF( self._db_tb_text, FLAGS_EXPAND_PERPENDICULAR )
|
||||
#vbox.AddF( self._copy_tb_button, FLAGS_EXPAND_PERPENDICULAR )
|
||||
# pause + cancel buttons
|
||||
|
||||
class PopupMessage( PopupWindow ):
|
||||
|
||||
def __init__( self, parent, message ):
|
||||
|
@ -2433,8 +2754,6 @@ class PopupMessage( PopupWindow ):
|
|||
self._message = message
|
||||
|
||||
|
||||
def IsClosed( self ): return self._message.IsClosed()
|
||||
|
||||
def Update( self ): pass
|
||||
|
||||
class PopupMessageDBError( PopupMessage ):
|
||||
|
@ -2681,7 +3000,7 @@ class PopupMessageGauge( PopupMessage ):
|
|||
|
||||
def Dismiss( self ):
|
||||
|
||||
if not self._message.IsClosed() and self._message.GetInfo( 'mode' ) == 'cancelable gauge':
|
||||
if self._message.GetInfo( 'mode' ) == 'cancelable gauge':
|
||||
|
||||
import ClientGUIDialogs
|
||||
|
||||
|
@ -2740,7 +3059,7 @@ class PopupMessageGauge( PopupMessage ):
|
|||
|
||||
mode = self._message.GetInfo( 'mode' )
|
||||
text = self._message.GetInfo( 'text' )[:TEXT_CUTOFF]
|
||||
|
||||
|
||||
if self._job_key.IsPausable() and self._created - HC.GetNow() > 2: self._pause_button.Show()
|
||||
else: self._pause_button.Hide()
|
||||
|
||||
|
@ -2774,7 +3093,7 @@ class PopupMessageGauge( PopupMessage ):
|
|||
|
||||
range = self._message.GetInfo( 'range' )
|
||||
value = self._message.GetInfo( 'value' )
|
||||
|
||||
|
||||
if range is None or value is None: self._gauge.Pulse()
|
||||
else:
|
||||
|
||||
|
@ -2857,7 +3176,6 @@ class PopupMessageManager( wx.Frame ):
|
|||
self._SizeAndPositionAndShow()
|
||||
|
||||
HC.pubsub.sub( self, 'AddMessage', 'message' )
|
||||
# maybe make a ding noise when a new message arrives
|
||||
|
||||
self._old_excepthook = sys.excepthook
|
||||
self._old_show_exception = HC.ShowException
|
||||
|
@ -2901,15 +3219,19 @@ class PopupMessageManager( wx.Frame ):
|
|||
|
||||
def _CreateMessageWindow( self, message ):
|
||||
|
||||
message_type = message.GetType()
|
||||
|
||||
if message_type == HC.MESSAGE_TYPE_TEXT: c = PopupMessageText
|
||||
elif message_type == HC.MESSAGE_TYPE_ERROR: c = PopupMessageError
|
||||
elif message_type == HC.MESSAGE_TYPE_DB_ERROR: c = PopupMessageDBError
|
||||
elif message_type == HC.MESSAGE_TYPE_FILES: c = PopupMessageFiles
|
||||
elif message_type == HC.MESSAGE_TYPE_GAUGE: c = PopupMessageGauge
|
||||
|
||||
window = c( self, message )
|
||||
if type( message ) == HC.JobKey: window = PopupMessageNew( self, message )
|
||||
else:
|
||||
|
||||
message_type = message.GetType()
|
||||
|
||||
if message_type == HC.MESSAGE_TYPE_TEXT: c = PopupMessageText
|
||||
elif message_type == HC.MESSAGE_TYPE_ERROR: c = PopupMessageError
|
||||
elif message_type == HC.MESSAGE_TYPE_DB_ERROR: c = PopupMessageDBError
|
||||
elif message_type == HC.MESSAGE_TYPE_FILES: c = PopupMessageFiles
|
||||
elif message_type == HC.MESSAGE_TYPE_GAUGE: c = PopupMessageGauge
|
||||
|
||||
window = c( self, message )
|
||||
|
||||
|
||||
window.Update()
|
||||
|
||||
|
@ -2918,6 +3240,13 @@ class PopupMessageManager( wx.Frame ):
|
|||
|
||||
def _PrintMessage( self, message ):
|
||||
|
||||
if type( message ) == HC.JobKey:
|
||||
|
||||
# if job_key hasvariable title, then print...
|
||||
|
||||
return
|
||||
|
||||
|
||||
message_type = message.GetType()
|
||||
|
||||
if message_type == HC.MESSAGE_TYPE_TEXT: message_string = HC.u( message.GetInfo( 'text' ) )
|
||||
|
@ -2944,6 +3273,13 @@ class PopupMessageManager( wx.Frame ):
|
|||
|
||||
def _ShouldDisplayMessage( self, message ):
|
||||
|
||||
if type( message ) == HC.JobKey:
|
||||
|
||||
# do the same, but for job_key errors
|
||||
|
||||
return True
|
||||
|
||||
|
||||
message_type = message.GetType()
|
||||
|
||||
if message_type == HC.MESSAGE_TYPE_ERROR:
|
||||
|
@ -3013,12 +3349,7 @@ class PopupMessageManager( wx.Frame ):
|
|||
self._CheckPending()
|
||||
|
||||
|
||||
except:
|
||||
|
||||
traceback.print_stack()
|
||||
|
||||
print( traceback.format_exc() )
|
||||
|
||||
except: print( traceback.format_exc() )
|
||||
|
||||
|
||||
def CleanBeforeDestroy( self ):
|
||||
|
@ -3077,8 +3408,7 @@ class PopupMessageManager( wx.Frame ):
|
|||
|
||||
message_window = sizer_item.GetWindow()
|
||||
|
||||
if message_window.IsClosed(): self.Dismiss( message_window )
|
||||
else: message_window.Update()
|
||||
message_window.Update()
|
||||
|
||||
|
||||
self.MakeSureEverythingFits()
|
||||
|
|
|
@ -117,6 +117,8 @@ class Dialog( wx.Dialog ):
|
|||
|
||||
if position == 'center': wx.CallAfter( self.Center )
|
||||
|
||||
HC.app.ResetIdleTimer()
|
||||
|
||||
|
||||
def EventDialogButton( self, event ): self.EndModal( event.GetId() )
|
||||
|
||||
|
@ -5122,11 +5124,9 @@ class DialogSelectYoutubeURL( Dialog ):
|
|||
|
||||
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||
|
||||
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, url_string, job_key )
|
||||
HydrusThreading.CallToThread( HydrusDownloading.THREADDownloadURL, job_key, url, url_string )
|
||||
|
||||
HydrusThreading.CallToThread( HydrusDownloading.THREADDownloadURL, message, url, url_string )
|
||||
|
||||
HC.pubsub.pub( 'message', message )
|
||||
HC.pubsub.pub( 'message', job_key )
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2787,7 +2787,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._listbook = ClientGUICommon.ListBook( self )
|
||||
|
||||
# files and memory
|
||||
# files and thumbnails
|
||||
|
||||
self._file_page = wx.Panel( self._listbook )
|
||||
self._file_page.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
|
||||
|
@ -2796,40 +2796,51 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._exclude_deleted_files = wx.CheckBox( self._file_page, label = '' )
|
||||
|
||||
self._thumbnail_cache_size = wx.SpinCtrl( self._file_page, min = 10, max = 3000 )
|
||||
self._thumbnail_cache_size.Bind( wx.EVT_SPINCTRL, self.EventThumbnailsUpdate )
|
||||
|
||||
self._estimated_number_thumbnails = wx.StaticText( self._file_page, label = '' )
|
||||
|
||||
self._preview_cache_size = wx.SpinCtrl( self._file_page, min = 20, max = 3000 )
|
||||
self._preview_cache_size.Bind( wx.EVT_SPINCTRL, self.EventPreviewsUpdate )
|
||||
|
||||
self._estimated_number_previews = wx.StaticText( self._file_page, label = '' )
|
||||
|
||||
self._fullscreen_cache_size = wx.SpinCtrl( self._file_page, min = 100, max = 3000 )
|
||||
self._fullscreen_cache_size.Bind( wx.EVT_SPINCTRL, self.EventFullscreensUpdate )
|
||||
|
||||
self._estimated_number_fullscreens = wx.StaticText( self._file_page, label = '' )
|
||||
|
||||
self._thumbnail_width = wx.SpinCtrl( self._file_page, min=20, max=200 )
|
||||
self._thumbnail_width.Bind( wx.EVT_SPINCTRL, self.EventThumbnailsUpdate )
|
||||
|
||||
self._thumbnail_height = wx.SpinCtrl( self._file_page, min=20, max=200 )
|
||||
self._thumbnail_height.Bind( wx.EVT_SPINCTRL, self.EventThumbnailsUpdate )
|
||||
|
||||
self._num_autocomplete_chars = wx.SpinCtrl( self._file_page, min = 1, max = 100 )
|
||||
self._listbook.AddPage( self._file_page, 'files and thumbnails' )
|
||||
|
||||
# maintenance and memory
|
||||
|
||||
self._maintenance_page = wx.Panel( self._listbook )
|
||||
self._maintenance_page.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
|
||||
|
||||
self._thumbnail_cache_size = wx.SpinCtrl( self._maintenance_page, min = 10, max = 3000 )
|
||||
self._thumbnail_cache_size.Bind( wx.EVT_SPINCTRL, self.EventThumbnailsUpdate )
|
||||
|
||||
self._estimated_number_thumbnails = wx.StaticText( self._maintenance_page, label = '' )
|
||||
|
||||
self._preview_cache_size = wx.SpinCtrl( self._maintenance_page, min = 20, max = 3000 )
|
||||
self._preview_cache_size.Bind( wx.EVT_SPINCTRL, self.EventPreviewsUpdate )
|
||||
|
||||
self._estimated_number_previews = wx.StaticText( self._maintenance_page, label = '' )
|
||||
|
||||
self._fullscreen_cache_size = wx.SpinCtrl( self._maintenance_page, min = 100, max = 3000 )
|
||||
self._fullscreen_cache_size.Bind( wx.EVT_SPINCTRL, self.EventFullscreensUpdate )
|
||||
|
||||
self._estimated_number_fullscreens = wx.StaticText( self._maintenance_page, label = '' )
|
||||
|
||||
self._maintenance_idle_period = wx.SpinCtrl( self._maintenance_page, min = 0, max = 1000 )
|
||||
self._maintenance_vacuum_period = wx.SpinCtrl( self._maintenance_page, min = 0, max = 365 )
|
||||
self._maintenance_delete_orphans_period = wx.SpinCtrl( self._maintenance_page, min = 0, max = 365 )
|
||||
|
||||
self._num_autocomplete_chars = wx.SpinCtrl( self._maintenance_page, min = 1, max = 100 )
|
||||
self._num_autocomplete_chars.SetToolTipString( 'how many characters you enter before the gui fetches autocomplete results from the db' + os.linesep + 'increase this if you find autocomplete results are slow' )
|
||||
|
||||
self._autocomplete_long_wait = wx.SpinCtrl( self._file_page, min = 0, max = 10000 )
|
||||
self._autocomplete_long_wait = wx.SpinCtrl( self._maintenance_page, min = 0, max = 10000 )
|
||||
self._autocomplete_long_wait.SetToolTipString( 'how long the gui will wait, after you enter a character, before it queries the db with what you have entered so far' )
|
||||
|
||||
self._autocomplete_short_wait_chars = wx.SpinCtrl( self._file_page, min = 1, max = 100 )
|
||||
self._autocomplete_short_wait_chars = wx.SpinCtrl( self._maintenance_page, min = 1, max = 100 )
|
||||
self._autocomplete_short_wait_chars.SetToolTipString( 'how many characters you enter before the gui starts waiting the short time before querying the db' )
|
||||
|
||||
self._autocomplete_short_wait = wx.SpinCtrl( self._file_page, min = 0, max = 10000 )
|
||||
self._autocomplete_short_wait = wx.SpinCtrl( self._maintenance_page, min = 0, max = 10000 )
|
||||
self._autocomplete_short_wait.SetToolTipString( 'how long the gui will wait, after you enter a lot of characters, before it queries the db with what you have entered so far' )
|
||||
|
||||
self._listbook.AddPage( self._file_page, 'files and memory' )
|
||||
self._listbook.AddPage( self._maintenance_page, 'maintenance and memory' )
|
||||
|
||||
# gui
|
||||
|
||||
|
@ -3038,20 +3049,26 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._exclude_deleted_files.SetValue( HC.options[ 'exclude_deleted_files' ] )
|
||||
|
||||
self._thumbnail_cache_size.SetValue( int( HC.options[ 'thumbnail_cache_size' ] / 1048576 ) )
|
||||
|
||||
self._preview_cache_size.SetValue( int( HC.options[ 'preview_cache_size' ] / 1048576 ) )
|
||||
|
||||
self._fullscreen_cache_size.SetValue( int( HC.options[ 'fullscreen_cache_size' ] / 1048576 ) )
|
||||
|
||||
( thumbnail_width, thumbnail_height ) = HC.options[ 'thumbnail_dimensions' ]
|
||||
|
||||
self._thumbnail_width.SetValue( thumbnail_width )
|
||||
|
||||
self._thumbnail_height.SetValue( thumbnail_height )
|
||||
|
||||
#
|
||||
|
||||
self._thumbnail_cache_size.SetValue( int( HC.options[ 'thumbnail_cache_size' ] / 1048576 ) )
|
||||
|
||||
self._preview_cache_size.SetValue( int( HC.options[ 'preview_cache_size' ] / 1048576 ) )
|
||||
|
||||
self._fullscreen_cache_size.SetValue( int( HC.options[ 'fullscreen_cache_size' ] / 1048576 ) )
|
||||
|
||||
self._num_autocomplete_chars.SetValue( HC.options[ 'num_autocomplete_chars' ] )
|
||||
|
||||
self._maintenance_idle_period.SetValue( HC.options[ 'idle_period' ] / 60 )
|
||||
self._maintenance_vacuum_period.SetValue( HC.options[ 'maintenance_vacuum_period' ] / 86400 )
|
||||
self._maintenance_delete_orphans_period.SetValue( HC.options[ 'maintenance_delete_orphans_period' ] / 86400 )
|
||||
|
||||
( char_limit, long_wait, short_wait ) = HC.options[ 'ac_timings' ]
|
||||
|
||||
self._autocomplete_long_wait.SetValue( long_wait )
|
||||
|
@ -3217,6 +3234,26 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def ArrangeControls():
|
||||
|
||||
gridbox = wx.FlexGridSizer( 0, 2 )
|
||||
|
||||
gridbox.AddGrowableCol( 1, 1 )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'Default export directory: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._export_location, FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'Exclude deleted files from new imports and remote searches: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._exclude_deleted_files, FLAGS_MIXED )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'Thumbnail width: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._thumbnail_width, FLAGS_MIXED )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'Thumbnail height: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._thumbnail_height, FLAGS_MIXED )
|
||||
|
||||
self._file_page.SetSizer( gridbox )
|
||||
|
||||
#
|
||||
|
||||
thumbnails_sizer = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
thumbnails_sizer.AddF( self._thumbnail_cache_size, FLAGS_MIXED )
|
||||
|
@ -3236,40 +3273,37 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
gridbox.AddGrowableCol( 1, 1 )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'Default export directory: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._export_location, FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'Exclude deleted files from new imports and remote searches: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._exclude_deleted_files, FLAGS_MIXED )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'MB memory reserved for thumbnail cache: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( wx.StaticText( self._maintenance_page, label = 'MB memory reserved for thumbnail cache: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( thumbnails_sizer, FLAGS_NONE )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'MB memory reserved for preview cache: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( wx.StaticText( self._maintenance_page, label = 'MB memory reserved for preview cache: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( previews_sizer, FLAGS_NONE )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'MB memory reserved for fullscreen cache: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( wx.StaticText( self._maintenance_page, label = 'MB memory reserved for fullscreen cache: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( fullscreens_sizer, FLAGS_NONE )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'Thumbnail width: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._thumbnail_width, FLAGS_MIXED )
|
||||
gridbox.AddF( wx.StaticText( self._maintenance_page, label = 'Minutes of inactivity until client is considered idle (0 for never): ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._maintenance_idle_period, FLAGS_MIXED )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'Thumbnail height: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._thumbnail_height, FLAGS_MIXED )
|
||||
gridbox.AddF( wx.StaticText( self._maintenance_page, label = 'Number of days to wait between vacuums (0 for never): ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._maintenance_vacuum_period, FLAGS_MIXED )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'Autocomplete character threshold: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( wx.StaticText( self._maintenance_page, label = 'Number of days to wait between orphan deletions (0 for never): ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._maintenance_delete_orphans_period, FLAGS_MIXED )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._maintenance_page, label = 'Autocomplete character threshold: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._num_autocomplete_chars, FLAGS_MIXED )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'Autocomplete long wait (ms): ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( wx.StaticText( self._maintenance_page, label = 'Autocomplete long wait (ms): ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._autocomplete_long_wait, FLAGS_MIXED )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'Autocomplete short wait threshold: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( wx.StaticText( self._maintenance_page, label = 'Autocomplete short wait threshold: ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._autocomplete_short_wait_chars, FLAGS_MIXED )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._file_page, label = 'Autocomplete short wait (ms): ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( wx.StaticText( self._maintenance_page, label = 'Autocomplete short wait (ms): ' ), FLAGS_MIXED )
|
||||
gridbox.AddF( self._autocomplete_short_wait, FLAGS_MIXED )
|
||||
|
||||
self._file_page.SetSizer( gridbox )
|
||||
self._maintenance_page.SetSizer( gridbox )
|
||||
|
||||
#
|
||||
|
||||
|
@ -3539,7 +3573,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
self.EventPreviewsUpdate( None )
|
||||
self.EventThumbnailsUpdate( None )
|
||||
|
||||
wx.CallAfter( self._file_page.Layout ) # draws the static texts correctly
|
||||
wx.CallAfter( self._maintenance_page.Layout ) # draws the static texts correctly
|
||||
|
||||
wx.CallAfter( self._ok.SetFocus )
|
||||
|
||||
|
@ -3759,6 +3793,10 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
HC.options[ 'preview_cache_size' ] = self._preview_cache_size.GetValue() * 1048576
|
||||
HC.options[ 'fullscreen_cache_size' ] = self._fullscreen_cache_size.GetValue() * 1048576
|
||||
|
||||
HC.options[ 'idle_period' ] = 60 * self._maintenance_idle_period.GetValue()
|
||||
HC.options[ 'maintenance_delete_orphans_period' ] = 86400 * self._maintenance_delete_orphans_period.GetValue()
|
||||
HC.options[ 'maintenance_vacuum_period' ] = 86400 * self._maintenance_vacuum_period.GetValue()
|
||||
|
||||
new_thumbnail_dimensions = [ self._thumbnail_width.GetValue(), self._thumbnail_height.GetValue() ]
|
||||
|
||||
if new_thumbnail_dimensions != HC.options[ 'thumbnail_dimensions' ]:
|
||||
|
|
|
@ -281,7 +281,16 @@ class MediaPanel( ClientGUIMixins.ListeningMediaList, wx.ScrolledWindow ):
|
|||
else: s = HC.ConvertIntToPrettyString( num_files ) + ' files'
|
||||
|
||||
elif num_selected == 1: s = '1 of ' + HC.ConvertIntToPrettyString( num_files ) + ' files selected, ' + pretty_total_size
|
||||
else: s = HC.ConvertIntToPrettyString( num_selected ) + ' of ' + HC.ConvertIntToPrettyString( num_files ) + ' files selected, totalling ' + pretty_total_size
|
||||
else:
|
||||
|
||||
num_inbox = sum( ( media.GetNumInbox() for media in self._selected_media ) )
|
||||
|
||||
if num_inbox == num_selected: inbox_phrase = 'all in inbox, '
|
||||
elif num_inbox == 0: inbox_phrase = 'all archived, '
|
||||
else: inbox_phrase = HC.ConvertIntToPrettyString( num_inbox ) + ' in inbox and ' + HC.ConvertIntToPrettyString( num_selected - num_inbox ) + ' archived, '
|
||||
|
||||
s = HC.ConvertIntToPrettyString( num_selected ) + ' of ' + HC.ConvertIntToPrettyString( num_files ) + ' files selected, ' + inbox_phrase + 'totalling ' + pretty_total_size
|
||||
|
||||
|
||||
return s
|
||||
|
||||
|
|
|
@ -565,9 +565,11 @@ class MediaCollection( MediaList, Media ):
|
|||
|
||||
def GetNumFiles( self ): return len( self._hashes )
|
||||
|
||||
def GetNumFrames( self ): return sum( [ media.GetNumFrames() for media in self._sorted_media ] )
|
||||
def GetNumInbox( self ): return sum( ( media.GetNumInbox() for media in self._sorted_media ) )
|
||||
|
||||
def GetNumWords( self ): return sum( [ media.GetNumWords() for media in self._sorted_media ] )
|
||||
def GetNumFrames( self ): return sum( ( media.GetNumFrames() for media in self._sorted_media ) )
|
||||
|
||||
def GetNumWords( self ): return sum( ( media.GetNumWords() for media in self._sorted_media ) )
|
||||
|
||||
def GetPrettyAge( self ): return 'imported ' + HC.ConvertTimestampToPrettyAgo( self._timestamp )
|
||||
|
||||
|
@ -681,6 +683,11 @@ class MediaSingleton( Media ):
|
|||
|
||||
def GetNumFrames( self ): return self._media_result.GetNumFrames()
|
||||
|
||||
def GetNumInbox( self ):
|
||||
|
||||
if self.HasInbox(): return 1
|
||||
else: return 0
|
||||
|
||||
def GetNumWords( self ): return self._media_result.GetNumWords()
|
||||
|
||||
def GetTimestamp( self ):
|
||||
|
|
|
@ -65,7 +65,7 @@ options = {}
|
|||
# Misc
|
||||
|
||||
NETWORK_VERSION = 15
|
||||
SOFTWARE_VERSION = 137
|
||||
SOFTWARE_VERSION = 138
|
||||
|
||||
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
||||
|
||||
|
@ -1962,7 +1962,10 @@ class JobKey( object ):
|
|||
|
||||
def DeleteVariable( self, name ):
|
||||
|
||||
with self._variable_lock: del self._variables[ name ]
|
||||
with self._variable_lock:
|
||||
|
||||
if name in self._variables: del self._variables[ name ]
|
||||
|
||||
|
||||
|
||||
def Finish( self ): self._done.set()
|
||||
|
@ -2076,9 +2079,10 @@ class JobNetwork( object ):
|
|||
|
||||
class Message( object ):
|
||||
|
||||
def __init__( self, message_type, info ):
|
||||
def __init__( self, message_type, job_key, info ):
|
||||
|
||||
self._message_type = message_type
|
||||
self._job_key = job_key
|
||||
self._info = info
|
||||
|
||||
self._closed = False
|
||||
|
@ -2111,7 +2115,7 @@ class MessageGauge( Message ):
|
|||
|
||||
def __init__( self, message_type, text, job_key ):
|
||||
|
||||
Message.__init__( self, message_type, {} )
|
||||
Message.__init__( self, message_type, job_key, {} )
|
||||
|
||||
self._info[ 'mode' ] = 'text'
|
||||
self._info[ 'text' ] = text
|
||||
|
|
|
@ -1786,7 +1786,7 @@ class ImportQueueGeneratorThread( ImportQueueGenerator ):
|
|||
finally: self._job_key.Finish()
|
||||
|
||||
|
||||
def THREADDownloadURL( message, url, url_string ):
|
||||
def THREADDownloadURL( job_key, url, url_string ):
|
||||
|
||||
try:
|
||||
|
||||
|
@ -1795,42 +1795,28 @@ def THREADDownloadURL( message, url, url_string ):
|
|||
if range is None: text = url_string + ' - ' + HC.ConvertIntToBytes( value )
|
||||
else: text = url_string + ' - ' + HC.ConvertIntToBytes( value ) + '/' + HC.ConvertIntToBytes( range )
|
||||
|
||||
message.SetInfo( 'range', range )
|
||||
message.SetInfo( 'value', value )
|
||||
message.SetInfo( 'text', text )
|
||||
job_key.SetVariable( 'popup_message_text_1', text )
|
||||
job_key.SetVariable( 'popup_message_gauge_1', ( value, range ) )
|
||||
|
||||
|
||||
message.SetInfo( 'range', None )
|
||||
message.SetInfo( 'value', None )
|
||||
message.SetInfo( 'mode', 'gauge' )
|
||||
|
||||
temp_path = HC.http.Request( HC.GET, url, response_to_path = True, report_hooks = [ hook ] )
|
||||
|
||||
message.SetInfo( 'range', None )
|
||||
message.SetInfo( 'value', None )
|
||||
message.SetInfo( 'text', 'importing ' + url_string )
|
||||
message.SetInfo( 'mode', 'gauge' )
|
||||
job_key.DeleteVariable( 'popup_message_gauge_1' )
|
||||
job_key.SetVariable( 'popup_message_text_1', 'importing ' + url_string )
|
||||
|
||||
( result, hash ) = HC.app.WriteSynchronous( 'import_file', temp_path )
|
||||
|
||||
if result in ( 'successful', 'redundant' ):
|
||||
|
||||
message.SetInfo( 'text', url_string )
|
||||
message.SetInfo( 'hashes', { hash } )
|
||||
message.SetInfo( 'mode', 'files' )
|
||||
job_key.SetVariable( 'popup_message_text_1', url_string )
|
||||
job_key.SetVariable( 'popup_message_files', { hash } )
|
||||
|
||||
elif result == 'deleted':
|
||||
|
||||
message.SetInfo( 'text', 'File was already deleted!' )
|
||||
message.SetInfo( 'mode', 'text' )
|
||||
job_key.SetVariable( 'popup_message_text_1', url_string + ' was already deleted!' )
|
||||
|
||||
|
||||
except Exception as e:
|
||||
|
||||
message.Close()
|
||||
|
||||
HC.ShowException( e )
|
||||
|
||||
except Exception as e: HC.ShowException( e )
|
||||
|
||||
def Parse4chanPostScreen( html ):
|
||||
|
||||
|
|
|
@ -550,6 +550,23 @@ class HydrusBitmap( object ):
|
|||
else: return wx.BitmapFromBufferRGBA( width, height, lz4.loads( self._data ) )
|
||||
|
||||
|
||||
def GetWxImage( self ):
|
||||
|
||||
( width, height ) = self._size
|
||||
|
||||
if self._format == wx.BitmapBufferFormat_RGB: return wx.ImageFromBuffer( width, height, lz4.loads( self._data ) )
|
||||
else:
|
||||
|
||||
bitmap = wx.BitmapFromBufferRGBA( width, height, lz4.loads( self._data ) )
|
||||
|
||||
image = wx.ImageFromBitmap( bitmap )
|
||||
|
||||
wx.CallAfter( bitmap.Destroy )
|
||||
|
||||
return image
|
||||
|
||||
|
||||
|
||||
def GetEstimatedMemoryFootprint( self ): return len( self._data )
|
||||
|
||||
def GetSize( self ): return self._size
|
||||
|
|
|
@ -2193,10 +2193,14 @@ class DB( ServiceDB ):
|
|||
|
||||
self._c.execute( 'ANALYZE' )
|
||||
|
||||
self._c.close()
|
||||
self._db.close()
|
||||
|
||||
self._InitDBCursor()
|
||||
|
||||
self._c.execute( 'BEGIN IMMEDIATE' )
|
||||
|
||||
shutil.copy( self._db_path, self._db_path + '.backup' )
|
||||
if os.path.exists( self._db_path + '-wal' ): shutil.copy( self._db_path + '-wal', self._db_path + '-wal.backup' )
|
||||
|
||||
shutil.rmtree( HC.SERVER_FILES_DIR + '_backup', ignore_errors = True )
|
||||
shutil.rmtree( HC.SERVER_THUMBNAILS_DIR + '_backup', ignore_errors = True )
|
||||
|
|
|
@ -46,7 +46,7 @@ class TestDaemons( unittest.TestCase ):
|
|||
|
||||
self.assertEqual( len( import_file ), 3 )
|
||||
|
||||
expected_tag_part = {'service_keys_to_tags': {HC.LOCAL_TAG_SERVICE_KEY: set(['local tag'])}}
|
||||
expected_tag_part = { 'service_keys_to_tags' : { HC.LOCAL_TAG_SERVICE_KEY : set( [ 'local tag' ] ) } }
|
||||
|
||||
( one, two, three ) = import_file
|
||||
|
||||
|
|
Loading…
Reference in New Issue