Version 285
This commit is contained in:
parent
a7f254485a
commit
de9b2e9f8b
|
@ -8,6 +8,38 @@
|
|||
<div class="content">
|
||||
<h3>changelog</h3>
|
||||
<ul>
|
||||
<li><h3>version 285</h3></li>
|
||||
<ul>
|
||||
<li>added 'network' main gui menu and moved network stuff from services to it</li>
|
||||
<li>split the new domain manager stuff up into separate dialogs and menu entries on the new network menu</li>
|
||||
<li>manage url classes dialog now lists url type in the listctrl</li>
|
||||
<li>added url class links info (which will permit client-specific settings and downloader mappings for url classes) to the domain manager</li>
|
||||
<li>wrote a 'url class links' dialog and added it to the new network menu (only the 'display on media viewer' part works atm)</li>
|
||||
<li>the domain manager now filters urls on the media viewer depending on whether they have a url match and are set to display in the new links panel</li>
|
||||
<li>updated the local booru service code to the new service system</li>
|
||||
<li>the local booru's shares can be reviewed again under review services</li>
|
||||
<li>the local booru's port and bandwidth settings can be set again under manage services</li>
|
||||
<li>the different gui parts of the local booru are updated to new controls</li>
|
||||
<li>fixed a local booru 404 reporting error</li>
|
||||
<li>the edit subscription panel now has a 'paste queries' button that lets you add queries en masse</li>
|
||||
<li>added 'manage_file_urls' to shortcuts system</li>
|
||||
<li>added several 'get_similar_to_x' actions to the shortcuts system</li>
|
||||
<li>the manage upnp dialog now initialises its mappings on another thread and fails better when UpnP mappings cannot be fetched</li>
|
||||
<li>connection and readtimeout network exceptions are now recognised more specifically by the client. subscriptions will only delay for an hour on one of these exceptions</li>
|
||||
<li>improved the resilience of the HF login code after wake from sleep (when networking is often not available for a couple of seconds)</li>
|
||||
<li>like the recent subscription query randomisation update, subscriptions themselves are now synced in random order (this stops a subscription named 'aadvark' always getting first bite into available bandwidth)</li>
|
||||
<li>fixed import for jpegs that have unparsable exif data</li>
|
||||
<li>fixed a bug in 'next month' bandwidth estimate calculation when the month is December, wew</li>
|
||||
<li>fixed some logic that was setting max page at 165 rather than the intended 200 and added a dialog that even lets you engage the debug override at 200 if you are insane</li>
|
||||
<li>all audio mime detection and duration parsing is now done through ffmpeg. hsaudiotag is no longer needed to run the program</li>
|
||||
<li>since the old listctrl sort crash bug is still hitting some people, I've disabled sort on the old listctrl class. feel free to try to sort any listctrls now, no matter your situation. I will continue replacing the old class with the new working class over time</li>
|
||||
<li>updated another listctrl</li>
|
||||
<li>a ton of misc controller options/manager access refactoring</li>
|
||||
<li>cleared out some old code</li>
|
||||
<li>moved Time controls to their own file and added velocity and checker options stuff as well</li>
|
||||
<li>wrote a new edit panel for single controls and updated the time delta button to use it</li>
|
||||
<li>misc refactoring</li>
|
||||
</ul>
|
||||
<li><h3>version 284</h3></li>
|
||||
<ul>
|
||||
<li>fixed subscription queries turning dead on the initial sync</li>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<h3>what you will need</h3>
|
||||
<p>You will need basic python experience, python 2.7 and a number of python modules. Most of it you can get through pip. I think this will do for most systems:</p>
|
||||
<ul>
|
||||
<li>pip install beautifulsoup4 hsaudiotag lxml lz4 nose numpy opencv-python pafy Pillow psutil pycrypto pylzma PyOpenSSL PyPDF2 PyYAML requests Send2Trash service_identity twisted youtube-dl</li>
|
||||
<li>pip install beautifulsoup4 lxml lz4 nose numpy opencv-python pafy Pillow psutil pycrypto pylzma PyOpenSSL PyPDF2 PyYAML requests Send2Trash service_identity twisted youtube-dl</li>
|
||||
</ul>
|
||||
<p>Although you may want to do all that in smaller batches. Ultimately, the best way to figure out if you have enough is to just keep running client.pyw and see what it complains about missing.</p>
|
||||
<p>I use Ubuntu 17.04, which also requires something like:</p>
|
||||
|
|
|
@ -309,9 +309,7 @@ class ClientFilesManager( object ):
|
|||
|
||||
full_size_path = self._GenerateExpectedFullSizeThumbnailPath( hash )
|
||||
|
||||
options = self._controller.GetOptions()
|
||||
|
||||
thumbnail_dimensions = options[ 'thumbnail_dimensions' ]
|
||||
thumbnail_dimensions = self._controller.options[ 'thumbnail_dimensions' ]
|
||||
|
||||
if mime in ( HC.IMAGE_GIF, HC.IMAGE_PNG ):
|
||||
|
||||
|
@ -385,7 +383,7 @@ class ClientFilesManager( object ):
|
|||
|
||||
def _GetRebalanceTuple( self ):
|
||||
|
||||
( locations_to_ideal_weights, resized_thumbnail_override, full_size_thumbnail_override ) = self._controller.GetNewOptions().GetClientFilesLocationsToIdealWeights()
|
||||
( locations_to_ideal_weights, resized_thumbnail_override, full_size_thumbnail_override ) = self._controller.new_options.GetClientFilesLocationsToIdealWeights()
|
||||
|
||||
total_weight = sum( locations_to_ideal_weights.values() )
|
||||
|
||||
|
@ -1341,8 +1339,6 @@ class DataCache( object ):
|
|||
|
||||
if key not in self._keys_to_data:
|
||||
|
||||
options = self._controller.GetOptions()
|
||||
|
||||
while self._total_estimated_memory_footprint > self._cache_size:
|
||||
|
||||
self._DeleteItem()
|
||||
|
@ -1676,9 +1672,7 @@ class RenderedImageCache( object ):
|
|||
|
||||
self._controller = controller
|
||||
|
||||
options = self._controller.GetOptions()
|
||||
|
||||
cache_size = options[ 'fullscreen_cache_size' ]
|
||||
cache_size = self._controller.options[ 'fullscreen_cache_size' ]
|
||||
|
||||
self._data_cache = DataCache( self._controller, cache_size, timeout = 600 )
|
||||
|
||||
|
@ -1723,9 +1717,7 @@ class ThumbnailCache( object ):
|
|||
|
||||
self._controller = controller
|
||||
|
||||
options = self._controller.GetOptions()
|
||||
|
||||
cache_size = options[ 'thumbnail_cache_size' ]
|
||||
cache_size = self._controller.options[ 'thumbnail_cache_size' ]
|
||||
|
||||
self._data_cache = DataCache( self._controller, cache_size, timeout = 86400 )
|
||||
|
||||
|
@ -1747,9 +1739,7 @@ class ThumbnailCache( object ):
|
|||
|
||||
def _GetResizedHydrusBitmapFromHardDrive( self, display_media ):
|
||||
|
||||
options = self._controller.GetOptions()
|
||||
|
||||
thumbnail_dimensions = options[ 'thumbnail_dimensions' ]
|
||||
thumbnail_dimensions = self._controller.options[ 'thumbnail_dimensions' ]
|
||||
|
||||
if tuple( thumbnail_dimensions ) == HC.UNSCALED_THUMBNAIL_DIMENSIONS:
|
||||
|
||||
|
@ -1819,11 +1809,9 @@ class ThumbnailCache( object ):
|
|||
|
||||
|
||||
|
||||
options = HG.client_controller.GetOptions()
|
||||
|
||||
( media_x, media_y ) = display_media.GetResolution()
|
||||
( actual_x, actual_y ) = hydrus_bitmap.GetSize()
|
||||
( desired_x, desired_y ) = options[ 'thumbnail_dimensions' ]
|
||||
( desired_x, desired_y ) = self._controller.options[ 'thumbnail_dimensions' ]
|
||||
|
||||
too_large = actual_x > desired_x or actual_y > desired_y
|
||||
|
||||
|
@ -1883,9 +1871,9 @@ class ThumbnailCache( object ):
|
|||
|
||||
path = os.path.join( HC.STATIC_DIR, name + '.png' )
|
||||
|
||||
options = self._controller.GetOptions()
|
||||
thumbnail_dimensions = self._controller.options[ 'thumbnail_dimensions' ]
|
||||
|
||||
thumbnail = HydrusFileHandling.GenerateThumbnailFromStaticImage( path, options[ 'thumbnail_dimensions' ], HC.IMAGE_PNG )
|
||||
thumbnail = HydrusFileHandling.GenerateThumbnailFromStaticImage( path, thumbnail_dimensions, HC.IMAGE_PNG )
|
||||
|
||||
with open( temp_path, 'wb' ) as f:
|
||||
|
||||
|
@ -2441,9 +2429,7 @@ class TagParentsManager( object ):
|
|||
|
||||
def ExpandPredicates( self, service_key, predicates ):
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
|
||||
if new_options.GetBoolean( 'apply_all_parents_to_all_services' ):
|
||||
if self._controller.new_options.GetBoolean( 'apply_all_parents_to_all_services' ):
|
||||
|
||||
service_key = CC.COMBINED_TAG_SERVICE_KEY
|
||||
|
||||
|
@ -2477,9 +2463,7 @@ class TagParentsManager( object ):
|
|||
|
||||
def ExpandTags( self, service_key, tags ):
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
|
||||
if new_options.GetBoolean( 'apply_all_parents_to_all_services' ):
|
||||
if self._controller.new_options.GetBoolean( 'apply_all_parents_to_all_services' ):
|
||||
|
||||
service_key = CC.COMBINED_TAG_SERVICE_KEY
|
||||
|
||||
|
@ -2499,9 +2483,7 @@ class TagParentsManager( object ):
|
|||
|
||||
def GetParents( self, service_key, tag ):
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
|
||||
if new_options.GetBoolean( 'apply_all_parents_to_all_services' ):
|
||||
if self._controller.new_options.GetBoolean( 'apply_all_parents_to_all_services' ):
|
||||
|
||||
service_key = CC.COMBINED_TAG_SERVICE_KEY
|
||||
|
||||
|
@ -2599,9 +2581,7 @@ class TagSiblingsManager( object ):
|
|||
|
||||
def GetAutocompleteSiblings( self, service_key, search_text, exact_match = False ):
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
|
||||
if new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
if self._controller.new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
|
||||
service_key = CC.COMBINED_TAG_SERVICE_KEY
|
||||
|
||||
|
@ -2652,9 +2632,7 @@ class TagSiblingsManager( object ):
|
|||
|
||||
def GetSibling( self, service_key, tag ):
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
|
||||
if new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
if self._controller.new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
|
||||
service_key = CC.COMBINED_TAG_SERVICE_KEY
|
||||
|
||||
|
@ -2676,9 +2654,7 @@ class TagSiblingsManager( object ):
|
|||
|
||||
def GetAllSiblings( self, service_key, tag ):
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
|
||||
if new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
if self._controller.new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
|
||||
service_key = CC.COMBINED_TAG_SERVICE_KEY
|
||||
|
||||
|
@ -2719,9 +2695,7 @@ class TagSiblingsManager( object ):
|
|||
|
||||
def CollapsePredicates( self, service_key, predicates ):
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
|
||||
if new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
if self._controller.new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
|
||||
service_key = CC.COMBINED_TAG_SERVICE_KEY
|
||||
|
||||
|
@ -2778,9 +2752,7 @@ class TagSiblingsManager( object ):
|
|||
|
||||
def CollapsePairs( self, service_key, pairs ):
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
|
||||
if new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
if self._controller.new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
|
||||
service_key = CC.COMBINED_TAG_SERVICE_KEY
|
||||
|
||||
|
@ -2812,9 +2784,7 @@ class TagSiblingsManager( object ):
|
|||
|
||||
def CollapseStatusesToTags( self, service_key, statuses_to_tags ):
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
|
||||
if new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
if self._controller.new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
|
||||
service_key = CC.COMBINED_TAG_SERVICE_KEY
|
||||
|
||||
|
@ -2836,9 +2806,7 @@ class TagSiblingsManager( object ):
|
|||
|
||||
def CollapseTag( self, service_key, tag ):
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
|
||||
if new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
if self._controller.new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
|
||||
service_key = CC.COMBINED_TAG_SERVICE_KEY
|
||||
|
||||
|
@ -2860,9 +2828,7 @@ class TagSiblingsManager( object ):
|
|||
|
||||
def CollapseTags( self, service_key, tags ):
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
|
||||
if new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
if self._controller.new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
|
||||
service_key = CC.COMBINED_TAG_SERVICE_KEY
|
||||
|
||||
|
@ -2875,9 +2841,7 @@ class TagSiblingsManager( object ):
|
|||
|
||||
def CollapseTagsToCount( self, service_key, tags_to_count ):
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
|
||||
if new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
if self._controller.new_options.GetBoolean( 'apply_all_siblings_to_all_services' ):
|
||||
|
||||
service_key = CC.COMBINED_TAG_SERVICE_KEY
|
||||
|
||||
|
|
|
@ -336,7 +336,7 @@ SHORTCUTS_RESERVED_NAMES = [ 'archive_delete_filter', 'duplicate_filter', 'media
|
|||
|
||||
# shortcut commands
|
||||
|
||||
SHORTCUTS_MEDIA_ACTIONS = [ 'manage_file_tags', 'manage_file_ratings', 'archive_file', 'inbox_file', 'delete_file', 'remove_file_from_view', 'open_file_in_external_program', 'launch_the_archive_delete_filter', 'copy_bmp', 'copy_file', 'copy_path', 'copy_sha256_hash' ]
|
||||
SHORTCUTS_MEDIA_ACTIONS = [ 'manage_file_tags', 'manage_file_ratings', 'manage_file_urls', 'archive_file', 'inbox_file', 'delete_file', 'remove_file_from_view', 'open_file_in_external_program', 'launch_the_archive_delete_filter', 'copy_bmp', 'copy_file', 'copy_path', 'copy_sha256_hash', 'get_similar_to_exact', 'get_similar_to_very_similar', 'get_similar_to_similar', 'get_similar_to_speculative' ]
|
||||
SHORTCUTS_MEDIA_VIEWER_ACTIONS = [ 'move_animation_to_previous_frame', 'move_animation_to_next_frame', 'switch_between_fullscreen_borderless_and_regular_framed_window', 'pan_up', 'pan_down', 'pan_left', 'pan_right', 'zoom_in', 'zoom_out', 'switch_between_100_percent_and_canvas_zoom', 'flip_darkmode' ]
|
||||
SHORTCUTS_MEDIA_VIEWER_BROWSER_ACTIONS = [ 'view_next', 'view_first', 'view_last', 'view_previous' ]
|
||||
SHORTCUTS_MAIN_GUI_ACTIONS = [ 'refresh', 'new_page', 'synchronised_wait_switch', 'set_media_focus', 'show_hide_splitters', 'set_search_focus', 'unclose_page', 'close_page', 'redo', 'undo', 'flip_darkmode' ]
|
||||
|
|
|
@ -499,11 +499,6 @@ class Controller( HydrusController.HydrusController ):
|
|||
return self.gui
|
||||
|
||||
|
||||
def GetOptions( self ):
|
||||
|
||||
return self.options
|
||||
|
||||
|
||||
def GetNewOptions( self ):
|
||||
|
||||
return self.new_options
|
||||
|
@ -619,6 +614,8 @@ class Controller( HydrusController.HydrusController ):
|
|||
wx.MessageBox( 'Your domain manager was missing on boot! I have recreated a new empty one. Please check that your hard drive and client are ok and let the hydrus dev know the details if there is a mystery.' )
|
||||
|
||||
|
||||
domain_manager.Initialise()
|
||||
|
||||
login_manager = ClientNetworkingLogin.NetworkLoginManager()
|
||||
|
||||
self.network_engine = ClientNetworking.NetworkEngine( self, bandwidth_manager, session_manager, domain_manager, login_manager )
|
||||
|
@ -629,7 +626,7 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
self._shortcuts_manager = ClientCaches.ShortcutsManager( self )
|
||||
|
||||
self._managers[ 'local_booru' ] = ClientCaches.LocalBooruCache( self )
|
||||
self.local_booru_manager = ClientCaches.LocalBooruCache( self )
|
||||
|
||||
self.pub( 'splash_set_status_subtext', u'tag censorship' )
|
||||
|
||||
|
@ -1359,7 +1356,10 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
def Write( self, action, *args, **kwargs ):
|
||||
|
||||
if action == 'content_updates': self._managers[ 'undo' ].AddCommand( 'content_updates', *args, **kwargs )
|
||||
if action == 'content_updates':
|
||||
|
||||
self._managers[ 'undo' ].AddCommand( 'content_updates', *args, **kwargs )
|
||||
|
||||
|
||||
return HydrusController.HydrusController.Write( self, action, *args, **kwargs )
|
||||
|
||||
|
|
|
@ -1633,7 +1633,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
def _CacheSimilarFilesMaintenanceDue( self ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
if new_options.GetBoolean( 'maintain_similar_files_duplicate_pairs_during_idle' ):
|
||||
|
||||
|
@ -1644,7 +1644,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
return True
|
||||
|
||||
|
||||
search_distance = HG.client_controller.GetNewOptions().GetInteger( 'similar_files_duplicate_pairs_search_distance' )
|
||||
search_distance = new_options.GetInteger( 'similar_files_duplicate_pairs_search_distance' )
|
||||
|
||||
( count, ) = self._c.execute( 'SELECT COUNT( * ) FROM shape_search_cache WHERE searched_distance IS NULL or searched_distance < ?;', ( search_distance, ) ).fetchone()
|
||||
|
||||
|
@ -3731,9 +3731,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
show_inbox_and_archive = True
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
|
||||
if new_options.GetBoolean( 'filter_inbox_and_archive_predicates' ) and ( num_inbox == 0 or num_archive == 0 ):
|
||||
if self._controller.new_options.GetBoolean( 'filter_inbox_and_archive_predicates' ) and ( num_inbox == 0 or num_archive == 0 ):
|
||||
|
||||
show_inbox_and_archive = False
|
||||
|
||||
|
@ -5511,7 +5509,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
newest_first.sort( key = sort_key, reverse = True )
|
||||
|
||||
num_we_want = HG.client_controller.GetNewOptions().GetNoneableInteger( 'num_recent_tags' )
|
||||
num_we_want = HG.client_controller.new_options.GetNoneableInteger( 'num_recent_tags' )
|
||||
|
||||
if num_we_want == None:
|
||||
|
||||
|
@ -6662,9 +6660,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
# vacuum
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
|
||||
maintenance_vacuum_period_days = new_options.GetNoneableInteger( 'maintenance_vacuum_period_days' )
|
||||
maintenance_vacuum_period_days = self._controller.new_options.GetNoneableInteger( 'maintenance_vacuum_period_days' )
|
||||
|
||||
if maintenance_vacuum_period_days is not None:
|
||||
|
||||
|
@ -6839,9 +6835,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
( file_info_manager, multihash ) = row
|
||||
|
||||
hash = file_info_manager.GetHash()
|
||||
|
||||
hash_id = self._GetHashId( hash )
|
||||
hash_id = self._GetHashId( file_info_manager.hash )
|
||||
|
||||
self._SetServiceFilename( service_id, hash_id, multihash )
|
||||
|
||||
|
@ -8315,11 +8309,9 @@ class DB( HydrusDB.HydrusDB ):
|
|||
password = hashlib.sha256( password_bytes ).digest()
|
||||
|
||||
|
||||
options = self._controller.GetOptions()
|
||||
self._controller.options[ 'password' ] = password
|
||||
|
||||
options[ 'password' ] = password
|
||||
|
||||
self._SaveOptions( options )
|
||||
self._SaveOptions( self._controller.options )
|
||||
|
||||
|
||||
def _SetServiceFilename( self, service_id, hash_id, filename ):
|
||||
|
@ -10503,7 +10495,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
def _Vacuum( self, stop_time = None, force_vacuum = False ):
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
new_options = self._controller.new_options
|
||||
|
||||
maintenance_vacuum_period_days = new_options.GetNoneableInteger( 'maintenance_vacuum_period_days' )
|
||||
|
||||
|
|
|
@ -16,15 +16,13 @@ import wx
|
|||
|
||||
def DAEMONCheckExportFolders( controller ):
|
||||
|
||||
options = controller.GetOptions()
|
||||
|
||||
if not options[ 'pause_export_folders_sync' ]:
|
||||
if not controller.options[ 'pause_export_folders_sync' ]:
|
||||
|
||||
export_folders = controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_EXPORT_FOLDER )
|
||||
|
||||
for export_folder in export_folders:
|
||||
|
||||
if options[ 'pause_export_folders_sync' ]:
|
||||
if controller.options[ 'pause_export_folders_sync' ]:
|
||||
|
||||
break
|
||||
|
||||
|
@ -35,9 +33,7 @@ def DAEMONCheckExportFolders( controller ):
|
|||
|
||||
def DAEMONCheckImportFolders( controller ):
|
||||
|
||||
options = controller.GetOptions()
|
||||
|
||||
if not options[ 'pause_import_folders_sync' ]:
|
||||
if not controller.options[ 'pause_import_folders_sync' ]:
|
||||
|
||||
import_folder_names = controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_FOLDER )
|
||||
|
||||
|
@ -45,7 +41,7 @@ def DAEMONCheckImportFolders( controller ):
|
|||
|
||||
import_folder = controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_FOLDER, name )
|
||||
|
||||
if options[ 'pause_import_folders_sync' ]:
|
||||
if controller.options[ 'pause_import_folders_sync' ]:
|
||||
|
||||
break
|
||||
|
||||
|
@ -268,9 +264,7 @@ def DAEMONSynchroniseAccounts( controller ):
|
|||
|
||||
def DAEMONSynchroniseRepositories( controller ):
|
||||
|
||||
options = controller.GetOptions()
|
||||
|
||||
if not options[ 'pause_repo_sync' ]:
|
||||
if not controller.options[ 'pause_repo_sync' ]:
|
||||
|
||||
services = controller.services_manager.GetServices( HC.REPOSITORIES )
|
||||
|
||||
|
@ -281,7 +275,7 @@ def DAEMONSynchroniseRepositories( controller ):
|
|||
return
|
||||
|
||||
|
||||
if options[ 'pause_repo_sync' ]:
|
||||
if controller.options[ 'pause_repo_sync' ]:
|
||||
|
||||
return
|
||||
|
||||
|
@ -300,13 +294,13 @@ def DAEMONSynchroniseRepositories( controller ):
|
|||
|
||||
def DAEMONSynchroniseSubscriptions( controller ):
|
||||
|
||||
options = controller.GetOptions()
|
||||
subscription_names = list( controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION ) )
|
||||
|
||||
subscription_names = controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION )
|
||||
random.shuffle( subscription_names )
|
||||
|
||||
for name in subscription_names:
|
||||
|
||||
p1 = options[ 'pause_subs_sync' ]
|
||||
p1 = controller.options[ 'pause_subs_sync' ]
|
||||
p2 = controller.ViewIsShutdown()
|
||||
|
||||
if p1 or p2:
|
||||
|
|
|
@ -253,10 +253,8 @@ def GetDefaultHentaiFoundryInfo():
|
|||
|
||||
def GetDefaultFileImportOptions():
|
||||
|
||||
options = HG.client_controller.GetOptions()
|
||||
|
||||
automatic_archive = False
|
||||
exclude_deleted = options[ 'exclude_deleted_files' ]
|
||||
exclude_deleted = HG.client_controller.options[ 'exclude_deleted_files' ]
|
||||
min_size = None
|
||||
min_resolution = None
|
||||
|
||||
|
|
|
@ -118,9 +118,7 @@ def GenerateExportFilename( destination_directory, media, terms ):
|
|||
|
||||
def GetExportPath():
|
||||
|
||||
options = HG.client_controller.GetOptions()
|
||||
|
||||
portable_path = options[ 'export_path' ]
|
||||
portable_path = HG.client_controller.options[ 'export_path' ]
|
||||
|
||||
if portable_path is None:
|
||||
|
||||
|
@ -229,9 +227,7 @@ class ExportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
if phrase is None:
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
|
||||
phrase = new_options.GetString( 'export_phrase' )
|
||||
phrase = HG.client_controller.new_options.GetString( 'export_phrase' )
|
||||
|
||||
|
||||
self._path = path
|
||||
|
|
|
@ -55,7 +55,7 @@ ID_TIMER_GUI_BANDWIDTH = wx.NewId()
|
|||
|
||||
# Sizer Flags
|
||||
|
||||
MENU_ORDER = [ 'file', 'undo', 'pages', 'database', 'pending', 'services', 'help' ]
|
||||
MENU_ORDER = [ 'file', 'undo', 'pages', 'database', 'pending', 'network', 'services', 'help' ]
|
||||
|
||||
class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
||||
|
||||
|
@ -63,7 +63,7 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
self._controller = controller
|
||||
|
||||
title = self._controller.GetNewOptions().GetString( 'main_gui_title' )
|
||||
title = self._controller.new_options.GetString( 'main_gui_title' )
|
||||
|
||||
if title is None or title == '':
|
||||
|
||||
|
@ -637,9 +637,7 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
def _CheckImportFolder( self, name = None ):
|
||||
|
||||
options = self._controller.GetOptions()
|
||||
|
||||
if options[ 'pause_import_folders_sync' ]:
|
||||
if self._controller.options[ 'pause_import_folders_sync' ]:
|
||||
|
||||
HydrusData.ShowText( 'Import folders are currently paused under the \'services\' menu. Please unpause them and try this again.' )
|
||||
|
||||
|
@ -873,8 +871,6 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
menu = wx.Menu()
|
||||
|
||||
p = self._controller.PrepStringForDisplay
|
||||
|
||||
def file():
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'import files', 'Add new files to the database.', self._ImportFiles )
|
||||
|
@ -931,7 +927,7 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'exit', 'Shut the client down.', self.Exit )
|
||||
|
||||
return ( menu, p( '&File' ), True )
|
||||
return ( menu, '&file', True )
|
||||
|
||||
|
||||
def undo():
|
||||
|
@ -998,7 +994,7 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
show = False
|
||||
|
||||
|
||||
return ( menu, p( '&Undo' ), show )
|
||||
return ( menu, '&undo', show )
|
||||
|
||||
|
||||
def pages():
|
||||
|
@ -1168,7 +1164,7 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
#
|
||||
|
||||
return ( menu, p( '&Pages' ), True )
|
||||
return ( menu, '&pages', True )
|
||||
|
||||
|
||||
def database():
|
||||
|
@ -1223,7 +1219,7 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
ClientGUIMenus.AppendMenu( menu, submenu, 'regenerate' )
|
||||
|
||||
return ( menu, p( '&Database' ), True )
|
||||
return ( menu, '&database', True )
|
||||
|
||||
|
||||
def pending():
|
||||
|
@ -1295,7 +1291,40 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
show = total_num_pending > 0
|
||||
|
||||
return ( menu, p( '&Pending (' + HydrusData.ConvertIntToPrettyString( total_num_pending ) + ')' ), show )
|
||||
return ( menu, '&pending (' + HydrusData.ConvertIntToPrettyString( total_num_pending ) + ')', show )
|
||||
|
||||
|
||||
def network():
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'review bandwidth usage', 'See where you are consuming data.', self._ReviewBandwidth )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage subscriptions', 'Change the queries you want the client to regularly import from.', self._ManageSubscriptions )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
# and transition this to 'manage logins'
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage pixiv account', 'Set up your pixiv username and password.', self._ManagePixivAccount )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage boorus', 'Change the html parsing information for boorus to download from.', self._ManageBoorus )
|
||||
# manage downloaders, or maybe just rename the parsing scripts stuff
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage parsing scripts', 'Manage how the client parses different types of web content.', self._ManageParsingScripts )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuLabel( menu, '(This section is under construction)' )
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage url classes', 'Configure which URLs the client can recognise.', self._ManageURLMatches )
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage url class links', 'Configure how URLs present across the client.', self._ManageURLMatchLinks )
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage http headers', 'Configure how the client talks to the network.', self._ManageNetworkHeaders )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage upnp', 'If your router supports it, see and edit your current UPnP NAT traversal mappings.', self._ManageUPnP )
|
||||
|
||||
return ( menu, '&network', True )
|
||||
|
||||
|
||||
def services():
|
||||
|
@ -1409,11 +1438,6 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
ClientGUIMenus.AppendMenu( menu, admin_menu, 'administrate services' )
|
||||
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'review bandwidth usage', 'See where you are consuming data.', self._ReviewBandwidth )
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage network rules (under construction)', 'Configure how the client talks to the network.', self._ManageNetworkRules )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'import repository update files', 'Add repository update files to the database.', self._ImportUpdateFiles )
|
||||
|
@ -1424,21 +1448,7 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage tag siblings', 'Set certain tags to be automatically replaced with other tags.', self._ManageTagSiblings )
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage tag parents', 'Set certain tags to be automatically added with other tags.', self._ManageTagParents )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage parsing scripts', 'Manage how the client parses different types of web content.', self._ManageParsingScripts )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage boorus', 'Change the html parsing information for boorus to download from.', self._ManageBoorus )
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage pixiv account', 'Set up your pixiv username and password.', self._ManagePixivAccount )
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage subscriptions', 'Change the queries you want the client to regularly import from.', self._ManageSubscriptions )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage upnp', 'If your router supports it, see and edit your current UPnP NAT traversal mappings.', self._ManageUPnP )
|
||||
|
||||
return ( menu, p( '&Services' ), True )
|
||||
return ( menu, '&services', True )
|
||||
|
||||
|
||||
def help():
|
||||
|
@ -1513,13 +1523,14 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
ClientGUIMenus.AppendMenuItem( self, menu, 'hardcoded shortcuts', 'Review some currently hardcoded shortcuts.', wx.MessageBox, CC.SHORTCUT_HELP )
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'about', 'See this client\'s version and other information.', self._AboutWindow )
|
||||
|
||||
return ( menu, p( '&Help' ), True )
|
||||
return ( menu, '&help', True )
|
||||
|
||||
|
||||
if name == 'file': return file()
|
||||
elif name == 'undo': return undo()
|
||||
elif name == 'pages': return pages()
|
||||
elif name == 'database': return database()
|
||||
elif name == 'network': return network()
|
||||
elif name == 'pending': return pending()
|
||||
elif name == 'services': return services()
|
||||
elif name == 'help': return help()
|
||||
|
@ -1782,28 +1793,24 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
|
||||
|
||||
def _ManageNetworkRules( self ):
|
||||
def _ManageNetworkHeaders( self ):
|
||||
|
||||
title = 'manage network rules'
|
||||
title = 'manage network headers'
|
||||
|
||||
with ClientGUITopLevelWindows.DialogEdit( self, title ) as dlg:
|
||||
|
||||
# eventually make this a proper management panel with several notebook pages or something
|
||||
|
||||
domain_manager = self._controller.network_engine.domain_manager
|
||||
|
||||
url_matches = domain_manager.GetURLMatches()
|
||||
network_contexts_to_custom_header_dicts = domain_manager.GetNetworkContextsToCustomHeaderDicts()
|
||||
|
||||
panel = ClientGUIScrolledPanelsEdit.EditDomainManagerInfoPanel( dlg, url_matches, network_contexts_to_custom_header_dicts )
|
||||
panel = ClientGUIScrolledPanelsEdit.EditNetworkContextCustomHeadersPanel( dlg, network_contexts_to_custom_header_dicts )
|
||||
|
||||
dlg.SetPanel( panel )
|
||||
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
|
||||
( url_matches, network_contexts_to_custom_header_dicts ) = panel.GetValue()
|
||||
network_contexts_to_custom_header_dicts = panel.GetValue()
|
||||
|
||||
domain_manager.SetURLMatches( url_matches )
|
||||
domain_manager.SetNetworkContextsToCustomHeaderDicts( network_contexts_to_custom_header_dicts )
|
||||
|
||||
|
||||
|
@ -1941,6 +1948,54 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
with ClientGUIDialogsManage.DialogManageTagSiblings( self ) as dlg: dlg.ShowModal()
|
||||
|
||||
|
||||
def _ManageURLMatches( self ):
|
||||
|
||||
title = 'manage url classes'
|
||||
|
||||
with ClientGUITopLevelWindows.DialogEdit( self, title ) as dlg:
|
||||
|
||||
domain_manager = self._controller.network_engine.domain_manager
|
||||
|
||||
url_matches = domain_manager.GetURLMatches()
|
||||
|
||||
panel = ClientGUIScrolledPanelsEdit.EditURLMatchesPanel( dlg, url_matches )
|
||||
|
||||
dlg.SetPanel( panel )
|
||||
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
|
||||
url_matches = panel.GetValue()
|
||||
|
||||
domain_manager.SetURLMatches( url_matches )
|
||||
|
||||
|
||||
|
||||
|
||||
def _ManageURLMatchLinks( self ):
|
||||
|
||||
title = 'manage url class links'
|
||||
|
||||
with ClientGUITopLevelWindows.DialogEdit( self, title ) as dlg:
|
||||
|
||||
# eventually make this a proper management panel with several notebook pages or something
|
||||
|
||||
domain_manager = self._controller.network_engine.domain_manager
|
||||
|
||||
( url_match_names_to_display, url_match_names_to_page_parsing_keys, url_match_names_to_gallery_parsing_keys ) = domain_manager.GetURLMatchLinks()
|
||||
|
||||
panel = ClientGUIScrolledPanelsEdit.EditURLMatchLinksPanel( dlg, self._controller.network_engine, url_match_names_to_display, url_match_names_to_page_parsing_keys, url_match_names_to_gallery_parsing_keys )
|
||||
|
||||
dlg.SetPanel( panel )
|
||||
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
|
||||
( url_match_names_to_display, url_match_names_to_page_parsing_keys, url_match_names_to_gallery_parsing_keys ) = panel.GetValue()
|
||||
|
||||
domain_manager.SetURLMatchLinks( url_match_names_to_display, url_match_names_to_page_parsing_keys, url_match_names_to_gallery_parsing_keys )
|
||||
|
||||
|
||||
|
||||
|
||||
def _ManageUPnP( self ):
|
||||
|
||||
with ClientGUIDialogsManage.DialogManageUPnP( self ) as dlg: dlg.ShowModal()
|
||||
|
@ -3190,6 +3245,13 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
|
||||
def ImportFiles( self, paths ):
|
||||
|
||||
# can more easily do this when seeds are doing their own tags
|
||||
|
||||
# get current media page
|
||||
# if it is an import page, ask user if they want to add it to the page or make a new one
|
||||
# if using existing, then load the panel without file import options
|
||||
# think about how to merge 'delete_after_success' or not--maybe this can be handled by seeds as well
|
||||
|
||||
paths = [ HydrusData.ToUnicode( path ) for path in paths ]
|
||||
|
||||
self._ImportFiles( paths )
|
||||
|
@ -3306,6 +3368,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
|
||||
self._dirty_menus.add( 'pages' )
|
||||
self._dirty_menus.add( 'services' )
|
||||
self._dirty_menus.add( 'network' )
|
||||
|
||||
self._menu_updater.Update()
|
||||
|
||||
|
@ -3314,6 +3377,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
|
||||
self._dirty_menus.add( 'pages' )
|
||||
self._dirty_menus.add( 'services' )
|
||||
self._dirty_menus.add( 'network' )
|
||||
|
||||
self._menu_updater.Update()
|
||||
|
||||
|
|
|
@ -276,9 +276,7 @@ class AutoCompleteDropdown( wx.Panel ):
|
|||
|
||||
def _UpdateBackgroundColour( self ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
|
||||
colour = new_options.GetColour( CC.COLOUR_AUTOCOMPLETE_BACKGROUND )
|
||||
colour = HG.client_controller.new_options.GetColour( CC.COLOUR_AUTOCOMPLETE_BACKGROUND )
|
||||
|
||||
if not self._intercept_key_events:
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ def CalculateCanvasZooms( canvas, media, show_action ):
|
|||
return ( 1.0, 1.0 )
|
||||
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
( canvas_width, canvas_height ) = CalculateCanvasMediaSize( media, canvas.GetClientSize() )
|
||||
|
||||
|
@ -378,7 +378,7 @@ class Animation( wx.Window ):
|
|||
|
||||
def _DrawWhite( self, dc ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
dc.SetBackground( wx.Brush( new_options.GetColour( CC.COLOUR_MEDIA_BACKGROUND ) ) )
|
||||
|
||||
|
@ -439,7 +439,7 @@ class Animation( wx.Window ):
|
|||
|
||||
path = client_files_manager.GetFilePath( hash, mime )
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
launch_path = new_options.GetMimeLaunch( mime )
|
||||
|
||||
|
@ -1183,7 +1183,7 @@ class Canvas( wx.Window ):
|
|||
self._reserved_shortcut_names.append( 'media' )
|
||||
self._reserved_shortcut_names.append( 'media_viewer' )
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
self._custom_shortcut_names = self._new_options.GetStringList( 'default_media_viewer_custom_shortcuts' )
|
||||
|
||||
|
@ -1712,6 +1712,10 @@ class Canvas( wx.Window ):
|
|||
|
||||
self._ManageTags()
|
||||
|
||||
elif action == 'manage_file_urls':
|
||||
|
||||
self._ManageURLs()
|
||||
|
||||
elif action == 'archive_file':
|
||||
|
||||
self._Archive()
|
||||
|
@ -2824,21 +2828,13 @@ class CanvasWithDetails( Canvas ):
|
|||
|
||||
urls = self._current_media.GetLocationsManager().GetURLs()
|
||||
|
||||
urls = list( urls )
|
||||
url_tuples = HG.client_controller.network_engine.domain_manager.ConvertURLsToMediaViewerTuples( urls )
|
||||
|
||||
urls.sort()
|
||||
|
||||
urls = urls[ : 10 ]
|
||||
|
||||
for url in urls:
|
||||
for ( display_string, url ) in url_tuples:
|
||||
|
||||
parse = urlparse.urlparse( url )
|
||||
( text_width, text_height ) = dc.GetTextExtent( display_string )
|
||||
|
||||
url_string = parse.hostname
|
||||
|
||||
( text_width, text_height ) = dc.GetTextExtent( url_string )
|
||||
|
||||
dc.DrawText( url_string, client_width - text_width - 3, current_y )
|
||||
dc.DrawText( display_string, client_width - text_width - 3, current_y )
|
||||
|
||||
current_y += text_height + 4
|
||||
|
||||
|
@ -3243,7 +3239,7 @@ class CanvasFilterDuplicates( CanvasWithHovers ):
|
|||
|
||||
duplicate_type = dlg_1.GetChoice()
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
duplicate_action_options = new_options.GetDuplicateActionOptions( duplicate_type )
|
||||
|
||||
|
@ -3333,7 +3329,7 @@ class CanvasFilterDuplicates( CanvasWithHovers ):
|
|||
|
||||
else:
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
duplicate_intensity = new_options.GetNoneableInteger( 'duplicate_background_switch_intensity' )
|
||||
|
||||
|
@ -3484,7 +3480,7 @@ class CanvasFilterDuplicates( CanvasWithHovers ):
|
|||
|
||||
if duplicate_action_options is None:
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
duplicate_action_options = new_options.GetDuplicateActionOptions( duplicate_type )
|
||||
|
||||
|
@ -5294,7 +5290,7 @@ class EmbedButton( wx.Window ):
|
|||
center_y = y / 2
|
||||
radius = min( 50, center_x, center_y ) - 5
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
dc.SetBackground( wx.Brush( new_options.GetColour( CC.COLOUR_MEDIA_BACKGROUND ) ) )
|
||||
|
||||
|
@ -5448,7 +5444,7 @@ class OpenExternallyPanel( wx.Panel ):
|
|||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
self.SetBackgroundColour( self._new_options.GetColour( CC.COLOUR_MEDIA_BACKGROUND ) )
|
||||
|
||||
|
@ -5529,7 +5525,7 @@ class StaticImage( wx.Window ):
|
|||
|
||||
def _DrawBackground( self, dc ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
dc.SetBackground( wx.Brush( new_options.GetColour( CC.COLOUR_MEDIA_BACKGROUND ) ) )
|
||||
|
||||
|
|
|
@ -719,14 +719,14 @@ class CheckboxManagerOptions( CheckboxManager ):
|
|||
|
||||
def GetCurrentValue( self ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
return new_options.GetBoolean( self._boolean_name )
|
||||
|
||||
|
||||
def Invert( self ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
new_options.InvertBoolean( self._boolean_name )
|
||||
|
||||
|
@ -2923,345 +2923,3 @@ class ThreadToGUIUpdater( object ):
|
|||
|
||||
|
||||
|
||||
( TimeDeltaEvent, EVT_TIME_DELTA ) = wx.lib.newevent.NewCommandEvent()
|
||||
|
||||
class TimeDeltaButton( wx.Button ):
|
||||
|
||||
def __init__( self, parent, min = 1, days = False, hours = False, minutes = False, seconds = False, monthly_allowed = False ):
|
||||
|
||||
wx.Button.__init__( self, parent )
|
||||
|
||||
self._min = min
|
||||
self._show_days = days
|
||||
self._show_hours = hours
|
||||
self._show_minutes = minutes
|
||||
self._show_seconds = seconds
|
||||
self._monthly_allowed = monthly_allowed
|
||||
|
||||
self._value = self._min
|
||||
|
||||
self.SetLabelText( 'initialising' )
|
||||
|
||||
self.Bind( wx.EVT_BUTTON, self.EventButton )
|
||||
|
||||
|
||||
def _RefreshLabel( self ):
|
||||
|
||||
text_components = []
|
||||
|
||||
value = self._value
|
||||
|
||||
if value is None:
|
||||
|
||||
text = 'monthly'
|
||||
|
||||
else:
|
||||
|
||||
text = HydrusData.ConvertTimeDeltaToPrettyString( value )
|
||||
|
||||
|
||||
self.SetLabelText( text )
|
||||
|
||||
|
||||
def EventButton( self, event ):
|
||||
|
||||
import ClientGUIDialogs
|
||||
|
||||
with ClientGUIDialogs.DialogInputTimeDelta( self, self._value, min = self._min, days = self._show_days, hours = self._show_hours, minutes = self._show_minutes, seconds = self._show_seconds, monthly_allowed = self._monthly_allowed ) as dlg:
|
||||
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
|
||||
value = dlg.GetValue()
|
||||
|
||||
self.SetValue( value )
|
||||
|
||||
new_event = TimeDeltaEvent( 0 )
|
||||
|
||||
wx.PostEvent( self, new_event )
|
||||
|
||||
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
return self._value
|
||||
|
||||
|
||||
def SetValue( self, value ):
|
||||
|
||||
self._value = value
|
||||
|
||||
self._RefreshLabel()
|
||||
|
||||
self.GetParent().Layout()
|
||||
|
||||
|
||||
class TimeDeltaCtrl( wx.Panel ):
|
||||
|
||||
def __init__( self, parent, min = 1, days = False, hours = False, minutes = False, seconds = False, monthly_allowed = False, monthly_label = 'monthly' ):
|
||||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
self._min = min
|
||||
self._show_days = days
|
||||
self._show_hours = hours
|
||||
self._show_minutes = minutes
|
||||
self._show_seconds = seconds
|
||||
self._monthly_allowed = monthly_allowed
|
||||
|
||||
hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
if self._show_days:
|
||||
|
||||
self._days = wx.SpinCtrl( self, min = 0, max = 3653, size = ( 50, -1 ) )
|
||||
self._days.Bind( wx.EVT_SPINCTRL, self.EventChange )
|
||||
|
||||
hbox.AddF( self._days, CC.FLAGS_VCENTER )
|
||||
hbox.AddF( BetterStaticText( self, 'days' ), CC.FLAGS_VCENTER )
|
||||
|
||||
|
||||
if self._show_hours:
|
||||
|
||||
self._hours = wx.SpinCtrl( self, min = 0, max = 23, size = ( 45, -1 ) )
|
||||
self._hours.Bind( wx.EVT_SPINCTRL, self.EventChange )
|
||||
|
||||
hbox.AddF( self._hours, CC.FLAGS_VCENTER )
|
||||
hbox.AddF( BetterStaticText( self, 'hours' ), CC.FLAGS_VCENTER )
|
||||
|
||||
|
||||
if self._show_minutes:
|
||||
|
||||
self._minutes = wx.SpinCtrl( self, min = 0, max = 59, size = ( 45, -1 ) )
|
||||
self._minutes.Bind( wx.EVT_SPINCTRL, self.EventChange )
|
||||
|
||||
hbox.AddF( self._minutes, CC.FLAGS_VCENTER )
|
||||
hbox.AddF( BetterStaticText( self, 'minutes' ), CC.FLAGS_VCENTER )
|
||||
|
||||
|
||||
if self._show_seconds:
|
||||
|
||||
self._seconds = wx.SpinCtrl( self, min = 0, max = 59, size = ( 45, -1 ) )
|
||||
self._seconds.Bind( wx.EVT_SPINCTRL, self.EventChange )
|
||||
|
||||
hbox.AddF( self._seconds, CC.FLAGS_VCENTER )
|
||||
hbox.AddF( BetterStaticText( self, 'seconds' ), CC.FLAGS_VCENTER )
|
||||
|
||||
|
||||
if self._monthly_allowed:
|
||||
|
||||
self._monthly = wx.CheckBox( self )
|
||||
self._monthly.Bind( wx.EVT_CHECKBOX, self.EventChange )
|
||||
|
||||
hbox.AddF( self._monthly, CC.FLAGS_VCENTER )
|
||||
hbox.AddF( BetterStaticText( self, monthly_label ), CC.FLAGS_VCENTER )
|
||||
|
||||
|
||||
self.SetSizer( hbox )
|
||||
|
||||
|
||||
def _UpdateEnables( self ):
|
||||
|
||||
value = self.GetValue()
|
||||
|
||||
if value is None:
|
||||
|
||||
if self._show_days:
|
||||
|
||||
self._days.Disable()
|
||||
|
||||
|
||||
if self._show_hours:
|
||||
|
||||
self._hours.Disable()
|
||||
|
||||
|
||||
if self._show_minutes:
|
||||
|
||||
self._minutes.Disable()
|
||||
|
||||
|
||||
if self._show_seconds:
|
||||
|
||||
self._seconds.Disable()
|
||||
|
||||
|
||||
else:
|
||||
|
||||
if self._show_days:
|
||||
|
||||
self._days.Enable()
|
||||
|
||||
|
||||
if self._show_hours:
|
||||
|
||||
self._hours.Enable()
|
||||
|
||||
|
||||
if self._show_minutes:
|
||||
|
||||
self._minutes.Enable()
|
||||
|
||||
|
||||
if self._show_seconds:
|
||||
|
||||
self._seconds.Enable()
|
||||
|
||||
|
||||
|
||||
|
||||
def EventChange( self, event ):
|
||||
|
||||
value = self.GetValue()
|
||||
|
||||
if value is not None and value < self._min:
|
||||
|
||||
self.SetValue( self._min )
|
||||
|
||||
|
||||
self._UpdateEnables()
|
||||
|
||||
new_event = TimeDeltaEvent( 0 )
|
||||
|
||||
wx.PostEvent( self, new_event )
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
if self._monthly_allowed and self._monthly.GetValue():
|
||||
|
||||
return None
|
||||
|
||||
|
||||
value = 0
|
||||
|
||||
if self._show_days:
|
||||
|
||||
value += self._days.GetValue() * 86400
|
||||
|
||||
|
||||
if self._show_hours:
|
||||
|
||||
value += self._hours.GetValue() * 3600
|
||||
|
||||
|
||||
if self._show_minutes:
|
||||
|
||||
value += self._minutes.GetValue() * 60
|
||||
|
||||
|
||||
if self._show_seconds:
|
||||
|
||||
value += self._seconds.GetValue()
|
||||
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def SetValue( self, value ):
|
||||
|
||||
if self._monthly_allowed:
|
||||
|
||||
if value is None:
|
||||
|
||||
self._monthly.SetValue( True )
|
||||
|
||||
else:
|
||||
|
||||
self._monthly.SetValue( False )
|
||||
|
||||
|
||||
|
||||
if value is not None:
|
||||
|
||||
if value < self._min:
|
||||
|
||||
value = self._min
|
||||
|
||||
|
||||
if self._show_days:
|
||||
|
||||
self._days.SetValue( value / 86400 )
|
||||
|
||||
value %= 86400
|
||||
|
||||
|
||||
if self._show_hours:
|
||||
|
||||
self._hours.SetValue( value / 3600 )
|
||||
|
||||
value %= 3600
|
||||
|
||||
|
||||
if self._show_minutes:
|
||||
|
||||
self._minutes.SetValue( value / 60 )
|
||||
|
||||
value %= 60
|
||||
|
||||
|
||||
if self._show_seconds:
|
||||
|
||||
self._seconds.SetValue( value )
|
||||
|
||||
|
||||
|
||||
self._UpdateEnables()
|
||||
|
||||
|
||||
class VelocityCtrl( wx.Panel ):
|
||||
|
||||
def __init__( self, parent, min_time_delta = 60, days = False, hours = False, minutes = False, seconds = False, per_phrase = 'per', unit = None ):
|
||||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
self._num = wx.SpinCtrl( self, min = 0, max = 1000, size = ( 60, -1 ) )
|
||||
|
||||
self._times = TimeDeltaCtrl( self, min = min_time_delta, days = days, hours = hours, minutes = minutes, seconds = seconds )
|
||||
|
||||
#
|
||||
|
||||
hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
hbox.AddF( self._num, CC.FLAGS_VCENTER )
|
||||
|
||||
mid_text = per_phrase
|
||||
|
||||
if unit is not None:
|
||||
|
||||
mid_text = unit + ' ' + mid_text
|
||||
|
||||
|
||||
hbox.AddF( BetterStaticText( self, mid_text ), CC.FLAGS_VCENTER )
|
||||
|
||||
hbox.AddF( self._times, CC.FLAGS_VCENTER )
|
||||
|
||||
self.SetSizer( hbox )
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
num = self._num.GetValue()
|
||||
time_delta = self._times.GetValue()
|
||||
|
||||
return ( num, time_delta )
|
||||
|
||||
|
||||
def SetToolTipString( self, text ):
|
||||
|
||||
wx.Panel.SetToolTipString( self, text )
|
||||
|
||||
for c in self.GetChildren():
|
||||
|
||||
c.SetToolTipString( text )
|
||||
|
||||
|
||||
|
||||
def SetValue( self, velocity ):
|
||||
|
||||
( num, time_delta ) = velocity
|
||||
|
||||
self._num.SetValue( num )
|
||||
|
||||
self._times.SetValue( time_delta )
|
||||
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import ClientGUIDialogs
|
|||
import ClientGUIListCtrl
|
||||
import ClientGUIMenus
|
||||
import ClientGUIScrolledPanels
|
||||
import ClientGUITime
|
||||
import ClientGUITopLevelWindows
|
||||
import HydrusConstants as HC
|
||||
import HydrusData
|
||||
|
@ -153,7 +154,7 @@ class BandwidthRulesCtrl( ClientGUICommon.StaticBox ):
|
|||
|
||||
self._bandwidth_type.Bind( wx.EVT_CHOICE, self.EventBandwidth )
|
||||
|
||||
self._time_delta = ClientGUICommon.TimeDeltaButton( self, min = 1, days = True, hours = True, minutes = True, seconds = True, monthly_allowed = True )
|
||||
self._time_delta = ClientGUITime.TimeDeltaButton( self, min = 1, days = True, hours = True, minutes = True, seconds = True, monthly_allowed = True )
|
||||
|
||||
self._max_allowed = wx.SpinCtrl( self, min = 1, max = 1024 * 1024 * 1024 )
|
||||
|
||||
|
@ -230,22 +231,21 @@ class EditStringToStringDictControl( wx.Panel ):
|
|||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
listctrl_panel = ClientGUIListCtrl.SaneListCtrlPanel( self )
|
||||
listctrl_panel = ClientGUIListCtrl.BetterListCtrlPanel( self )
|
||||
|
||||
self._listctrl = ClientGUIListCtrl.SaneListCtrl( listctrl_panel, 120, [ ( 'key', 200 ), ( 'value', -1 ) ], delete_key_callback = self.Delete, activation_callback = self.Edit )
|
||||
self._listctrl = ClientGUIListCtrl.BetterListCtrl( listctrl_panel, 'key_to_value', 10, 36, [ ( 'key', 20 ), ( 'value', -1 ) ], self._ConvertDataToListCtrlTuples, delete_key_callback = self.Delete, activation_callback = self.Edit )
|
||||
|
||||
listctrl_panel.SetListCtrl( self._listctrl )
|
||||
|
||||
listctrl_panel.AddButton( 'add', self.Add )
|
||||
listctrl_panel.AddButton( 'edit', self.Edit, enabled_only_on_selection = True )
|
||||
listctrl_panel.AddButton( 'delete', self.Delete, enabled_only_on_selection = True )
|
||||
listctrl_panel.AddButton( 'add', self._Add )
|
||||
listctrl_panel.AddButton( 'edit', self._Edit, enabled_only_on_selection = True )
|
||||
listctrl_panel.AddButton( 'delete', self._Delete, enabled_only_on_selection = True )
|
||||
|
||||
#
|
||||
|
||||
for display_tuple in initial_dict.items():
|
||||
|
||||
self._listctrl.Append( display_tuple, display_tuple )
|
||||
|
||||
self._listctrl.AddDatas( initial_dict.items() )
|
||||
|
||||
self._listctrl.Sort()
|
||||
|
||||
#
|
||||
|
||||
|
@ -256,7 +256,17 @@ class EditStringToStringDictControl( wx.Panel ):
|
|||
self.SetSizer( vbox )
|
||||
|
||||
|
||||
def Add( self ):
|
||||
def _ConvertDataToListCtrlTuples( self, data ):
|
||||
|
||||
( key, value ) = data
|
||||
|
||||
display_tuple = ( key, value )
|
||||
sort_tuple = ( key, value )
|
||||
|
||||
return ( display_tuple, sort_tuple )
|
||||
|
||||
|
||||
def _Add( self ):
|
||||
|
||||
with ClientGUIDialogs.DialogTextEntry( self, 'enter the key', allow_blank = False ) as dlg:
|
||||
|
||||
|
@ -270,33 +280,31 @@ class EditStringToStringDictControl( wx.Panel ):
|
|||
|
||||
value = dlg.GetValue()
|
||||
|
||||
display_tuple = ( key, value )
|
||||
data = ( key, value )
|
||||
|
||||
self._listctrl.Append( display_tuple, display_tuple )
|
||||
self._listctrl.AddDatas( ( data, ) )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def Delete( self ):
|
||||
def _Delete( self ):
|
||||
|
||||
with ClientGUIDialogs.DialogYesNo( self, 'Remove all selected?' ) as dlg:
|
||||
|
||||
if dlg.ShowModal() == wx.ID_YES:
|
||||
|
||||
self._listctrl.RemoveAllSelected()
|
||||
self._listctrl.DeleteSelected()
|
||||
|
||||
|
||||
|
||||
|
||||
def Edit( self ):
|
||||
def _Edit( self ):
|
||||
|
||||
for i in self._listctrl.GetAllSelected():
|
||||
for data in self._listctrl.GetData( only_selected = True ):
|
||||
|
||||
( key, value ) = self._listctrl.GetClientData( i )
|
||||
|
||||
import ClientGUIDialogs
|
||||
( key, value ) = data
|
||||
|
||||
with ClientGUIDialogs.DialogTextEntry( self, 'edit the key', default = key, allow_blank = False ) as dlg:
|
||||
|
||||
|
@ -306,7 +314,7 @@ class EditStringToStringDictControl( wx.Panel ):
|
|||
|
||||
else:
|
||||
|
||||
return
|
||||
break
|
||||
|
||||
|
||||
|
||||
|
@ -318,19 +326,23 @@ class EditStringToStringDictControl( wx.Panel ):
|
|||
|
||||
else:
|
||||
|
||||
return
|
||||
break
|
||||
|
||||
|
||||
|
||||
display_tuple = ( key, value )
|
||||
self._listctrl.DeleteDatas( ( data, ) )
|
||||
|
||||
self._listctrl.UpdateRow( i, display_tuple, display_tuple )
|
||||
new_data = ( key, value )
|
||||
|
||||
self._listctrl.AddDatas( ( data, ) )
|
||||
|
||||
|
||||
self._listctrl.Sort()
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
value_dict = { key : value for ( key, value ) in self._listctrl.GetClientData() }
|
||||
value_dict = dict( self._listctrl.GetData() )
|
||||
|
||||
return value_dict
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import ClientGUIImport
|
|||
import ClientGUIListBoxes
|
||||
import ClientGUIListCtrl
|
||||
import ClientGUIPredicates
|
||||
import ClientGUITime
|
||||
import ClientGUITopLevelWindows
|
||||
import ClientImporting
|
||||
import ClientThreading
|
||||
|
@ -129,7 +130,7 @@ class Dialog( wx.Dialog ):
|
|||
|
||||
wx.Dialog.__init__( self, parent, title = title, style = style, pos = pos )
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_FRAMEBK ) )
|
||||
|
||||
|
@ -668,6 +669,16 @@ class DialogInputLocalBooruShare( Dialog ):
|
|||
|
||||
self._hashes = hashes
|
||||
|
||||
self._service = HG.client_controller.services_manager.GetService( CC.LOCAL_BOORU_SERVICE_KEY )
|
||||
|
||||
internal_port = self._service.GetPort()
|
||||
|
||||
if internal_port is None:
|
||||
|
||||
self._copy_internal_share_link.Disable()
|
||||
self._copy_external_share_link.Disable()
|
||||
|
||||
|
||||
#
|
||||
|
||||
rows = []
|
||||
|
@ -1459,49 +1470,6 @@ class DialogInputTags( Dialog ):
|
|||
self.EndModal( wx.ID_OK )
|
||||
|
||||
|
||||
class DialogInputTimeDelta( Dialog ):
|
||||
|
||||
def __init__( self, parent, initial_value, min = 1, days = False, hours = False, minutes = False, seconds = False, monthly_allowed = False ):
|
||||
|
||||
Dialog.__init__( self, parent, 'input time delta' )
|
||||
|
||||
self._time_delta = ClientGUICommon.TimeDeltaCtrl( self, min = min, days = days, hours = hours, minutes = minutes, seconds = seconds, monthly_allowed = monthly_allowed )
|
||||
|
||||
self._ok = wx.Button( self, id = wx.ID_OK, label = 'OK' )
|
||||
self._ok.SetForegroundColour( ( 0, 128, 0 ) )
|
||||
|
||||
self._cancel = wx.Button( self, id = wx.ID_CANCEL, label = 'Cancel' )
|
||||
self._cancel.SetForegroundColour( ( 128, 0, 0 ) )
|
||||
|
||||
#
|
||||
|
||||
self._time_delta.SetValue( initial_value )
|
||||
|
||||
#
|
||||
|
||||
b_box = wx.BoxSizer( wx.HORIZONTAL )
|
||||
b_box.AddF( self._ok, CC.FLAGS_VCENTER )
|
||||
b_box.AddF( self._cancel, CC.FLAGS_VCENTER )
|
||||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
vbox.AddF( self._time_delta, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
vbox.AddF( b_box, CC.FLAGS_BUTTON_SIZER )
|
||||
|
||||
self.SetSizer( vbox )
|
||||
|
||||
( x, y ) = self.GetEffectiveMinSize()
|
||||
|
||||
self.SetInitialSize( ( x, y ) )
|
||||
|
||||
wx.CallAfter( self._ok.SetFocus )
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
return self._time_delta.GetValue()
|
||||
|
||||
|
||||
class DialogInputUPnPMapping( Dialog ):
|
||||
|
||||
def __init__( self, parent, external_port, protocol_type, internal_port, description, duration ):
|
||||
|
@ -2231,7 +2199,7 @@ class DialogSetupExport( Dialog ):
|
|||
|
||||
Dialog.__init__( self, parent, 'setup export' )
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
self._tags_box = ClientGUICommon.StaticBoxSorterForListBoxTags( self, 'files\' tags' )
|
||||
|
||||
|
@ -2414,7 +2382,7 @@ class DialogSetupExport( Dialog ):
|
|||
|
||||
pattern = self._pattern.GetValue()
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
new_options.SetKeyList( 'default_neighbouring_txt_tag_service_keys', self._neighbouring_txt_tag_service_keys )
|
||||
|
||||
|
@ -2553,7 +2521,7 @@ class DialogSetupExport( Dialog ):
|
|||
|
||||
pattern = self._pattern.GetValue()
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
new_options.SetString( 'export_phrase', pattern )
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import ClientGUIOptionsPanels
|
|||
import ClientGUIPredicates
|
||||
import ClientGUIScrolledPanelsEdit
|
||||
import ClientGUISeedCache
|
||||
import ClientGUITime
|
||||
import ClientGUITopLevelWindows
|
||||
import ClientImporting
|
||||
import ClientMedia
|
||||
|
@ -1173,7 +1174,7 @@ class DialogManageExportFolders( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def _AddFolder( self ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
phrase = new_options.GetString( 'export_phrase' )
|
||||
|
||||
|
@ -1350,7 +1351,7 @@ class DialogManageExportFoldersEdit( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._period_box = ClientGUICommon.StaticBox( self, 'export period' )
|
||||
|
||||
self._period = ClientGUICommon.TimeDeltaButton( self._period_box, min = 3 * 60, days = True, hours = True, minutes = True )
|
||||
self._period = ClientGUITime.TimeDeltaButton( self._period_box, min = 3 * 60, days = True, hours = True, minutes = True )
|
||||
|
||||
#
|
||||
|
||||
|
@ -2413,7 +2414,7 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._open_popup = wx.CheckBox( self._folder_box )
|
||||
|
||||
self._period = ClientGUICommon.TimeDeltaButton( self._folder_box, min = 3 * 60, days = True, hours = True, minutes = True )
|
||||
self._period = ClientGUITime.TimeDeltaButton( self._folder_box, min = 3 * 60, days = True, hours = True, minutes = True )
|
||||
|
||||
self._paused = wx.CheckBox( self._folder_box )
|
||||
|
||||
|
@ -4836,6 +4837,8 @@ class DialogManageUPnP( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._hidden_cancel = wx.Button( self, id = wx.ID_CANCEL, size = ( 0, 0 ) )
|
||||
|
||||
self._status_st = ClientGUICommon.BetterStaticText( self )
|
||||
|
||||
self._mappings_list_ctrl = ClientGUIListCtrl.SaneListCtrl( self, 480, [ ( 'description', -1 ), ( 'internal ip', 100 ), ( 'internal port', 80 ), ( 'external ip', 100 ), ( 'external port', 80 ), ( 'protocol', 80 ), ( 'lease', 80 ) ], delete_key_callback = self.RemoveMappings, activation_callback = self.EditMappings )
|
||||
|
||||
self._add_custom = wx.Button( self, label = 'add custom mapping' )
|
||||
|
@ -4853,10 +4856,6 @@ class DialogManageUPnP( ClientGUIDialogs.Dialog ):
|
|||
|
||||
#
|
||||
|
||||
self._RefreshMappings()
|
||||
|
||||
#
|
||||
|
||||
edit_buttons = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
edit_buttons.AddF( self._add_custom, CC.FLAGS_VCENTER )
|
||||
|
@ -4865,6 +4864,7 @@ class DialogManageUPnP( ClientGUIDialogs.Dialog ):
|
|||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
vbox.AddF( self._status_st, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._mappings_list_ctrl, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
vbox.AddF( edit_buttons, CC.FLAGS_BUTTON_SIZER )
|
||||
vbox.AddF( self._ok, CC.FLAGS_LONE_BUTTON )
|
||||
|
@ -4877,21 +4877,53 @@ class DialogManageUPnP( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self.SetInitialSize( ( x, y ) )
|
||||
|
||||
wx.CallAfter( self._ok.SetFocus )
|
||||
#
|
||||
|
||||
self._RefreshMappings()
|
||||
|
||||
|
||||
def _RefreshMappings( self ):
|
||||
|
||||
|
||||
def THREADdo_it():
|
||||
|
||||
def wx_code( mappings ):
|
||||
|
||||
if not self:
|
||||
|
||||
return
|
||||
|
||||
|
||||
self._mappings = mappings
|
||||
|
||||
for mapping in self._mappings:
|
||||
|
||||
self._mappings_list_ctrl.Append( mapping, mapping )
|
||||
|
||||
|
||||
self._status_st.SetLabelText( '' )
|
||||
|
||||
|
||||
try:
|
||||
|
||||
mappings = HydrusNATPunch.GetUPnPMappings()
|
||||
|
||||
except Exception as e:
|
||||
|
||||
HydrusData.ShowException( e )
|
||||
|
||||
wx.CallAfter( wx.MessageBox, 'Could not load mappings:' + os.linesep * 2 + str( e ) )
|
||||
|
||||
return
|
||||
|
||||
|
||||
wx.CallAfter( wx_code, mappings )
|
||||
|
||||
|
||||
self._status_st.SetLabelText( 'Refreshing mappings--please wait...' )
|
||||
|
||||
self._mappings_list_ctrl.DeleteAllItems()
|
||||
|
||||
self._mappings = HydrusNATPunch.GetUPnPMappings()
|
||||
|
||||
for mapping in self._mappings:
|
||||
|
||||
self._mappings_list_ctrl.Append( mapping, mapping )
|
||||
|
||||
|
||||
#self._mappings_list_ctrl.SortListItems( 1 )
|
||||
HG.client_controller.CallToThread( THREADdo_it )
|
||||
|
||||
|
||||
def EditMappings( self ):
|
||||
|
@ -4919,7 +4951,10 @@ class DialogManageUPnP( ClientGUIDialogs.Dialog ):
|
|||
|
||||
|
||||
|
||||
if do_refresh: self._RefreshMappings()
|
||||
if do_refresh:
|
||||
|
||||
self._RefreshMappings()
|
||||
|
||||
|
||||
|
||||
def EventAddCustomMapping( self, event ):
|
||||
|
@ -4956,7 +4991,10 @@ class DialogManageUPnP( ClientGUIDialogs.Dialog ):
|
|||
|
||||
|
||||
|
||||
if do_refresh: self._RefreshMappings()
|
||||
if do_refresh:
|
||||
|
||||
self._RefreshMappings()
|
||||
|
||||
|
||||
|
||||
def EventEditMapping( self, event ):
|
||||
|
@ -4987,5 +5025,8 @@ class DialogManageUPnP( ClientGUIDialogs.Dialog ):
|
|||
do_refresh = True
|
||||
|
||||
|
||||
if do_refresh: self._RefreshMappings()
|
||||
if do_refresh:
|
||||
|
||||
self._RefreshMappings()
|
||||
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ class FullscreenHoverFrame( wx.Frame ):
|
|||
|
||||
try:
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
if new_options.GetBoolean( 'always_show_hover_windows' ):
|
||||
|
||||
|
@ -425,7 +425,7 @@ class FullscreenHoverFrameTop( FullscreenHoverFrame ):
|
|||
|
||||
def _SetDefaultShortcuts( self ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
default_media_viewer_custom_shortcuts = new_options.GetStringList( 'default_media_viewer_custom_shortcuts' )
|
||||
|
||||
|
@ -617,7 +617,7 @@ class FullscreenHoverFrameTopDuplicatesFilter( FullscreenHoverFrameTopNavigable
|
|||
|
||||
def _EditBackgroundSwitchIntensity( self ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
value = new_options.GetNoneableInteger( 'duplicate_background_switch_intensity' )
|
||||
|
||||
|
@ -638,7 +638,7 @@ class FullscreenHoverFrameTopDuplicatesFilter( FullscreenHoverFrameTopNavigable
|
|||
|
||||
def _EditMergeOptions( self, duplicate_type ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
duplicate_action_options = new_options.GetDuplicateActionOptions( duplicate_type )
|
||||
|
||||
|
@ -867,25 +867,17 @@ class FullscreenHoverFrameTopRight( FullscreenHoverFrame ):
|
|||
|
||||
urls = self._current_media.GetLocationsManager().GetURLs()
|
||||
|
||||
urls = list( urls )
|
||||
|
||||
urls.sort()
|
||||
|
||||
urls = urls[ : 10 ]
|
||||
|
||||
if urls != self._last_seen_urls:
|
||||
|
||||
self._last_seen_urls = list( urls )
|
||||
|
||||
self._urls_vbox.Clear( deleteWindows = True )
|
||||
|
||||
for url in urls:
|
||||
url_tuples = HG.client_controller.network_engine.domain_manager.ConvertURLsToMediaViewerTuples( urls )
|
||||
|
||||
for ( display_string, url ) in url_tuples:
|
||||
|
||||
parse = urlparse.urlparse( url )
|
||||
|
||||
url_string = parse.hostname
|
||||
|
||||
link = wx.HyperlinkCtrl( self, id = -1, label = url_string, url = url )
|
||||
link = wx.HyperlinkCtrl( self, id = -1, label = display_string, url = url )
|
||||
|
||||
link.SetToolTipString( url )
|
||||
|
||||
|
|
|
@ -606,7 +606,7 @@ class FilenameTaggingOptionsPanel( wx.Panel ):
|
|||
|
||||
try:
|
||||
|
||||
tags = HydrusData.DeserialisePrettyTags( text )
|
||||
tags = HydrusData.DeserialiseNewlinedTexts( text )
|
||||
|
||||
tags = HydrusTags.CleanTags( tags )
|
||||
|
||||
|
|
|
@ -1019,7 +1019,7 @@ class ListBoxTags( ListBox ):
|
|||
|
||||
def _UpdateBackgroundColour( self ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
self._background_colour = new_options.GetColour( CC.COLOUR_TAGS_BOX )
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import HydrusSerialisable
|
|||
import os
|
||||
import wx
|
||||
from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
|
||||
from wx.lib.mixins.listctrl import ColumnSorterMixin
|
||||
|
||||
def SetNonDupeName( obj, disallowed_names ):
|
||||
|
||||
|
@ -26,8 +25,10 @@ def SetNonDupeName( obj, disallowed_names ):
|
|||
|
||||
|
||||
obj.SetName( new_name )
|
||||
|
||||
class SaneListCtrl( wx.ListCtrl, ListCtrlAutoWidthMixin, ColumnSorterMixin ):
|
||||
|
||||
# This used to be ColumnSorterMixin, but it was crashing on sort-click on clients with many pages open
|
||||
# I've disabled it for now because it was still catching people. The transition to BetterListCtrl will nuke the whole thing eventually.
|
||||
class SaneListCtrl( wx.ListCtrl, ListCtrlAutoWidthMixin ):
|
||||
|
||||
def __init__( self, parent, height, columns, delete_key_callback = None, activation_callback = None ):
|
||||
|
||||
|
@ -35,7 +36,6 @@ class SaneListCtrl( wx.ListCtrl, ListCtrlAutoWidthMixin, ColumnSorterMixin ):
|
|||
|
||||
wx.ListCtrl.__init__( self, parent, style = wx.LC_REPORT )
|
||||
ListCtrlAutoWidthMixin.__init__( self )
|
||||
ColumnSorterMixin.__init__( self, num_columns )
|
||||
|
||||
self.itemDataMap = {}
|
||||
self._data_indices_to_sort_indices = {}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import HydrusConstants as HC
|
||||
import HydrusAudioHandling
|
||||
import ClientDownloading
|
||||
import HydrusExceptions
|
||||
import HydrusPaths
|
||||
|
@ -21,6 +20,7 @@ import ClientGUIMedia
|
|||
import ClientGUIMenus
|
||||
import ClientGUIScrolledPanelsEdit
|
||||
import ClientGUISeedCache
|
||||
import ClientGUITime
|
||||
import ClientGUITopLevelWindows
|
||||
import ClientImporting
|
||||
import ClientMedia
|
||||
|
@ -67,7 +67,7 @@ def CreateManagementController( page_name, management_type, file_service_key = N
|
|||
file_service_key = CC.COMBINED_LOCAL_FILE_SERVICE_KEY
|
||||
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
management_controller = ManagementController( page_name )
|
||||
|
||||
|
@ -867,7 +867,7 @@ class ManagementPanelDuplicateFilter( ManagementPanel ):
|
|||
|
||||
#
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
new_options = self._controller.new_options
|
||||
|
||||
self._search_distance_spinctrl.SetValue( new_options.GetInteger( 'similar_files_duplicate_pairs_search_distance' ) )
|
||||
|
||||
|
@ -1148,7 +1148,7 @@ class ManagementPanelDuplicateFilter( ManagementPanel ):
|
|||
|
||||
search_distance = self._search_distance_spinctrl.GetValue()
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
new_options = self._controller.new_options
|
||||
|
||||
new_options.SetInteger( 'similar_files_duplicate_pairs_search_distance', search_distance )
|
||||
|
||||
|
@ -2267,7 +2267,7 @@ class ManagementPanelImporterThreadWatcher( ManagementPanelImporter ):
|
|||
|
||||
with ClientGUITopLevelWindows.DialogEdit( self._checker_options_button, 'edit check timings' ) as dlg:
|
||||
|
||||
panel = ClientGUIScrolledPanelsEdit.EditCheckerOptions( dlg, checker_options )
|
||||
panel = ClientGUITime.EditCheckerOptions( dlg, checker_options )
|
||||
|
||||
dlg.SetPanel( panel )
|
||||
|
||||
|
|
|
@ -464,7 +464,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
def _EditDuplicateActionOptions( self, duplicate_type ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
duplicate_action_options = new_options.GetDuplicateActionOptions( duplicate_type )
|
||||
|
||||
|
@ -490,7 +490,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
display_media = self._focussed_media.GetDisplayMedia()
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
media_show_action = new_options.GetMediaShowAction( display_media.GetMime() )
|
||||
|
||||
|
@ -503,7 +503,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
path = client_files_manager.GetFilePath( hash, mime )
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
launch_path = new_options.GetMimeLaunch( mime )
|
||||
|
||||
|
@ -922,7 +922,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
path = client_files_manager.GetFilePath( hash, mime )
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
launch_path = new_options.GetMimeLaunch( mime )
|
||||
|
||||
|
@ -1034,6 +1034,10 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
self._ManageTags()
|
||||
|
||||
elif action == 'manage_file_urls':
|
||||
|
||||
self._ManageURLs()
|
||||
|
||||
elif action == 'archive_file':
|
||||
|
||||
self._Archive()
|
||||
|
@ -1050,6 +1054,22 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
self._Remove()
|
||||
|
||||
elif action == 'get_similar_to_exact':
|
||||
|
||||
self._GetSimilarTo( HC.HAMMING_EXACT_MATCH )
|
||||
|
||||
elif action == 'get_similar_to_very_similar':
|
||||
|
||||
self._GetSimilarTo( HC.HAMMING_VERY_SIMILAR )
|
||||
|
||||
elif action == 'get_similar_to_similar':
|
||||
|
||||
self._GetSimilarTo( HC.HAMMING_SIMILAR )
|
||||
|
||||
elif action == 'get_similar_to_speculative':
|
||||
|
||||
self._GetSimilarTo( HC.HAMMING_SPECULATIVE )
|
||||
|
||||
elif action == 'open_file_in_external_program':
|
||||
|
||||
self._OpenExternally()
|
||||
|
@ -1282,7 +1302,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
yes_no_text = 'set all pair relationships to ' + HC.duplicate_type_string_lookup[ duplicate_type ] + ' (with default duplicate action/merge options)'
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
duplicate_action_options = new_options.GetDuplicateActionOptions( duplicate_type )
|
||||
|
||||
|
@ -1358,7 +1378,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
duplicate_type = dlg_1.GetChoice()
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
duplicate_action_options = new_options.GetDuplicateActionOptions( duplicate_type )
|
||||
|
||||
|
@ -1517,7 +1537,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
def _UpdateBackgroundColour( self ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
self.SetBackgroundColour( new_options.GetColour( CC.COLOUR_THUMBGRID_BACKGROUND ) )
|
||||
|
||||
|
@ -1865,7 +1885,7 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
dc = wx.MemoryDC( bmp )
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
dc.SetBackground( wx.Brush( new_options.GetColour( CC.COLOUR_THUMBGRID_BACKGROUND ) ) )
|
||||
|
||||
|
@ -2326,7 +2346,7 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
( thumbnail_span_width, thumbnail_span_height ) = self._GetThumbnailSpanDimensions()
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
percent_visible = new_options.GetInteger( 'thumbnail_visibility_scroll_percent' ) / float( 100 )
|
||||
|
||||
|
@ -2460,7 +2480,7 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
do_temp_dnd = False
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
if new_options.GetBoolean( 'discord_dnd_fix' ):
|
||||
|
||||
|
@ -2718,7 +2738,7 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
def EventShowMenu( self, event ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
advanced_mode = new_options.GetBoolean( 'advanced_mode' )
|
||||
|
||||
|
@ -3871,7 +3891,7 @@ class Thumbnail( Selectable ):
|
|||
|
||||
dc = wx.MemoryDC( bmp )
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
if not local:
|
||||
|
||||
|
@ -3947,7 +3967,7 @@ class Thumbnail( Selectable ):
|
|||
chapters = namespaces[ 'chapter' ]
|
||||
pages = namespaces[ 'page' ]
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
if new_options.GetBoolean( 'show_thumbnail_page' ):
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ class DialogPageChooser( ClientGUIDialogs.Dialog ):
|
|||
|
||||
search_enabled = True
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
new_options = self._controller.new_options
|
||||
|
||||
tag_service_key = new_options.GetKey( 'default_tag_service_search_page' )
|
||||
|
||||
|
@ -901,7 +901,7 @@ class PagesNotebook( wx.Notebook ):
|
|||
|
||||
def _GetDefaultPageInsertionIndex( self ):
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
new_options = self._controller.new_options
|
||||
|
||||
new_page_goes = new_options.GetInteger( 'default_new_page_goes' )
|
||||
|
||||
|
@ -1105,7 +1105,7 @@ class PagesNotebook( wx.Notebook ):
|
|||
return
|
||||
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
new_options = self._controller.new_options
|
||||
|
||||
max_page_name_chars = new_options.GetInteger( 'max_page_name_chars' )
|
||||
|
||||
|
@ -1756,26 +1756,38 @@ class PagesNotebook( wx.Notebook ):
|
|||
return current_page.NewPage( management_controller, initial_hashes = initial_hashes, forced_insertion_index = forced_insertion_index, on_deepest_notebook = on_deepest_notebook )
|
||||
|
||||
|
||||
WARNING_TOTAL_PAGES = 165
|
||||
MAX_TOTAL_PAGES = 200
|
||||
|
||||
( total_active_page_count, total_closed_page_count ) = self._controller.gui.GetTotalPageCounts()
|
||||
|
||||
if total_active_page_count + total_closed_page_count >= WARNING_TOTAL_PAGES:
|
||||
|
||||
self._controller.gui.DeleteAllClosedPages()
|
||||
|
||||
|
||||
if not HG.no_page_limit_mode:
|
||||
|
||||
WARNING_TOTAL_PAGES = 200
|
||||
MAX_TOTAL_PAGES = 165
|
||||
|
||||
( total_active_page_count, total_closed_page_count ) = self._controller.gui.GetTotalPageCounts()
|
||||
|
||||
if total_active_page_count + total_closed_page_count >= MAX_TOTAL_PAGES:
|
||||
|
||||
self._controller.gui.DeleteAllClosedPages()
|
||||
|
||||
|
||||
if total_active_page_count >= MAX_TOTAL_PAGES:
|
||||
|
||||
HydrusData.ShowText( 'The client cannot have more than ' + str( MAX_TOTAL_PAGES ) + ' pages open! For system stability reasons, please close some now!' )
|
||||
message = 'The client should not have more than ' + str( MAX_TOTAL_PAGES ) + ' pages open, as it leads to program instability! Are you sure you want to open more pages?'
|
||||
|
||||
return
|
||||
with ClientGUIDialogs.DialogYesNo( self, message, title = 'Too many pages!', yes_label = 'yes, and do not tell me again', no_label = 'no' ) as dlg:
|
||||
|
||||
if dlg.ShowModal() == wx.ID_YES:
|
||||
|
||||
HG.no_page_limit_mode = True
|
||||
|
||||
self._controller.pub( 'notify_new_options' )
|
||||
|
||||
else:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
if total_active_page_count == WARNING_TOTAL_PAGES - 5:
|
||||
if total_active_page_count == WARNING_TOTAL_PAGES:
|
||||
|
||||
HydrusData.ShowText( 'You have ' + str( total_active_page_count ) + ' pages open! You can only open a few more before system stability is affected! Please close some now!' )
|
||||
|
||||
|
@ -1899,7 +1911,7 @@ class PagesNotebook( wx.Notebook ):
|
|||
|
||||
search_enabled = len( initial_hashes ) == 0
|
||||
|
||||
new_options = self._controller.GetNewOptions()
|
||||
new_options = self._controller.new_options
|
||||
|
||||
tag_service_key = new_options.GetKey( 'default_tag_service_search_page' )
|
||||
|
||||
|
@ -2114,7 +2126,7 @@ class PagesNotebook( wx.Notebook ):
|
|||
|
||||
follow_dropped_page = not shift_down
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
if new_options.GetBoolean( 'reverse_page_shift_drag_behaviour' ):
|
||||
|
||||
|
|
|
@ -111,129 +111,6 @@ class ReviewServicePanel( wx.Panel ):
|
|||
|
||||
|
||||
|
||||
if service_type == HC.LOCAL_BOORU:
|
||||
|
||||
booru_shares = self._controller.Read( 'local_booru_shares' )
|
||||
|
||||
self._booru_shares.DeleteAllItems()
|
||||
|
||||
for ( share_key, info ) in booru_shares.items():
|
||||
|
||||
name = info[ 'name' ]
|
||||
text = info[ 'text' ]
|
||||
timeout = info[ 'timeout' ]
|
||||
hashes = info[ 'hashes' ]
|
||||
|
||||
self._booru_shares.Append( ( name, text, HydrusData.ConvertTimestampToPrettyExpires( timeout ), len( hashes ) ), ( name, text, timeout, ( len( hashes ), hashes, share_key ) ) )
|
||||
|
||||
|
||||
|
||||
|
||||
def DeleteBoorus( self ):
|
||||
|
||||
with ClientGUIDialogs.DialogYesNo( self, 'Remove all selected?' ) as dlg:
|
||||
|
||||
if dlg.ShowModal() == wx.ID_YES:
|
||||
|
||||
for ( name, text, timeout, ( num_hashes, hashes, share_key ) ) in self._booru_shares.GetSelectedClientData():
|
||||
|
||||
self._controller.Write( 'delete_local_booru_share', share_key )
|
||||
|
||||
|
||||
self._booru_shares.RemoveAllSelected()
|
||||
|
||||
|
||||
|
||||
|
||||
def EditBoorus( self ):
|
||||
|
||||
writes = []
|
||||
|
||||
for ( name, text, timeout, ( num_hashes, hashes, share_key ) ) in self._booru_shares.GetSelectedClientData():
|
||||
|
||||
with ClientGUIDialogs.DialogInputLocalBooruShare( self, share_key, name, text, timeout, hashes, new_share = False) as dlg:
|
||||
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
|
||||
( share_key, name, text, timeout, hashes ) = dlg.GetInfo()
|
||||
|
||||
info = {}
|
||||
|
||||
info[ 'name' ] = name
|
||||
info[ 'text' ] = text
|
||||
info[ 'timeout' ] = timeout
|
||||
info[ 'hashes' ] = hashes
|
||||
|
||||
writes.append( ( share_key, info ) )
|
||||
|
||||
|
||||
|
||||
|
||||
for ( share_key, info ) in writes:
|
||||
|
||||
self._controller.Write( 'local_booru_share', share_key, info )
|
||||
|
||||
|
||||
|
||||
def EventBooruDelete( self, event ):
|
||||
|
||||
self.DeleteBoorus()
|
||||
|
||||
|
||||
def EventBooruEdit( self, event ):
|
||||
|
||||
self.EditBoorus()
|
||||
|
||||
|
||||
def EventBooruOpenSearch( self, event ):
|
||||
|
||||
for ( name, text, timeout, ( num_hashes, hashes, share_key ) ) in self._booru_shares.GetSelectedClientData():
|
||||
|
||||
self._controller.pub( 'new_page_query', CC.LOCAL_FILE_SERVICE_KEY, initial_hashes = hashes, page_name = 'booru share' )
|
||||
|
||||
|
||||
|
||||
def EventCopyExternalShareURL( self, event ):
|
||||
|
||||
shares = self._booru_shares.GetSelectedClientData()
|
||||
|
||||
if len( shares ) > 0:
|
||||
|
||||
( name, text, timeout, ( num_hashes, hashes, share_key ) ) = shares[0]
|
||||
|
||||
info = self._service.GetInfo()
|
||||
|
||||
external_ip = HydrusNATPunch.GetExternalIP() # eventually check for optional host replacement here
|
||||
|
||||
external_port = info[ 'upnp' ]
|
||||
|
||||
if external_port is None: external_port = info[ 'port' ]
|
||||
|
||||
url = 'http://' + external_ip + ':' + HydrusData.ToUnicode( external_port ) + '/gallery?share_key=' + share_key.encode( 'hex' )
|
||||
|
||||
self._controller.pub( 'clipboard', 'text', url )
|
||||
|
||||
|
||||
|
||||
def EventCopyInternalShareURL( self, event ):
|
||||
|
||||
shares = self._booru_shares.GetSelectedClientData()
|
||||
|
||||
if len( shares ) > 0:
|
||||
|
||||
( name, text, timeout, ( num_hashes, hashes, share_key ) ) = shares[0]
|
||||
|
||||
info = self._service.GetInfo()
|
||||
|
||||
internal_ip = '127.0.0.1'
|
||||
|
||||
internal_port = info[ 'port' ]
|
||||
|
||||
url = 'http://' + internal_ip + ':' + str( internal_port ) + '/gallery?share_key=' + share_key.encode( 'hex' )
|
||||
|
||||
self._controller.pub( 'clipboard', 'text', url )
|
||||
|
||||
|
||||
|
||||
def EventDeleteLocalDeleted( self, event ):
|
||||
|
||||
|
@ -331,11 +208,6 @@ class ReviewServicePanel( wx.Panel ):
|
|||
return self._service.GetServiceKey()
|
||||
|
||||
|
||||
def RefreshLocalBooruShares( self ):
|
||||
|
||||
self._DisplayService()
|
||||
|
||||
|
||||
class _ServicePanel( ClientGUICommon.StaticBox ):
|
||||
|
||||
def __init__( self, parent, service ):
|
||||
|
@ -748,7 +620,7 @@ class ReviewServicePanel( wx.Panel ):
|
|||
|
||||
#
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
if not new_options.GetBoolean( 'advanced_mode' ):
|
||||
|
||||
|
@ -986,9 +858,7 @@ class ReviewServicePanel( wx.Panel ):
|
|||
|
||||
service_paused = self._service.IsPaused()
|
||||
|
||||
options = HG.client_controller.GetOptions()
|
||||
|
||||
all_repo_sync_paused = options[ 'pause_repo_sync' ]
|
||||
all_repo_sync_paused = HG.client_controller.options[ 'pause_repo_sync' ]
|
||||
|
||||
if service_paused or all_repo_sync_paused or not processing_work_to_do:
|
||||
|
||||
|
@ -1258,9 +1128,26 @@ class ReviewServicePanel( wx.Panel ):
|
|||
|
||||
self._service = service
|
||||
|
||||
self._share_key_info = {}
|
||||
|
||||
self._my_updater = ClientGUICommon.ThreadToGUIUpdater( self, self._Refresh )
|
||||
|
||||
self._name_and_type = ClientGUICommon.BetterStaticText( self )
|
||||
self._service_status = ClientGUICommon.BetterStaticText( self )
|
||||
|
||||
booru_search_panel = ClientGUIListCtrl.BetterListCtrlPanel( self )
|
||||
|
||||
self._booru_shares = ClientGUIListCtrl.BetterListCtrl( booru_search_panel, 'local_booru_shares', 10, 36, [ ( 'name', -1 ), ( 'info', 36 ), ( 'expires', 12 ), ( 'files', 12 ) ], self._ConvertDataToListCtrlTuple, delete_key_callback = self._Delete, activation_callback = self._Edit )
|
||||
|
||||
booru_search_panel.SetListCtrl( self._booru_shares )
|
||||
|
||||
booru_search_panel.AddButton( 'edit', self._Edit, enabled_only_on_selection = True )
|
||||
booru_search_panel.AddButton( 'delete', self._Delete, enabled_only_on_selection = True )
|
||||
booru_search_panel.AddSeparator()
|
||||
booru_search_panel.AddButton( 'open in new page', self._OpenSearch, enabled_only_on_selection = True )
|
||||
booru_search_panel.AddButton( 'copy internal share url', self._CopyInternalShareURL, enabled_check_func = self._CanCopyURL )
|
||||
booru_search_panel.AddButton( 'copy external share url', self._CopyExternalShareURL, enabled_check_func = self._CanCopyURL )
|
||||
|
||||
self._booru_shares.Sort()
|
||||
|
||||
#
|
||||
|
||||
|
@ -1268,11 +1155,173 @@ class ReviewServicePanel( wx.Panel ):
|
|||
|
||||
#
|
||||
|
||||
self.AddF( self._name_and_type, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
self.AddF( self._service_status, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
self.AddF( booru_search_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
HG.client_controller.sub( self, 'ServiceUpdated', 'service_updated' )
|
||||
|
||||
|
||||
def _CanCopyURL( self ):
|
||||
|
||||
has_selected = self._booru_shares.HasSelected()
|
||||
service_is_running = self._service.GetPort() is not None
|
||||
|
||||
return has_selected and service_is_running
|
||||
|
||||
|
||||
def _ConvertDataToListCtrlTuple( self, share_key ):
|
||||
|
||||
info = self._share_key_info[ share_key ]
|
||||
|
||||
name = info[ 'name' ]
|
||||
text = info[ 'text' ]
|
||||
timeout = info[ 'timeout' ]
|
||||
hashes = info[ 'hashes' ]
|
||||
|
||||
num_hashes = len( hashes )
|
||||
|
||||
pretty_name = name
|
||||
pretty_text = text
|
||||
pretty_timeout = HydrusData.ConvertTimestampToPrettyExpires( timeout )
|
||||
pretty_hashes = HydrusData.ConvertIntToPrettyString( num_hashes )
|
||||
|
||||
display_tuple = ( pretty_name, pretty_text, pretty_timeout, pretty_hashes )
|
||||
sort_tuple = ( name, text, timeout, num_hashes )
|
||||
|
||||
return ( display_tuple, sort_tuple )
|
||||
|
||||
|
||||
def _CopyExternalShareURL( self ):
|
||||
|
||||
try:
|
||||
|
||||
external_ip = HydrusNATPunch.GetExternalIP()
|
||||
|
||||
except Exception as e:
|
||||
|
||||
wx.MessageBox( unicode( e ) )
|
||||
|
||||
return
|
||||
|
||||
|
||||
internal_port = self._service.GetPort()
|
||||
|
||||
if internal_port is None:
|
||||
|
||||
wx.MessageBox( 'The local booru is not currently running!' )
|
||||
|
||||
|
||||
external_port = self._service.GetUPnPPort()
|
||||
|
||||
if external_port is None:
|
||||
|
||||
external_port = internal_port
|
||||
|
||||
|
||||
urls = []
|
||||
|
||||
for share_key in self._booru_shares.GetData( only_selected = True ):
|
||||
|
||||
url = 'http://' + external_ip + ':' + HydrusData.ToUnicode( external_port ) + '/gallery?share_key=' + share_key.encode( 'hex' )
|
||||
|
||||
urls.append( url )
|
||||
|
||||
|
||||
text = os.linesep.join( urls )
|
||||
|
||||
HG.client_controller.pub( 'clipboard', 'text', text )
|
||||
|
||||
|
||||
def _CopyInternalShareURL( self ):
|
||||
|
||||
internal_ip = '127.0.0.1'
|
||||
|
||||
internal_port = self._service.GetPort()
|
||||
|
||||
if internal_port is None:
|
||||
|
||||
wx.MessageBox( 'The local booru is not currently running!' )
|
||||
|
||||
|
||||
urls = []
|
||||
|
||||
for share_key in self._booru_shares.GetData( only_selected = True ):
|
||||
|
||||
url = 'http://' + internal_ip + ':' + str( internal_port ) + '/gallery?share_key=' + share_key.encode( 'hex' )
|
||||
|
||||
urls.append( url )
|
||||
|
||||
|
||||
text = os.linesep.join( urls )
|
||||
|
||||
HG.client_controller.pub( 'clipboard', 'text', text )
|
||||
|
||||
|
||||
def _Delete( self ):
|
||||
|
||||
with ClientGUIDialogs.DialogYesNo( self, 'Remove all selected?' ) as dlg:
|
||||
|
||||
if dlg.ShowModal() == wx.ID_YES:
|
||||
|
||||
for share_key in self._booru_shares.GetData( only_selected = True ):
|
||||
|
||||
HG.client_controller.Write( 'delete_local_booru_share', share_key )
|
||||
|
||||
|
||||
self._booru_shares.DeleteSelected()
|
||||
|
||||
|
||||
|
||||
|
||||
def _Edit( self ):
|
||||
|
||||
for share_key in self._booru_shares.GetData( only_selected = True ):
|
||||
|
||||
info = self._share_key_info[ share_key ]
|
||||
|
||||
name = info[ 'name' ]
|
||||
text = info[ 'text' ]
|
||||
timeout = info[ 'timeout' ]
|
||||
hashes = info[ 'hashes' ]
|
||||
|
||||
with ClientGUIDialogs.DialogInputLocalBooruShare( self, share_key, name, text, timeout, hashes, new_share = False) as dlg:
|
||||
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
|
||||
( share_key, name, text, timeout, hashes ) = dlg.GetInfo()
|
||||
|
||||
info = {}
|
||||
|
||||
info[ 'name' ] = name
|
||||
info[ 'text' ] = text
|
||||
info[ 'timeout' ] = timeout
|
||||
info[ 'hashes' ] = hashes
|
||||
|
||||
HG.client_controller.Write( 'local_booru_share', share_key, info )
|
||||
|
||||
else:
|
||||
|
||||
break
|
||||
|
||||
|
||||
|
||||
|
||||
self._Refresh()
|
||||
|
||||
|
||||
def _OpenSearch( self ):
|
||||
|
||||
for share_key in self._booru_shares.GetData( only_selected = True ):
|
||||
|
||||
info = self._share_key_info[ share_key ]
|
||||
|
||||
name = info[ 'name' ]
|
||||
hashes = info[ 'hashes' ]
|
||||
|
||||
HG.client_controller.pub( 'new_page_query', CC.LOCAL_FILE_SERVICE_KEY, initial_hashes = hashes, page_name = 'booru share: ' + name )
|
||||
|
||||
|
||||
|
||||
def _Refresh( self ):
|
||||
|
||||
if not self:
|
||||
|
@ -1280,7 +1329,20 @@ class ReviewServicePanel( wx.Panel ):
|
|||
return
|
||||
|
||||
|
||||
self._name_and_type.SetLabelText( 'This is a Local Booru service. This box will regain its old information and controls in a later version.' )
|
||||
port = self._service.GetPort()
|
||||
|
||||
if port is None:
|
||||
|
||||
status = 'The local booru is not running.'
|
||||
|
||||
else:
|
||||
|
||||
status = 'The local booru should be running on port ' + str( port ) + '.'
|
||||
|
||||
|
||||
self._service_status.SetLabelText( status )
|
||||
|
||||
HG.client_controller.CallToThread( self.THREADFetchInfo )
|
||||
|
||||
|
||||
def ServiceUpdated( self, service ):
|
||||
|
@ -1293,6 +1355,27 @@ class ReviewServicePanel( wx.Panel ):
|
|||
|
||||
|
||||
|
||||
def THREADFetchInfo( self ):
|
||||
|
||||
def wx_code( booru_shares ):
|
||||
|
||||
if not self:
|
||||
|
||||
return
|
||||
|
||||
|
||||
self._share_key_info.update( booru_shares )
|
||||
|
||||
self._booru_shares.SetData( booru_shares.keys() )
|
||||
|
||||
self._booru_shares.Sort()
|
||||
|
||||
|
||||
booru_shares = HG.client_controller.Read( 'local_booru_shares' )
|
||||
|
||||
wx.CallAfter( wx_code, booru_shares )
|
||||
|
||||
|
||||
|
||||
class _ServiceRatingPanel( ClientGUICommon.StaticBox ):
|
||||
|
||||
|
@ -1368,7 +1451,7 @@ class ReviewServicePanel( wx.Panel ):
|
|||
|
||||
#
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
advanced_mode = new_options.GetBoolean( 'advanced_mode' )
|
||||
|
||||
|
|
|
@ -656,7 +656,7 @@ class PopupMessageManager( wx.Frame ):
|
|||
|
||||
going_to_bug_out_at_hide_or_show = windows_and_iconised or possibly_on_hidden_virtual_desktop
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
if new_options.GetBoolean( 'hide_message_manager_on_gui_iconise' ):
|
||||
|
||||
|
|
|
@ -30,6 +30,33 @@ class EditPanel( ResizingScrolledPanel ):
|
|||
raise NotImplementedError()
|
||||
|
||||
|
||||
class EditSingleCtrlPanel( EditPanel ):
|
||||
|
||||
def __init__( self, parent ):
|
||||
|
||||
EditPanel.__init__( self, parent )
|
||||
|
||||
self._control = None
|
||||
|
||||
#
|
||||
|
||||
self._vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
self.SetSizer( self._vbox )
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
return self._control.GetValue()
|
||||
|
||||
|
||||
def SetControl( self, control ):
|
||||
|
||||
self._control = control
|
||||
|
||||
self._vbox.AddF( control, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
|
||||
class ManagePanel( ResizingScrolledPanel ):
|
||||
|
||||
def CanCancel( self ):
|
||||
|
|
|
@ -13,6 +13,7 @@ import ClientGUIListCtrl
|
|||
import ClientGUIMenus
|
||||
import ClientGUIScrolledPanels
|
||||
import ClientGUISeedCache
|
||||
import ClientGUITime
|
||||
import ClientGUITopLevelWindows
|
||||
import ClientNetworking
|
||||
import ClientNetworkingDomain
|
||||
|
@ -1784,6 +1785,7 @@ class EditSubscriptionPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
queries_panel.SetListCtrl( self._queries )
|
||||
|
||||
queries_panel.AddButton( 'add', self._AddQuery )
|
||||
queries_panel.AddButton( 'paste queries', self._PasteQueries )
|
||||
queries_panel.AddButton( 'edit', self._EditQuery, enabled_only_on_selection = True )
|
||||
queries_panel.AddButton( 'delete', self._DeleteQuery, enabled_only_on_selection = True )
|
||||
queries_panel.AddSeparator()
|
||||
|
@ -1967,7 +1969,7 @@ class EditSubscriptionPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
( namespaces, search_value ) = ClientDefaults.GetDefaultNamespacesAndSearchValue( gallery_identifier )
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
tag_import_options = new_options.GetDefaultTagImportOptions( gallery_identifier )
|
||||
|
||||
|
@ -2050,7 +2052,7 @@ class EditSubscriptionPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
with ClientGUITopLevelWindows.DialogEdit( self._checker_options_button, 'edit check timings' ) as dlg:
|
||||
|
||||
panel = EditCheckerOptions( dlg, self._checker_options )
|
||||
panel = ClientGUITime.EditCheckerOptions( dlg, self._checker_options )
|
||||
|
||||
dlg.SetPanel( panel )
|
||||
|
||||
|
@ -2166,6 +2168,47 @@ class EditSubscriptionPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
return False
|
||||
|
||||
|
||||
def _PasteQueries( self ):
|
||||
|
||||
message = 'This will add new queries by pulling them from your clipboard. It assumes they are currently in your clipboard and newline separated. Is that ok?'
|
||||
|
||||
with ClientGUIDialogs.DialogYesNo( self, message ) as dlg:
|
||||
|
||||
if dlg.ShowModal() != wx.ID_YES:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
if wx.TheClipboard.Open():
|
||||
|
||||
data = wx.TextDataObject()
|
||||
|
||||
wx.TheClipboard.GetData( data )
|
||||
|
||||
wx.TheClipboard.Close()
|
||||
|
||||
text = data.GetText()
|
||||
|
||||
try:
|
||||
|
||||
query_texts = HydrusData.DeserialiseNewlinedTexts( text )
|
||||
|
||||
queries = [ ClientImporting.SubscriptionQuery( query_text ) for query_text in query_texts ]
|
||||
|
||||
self._queries.AddDatas( queries )
|
||||
|
||||
except:
|
||||
|
||||
wx.MessageBox( 'I could not understand what was in the clipboard' )
|
||||
|
||||
|
||||
else:
|
||||
|
||||
wx.MessageBox( 'I could not get permission to access the clipboard.' )
|
||||
|
||||
|
||||
|
||||
def _PausePlay( self ):
|
||||
|
||||
selected_queries = self._queries.GetData( only_selected = True )
|
||||
|
@ -2851,7 +2894,7 @@ class EditURLMatchPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
self._url_type = ClientGUICommon.BetterChoice( self )
|
||||
|
||||
for url_type in ( HC.URL_TYPE_POST, HC.URL_TYPE_GALLERY, HC.URL_TYPE_API, HC.URL_TYPE_FILE ):
|
||||
for url_type in ( HC.URL_TYPE_POST, HC.URL_TYPE_GALLERY, HC.URL_TYPE_FILE ):
|
||||
|
||||
self._url_type.Append( HC.url_type_string_lookup[ url_type ], url_type )
|
||||
|
||||
|
@ -3240,7 +3283,7 @@ class EditURLMatchesPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
self._list_ctrl_panel = ClientGUIListCtrl.BetterListCtrlPanel( self )
|
||||
|
||||
self._list_ctrl = ClientGUIListCtrl.BetterListCtrl( self._list_ctrl_panel, 'url_matches', 15, 40, [ ( 'name', 36 ), ( 'example url', -1 ) ], self._ConvertDataToListCtrlTuples, delete_key_callback = self._Delete, activation_callback = self._Edit )
|
||||
self._list_ctrl = ClientGUIListCtrl.BetterListCtrl( self._list_ctrl_panel, 'url_matches', 15, 40, [ ( 'name', 36 ), ( 'type', 20 ), ( 'example url', -1 ) ], self._ConvertDataToListCtrlTuples, delete_key_callback = self._Delete, activation_callback = self._Edit )
|
||||
|
||||
self._list_ctrl_panel.SetListCtrl( self._list_ctrl )
|
||||
|
||||
|
@ -3303,13 +3346,15 @@ class EditURLMatchesPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
def _ConvertDataToListCtrlTuples( self, url_match ):
|
||||
|
||||
name = url_match.GetName()
|
||||
url_type = url_match.GetURLType()
|
||||
example_url = url_match.GetExampleURL()
|
||||
|
||||
pretty_name = name
|
||||
pretty_url_type = HC.url_type_string_lookup[ url_type ]
|
||||
pretty_example_url = example_url
|
||||
|
||||
display_tuple = ( pretty_name, pretty_example_url )
|
||||
sort_tuple = ( name, example_url )
|
||||
display_tuple = ( pretty_name, pretty_url_type, pretty_example_url )
|
||||
sort_tuple = ( name, url_type, example_url )
|
||||
|
||||
return ( display_tuple, sort_tuple )
|
||||
|
||||
|
@ -3369,84 +3414,193 @@ class EditURLMatchesPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
return url_matches
|
||||
|
||||
|
||||
class EditCheckerOptions( ClientGUIScrolledPanels.EditPanel ):
|
||||
class EditURLMatchLinksPanel( ClientGUIScrolledPanels.EditPanel ):
|
||||
|
||||
def __init__( self, parent, checker_options ):
|
||||
def __init__( self, parent, network_engine, url_match_names_to_display, url_match_names_to_page_parsing_keys, url_match_names_to_gallery_parsing_keys ):
|
||||
|
||||
ClientGUIScrolledPanels.EditPanel.__init__( self, parent )
|
||||
|
||||
help_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.help, self._ShowHelp )
|
||||
help_button.SetToolTipString( 'Show help regarding these checker options.' )
|
||||
self._network_engine = network_engine
|
||||
|
||||
# add statictext or whatever that will update on any updates above to say 'given velocity of blah and last check at blah, next check in 5 mins'
|
||||
# or indeed this could just take the seed cache and last check of the caller, if there is one
|
||||
# this would be more useful to the user, to know 'right, on ok, it'll refresh in 30 mins'
|
||||
self._display_list_ctrl_panel = ClientGUIListCtrl.BetterListCtrlPanel( self )
|
||||
|
||||
self._intended_files_per_check = wx.SpinCtrl( self, min = 1, max = 1000 )
|
||||
self._display_list_ctrl = ClientGUIListCtrl.BetterListCtrl( self._display_list_ctrl_panel, 'url_match_names_to_display', 15, 36, [ ( 'url class', -1 ), ( 'display on media viewer?', 36 ) ], self._ConvertDisplayDataToListCtrlTuples, activation_callback = self._EditDisplay )
|
||||
|
||||
self._never_faster_than = ClientGUICommon.TimeDeltaCtrl( self, min = 30, days = True, hours = True, minutes = True, seconds = True )
|
||||
self._display_list_ctrl_panel.SetListCtrl( self._display_list_ctrl )
|
||||
|
||||
self._never_slower_than = ClientGUICommon.TimeDeltaCtrl( self, min = 600, days = True, hours = True, minutes = True )
|
||||
self._display_list_ctrl_panel.AddButton( 'edit', self._EditDisplay, enabled_only_on_selection = True )
|
||||
|
||||
self._death_file_velocity = ClientGUICommon.VelocityCtrl( self, min_time_delta = 60, days = True, hours = True, minutes = True, per_phrase = 'in', unit = 'files' )
|
||||
self._page_list_ctrl_panel = ClientGUIListCtrl.BetterListCtrlPanel( self )
|
||||
|
||||
self._page_list_ctrl = ClientGUIListCtrl.BetterListCtrl( self._page_list_ctrl_panel, 'url_match_names_to_page_parsing_keys', 15, 36, [ ( 'url class', -1 ), ( 'page parser', 36 ) ], self._ConvertPageDataToListCtrlTuples, activation_callback = self._EditPage )
|
||||
|
||||
self._page_list_ctrl_panel.SetListCtrl( self._page_list_ctrl )
|
||||
|
||||
self._page_list_ctrl_panel.AddButton( 'edit', self._EditPage, enabled_only_on_selection = True )
|
||||
|
||||
self._gallery_list_ctrl_panel = ClientGUIListCtrl.BetterListCtrlPanel( self )
|
||||
|
||||
self._gallery_list_ctrl = ClientGUIListCtrl.BetterListCtrl( self._gallery_list_ctrl_panel, 'url_match_names_to_gallery_parsing_keys', 15, 36, [ ( 'url class', -1 ), ( 'gallery parser', 36 ) ], self._ConvertGalleryDataToListCtrlTuples, activation_callback = self._EditGallery )
|
||||
|
||||
self._gallery_list_ctrl_panel.SetListCtrl( self._gallery_list_ctrl )
|
||||
|
||||
self._gallery_list_ctrl_panel.AddButton( 'edit', self._EditGallery, enabled_only_on_selection = True )
|
||||
|
||||
#
|
||||
|
||||
( intended_files_per_check, never_faster_than, never_slower_than, death_file_velocity ) = checker_options.ToTuple()
|
||||
self._display_list_ctrl.AddDatas( url_match_names_to_display.items() )
|
||||
|
||||
self._intended_files_per_check.SetValue( intended_files_per_check )
|
||||
self._never_faster_than.SetValue( never_faster_than )
|
||||
self._never_slower_than.SetValue( never_slower_than )
|
||||
self._death_file_velocity.SetValue( death_file_velocity )
|
||||
self._display_list_ctrl.Sort( 0 )
|
||||
|
||||
self._page_list_ctrl.AddDatas( url_match_names_to_page_parsing_keys.items() )
|
||||
|
||||
self._page_list_ctrl.Sort( 0 )
|
||||
|
||||
self._gallery_list_ctrl.AddDatas( url_match_names_to_gallery_parsing_keys.items() )
|
||||
|
||||
self._gallery_list_ctrl.Sort( 0 )
|
||||
|
||||
#
|
||||
|
||||
rows = []
|
||||
|
||||
rows.append( ( 'intended new files per check: ', self._intended_files_per_check ) )
|
||||
rows.append( ( 'stop checking if new files found falls below: ', self._death_file_velocity ) )
|
||||
rows.append( ( 'never check faster than once per: ', self._never_faster_than ) )
|
||||
rows.append( ( 'never check slower than once per: ', self._never_slower_than ) )
|
||||
|
||||
gridbox = ClientGUICommon.WrapInGrid( self, rows )
|
||||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
help_hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
st = ClientGUICommon.BetterStaticText( self, 'help for this panel -->' )
|
||||
|
||||
st.SetForegroundColour( wx.Colour( 0, 0, 255 ) )
|
||||
|
||||
help_hbox.AddF( st, CC.FLAGS_VCENTER )
|
||||
help_hbox.AddF( help_button, CC.FLAGS_VCENTER )
|
||||
|
||||
vbox.AddF( help_hbox, CC.FLAGS_LONE_BUTTON )
|
||||
vbox.AddF( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
vbox.AddF( self._display_list_ctrl_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
vbox.AddF( self._page_list_ctrl_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
vbox.AddF( self._gallery_list_ctrl_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
self.SetSizer( vbox )
|
||||
|
||||
|
||||
def _ShowHelp( self ):
|
||||
def _ConvertDisplayDataToListCtrlTuples( self, data ):
|
||||
|
||||
help = 'PROTIP: Do not change anything here unless you understand what it means!'
|
||||
help += os.linesep * 2
|
||||
help += 'After its initialisation check, the checker times future checks so that it will probably find the same specified number of new files each time. When files are being posted frequently, it will check more often. When things are slow, it will slow down as well.'
|
||||
help += os.linesep * 2
|
||||
help += 'For instance, if it were set to try for 5 new files with every check, and at the last check it knew that the last 24 hours had produced 10 new files, it would check again 12 hours later. When that check was done and any new files found, it would then recalculate and repeat the process.'
|
||||
help += os.linesep * 2
|
||||
help += 'If the \'file velocity\' drops below a certain amount, the checker considers the source of files dead and will stop checking. If it falls into this state but you think there might have been a rush of new files, hit the \'check now\' button in an attempt to revive the checker. If there are new files, it will start checking again until they drop off once more.'
|
||||
( url_match_name, display ) = data
|
||||
|
||||
wx.MessageBox( help )
|
||||
pretty_name = url_match_name
|
||||
|
||||
if display:
|
||||
|
||||
pretty_display = 'yes'
|
||||
|
||||
else:
|
||||
|
||||
pretty_display = 'no'
|
||||
|
||||
|
||||
display_tuple = ( pretty_name, pretty_display )
|
||||
sort_tuple = ( url_match_name, display )
|
||||
|
||||
return ( display_tuple, sort_tuple )
|
||||
|
||||
|
||||
def _ConvertGalleryDataToListCtrlTuples( self, data ):
|
||||
|
||||
( url_match_name, gallery_script_key ) = data
|
||||
|
||||
pretty_name = url_match_name
|
||||
|
||||
if gallery_script_key is None:
|
||||
|
||||
pretty_script_key = ''
|
||||
|
||||
else:
|
||||
|
||||
# fetch this from network engine
|
||||
pretty_script_key = 'fetch this from network engine'
|
||||
|
||||
|
||||
display_tuple = ( pretty_name, pretty_script_key )
|
||||
sort_tuple = ( url_match_name, pretty_script_key )
|
||||
|
||||
return ( display_tuple, sort_tuple )
|
||||
|
||||
|
||||
def _ConvertPageDataToListCtrlTuples( self, data ):
|
||||
|
||||
( url_match_name, page_script_key ) = data
|
||||
|
||||
pretty_name = url_match_name
|
||||
|
||||
if page_script_key is None:
|
||||
|
||||
pretty_script_key = ''
|
||||
|
||||
else:
|
||||
|
||||
pretty_script_key = 'fetch this from network engine'
|
||||
|
||||
|
||||
display_tuple = ( pretty_name, pretty_script_key )
|
||||
sort_tuple = ( url_match_name, pretty_script_key )
|
||||
|
||||
return ( display_tuple, sort_tuple )
|
||||
|
||||
|
||||
def _EditDisplay( self ):
|
||||
|
||||
for data in self._display_list_ctrl.GetData( only_selected = True ):
|
||||
|
||||
( url_match_name, display ) = data
|
||||
|
||||
message = 'Show ' + url_match_name + ' in the media viewer?'
|
||||
|
||||
with ClientGUIDialogs.DialogYesNo( self, message, title = 'Show in the media viewer?' ) as dlg:
|
||||
|
||||
result = dlg.ShowModal()
|
||||
|
||||
if result in ( wx.ID_YES, wx.ID_NO ):
|
||||
|
||||
display = result == wx.ID_YES
|
||||
|
||||
self._display_list_ctrl.DeleteDatas( ( data, ) )
|
||||
|
||||
new_data = ( url_match_name, display )
|
||||
|
||||
self._display_list_ctrl.AddDatas( ( new_data, ) )
|
||||
|
||||
else:
|
||||
|
||||
break
|
||||
|
||||
|
||||
|
||||
|
||||
self._display_list_ctrl.Sort()
|
||||
|
||||
|
||||
def _EditGallery( self ):
|
||||
|
||||
for data in self._gallery_list_ctrl.GetData( only_selected = True ):
|
||||
|
||||
( url_match_name, gallery_script_key ) = data
|
||||
|
||||
# present the user with a dialog to choose gallery script key, or none
|
||||
|
||||
wx.MessageBox( 'This does not work yet!' )
|
||||
|
||||
break
|
||||
|
||||
|
||||
|
||||
def _EditPage( self ):
|
||||
|
||||
for data in self._page_list_ctrl.GetData( only_selected = True ):
|
||||
|
||||
( url_match_name, page_script_key ) = data
|
||||
|
||||
# present the user with a dialog to choose page script key, or none
|
||||
|
||||
wx.MessageBox( 'This does not work yet!' )
|
||||
|
||||
break
|
||||
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
intended_files_per_check = self._intended_files_per_check.GetValue()
|
||||
never_faster_than = self._never_faster_than.GetValue()
|
||||
never_slower_than = self._never_slower_than.GetValue()
|
||||
death_file_velocity = self._death_file_velocity.GetValue()
|
||||
url_match_names_to_display = dict( self._display_list_ctrl.GetData() )
|
||||
url_match_names_to_page_parsing_keys = dict( self._page_list_ctrl.GetData() )
|
||||
url_match_names_to_gallery_parsing_keys = dict( self._gallery_list_ctrl.GetData() )
|
||||
|
||||
return ClientData.CheckerOptions( intended_files_per_check, never_faster_than, never_slower_than, death_file_velocity )
|
||||
return ( url_match_names_to_display, url_match_names_to_page_parsing_keys, url_match_names_to_gallery_parsing_keys )
|
||||
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import ClientMedia
|
|||
import ClientRatings
|
||||
import ClientSerialisable
|
||||
import ClientServices
|
||||
import ClientGUITime
|
||||
import collections
|
||||
import HydrusConstants as HC
|
||||
import HydrusData
|
||||
|
@ -1046,36 +1047,36 @@ class ManageClientServicesPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
ClientGUICommon.StaticBox.__init__( self, parent, 'local booru' )
|
||||
|
||||
#dictionary[ 'port' ] = None
|
||||
#dictionary[ 'upnp_port' ] = None
|
||||
#dictionary[ 'bandwidth_rules' ] = HydrusNetworking.BandwidthRules()
|
||||
|
||||
self._st = ClientGUICommon.BetterStaticText( self )
|
||||
'''
|
||||
if service_type == HC.LOCAL_BOORU:
|
||||
|
||||
self._booru_options_panel = ClientGUICommon.StaticBox( self, 'options' )
|
||||
|
||||
self._port = ClientGUICommon.NoneableSpinCtrl( self._booru_options_panel, 'booru local port', none_phrase = 'do not run local booru service', min = 1, max = 65535 )
|
||||
|
||||
self._upnp = ClientGUICommon.NoneableSpinCtrl( self._booru_options_panel, 'upnp port', none_phrase = 'do not forward port', max = 65535 )
|
||||
|
||||
self._max_monthly_data = ClientGUICommon.NoneableSpinCtrl( self._booru_options_panel, 'max monthly MB', multiplier = 1024 * 1024 )
|
||||
|
||||
'''
|
||||
#
|
||||
|
||||
self._st.SetLabelText( 'This is a Local Booru service. This box will get regain its port options in a future update.' )
|
||||
self._bandwidth_rules = ClientGUIControls.BandwidthRulesCtrl( self._booru_options_panel, dictionary[ 'bandwidth_rules' ] )
|
||||
|
||||
#
|
||||
|
||||
self.AddF( self._st, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
self._port.SetValue( dictionary[ 'port' ] )
|
||||
self._upnp.SetValue( dictionary[ 'upnp_port' ] )
|
||||
|
||||
#
|
||||
|
||||
self._booru_options_panel.AddF( self._port, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
self._booru_options_panel.AddF( self._upnp, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
self._booru_options_panel.AddF( self._bandwidth_rules, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
self.AddF( self._booru_options_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
dictionary_part = {}
|
||||
|
||||
dictionary_part[ 'port' ] = self._port.GetValue()
|
||||
dictionary_part[ 'upnp_port' ] = self._upnp.GetValue()
|
||||
dictionary_part[ 'bandwidth_rules' ] = self._bandwidth_rules.GetValue()
|
||||
|
||||
return dictionary_part
|
||||
|
||||
|
||||
|
@ -1259,7 +1260,7 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
ClientGUIScrolledPanels.ManagePanel.__init__( self, parent )
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
self._listbook = ClientGUICommon.ListBook( self )
|
||||
|
||||
|
@ -1311,7 +1312,7 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
#
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
( locations_to_ideal_weights, resized_thumbnail_override, full_size_thumbnail_override ) = self._new_options.GetClientFilesLocationsToIdealWeights()
|
||||
|
||||
|
@ -1574,7 +1575,7 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
self._current_colourset = ClientGUICommon.BetterChoice( self )
|
||||
|
||||
|
@ -1773,7 +1774,7 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
self._external_host.SetValue( HC.options[ 'external_host' ] )
|
||||
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
self._network_timeout.SetValue( self._new_options.GetInteger( 'network_timeout' ) )
|
||||
|
||||
|
@ -1908,7 +1909,7 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
checker_options = self._new_options.GetDefaultThreadCheckerOptions()
|
||||
|
||||
self._thread_checker_options = ClientGUIScrolledPanelsEdit.EditCheckerOptions( thread_checker, checker_options )
|
||||
self._thread_checker_options = ClientGUITime.EditCheckerOptions( thread_checker, checker_options )
|
||||
|
||||
#
|
||||
|
||||
|
@ -1980,7 +1981,7 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
self._jobs_panel = ClientGUICommon.StaticBox( self, 'when to run high cpu jobs' )
|
||||
self._maintenance_panel = ClientGUICommon.StaticBox( self, 'maintenance period' )
|
||||
|
@ -2304,7 +2305,7 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
tag_import_options = new_options.GetDefaultTagImportOptions( gallery_identifier )
|
||||
|
||||
|
@ -2424,7 +2425,7 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
self._trash_max_age.SetValue( HC.options[ 'trash_max_age' ] )
|
||||
self._trash_max_size.SetValue( HC.options[ 'trash_max_size' ] )
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
for mime in HC.SEARCHABLE_MIMES:
|
||||
|
||||
|
@ -2616,7 +2617,7 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
#
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
self._main_gui_title.SetValue( self._new_options.GetString( 'main_gui_title' ) )
|
||||
|
||||
|
@ -2826,7 +2827,7 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
self._animation_start_position = wx.SpinCtrl( self, min = 0, max = 100 )
|
||||
|
||||
|
@ -3065,7 +3066,7 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
#
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
try:
|
||||
|
||||
|
@ -5885,7 +5886,7 @@ class ManageTagsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
self._tags_box_sorter.SetTagsBox( self._tags_box )
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
self._add_parents_checkbox = wx.CheckBox( self._tags_box_sorter, label = 'auto-add entered tags\' parents' )
|
||||
self._add_parents_checkbox.SetValue( self._new_options.GetBoolean( 'add_parents_on_manage_tags' ) )
|
||||
|
@ -6238,7 +6239,7 @@ class ManageTagsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
|
||||
|
||||
if len( recent_tags ) > 0 and HG.client_controller.GetNewOptions().GetNoneableInteger( 'num_recent_tags' ) is not None:
|
||||
if len( recent_tags ) > 0 and HG.client_controller.new_options.GetNoneableInteger( 'num_recent_tags' ) is not None:
|
||||
|
||||
HG.client_controller.Write( 'push_recent_tags', self._tag_service_key, recent_tags )
|
||||
|
||||
|
@ -6377,7 +6378,7 @@ class ManageTagsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
try:
|
||||
|
||||
tags = HydrusData.DeserialisePrettyTags( text )
|
||||
tags = HydrusData.DeserialiseNewlinedTexts( text )
|
||||
|
||||
tags = HydrusTags.CleanTags( tags )
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import ClientGUIScrolledPanels
|
|||
import ClientGUIScrolledPanelsEdit
|
||||
import ClientGUIPanels
|
||||
import ClientGUIPopupMessages
|
||||
import ClientGUITime
|
||||
import ClientGUITopLevelWindows
|
||||
import ClientNetworking
|
||||
import ClientTags
|
||||
|
@ -308,8 +309,8 @@ class ReviewAllBandwidthPanel( ClientGUIScrolledPanels.ReviewPanel ):
|
|||
|
||||
ClientGUIScrolledPanels.ReviewPanel.__init__( self, parent )
|
||||
|
||||
self._history_time_delta_threshold = ClientGUICommon.TimeDeltaButton( self, days = True, hours = True, minutes = True, seconds = True )
|
||||
self._history_time_delta_threshold.Bind( ClientGUICommon.EVT_TIME_DELTA, self.EventTimeDeltaChanged )
|
||||
self._history_time_delta_threshold = ClientGUITime.TimeDeltaButton( self, days = True, hours = True, minutes = True, seconds = True )
|
||||
self._history_time_delta_threshold.Bind( ClientGUITime.EVT_TIME_DELTA, self.EventTimeDeltaChanged )
|
||||
|
||||
self._history_time_delta_none = wx.CheckBox( self, label = 'show all' )
|
||||
self._history_time_delta_none.Bind( wx.EVT_CHECKBOX, self.EventTimeDeltaChanged )
|
||||
|
@ -567,7 +568,7 @@ class ReviewNetworkContextBandwidthPanel( ClientGUIScrolledPanels.ReviewPanel ):
|
|||
self._current_usage_st = ClientGUICommon.BetterStaticText( usage_panel )
|
||||
|
||||
self._time_delta_usage_bandwidth_type = ClientGUICommon.BetterChoice( usage_panel )
|
||||
self._time_delta_usage_time_delta = ClientGUICommon.TimeDeltaButton( usage_panel, days = True, hours = True, minutes = True, seconds = True )
|
||||
self._time_delta_usage_time_delta = ClientGUITime.TimeDeltaButton( usage_panel, days = True, hours = True, minutes = True, seconds = True )
|
||||
self._time_delta_usage_st = ClientGUICommon.BetterStaticText( usage_panel )
|
||||
|
||||
#
|
||||
|
@ -985,7 +986,7 @@ class MigrateDatabasePanel( ClientGUIScrolledPanels.ReviewPanel ):
|
|||
|
||||
self._controller = controller
|
||||
|
||||
self._new_options = self._controller.GetNewOptions()
|
||||
self._new_options = self._controller.new_options
|
||||
|
||||
ClientGUIScrolledPanels.ReviewPanel.__init__( self, parent )
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class ListBoxTagsSuggestionsFavourites( ClientGUIListBoxes.ListBoxTagsStrings ):
|
|||
|
||||
self._activate_callable = activate_callable
|
||||
|
||||
width = HG.client_controller.GetNewOptions().GetInteger( 'suggested_tags_width' )
|
||||
width = HG.client_controller.new_options.GetInteger( 'suggested_tags_width' )
|
||||
|
||||
if width is not None:
|
||||
|
||||
|
@ -53,7 +53,7 @@ class ListBoxTagsSuggestionsRelated( ClientGUIListBoxes.ListBoxTagsPredicates ):
|
|||
|
||||
self._activate_callable = activate_callable
|
||||
|
||||
width = HG.client_controller.GetNewOptions().GetInteger( 'suggested_tags_width' )
|
||||
width = HG.client_controller.new_options.GetInteger( 'suggested_tags_width' )
|
||||
|
||||
self.SetMinSize( ( width, -1 ) )
|
||||
|
||||
|
@ -96,7 +96,7 @@ class RecentTagsPanel( wx.Panel ):
|
|||
self._service_key = service_key
|
||||
self._canvas_key = canvas_key
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
|
@ -150,7 +150,7 @@ class RelatedTagsPanel( wx.Panel ):
|
|||
self._media = media
|
||||
self._canvas_key = canvas_key
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
|
@ -258,7 +258,7 @@ class FileLookupScriptTagsPanel( wx.Panel ):
|
|||
self._script_choice.Append( script.GetName(), script )
|
||||
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
favourite_file_lookup_script = new_options.GetNoneableString( 'favourite_file_lookup_script' )
|
||||
|
||||
|
@ -376,7 +376,7 @@ class SuggestedTagsPanel( wx.Panel ):
|
|||
self._media = media
|
||||
self._canvas_key = canvas_key
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
layout_mode = self._new_options.GetNoneableString( 'suggested_tags_layout' )
|
||||
|
||||
|
|
|
@ -0,0 +1,438 @@
|
|||
import ClientConstants as CC
|
||||
import ClientData
|
||||
import ClientGUICommon
|
||||
import ClientGUIScrolledPanels
|
||||
import ClientGUITopLevelWindows
|
||||
import HydrusData
|
||||
import os
|
||||
import wx
|
||||
|
||||
class EditCheckerOptions( ClientGUIScrolledPanels.EditPanel ):
|
||||
|
||||
def __init__( self, parent, checker_options ):
|
||||
|
||||
ClientGUIScrolledPanels.EditPanel.__init__( self, parent )
|
||||
|
||||
help_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.help, self._ShowHelp )
|
||||
help_button.SetToolTipString( 'Show help regarding these checker options.' )
|
||||
|
||||
# add statictext or whatever that will update on any updates above to say 'given velocity of blah and last check at blah, next check in 5 mins'
|
||||
# or indeed this could just take the seed cache and last check of the caller, if there is one
|
||||
# this would be more useful to the user, to know 'right, on ok, it'll refresh in 30 mins'
|
||||
|
||||
self._intended_files_per_check = wx.SpinCtrl( self, min = 1, max = 1000 )
|
||||
|
||||
self._never_faster_than = TimeDeltaCtrl( self, min = 30, days = True, hours = True, minutes = True, seconds = True )
|
||||
|
||||
self._never_slower_than = TimeDeltaCtrl( self, min = 600, days = True, hours = True, minutes = True )
|
||||
|
||||
self._death_file_velocity = VelocityCtrl( self, min_time_delta = 60, days = True, hours = True, minutes = True, per_phrase = 'in', unit = 'files' )
|
||||
|
||||
#
|
||||
|
||||
( intended_files_per_check, never_faster_than, never_slower_than, death_file_velocity ) = checker_options.ToTuple()
|
||||
|
||||
self._intended_files_per_check.SetValue( intended_files_per_check )
|
||||
self._never_faster_than.SetValue( never_faster_than )
|
||||
self._never_slower_than.SetValue( never_slower_than )
|
||||
self._death_file_velocity.SetValue( death_file_velocity )
|
||||
|
||||
#
|
||||
|
||||
rows = []
|
||||
|
||||
rows.append( ( 'intended new files per check: ', self._intended_files_per_check ) )
|
||||
rows.append( ( 'stop checking if new files found falls below: ', self._death_file_velocity ) )
|
||||
rows.append( ( 'never check faster than once per: ', self._never_faster_than ) )
|
||||
rows.append( ( 'never check slower than once per: ', self._never_slower_than ) )
|
||||
|
||||
gridbox = ClientGUICommon.WrapInGrid( self, rows )
|
||||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
help_hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
st = ClientGUICommon.BetterStaticText( self, 'help for this panel -->' )
|
||||
|
||||
st.SetForegroundColour( wx.Colour( 0, 0, 255 ) )
|
||||
|
||||
help_hbox.AddF( st, CC.FLAGS_VCENTER )
|
||||
help_hbox.AddF( help_button, CC.FLAGS_VCENTER )
|
||||
|
||||
vbox.AddF( help_hbox, CC.FLAGS_LONE_BUTTON )
|
||||
vbox.AddF( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
|
||||
self.SetSizer( vbox )
|
||||
|
||||
|
||||
def _ShowHelp( self ):
|
||||
|
||||
help = 'PROTIP: Do not change anything here unless you understand what it means!'
|
||||
help += os.linesep * 2
|
||||
help += 'After its initialisation check, the checker times future checks so that it will probably find the same specified number of new files each time. When files are being posted frequently, it will check more often. When things are slow, it will slow down as well.'
|
||||
help += os.linesep * 2
|
||||
help += 'For instance, if it were set to try for 5 new files with every check, and at the last check it knew that the last 24 hours had produced 10 new files, it would check again 12 hours later. When that check was done and any new files found, it would then recalculate and repeat the process.'
|
||||
help += os.linesep * 2
|
||||
help += 'If the \'file velocity\' drops below a certain amount, the checker considers the source of files dead and will stop checking. If it falls into this state but you think there might have been a rush of new files, hit the \'check now\' button in an attempt to revive the checker. If there are new files, it will start checking again until they drop off once more.'
|
||||
|
||||
wx.MessageBox( help )
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
intended_files_per_check = self._intended_files_per_check.GetValue()
|
||||
never_faster_than = self._never_faster_than.GetValue()
|
||||
never_slower_than = self._never_slower_than.GetValue()
|
||||
death_file_velocity = self._death_file_velocity.GetValue()
|
||||
|
||||
return ClientData.CheckerOptions( intended_files_per_check, never_faster_than, never_slower_than, death_file_velocity )
|
||||
|
||||
|
||||
( TimeDeltaEvent, EVT_TIME_DELTA ) = wx.lib.newevent.NewCommandEvent()
|
||||
|
||||
class TimeDeltaButton( wx.Button ):
|
||||
|
||||
def __init__( self, parent, min = 1, days = False, hours = False, minutes = False, seconds = False, monthly_allowed = False ):
|
||||
|
||||
wx.Button.__init__( self, parent )
|
||||
|
||||
self._min = min
|
||||
self._show_days = days
|
||||
self._show_hours = hours
|
||||
self._show_minutes = minutes
|
||||
self._show_seconds = seconds
|
||||
self._monthly_allowed = monthly_allowed
|
||||
|
||||
self._value = self._min
|
||||
|
||||
self.SetLabelText( 'initialising' )
|
||||
|
||||
self.Bind( wx.EVT_BUTTON, self.EventButton )
|
||||
|
||||
|
||||
def _RefreshLabel( self ):
|
||||
|
||||
value = self._value
|
||||
|
||||
if value is None:
|
||||
|
||||
text = 'monthly'
|
||||
|
||||
else:
|
||||
|
||||
text = HydrusData.ConvertTimeDeltaToPrettyString( value )
|
||||
|
||||
|
||||
self.SetLabelText( text )
|
||||
|
||||
|
||||
def EventButton( self, event ):
|
||||
|
||||
with ClientGUITopLevelWindows.DialogEdit( self, 'edit time delta' ) as dlg:
|
||||
|
||||
panel = ClientGUIScrolledPanels.EditSingleCtrlPanel( dlg )
|
||||
|
||||
control = TimeDeltaCtrl( panel, min = self._min, days = self._show_days, hours = self._show_hours, minutes = self._show_minutes, seconds = self._show_seconds, monthly_allowed = self._monthly_allowed )
|
||||
|
||||
control.SetValue( self._value )
|
||||
|
||||
panel.SetControl( control )
|
||||
|
||||
dlg.SetPanel( panel )
|
||||
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
|
||||
value = panel.GetValue()
|
||||
|
||||
self.SetValue( value )
|
||||
|
||||
new_event = TimeDeltaEvent( 0 )
|
||||
|
||||
wx.PostEvent( self, new_event )
|
||||
|
||||
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
return self._value
|
||||
|
||||
|
||||
def SetValue( self, value ):
|
||||
|
||||
self._value = value
|
||||
|
||||
self._RefreshLabel()
|
||||
|
||||
self.GetParent().Layout()
|
||||
|
||||
|
||||
class TimeDeltaCtrl( wx.Panel ):
|
||||
|
||||
def __init__( self, parent, min = 1, days = False, hours = False, minutes = False, seconds = False, monthly_allowed = False, monthly_label = 'monthly' ):
|
||||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
self._min = min
|
||||
self._show_days = days
|
||||
self._show_hours = hours
|
||||
self._show_minutes = minutes
|
||||
self._show_seconds = seconds
|
||||
self._monthly_allowed = monthly_allowed
|
||||
|
||||
hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
if self._show_days:
|
||||
|
||||
self._days = wx.SpinCtrl( self, min = 0, max = 3653, size = ( 50, -1 ) )
|
||||
self._days.Bind( wx.EVT_SPINCTRL, self.EventChange )
|
||||
|
||||
hbox.AddF( self._days, CC.FLAGS_VCENTER )
|
||||
hbox.AddF( ClientGUICommon.BetterStaticText( self, 'days' ), CC.FLAGS_VCENTER )
|
||||
|
||||
|
||||
if self._show_hours:
|
||||
|
||||
self._hours = wx.SpinCtrl( self, min = 0, max = 23, size = ( 45, -1 ) )
|
||||
self._hours.Bind( wx.EVT_SPINCTRL, self.EventChange )
|
||||
|
||||
hbox.AddF( self._hours, CC.FLAGS_VCENTER )
|
||||
hbox.AddF( ClientGUICommon.BetterStaticText( self, 'hours' ), CC.FLAGS_VCENTER )
|
||||
|
||||
|
||||
if self._show_minutes:
|
||||
|
||||
self._minutes = wx.SpinCtrl( self, min = 0, max = 59, size = ( 45, -1 ) )
|
||||
self._minutes.Bind( wx.EVT_SPINCTRL, self.EventChange )
|
||||
|
||||
hbox.AddF( self._minutes, CC.FLAGS_VCENTER )
|
||||
hbox.AddF( ClientGUICommon.BetterStaticText( self, 'minutes' ), CC.FLAGS_VCENTER )
|
||||
|
||||
|
||||
if self._show_seconds:
|
||||
|
||||
self._seconds = wx.SpinCtrl( self, min = 0, max = 59, size = ( 45, -1 ) )
|
||||
self._seconds.Bind( wx.EVT_SPINCTRL, self.EventChange )
|
||||
|
||||
hbox.AddF( self._seconds, CC.FLAGS_VCENTER )
|
||||
hbox.AddF( ClientGUICommon.BetterStaticText( self, 'seconds' ), CC.FLAGS_VCENTER )
|
||||
|
||||
|
||||
if self._monthly_allowed:
|
||||
|
||||
self._monthly = wx.CheckBox( self )
|
||||
self._monthly.Bind( wx.EVT_CHECKBOX, self.EventChange )
|
||||
|
||||
hbox.AddF( self._monthly, CC.FLAGS_VCENTER )
|
||||
hbox.AddF( ClientGUICommon.BetterStaticText( self, monthly_label ), CC.FLAGS_VCENTER )
|
||||
|
||||
|
||||
self.SetSizer( hbox )
|
||||
|
||||
|
||||
def _UpdateEnables( self ):
|
||||
|
||||
value = self.GetValue()
|
||||
|
||||
if value is None:
|
||||
|
||||
if self._show_days:
|
||||
|
||||
self._days.Disable()
|
||||
|
||||
|
||||
if self._show_hours:
|
||||
|
||||
self._hours.Disable()
|
||||
|
||||
|
||||
if self._show_minutes:
|
||||
|
||||
self._minutes.Disable()
|
||||
|
||||
|
||||
if self._show_seconds:
|
||||
|
||||
self._seconds.Disable()
|
||||
|
||||
|
||||
else:
|
||||
|
||||
if self._show_days:
|
||||
|
||||
self._days.Enable()
|
||||
|
||||
|
||||
if self._show_hours:
|
||||
|
||||
self._hours.Enable()
|
||||
|
||||
|
||||
if self._show_minutes:
|
||||
|
||||
self._minutes.Enable()
|
||||
|
||||
|
||||
if self._show_seconds:
|
||||
|
||||
self._seconds.Enable()
|
||||
|
||||
|
||||
|
||||
|
||||
def EventChange( self, event ):
|
||||
|
||||
value = self.GetValue()
|
||||
|
||||
if value is not None and value < self._min:
|
||||
|
||||
self.SetValue( self._min )
|
||||
|
||||
|
||||
self._UpdateEnables()
|
||||
|
||||
new_event = TimeDeltaEvent( 0 )
|
||||
|
||||
wx.PostEvent( self, new_event )
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
if self._monthly_allowed and self._monthly.GetValue():
|
||||
|
||||
return None
|
||||
|
||||
|
||||
value = 0
|
||||
|
||||
if self._show_days:
|
||||
|
||||
value += self._days.GetValue() * 86400
|
||||
|
||||
|
||||
if self._show_hours:
|
||||
|
||||
value += self._hours.GetValue() * 3600
|
||||
|
||||
|
||||
if self._show_minutes:
|
||||
|
||||
value += self._minutes.GetValue() * 60
|
||||
|
||||
|
||||
if self._show_seconds:
|
||||
|
||||
value += self._seconds.GetValue()
|
||||
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def SetValue( self, value ):
|
||||
|
||||
if self._monthly_allowed:
|
||||
|
||||
if value is None:
|
||||
|
||||
self._monthly.SetValue( True )
|
||||
|
||||
else:
|
||||
|
||||
self._monthly.SetValue( False )
|
||||
|
||||
|
||||
|
||||
if value is not None:
|
||||
|
||||
if value < self._min:
|
||||
|
||||
value = self._min
|
||||
|
||||
|
||||
if self._show_days:
|
||||
|
||||
self._days.SetValue( value / 86400 )
|
||||
|
||||
value %= 86400
|
||||
|
||||
|
||||
if self._show_hours:
|
||||
|
||||
self._hours.SetValue( value / 3600 )
|
||||
|
||||
value %= 3600
|
||||
|
||||
|
||||
if self._show_minutes:
|
||||
|
||||
self._minutes.SetValue( value / 60 )
|
||||
|
||||
value %= 60
|
||||
|
||||
|
||||
if self._show_seconds:
|
||||
|
||||
self._seconds.SetValue( value )
|
||||
|
||||
|
||||
|
||||
self._UpdateEnables()
|
||||
|
||||
|
||||
class VelocityCtrl( wx.Panel ):
|
||||
|
||||
def __init__( self, parent, min_time_delta = 60, days = False, hours = False, minutes = False, seconds = False, per_phrase = 'per', unit = None ):
|
||||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
self._num = wx.SpinCtrl( self, min = 0, max = 1000, size = ( 60, -1 ) )
|
||||
|
||||
self._times = TimeDeltaCtrl( self, min = min_time_delta, days = days, hours = hours, minutes = minutes, seconds = seconds )
|
||||
|
||||
#
|
||||
|
||||
hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
hbox.AddF( self._num, CC.FLAGS_VCENTER )
|
||||
|
||||
mid_text = per_phrase
|
||||
|
||||
if unit is not None:
|
||||
|
||||
mid_text = unit + ' ' + mid_text
|
||||
|
||||
|
||||
hbox.AddF( ClientGUICommon.BetterStaticText( self, mid_text ), CC.FLAGS_VCENTER )
|
||||
|
||||
hbox.AddF( self._times, CC.FLAGS_VCENTER )
|
||||
|
||||
self.SetSizer( hbox )
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
num = self._num.GetValue()
|
||||
time_delta = self._times.GetValue()
|
||||
|
||||
return ( num, time_delta )
|
||||
|
||||
|
||||
def SetToolTipString( self, text ):
|
||||
|
||||
wx.Panel.SetToolTipString( self, text )
|
||||
|
||||
for c in self.GetChildren():
|
||||
|
||||
c.SetToolTipString( text )
|
||||
|
||||
|
||||
|
||||
def SetValue( self, velocity ):
|
||||
|
||||
( num, time_delta ) = velocity
|
||||
|
||||
self._num.SetValue( num )
|
||||
|
||||
self._times.SetValue( time_delta )
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ def GetSafeSize( tlw, min_size, gravity ):
|
|||
|
||||
def ExpandTLWIfPossible( tlw, frame_key, desired_size_delta ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
( remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen ) = new_options.GetFrameLocation( frame_key )
|
||||
|
||||
|
@ -148,7 +148,7 @@ def PostSizeChangedEvent( window ):
|
|||
|
||||
def SaveTLWSizeAndPosition( tlw, frame_key ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
( remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen ) = new_options.GetFrameLocation( frame_key )
|
||||
|
||||
|
@ -170,7 +170,7 @@ def SaveTLWSizeAndPosition( tlw, frame_key ):
|
|||
|
||||
def SetTLWSizeAndPosition( tlw, frame_key ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
( remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen ) = new_options.GetFrameLocation( frame_key )
|
||||
|
||||
|
@ -293,7 +293,7 @@ class NewDialog( wx.Dialog ):
|
|||
|
||||
wx.Dialog.__init__( self, parent, title = title, style = style )
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_FRAMEBK ) )
|
||||
|
||||
|
@ -638,7 +638,7 @@ class Frame( wx.Frame ):
|
|||
|
||||
wx.Frame.__init__( self, parent, title = title, style = style )
|
||||
|
||||
self._new_options = HG.client_controller.GetNewOptions()
|
||||
self._new_options = HG.client_controller.new_options
|
||||
|
||||
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_FRAMEBK ) )
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ def EfficientlyThumbnailNumpyImage( numpy_image, ( target_x, target_y ) ):
|
|||
|
||||
def GenerateNumpyImage( path, mime ):
|
||||
|
||||
if mime == HC.IMAGE_GIF or HG.client_controller.GetNewOptions().GetBoolean( 'load_images_with_pil' ):
|
||||
if mime == HC.IMAGE_GIF or HG.client_controller.new_options.GetBoolean( 'load_images_with_pil' ):
|
||||
|
||||
# a regular cv.imread call, can crash the whole process on random thumbs, hooray, so have this as backup
|
||||
# it was just the read that was the problem, so this seems to work fine, even if pil is only about half as fast
|
||||
|
@ -302,7 +302,7 @@ HydrusFileHandling.GenerateThumbnailFromStaticImage = GenerateThumbnailFromStati
|
|||
|
||||
def ResizeNumpyImage( mime, numpy_image, ( target_x, target_y ) ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
( scale_up_quality, scale_down_quality ) = new_options.GetMediaZoomQuality( mime )
|
||||
|
||||
|
|
|
@ -373,7 +373,7 @@ class FileImportJob( object ):
|
|||
|
||||
mime = HydrusFileHandling.GetMime( self._temp_path )
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
if mime in HC.DECOMPRESSION_BOMB_IMAGES and new_options.GetBoolean( 'do_not_import_decompression_bombs' ):
|
||||
|
||||
|
@ -430,7 +430,7 @@ class GalleryImport( HydrusSerialisable.SerialisableBase ):
|
|||
|
||||
self._pending_queries = []
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
self._get_tags_if_url_known_and_file_redundant = new_options.GetBoolean( 'get_tags_if_url_known_and_file_redundant' )
|
||||
|
||||
|
@ -1766,7 +1766,7 @@ class ImportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
if tag_import_options is None:
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
tag_import_options = new_options.GetDefaultTagImportOptions( ClientDownloading.GalleryIdentifier( HC.SITE_TYPE_DEFAULT ) )
|
||||
|
||||
|
@ -3717,7 +3717,7 @@ class Subscription( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
self._file_import_options = ClientDefaults.GetDefaultFileImportOptions()
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
self._tag_import_options = new_options.GetDefaultTagImportOptions( self._gallery_identifier )
|
||||
|
||||
|
@ -4478,12 +4478,21 @@ class Subscription( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
except HydrusExceptions.NetworkException as e:
|
||||
|
||||
if isinstance( e, HydrusExceptions.NetworkInfrastructureException ):
|
||||
|
||||
delay = 3600
|
||||
|
||||
else:
|
||||
|
||||
delay = HC.UPDATE_DURATION
|
||||
|
||||
|
||||
HydrusData.Print( 'The subscription ' + self._name + ' encountered an exception when trying to sync:' )
|
||||
HydrusData.PrintException( e )
|
||||
|
||||
job_key.SetVariable( 'popup_text_1', 'Encountered a network error, will retry again later' )
|
||||
|
||||
self._DelayWork( HC.UPDATE_DURATION, 'network error: ' + HydrusData.ToUnicode( e ) )
|
||||
self._DelayWork( delay, 'network error: ' + HydrusData.ToUnicode( e ) )
|
||||
|
||||
time.sleep( 5 )
|
||||
|
||||
|
@ -4936,7 +4945,7 @@ class ThreadWatcherImport( HydrusSerialisable.SerialisableBase ):
|
|||
|
||||
file_import_options = ClientDefaults.GetDefaultFileImportOptions()
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
tag_import_options = new_options.GetDefaultTagImportOptions( ClientDownloading.GalleryIdentifier( HC.SITE_TYPE_THREAD_WATCHER ) )
|
||||
|
||||
|
@ -5148,7 +5157,7 @@ class ThreadWatcherImport( HydrusSerialisable.SerialisableBase ):
|
|||
|
||||
def _PublishPageName( self, page_key ):
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
cannot_rename = not new_options.GetBoolean( 'permit_watchers_to_name_their_pages' )
|
||||
|
||||
|
|
|
@ -39,9 +39,7 @@ class HydrusResourceBooruFile( HydrusResourceBooru ):
|
|||
share_key = request.hydrus_args[ 'share_key' ]
|
||||
hash = request.hydrus_args[ 'hash' ]
|
||||
|
||||
local_booru_manager = HG.client_controller.GetManager( 'local_booru' )
|
||||
|
||||
local_booru_manager.CheckFileAuthorised( share_key, hash )
|
||||
HG.client_controller.local_booru_manager.CheckFileAuthorised( share_key, hash )
|
||||
|
||||
client_files_manager = HG.client_controller.client_files_manager
|
||||
|
||||
|
@ -61,7 +59,7 @@ class HydrusResourceBooruGallery( HydrusResourceBooru ):
|
|||
|
||||
share_key = request.hydrus_args[ 'share_key' ]
|
||||
|
||||
local_booru_manager = HG.client_controller.GetManager( 'local_booru' )
|
||||
local_booru_manager = HG.client_controller.local_booru_manager
|
||||
|
||||
local_booru_manager.CheckShareAuthorised( share_key )
|
||||
|
||||
|
@ -143,7 +141,7 @@ class HydrusResourceBooruPage( HydrusResourceBooru ):
|
|||
share_key = request.hydrus_args[ 'share_key' ]
|
||||
hash = request.hydrus_args[ 'hash' ]
|
||||
|
||||
local_booru_manager = HG.client_controller.GetManager( 'local_booru' )
|
||||
local_booru_manager = HG.client_controller.local_booru_manager
|
||||
|
||||
local_booru_manager.CheckFileAuthorised( share_key, hash )
|
||||
|
||||
|
@ -232,7 +230,7 @@ class HydrusResourceBooruThumbnail( HydrusResourceBooru ):
|
|||
share_key = request.hydrus_args[ 'share_key' ]
|
||||
hash = request.hydrus_args[ 'hash' ]
|
||||
|
||||
local_booru_manager = HG.client_controller.GetManager( 'local_booru' )
|
||||
local_booru_manager = HG.client_controller.local_booru_manager
|
||||
|
||||
local_booru_manager.CheckFileAuthorised( share_key, hash )
|
||||
|
||||
|
|
|
@ -251,59 +251,24 @@ class FileInfoManager( object ):
|
|||
mime = HC.APPLICATION_UNKNOWN
|
||||
|
||||
|
||||
self._hash = hash
|
||||
self._size = size
|
||||
self._mime = mime
|
||||
self._width = width
|
||||
self._height = height
|
||||
self._duration = duration
|
||||
self._num_frames = num_frames
|
||||
self._num_words = num_words
|
||||
self.hash = hash
|
||||
self.size = size
|
||||
self.mime = mime
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.duration = duration
|
||||
self.num_frames = num_frames
|
||||
self.num_words = num_words
|
||||
|
||||
|
||||
def Duplicate( self ):
|
||||
|
||||
return FileInfoManager( self._hash, self._size, self._mime, self._width, self._height, self._duration, self._num_frames, self._num_words )
|
||||
|
||||
|
||||
def GetDuration( self ):
|
||||
|
||||
return self._duration
|
||||
|
||||
|
||||
def GetHash( self ):
|
||||
|
||||
return self._hash
|
||||
|
||||
|
||||
def GetMime( self ):
|
||||
|
||||
return self._mime
|
||||
|
||||
|
||||
def GetNumFrames( self ):
|
||||
|
||||
return self._num_frames
|
||||
|
||||
|
||||
def GetNumWords( self ):
|
||||
|
||||
return self._num_words
|
||||
|
||||
|
||||
def GetResolution( self ):
|
||||
|
||||
return ( self._width, self._height )
|
||||
|
||||
|
||||
def GetSize( self ):
|
||||
|
||||
return self._size
|
||||
return FileInfoManager( self.hash, self.size, self.mime, self.width, self.height, self.duration, self.num_frames, self.num_words )
|
||||
|
||||
|
||||
def ToTuple( self ):
|
||||
|
||||
return ( self._hash, self._size, self._mime, self._width, self._height, self._duration, self._num_frames, self._num_words )
|
||||
return ( self.hash, self.size, self.mime, self.width, self.height, self.duration, self.num_frames, self.num_words )
|
||||
|
||||
|
||||
class LocationsManager( object ):
|
||||
|
@ -1040,7 +1005,7 @@ class MediaList( object ):
|
|||
|
||||
if for_media_viewer:
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
media_show_action = new_options.GetMediaShowAction( media.GetMime() )
|
||||
|
||||
|
@ -1239,7 +1204,7 @@ class MediaList( object ):
|
|||
|
||||
self._media_sort = media_sort
|
||||
|
||||
media_sort_fallback = HG.client_controller.GetNewOptions().GetFallbackSort()
|
||||
media_sort_fallback = HG.client_controller.new_options.GetFallbackSort()
|
||||
|
||||
( sort_key, reverse ) = media_sort_fallback.GetSortKeyAndReverse( self._file_service_key )
|
||||
|
||||
|
@ -1860,7 +1825,7 @@ class MediaResult( object ):
|
|||
|
||||
def GetDuration( self ):
|
||||
|
||||
return self._file_info_manager.GetDuration()
|
||||
return self._file_info_manager.duration
|
||||
|
||||
|
||||
def GetFileInfoManager( self ):
|
||||
|
@ -1870,7 +1835,7 @@ class MediaResult( object ):
|
|||
|
||||
def GetHash( self ):
|
||||
|
||||
return self._file_info_manager.GetHash()
|
||||
return self._file_info_manager.hash
|
||||
|
||||
|
||||
def GetInbox( self ):
|
||||
|
@ -1885,17 +1850,17 @@ class MediaResult( object ):
|
|||
|
||||
def GetMime( self ):
|
||||
|
||||
return self._file_info_manager.GetMime()
|
||||
return self._file_info_manager.mime
|
||||
|
||||
|
||||
def GetNumFrames( self ):
|
||||
|
||||
return self._file_info_manager.GetNumFrames()
|
||||
return self._file_info_manager.num_frames
|
||||
|
||||
|
||||
def GetNumWords( self ):
|
||||
|
||||
return self._file_info_manager.GetNumWords()
|
||||
return self._file_info_manager.num_words
|
||||
|
||||
|
||||
def GetRatingsManager( self ):
|
||||
|
@ -1905,12 +1870,12 @@ class MediaResult( object ):
|
|||
|
||||
def GetResolution( self ):
|
||||
|
||||
return self._file_info_manager.GetResolution()
|
||||
return ( self._file_info_manager.width, self._file_info_manager.height )
|
||||
|
||||
|
||||
def GetSize( self ):
|
||||
|
||||
return self._file_info_manager.GetSize()
|
||||
return self._file_info_manager.size
|
||||
|
||||
|
||||
def GetTagsManager( self ):
|
||||
|
|
|
@ -1080,7 +1080,7 @@ class NetworkJob( object ):
|
|||
self._status_text = u'sending request\u2026'
|
||||
|
||||
|
||||
connect_timeout = HG.client_controller.GetNewOptions().GetInteger( 'network_timeout' )
|
||||
connect_timeout = HG.client_controller.new_options.GetInteger( 'network_timeout' )
|
||||
|
||||
read_timeout = connect_timeout * 6
|
||||
|
||||
|
@ -1621,7 +1621,7 @@ class NetworkJob( object ):
|
|||
|
||||
if not self._CanReattemptRequest():
|
||||
|
||||
raise HydrusExceptions.NetworkException( 'Could not connect!' )
|
||||
raise HydrusExceptions.ConnectionException( 'Could not connect!' )
|
||||
|
||||
|
||||
with self._lock:
|
||||
|
@ -1637,7 +1637,7 @@ class NetworkJob( object ):
|
|||
|
||||
if not self._CanReattemptRequest():
|
||||
|
||||
raise HydrusExceptions.NetworkException( 'Connection successful, but reading response timed out!' )
|
||||
raise HydrusExceptions.ConnectionException( 'Connection successful, but reading response timed out!' )
|
||||
|
||||
|
||||
with self._lock:
|
||||
|
|
|
@ -92,7 +92,7 @@ class NetworkDomainManager( HydrusSerialisable.SerialisableBase ):
|
|||
|
||||
SERIALISABLE_TYPE = HydrusSerialisable.SERIALISABLE_TYPE_NETWORK_DOMAIN_MANAGER
|
||||
SERIALISABLE_NAME = 'Domain Manager'
|
||||
SERIALISABLE_VERSION = 1
|
||||
SERIALISABLE_VERSION = 2
|
||||
|
||||
def __init__( self ):
|
||||
|
||||
|
@ -103,6 +103,10 @@ class NetworkDomainManager( HydrusSerialisable.SerialisableBase ):
|
|||
self._url_matches = HydrusSerialisable.SerialisableList()
|
||||
self._network_contexts_to_custom_header_dicts = collections.defaultdict( dict )
|
||||
|
||||
self._url_match_names_to_display = {}
|
||||
self._url_match_names_to_page_parsing_keys = HydrusSerialisable.SerialisableBytesDictionary()
|
||||
self._url_match_names_to_gallery_parsing_keys = HydrusSerialisable.SerialisableBytesDictionary()
|
||||
|
||||
self._domains_to_url_matches = collections.defaultdict( list )
|
||||
|
||||
self._dirty = False
|
||||
|
@ -115,31 +119,29 @@ class NetworkDomainManager( HydrusSerialisable.SerialisableBase ):
|
|||
def _GetSerialisableInfo( self ):
|
||||
|
||||
serialisable_url_matches = self._url_matches.GetSerialisableTuple()
|
||||
serialisable_url_match_names_to_display = self._url_match_names_to_display.items()
|
||||
serialisable_url_match_names_to_page_parsing_keys = self._url_match_names_to_page_parsing_keys.GetSerialisableTuple()
|
||||
serialisable_url_match_names_to_gallery_parsing_keys = self._url_match_names_to_gallery_parsing_keys.GetSerialisableTuple()
|
||||
serialisable_network_contexts_to_custom_header_dicts = [ ( network_context.GetSerialisableTuple(), custom_header_dict.items() ) for ( network_context, custom_header_dict ) in self._network_contexts_to_custom_header_dicts.items() ]
|
||||
|
||||
return ( serialisable_url_matches, serialisable_network_contexts_to_custom_header_dicts )
|
||||
return ( serialisable_url_matches, serialisable_url_match_names_to_display, serialisable_url_match_names_to_page_parsing_keys, serialisable_url_match_names_to_gallery_parsing_keys, serialisable_network_contexts_to_custom_header_dicts )
|
||||
|
||||
|
||||
def _GetURLMatch( self, url ):
|
||||
|
||||
domain = ConvertURLIntoDomain( url )
|
||||
domain = ConvertDomainIntoSecondLevelDomain( ConvertURLIntoDomain( url ) )
|
||||
|
||||
if domain in self._domains_to_url_matches:
|
||||
|
||||
url_matches = self._domains_to_url_matches[ domain ]
|
||||
|
||||
# it would be nice to somehow sort these based on descending complexity
|
||||
# maybe by length of example url
|
||||
# in this way, url matches can have overlapping desmaign
|
||||
# e.g. 'post url' vs 'post url, manga subpage'
|
||||
|
||||
for url_match in url_matches:
|
||||
|
||||
try:
|
||||
|
||||
url_match.Test( url )
|
||||
|
||||
return url_match.Normalise( url )
|
||||
return url_match
|
||||
|
||||
except HydrusExceptions.URLMatchException:
|
||||
|
||||
|
@ -153,10 +155,14 @@ class NetworkDomainManager( HydrusSerialisable.SerialisableBase ):
|
|||
|
||||
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
|
||||
|
||||
( serialisable_url_matches, serialisable_network_contexts_to_custom_header_dicts ) = serialisable_info
|
||||
( serialisable_url_matches, serialisable_url_match_names_to_display, serialisable_url_match_names_to_page_parsing_keys, serialisable_url_match_names_to_gallery_parsing_keys, serialisable_network_contexts_to_custom_header_dicts ) = serialisable_info
|
||||
|
||||
self._url_matches = HydrusSerialisable.CreateFromSerialisableTuple( serialisable_url_matches )
|
||||
|
||||
self._url_match_names_to_display = dict( serialisable_url_match_names_to_display )
|
||||
self._url_match_names_to_page_parsing_keys = HydrusSerialisable.CreateFromSerialisableTuple( serialisable_url_match_names_to_page_parsing_keys )
|
||||
self._url_match_names_to_gallery_parsing_keys = HydrusSerialisable.CreateFromSerialisableTuple( serialisable_url_match_names_to_gallery_parsing_keys )
|
||||
|
||||
self._network_contexts_to_custom_header_dicts = collections.defaultdict( dict )
|
||||
|
||||
for ( serialisable_network_context, custom_header_dict_items ) in serialisable_network_contexts_to_custom_header_dicts:
|
||||
|
@ -179,12 +185,95 @@ class NetworkDomainManager( HydrusSerialisable.SerialisableBase ):
|
|||
self._domains_to_url_matches[ domain ].append( url_match )
|
||||
|
||||
|
||||
# we now sort them in descending complexity so that
|
||||
# post url/manga subpage
|
||||
# is before
|
||||
# post url
|
||||
|
||||
def key( u_m ):
|
||||
|
||||
return len( u_m.GetExampleURL() )
|
||||
|
||||
|
||||
for url_matches in self._domains_to_url_matches.values():
|
||||
|
||||
url_matches.sort( key = key, reverse = True )
|
||||
|
||||
|
||||
|
||||
def _SetDirty( self ):
|
||||
|
||||
self._dirty = True
|
||||
|
||||
|
||||
def _UpdateSerialisableInfo( self, version, old_serialisable_info ):
|
||||
|
||||
if version == 1:
|
||||
|
||||
( serialisable_url_matches, serialisable_network_contexts_to_custom_header_dicts ) = old_serialisable_info
|
||||
|
||||
url_matches = HydrusSerialisable.CreateFromSerialisableTuple( serialisable_url_matches )
|
||||
|
||||
url_match_names_to_display = {}
|
||||
url_match_names_to_page_parsing_keys = HydrusSerialisable.SerialisableBytesDictionary()
|
||||
url_match_names_to_gallery_parsing_keys = HydrusSerialisable.SerialisableBytesDictionary()
|
||||
|
||||
for url_match in url_matches:
|
||||
|
||||
name = url_match.GetName()
|
||||
|
||||
if url_match.IsPostURL():
|
||||
|
||||
url_match_names_to_display[ name ] = True
|
||||
|
||||
url_match_names_to_page_parsing_keys[ name ] = None
|
||||
|
||||
|
||||
if url_match.IsGalleryURL():
|
||||
|
||||
url_match_names_to_gallery_parsing_keys[ name ] = None
|
||||
|
||||
|
||||
|
||||
serialisable_url_match_names_to_display = url_match_names_to_display.items()
|
||||
serialisable_url_match_names_to_page_parsing_keys = url_match_names_to_page_parsing_keys.GetSerialisableTuple()
|
||||
serialisable_url_match_names_to_gallery_parsing_keys = url_match_names_to_gallery_parsing_keys.GetSerialisableTuple()
|
||||
|
||||
new_serialisable_info = ( serialisable_url_matches, serialisable_url_match_names_to_display, serialisable_url_match_names_to_page_parsing_keys, serialisable_url_match_names_to_gallery_parsing_keys, serialisable_network_contexts_to_custom_header_dicts )
|
||||
|
||||
return ( 2, new_serialisable_info )
|
||||
|
||||
|
||||
|
||||
def _UpdateURLMatchLinks( self ):
|
||||
|
||||
for url_match in self._url_matches:
|
||||
|
||||
name = url_match.GetName()
|
||||
|
||||
if url_match.IsPostURL():
|
||||
|
||||
if name not in self._url_match_names_to_display:
|
||||
|
||||
self._url_match_names_to_display[ name ] = True
|
||||
|
||||
|
||||
if name not in self._url_match_names_to_page_parsing_keys:
|
||||
|
||||
self._url_match_names_to_page_parsing_keys[ name ] = None
|
||||
|
||||
|
||||
|
||||
if url_match.IsGalleryURL():
|
||||
|
||||
if name not in self._url_match_names_to_gallery_parsing_keys:
|
||||
|
||||
self._url_match_names_to_gallery_parsing_keys[ name ] = None
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def CanValidateInPopup( self, network_contexts ):
|
||||
|
||||
# we can always do this for headers
|
||||
|
@ -192,6 +281,47 @@ class NetworkDomainManager( HydrusSerialisable.SerialisableBase ):
|
|||
return True
|
||||
|
||||
|
||||
def ConvertURLsToMediaViewerTuples( self, urls ):
|
||||
|
||||
url_tuples = []
|
||||
|
||||
with self._lock:
|
||||
|
||||
for url in urls:
|
||||
|
||||
url_match = self._GetURLMatch( url )
|
||||
|
||||
if url_match is None:
|
||||
|
||||
domain = ConvertURLIntoDomain( url )
|
||||
|
||||
url_tuples.append( ( domain, url ) )
|
||||
|
||||
else:
|
||||
|
||||
name = url_match.GetName()
|
||||
|
||||
if url_match.IsPostURL() and name in self._url_match_names_to_display:
|
||||
|
||||
if self._url_match_names_to_display[ name ]:
|
||||
|
||||
url_tuples.append( ( name, url ) )
|
||||
|
||||
|
||||
|
||||
|
||||
if len( url_tuples ) == 10:
|
||||
|
||||
break
|
||||
|
||||
|
||||
|
||||
|
||||
url_tuples.sort()
|
||||
|
||||
return url_tuples
|
||||
|
||||
|
||||
def GenerateValidationPopupProcess( self, network_contexts ):
|
||||
|
||||
with self._lock:
|
||||
|
@ -275,6 +405,19 @@ class NetworkDomainManager( HydrusSerialisable.SerialisableBase ):
|
|||
|
||||
|
||||
|
||||
def GetURLMatchLinks( self ):
|
||||
|
||||
with self._lock:
|
||||
|
||||
return ( dict( self._url_match_names_to_display ), dict( self._url_match_names_to_page_parsing_keys ), dict( self._url_match_names_to_gallery_parsing_keys ) )
|
||||
|
||||
|
||||
|
||||
def Initialise( self ):
|
||||
|
||||
self._RecalcCache()
|
||||
|
||||
|
||||
def IsDirty( self ):
|
||||
|
||||
with self._lock:
|
||||
|
@ -308,9 +451,6 @@ class NetworkDomainManager( HydrusSerialisable.SerialisableBase ):
|
|||
|
||||
def NormaliseURL( self, url ):
|
||||
|
||||
# call this before an entry into a seed cache or the db
|
||||
# use it in the dialog to review mass db-level changes
|
||||
|
||||
with self._lock:
|
||||
|
||||
url_match = self._GetURLMatch( url )
|
||||
|
@ -372,6 +512,26 @@ class NetworkDomainManager( HydrusSerialisable.SerialisableBase ):
|
|||
|
||||
self._url_matches.extend( url_matches )
|
||||
|
||||
self._UpdateURLMatchLinks()
|
||||
|
||||
self._RecalcCache()
|
||||
|
||||
self._SetDirty()
|
||||
|
||||
|
||||
|
||||
def SetURLMatchLinks( self, url_match_names_to_display, url_match_names_to_page_parsing_keys, url_match_names_to_gallery_parsing_keys ):
|
||||
|
||||
with self._lock:
|
||||
|
||||
self._url_match_names_to_display = {}
|
||||
self._url_match_names_to_page_parsing_keys = HydrusSerialisable.SerialisableBytesDictionary()
|
||||
self._url_match_names_to_gallery_parsing_keys = HydrusSerialisable.SerialisableBytesDictionary()
|
||||
|
||||
self._url_match_names_to_display.update( url_match_names_to_display )
|
||||
self._url_match_names_to_page_parsing_keys.update( url_match_names_to_page_parsing_keys )
|
||||
self._url_match_names_to_gallery_parsing_keys.update( url_match_names_to_gallery_parsing_keys )
|
||||
|
||||
self._SetDirty()
|
||||
|
||||
|
||||
|
@ -577,7 +737,7 @@ class URLMatch( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
def GetDomain( self ):
|
||||
|
||||
return ConvertURLIntoDomain( self._example_url )
|
||||
return ConvertDomainIntoSecondLevelDomain( HydrusData.ToByteString( self._netloc ) )
|
||||
|
||||
|
||||
def GetExampleURL( self ):
|
||||
|
@ -590,6 +750,16 @@ class URLMatch( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
return self._url_type
|
||||
|
||||
|
||||
def IsGalleryURL( self ):
|
||||
|
||||
return self._url_type == HC.URL_TYPE_GALLERY
|
||||
|
||||
|
||||
def IsPostURL( self ):
|
||||
|
||||
return self._url_type == HC.URL_TYPE_POST
|
||||
|
||||
|
||||
def Normalise( self, url ):
|
||||
|
||||
p = urlparse.urlparse( url )
|
||||
|
|
|
@ -294,7 +294,30 @@ class NetworkLoginManager( HydrusSerialisable.SerialisableBase ):
|
|||
|
||||
session = self.engine.session_manager.GetSession( network_context )
|
||||
|
||||
response = session.get( 'https://www.hentai-foundry.com/' )
|
||||
num_attempts = 0
|
||||
|
||||
while True:
|
||||
|
||||
try:
|
||||
|
||||
response = session.get( 'https://www.hentai-foundry.com/', timeout = 10 )
|
||||
|
||||
break
|
||||
|
||||
except requests.exceptions.ConnectionError, requests.exceptions.ConnectTimeout:
|
||||
|
||||
if num_attempts < 3:
|
||||
|
||||
num_attempts += 1
|
||||
|
||||
time.sleep( 3 )
|
||||
|
||||
else:
|
||||
|
||||
raise HydrusExceptions.ConnectionException( 'Could not connect to HF to log in!' )
|
||||
|
||||
|
||||
|
||||
|
||||
time.sleep( 1 )
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ class RasterContainerVideo( RasterContainer ):
|
|||
|
||||
( x, y ) = self._target_resolution
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
video_buffer_size_mb = new_options.GetInteger( 'video_buffer_size_mb' )
|
||||
|
||||
|
|
|
@ -427,7 +427,7 @@ class FileSystemPredicates( object ):
|
|||
|
||||
self._duplicate_predicates = []
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
forced_search_limit = new_options.GetNoneableInteger( 'forced_search_limit' )
|
||||
|
||||
|
|
|
@ -932,9 +932,7 @@ class ServiceRepository( ServiceRestricted ):
|
|||
return False
|
||||
|
||||
|
||||
options = HG.client_controller.GetOptions()
|
||||
|
||||
if options[ 'pause_repo_sync' ]:
|
||||
if HG.client_controller.options[ 'pause_repo_sync' ]:
|
||||
|
||||
return False
|
||||
|
||||
|
@ -968,8 +966,6 @@ class ServiceRepository( ServiceRestricted ):
|
|||
|
||||
with self._lock:
|
||||
|
||||
options = HG.client_controller.GetOptions()
|
||||
|
||||
if not self._CanSync():
|
||||
|
||||
return False
|
||||
|
|
|
@ -220,7 +220,7 @@ def RenderTag( tag, render_for_user ):
|
|||
|
||||
if render_for_user:
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
if new_options.GetBoolean( 'show_namespaces' ):
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ class GIFRenderer( object ):
|
|||
self._num_frames = num_frames
|
||||
self._target_resolution = target_resolution
|
||||
|
||||
new_options = HG.client_controller.GetNewOptions()
|
||||
new_options = HG.client_controller.new_options
|
||||
|
||||
if new_options.GetBoolean( 'disable_cv_for_gifs' ) or cv2.__version__.startswith( '2' ):
|
||||
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
import hsaudiotag
|
||||
import hsaudiotag.auto
|
||||
import hsaudiotag.flac
|
||||
import hsaudiotag.mpeg
|
||||
import hsaudiotag.ogg
|
||||
import HydrusConstants as HC
|
||||
import os
|
||||
import threading
|
||||
|
@ -11,55 +6,7 @@ import traceback
|
|||
|
||||
#if HC.PLATFORM_WINDOWS: import mp3play
|
||||
|
||||
parsed_noises = {}
|
||||
|
||||
def GetFLACDuration( path ):
|
||||
|
||||
hsaudio_object = hsaudiotag.flac.FLAC( path )
|
||||
|
||||
if not hsaudio_object.valid: raise Exception( 'FLAC file was not valid!' )
|
||||
|
||||
length_in_seconds = hsaudio_object.duration
|
||||
|
||||
length_in_ms = int( length_in_seconds * 1000 )
|
||||
|
||||
return length_in_ms
|
||||
|
||||
def GetMP3Duration( path ):
|
||||
|
||||
hsaudio_object = hsaudiotag.mpeg.Mpeg( path )
|
||||
|
||||
if not hsaudio_object.valid: raise Exception( 'MP3 file was not valid!' )
|
||||
|
||||
length_in_seconds = hsaudio_object.duration
|
||||
|
||||
length_in_ms = int( length_in_seconds * 1000 )
|
||||
|
||||
return length_in_ms
|
||||
|
||||
def GetOGGVorbisDuration( path ):
|
||||
|
||||
hsaudio_object = hsaudiotag.ogg.Vorbis( path )
|
||||
|
||||
if not hsaudio_object.valid: raise Exception( 'Ogg Vorbis file was not valid!' )
|
||||
|
||||
length_in_seconds = hsaudio_object.duration
|
||||
|
||||
length_in_ms = int( length_in_seconds * 1000 )
|
||||
|
||||
return length_in_ms
|
||||
|
||||
def GetWMADuration( path ):
|
||||
|
||||
hsaudio_object = hsaudiotag.wma.WMADecoder( path )
|
||||
|
||||
if not hsaudio_object.valid: raise Exception( 'WMA file was not valid!' )
|
||||
|
||||
length_in_seconds = hsaudio_object.duration
|
||||
|
||||
length_in_ms = int( length_in_seconds * 1000 )
|
||||
|
||||
return length_in_ms
|
||||
# There used to be hsaudiotag duration stuff here, but I moved it all to FFMPEG
|
||||
|
||||
'''
|
||||
def PlayNoise( name ):
|
||||
|
@ -81,4 +28,4 @@ def PlayNoise( name ):
|
|||
noise = parsed_noises[ name ]
|
||||
|
||||
noise.play()
|
||||
'''
|
||||
'''
|
||||
|
|
|
@ -49,7 +49,7 @@ options = {}
|
|||
# Misc
|
||||
|
||||
NETWORK_VERSION = 18
|
||||
SOFTWARE_VERSION = 284
|
||||
SOFTWARE_VERSION = 285
|
||||
|
||||
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
||||
|
||||
|
|
|
@ -629,13 +629,15 @@ def DebugPrint( debug_info ):
|
|||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
|
||||
def DeserialisePrettyTags( text ):
|
||||
def DeserialiseNewlinedTexts( text ):
|
||||
|
||||
text = text.replace( '\r', '' )
|
||||
|
||||
tags = text.split( '\n' )
|
||||
texts = text.split( '\n' )
|
||||
|
||||
return tags
|
||||
texts = [ line for line in texts if line != '' ]
|
||||
|
||||
return texts
|
||||
|
||||
def EncodeBytes( encoding, data ):
|
||||
|
||||
|
@ -1612,9 +1614,7 @@ class ContentUpdate( object ):
|
|||
|
||||
( file_info_manager, timestamp ) = self._row
|
||||
|
||||
hash = file_info_manager.GetHash()
|
||||
|
||||
hashes = { hash }
|
||||
hashes = { file_info_manager.hash }
|
||||
|
||||
elif self._action in ( HC.CONTENT_UPDATE_ARCHIVE, HC.CONTENT_UPDATE_DELETE, HC.CONTENT_UPDATE_UNDELETE, HC.CONTENT_UPDATE_INBOX, HC.CONTENT_UPDATE_PEND, HC.CONTENT_UPDATE_RESCIND_PEND, HC.CONTENT_UPDATE_RESCIND_PETITION ):
|
||||
|
||||
|
@ -1685,56 +1685,6 @@ class ContentUpdate( object ):
|
|||
return ( self._data_type, self._action, self._row )
|
||||
|
||||
|
||||
class EditLogAction( object ):
|
||||
|
||||
yaml_tag = u'!EditLogAction'
|
||||
|
||||
def __init__( self, action ): self._action = action
|
||||
|
||||
def GetAction( self ): return self._action
|
||||
|
||||
class EditLogActionAdd( EditLogAction ):
|
||||
|
||||
yaml_tag = u'!EditLogActionAdd'
|
||||
|
||||
def __init__( self, data ):
|
||||
|
||||
EditLogAction.__init__( self, HC.ADD )
|
||||
|
||||
self._data = data
|
||||
|
||||
|
||||
def GetData( self ): return self._data
|
||||
|
||||
class EditLogActionDelete( EditLogAction ):
|
||||
|
||||
yaml_tag = u'!EditLogActionDelete'
|
||||
|
||||
def __init__( self, identifier ):
|
||||
|
||||
EditLogAction.__init__( self, HC.DELETE )
|
||||
|
||||
self._identifier = identifier
|
||||
|
||||
|
||||
def GetIdentifier( self ): return self._identifier
|
||||
|
||||
class EditLogActionEdit( EditLogAction ):
|
||||
|
||||
yaml_tag = u'!EditLogActionEdit'
|
||||
|
||||
def __init__( self, identifier, data ):
|
||||
|
||||
EditLogAction.__init__( self, HC.EDIT )
|
||||
|
||||
self._identifier = identifier
|
||||
self._data = data
|
||||
|
||||
|
||||
def GetData( self ): return self._data
|
||||
|
||||
def GetIdentifier( self ): return self._identifier
|
||||
|
||||
class JobDatabase( object ):
|
||||
|
||||
def __init__( self, job_type, synchronous, action, *args, **kwargs ):
|
||||
|
|
|
@ -25,8 +25,13 @@ class StringMatchException( ParseException ): pass
|
|||
class URLMatchException( ParseException ): pass
|
||||
|
||||
class NetworkException( Exception ): pass
|
||||
|
||||
class NetworkInfrastructureException( NetworkException ): pass
|
||||
class ConnectionException( NetworkInfrastructureException ): pass
|
||||
class FirewallException( NetworkInfrastructureException ): pass
|
||||
class ServerBusyException( NetworkInfrastructureException ): pass
|
||||
|
||||
class BandwidthException( NetworkException ): pass
|
||||
class FirewallException( NetworkException ): pass
|
||||
class ForbiddenException( NetworkException ): pass
|
||||
class LoginException( NetworkException ): pass
|
||||
class NetworkVersionException( NetworkException ): pass
|
||||
|
@ -35,7 +40,6 @@ class NotFoundException( NetworkException ): pass
|
|||
class NotModifiedException( NetworkException ): pass
|
||||
class PermissionException( NetworkException ): pass
|
||||
class RedirectionException( NetworkException ): pass
|
||||
class ServerBusyException( NetworkException ): pass
|
||||
class ServerException( NetworkException ): pass
|
||||
class SessionException( NetworkException ): pass
|
||||
class WrongServiceTypeException( NetworkException ): pass
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
import gc
|
||||
import hashlib
|
||||
import hsaudiotag
|
||||
import hsaudiotag.auto
|
||||
import hsaudiotag.flac
|
||||
import hsaudiotag.mpeg
|
||||
import hsaudiotag.ogg
|
||||
import HydrusAudioHandling
|
||||
import HydrusConstants as HC
|
||||
import HydrusDocumentHandling
|
||||
|
@ -219,21 +214,13 @@ def GetFileInfo( path, mime = None ):
|
|||
|
||||
num_words = HydrusDocumentHandling.GetPDFNumWords( path )
|
||||
|
||||
elif mime == HC.AUDIO_MP3:
|
||||
elif mime in HC.AUDIO:
|
||||
|
||||
duration = HydrusAudioHandling.GetMP3Duration( path )
|
||||
ffmpeg_lines = HydrusVideoHandling.GetFFMPEGInfoLines( path )
|
||||
|
||||
elif mime == HC.AUDIO_OGG:
|
||||
duration_in_s = HydrusVideoHandling.ParseFFMPEGDuration( ffmpeg_lines )
|
||||
|
||||
duration = HydrusAudioHandling.GetOGGVorbisDuration( path )
|
||||
|
||||
elif mime == HC.AUDIO_FLAC:
|
||||
|
||||
duration = HydrusAudioHandling.GetFLACDuration( path )
|
||||
|
||||
elif mime == HC.AUDIO_WMA:
|
||||
|
||||
duration = HydrusAudioHandling.GetWMADuration( path )
|
||||
duration = int( duration_in_s * 1000 )
|
||||
|
||||
|
||||
return ( size, mime, width, height, duration, num_frames, num_words )
|
||||
|
@ -320,15 +307,5 @@ def GetMime( path ):
|
|||
HydrusData.PrintException( e, do_wait = False )
|
||||
|
||||
|
||||
hsaudio_object = hsaudiotag.auto.File( path )
|
||||
|
||||
if hsaudio_object.valid:
|
||||
|
||||
if isinstance( hsaudio_object.original, hsaudiotag.mpeg.Mpeg ): return HC.AUDIO_MP3
|
||||
elif isinstance( hsaudio_object.original, hsaudiotag.flac.FLAC ): return HC.AUDIO_FLAC
|
||||
elif isinstance( hsaudio_object.original, hsaudiotag.ogg.Vorbis ): return HC.AUDIO_OGG
|
||||
elif isinstance( hsaudio_object.original, hsaudiotag.wma.WMADecoder ): return HC.AUDIO_WMA
|
||||
|
||||
|
||||
return HC.APPLICATION_UNKNOWN
|
||||
|
||||
|
|
|
@ -127,7 +127,14 @@ def GeneratePILImage( path ):
|
|||
|
||||
if pil_image.format == 'JPEG' and hasattr( pil_image, '_getexif' ):
|
||||
|
||||
exif_dict = pil_image._getexif()
|
||||
try:
|
||||
|
||||
exif_dict = pil_image._getexif()
|
||||
|
||||
except:
|
||||
|
||||
exif_dict = None
|
||||
|
||||
|
||||
if exif_dict is not None:
|
||||
|
||||
|
|
|
@ -44,7 +44,10 @@ def GetExternalIP():
|
|||
|
||||
( output, error ) = p.communicate()
|
||||
|
||||
if error is not None and len( error ) > 0: raise Exception( 'Problem while trying to fetch External IP:' + os.linesep * 2 + HydrusData.ToUnicode( error ) )
|
||||
if error is not None and len( error ) > 0:
|
||||
|
||||
raise Exception( 'Problem while trying to fetch External IP:' + os.linesep * 2 + HydrusData.ToUnicode( error ) )
|
||||
|
||||
else:
|
||||
|
||||
try:
|
||||
|
|
|
@ -622,7 +622,16 @@ class BandwidthTracker( HydrusSerialisable.SerialisableBase ):
|
|||
|
||||
( year, month ) = ( dt.year, dt.month )
|
||||
|
||||
next_month_dt = datetime.datetime( year, month + 1, 1 )
|
||||
next_month_year = year
|
||||
|
||||
if month == 12:
|
||||
|
||||
next_month_year += 1
|
||||
|
||||
|
||||
next_month = ( month + 1 ) % 12
|
||||
|
||||
next_month_dt = datetime.datetime( next_month_year, next_month, 1 )
|
||||
|
||||
next_month_time = calendar.timegm( next_month_dt.timetuple() )
|
||||
|
||||
|
|
|
@ -320,6 +320,10 @@ class SerialisableBytesDictionary( SerialisableBase, dict ):
|
|||
|
||||
encoded_value = [ item.encode( 'hex' ) for item in value ]
|
||||
|
||||
elif value is None:
|
||||
|
||||
encoded_value = value
|
||||
|
||||
else:
|
||||
|
||||
encoded_value = value.encode( 'hex' )
|
||||
|
@ -348,6 +352,10 @@ class SerialisableBytesDictionary( SerialisableBase, dict ):
|
|||
|
||||
value = [ encoded_item.decode( 'hex' ) for encoded_item in encoded_value ]
|
||||
|
||||
elif encoded_value is None:
|
||||
|
||||
value = encoded_value
|
||||
|
||||
else:
|
||||
|
||||
value = encoded_value.decode( 'hex' )
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import collections
|
||||
import HydrusAudioHandling
|
||||
import HydrusConstants as HC
|
||||
import HydrusDocumentHandling
|
||||
import HydrusExceptions
|
||||
|
|
|
@ -586,7 +586,7 @@ class HydrusResource( Resource ):
|
|||
|
||||
response_context = ResponseContext( 403, mime = default_mime, body = default_encoding( failure.value ) )
|
||||
|
||||
elif failure.type in ( HydrusExceptions.NotFoundException, HydrusExceptions.DataMissing ):
|
||||
elif failure.type in ( HydrusExceptions.NotFoundException, HydrusExceptions.DataMissing, HydrusExceptions.FileMissingException ):
|
||||
|
||||
response_context = ResponseContext( 404, mime = default_mime, body = default_encoding( failure.value ) )
|
||||
|
||||
|
|
|
@ -279,11 +279,6 @@ class Controller( HydrusController.HydrusController ):
|
|||
return self.db.GetFilesDir()
|
||||
|
||||
|
||||
def GetServerSessionManager( self ):
|
||||
|
||||
return self._server_session_manager
|
||||
|
||||
|
||||
def GetServices( self ):
|
||||
|
||||
return list( self._services )
|
||||
|
@ -293,7 +288,7 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
HydrusController.HydrusController.InitModel( self )
|
||||
|
||||
self._server_session_manager = HydrusSessions.HydrusSessionManagerServer()
|
||||
self.server_session_manager = HydrusSessions.HydrusSessionManagerServer()
|
||||
|
||||
self._service_keys_to_connected_ports = {}
|
||||
|
||||
|
@ -421,7 +416,7 @@ class Controller( HydrusController.HydrusController ):
|
|||
self.WriteSynchronous( 'dirty_services', dirty_services )
|
||||
|
||||
|
||||
dirty_accounts = self._server_session_manager.GetDirtyAccounts()
|
||||
dirty_accounts = self.server_session_manager.GetDirtyAccounts()
|
||||
|
||||
if len( dirty_accounts ) > 0:
|
||||
|
||||
|
|
|
@ -74,9 +74,7 @@ class HydrusResourceSessionKey( HydrusServerResources.HydrusResource ):
|
|||
|
||||
access_key = self._parseAccessKey( request )
|
||||
|
||||
session_manager = HG.server_controller.GetServerSessionManager()
|
||||
|
||||
( session_key, expires ) = session_manager.AddSession( self._service_key, access_key )
|
||||
( session_key, expires ) = HG.server_controller.server_session_manager.AddSession( self._service_key, access_key )
|
||||
|
||||
now = HydrusData.GetNow()
|
||||
|
||||
|
@ -151,9 +149,7 @@ class HydrusResourceRestricted( HydrusServerResources.HydrusResource ):
|
|||
raise Exception( 'Problem parsing cookies!' )
|
||||
|
||||
|
||||
session_manager = HG.server_controller.GetServerSessionManager()
|
||||
|
||||
account = session_manager.GetAccount( self._service_key, session_key )
|
||||
account = HG.server_controller.server_session_manager.GetAccount( self._service_key, session_key )
|
||||
|
||||
request.hydrus_account = account
|
||||
|
||||
|
@ -229,13 +225,11 @@ class HydrusResourceRestrictedAccountModification( HydrusResourceRestricted ):
|
|||
|
||||
kwargs = request.hydrus_args # for things like expires, title, and so on
|
||||
|
||||
server_session_manager = HG.server_controller.GetServerSessionManager()
|
||||
|
||||
with HG.dirty_object_lock:
|
||||
|
||||
HG.server_controller.WriteSynchronous( 'account_modification', self._service_key, request.hydrus_account, action, subject_accounts, **kwargs )
|
||||
|
||||
server_session_manager.UpdateAccounts( self._service_key, subject_accounts )
|
||||
HG.server_controller.server_session_manager.UpdateAccounts( self._service_key, subject_accounts )
|
||||
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
@ -263,9 +257,7 @@ class HydrusResourceRestrictedAccountTypes( HydrusResourceRestricted ):
|
|||
|
||||
HG.server_controller.WriteSynchronous( 'account_types', self._service_key, request.hydrus_account, account_types, deletee_account_type_keys_to_new_account_type_keys )
|
||||
|
||||
session_manager = HG.server_controller.GetServerSessionManager()
|
||||
|
||||
session_manager.RefreshAccounts( self._service_key )
|
||||
HG.server_controller.server_session_manager.RefreshAccounts( self._service_key )
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
||||
|
|
|
@ -250,7 +250,7 @@ class TestServer( unittest.TestCase ):
|
|||
with open( file_path, 'wb' ) as f: f.write( EXAMPLE_FILE )
|
||||
with open( thumbnail_path, 'wb' ) as f: f.write( EXAMPLE_THUMBNAIL )
|
||||
|
||||
local_booru_manager = HG.test_controller.GetManager( 'local_booru' )
|
||||
local_booru_manager = HG.client_controller.local_booru_manager
|
||||
|
||||
#
|
||||
|
||||
|
|
21
test.py
21
test.py
|
@ -79,6 +79,10 @@ class Controller( object ):
|
|||
|
||||
self.new_options = ClientData.ClientOptions( self.db_dir )
|
||||
|
||||
HC.options = ClientDefaults.GetClientDefaultOptions()
|
||||
|
||||
self.options = HC.options
|
||||
|
||||
def show_text( text ): pass
|
||||
|
||||
HydrusData.ShowText = show_text
|
||||
|
@ -125,8 +129,6 @@ class Controller( object ):
|
|||
self._reads[ 'tag_parents' ] = {}
|
||||
self._reads[ 'tag_siblings' ] = {}
|
||||
|
||||
HC.options = ClientDefaults.GetClientDefaultOptions()
|
||||
|
||||
self._writes = collections.defaultdict( list )
|
||||
|
||||
self._managers = {}
|
||||
|
@ -138,8 +140,9 @@ class Controller( object ):
|
|||
self._managers[ 'tag_siblings' ] = ClientCaches.TagSiblingsManager( self )
|
||||
self._managers[ 'tag_parents' ] = ClientCaches.TagParentsManager( self )
|
||||
self._managers[ 'undo' ] = ClientCaches.UndoManager( self )
|
||||
self._server_session_manager = HydrusSessions.HydrusSessionManagerServer()
|
||||
self._managers[ 'local_booru' ] = ClientCaches.LocalBooruCache( self )
|
||||
self.server_session_manager = HydrusSessions.HydrusSessionManagerServer()
|
||||
|
||||
self.local_booru_manager = ClientCaches.LocalBooruCache( self )
|
||||
|
||||
self._cookies = {}
|
||||
|
||||
|
@ -216,21 +219,11 @@ class Controller( object ):
|
|||
return self.new_options
|
||||
|
||||
|
||||
def GetOptions( self ):
|
||||
|
||||
return HC.options
|
||||
|
||||
|
||||
def GetManager( self, manager_type ):
|
||||
|
||||
return self._managers[ manager_type ]
|
||||
|
||||
|
||||
def GetServerSessionManager( self ):
|
||||
|
||||
return self._server_session_manager
|
||||
|
||||
|
||||
def GetWrite( self, name ):
|
||||
|
||||
write = self._writes[ name ]
|
||||
|
|
Loading…
Reference in New Issue