Version 157
This commit is contained in:
parent
b44ff7d9b5
commit
cec6ca96bb
|
@ -8,6 +8,29 @@
|
|||
<div class="content">
|
||||
<h3>changelog</h3>
|
||||
<ul>
|
||||
<li><h3>version 157</h3></li>
|
||||
<ul>
|
||||
<li>fixed a bug in listbook page initialisation and retrieval that was affecting many dialogs on OK</li>
|
||||
<li>some general dialog OK code cleanup</li>
|
||||
<li>fixed a media-navigation bug in managetags dialog</li>
|
||||
<li>fixed a serious OK bug in imageboards dialog</li>
|
||||
<li>created a new 'periodic' object to manage future subscriptions timing improvements</li>
|
||||
<li>started subscription YAML->JSON conversion</li>
|
||||
<li>stopped compressing json in the client db so it is human readable and thus easily editable</li>
|
||||
<li>subscriptions are no longer renamable, as this code was super buggy and could delete other subs</li>
|
||||
<li>tidied up the database menu</li>
|
||||
<li>a bit of misc cleanup</li>
|
||||
<li>in many cases where it was once pseudorandom, services are now reported in alphabetical order</li>
|
||||
<li>prototyped 'like' ratings control</li>
|
||||
<li>added new like ratings control to the background bmp of the media viewer</li>
|
||||
<li>added new like ratings control to the manage ratings dialog</li>
|
||||
<li>added new like ratings control to a new hover window in the top-right</li>
|
||||
<li>added basic additional icon support to new hover window</li>
|
||||
<li>fixed some misc new alignment bugs related to new ratings stuff</li>
|
||||
<li>like ratings controls on the hover window have tooltips</li>
|
||||
<li>fixed up some icon/rating display logic in the background bmp of the media viewer</li>
|
||||
<li>updated ratings dialog error handling</li>
|
||||
</ul>
|
||||
<li><h3>version 156</h3></li>
|
||||
<ul>
|
||||
<li>improved my build workflow in several ways, which should result in fewer orphan files and other build weirdnesses</li>
|
||||
|
|
|
@ -49,7 +49,9 @@ class DataCache( object ):
|
|||
|
||||
if key not in self._keys_to_data:
|
||||
|
||||
while self._total_estimated_memory_footprint > HC.options[ self._cache_size_key ]:
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
while self._total_estimated_memory_footprint > options[ self._cache_size_key ]:
|
||||
|
||||
( deletee_key, last_access_time ) = self._keys_fifo.pop( 0 )
|
||||
|
||||
|
@ -395,7 +397,9 @@ class ThumbnailCache( object ):
|
|||
|
||||
path = HC.STATIC_DIR + os.path.sep + name + '.png'
|
||||
|
||||
thumbnail = HydrusFileHandling.GenerateThumbnail( path, HC.options[ 'thumbnail_dimensions' ] )
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
thumbnail = HydrusFileHandling.GenerateThumbnail( path, options[ 'thumbnail_dimensions' ] )
|
||||
|
||||
with open( temp_path, 'wb' ) as f: f.write( thumbnail )
|
||||
|
||||
|
|
|
@ -96,6 +96,12 @@ field_string_lookup[ FIELD_FILE ] = 'file'
|
|||
field_string_lookup[ FIELD_THREAD_ID ] = 'thread id'
|
||||
field_string_lookup[ FIELD_PASSWORD ] = 'password'
|
||||
|
||||
FILE_UNKNOWN = 0
|
||||
FILE_SUCCESSFUL = 1
|
||||
FILE_REDUNDANT = 2
|
||||
FILE_DELETED = 3
|
||||
FILE_FAILED = 4
|
||||
|
||||
FLAGS_NONE = wx.SizerFlags( 0 )
|
||||
|
||||
FLAGS_SMALL_INDENT = wx.SizerFlags( 0 ).Border( wx.ALL, 2 )
|
||||
|
@ -119,6 +125,10 @@ FLAGS_LONE_BUTTON = wx.SizerFlags( 0 ).Border( wx.ALL, 2 ).Align( wx.ALIGN_RIGHT
|
|||
|
||||
FLAGS_MIXED = wx.SizerFlags( 0 ).Border( wx.ALL, 2 ).Align( wx.ALIGN_CENTER_VERTICAL )
|
||||
|
||||
DAY = 0
|
||||
WEEK = 1
|
||||
MONTH = 2
|
||||
|
||||
RESTRICTION_MIN_RESOLUTION = 0
|
||||
RESTRICTION_MAX_RESOLUTION = 1
|
||||
RESTRICTION_MAX_FILE_SIZE = 2
|
||||
|
|
|
@ -149,9 +149,9 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
def CurrentlyIdle( self ):
|
||||
|
||||
if HC.options[ 'idle_period' ] == 0: return False
|
||||
if self._options[ 'idle_period' ] == 0: return False
|
||||
|
||||
return HydrusData.GetNow() - self._timestamps[ 'last_user_action' ] > HC.options[ 'idle_period' ]
|
||||
return HydrusData.GetNow() - self._timestamps[ 'last_user_action' ] > self._options[ 'idle_period' ]
|
||||
|
||||
|
||||
def DoHTTP( self, *args, **kwargs ): return self._http.Request( *args, **kwargs )
|
||||
|
@ -160,6 +160,11 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
def GetManager( self, manager_type ): return self._managers[ manager_type ]
|
||||
|
||||
def GetOptions( self ):
|
||||
|
||||
return self._options
|
||||
|
||||
|
||||
def InitCheckPassword( self ):
|
||||
|
||||
while True:
|
||||
|
@ -168,7 +173,7 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
|
||||
if hashlib.sha256( dlg.GetValue() ).digest() == HC.options[ 'password' ]: break
|
||||
if hashlib.sha256( dlg.GetValue() ).digest() == self._options[ 'password' ]: break
|
||||
|
||||
else: raise HydrusExceptions.PermissionException()
|
||||
|
||||
|
@ -254,14 +259,14 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
shutdown_timestamps = self.Read( 'shutdown_timestamps' )
|
||||
|
||||
if HC.options[ 'maintenance_vacuum_period' ] != 0:
|
||||
if self._options[ 'maintenance_vacuum_period' ] != 0:
|
||||
|
||||
if now - shutdown_timestamps[ CC.SHUTDOWN_TIMESTAMP_VACUUM ] > HC.options[ 'maintenance_vacuum_period' ]: self.Write( 'vacuum' )
|
||||
if now - shutdown_timestamps[ CC.SHUTDOWN_TIMESTAMP_VACUUM ] > self._options[ 'maintenance_vacuum_period' ]: self.Write( 'vacuum' )
|
||||
|
||||
|
||||
if HC.options[ 'maintenance_delete_orphans_period' ] != 0:
|
||||
if self._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 - shutdown_timestamps[ CC.SHUTDOWN_TIMESTAMP_DELETE_ORPHANS ] > self._options[ 'maintenance_delete_orphans_period' ]: self.Write( 'delete_orphans' )
|
||||
|
||||
|
||||
if self._timestamps[ 'last_service_info_cache_fatten' ] != 0 and now - self._timestamps[ 'last_service_info_cache_fatten' ] > 60 * 20:
|
||||
|
@ -316,7 +321,7 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
def PrepStringForDisplay( self, text ):
|
||||
|
||||
if HC.options[ 'gui_capitalisation' ]: return text
|
||||
if self._options[ 'gui_capitalisation' ]: return text
|
||||
else: return text.lower()
|
||||
|
||||
|
||||
|
@ -387,7 +392,7 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
def RestartServer( self ):
|
||||
|
||||
port = HC.options[ 'local_port' ]
|
||||
port = self._options[ 'local_port' ]
|
||||
|
||||
def TWISTEDRestartServer():
|
||||
|
||||
|
@ -525,9 +530,11 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
self.InitDB() # can't run on wx thread because we need event queue free to update splash text
|
||||
|
||||
HC.options = wx.GetApp().Read( 'options' )
|
||||
self._options = wx.GetApp().Read( 'options' )
|
||||
|
||||
if HC.options[ 'password' ] is not None:
|
||||
HC.options = self._options
|
||||
|
||||
if self._options[ 'password' ] is not None:
|
||||
|
||||
HydrusGlobals.pubsub.pub( 'splash_set_text', 'waiting for password' )
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import HydrusTags
|
|||
import HydrusThreading
|
||||
import ClientConstants as CC
|
||||
import ClientDaemons
|
||||
import lz4
|
||||
import os
|
||||
import Queue
|
||||
import random
|
||||
|
@ -1116,13 +1117,15 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
def _AddThumbnails( self, thumbnails ):
|
||||
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
for ( hash, thumbnail ) in thumbnails:
|
||||
|
||||
thumbnail_path = ClientFiles.GetExpectedThumbnailPath( hash, True )
|
||||
|
||||
with open( thumbnail_path, 'wb' ) as f: f.write( thumbnail )
|
||||
|
||||
thumbnail_resized = HydrusFileHandling.GenerateThumbnail( thumbnail_path, HC.options[ 'thumbnail_dimensions' ] )
|
||||
thumbnail_resized = HydrusFileHandling.GenerateThumbnail( thumbnail_path, options[ 'thumbnail_dimensions' ] )
|
||||
|
||||
thumbnail_resized_path = ClientFiles.GetExpectedThumbnailPath( hash, False )
|
||||
|
||||
|
@ -2298,7 +2301,9 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
for wildcard in wildcards_to_exclude: exclude_query_hash_ids.update( self._GetHashIdsFromWildcard( file_service_key, tag_service_key, wildcard, include_current_tags, include_pending_tags ) )
|
||||
|
||||
if file_service_type == HC.FILE_REPOSITORY and HC.options[ 'exclude_deleted_files' ]: exclude_query_hash_ids.update( [ hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM deleted_files WHERE service_id = ?;', ( self._local_file_service_id, ) ) ] )
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
if file_service_type == HC.FILE_REPOSITORY and options[ 'exclude_deleted_files' ]: exclude_query_hash_ids.update( [ hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM deleted_files WHERE service_id = ?;', ( self._local_file_service_id, ) ) ] )
|
||||
|
||||
query_hash_ids.difference_update( exclude_query_hash_ids )
|
||||
|
||||
|
@ -2431,7 +2436,9 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
if service_type == HC.FILE_REPOSITORY:
|
||||
|
||||
if HC.options[ 'exclude_deleted_files' ]:
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
if options[ 'exclude_deleted_files' ]:
|
||||
|
||||
( num_everything_deleted, ) = self._c.execute( 'SELECT COUNT( * ) FROM files_info, deleted_files USING ( hash_id ) WHERE files_info.service_id = ? AND deleted_files.service_id = ?;', ( service_id, self._local_file_service_id ) ).fetchone()
|
||||
|
||||
|
@ -2804,7 +2811,9 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
( hash_id, ) = result
|
||||
|
||||
if HC.options[ 'exclude_deleted_files' ]:
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
if options[ 'exclude_deleted_files' ]:
|
||||
|
||||
result = self._c.execute( 'SELECT 1 FROM deleted_files WHERE hash_id = ?;', ( hash_id, ) ).fetchone()
|
||||
|
||||
|
@ -3645,7 +3654,9 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
( hash_id, ) = result
|
||||
|
||||
if HC.options[ 'exclude_deleted_files' ]:
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
if options[ 'exclude_deleted_files' ]:
|
||||
|
||||
result = self._c.execute( 'SELECT 1 FROM deleted_files WHERE hash_id = ?;', ( hash_id, ) ).fetchone()
|
||||
|
||||
|
@ -4653,15 +4664,15 @@ class DB( HydrusDB.HydrusDB ):
|
|||
HydrusData.ShowText( 'Service ' + name + ' was reset successfully!' )
|
||||
|
||||
|
||||
def _SaveOptions( self ):
|
||||
def _SaveOptions( self, options ):
|
||||
|
||||
( old_options, ) = self._c.execute( 'SELECT options FROM options;' ).fetchone()
|
||||
|
||||
( old_width, old_height ) = old_options[ 'thumbnail_dimensions' ]
|
||||
|
||||
( new_width, new_height ) = HC.options[ 'thumbnail_dimensions' ]
|
||||
( new_width, new_height ) = options[ 'thumbnail_dimensions' ]
|
||||
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( HC.options, ) )
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( options, ) )
|
||||
|
||||
resize_thumbs = new_width != old_width or new_height != old_height
|
||||
|
||||
|
@ -4718,9 +4729,11 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
if password is not None: password = hashlib.sha256( password ).digest()
|
||||
|
||||
HC.options[ 'password' ] = password
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
self._SaveOptions()
|
||||
options[ 'password' ] = password
|
||||
|
||||
self._SaveOptions( options )
|
||||
|
||||
|
||||
def _SetTagCensorship( self, info ):
|
||||
|
@ -5086,11 +5099,11 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
if version == 125:
|
||||
|
||||
HC.options = self._GetOptions()
|
||||
options = self._GetOptions()
|
||||
|
||||
HC.options[ 'default_tag_repository' ] = HC.options[ 'default_tag_repository' ].GetServiceKey()
|
||||
options[ 'default_tag_repository' ] = options[ 'default_tag_repository' ].GetServiceKey()
|
||||
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( HC.options, ) )
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( options, ) )
|
||||
|
||||
#
|
||||
|
||||
|
@ -5154,17 +5167,17 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
#
|
||||
|
||||
HC.options = self._GetOptions()
|
||||
options = self._GetOptions()
|
||||
|
||||
client_size = HC.options[ 'client_size' ]
|
||||
client_size = options[ 'client_size' ]
|
||||
|
||||
client_size[ 'fs_fullscreen' ] = True
|
||||
|
||||
client_size[ 'gui_fullscreen' ] = False
|
||||
|
||||
del HC.options[ 'fullscreen_borderless' ]
|
||||
del options[ 'fullscreen_borderless' ]
|
||||
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( HC.options, ) )
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( options, ) )
|
||||
|
||||
|
||||
if version == 135:
|
||||
|
@ -5254,29 +5267,29 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
if version == 143:
|
||||
|
||||
HC.options = self._GetOptions()
|
||||
options = self._GetOptions()
|
||||
|
||||
HC.options[ 'shortcuts' ][ wx.ACCEL_CTRL ][ ord( 'E' ) ] = 'open_externally'
|
||||
options[ 'shortcuts' ][ wx.ACCEL_CTRL ][ ord( 'E' ) ] = 'open_externally'
|
||||
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( HC.options, ) )
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( options, ) )
|
||||
|
||||
|
||||
if version == 145:
|
||||
|
||||
HC.options = self._GetOptions()
|
||||
options = self._GetOptions()
|
||||
|
||||
HC.options[ 'gui_colours' ][ 'tags_box' ] = ( 255, 255, 255 )
|
||||
options[ 'gui_colours' ][ 'tags_box' ] = ( 255, 255, 255 )
|
||||
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( HC.options, ) )
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( options, ) )
|
||||
|
||||
|
||||
if version == 150:
|
||||
|
||||
HC.options = self._GetOptions()
|
||||
options = self._GetOptions()
|
||||
|
||||
HC.options[ 'file_system_predicates' ][ 'hamming_distance' ] = 5
|
||||
options[ 'file_system_predicates' ][ 'hamming_distance' ] = 5
|
||||
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( HC.options, ) )
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( options, ) )
|
||||
|
||||
|
||||
if version == 151:
|
||||
|
@ -5293,20 +5306,20 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
if version == 152:
|
||||
|
||||
HC.options = self._GetOptions()
|
||||
options = self._GetOptions()
|
||||
|
||||
HC.options[ 'file_system_predicates' ][ 'num_pixels' ] = ( 1, 2, 2 )
|
||||
options[ 'file_system_predicates' ][ 'num_pixels' ] = ( 1, 2, 2 )
|
||||
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( HC.options, ) )
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( options, ) )
|
||||
|
||||
|
||||
if version == 153:
|
||||
|
||||
HC.options = self._GetOptions()
|
||||
options = self._GetOptions()
|
||||
|
||||
HC.options[ 'file_system_predicates' ] = ClientDefaults.GetClientDefaultOptions()[ 'file_system_predicates' ]
|
||||
options[ 'file_system_predicates' ] = ClientDefaults.GetClientDefaultOptions()[ 'file_system_predicates' ]
|
||||
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( HC.options, ) )
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( options, ) )
|
||||
|
||||
#
|
||||
|
||||
|
@ -5351,6 +5364,18 @@ class DB( HydrusDB.HydrusDB ):
|
|||
self._c.execute( 'DELETE FROM yaml_dumps WHERE dump_type = ?;', ( YAML_DUMP_ID_FAVOURITE_CUSTOM_FILTER_ACTIONS, ) )
|
||||
|
||||
|
||||
if version == 156:
|
||||
|
||||
results = self._c.execute( 'SELECT dump_type, dump_name, dump FROM json_dumps_named;' ).fetchall()
|
||||
|
||||
for ( dump_type, dump_name, dump ) in results:
|
||||
|
||||
dump = lz4.loads( dump )
|
||||
|
||||
self._c.execute( 'UPDATE json_dumps_named SET dump = ? WHERE dump_type = ? AND dump_name = ?;', ( sqlite3.Binary( dump ), dump_type, dump_name ) )
|
||||
|
||||
|
||||
|
||||
self._c.execute( 'UPDATE version SET version = ?;', ( version + 1, ) )
|
||||
|
||||
HydrusGlobals.is_db_updated = True
|
||||
|
|
|
@ -35,7 +35,9 @@ import HydrusGlobals
|
|||
|
||||
def DAEMONCheckExportFolders():
|
||||
|
||||
if not HC.options[ 'pause_export_folders_sync' ]:
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
if not options[ 'pause_export_folders_sync' ]:
|
||||
|
||||
export_folders = wx.GetApp().Read( 'export_folders' )
|
||||
|
||||
|
@ -73,7 +75,7 @@ def DAEMONCheckExportFolders():
|
|||
|
||||
while i < len( query_hash_ids ):
|
||||
|
||||
if HC.options[ 'pause_export_folders_sync' ]: return
|
||||
if options[ 'pause_export_folders_sync' ]: return
|
||||
|
||||
if i == 0: ( last_i, i ) = ( 0, base )
|
||||
else: ( last_i, i ) = ( i, i + base )
|
||||
|
@ -120,7 +122,9 @@ def DAEMONCheckExportFolders():
|
|||
|
||||
def DAEMONCheckImportFolders():
|
||||
|
||||
if not HC.options[ 'pause_import_folders_sync' ]:
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
if not options[ 'pause_import_folders_sync' ]:
|
||||
|
||||
import_folders = wx.GetApp().Read( 'import_folders' )
|
||||
|
||||
|
@ -149,7 +153,7 @@ def DAEMONCheckImportFolders():
|
|||
|
||||
for ( i, path ) in enumerate( all_paths ):
|
||||
|
||||
if HC.options[ 'pause_import_folders_sync' ]: return
|
||||
if options[ 'pause_import_folders_sync' ]: return
|
||||
|
||||
info = os.lstat( path )
|
||||
|
||||
|
@ -328,11 +332,13 @@ def DAEMONResizeThumbnails():
|
|||
|
||||
limit = max( 100, len( thumbnail_paths_to_render ) / 10 )
|
||||
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
for thumbnail_path in thumbnail_paths_to_render:
|
||||
|
||||
try:
|
||||
|
||||
thumbnail_resized = HydrusFileHandling.GenerateThumbnail( thumbnail_path, HC.options[ 'thumbnail_dimensions' ] )
|
||||
thumbnail_resized = HydrusFileHandling.GenerateThumbnail( thumbnail_path, options[ 'thumbnail_dimensions' ] )
|
||||
|
||||
thumbnail_resized_path = thumbnail_path + '_resized'
|
||||
|
||||
|
@ -360,6 +366,8 @@ def DAEMONSynchroniseAccounts():
|
|||
|
||||
services = wx.GetApp().GetManager( 'services' ).GetServices( HC.RESTRICTED_SERVICES )
|
||||
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
do_notify = False
|
||||
|
||||
for service in services:
|
||||
|
@ -372,7 +380,7 @@ def DAEMONSynchroniseAccounts():
|
|||
|
||||
if service_type in HC.REPOSITORIES:
|
||||
|
||||
if HC.options[ 'pause_repo_sync' ]: continue
|
||||
if options[ 'pause_repo_sync' ]: continue
|
||||
|
||||
info = service.GetInfo()
|
||||
|
||||
|
@ -581,7 +589,9 @@ def DAEMONSynchroniseRepositories():
|
|||
|
||||
HydrusGlobals.repos_changed = False
|
||||
|
||||
if not HC.options[ 'pause_repo_sync' ]:
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
if not options[ 'pause_repo_sync' ]:
|
||||
|
||||
services = wx.GetApp().GetManager( 'services' ).GetServices( HC.REPOSITORIES )
|
||||
|
||||
|
@ -612,13 +622,13 @@ def DAEMONSynchroniseRepositories():
|
|||
|
||||
while service.CanDownloadUpdate():
|
||||
|
||||
while job_key.IsPaused() or job_key.IsCancelled() or HC.options[ 'pause_repo_sync' ] or HydrusGlobals.shutdown:
|
||||
while job_key.IsPaused() or job_key.IsCancelled() or options[ 'pause_repo_sync' ] or HydrusGlobals.shutdown:
|
||||
|
||||
time.sleep( 0.1 )
|
||||
|
||||
if job_key.IsPaused(): job_key.SetVariable( 'popup_message_text_1', 'paused' )
|
||||
|
||||
if HC.options[ 'pause_repo_sync' ]: job_key.SetVariable( 'popup_message_text_1', 'repository synchronisation paused' )
|
||||
if options[ 'pause_repo_sync' ]: job_key.SetVariable( 'popup_message_text_1', 'repository synchronisation paused' )
|
||||
|
||||
if HydrusGlobals.shutdown: raise Exception( 'application shutting down!' )
|
||||
|
||||
|
@ -705,13 +715,13 @@ def DAEMONSynchroniseRepositories():
|
|||
|
||||
while service.CanProcessUpdate():
|
||||
|
||||
while job_key.IsPaused() or job_key.IsCancelled() or HC.options[ 'pause_repo_sync' ] or HydrusGlobals.shutdown:
|
||||
while job_key.IsPaused() or job_key.IsCancelled() or options[ 'pause_repo_sync' ] or HydrusGlobals.shutdown:
|
||||
|
||||
time.sleep( 0.1 )
|
||||
|
||||
if job_key.IsPaused(): job_key.SetVariable( 'popup_message_text_1', 'paused' )
|
||||
|
||||
if HC.options[ 'pause_repo_sync' ]: job_key.SetVariable( 'popup_message_text_1', 'repository synchronisation paused' )
|
||||
if options[ 'pause_repo_sync' ]: job_key.SetVariable( 'popup_message_text_1', 'repository synchronisation paused' )
|
||||
|
||||
if HydrusGlobals.shutdown: raise Exception( 'application shutting down!' )
|
||||
|
||||
|
@ -770,13 +780,13 @@ def DAEMONSynchroniseRepositories():
|
|||
|
||||
for ( i, content_update ) in enumerate( update.IterateContentUpdates() ):
|
||||
|
||||
while job_key.IsPaused() or job_key.IsCancelled() or HC.options[ 'pause_repo_sync' ] or HydrusGlobals.shutdown:
|
||||
while job_key.IsPaused() or job_key.IsCancelled() or options[ 'pause_repo_sync' ] or HydrusGlobals.shutdown:
|
||||
|
||||
time.sleep( 0.1 )
|
||||
|
||||
if job_key.IsPaused(): job_key.SetVariable( 'popup_message_text_2', 'paused' )
|
||||
|
||||
if HC.options[ 'pause_repo_sync' ]: job_key.SetVariable( 'popup_message_text_2', 'repository synchronisation paused' )
|
||||
if options[ 'pause_repo_sync' ]: job_key.SetVariable( 'popup_message_text_2', 'repository synchronisation paused' )
|
||||
|
||||
if HydrusGlobals.shutdown: raise Exception( 'application shutting down!' )
|
||||
|
||||
|
@ -906,13 +916,13 @@ def DAEMONSynchroniseRepositories():
|
|||
|
||||
if len( thumbnail_hashes_i_need ) > 0:
|
||||
|
||||
while job_key.IsPaused() or job_key.IsCancelled() or HC.options[ 'pause_repo_sync' ] or HydrusGlobals.shutdown:
|
||||
while job_key.IsPaused() or job_key.IsCancelled() or options[ 'pause_repo_sync' ] or HydrusGlobals.shutdown:
|
||||
|
||||
time.sleep( 0.1 )
|
||||
|
||||
if job_key.IsPaused(): job_key.SetVariable( 'popup_message_text_1', 'paused' )
|
||||
|
||||
if HC.options[ 'pause_repo_sync' ]: job_key.SetVariable( 'popup_message_text_1', 'repository synchronisation paused' )
|
||||
if options[ 'pause_repo_sync' ]: job_key.SetVariable( 'popup_message_text_1', 'repository synchronisation paused' )
|
||||
|
||||
if HydrusGlobals.shutdown: raise Exception( 'application shutting down!' )
|
||||
|
||||
|
@ -1014,7 +1024,9 @@ def DAEMONSynchroniseSubscriptions():
|
|||
|
||||
HydrusGlobals.subs_changed = False
|
||||
|
||||
if not HC.options[ 'pause_subs_sync' ]:
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
if not options[ 'pause_subs_sync' ]:
|
||||
|
||||
subscription_names = wx.GetApp().Read( 'subscription_names' )
|
||||
|
||||
|
@ -1111,13 +1123,13 @@ def DAEMONSynchroniseSubscriptions():
|
|||
|
||||
while True:
|
||||
|
||||
while job_key.IsPaused() or job_key.IsCancelled() or HC.options[ 'pause_subs_sync' ] or HydrusGlobals.shutdown:
|
||||
while job_key.IsPaused() or job_key.IsCancelled() or options[ 'pause_subs_sync' ] or HydrusGlobals.shutdown:
|
||||
|
||||
time.sleep( 0.1 )
|
||||
|
||||
if job_key.IsPaused(): job_key.SetVariable( 'popup_message_text_1', 'paused' )
|
||||
|
||||
if HC.options[ 'pause_subs_sync' ]: job_key.SetVariable( 'popup_message_text_1', 'subscriptions paused' )
|
||||
if options[ 'pause_subs_sync' ]: job_key.SetVariable( 'popup_message_text_1', 'subscriptions paused' )
|
||||
|
||||
if HydrusGlobals.shutdown: raise Exception( 'application shutting down!' )
|
||||
|
||||
|
@ -1185,13 +1197,13 @@ def DAEMONSynchroniseSubscriptions():
|
|||
|
||||
for ( i, url_args ) in enumerate( all_url_args ):
|
||||
|
||||
while job_key.IsPaused() or job_key.IsCancelled() or HC.options[ 'pause_subs_sync' ] or HydrusGlobals.shutdown:
|
||||
while job_key.IsPaused() or job_key.IsCancelled() or options[ 'pause_subs_sync' ] or HydrusGlobals.shutdown:
|
||||
|
||||
time.sleep( 0.1 )
|
||||
|
||||
if job_key.IsPaused(): job_key.SetVariable( 'popup_message_text_1', 'paused' )
|
||||
|
||||
if HC.options[ 'pause_subs_sync' ]: job_key.SetVariable( 'popup_message_text_1', 'subscriptions paused' )
|
||||
if options[ 'pause_subs_sync' ]: job_key.SetVariable( 'popup_message_text_1', 'subscriptions paused' )
|
||||
|
||||
if HydrusGlobals.shutdown: raise Exception( 'application shutting down!' )
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import ClientConstants as CC
|
||||
import collections
|
||||
import datetime
|
||||
import HydrusConstants as HC
|
||||
import HydrusExceptions
|
||||
import HydrusNetworking
|
||||
|
@ -9,6 +10,7 @@ import traceback
|
|||
import os
|
||||
import sqlite3
|
||||
import sys
|
||||
import time
|
||||
import wx
|
||||
import yaml
|
||||
import HydrusData
|
||||
|
@ -122,7 +124,9 @@ def GenerateExportFilename( media, terms ):
|
|||
|
||||
def GetExportPath():
|
||||
|
||||
path = HC.options[ 'export_path' ]
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
path = options[ 'export_path' ]
|
||||
|
||||
if path is None:
|
||||
|
||||
|
@ -788,6 +792,39 @@ class FileSystemPredicates( object ):
|
|||
|
||||
def MustNotBeLocal( self ): return self._not_local
|
||||
|
||||
class GalleryQuery( HydrusSerialisable.SerialisableBase ):
|
||||
|
||||
SERIALISABLE_TYPE = HydrusSerialisable.SERIALISABLE_TYPE_GALLERY_QUERY
|
||||
VERSION = 1
|
||||
|
||||
def __init__( self, name ):
|
||||
|
||||
HydrusSerialisable.SerialisableBase.__init__( self )
|
||||
|
||||
self._site_type = None
|
||||
self._query_type = None
|
||||
self._query = None
|
||||
# add 'check tags if redundant' here
|
||||
self._import_file_options = None
|
||||
self._import_tag_options = None
|
||||
|
||||
|
||||
def _GetSerialisableInfo( self ):
|
||||
|
||||
return ( self._site_type, self._query_type, self._query, self._import_file_options.GetEasySerialisedInfo(), self._import_tag_options.GetEasySerialisedInfo() )
|
||||
|
||||
|
||||
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
|
||||
|
||||
( self._site_type, self._query_type, self._query, easy_serialised_import_file_options, easy_serialised_import_tag_options ) = serialisable_info
|
||||
|
||||
self._import_file_options = HydrusSerialisable.CreateFromEasy( easy_serialised_import_file_options )
|
||||
|
||||
self._import_tag_options = HydrusSerialisable.CreateFromEasy( easy_serialised_import_tag_options )
|
||||
|
||||
|
||||
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_GALLERY_QUERY ] = GalleryQuery
|
||||
|
||||
class Imageboard( HydrusData.HydrusYAMLBase ):
|
||||
|
||||
yaml_tag = u'!Imageboard'
|
||||
|
@ -832,6 +869,246 @@ class Imageboard( HydrusData.HydrusYAMLBase ):
|
|||
|
||||
sqlite3.register_adapter( Imageboard, yaml.safe_dump )
|
||||
|
||||
class ImportFileOptions( HydrusSerialisable.SerialisableBase ):
|
||||
|
||||
SERIALISABLE_TYPE = HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_FILE_OPTIONS
|
||||
VERSION = 1
|
||||
|
||||
def __init__( self, name ):
|
||||
|
||||
HydrusSerialisable.SerialisableBase.__init__( self )
|
||||
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
self._automatic_archive = False
|
||||
self._exclude_deleted = options[ 'exclude_deleted_files' ]
|
||||
self._min_size = None
|
||||
self._min_resolution = None
|
||||
self._file_limit = None
|
||||
|
||||
|
||||
def _GetSerialisableInfo( self ):
|
||||
|
||||
return ( self._automatic_archive, self._exclude_deleted, self._min_size, self._min_resolution, self._file_limit )
|
||||
|
||||
|
||||
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
|
||||
|
||||
( self._automatic_archive, self._exclude_deleted, self._min_size, self._min_resolution, self._file_limit ) = serialisable_info
|
||||
|
||||
|
||||
def ToTuple( self ):
|
||||
|
||||
return ( self._automatic_archive, self._exclude_deleted, self._min_size, self._min_resolution, self._file_limit )
|
||||
|
||||
|
||||
def SetTuple( self, automatic_archive, exclude_deleted, min_size, min_resolution, file_limit ):
|
||||
|
||||
self._automatic_archive = automatic_archive
|
||||
self._exclude_deleted = exclude_deleted
|
||||
self._min_size = min_size
|
||||
self._min_resolution = min_resolution
|
||||
file_limit = file_limit
|
||||
|
||||
|
||||
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_FILE_OPTIONS ] = ImportFileOptions
|
||||
|
||||
class ImportTagOptions( HydrusSerialisable.SerialisableBase ):
|
||||
|
||||
SERIALISABLE_TYPE = HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_TAG_OPTIONS
|
||||
VERSION = 1
|
||||
|
||||
def __init__( self, name ):
|
||||
|
||||
HydrusSerialisable.SerialisableBase.__init__( self )
|
||||
|
||||
self._get_tags_on_redundant = False
|
||||
self._service_keys_to_namespaces = {}
|
||||
|
||||
|
||||
def _GetSerialisableInfo( self ):
|
||||
|
||||
safe_service_keys_to_namespaces = { service_key.encode( 'hex' ) : list( namespaces ) for ( service_key, namespaces ) in self._service_keys_to_namespaces.items() }
|
||||
|
||||
return ( self._get_tags_on_redundant, safe_service_keys_to_namespaces )
|
||||
|
||||
|
||||
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
|
||||
|
||||
( self._get_tags_on_redundant, safe_service_keys_to_namespaces ) = serialisable_info
|
||||
|
||||
self._service_keys_to_namespaces = { service_key.decode( 'hex' ) : set( namespaces ) for ( service_key, namespaces ) in self._service_keys_to_namespaces.items() }
|
||||
|
||||
|
||||
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_TAG_OPTIONS ] = ImportTagOptions
|
||||
|
||||
class Periodic( HydrusSerialisable.SerialisableBase ):
|
||||
|
||||
SERIALISABLE_TYPE = HydrusSerialisable.SERIALISABLE_TYPE_PERIODIC
|
||||
VERSION = 1
|
||||
|
||||
def __init__( self, name ):
|
||||
|
||||
HydrusSerialisable.SerialisableBase.__init__( self )
|
||||
|
||||
self._wavelength = CC.DAY
|
||||
self._multiplier = 1
|
||||
self._phase = 0
|
||||
self._last_run = 0
|
||||
self._failure_delay_timestamp = None
|
||||
self._paused = False
|
||||
|
||||
|
||||
def _GetSerialisableInfo( self ):
|
||||
|
||||
return ( self._wavelength, self._multiplier, self._phase, self._last_run, self._failure_delay_timestamp, self._paused )
|
||||
|
||||
|
||||
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
|
||||
|
||||
( self._wavelength, self._multiplier, self._phase, self._last_run, self._failure_delay_timestamp, self._paused ) = serialisable_info
|
||||
|
||||
|
||||
def GetDue( self ):
|
||||
|
||||
day_phase = self._phase / ( 24 * 3600 )
|
||||
hour_phase = ( self._phase % ( 24 * 3600 ) ) / 3600
|
||||
minute_phase = ( self._phase % 3600 ) / 60
|
||||
|
||||
last_run_datetime = datetime.datetime.fromtimestamp( self._last_run )
|
||||
|
||||
due_datetime = last_run_datetime.replace( hour = hour_phase, minute = minute_phase, second = 0, microsecond = 0 )
|
||||
|
||||
one_day = datetime.timedelta( days = 1 )
|
||||
|
||||
if self._wavelength == CC.DAY:
|
||||
|
||||
due_datetime += one_day * self._multiplier
|
||||
|
||||
elif self._wavelength == CC.WEEK:
|
||||
|
||||
times_passed = 0
|
||||
|
||||
while times_passed < self._multiplier:
|
||||
|
||||
due_datetime += one_day
|
||||
|
||||
if due_datetime.weekday() == day_phase:
|
||||
|
||||
times_passed += 1
|
||||
|
||||
|
||||
|
||||
elif self._wavelength == CC.MONTH:
|
||||
|
||||
times_passed = 0
|
||||
|
||||
while times_passed < self._multiplier:
|
||||
|
||||
due_datetime += one_day
|
||||
|
||||
if due_datetime.day == day_phase + 1:
|
||||
|
||||
times_passed += 1
|
||||
|
||||
|
||||
|
||||
|
||||
due_timestamp = time.mktime( due_datetime.timetuple() )
|
||||
|
||||
return due_timestamp
|
||||
|
||||
|
||||
def GetString( self ):
|
||||
|
||||
s = 'last run was '
|
||||
s += HydrusData.ConvertTimestampToPrettyAgo( self._last_run )
|
||||
s += ', will next run in '
|
||||
|
||||
if self.IsFailureDelaying():
|
||||
|
||||
s += HydrusData.ConvertTimestampToPrettyPending( max( self.GetDue(), self._failure_delay_timestamp ) )
|
||||
s += ', which may be slightly delayed because of an error'
|
||||
|
||||
else:
|
||||
|
||||
s += HydrusData.ConvertTimestampToPrettyPending( self.GetDue() )
|
||||
|
||||
|
||||
return s
|
||||
|
||||
|
||||
def GetPeriodics( self ):
|
||||
|
||||
return ( self._wavelength, self._multiplier, self._phase )
|
||||
|
||||
|
||||
def IsDue( self ):
|
||||
|
||||
return HydrusData.GetNow() > self.GetDue()
|
||||
|
||||
|
||||
def IsFailureDelaying( self ):
|
||||
|
||||
if self._failure_delay_timestamp is None:
|
||||
|
||||
return False
|
||||
|
||||
else:
|
||||
|
||||
return HydrusData.GetNow() > self._failure_delay_timestamp
|
||||
|
||||
|
||||
|
||||
def IsPaused( self ): return self._paused
|
||||
|
||||
def IsReadyToRun( self ):
|
||||
|
||||
if self.IsPaused(): return False
|
||||
|
||||
if not self.IsDue(): return False
|
||||
|
||||
if self.IsFailureDelaying(): return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def Pause( self ):
|
||||
|
||||
self._paused = True
|
||||
|
||||
|
||||
def ReportError( self, delay ):
|
||||
|
||||
self._failure_delay_timestamp = HydrusData.GetNow() + delay
|
||||
|
||||
|
||||
def ReportRun( self ):
|
||||
|
||||
self._last_run = HydrusData.GetNow()
|
||||
|
||||
|
||||
def Reset( self ):
|
||||
|
||||
self._last_run = 0
|
||||
self._failure_delay_timestamp = None
|
||||
self._paused = False
|
||||
|
||||
|
||||
def Resume( self ):
|
||||
|
||||
self.paused = False
|
||||
|
||||
|
||||
def SetPeriodics( self, wavelength, multiplier, phase ):
|
||||
|
||||
self._wavelength = wavelength
|
||||
self._multiplier = multiplier
|
||||
self._phase = phase
|
||||
|
||||
|
||||
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_PERIODIC ] = Periodic
|
||||
|
||||
class Service( HydrusData.HydrusYAMLBase ):
|
||||
|
||||
yaml_tag = u'!Service'
|
||||
|
@ -1123,6 +1400,7 @@ class ServicesManager( object ):
|
|||
|
||||
self._lock = threading.Lock()
|
||||
self._keys_to_services = {}
|
||||
self._services_sorted = []
|
||||
|
||||
self.RefreshServices()
|
||||
|
||||
|
@ -1140,7 +1418,7 @@ class ServicesManager( object ):
|
|||
|
||||
def GetServices( self, types = HC.ALL_SERVICES ):
|
||||
|
||||
with self._lock: return [ service for service in self._keys_to_services.values() if service.GetServiceType() in types ]
|
||||
with self._lock: return [ service for service in self._services_sorted if service.GetServiceType() in types ]
|
||||
|
||||
|
||||
def RefreshServices( self ):
|
||||
|
@ -1151,6 +1429,11 @@ class ServicesManager( object ):
|
|||
|
||||
self._keys_to_services = { service.GetServiceKey() : service for service in services }
|
||||
|
||||
compare_function = lambda a, b: cmp( a.GetName(), b.GetName() )
|
||||
|
||||
self._services_sorted = list( services )
|
||||
self._services_sorted.sort( cmp = compare_function )
|
||||
|
||||
|
||||
|
||||
class Shortcuts( HydrusSerialisable.SerialisableBaseNamed ):
|
||||
|
@ -1312,6 +1595,32 @@ class Shortcuts( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_SHORTCUTS ] = Shortcuts
|
||||
|
||||
class Subscription( HydrusSerialisable.SerialisableBaseNamed ):
|
||||
|
||||
SERIALISABLE_TYPE = HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION
|
||||
VERSION = 1
|
||||
|
||||
def __init__( self, name ):
|
||||
|
||||
HydrusSerialisable.SerialisableBaseNamed.__init__( self, name )
|
||||
|
||||
self._gallery_query = None
|
||||
self._periodic_info = None # include last checked and paused
|
||||
self._url_cache = []
|
||||
|
||||
|
||||
def _GetSerialisableInfo( self ):
|
||||
|
||||
return ( serialisable_mouse_actions, serialisable_keyboard_actions )
|
||||
|
||||
|
||||
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
|
||||
|
||||
( serialisable_mouse_actions, serialisable_keyboard_actions ) = serialisable_info
|
||||
|
||||
|
||||
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION ] = Subscription
|
||||
|
||||
class UndoManager( object ):
|
||||
|
||||
def __init__( self ):
|
||||
|
@ -1520,7 +1829,9 @@ def GetDefaultAdvancedTagOptions( lookup ):
|
|||
if site_type == HC.SITE_TYPE_BOORU: backup_lookup = HC.SITE_TYPE_BOORU
|
||||
|
||||
|
||||
ato_options = HC.options[ 'default_advanced_tag_options' ]
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
ato_options = options[ 'default_advanced_tag_options' ]
|
||||
|
||||
if lookup in ato_options: ato = ato_options[ lookup ]
|
||||
elif backup_lookup is not None and backup_lookup in ato_options: ato = ato_options[ backup_lookup ]
|
||||
|
|
|
@ -7,6 +7,7 @@ import dircache
|
|||
import itertools
|
||||
import ClientData
|
||||
import ClientConstants
|
||||
import wx
|
||||
|
||||
def GetAllFileHashes():
|
||||
|
||||
|
@ -203,7 +204,9 @@ def GetThumbnailPath( hash, full_size = True ):
|
|||
|
||||
full_size_path = GetThumbnailPath( hash, True )
|
||||
|
||||
thumbnail_dimensions = HC.options[ 'thumbnail_dimensions' ]
|
||||
options = wx.GetApp().GetOptions()
|
||||
|
||||
thumbnail_dimensions = options[ 'thumbnail_dimensions' ]
|
||||
|
||||
thumbnail_resized = HydrusFileHandling.GenerateThumbnail( full_size_path, thumbnail_dimensions )
|
||||
|
||||
|
|
|
@ -696,13 +696,16 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
|||
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'backup_database' ), p( 'Create Database Backup' ), p( 'Back the database up to an external location.' ) )
|
||||
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'restore_database' ), p( 'Restore Database Backup' ), p( 'Restore the database from an external location.' ) )
|
||||
menu.AppendSeparator()
|
||||
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'vacuum_db' ), p( '&Vacuum' ), p( 'Rebuild the Database.' ) )
|
||||
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'delete_orphans' ), p( '&Delete Orphan Files' ), p( 'Go through the client\'s file store, deleting any files that are no longer needed.' ) )
|
||||
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'delete_service_info' ), p( '&Clear Service Info Cache' ), p( 'Delete all cache service info, in case it has become desynchronised.' ) )
|
||||
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'regenerate_thumbnails' ), p( '&Regenerate All Thumbnails' ), p( 'Delete all thumbnails and regenerate from original files.' ) )
|
||||
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'file_integrity' ), p( '&Check File Integrity' ), p( 'Review and fix all local file records.' ) )
|
||||
menu.AppendSeparator()
|
||||
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'clear_caches' ), p( '&Clear Caches' ), p( 'Fully clear the fullscreen, preview and thumbnail caches.' ) )
|
||||
|
||||
submenu = wx.Menu()
|
||||
|
||||
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'vacuum_db' ), p( '&Vacuum' ), p( 'Rebuild the Database.' ) )
|
||||
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'delete_orphans' ), p( '&Delete Orphan Files' ), p( 'Go through the client\'s file store, deleting any files that are no longer needed.' ) )
|
||||
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'delete_service_info' ), p( '&Clear Service Info Cache' ), p( 'Delete all cache service info, in case it has become desynchronised.' ) )
|
||||
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'regenerate_thumbnails' ), p( '&Regenerate All Thumbnails' ), p( 'Delete all thumbnails and regenerate from original files.' ) )
|
||||
submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'file_integrity' ), p( '&Check File Integrity' ), p( 'Review and fix all local file records.' ) )
|
||||
|
||||
menu.AppendMenu( CC.ID_NULL, p( '&Maintenance' ), submenu )
|
||||
|
||||
return ( menu, p( '&Database' ), True )
|
||||
|
||||
|
@ -898,6 +901,8 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
|||
debug.AppendCheckItem( db_profile_mode_id, p( '&DB Profile Mode' ) )
|
||||
debug.Check( db_profile_mode_id, HydrusGlobals.db_profile_mode )
|
||||
debug.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'debug_garbage' ), p( 'Garbage' ) )
|
||||
debug.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'clear_caches' ), p( '&Clear Caches' ) )
|
||||
|
||||
|
||||
menu.AppendMenu( wx.ID_NONE, p( 'Debug' ), debug )
|
||||
menu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'help_shortcuts' ), p( '&Shortcuts' ) )
|
||||
|
@ -1285,7 +1290,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
|||
HydrusGlobals.pubsub.pub( 'notify_restart_import_folders_daemon' )
|
||||
|
||||
|
||||
try: wx.GetApp().Write( 'save_options' )
|
||||
try: wx.GetApp().Write( 'save_options', HC.options )
|
||||
except: wx.MessageBox( traceback.format_exc() )
|
||||
|
||||
|
||||
|
@ -2200,7 +2205,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
( HC.options[ 'hpos' ], HC.options[ 'vpos' ] ) = page.GetSashPositions()
|
||||
|
||||
|
||||
wx.GetApp().Write( 'save_options' )
|
||||
wx.GetApp().Write( 'save_options', HC.options )
|
||||
|
||||
self._SaveGUISession( 'last session' )
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import ClientGUICommon
|
|||
import ClientGUIDialogs
|
||||
import ClientGUIDialogsManage
|
||||
import ClientMedia
|
||||
import ClientRatings
|
||||
import collections
|
||||
import gc
|
||||
import HydrusImageHandling
|
||||
|
@ -586,9 +587,7 @@ class Canvas( object ):
|
|||
|
||||
if self._current_media is not None:
|
||||
|
||||
try:
|
||||
with ClientGUIDialogsManage.DialogManageRatings( self, ( self._current_media, ) ) as dlg: dlg.ShowModal()
|
||||
except: wx.MessageBox( 'Had a problem displaying the manage ratings dialog from fullscreen.' )
|
||||
with ClientGUIDialogsManage.DialogManageRatings( self, ( self._current_media, ) ) as dlg: dlg.ShowModal()
|
||||
|
||||
|
||||
|
||||
|
@ -900,6 +899,10 @@ class CanvasWithDetails( Canvas ):
|
|||
self._hover_commands = FullscreenHoverFrameCommands( self, self._canvas_key )
|
||||
self._hover_tags = FullscreenHoverFrameTags( self, self._canvas_key )
|
||||
|
||||
ratings_services = wx.GetApp().GetManager( 'services' ).GetServices( ( HC.RATINGS_SERVICES ) )
|
||||
|
||||
if len( ratings_services ) > 0: self._hover_ratings = FullscreenHoverFrameRatings( self, self._canvas_key )
|
||||
|
||||
|
||||
def _DrawBackgroundDetails( self, dc ):
|
||||
|
||||
|
@ -951,6 +954,10 @@ class CanvasWithDetails( Canvas ):
|
|||
|
||||
dc.SetTextForeground( wx.Colour( *HC.options[ 'gui_colours' ][ 'media_text' ] ) )
|
||||
|
||||
# top right
|
||||
|
||||
current_y = 2
|
||||
|
||||
# icons
|
||||
|
||||
icons_to_show = []
|
||||
|
@ -978,12 +985,37 @@ class CanvasWithDetails( Canvas ):
|
|||
current_x -= 20
|
||||
|
||||
|
||||
# top right
|
||||
if len( icons_to_show ) > 0: current_y += 18
|
||||
|
||||
# ratings
|
||||
|
||||
top_right_strings = []
|
||||
|
||||
( local_ratings, remote_ratings ) = self._current_display_media.GetRatings()
|
||||
|
||||
services_manager = wx.GetApp().GetManager( 'services' )
|
||||
|
||||
like_services = services_manager.GetServices( ( HC.LOCAL_RATING_LIKE, ) )
|
||||
|
||||
like_services.reverse()
|
||||
|
||||
like_rating_current_x = client_width - 16
|
||||
|
||||
for like_service in like_services:
|
||||
|
||||
service_key = like_service.GetServiceKey()
|
||||
|
||||
rating_state = ClientRatings.GetLikeStateFromMedia( ( self._current_display_media, ), service_key )
|
||||
|
||||
( pen_colour, brush_colour ) = ClientRatings.GetPenAndBrushColours( service_key, rating_state )
|
||||
|
||||
ClientRatings.DrawLike( dc, like_rating_current_x, current_y, pen_colour, brush_colour )
|
||||
|
||||
like_rating_current_x -= 16
|
||||
|
||||
|
||||
if len( like_services ) > 0: current_y += 16
|
||||
|
||||
service_keys_to_ratings = local_ratings.GetServiceKeysToRatings()
|
||||
|
||||
for ( service_key, rating ) in service_keys_to_ratings.items():
|
||||
|
@ -1001,29 +1033,18 @@ class CanvasWithDetails( Canvas ):
|
|||
|
||||
service_type = service.GetServiceType()
|
||||
|
||||
if service_type == HC.LOCAL_RATING_LIKE:
|
||||
|
||||
( like, dislike ) = service.GetLikeDislike()
|
||||
|
||||
if rating == 1: s = like
|
||||
elif rating == 0: s = dislike
|
||||
|
||||
elif service_type == HC.LOCAL_RATING_NUMERICAL:
|
||||
if service_type == HC.LOCAL_RATING_NUMERICAL:
|
||||
|
||||
( lower, upper ) = service.GetLowerUpper()
|
||||
|
||||
s = HydrusData.ConvertNumericalRatingToPrettyString( lower, upper, rating )
|
||||
|
||||
|
||||
top_right_strings.append( s )
|
||||
top_right_strings.append( s )
|
||||
|
||||
|
||||
|
||||
if len( top_right_strings ) > 0:
|
||||
|
||||
current_y = 3
|
||||
|
||||
if len( icons_to_show ) > 0: current_y += 16
|
||||
|
||||
for s in top_right_strings:
|
||||
|
||||
( x, y ) = dc.GetTextExtent( s )
|
||||
|
@ -1034,6 +1055,8 @@ class CanvasWithDetails( Canvas ):
|
|||
|
||||
|
||||
|
||||
# middle
|
||||
|
||||
current_y = 3
|
||||
|
||||
title_string = self._current_display_media.GetTitleString()
|
||||
|
@ -2674,7 +2697,7 @@ class FullscreenHoverFrameCommands( FullscreenHoverFrame ):
|
|||
|
||||
( my_width, my_height ) = self.GetClientSize()
|
||||
|
||||
my_ideal_width = parent_width * 0.6
|
||||
my_ideal_width = int( parent_width * 0.6 )
|
||||
|
||||
if my_height != parent_height or my_ideal_width != my_width:
|
||||
|
||||
|
@ -2683,9 +2706,7 @@ class FullscreenHoverFrameCommands( FullscreenHoverFrame ):
|
|||
self.SetSize( ( my_ideal_width, -1 ) )
|
||||
|
||||
|
||||
x = ( parent_width - my_ideal_width ) / 2
|
||||
|
||||
self.SetPosition( parent.ClientToScreenXY( x, 0 ) )
|
||||
self.SetPosition( parent.ClientToScreenXY( int( parent_width * 0.2 ), 0 ) )
|
||||
|
||||
|
||||
def AddCommand( self, label, callback ):
|
||||
|
@ -2798,6 +2819,129 @@ class FullscreenHoverFrameCommands( FullscreenHoverFrame ):
|
|||
|
||||
|
||||
|
||||
class FullscreenHoverFrameRatings( FullscreenHoverFrame ):
|
||||
|
||||
def __init__( self, parent, canvas_key ):
|
||||
|
||||
FullscreenHoverFrame.__init__( self, parent, canvas_key )
|
||||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
self._icon_panel = wx.Panel( self )
|
||||
|
||||
self._inbox_icon = ClientGUICommon.BufferedWindowIcon( self._icon_panel, CC.GlobalBMPs.inbox_bmp )
|
||||
|
||||
icon_hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
icon_hbox.AddF( ( 16, 16 ), CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
|
||||
icon_hbox.AddF( self._inbox_icon, CC.FLAGS_MIXED )
|
||||
|
||||
self._icon_panel.SetSizer( icon_hbox )
|
||||
|
||||
like_hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
like_hbox.AddF( ( 16, 16 ), CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
like_services = wx.GetApp().GetManager( 'services' ).GetServices( ( HC.LOCAL_RATING_LIKE, ) )
|
||||
|
||||
for service in like_services:
|
||||
|
||||
service_key = service.GetServiceKey()
|
||||
|
||||
control = ClientGUICommon.RatingLikeCanvas( self, service_key, canvas_key )
|
||||
|
||||
like_hbox.AddF( control, CC.FLAGS_NONE )
|
||||
|
||||
|
||||
# each numerical one in turn
|
||||
|
||||
vbox.AddF( self._icon_panel, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
|
||||
vbox.AddF( ( 1, 2 ), CC.FLAGS_NONE )
|
||||
vbox.AddF( like_hbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
|
||||
|
||||
self.SetSizer( vbox )
|
||||
|
||||
self._ShowHideIcons()
|
||||
|
||||
HydrusGlobals.pubsub.sub( self, 'ProcessContentUpdates', 'content_updates_gui' )
|
||||
|
||||
|
||||
def _ShowHideIcons( self ):
|
||||
|
||||
if self._current_media is not None:
|
||||
|
||||
if self._current_media.HasInbox():
|
||||
|
||||
self._icon_panel.Show()
|
||||
|
||||
else:
|
||||
|
||||
self._icon_panel.Hide()
|
||||
|
||||
|
||||
self.Fit()
|
||||
|
||||
|
||||
self._SizeAndPosition()
|
||||
|
||||
|
||||
def _SizeAndPosition( self ):
|
||||
|
||||
parent = self.GetParent()
|
||||
|
||||
( parent_width, parent_height ) = parent.GetClientSize()
|
||||
|
||||
( my_width, my_height ) = self.GetClientSize()
|
||||
|
||||
my_ideal_width = int( parent_width * 0.2 )
|
||||
|
||||
my_ideal_height = my_height
|
||||
|
||||
if my_ideal_width != my_width or my_ideal_height != my_height:
|
||||
|
||||
self.Fit()
|
||||
|
||||
self.SetSize( ( my_ideal_width, -1 ) )
|
||||
|
||||
|
||||
self.SetPosition( parent.ClientToScreenXY( int( parent_width * 0.8 ), 0 ) )
|
||||
|
||||
|
||||
def ProcessContentUpdates( self, service_keys_to_content_updates ):
|
||||
|
||||
if self._current_media is not None:
|
||||
|
||||
my_hash = self._current_media.GetHash()
|
||||
|
||||
do_redraw = False
|
||||
|
||||
for ( service_key, content_updates ) in service_keys_to_content_updates.items():
|
||||
|
||||
if True in ( my_hash in content_update.GetHashes() for content_update in content_updates ):
|
||||
|
||||
do_redraw = True
|
||||
|
||||
break
|
||||
|
||||
|
||||
|
||||
if do_redraw:
|
||||
|
||||
self._ShowHideIcons()
|
||||
|
||||
|
||||
|
||||
|
||||
def SetDisplayMedia( self, canvas_key, media ):
|
||||
|
||||
if canvas_key == self._canvas_key:
|
||||
|
||||
FullscreenHoverFrame.SetDisplayMedia( self, canvas_key, media )
|
||||
|
||||
self._ShowHideIcons()
|
||||
|
||||
|
||||
|
||||
class FullscreenHoverFrameTags( FullscreenHoverFrame ):
|
||||
|
||||
def __init__( self, parent, canvas_key ):
|
||||
|
@ -2812,7 +2956,6 @@ class FullscreenHoverFrameTags( FullscreenHoverFrame ):
|
|||
|
||||
self.SetSizer( vbox )
|
||||
|
||||
HydrusGlobals.pubsub.sub( self, 'SetDisplayMedia', 'canvas_new_display_media' )
|
||||
HydrusGlobals.pubsub.sub( self, 'ProcessContentUpdates', 'content_updates_gui' )
|
||||
|
||||
|
||||
|
@ -2844,7 +2987,7 @@ class FullscreenHoverFrameTags( FullscreenHoverFrame ):
|
|||
|
||||
( my_width, my_height ) = self.GetClientSize()
|
||||
|
||||
my_ideal_width = parent_width / 5
|
||||
my_ideal_width = int( parent_width * 0.2 )
|
||||
|
||||
my_ideal_height = parent_height
|
||||
|
||||
|
@ -3166,7 +3309,7 @@ class FullscreenPopoutFilterNumerical( FullscreenPopout ):
|
|||
|
||||
HC.options[ 'ratings_filter_accuracy' ] = 1
|
||||
|
||||
wx.GetApp().Write( 'save_options' )
|
||||
wx.GetApp().Write( 'save_options', HC.options )
|
||||
|
||||
|
||||
value = HC.options[ 'ratings_filter_accuracy' ]
|
||||
|
@ -3186,7 +3329,7 @@ class FullscreenPopoutFilterNumerical( FullscreenPopout ):
|
|||
|
||||
HC.options[ 'ratings_filter_compare_same' ] = False
|
||||
|
||||
wx.GetApp().Write( 'save_options' )
|
||||
wx.GetApp().Write( 'save_options', HC.options )
|
||||
|
||||
|
||||
compare_same = HC.options[ 'ratings_filter_compare_same' ]
|
||||
|
@ -3205,7 +3348,7 @@ class FullscreenPopoutFilterNumerical( FullscreenPopout ):
|
|||
|
||||
HC.options[ 'ratings_filter_left_right' ] = 'left'
|
||||
|
||||
wx.GetApp().Write( 'save_options' )
|
||||
wx.GetApp().Write( 'save_options', HC.options )
|
||||
|
||||
|
||||
left_right = HC.options[ 'ratings_filter_left_right' ]
|
||||
|
@ -4013,14 +4156,14 @@ class RatingsFilterFrameNumerical( ClientGUICommon.FrameThatResizes ):
|
|||
|
||||
HC.options[ 'ratings_filter_accuracy' ] = accuracy
|
||||
|
||||
wx.GetApp().Write( 'save_options' )
|
||||
wx.GetApp().Write( 'save_options', HC.options )
|
||||
|
||||
|
||||
def SetCompareSame( self, compare_same ):
|
||||
|
||||
HC.options[ 'ratings_filter_compare_same' ] = compare_same
|
||||
|
||||
wx.GetApp().Write( 'save_options' )
|
||||
wx.GetApp().Write( 'save_options', HC.options )
|
||||
|
||||
self._compare_same = compare_same
|
||||
|
||||
|
@ -4029,7 +4172,7 @@ class RatingsFilterFrameNumerical( ClientGUICommon.FrameThatResizes ):
|
|||
|
||||
HC.options[ 'ratings_filter_left_right' ] = left_right
|
||||
|
||||
wx.GetApp().Write( 'save_options' )
|
||||
wx.GetApp().Write( 'save_options', HC.options )
|
||||
|
||||
self._left_right = left_right
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import HydrusConstants as HC
|
|||
import ClientCaches
|
||||
import ClientData
|
||||
import ClientConstants as CC
|
||||
import ClientRatings
|
||||
import itertools
|
||||
import os
|
||||
import random
|
||||
|
@ -949,7 +950,6 @@ class BufferedWindow( wx.Window ):
|
|||
self.Bind( wx.EVT_SIZE, self.EventResize )
|
||||
self.Bind( wx.EVT_ERASE_BACKGROUND, self.EventEraseBackground )
|
||||
|
||||
|
||||
|
||||
def GetDC( self ): return wx.BufferedDC( wx.ClientDC( self ), self._canvas_bmp )
|
||||
|
||||
|
@ -966,6 +966,25 @@ class BufferedWindow( wx.Window ):
|
|||
if my_width != current_bmp_width or my_height != current_bmp_height: self._canvas_bmp = wx.EmptyBitmap( my_width, my_height, 24 )
|
||||
|
||||
|
||||
class BufferedWindowIcon( BufferedWindow ):
|
||||
|
||||
def __init__( self, parent, bmp ):
|
||||
|
||||
BufferedWindow.__init__( self, parent, size = bmp.GetSize() )
|
||||
|
||||
self._bmp = bmp
|
||||
|
||||
dc = self.GetDC()
|
||||
|
||||
background_colour = self.GetParent().GetBackgroundColour()
|
||||
|
||||
dc.SetBackground( wx.Brush( background_colour ) )
|
||||
|
||||
dc.Clear()
|
||||
|
||||
dc.DrawBitmap( bmp, 0, 0 )
|
||||
|
||||
|
||||
class BetterChoice( wx.Choice ):
|
||||
|
||||
def GetChoice( self ):
|
||||
|
@ -1617,7 +1636,9 @@ class ListBook( wx.Panel ):
|
|||
|
||||
def GetNameToPageDict( self ):
|
||||
|
||||
return self._names_to_pages
|
||||
result = { name : page_info for ( name, page_info ) in self._names_to_pages.items() if type( page_info ) != tuple }
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def NameExists( self, name, panel = None ): return self._list_box.FindString( name ) != wx.NOT_FOUND
|
||||
|
@ -3834,6 +3855,218 @@ class PopupMessageManager( wx.Frame ):
|
|||
self._SizeAndPositionAndShow()
|
||||
|
||||
|
||||
class RatingLike( wx.Window ):
|
||||
|
||||
def __init__( self, parent, service_key ):
|
||||
|
||||
wx.Window.__init__( self, parent )
|
||||
|
||||
self._service_key = service_key
|
||||
|
||||
self._canvas_bmp = wx.EmptyBitmap( 16, 16, 24 )
|
||||
|
||||
self.Bind( wx.EVT_PAINT, self.EventPaint )
|
||||
self.Bind( wx.EVT_ERASE_BACKGROUND, self.EventEraseBackground )
|
||||
|
||||
self.Bind( wx.EVT_LEFT_DOWN, self.EventLeftDown )
|
||||
self.Bind( wx.EVT_LEFT_DCLICK, self.EventLeftDown )
|
||||
self.Bind( wx.EVT_RIGHT_DOWN, self.EventRightDown )
|
||||
self.Bind( wx.EVT_RIGHT_DCLICK, self.EventRightDown )
|
||||
|
||||
self.SetMinSize( ( 16, 16 ) )
|
||||
|
||||
self._dirty = True
|
||||
|
||||
|
||||
def _Draw( self ):
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def GetDC( self ): return wx.BufferedDC( wx.ClientDC( self ), self._canvas_bmp )
|
||||
|
||||
def EventEraseBackground( self, event ): pass
|
||||
|
||||
def EventLeftDown( self, event ):
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def EventPaint( self, event ):
|
||||
|
||||
if self._dirty:
|
||||
|
||||
self._Draw()
|
||||
|
||||
|
||||
wx.BufferedPaintDC( self, self._canvas_bmp )
|
||||
|
||||
|
||||
def EventRightDown( self, event ):
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class RatingLikeDialog( RatingLike ):
|
||||
|
||||
def __init__( self, parent, service_key ):
|
||||
|
||||
RatingLike.__init__( self, parent, service_key )
|
||||
|
||||
self._rating_state = ClientRatings.ALL_NULL
|
||||
|
||||
|
||||
def _Draw( self ):
|
||||
|
||||
dc = self.GetDC()
|
||||
|
||||
dc.SetBackground( wx.Brush( self.GetParent().GetBackgroundColour() ) )
|
||||
|
||||
dc.Clear()
|
||||
|
||||
( pen_colour, brush_colour ) = ClientRatings.GetPenAndBrushColours( self._service_key, self._rating_state )
|
||||
|
||||
ClientRatings.DrawLike( dc, 0, 0, pen_colour, brush_colour )
|
||||
|
||||
self._dirty = False
|
||||
|
||||
|
||||
def EventLeftDown( self, event ):
|
||||
|
||||
if self._rating_state == ClientRatings.ALL_ON: self._rating_state = ClientRatings.ALL_NULL
|
||||
else: self._rating_state = ClientRatings.ALL_ON
|
||||
|
||||
self._dirty = True
|
||||
|
||||
self.Refresh()
|
||||
|
||||
|
||||
def EventRightDown( self, event ):
|
||||
|
||||
if self._rating_state == ClientRatings.ALL_OFF: self._rating_state = ClientRatings.ALL_NULL
|
||||
else: self._rating_state = ClientRatings.ALL_OFF
|
||||
|
||||
self._dirty = True
|
||||
|
||||
self.Refresh()
|
||||
|
||||
|
||||
def GetRatingState( self ):
|
||||
|
||||
return self._rating_state
|
||||
|
||||
|
||||
def SetRatingState( self, rating_state ):
|
||||
|
||||
self._rating_state = rating_state
|
||||
|
||||
|
||||
class RatingLikeCanvas( RatingLike ):
|
||||
|
||||
def __init__( self, parent, service_key, canvas_key ):
|
||||
|
||||
RatingLike.__init__( self, parent, service_key )
|
||||
|
||||
self._canvas_key = canvas_key
|
||||
self._current_media = None
|
||||
self._rating_state = None
|
||||
|
||||
service = wx.GetApp().GetManager( 'services' ).GetService( service_key )
|
||||
|
||||
name = service.GetName()
|
||||
|
||||
self.SetToolTipString( name )
|
||||
|
||||
HydrusGlobals.pubsub.sub( self, 'ProcessContentUpdates', 'content_updates_gui' )
|
||||
HydrusGlobals.pubsub.sub( self, 'SetDisplayMedia', 'canvas_new_display_media' )
|
||||
|
||||
|
||||
def _Draw( self ):
|
||||
|
||||
dc = self.GetDC()
|
||||
|
||||
dc.SetBackground( wx.Brush( self.GetParent().GetBackgroundColour() ) )
|
||||
|
||||
dc.Clear()
|
||||
|
||||
if self._current_media is not None:
|
||||
|
||||
self._rating_state = ClientRatings.GetLikeStateFromMedia( ( self._current_media, ), self._service_key )
|
||||
|
||||
( pen_colour, brush_colour ) = ClientRatings.GetPenAndBrushColours( self._service_key, self._rating_state )
|
||||
|
||||
ClientRatings.DrawLike( dc, 0, 0, pen_colour, brush_colour )
|
||||
|
||||
|
||||
self._dirty = False
|
||||
|
||||
|
||||
def EventLeftDown( self, event ):
|
||||
|
||||
if self._current_media is not None:
|
||||
|
||||
if self._rating_state == ClientRatings.ALL_ON: rating = None
|
||||
else: rating = 1
|
||||
|
||||
content_update = HydrusData.ContentUpdate( HC.CONTENT_DATA_TYPE_RATINGS, HC.CONTENT_UPDATE_ADD, ( rating, self._hashes ) )
|
||||
|
||||
wx.GetApp().Write( 'content_updates', { self._service_key : ( content_update, ) } )
|
||||
|
||||
|
||||
|
||||
def EventRightDown( self, event ):
|
||||
|
||||
if self._current_media is not None:
|
||||
|
||||
if self._rating_state == ClientRatings.ALL_OFF: rating = None
|
||||
else: rating = 0
|
||||
|
||||
content_update = HydrusData.ContentUpdate( HC.CONTENT_DATA_TYPE_RATINGS, HC.CONTENT_UPDATE_ADD, ( rating, self._hashes ) )
|
||||
|
||||
wx.GetApp().Write( 'content_updates', { self._service_key : ( content_update, ) } )
|
||||
|
||||
|
||||
|
||||
def ProcessContentUpdates( self, service_keys_to_content_updates ):
|
||||
|
||||
if self._current_media is not None:
|
||||
|
||||
for ( service_key, content_updates ) in service_keys_to_content_updates.items():
|
||||
|
||||
for content_update in content_updates:
|
||||
|
||||
( data_type, action, row ) = content_update.ToTuple()
|
||||
|
||||
if data_type == HC.CONTENT_DATA_TYPE_RATINGS:
|
||||
|
||||
hashes = content_update.GetHashes()
|
||||
|
||||
if len( self._hashes.intersection( hashes ) ) > 0:
|
||||
|
||||
self._dirty = True
|
||||
|
||||
self.Refresh()
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def SetDisplayMedia( self, canvas_key, media ):
|
||||
|
||||
if canvas_key == self._canvas_key:
|
||||
|
||||
self._current_media = media
|
||||
|
||||
self._hashes = self._current_media.GetHashes()
|
||||
|
||||
self._dirty = True
|
||||
|
||||
|
||||
|
||||
class RegexButton( wx.Button ):
|
||||
|
||||
ID_REGEX_WHITESPACE = 0
|
||||
|
|
|
@ -11,6 +11,7 @@ import ClientGUICommon
|
|||
import ClientGUIDialogs
|
||||
import ClientGUIPredicates
|
||||
import ClientMedia
|
||||
import ClientRatings
|
||||
import collections
|
||||
import HydrusNATPunch
|
||||
import HydrusNetworking
|
||||
|
@ -516,11 +517,6 @@ class DialogManageBoorus( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def EventOK( self, event ):
|
||||
|
||||
for ( name, page ) in self._boorus.GetNameToPageDict().items():
|
||||
|
||||
if page.HasChanges(): self._edit_log.append( ( HC.SET, ( name, page.GetBooru() ) ) )
|
||||
|
||||
|
||||
try:
|
||||
|
||||
for ( action, data ) in self._edit_log:
|
||||
|
@ -539,6 +535,11 @@ class DialogManageBoorus( ClientGUIDialogs.Dialog ):
|
|||
|
||||
|
||||
|
||||
for ( name, page ) in self._boorus.GetNameToPageDict().items():
|
||||
|
||||
if page.HasChanges(): self._edit_log.append( ( HC.SET, ( name, page.GetBooru() ) ) )
|
||||
|
||||
|
||||
finally: self.EndModal( wx.ID_OK )
|
||||
|
||||
|
||||
|
@ -1883,11 +1884,6 @@ class DialogManageImageboards( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def EventOK( self, event ):
|
||||
|
||||
for ( name, page ) in self._sites.GetNameToPageDict().items():
|
||||
|
||||
if page.HasChanges(): self._edit_log.append( ( HC.SET, ( name, page.GetImageboards() ) ) )
|
||||
|
||||
|
||||
try:
|
||||
|
||||
for ( action, data ) in self._edit_log:
|
||||
|
@ -1906,6 +1902,11 @@ class DialogManageImageboards( ClientGUIDialogs.Dialog ):
|
|||
|
||||
|
||||
|
||||
for ( name, page ) in self._sites.GetNameToPageDict().items():
|
||||
|
||||
if page.HasChanges(): self._edit_log.append( ( HC.SET, ( name, page.GetImageboards() ) ) )
|
||||
|
||||
|
||||
finally: self.EndModal( wx.ID_OK )
|
||||
|
||||
|
||||
|
@ -2022,6 +2023,7 @@ class DialogManageImageboards( ClientGUIDialogs.Dialog ):
|
|||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
self._original_imageboards = imageboards
|
||||
self._has_changes = False
|
||||
|
||||
InitialiseControls()
|
||||
|
@ -2099,7 +2101,19 @@ class DialogManageImageboards( ClientGUIDialogs.Dialog ):
|
|||
|
||||
|
||||
|
||||
def GetImageboards( self ): return [ page.GetImageboard() for page in self._imageboards.GetNameToPageDict().values() ]
|
||||
def GetImageboards( self ):
|
||||
|
||||
names_to_imageboards = { imageboard.GetName() : imageboard for imageboard in self._original_imageboards }
|
||||
|
||||
for page in self._imageboards.GetNameToPageDict().values():
|
||||
|
||||
imageboard = page.GetImageboard()
|
||||
|
||||
names_to_imageboards[ imageboard.GetName() ] = imageboard
|
||||
|
||||
|
||||
return names_to_imageboards.values()
|
||||
|
||||
|
||||
def HasChanges( self ): return self._has_changes or True in ( page.HasChanges() for page in self._imageboards.GetNameToPageDict().values() )
|
||||
|
||||
|
@ -3744,7 +3758,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
HC.options[ 'thread_checker_timings' ] = ( self._thread_times_to_check.GetValue(), self._thread_check_period.GetValue() )
|
||||
|
||||
try: wx.GetApp().Write( 'save_options' )
|
||||
try: wx.GetApp().Write( 'save_options', HC.options )
|
||||
except: wx.MessageBox( traceback.format_exc() )
|
||||
|
||||
self.EndModal( wx.ID_OK )
|
||||
|
@ -3938,15 +3952,17 @@ class DialogManageRatings( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def InitialiseControls():
|
||||
|
||||
services = wx.GetApp().GetManager( 'services' ).GetServices( HC.RATINGS_SERVICES )
|
||||
|
||||
# sort according to local/remote, I guess
|
||||
# and maybe sub-sort according to name?
|
||||
# maybe just do two get service_key queries
|
||||
like_services = wx.GetApp().GetManager( 'services' ).GetServices( ( HC.LOCAL_RATING_LIKE, ) )
|
||||
numerical_services = wx.GetApp().GetManager( 'services' ).GetServices( ( HC.LOCAL_RATING_NUMERICAL, ) )
|
||||
|
||||
self._panels = []
|
||||
|
||||
for service in services: self._panels.append( self._Panel( self, service.GetServiceKey(), media ) )
|
||||
if len( like_services ) > 0:
|
||||
|
||||
self._panels.append( self._LikePanel( self, like_services, media ) )
|
||||
|
||||
|
||||
for service in numerical_services: self._panels.append( self._NumericalPanel( self, service.GetServiceKey(), media ) )
|
||||
|
||||
self._apply = wx.Button( self, id = wx.ID_OK, label = 'apply' )
|
||||
self._apply.Bind( wx.EVT_BUTTON, self.EventOK )
|
||||
|
@ -3977,7 +3993,7 @@ class DialogManageRatings( ClientGUIDialogs.Dialog ):
|
|||
|
||||
( x, y ) = self.GetEffectiveMinSize()
|
||||
|
||||
self.SetInitialSize( ( x + 200, y ) )
|
||||
self.SetInitialSize( ( x, y ) )
|
||||
|
||||
|
||||
self._hashes = set()
|
||||
|
@ -4021,9 +4037,9 @@ class DialogManageRatings( ClientGUIDialogs.Dialog ):
|
|||
|
||||
if panel.HasChanges():
|
||||
|
||||
( service_key, content_updates ) = panel.GetContentUpdates()
|
||||
sub_service_keys_to_content_updates = panel.GetContentUpdates()
|
||||
|
||||
service_keys_to_content_updates[ service_key ] = content_updates
|
||||
service_keys_to_content_updates.update( sub_service_keys_to_content_updates )
|
||||
|
||||
|
||||
|
||||
|
@ -4043,7 +4059,90 @@ class DialogManageRatings( ClientGUIDialogs.Dialog ):
|
|||
self.SetAcceleratorTable( wx.AcceleratorTable( entries ) )
|
||||
|
||||
|
||||
class _Panel( wx.Panel ):
|
||||
class _LikePanel( wx.Panel ):
|
||||
|
||||
def __init__( self, parent, services, media ):
|
||||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
|
||||
|
||||
self._services = services
|
||||
|
||||
self._media = media
|
||||
|
||||
self._service_keys_to_controls = {}
|
||||
self._service_keys_to_original_ratings_states = {}
|
||||
|
||||
gridbox = wx.FlexGridSizer( 0, 2 )
|
||||
|
||||
gridbox.AddGrowableCol( 0, 1 )
|
||||
|
||||
for service in self._services:
|
||||
|
||||
name = service.GetName()
|
||||
|
||||
service_key = service.GetServiceKey()
|
||||
|
||||
rating_state = ClientRatings.GetLikeStateFromMedia( self._media, service_key )
|
||||
|
||||
control = ClientGUICommon.RatingLikeDialog( self, service_key )
|
||||
|
||||
control.SetRatingState( rating_state )
|
||||
|
||||
self._service_keys_to_controls[ service_key ] = control
|
||||
self._service_keys_to_original_ratings_states[ service_key ] = rating_state
|
||||
|
||||
gridbox.AddF( wx.StaticText( self, label = name ), CC.FLAGS_MIXED )
|
||||
gridbox.AddF( control, CC.FLAGS_MIXED )
|
||||
|
||||
|
||||
self.SetSizer( gridbox )
|
||||
|
||||
|
||||
def GetContentUpdates( self ):
|
||||
|
||||
service_keys_to_content_updates = {}
|
||||
|
||||
hashes = { hash for hash in itertools.chain.from_iterable( ( media.GetHashes() for media in self._media ) ) }
|
||||
|
||||
for ( service_key, control ) in self._service_keys_to_controls.items():
|
||||
|
||||
original_rating_state = self._service_keys_to_original_ratings_states[ service_key ]
|
||||
|
||||
rating_state = control.GetRatingState()
|
||||
|
||||
if rating_state != original_rating_state:
|
||||
|
||||
if rating_state == ClientRatings.ALL_ON: rating = 1
|
||||
elif rating_state == ClientRatings.ALL_OFF: rating = 0
|
||||
else: rating = None
|
||||
|
||||
content_update = HydrusData.ContentUpdate( HC.CONTENT_DATA_TYPE_RATINGS, HC.CONTENT_UPDATE_ADD, ( rating, hashes ) )
|
||||
|
||||
service_keys_to_content_updates[ service_key ] = ( content_update, )
|
||||
|
||||
|
||||
|
||||
return service_keys_to_content_updates
|
||||
|
||||
|
||||
def HasChanges( self ):
|
||||
|
||||
for ( service_key, control ) in self._service_keys_to_controls.items():
|
||||
|
||||
original_rating_state = self._service_keys_to_original_ratings_states[ service_key ]
|
||||
|
||||
rating_state = control.GetRatingState()
|
||||
|
||||
if rating_state != original_rating_state: return True
|
||||
|
||||
|
||||
return False
|
||||
|
||||
|
||||
|
||||
class _NumericalPanel( wx.Panel ):
|
||||
|
||||
def __init__( self, parent, service_key, media ):
|
||||
|
||||
|
@ -4299,7 +4398,7 @@ class DialogManageRatings( ClientGUIDialogs.Dialog ):
|
|||
|
||||
content_update = HydrusData.ContentUpdate( HC.CONTENT_DATA_TYPE_RATINGS, HC.CONTENT_UPDATE_ADD, ( rating, hashes ) )
|
||||
|
||||
return ( self._service_key, [ content_update ] )
|
||||
return { self._service_key : ( content_update, ) }
|
||||
|
||||
|
||||
def HasChanges( self ):
|
||||
|
@ -5626,7 +5725,6 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
def InitialiseControls():
|
||||
|
||||
self._listbook = ClientGUICommon.ListBook( self )
|
||||
self._listbook.Bind( wx.EVT_NOTEBOOK_PAGE_CHANGING, self.EventPageChanging )
|
||||
|
||||
self._add = wx.Button( self, label = 'add' )
|
||||
self._add.Bind( wx.EVT_BUTTON, self.EventAdd )
|
||||
|
@ -5697,24 +5795,6 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
wx.CallAfter( self._ok.SetFocus )
|
||||
|
||||
|
||||
def _CheckCurrentSubscriptionIsValid( self ):
|
||||
|
||||
panel = self._listbook.GetCurrentPage()
|
||||
|
||||
if panel is not None:
|
||||
|
||||
name = panel.GetName()
|
||||
old_name = self._listbook.GetCurrentName()
|
||||
|
||||
if old_name is not None and name != old_name:
|
||||
|
||||
if self._listbook.NameExists( name ): raise Exception( 'That name is already in use!' )
|
||||
|
||||
self._listbook.RenamePage( old_name, name )
|
||||
|
||||
|
||||
|
||||
|
||||
def EventAdd( self, event ):
|
||||
|
||||
with ClientGUIDialogs.DialogTextEntry( self, 'Enter name for subscription.' ) as dlg:
|
||||
|
@ -5745,14 +5825,6 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def EventExport( self, event ):
|
||||
|
||||
try: self._CheckCurrentSubscriptionIsValid()
|
||||
except Exception as e:
|
||||
|
||||
wx.MessageBox( HydrusData.ToString( e ) )
|
||||
|
||||
return
|
||||
|
||||
|
||||
panel = self._listbook.GetCurrentPage()
|
||||
|
||||
if panel is not None:
|
||||
|
@ -5784,14 +5856,6 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def EventOK( self, event ):
|
||||
|
||||
try: self._CheckCurrentSubscriptionIsValid()
|
||||
except Exception as e:
|
||||
|
||||
wx.MessageBox( HydrusData.ToString( e ) )
|
||||
|
||||
return
|
||||
|
||||
|
||||
all_pages = self._listbook.GetNameToPageDict().values()
|
||||
|
||||
try:
|
||||
|
@ -5802,10 +5866,6 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
( name, info ) = page.GetSubscription()
|
||||
|
||||
original_name = page.GetOriginalName()
|
||||
|
||||
if original_name != name: wx.GetApp().Write( 'delete_subscription', original_name )
|
||||
|
||||
wx.GetApp().Write( 'subscription', name, info )
|
||||
|
||||
|
||||
|
@ -5816,38 +5876,17 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
finally: self.EndModal( wx.ID_OK )
|
||||
|
||||
|
||||
def EventPageChanging( self, event ):
|
||||
|
||||
try: self._CheckCurrentSubscriptionIsValid()
|
||||
except Exception as e:
|
||||
|
||||
wx.MessageBox( HydrusData.ToString( e ) )
|
||||
|
||||
event.Veto()
|
||||
|
||||
|
||||
|
||||
def EventRemove( self, event ):
|
||||
|
||||
panel = self._listbook.GetCurrentPage()
|
||||
|
||||
name = panel.GetOriginalName()
|
||||
name = self._listbook.GetCurrentName()
|
||||
|
||||
self._names_to_delete.add( name )
|
||||
|
||||
if panel is not None: self._listbook.DeleteCurrentPage()
|
||||
self._listbook.DeleteCurrentPage()
|
||||
|
||||
|
||||
def Import( self, paths ):
|
||||
|
||||
try: self._CheckCurrentSubscriptionIsValid()
|
||||
except Exception as e:
|
||||
|
||||
wx.MessageBox( HydrusData.ToString( e ) )
|
||||
|
||||
return
|
||||
|
||||
|
||||
for path in paths:
|
||||
|
||||
try:
|
||||
|
@ -5864,15 +5903,19 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
if dlg.ShowModal() == wx.ID_YES:
|
||||
|
||||
self._listbook.Select( name )
|
||||
|
||||
page = self._listbook.GetNameToPageDict()[ name ]
|
||||
|
||||
page.Update( name, info )
|
||||
page.Update( info )
|
||||
|
||||
|
||||
|
||||
else:
|
||||
|
||||
page = self._Panel( self._listbook, name, info )
|
||||
page = self._Panel( self._listbook, name, new_subscription = True )
|
||||
|
||||
page.Update( info )
|
||||
|
||||
self._listbook.AddPage( page, name, select = True )
|
||||
|
||||
|
@ -5890,10 +5933,6 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def InitialiseControls():
|
||||
|
||||
self._name_panel = ClientGUICommon.StaticBox( self, 'name' )
|
||||
|
||||
self._name = wx.TextCtrl( self._name_panel )
|
||||
|
||||
self._query_panel = ClientGUICommon.StaticBox( self, 'site and query' )
|
||||
|
||||
self._site_type = ClientGUICommon.BetterChoice( self._query_panel )
|
||||
|
@ -5940,15 +5979,13 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def PopulateControls():
|
||||
|
||||
self._SetControls( name, info )
|
||||
self._SetControls( info )
|
||||
|
||||
|
||||
def ArrangeControls():
|
||||
|
||||
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
|
||||
|
||||
self._name_panel.AddF( self._name, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
hbox.AddF( wx.StaticText( self._query_panel, label = 'Check subscription every ' ), CC.FLAGS_MIXED )
|
||||
|
@ -5978,7 +6015,6 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
vbox.AddF( self._name_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._query_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._info_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._advanced_tag_options, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
@ -5989,6 +6025,8 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
wx.ScrolledWindow.__init__( self, parent )
|
||||
|
||||
self._name = name
|
||||
|
||||
if new_subscription:
|
||||
|
||||
info = {}
|
||||
|
@ -6009,12 +6047,11 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
else:
|
||||
|
||||
info = wx.GetApp().Read( 'subscription', name )
|
||||
info = wx.GetApp().Read( 'subscription', self._name )
|
||||
|
||||
self._new_subscription = False
|
||||
|
||||
|
||||
self._original_name = name
|
||||
self._original_info = info
|
||||
|
||||
InitialiseControls()
|
||||
|
@ -6100,7 +6137,7 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
self.Layout()
|
||||
|
||||
|
||||
def _SetControls( self, name, info ):
|
||||
def _SetControls( self, info ):
|
||||
|
||||
site_type = info[ 'site_type' ]
|
||||
query_type = info[ 'query_type' ]
|
||||
|
@ -6116,8 +6153,6 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
#
|
||||
|
||||
self._name.SetValue( name )
|
||||
|
||||
self._site_type.SelectClientData( site_type )
|
||||
|
||||
self._PresentForSiteType()
|
||||
|
@ -6190,8 +6225,6 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def GetSubscription( self ):
|
||||
|
||||
name = self._name.GetValue()
|
||||
|
||||
info = dict( self._original_info )
|
||||
|
||||
info[ 'site_type' ] = self._site_type.GetChoice()
|
||||
|
@ -6227,18 +6260,16 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
info[ 'paused' ] = self._paused.GetValue()
|
||||
|
||||
return ( name, info )
|
||||
return ( self._name, info )
|
||||
|
||||
|
||||
def GetOriginalName( self ): return self._original_name
|
||||
def GetName( self ): return self._name
|
||||
|
||||
def GetName( self ): return self._name.GetValue()
|
||||
|
||||
def Update( self, name, info ):
|
||||
def Update( self, info ):
|
||||
|
||||
self._original_info = info
|
||||
|
||||
self._SetControls( name, info )
|
||||
self._SetControls( info )
|
||||
|
||||
|
||||
|
||||
|
@ -7577,9 +7608,9 @@ class DialogManageTags( ClientGUIDialogs.Dialog ):
|
|||
service_type = service.GetServiceType()
|
||||
name = service.GetName()
|
||||
|
||||
page_info = ( self._Panel, ( self._tag_repositories, self._file_service_key, service.GetServiceKey(), media ), {} )
|
||||
page = self._Panel( self._tag_repositories, self._file_service_key, service.GetServiceKey(), media )
|
||||
|
||||
self._tag_repositories.AddPage( page_info, name )
|
||||
self._tag_repositories.AddPage( page, name )
|
||||
|
||||
if service_key == HC.options[ 'default_tag_repository' ]: name_to_select = name
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import ClientGUICommon
|
|||
import ClientCaches
|
||||
import HydrusConstants as HC
|
||||
import wx
|
||||
import wx.lib.masked.timectrl
|
||||
import HydrusGlobals
|
||||
|
||||
class OptionsPanel( wx.Panel ):
|
||||
|
@ -252,6 +253,106 @@ class OptionsPanelImport( OptionsPanel ):
|
|||
|
||||
|
||||
|
||||
class OptionsPanelPeriodic( OptionsPanel ):
|
||||
|
||||
def __init__( self, parent ):
|
||||
|
||||
OptionsPanel.__init__( self, parent )
|
||||
|
||||
self._multiplier = wx.SpinCtrl( self, min = 1, max = 1000 )
|
||||
|
||||
self._wavelength = wx.Choice( self )
|
||||
|
||||
self._wavelength.Append( 'days', CC.DAY )
|
||||
self._wavelength.Append( 'weeks', CC.WEEK )
|
||||
self._wavelength.Append( 'months', CC.MONTH )
|
||||
|
||||
self._wavelength.Bind( wx.EVT_CHOICE, self.EventWavelength )
|
||||
|
||||
self._weekday_phase = wx.Choice( self )
|
||||
|
||||
self._weekday_phase.Append( 'monday', 0 )
|
||||
self._weekday_phase.Append( 'tuesday', 1 )
|
||||
self._weekday_phase.Append( 'wednesday', 2 )
|
||||
self._weekday_phase.Append( 'thursday', 3 )
|
||||
self._weekday_phase.Append( 'friday', 4 )
|
||||
self._weekday_phase.Append( 'saturday', 5 )
|
||||
self._weekday_phase.Append( 'sunday', 6 )
|
||||
|
||||
self._monthday_phase = wx.SpinCtrl( self, min = 1, max = 28 )
|
||||
|
||||
self._time_phase = wx.lib.masked.timectrl.TimeCtrl( self, fmt24hr = True, spinButton = True )
|
||||
|
||||
self._reset = wx.Button( self, label = 'forget failure' )
|
||||
self._reset.Bind( wx.EVT_BUTTON, self.EventReset )
|
||||
|
||||
self._paused = wx.CheckBox( self, label = 'paused' )
|
||||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
# this is complicated, with the statictexts to be hidden and so on
|
||||
|
||||
vbox.AddF( self._auto_archive, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._exclude_deleted, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._min_size, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._min_resolution, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
self.SetSizer( vbox )
|
||||
|
||||
self.SetInfo( {} )
|
||||
|
||||
self._wavelength.Select( 0 )
|
||||
|
||||
|
||||
def EventReset( self, event ):
|
||||
|
||||
# tell the periodic to reset itself
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def EventWavelength( self, event ):
|
||||
|
||||
selection = self._wavelength.GetSelection()
|
||||
|
||||
if selection != wx.NOT_FOUND:
|
||||
|
||||
# this is more complicated, since there will be a bit of statictext as well
|
||||
|
||||
wavelength = self._wavelength.GetClientData( selection )
|
||||
|
||||
if wavelength == CC.DAY:
|
||||
|
||||
self._weekday_phase.Hide()
|
||||
self._monthday_phase.Hide()
|
||||
|
||||
elif wavelength == CC.WEEK:
|
||||
|
||||
self._weekday_phase.Show()
|
||||
self._monthday_phase.Hide()
|
||||
|
||||
elif wavelength == CC.MONTH:
|
||||
|
||||
self._weekday_phase.Hide()
|
||||
self._monthday_phase.Show()
|
||||
|
||||
|
||||
# maybe a layout here as well?
|
||||
|
||||
|
||||
|
||||
def GetInfo( self ):
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def SetInfo( self, info ):
|
||||
|
||||
# 7 days, at 8pm
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class OptionsPanelTags( OptionsPanel ):
|
||||
|
||||
def __init__( self, parent ):
|
||||
|
|
|
@ -1,5 +1,70 @@
|
|||
import HydrusConstants as HC
|
||||
import wx
|
||||
|
||||
ALL_ON = 0
|
||||
ALL_OFF = 1
|
||||
ALL_NULL = 2
|
||||
MIXED = 3
|
||||
|
||||
def DrawLike( dc, x, y, pen_colour, brush_colour ):
|
||||
|
||||
dc.SetPen( wx.Pen( pen_colour ) )
|
||||
dc.SetBrush( wx.Brush( brush_colour ) )
|
||||
|
||||
dc.DrawCircle( x + 7, y + 7, 6 )
|
||||
|
||||
def GetLikeStateFromMedia( media, service_key ):
|
||||
|
||||
on_exists = False
|
||||
off_exists = False
|
||||
null_exists = False
|
||||
|
||||
for m in media:
|
||||
|
||||
( local_ratings, remote_ratings ) = m.GetRatings()
|
||||
|
||||
rating = local_ratings.GetRating( service_key )
|
||||
|
||||
if rating == 1: on_exists = True
|
||||
elif rating == 0: off_exists = True
|
||||
elif rating is None: null_exists = True
|
||||
|
||||
|
||||
if len( [ b for b in ( on_exists, off_exists, null_exists ) if b ] ) == 1:
|
||||
|
||||
if on_exists: return ALL_ON
|
||||
elif off_exists: return ALL_OFF
|
||||
else: return ALL_NULL
|
||||
|
||||
else: return MIXED
|
||||
|
||||
def GetLikeStateFromRating( rating ):
|
||||
|
||||
if rating == 1: return ALL_ON
|
||||
elif rating == 0: return ALL_OFF
|
||||
else: return ALL_NULL
|
||||
|
||||
def GetPenAndBrushColours( service_key, rating_state ):
|
||||
|
||||
if rating_state == ALL_ON:
|
||||
|
||||
brush_colour = wx.Colour( 80, 200, 120 )
|
||||
|
||||
elif rating_state == ALL_OFF:
|
||||
|
||||
brush_colour = wx.Colour( 200, 80, 120 )
|
||||
|
||||
elif rating_state == ALL_NULL:
|
||||
|
||||
brush_colour = wx.WHITE
|
||||
|
||||
else:
|
||||
|
||||
brush_colour = wx.Colour( 127, 127, 127 )
|
||||
|
||||
|
||||
return ( wx.BLACK, brush_colour )
|
||||
|
||||
class CPRemoteRatingsServiceKeys( object ):
|
||||
|
||||
def __init__( self, service_keys_to_cp ):
|
||||
|
@ -100,7 +165,4 @@ class LocalRatingsManager( object ):
|
|||
|
||||
if service_key in self._service_keys_to_ratings: del self._service_keys_to_ratings[ service_key ]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ options = {}
|
|||
# Misc
|
||||
|
||||
NETWORK_VERSION = 15
|
||||
SOFTWARE_VERSION = 156
|
||||
SOFTWARE_VERSION = 157
|
||||
|
||||
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
||||
|
||||
|
|
|
@ -4,9 +4,22 @@ import lz4
|
|||
SERIALISABLE_TYPE_BASE = 0
|
||||
SERIALISABLE_TYPE_BASE_NAMED = 1
|
||||
SERIALISABLE_TYPE_SHORTCUTS = 2
|
||||
SERIALISABLE_TYPE_SUBSCRIPTION = 3
|
||||
SERIALISABLE_TYPE_PERIODIC = 4
|
||||
SERIALISABLE_TYPE_GALLERY_QUERY = 5
|
||||
SERIALISABLE_TYPE_IMPORT_TAG_OPTIONS = 6
|
||||
SERIALISABLE_TYPE_IMPORT_FILE_OPTIONS = 7
|
||||
|
||||
SERIALISABLE_TYPES_TO_OBJECT_TYPES = {}
|
||||
|
||||
def CreateFromEasy( ( serialisable_type, version, serialised_info ) ):
|
||||
|
||||
obj = SERIALISABLE_TYPES_TO_OBJECT_TYPES[ serialisable_type ]()
|
||||
|
||||
obj.InitialiseFromSerialisedInfo( version, serialised_info )
|
||||
|
||||
return obj
|
||||
|
||||
class SerialisableBase( object ):
|
||||
|
||||
SERIALISABLE_TYPE = SERIALISABLE_TYPE_BASE
|
||||
|
@ -27,15 +40,27 @@ class SerialisableBase( object ):
|
|||
return old_info
|
||||
|
||||
|
||||
def GetCompressedSerialisedInfo( self ):
|
||||
|
||||
serialised_info = self.GetSerialisedInfo()
|
||||
|
||||
compressed_serialised_info = lz4.dumps( serialised_info )
|
||||
|
||||
return compressed_serialised_info
|
||||
|
||||
|
||||
def GetEasySerialisedInfo( self ):
|
||||
|
||||
return ( self.SERIALISABLE_TYPE, self.VERSION, self.GetSerialisedInfo() )
|
||||
|
||||
|
||||
def GetSerialisedInfo( self ):
|
||||
|
||||
serialisable_info = self._GetSerialisableInfo()
|
||||
|
||||
serialised_info = json.dumps( serialisable_info )
|
||||
|
||||
compressed_serialised_info = lz4.dumps( serialised_info )
|
||||
|
||||
return compressed_serialised_info
|
||||
return serialised_info
|
||||
|
||||
|
||||
def GetTypeAndVersion( self ):
|
||||
|
@ -43,10 +68,15 @@ class SerialisableBase( object ):
|
|||
return ( self.SERIALISABLE_TYPE, self.VERSION )
|
||||
|
||||
|
||||
def InitialiseFromSerialisedInfo( self, version, compressed_serialised_info ):
|
||||
def InitialiseFromCompressedSerialisedInfo( self, version, compressed_serialised_info ):
|
||||
|
||||
serialised_info = lz4.loads( compressed_serialised_info )
|
||||
|
||||
self.InitialiseFromSerialisedInfo( version, serialised_info )
|
||||
|
||||
|
||||
def InitialiseFromSerialisedInfo( self, version, serialised_info ):
|
||||
|
||||
serialisable_info = json.loads( serialised_info )
|
||||
|
||||
if version != self.VERSION:
|
||||
|
@ -60,7 +90,6 @@ class SerialisableBase( object ):
|
|||
class SerialisableBaseNamed( SerialisableBase ):
|
||||
|
||||
SERIALISABLE_TYPE = SERIALISABLE_TYPE_BASE_NAMED
|
||||
VERSION = 1
|
||||
|
||||
def __init__( self, name ):
|
||||
|
||||
|
|
|
@ -275,39 +275,6 @@ class TestClientDB( unittest.TestCase ):
|
|||
self.assertEqual( result, set() )
|
||||
|
||||
|
||||
def test_shortcuts( self ):
|
||||
|
||||
result = self._read( 'shortcuts' )
|
||||
|
||||
self.assertEqual( result, [] )
|
||||
|
||||
#
|
||||
|
||||
shortcuts = ClientData.Shortcuts( 'test' )
|
||||
|
||||
shortcuts.SetKeyboardAction( wx.ACCEL_NORMAL, wx.WXK_NUMPAD1, ( os.urandom( 32 ), 'action_data' ) )
|
||||
shortcuts.SetKeyboardAction( wx.ACCEL_SHIFT, wx.WXK_END, ( None, 'other_action_data' ) )
|
||||
|
||||
self._write( 'shortcuts', shortcuts )
|
||||
|
||||
result = self._read( 'shortcuts' )
|
||||
|
||||
self.assertEqual( len( result ), 1 )
|
||||
|
||||
result = self._read( 'shortcuts', 'test' )
|
||||
|
||||
self.assertEqual( result.GetKeyboardAction( wx.ACCEL_NORMAL, wx.WXK_NUMPAD1 ), shortcuts.GetKeyboardAction( wx.ACCEL_NORMAL, wx.WXK_NUMPAD1 ) )
|
||||
self.assertEqual( result.GetKeyboardAction( wx.ACCEL_SHIFT, wx.WXK_END ), shortcuts.GetKeyboardAction( wx.ACCEL_SHIFT, wx.WXK_END ) )
|
||||
|
||||
#
|
||||
|
||||
self._write( 'delete_shortcuts', 'test' )
|
||||
|
||||
result = self._read( 'shortcuts' )
|
||||
|
||||
self.assertEqual( result, [] )
|
||||
|
||||
|
||||
def test_file_query_ids( self ):
|
||||
|
||||
self._clear_db()
|
||||
|
@ -1120,6 +1087,39 @@ class TestClientDB( unittest.TestCase ):
|
|||
self.assertEqual( result, [ session ] )
|
||||
|
||||
|
||||
def test_shortcuts( self ):
|
||||
|
||||
result = self._read( 'shortcuts' )
|
||||
|
||||
self.assertEqual( result, [] )
|
||||
|
||||
#
|
||||
|
||||
shortcuts = ClientData.Shortcuts( 'test' )
|
||||
|
||||
shortcuts.SetKeyboardAction( wx.ACCEL_NORMAL, wx.WXK_NUMPAD1, ( os.urandom( 32 ), 'action_data' ) )
|
||||
shortcuts.SetKeyboardAction( wx.ACCEL_SHIFT, wx.WXK_END, ( None, 'other_action_data' ) )
|
||||
|
||||
self._write( 'shortcuts', shortcuts )
|
||||
|
||||
result = self._read( 'shortcuts' )
|
||||
|
||||
self.assertEqual( len( result ), 1 )
|
||||
|
||||
result = self._read( 'shortcuts', 'test' )
|
||||
|
||||
self.assertEqual( result.GetKeyboardAction( wx.ACCEL_NORMAL, wx.WXK_NUMPAD1 ), shortcuts.GetKeyboardAction( wx.ACCEL_NORMAL, wx.WXK_NUMPAD1 ) )
|
||||
self.assertEqual( result.GetKeyboardAction( wx.ACCEL_SHIFT, wx.WXK_END ), shortcuts.GetKeyboardAction( wx.ACCEL_SHIFT, wx.WXK_END ) )
|
||||
|
||||
#
|
||||
|
||||
self._write( 'delete_shortcuts', 'test' )
|
||||
|
||||
result = self._read( 'shortcuts' )
|
||||
|
||||
self.assertEqual( result, [] )
|
||||
|
||||
|
||||
def test_shutdown_timestamps( self ):
|
||||
|
||||
result = self._read( 'shutdown_timestamps' )
|
||||
|
|
Loading…
Reference in New Issue