Version 298
This commit is contained in:
parent
24fa015c89
commit
2e35b85777
|
@ -8,6 +8,32 @@
|
|||
<div class="content">
|
||||
<h3>changelog</h3>
|
||||
<ul>
|
||||
<li><h3>version 298</h3></li>
|
||||
<ul>
|
||||
<li>wrote a new 'bytescontrol' and related noneablebytescontrol that allows for a uniform way to choose a bytes size value with a wider range--and deployed it all over the place</li>
|
||||
<li>hitting a mapped shortcut for 'manage file notes' should now ok the 'manage file notes' dialog as well as open it</li>
|
||||
<li>the manage file notes text control will now start with its caret at the end of the document</li>
|
||||
<li>manage siblings/parents now state how many pairs they have</li>
|
||||
<li>as an experiment, manage parents now only lists pertinent information in its listctrl. this is hacky but potentially a big improvement to the workflow here, feedback would be appreciated</li>
|
||||
<li>added a new menu entry, 'network->pause->all new network traffic', which will indefinitely pause any new network jobs. this value will persist through a restart</li>
|
||||
<li>'pause subscriptions' is moved from 'services' to 'network'</li>
|
||||
<li>'pause import/export folders' is moved to 'file' and all the import/export folder stuff is sent down to its own submenu</li>
|
||||
<li>in lieu of proper session inspection gui, added some debug 'reset login' entries to the network menu for pixiv and hf</li>
|
||||
<li>if a page has files but none are selected, it will now say the total size in the status bar</li>
|
||||
<li>the edit bandwidth rules control and its subsidiary dialog use some saner and more user-friendly layout and presentation</li>
|
||||
<li>the previous search distance on the 'review bandwidth usage' frame is now remembered</li>
|
||||
<li>fixed some bad logic where a 'copy_bmp' event could trigger despite the current media being None or a non-static image</li>
|
||||
<li>you can no longer open multiple copies of the subscriptions or import/export folder manage dialogs if you hit the menu entry multiple times while the first is waiting for the jobs to finish</li>
|
||||
<li>like import folders and subscriptions, manage export folders now waits for currently running export folders to quit before opening</li>
|
||||
<li>export folders run lighter and quit faster on client shutdown</li>
|
||||
<li>the domain manager will give a better error if a URL submitted to it lacks a schema (the http or https part)</li>
|
||||
<li>fixed a bunch of unicode error handling</li>
|
||||
<li>fixed an issue with similar files metadata orphans prohibiting new file imports</li>
|
||||
<li>finished up a simple shared shortcut processing object and replaced most old temp duplicate shortcut code with it</li>
|
||||
<li>misc ui cleanup</li>
|
||||
<li>misc text rendering fixes</li>
|
||||
<li>misc shortcut code refactoring</li>
|
||||
</ul>
|
||||
<li><h3>version 297</h3></li>
|
||||
<ul>
|
||||
<li>finished a prototype 'file notes' system. thumbnails and media viewer canvas now support 'manage->file notes' in their right-click menus. this launches a simple text box which will save its contents to db</li>
|
||||
|
@ -19,7 +45,7 @@
|
|||
<li>cleaned up tag import options layout, controls, internal workflow, and help button</li>
|
||||
<li>added 'select all/none' buttons to tag import options panels with multiple namespaces</li>
|
||||
<li>if a subscription is blocked by bandwidth, the manage subscriptions dialog will display that in its 'recent error/delay' column</li>
|
||||
<li>the edit subscription dialog will show similar bandwidth blocking info on a per-query basis, under a new 'recent delays' column</li>
|
||||
<li>the edit subscription dialog will show similar bandwidth blocking info, on a per-query basis, under a new 'recent delays' column</li>
|
||||
<li>the review bandwidth usage panel will no longer show some unusual results by default that you can see with 'show all' hit anyway</li>
|
||||
<li>the review bandwidth usage panel will show the usage at the current search distance in a new column</li>
|
||||
<li>the review bandiwdth usage panel will show number of requests after data usage. this might be info-overload, so I might alter the syntax or roll it back entirely</li>
|
||||
|
|
|
@ -836,7 +836,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
outer_id = None
|
||||
outer_population = 0
|
||||
|
||||
self._c.execute( 'INSERT INTO shape_vptree ( phash_id, parent_id, radius, inner_id, inner_population, outer_id, outer_population ) VALUES ( ?, ?, ?, ?, ?, ?, ? );', ( phash_id, parent_id, radius, inner_id, inner_population, outer_id, outer_population ) )
|
||||
self._c.execute( 'INSERT OR REPLACE INTO shape_vptree ( phash_id, parent_id, radius, inner_id, inner_population, outer_id, outer_population ) VALUES ( ?, ?, ?, ?, ?, ?, ? );', ( phash_id, parent_id, radius, inner_id, inner_population, outer_id, outer_population ) )
|
||||
|
||||
|
||||
def _CacheSimilarFilesAssociatePHashes( self, hash_id, phashes ):
|
||||
|
@ -980,7 +980,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
job_key.SetVariable( 'popup_text_2', 'branch constructed, now committing' )
|
||||
|
||||
self._c.executemany( 'INSERT INTO shape_vptree ( phash_id, parent_id, radius, inner_id, inner_population, outer_id, outer_population ) VALUES ( ?, ?, ?, ?, ?, ?, ? );', insert_rows )
|
||||
self._c.executemany( 'INSERT OR REPLACE INTO shape_vptree ( phash_id, parent_id, radius, inner_id, inner_population, outer_id, outer_population ) VALUES ( ?, ?, ?, ?, ?, ?, ? );', insert_rows )
|
||||
|
||||
|
||||
def _CacheSimilarFilesGetDuplicateHashes( self, file_service_key, hash, duplicate_type ):
|
||||
|
|
|
@ -18,16 +18,27 @@ def DAEMONCheckExportFolders( controller ):
|
|||
|
||||
if not controller.options[ 'pause_export_folders_sync' ]:
|
||||
|
||||
export_folders = controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_EXPORT_FOLDER )
|
||||
HG.export_folders_running = True
|
||||
|
||||
for export_folder in export_folders:
|
||||
try:
|
||||
|
||||
if controller.options[ 'pause_export_folders_sync' ]:
|
||||
export_folder_names = controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_EXPORT_FOLDER )
|
||||
|
||||
for name in export_folder_names:
|
||||
|
||||
break
|
||||
export_folder = controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_EXPORT_FOLDER, name )
|
||||
|
||||
if controller.options[ 'pause_export_folders_sync' ] or HydrusThreading.IsThreadShuttingDown():
|
||||
|
||||
break
|
||||
|
||||
|
||||
export_folder.DoWork()
|
||||
|
||||
|
||||
export_folder.DoWork()
|
||||
finally:
|
||||
|
||||
HG.export_folders_running = False
|
||||
|
||||
|
||||
|
||||
|
@ -37,10 +48,10 @@ def DAEMONCheckImportFolders( controller ):
|
|||
|
||||
HG.import_folders_running = True
|
||||
|
||||
import_folder_names = controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_FOLDER )
|
||||
|
||||
try:
|
||||
|
||||
import_folder_names = controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_FOLDER )
|
||||
|
||||
for name in import_folder_names:
|
||||
|
||||
import_folder = controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_FOLDER, name )
|
||||
|
|
|
@ -1039,6 +1039,8 @@ class ClientOptions( HydrusSerialisable.SerialisableBase ):
|
|||
|
||||
self._dictionary[ 'booleans' ][ 'saving_sash_positions_on_exit' ] = True
|
||||
|
||||
self._dictionary[ 'booleans' ][ 'pause_all_new_network_traffic' ] = False
|
||||
|
||||
#
|
||||
|
||||
self._dictionary[ 'colours' ] = HydrusSerialisable.SerialisableDictionary()
|
||||
|
@ -1136,6 +1138,8 @@ class ClientOptions( HydrusSerialisable.SerialisableBase ):
|
|||
|
||||
self._dictionary[ 'noneable_integers' ][ 'duplicate_background_switch_intensity' ] = 3
|
||||
|
||||
self._dictionary[ 'noneable_integers' ][ 'last_review_bandwidth_search_distance' ] = 7 * 86400
|
||||
|
||||
#
|
||||
|
||||
self._dictionary[ 'noneable_strings' ] = {}
|
||||
|
|
|
@ -95,6 +95,8 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
self._deleted_page_keys = set()
|
||||
self._lock = threading.Lock()
|
||||
|
||||
self._delayed_dialog_lock = threading.Lock()
|
||||
|
||||
self._notebook = ClientGUIPages.PagesNotebook( self, self._controller, 'top page notebook' )
|
||||
|
||||
self.SetDropTarget( ClientDragDrop.FileDropTarget( self, self.ImportFiles, self.ImportURL, self._notebook.MediaDragAndDropDropped, self._notebook.PageDragAndDropDropped ) )
|
||||
|
@ -108,7 +110,6 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
self.Bind( wx.EVT_RIGHT_DOWN, self.EventFrameNotebookMenu )
|
||||
self.Bind( wx.EVT_CLOSE, self.EventClose )
|
||||
self.Bind( wx.EVT_SET_FOCUS, self.EventFocus )
|
||||
self.Bind( wx.EVT_CHAR_HOOK, self.EventCharHook )
|
||||
self.Bind( wx.EVT_TIMER, self.TIMEREventBandwidth, id = ID_TIMER_GUI_BANDWIDTH )
|
||||
self.Bind( wx.EVT_TIMER, self.TIMEREventPageUpdate, id = ID_TIMER_PAGE_UPDATE )
|
||||
self.Bind( wx.EVT_TIMER, self.TIMEREventUIUpdate, id = ID_TIMER_UI_UPDATE )
|
||||
|
@ -171,6 +172,8 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
self._animation_update_windows = set()
|
||||
|
||||
self._my_shortcut_handler = ClientGUIShortcuts.ShortcutsHandler( self, [ 'main_gui' ] )
|
||||
|
||||
wx.CallAfter( self.Layout ) # some i3 thing--doesn't layout main gui on init for some reason
|
||||
|
||||
|
||||
|
@ -990,6 +993,19 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
#
|
||||
|
||||
i_and_e_submenu = wx.Menu()
|
||||
|
||||
submenu = wx.Menu()
|
||||
|
||||
ClientGUIMenus.AppendMenuCheckItem( self, submenu, 'import folders', 'Pause the client\'s import folders.', HC.options[ 'pause_import_folders_sync' ], self._PauseSync, 'import_folders' )
|
||||
ClientGUIMenus.AppendMenuCheckItem( self, submenu, 'export folders', 'Pause the client\'s export folders.', HC.options[ 'pause_export_folders_sync' ], self._PauseSync, 'export_folders' )
|
||||
|
||||
ClientGUIMenus.AppendMenu( i_and_e_submenu, submenu, 'pause' )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( i_and_e_submenu )
|
||||
|
||||
import_folder_names = self._controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_FOLDER )
|
||||
|
||||
if len( import_folder_names ) > 0:
|
||||
|
@ -1008,11 +1024,17 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
ClientGUIMenus.AppendMenuItem( self, submenu, name, 'Check this import folder now.', self._CheckImportFolder, name )
|
||||
|
||||
|
||||
ClientGUIMenus.AppendMenu( menu, submenu, 'check import folder now' )
|
||||
ClientGUIMenus.AppendMenu( i_and_e_submenu, submenu, 'check import folder now' )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( i_and_e_submenu )
|
||||
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage import folders', 'Manage folders from which the client can automatically import.', self._ManageImportFolders )
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage export folders', 'Manage folders to which the client can automatically export.', self._ManageExportFolders )
|
||||
ClientGUIMenus.AppendMenuItem( self, i_and_e_submenu, 'manage import folders', 'Manage folders from which the client can automatically import.', self._ManageImportFolders )
|
||||
ClientGUIMenus.AppendMenuItem( self, i_and_e_submenu, 'manage export folders', 'Manage folders to which the client can automatically export.', self._ManageExportFolders )
|
||||
|
||||
ClientGUIMenus.AppendMenu( menu, i_and_e_submenu, 'import and export folders' )
|
||||
|
||||
#
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
|
@ -1126,9 +1148,17 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
splitter_menu = wx.Menu()
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, splitter_menu, 'show/hide', 'Show or hide the panels on the left.', self._ShowHideSplitters )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( splitter_menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuCheckItem( self, splitter_menu, 'save current page\'s sash positions on client exit', 'Set whether sash position should be saved over on client exit.', self._new_options.GetBoolean( 'saving_sash_positions_on_exit' ), self._new_options.FlipBoolean, 'saving_sash_positions_on_exit' )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( splitter_menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, splitter_menu, 'save current page\'s sash positions now', 'Save the current page\'s sash positions.', self._SaveSplitterPositions )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( splitter_menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, splitter_menu, 'restore all pages\' sash positions to saved value', 'Restore the current sash positions for all pages to the values that are saved.', self._RestoreSplitterPositions )
|
||||
|
||||
ClientGUIMenus.AppendMenu( menu, splitter_menu, 'management and preview panels' )
|
||||
|
@ -1433,6 +1463,17 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
def network():
|
||||
|
||||
submenu = wx.Menu()
|
||||
|
||||
pause_all_new_network_traffic = self._controller.new_options.GetBoolean( 'pause_all_new_network_traffic' )
|
||||
|
||||
ClientGUIMenus.AppendMenuCheckItem( self, submenu, 'all new network traffic', 'Stop any new network jobs from sending data.', pause_all_new_network_traffic, self._controller.network_engine.PausePlayNewJobs )
|
||||
ClientGUIMenus.AppendMenuCheckItem( self, submenu, 'subscriptions', 'Pause the client\'s synchronisation with website subscriptions.', HC.options[ 'pause_subs_sync' ], self._PauseSync, 'subs' )
|
||||
|
||||
ClientGUIMenus.AppendMenu( menu, submenu, 'pause' )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'review bandwidth usage', 'See where you are consuming data.', self._ReviewBandwidth )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
@ -1474,6 +1515,13 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
ClientGUIMenus.AppendMenuItem( self, menu, 'manage http headers', 'Configure how the client talks to the network.', self._ManageNetworkHeaders )
|
||||
|
||||
submenu = wx.Menu()
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( self, submenu, 'pixiv', 'Reset pixiv session.', self._controller.network_engine.session_manager.ClearSession, ClientNetworking.NetworkContext( CC.NETWORK_CONTEXT_DOMAIN, 'pixiv.net' ) )
|
||||
ClientGUIMenus.AppendMenuItem( self, submenu, 'hentai foundry', 'Reset HF session.', self._controller.network_engine.session_manager.ClearSession, ClientNetworking.NetworkContext( CC.NETWORK_CONTEXT_DOMAIN, 'hentai-foundry.com' ) )
|
||||
|
||||
ClientGUIMenus.AppendMenu( menu, submenu, 'DEBUG: reset login' )
|
||||
|
||||
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 )
|
||||
|
@ -1488,10 +1536,7 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
submenu = wx.Menu()
|
||||
|
||||
ClientGUIMenus.AppendMenuCheckItem( self, submenu, 'export folders synchronisation', 'Pause the client\'s export folders.', HC.options[ 'pause_export_folders_sync' ], self._PauseSync, 'export_folders' )
|
||||
ClientGUIMenus.AppendMenuCheckItem( self, submenu, 'import folders synchronisation', 'Pause the client\'s import folders.', HC.options[ 'pause_import_folders_sync' ], self._PauseSync, 'import_folders' )
|
||||
ClientGUIMenus.AppendMenuCheckItem( self, submenu, 'repositories synchronisation', 'Pause the client\'s synchronisation with hydrus repositories.', HC.options[ 'pause_repo_sync' ], self._PauseSync, 'repo' )
|
||||
ClientGUIMenus.AppendMenuCheckItem( self, submenu, 'subscriptions synchronisation', 'Pause the client\'s synchronisation with website subscriptions.', HC.options[ 'pause_subs_sync' ], self._PauseSync, 'subs' )
|
||||
|
||||
ClientGUIMenus.AppendMenu( menu, submenu, 'pause' )
|
||||
|
||||
|
@ -1927,22 +1972,68 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
def _ManageExportFolders( self ):
|
||||
|
||||
original_pause_status = HC.options[ 'pause_export_folders_sync' ]
|
||||
|
||||
HC.options[ 'pause_export_folders_sync' ] = True
|
||||
|
||||
try:
|
||||
def wx_do_it():
|
||||
|
||||
if not self:
|
||||
|
||||
return
|
||||
|
||||
|
||||
with ClientGUIDialogsManage.DialogManageExportFolders( self ) as dlg:
|
||||
|
||||
dlg.ShowModal()
|
||||
|
||||
|
||||
finally:
|
||||
|
||||
def THREAD_do_it( controller ):
|
||||
|
||||
HC.options[ 'pause_export_folders_sync' ] = original_pause_status
|
||||
with self._delayed_dialog_lock:
|
||||
|
||||
original_pause_status = controller.options[ 'pause_export_folders_sync' ]
|
||||
|
||||
controller.options[ 'pause_export_folders_sync' ] = True
|
||||
|
||||
try:
|
||||
|
||||
if HG.export_folders_running:
|
||||
|
||||
job_key = ClientThreading.JobKey()
|
||||
|
||||
try:
|
||||
|
||||
job_key.SetVariable( 'popup_text_1', 'Waiting for import folders to finish.' )
|
||||
|
||||
controller.pub( 'message', job_key )
|
||||
|
||||
while HG.export_folders_running:
|
||||
|
||||
time.sleep( 0.1 )
|
||||
|
||||
if HG.view_shutdown:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
finally:
|
||||
|
||||
job_key.Delete()
|
||||
|
||||
|
||||
|
||||
controller.CallBlockingToWx( wx_do_it )
|
||||
|
||||
finally:
|
||||
|
||||
controller.options[ 'pause_export_folders_sync' ] = original_pause_status
|
||||
|
||||
controller.pub( 'notify_new_export_folders' )
|
||||
|
||||
|
||||
|
||||
|
||||
self._controller.CallToThread( THREAD_do_it, self._controller )
|
||||
|
||||
|
||||
def _ManageImportFolders( self ):
|
||||
|
||||
|
@ -1961,45 +2052,48 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
def THREAD_do_it( controller ):
|
||||
|
||||
original_pause_status = controller.options[ 'pause_import_folders_sync' ]
|
||||
|
||||
controller.options[ 'pause_import_folders_sync' ] = True
|
||||
|
||||
try:
|
||||
with self._delayed_dialog_lock:
|
||||
|
||||
if HG.import_folders_running:
|
||||
original_pause_status = controller.options[ 'pause_import_folders_sync' ]
|
||||
|
||||
controller.options[ 'pause_import_folders_sync' ] = True
|
||||
|
||||
try:
|
||||
|
||||
job_key = ClientThreading.JobKey()
|
||||
|
||||
try:
|
||||
if HG.import_folders_running:
|
||||
|
||||
job_key.SetVariable( 'popup_text_1', 'Waiting for import folders to finish.' )
|
||||
job_key = ClientThreading.JobKey()
|
||||
|
||||
controller.pub( 'message', job_key )
|
||||
|
||||
while HG.import_folders_running:
|
||||
try:
|
||||
|
||||
time.sleep( 0.1 )
|
||||
job_key.SetVariable( 'popup_text_1', 'Waiting for import folders to finish.' )
|
||||
|
||||
if HG.view_shutdown:
|
||||
controller.pub( 'message', job_key )
|
||||
|
||||
while HG.import_folders_running:
|
||||
|
||||
return
|
||||
time.sleep( 0.1 )
|
||||
|
||||
if HG.view_shutdown:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
finally:
|
||||
|
||||
job_key.Delete()
|
||||
finally:
|
||||
|
||||
job_key.Delete()
|
||||
|
||||
|
||||
|
||||
|
||||
controller.CallBlockingToWx( wx_do_it )
|
||||
|
||||
finally:
|
||||
|
||||
controller.options[ 'pause_import_folders_sync' ] = original_pause_status
|
||||
|
||||
controller.pub( 'notify_new_import_folders' )
|
||||
controller.CallBlockingToWx( wx_do_it )
|
||||
|
||||
finally:
|
||||
|
||||
controller.options[ 'pause_import_folders_sync' ] = original_pause_status
|
||||
|
||||
controller.pub( 'notify_new_import_folders' )
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -2171,47 +2265,50 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
def THREAD_do_it( controller ):
|
||||
|
||||
original_pause_status = controller.options[ 'pause_subs_sync' ]
|
||||
|
||||
controller.options[ 'pause_subs_sync' ] = True
|
||||
|
||||
try:
|
||||
with self._delayed_dialog_lock:
|
||||
|
||||
if HG.subscriptions_running:
|
||||
original_pause_status = controller.options[ 'pause_subs_sync' ]
|
||||
|
||||
controller.options[ 'pause_subs_sync' ] = True
|
||||
|
||||
try:
|
||||
|
||||
job_key = ClientThreading.JobKey()
|
||||
|
||||
try:
|
||||
if HG.subscriptions_running:
|
||||
|
||||
job_key.SetVariable( 'popup_text_1', 'Waiting for subs to finish.' )
|
||||
job_key = ClientThreading.JobKey()
|
||||
|
||||
controller.pub( 'message', job_key )
|
||||
|
||||
while HG.subscriptions_running:
|
||||
try:
|
||||
|
||||
time.sleep( 0.1 )
|
||||
job_key.SetVariable( 'popup_text_1', 'Waiting for subs to finish.' )
|
||||
|
||||
if HG.view_shutdown:
|
||||
controller.pub( 'message', job_key )
|
||||
|
||||
while HG.subscriptions_running:
|
||||
|
||||
return
|
||||
time.sleep( 0.1 )
|
||||
|
||||
if HG.view_shutdown:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
finally:
|
||||
|
||||
job_key.Delete()
|
||||
finally:
|
||||
|
||||
job_key.Delete()
|
||||
|
||||
|
||||
|
||||
|
||||
subscriptions = HG.client_controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION )
|
||||
|
||||
controller.CallBlockingToWx( wx_do_it, subscriptions )
|
||||
|
||||
finally:
|
||||
|
||||
controller.options[ 'pause_subs_sync' ] = original_pause_status
|
||||
|
||||
controller.pub( 'notify_new_subscriptions' )
|
||||
subscriptions = HG.client_controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION )
|
||||
|
||||
controller.CallBlockingToWx( wx_do_it, subscriptions )
|
||||
|
||||
finally:
|
||||
|
||||
controller.options[ 'pause_subs_sync' ] = original_pause_status
|
||||
|
||||
controller.pub( 'notify_new_subscriptions' )
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -2376,97 +2473,6 @@ class FrameGUI( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
self._controller.Write( 'save_options', HC.options )
|
||||
|
||||
|
||||
def _ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action == 'refresh':
|
||||
|
||||
self._Refresh()
|
||||
|
||||
elif action == 'new_page':
|
||||
|
||||
self._notebook.ChooseNewPageForDeepestNotebook()
|
||||
|
||||
if action == 'close_page':
|
||||
|
||||
self._notebook.CloseCurrentPage()
|
||||
|
||||
elif action == 'unclose_page':
|
||||
|
||||
self._UnclosePage()
|
||||
|
||||
elif action == 'check_all_import_folders':
|
||||
|
||||
self._CheckImportFolder()
|
||||
|
||||
elif action == 'flip_darkmode':
|
||||
|
||||
self.FlipDarkmode()
|
||||
|
||||
elif action == 'show_hide_splitters':
|
||||
|
||||
self._ShowHideSplitters()
|
||||
|
||||
elif action == 'synchronised_wait_switch':
|
||||
|
||||
self._SetSynchronisedWait()
|
||||
|
||||
elif action == 'set_media_focus':
|
||||
|
||||
self._SetMediaFocus()
|
||||
|
||||
elif action == 'set_search_focus':
|
||||
|
||||
self._SetSearchFocus()
|
||||
|
||||
elif action == 'redo':
|
||||
|
||||
self._controller.pub( 'redo' )
|
||||
|
||||
elif action == 'undo':
|
||||
|
||||
self._controller.pub( 'undo' )
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
def _ProcessShortcut( self, shortcut ):
|
||||
|
||||
shortcut_processed = False
|
||||
|
||||
command = HG.client_controller.GetCommandFromShortcut( [ 'main_gui' ], shortcut )
|
||||
|
||||
if command is not None:
|
||||
|
||||
command_processed = self._ProcessApplicationCommand( command )
|
||||
|
||||
if command_processed:
|
||||
|
||||
shortcut_processed = True
|
||||
|
||||
|
||||
|
||||
return shortcut_processed
|
||||
|
||||
|
||||
def _Refresh( self ):
|
||||
|
||||
page = self._notebook.GetCurrentMediaPage()
|
||||
|
@ -3325,26 +3331,6 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
self._DestroyPages( deletee_pages )
|
||||
|
||||
|
||||
def EventCharHook( self, event ):
|
||||
|
||||
if ClientGUIShortcuts.IShouldCatchCharHook( self ):
|
||||
|
||||
shortcut = ClientData.ConvertKeyEventToShortcut( event )
|
||||
|
||||
if shortcut is not None:
|
||||
|
||||
shortcut_processed = self._ProcessShortcut( shortcut )
|
||||
|
||||
if shortcut_processed:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
event.Skip()
|
||||
|
||||
|
||||
def EventClose( self, event ):
|
||||
|
||||
if not event.CanVeto():
|
||||
|
@ -3910,6 +3896,78 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
dest_page = self._notebook.PresentImportedFilesToPage( hashes, page_name )
|
||||
|
||||
|
||||
def ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action == 'refresh':
|
||||
|
||||
self._Refresh()
|
||||
|
||||
elif action == 'new_page':
|
||||
|
||||
self._notebook.ChooseNewPageForDeepestNotebook()
|
||||
|
||||
if action == 'close_page':
|
||||
|
||||
self._notebook.CloseCurrentPage()
|
||||
|
||||
elif action == 'unclose_page':
|
||||
|
||||
self._UnclosePage()
|
||||
|
||||
elif action == 'check_all_import_folders':
|
||||
|
||||
self._CheckImportFolder()
|
||||
|
||||
elif action == 'flip_darkmode':
|
||||
|
||||
self.FlipDarkmode()
|
||||
|
||||
elif action == 'show_hide_splitters':
|
||||
|
||||
self._ShowHideSplitters()
|
||||
|
||||
elif action == 'synchronised_wait_switch':
|
||||
|
||||
self._SetSynchronisedWait()
|
||||
|
||||
elif action == 'set_media_focus':
|
||||
|
||||
self._SetMediaFocus()
|
||||
|
||||
elif action == 'set_search_focus':
|
||||
|
||||
self._SetSearchFocus()
|
||||
|
||||
elif action == 'redo':
|
||||
|
||||
self._controller.pub( 'redo' )
|
||||
|
||||
elif action == 'undo':
|
||||
|
||||
self._controller.pub( 'undo' )
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
def RefreshMenu( self ):
|
||||
|
||||
if not self:
|
||||
|
|
|
@ -1002,10 +1002,34 @@ class CanvasFrame( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
|
||||
self._canvas_window = None
|
||||
|
||||
self.Bind( wx.EVT_CHAR_HOOK, self.EventCharHook )
|
||||
self._my_shortcut_handler = ClientGUIShortcuts.ShortcutsHandler( self, [ 'media_viewer' ] )
|
||||
|
||||
|
||||
def _ProcessApplicationCommand( self, command ):
|
||||
def Close( self ):
|
||||
|
||||
if HC.PLATFORM_OSX and self.IsFullScreen():
|
||||
|
||||
self.ShowFullScreen( False, wx.FULLSCREEN_ALL )
|
||||
|
||||
|
||||
self.Destroy()
|
||||
|
||||
|
||||
def FullscreenSwitch( self ):
|
||||
|
||||
if self.IsFullScreen():
|
||||
|
||||
self.ShowFullScreen( False, wx.FULLSCREEN_ALL )
|
||||
|
||||
else:
|
||||
|
||||
self.ShowFullScreen( True, wx.FULLSCREEN_ALL )
|
||||
|
||||
|
||||
self._canvas_window.ResetDragDelta()
|
||||
|
||||
|
||||
def ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
|
@ -1037,69 +1061,6 @@ class CanvasFrame( ClientGUITopLevelWindows.FrameThatResizes ):
|
|||
return command_processed
|
||||
|
||||
|
||||
def _ProcessShortcut( self, shortcut ):
|
||||
|
||||
shortcut_processed = False
|
||||
|
||||
command = HG.client_controller.GetCommandFromShortcut( [ 'media_viewer' ], shortcut )
|
||||
|
||||
if command is not None:
|
||||
|
||||
command_processed = self._ProcessApplicationCommand( command )
|
||||
|
||||
if command_processed:
|
||||
|
||||
shortcut_processed = True
|
||||
|
||||
|
||||
|
||||
return shortcut_processed
|
||||
|
||||
|
||||
def Close( self ):
|
||||
|
||||
if HC.PLATFORM_OSX and self.IsFullScreen():
|
||||
|
||||
self.ShowFullScreen( False, wx.FULLSCREEN_ALL )
|
||||
|
||||
|
||||
self.Destroy()
|
||||
|
||||
|
||||
def EventCharHook( self, event ):
|
||||
|
||||
if ClientGUIShortcuts.IShouldCatchCharHook( self ):
|
||||
|
||||
shortcut = ClientData.ConvertKeyEventToShortcut( event )
|
||||
|
||||
if shortcut is not None:
|
||||
|
||||
shortcut_processed = self._ProcessShortcut( shortcut )
|
||||
|
||||
if shortcut_processed:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
event.Skip()
|
||||
|
||||
|
||||
def FullscreenSwitch( self ):
|
||||
|
||||
if self.IsFullScreen():
|
||||
|
||||
self.ShowFullScreen( False, wx.FULLSCREEN_ALL )
|
||||
|
||||
else:
|
||||
|
||||
self.ShowFullScreen( True, wx.FULLSCREEN_ALL )
|
||||
|
||||
|
||||
self._canvas_window.ResetDragDelta()
|
||||
|
||||
|
||||
def SetCanvas( self, canvas_window ):
|
||||
|
||||
self._canvas_window = canvas_window
|
||||
|
@ -1233,7 +1194,14 @@ class Canvas( wx.Window ):
|
|||
|
||||
if self._current_media is not None:
|
||||
|
||||
HG.client_controller.pub( 'clipboard', 'bmp', self._current_media )
|
||||
if self._current_media.GetMime() in HC.IMAGES and self._current_media.GetDuration() is None:
|
||||
|
||||
HG.client_controller.pub( 'clipboard', 'bmp', self._current_media )
|
||||
|
||||
else:
|
||||
|
||||
wx.MessageBox( 'Sorry, cannot take bmps of anything but static images right now!' )
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1560,7 +1528,7 @@ class Canvas( wx.Window ):
|
|||
|
||||
with ClientGUITopLevelWindows.DialogEdit( self, title ) as dlg:
|
||||
|
||||
panel = ClientGUIScrolledPanels.EditSingleCtrlPanel( dlg )
|
||||
panel = ClientGUIScrolledPanels.EditSingleCtrlPanel( dlg, [ 'manage_file_notes' ] )
|
||||
|
||||
control = wx.TextCtrl( panel, style = wx.TE_MULTILINE )
|
||||
|
||||
|
@ -1575,6 +1543,7 @@ class Canvas( wx.Window ):
|
|||
dlg.SetPanel( panel )
|
||||
|
||||
wx.CallAfter( control.SetFocus )
|
||||
wx.CallAfter( control.SetInsertionPointEnd )
|
||||
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
|
||||
|
@ -1730,123 +1699,6 @@ class Canvas( wx.Window ):
|
|||
pass
|
||||
|
||||
|
||||
def _ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action == 'manage_file_ratings':
|
||||
|
||||
self._ManageRatings()
|
||||
|
||||
elif action == 'manage_file_tags':
|
||||
|
||||
self._ManageTags()
|
||||
|
||||
elif action == 'manage_file_urls':
|
||||
|
||||
self._ManageURLs()
|
||||
|
||||
elif action == 'manage_file_notes':
|
||||
|
||||
self._ManageNotes()
|
||||
|
||||
elif action == 'archive_file':
|
||||
|
||||
self._Archive()
|
||||
|
||||
elif action == 'copy_bmp':
|
||||
|
||||
self._CopyBMPToClipboard()
|
||||
|
||||
elif action == 'copy_file':
|
||||
|
||||
self._CopyFileToClipboard()
|
||||
|
||||
elif action == 'copy_path':
|
||||
|
||||
self._CopyPathToClipboard()
|
||||
|
||||
elif action == 'copy_sha256_hash':
|
||||
|
||||
self._CopyHashToClipboard( 'sha256' )
|
||||
|
||||
elif action == 'delete_file':
|
||||
|
||||
self._Delete()
|
||||
|
||||
elif action == 'inbox_file':
|
||||
|
||||
self._Inbox()
|
||||
|
||||
elif action == 'open_file_in_external_program':
|
||||
|
||||
self._OpenExternally()
|
||||
|
||||
elif action == 'pan_up':
|
||||
|
||||
self._DoManualPan( 0, -1 )
|
||||
|
||||
elif action == 'pan_down':
|
||||
|
||||
self._DoManualPan( 0, 1 )
|
||||
|
||||
elif action == 'pan_left':
|
||||
|
||||
self._DoManualPan( -1, 0 )
|
||||
|
||||
elif action == 'pan_right':
|
||||
|
||||
self._DoManualPan( 1, 0 )
|
||||
|
||||
elif action == 'move_animation_to_previous_frame':
|
||||
|
||||
self._media_container.GotoPreviousOrNextFrame( -1 )
|
||||
|
||||
elif action == 'move_animation_to_next_frame':
|
||||
|
||||
self._media_container.GotoPreviousOrNextFrame( 1 )
|
||||
|
||||
elif action == 'zoom_in':
|
||||
|
||||
self._ZoomIn()
|
||||
|
||||
elif action == 'zoom_out':
|
||||
|
||||
self._ZoomOut()
|
||||
|
||||
elif action == 'switch_between_100_percent_and_canvas_zoom':
|
||||
|
||||
self._ZoomSwitch()
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
elif command_type == CC.APPLICATION_COMMAND_TYPE_CONTENT:
|
||||
|
||||
if self._current_media is None:
|
||||
|
||||
return
|
||||
|
||||
|
||||
command_processed = ClientGUICommon.ApplyContentApplicationCommandToMedia( self, command, ( self._current_media, ) )
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
def _ProcessShortcut( self, shortcut ):
|
||||
|
||||
shortcut_processed = False
|
||||
|
@ -1857,7 +1709,7 @@ class Canvas( wx.Window ):
|
|||
|
||||
if command is not None:
|
||||
|
||||
command_processed = self._ProcessApplicationCommand( command )
|
||||
command_processed = self.ProcessApplicationCommand( command )
|
||||
|
||||
shortcut_processed = command_processed
|
||||
|
||||
|
@ -2277,13 +2129,127 @@ class Canvas( wx.Window ):
|
|||
|
||||
|
||||
|
||||
def ProcessApplicationCommand( self, canvas_key, command ):
|
||||
def ProcessApplicationCommand( self, command, canvas_key = None ):
|
||||
|
||||
if canvas_key == self._canvas_key:
|
||||
if canvas_key is not None and canvas_key != self._canvas_key:
|
||||
|
||||
self._ProcessApplicationCommand( command )
|
||||
return False
|
||||
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action == 'manage_file_ratings':
|
||||
|
||||
self._ManageRatings()
|
||||
|
||||
elif action == 'manage_file_tags':
|
||||
|
||||
self._ManageTags()
|
||||
|
||||
elif action == 'manage_file_urls':
|
||||
|
||||
self._ManageURLs()
|
||||
|
||||
elif action == 'manage_file_notes':
|
||||
|
||||
self._ManageNotes()
|
||||
|
||||
elif action == 'archive_file':
|
||||
|
||||
self._Archive()
|
||||
|
||||
elif action == 'copy_bmp':
|
||||
|
||||
self._CopyBMPToClipboard()
|
||||
|
||||
elif action == 'copy_file':
|
||||
|
||||
self._CopyFileToClipboard()
|
||||
|
||||
elif action == 'copy_path':
|
||||
|
||||
self._CopyPathToClipboard()
|
||||
|
||||
elif action == 'copy_sha256_hash':
|
||||
|
||||
self._CopyHashToClipboard( 'sha256' )
|
||||
|
||||
elif action == 'delete_file':
|
||||
|
||||
self._Delete()
|
||||
|
||||
elif action == 'inbox_file':
|
||||
|
||||
self._Inbox()
|
||||
|
||||
elif action == 'open_file_in_external_program':
|
||||
|
||||
self._OpenExternally()
|
||||
|
||||
elif action == 'pan_up':
|
||||
|
||||
self._DoManualPan( 0, -1 )
|
||||
|
||||
elif action == 'pan_down':
|
||||
|
||||
self._DoManualPan( 0, 1 )
|
||||
|
||||
elif action == 'pan_left':
|
||||
|
||||
self._DoManualPan( -1, 0 )
|
||||
|
||||
elif action == 'pan_right':
|
||||
|
||||
self._DoManualPan( 1, 0 )
|
||||
|
||||
elif action == 'move_animation_to_previous_frame':
|
||||
|
||||
self._media_container.GotoPreviousOrNextFrame( -1 )
|
||||
|
||||
elif action == 'move_animation_to_next_frame':
|
||||
|
||||
self._media_container.GotoPreviousOrNextFrame( 1 )
|
||||
|
||||
elif action == 'zoom_in':
|
||||
|
||||
self._ZoomIn()
|
||||
|
||||
elif action == 'zoom_out':
|
||||
|
||||
self._ZoomOut()
|
||||
|
||||
elif action == 'switch_between_100_percent_and_canvas_zoom':
|
||||
|
||||
self._ZoomSwitch()
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
elif command_type == CC.APPLICATION_COMMAND_TYPE_CONTENT:
|
||||
|
||||
if self._current_media is None:
|
||||
|
||||
return
|
||||
|
||||
|
||||
command_processed = ClientGUICommon.ApplyContentApplicationCommandToMedia( self, command, ( self._current_media, ) )
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
def ResetDragDelta( self ):
|
||||
|
||||
|
@ -3318,67 +3284,6 @@ class CanvasFilterDuplicates( CanvasWithHovers ):
|
|||
self._ProcessPair( HC.DUPLICATE_SAME_QUALITY )
|
||||
|
||||
|
||||
def _ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action == 'duplicate_filter_this_is_better':
|
||||
|
||||
self._CurrentMediaIsBetter()
|
||||
|
||||
elif action == 'duplicate_filter_exactly_the_same':
|
||||
|
||||
self._MediaAreTheSame()
|
||||
|
||||
elif action == 'duplicate_filter_alternates':
|
||||
|
||||
self._MediaAreAlternates()
|
||||
|
||||
elif action == 'duplicate_filter_not_dupes':
|
||||
|
||||
self._MediaAreNotDupes()
|
||||
|
||||
elif action == 'duplicate_filter_custom_action':
|
||||
|
||||
self._DoCustomAction()
|
||||
|
||||
elif action == 'duplicate_filter_skip':
|
||||
|
||||
self._SkipPair()
|
||||
|
||||
elif action == 'duplicate_filter_back':
|
||||
|
||||
self._GoBack()
|
||||
|
||||
elif action in ( 'view_first', 'view_last', 'view_previous', 'view_next' ):
|
||||
|
||||
self._SwitchMedia()
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
if not command_processed:
|
||||
|
||||
command_processed = CanvasWithHovers._ProcessApplicationCommand( self, command )
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
def _ProcessPair( self, duplicate_type, duplicate_action_options = None ):
|
||||
|
||||
if self._current_media is None:
|
||||
|
@ -3686,6 +3591,67 @@ class CanvasFilterDuplicates( CanvasWithHovers ):
|
|||
|
||||
|
||||
|
||||
def ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action == 'duplicate_filter_this_is_better':
|
||||
|
||||
self._CurrentMediaIsBetter()
|
||||
|
||||
elif action == 'duplicate_filter_exactly_the_same':
|
||||
|
||||
self._MediaAreTheSame()
|
||||
|
||||
elif action == 'duplicate_filter_alternates':
|
||||
|
||||
self._MediaAreAlternates()
|
||||
|
||||
elif action == 'duplicate_filter_not_dupes':
|
||||
|
||||
self._MediaAreNotDupes()
|
||||
|
||||
elif action == 'duplicate_filter_custom_action':
|
||||
|
||||
self._DoCustomAction()
|
||||
|
||||
elif action == 'duplicate_filter_skip':
|
||||
|
||||
self._SkipPair()
|
||||
|
||||
elif action == 'duplicate_filter_back':
|
||||
|
||||
self._GoBack()
|
||||
|
||||
elif action in ( 'view_first', 'view_last', 'view_previous', 'view_next' ):
|
||||
|
||||
self._SwitchMedia()
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
if not command_processed:
|
||||
|
||||
command_processed = CanvasWithHovers.ProcessApplicationCommand( self, command )
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
def ProcessContentUpdates( self, service_keys_to_content_updates ):
|
||||
|
||||
def catch_up():
|
||||
|
@ -4154,55 +4120,6 @@ class CanvasMediaListFilterArchiveDelete( CanvasMediaList ):
|
|||
else: self._ShowNext()
|
||||
|
||||
|
||||
def _ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action in ( 'archive_delete_filter_keep', 'archive_file' ):
|
||||
|
||||
self._Keep()
|
||||
|
||||
elif action in ( 'archive_delete_filter_delete', 'delete_file' ):
|
||||
|
||||
self._Delete()
|
||||
|
||||
elif action == 'archive_delete_filter_skip':
|
||||
|
||||
self._Skip()
|
||||
|
||||
elif action == 'archive_delete_filter_back':
|
||||
|
||||
self._Back()
|
||||
|
||||
elif action == 'launch_the_archive_delete_filter':
|
||||
|
||||
self._Close()
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
if not command_processed:
|
||||
|
||||
command_processed = CanvasMediaList._ProcessApplicationCommand( self, command )
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
def _Skip( self ):
|
||||
|
||||
if self._current_media == self._GetLast():
|
||||
|
@ -4338,6 +4255,55 @@ class CanvasMediaListFilterArchiveDelete( CanvasMediaList ):
|
|||
|
||||
|
||||
|
||||
def ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action in ( 'archive_delete_filter_keep', 'archive_file' ):
|
||||
|
||||
self._Keep()
|
||||
|
||||
elif action in ( 'archive_delete_filter_delete', 'delete_file' ):
|
||||
|
||||
self._Delete()
|
||||
|
||||
elif action == 'archive_delete_filter_skip':
|
||||
|
||||
self._Skip()
|
||||
|
||||
elif action == 'archive_delete_filter_back':
|
||||
|
||||
self._Back()
|
||||
|
||||
elif action == 'launch_the_archive_delete_filter':
|
||||
|
||||
self._Close()
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
if not command_processed:
|
||||
|
||||
command_processed = CanvasMediaList.ProcessApplicationCommand( self, command )
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
def Skip( self, canvas_key ):
|
||||
|
||||
if canvas_key == self._canvas_key:
|
||||
|
@ -4373,7 +4339,51 @@ class CanvasMediaListNavigable( CanvasMediaList ):
|
|||
return ClientGUIHoverFrames.FullscreenHoverFrameTopNavigableList( self, self._canvas_key )
|
||||
|
||||
|
||||
def _ProcessApplicationCommand( self, command ):
|
||||
def Archive( self, canvas_key ):
|
||||
|
||||
if self._canvas_key == canvas_key:
|
||||
|
||||
self._Archive()
|
||||
|
||||
|
||||
|
||||
def Delete( self, canvas_key ):
|
||||
|
||||
if self._canvas_key == canvas_key:
|
||||
|
||||
self._Delete()
|
||||
|
||||
|
||||
|
||||
def EventArchive( self, event ):
|
||||
|
||||
self._Archive()
|
||||
|
||||
|
||||
def EventDelete( self, event ):
|
||||
|
||||
self._Delete()
|
||||
|
||||
|
||||
def EventNext( self, event ):
|
||||
|
||||
self._ShowNext()
|
||||
|
||||
|
||||
def EventPrevious( self, event ):
|
||||
|
||||
self._ShowPrevious()
|
||||
|
||||
|
||||
def Inbox( self, canvas_key ):
|
||||
|
||||
if self._canvas_key == canvas_key:
|
||||
|
||||
self._Inbox()
|
||||
|
||||
|
||||
|
||||
def ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
|
@ -4420,56 +4430,12 @@ class CanvasMediaListNavigable( CanvasMediaList ):
|
|||
|
||||
if not command_processed:
|
||||
|
||||
command_processed = CanvasMediaList._ProcessApplicationCommand( self, command )
|
||||
command_processed = CanvasMediaList.ProcessApplicationCommand( self, command )
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
def Archive( self, canvas_key ):
|
||||
|
||||
if self._canvas_key == canvas_key:
|
||||
|
||||
self._Archive()
|
||||
|
||||
|
||||
|
||||
def Delete( self, canvas_key ):
|
||||
|
||||
if self._canvas_key == canvas_key:
|
||||
|
||||
self._Delete()
|
||||
|
||||
|
||||
|
||||
def EventArchive( self, event ):
|
||||
|
||||
self._Archive()
|
||||
|
||||
|
||||
def EventDelete( self, event ):
|
||||
|
||||
self._Delete()
|
||||
|
||||
|
||||
def EventNext( self, event ):
|
||||
|
||||
self._ShowNext()
|
||||
|
||||
|
||||
def EventPrevious( self, event ):
|
||||
|
||||
self._ShowPrevious()
|
||||
|
||||
|
||||
def Inbox( self, canvas_key ):
|
||||
|
||||
if self._canvas_key == canvas_key:
|
||||
|
||||
self._Inbox()
|
||||
|
||||
|
||||
|
||||
def ShowFirst( self, canvas_key ):
|
||||
|
||||
if canvas_key == self._canvas_key:
|
||||
|
|
|
@ -23,7 +23,7 @@ class BandwidthRulesCtrl( ClientGUICommon.StaticBox ):
|
|||
|
||||
listctrl_panel = ClientGUIListCtrl.BetterListCtrlPanel( self )
|
||||
|
||||
self._listctrl = ClientGUIListCtrl.BetterListCtrl( listctrl_panel, 'bandwidth_rules', 8, 10, [ ( 'type', -1 ), ( 'time delta', 16 ), ( 'max allowed', 14 ) ], self._ConvertRuleToListctrlTuples, delete_key_callback = self._Delete, activation_callback = self._Edit )
|
||||
self._listctrl = ClientGUIListCtrl.BetterListCtrl( listctrl_panel, 'bandwidth_rules', 8, 10, [ ( 'max allowed', 14 ), ( 'every', 16 ) ], self._ConvertRuleToListctrlTuples, delete_key_callback = self._Delete, activation_callback = self._Edit )
|
||||
|
||||
listctrl_panel.SetListCtrl( self._listctrl )
|
||||
|
||||
|
@ -67,8 +67,6 @@ class BandwidthRulesCtrl( ClientGUICommon.StaticBox ):
|
|||
|
||||
( bandwidth_type, time_delta, max_allowed ) = rule
|
||||
|
||||
pretty_bandwidth_type = HC.bandwidth_type_string_lookup[ bandwidth_type ]
|
||||
|
||||
pretty_time_delta = HydrusData.ConvertTimeDeltaToPrettyString( time_delta )
|
||||
|
||||
if bandwidth_type == HC.BANDWIDTH_TYPE_DATA:
|
||||
|
@ -77,11 +75,11 @@ class BandwidthRulesCtrl( ClientGUICommon.StaticBox ):
|
|||
|
||||
elif bandwidth_type == HC.BANDWIDTH_TYPE_REQUESTS:
|
||||
|
||||
pretty_max_allowed = HydrusData.ConvertIntToPrettyString( max_allowed )
|
||||
pretty_max_allowed = HydrusData.ConvertIntToPrettyString( max_allowed ) + ' requests'
|
||||
|
||||
|
||||
sort_tuple = ( pretty_bandwidth_type, time_delta, max_allowed )
|
||||
display_tuple = ( pretty_bandwidth_type, pretty_time_delta, pretty_max_allowed )
|
||||
sort_tuple = ( max_allowed, time_delta )
|
||||
display_tuple = ( pretty_max_allowed, pretty_time_delta )
|
||||
|
||||
return ( display_tuple, sort_tuple )
|
||||
|
||||
|
@ -154,12 +152,11 @@ class BandwidthRulesCtrl( ClientGUICommon.StaticBox ):
|
|||
|
||||
self._bandwidth_type.Bind( wx.EVT_CHOICE, self.EventBandwidth )
|
||||
|
||||
self._max_allowed_bytes = BytesControl( self )
|
||||
self._max_allowed_requests = wx.SpinCtrl( self, min = 1, max = 1048576 )
|
||||
|
||||
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 )
|
||||
|
||||
self._max_allowed_st = ClientGUICommon.BetterStaticText( self )
|
||||
|
||||
#
|
||||
|
||||
( bandwidth_type, time_delta, max_allowed ) = rule
|
||||
|
@ -170,42 +167,49 @@ class BandwidthRulesCtrl( ClientGUICommon.StaticBox ):
|
|||
|
||||
if bandwidth_type == HC.BANDWIDTH_TYPE_DATA:
|
||||
|
||||
max_allowed /= 1048576
|
||||
self._max_allowed_bytes.SetValue( max_allowed )
|
||||
|
||||
else:
|
||||
|
||||
self._max_allowed_requests.SetValue( max_allowed )
|
||||
|
||||
|
||||
self._max_allowed.SetValue( max_allowed )
|
||||
|
||||
self._UpdateMaxAllowedSt()
|
||||
self._UpdateEnabled()
|
||||
|
||||
#
|
||||
|
||||
hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
hbox.Add( self._max_allowed_bytes, CC.FLAGS_VCENTER )
|
||||
hbox.Add( self._max_allowed_requests, CC.FLAGS_VCENTER )
|
||||
hbox.Add( self._bandwidth_type, CC.FLAGS_VCENTER )
|
||||
hbox.Add( ClientGUICommon.BetterStaticText( self, ' every ' ), CC.FLAGS_VCENTER )
|
||||
hbox.Add( self._time_delta, CC.FLAGS_VCENTER )
|
||||
hbox.Add( self._max_allowed, CC.FLAGS_VCENTER )
|
||||
hbox.Add( self._max_allowed_st, CC.FLAGS_VCENTER )
|
||||
|
||||
self.SetSizer( hbox )
|
||||
|
||||
|
||||
def _UpdateMaxAllowedSt( self ):
|
||||
def _UpdateEnabled( self ):
|
||||
|
||||
bandwidth_type = self._bandwidth_type.GetChoice()
|
||||
|
||||
if bandwidth_type == HC.BANDWIDTH_TYPE_DATA:
|
||||
|
||||
self._max_allowed_st.SetLabelText( 'MB' )
|
||||
self._max_allowed_bytes.Show()
|
||||
self._max_allowed_requests.Hide()
|
||||
|
||||
elif bandwidth_type == HC.BANDWIDTH_TYPE_REQUESTS:
|
||||
|
||||
self._max_allowed_st.SetLabelText( 'requests' )
|
||||
self._max_allowed_bytes.Hide()
|
||||
self._max_allowed_requests.Show()
|
||||
|
||||
|
||||
self.Layout()
|
||||
|
||||
|
||||
def EventBandwidth( self, event ):
|
||||
|
||||
self._UpdateMaxAllowedSt()
|
||||
self._UpdateEnabled()
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
@ -214,17 +218,153 @@ class BandwidthRulesCtrl( ClientGUICommon.StaticBox ):
|
|||
|
||||
time_delta = self._time_delta.GetValue()
|
||||
|
||||
max_allowed = self._max_allowed.GetValue()
|
||||
|
||||
if bandwidth_type == HC.BANDWIDTH_TYPE_DATA:
|
||||
|
||||
max_allowed *= 1048576
|
||||
max_allowed = self._max_allowed_bytes.GetValue()
|
||||
|
||||
elif bandwidth_type == HC.BANDWIDTH_TYPE_REQUESTS:
|
||||
|
||||
max_allowed = self._max_allowed_requests.GetValue()
|
||||
|
||||
|
||||
return ( bandwidth_type, time_delta, max_allowed )
|
||||
|
||||
|
||||
|
||||
class BytesControl( wx.Panel ):
|
||||
|
||||
def __init__( self, parent, initial_value = 65536 ):
|
||||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
self._spin = wx.SpinCtrl( self, min = 0, max = 1048576, size = ( 60, -1 ) )
|
||||
|
||||
self._unit = ClientGUICommon.BetterChoice( self )
|
||||
|
||||
self._unit.Append( 'B', 1 )
|
||||
self._unit.Append( 'KB', 1024 )
|
||||
self._unit.Append( 'MB', 1024 * 1024 )
|
||||
self._unit.Append( 'GB', 1024 * 1024 * 1024 )
|
||||
|
||||
#
|
||||
|
||||
self.SetValue( initial_value )
|
||||
|
||||
#
|
||||
|
||||
hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
hbox.Add( self._spin, CC.FLAGS_VCENTER )
|
||||
hbox.Add( self._unit, CC.FLAGS_VCENTER )
|
||||
|
||||
self.SetSizer( hbox )
|
||||
|
||||
|
||||
def GetSeparatedValue( self ):
|
||||
|
||||
return ( self._spin.GetValue(), self._unit.GetChoice() )
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
return self._spin.GetValue() * self._unit.GetChoice()
|
||||
|
||||
|
||||
def SetSeparatedValue( self, value, unit ):
|
||||
|
||||
return ( self._spin.SetValue( value ), self._unit.SelectClientData( unit ) )
|
||||
|
||||
|
||||
def SetValue( self, value ):
|
||||
|
||||
max_unit = 1024 * 1024 * 1024
|
||||
|
||||
unit = 1
|
||||
|
||||
while value % 1024 == 0 and unit < max_unit:
|
||||
|
||||
value /= 1024
|
||||
|
||||
unit *= 1024
|
||||
|
||||
|
||||
self._spin.SetValue( value )
|
||||
self._unit.SelectClientData( unit )
|
||||
|
||||
|
||||
class NoneableBytesControl( wx.Panel ):
|
||||
|
||||
def __init__( self, parent, initial_value = 65536, none_label = 'no limit' ):
|
||||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
self._bytes = BytesControl( self )
|
||||
|
||||
self._none_checkbox = wx.CheckBox( self, label = none_label )
|
||||
|
||||
#
|
||||
|
||||
self.SetValue( initial_value )
|
||||
|
||||
#
|
||||
|
||||
hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
hbox.Add( self._bytes, CC.FLAGS_SIZER_VCENTER )
|
||||
hbox.Add( self._none_checkbox, CC.FLAGS_VCENTER )
|
||||
|
||||
self.SetSizer( hbox )
|
||||
|
||||
#
|
||||
|
||||
self._none_checkbox.Bind( wx.EVT_CHECKBOX, self.EventNoneChecked )
|
||||
|
||||
|
||||
def _UpdateEnabled( self ):
|
||||
|
||||
if self._none_checkbox.GetValue():
|
||||
|
||||
self._bytes.Disable()
|
||||
|
||||
else:
|
||||
|
||||
self._bytes.Enable()
|
||||
|
||||
|
||||
|
||||
def EventNoneChecked( self, event ):
|
||||
|
||||
self._UpdateEnabled()
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
if self._none_checkbox.GetValue():
|
||||
|
||||
return None
|
||||
|
||||
else:
|
||||
|
||||
return self._bytes.GetValue()
|
||||
|
||||
|
||||
|
||||
def SetValue( self, value ):
|
||||
|
||||
if value is None:
|
||||
|
||||
self._none_checkbox.SetValue( True )
|
||||
|
||||
else:
|
||||
|
||||
self._none_checkbox.SetValue( False )
|
||||
|
||||
self._bytes.SetValue( value )
|
||||
|
||||
|
||||
self._UpdateEnabled()
|
||||
|
||||
|
||||
class EditStringToStringDictControl( wx.Panel ):
|
||||
|
||||
def __init__( self, parent, initial_dict ):
|
||||
|
|
|
@ -15,6 +15,7 @@ import ClientGUIImport
|
|||
import ClientGUIOptionsPanels
|
||||
import ClientGUIPredicates
|
||||
import ClientGUIScrolledPanelsEdit
|
||||
import ClientGUIShortcuts
|
||||
import ClientGUISeedCache
|
||||
import ClientGUITime
|
||||
import ClientGUITopLevelWindows
|
||||
|
@ -3129,71 +3130,7 @@ class DialogManageRatings( ClientGUIDialogs.Dialog ):
|
|||
|
||||
#
|
||||
|
||||
self.Bind( wx.EVT_CHAR_HOOK, self.EventCharHook )
|
||||
|
||||
|
||||
def _ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action == 'manage_file_ratings':
|
||||
|
||||
self.EventOK( None )
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
def _ProcessShortcut( self, shortcut ):
|
||||
|
||||
shortcut_processed = False
|
||||
|
||||
command = HG.client_controller.GetCommandFromShortcut( [ 'media' ], shortcut )
|
||||
|
||||
if command is not None:
|
||||
|
||||
command_processed = self._ProcessApplicationCommand( command )
|
||||
|
||||
if command_processed:
|
||||
|
||||
shortcut_processed = True
|
||||
|
||||
|
||||
|
||||
return shortcut_processed
|
||||
|
||||
|
||||
def EventCharHook( self, event ):
|
||||
|
||||
shortcut = ClientData.ConvertKeyEventToShortcut( event )
|
||||
|
||||
if shortcut is not None:
|
||||
|
||||
shortcut_processed = self._ProcessShortcut( shortcut )
|
||||
|
||||
if shortcut_processed:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
event.Skip()
|
||||
self._my_shortcut_handler = ClientGUIShortcuts.ShortcutsHandler( self, [ 'media' ] )
|
||||
|
||||
|
||||
def EventOK( self, event ):
|
||||
|
@ -3231,6 +3168,34 @@ class DialogManageRatings( ClientGUIDialogs.Dialog ):
|
|||
|
||||
|
||||
|
||||
def ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action == 'manage_file_ratings':
|
||||
|
||||
self.EventOK( None )
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
class _LikePanel( wx.Panel ):
|
||||
|
||||
def __init__( self, parent, services, media ):
|
||||
|
@ -3687,6 +3652,8 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
self._tag_parents.Bind( wx.EVT_LIST_ITEM_SELECTED, self.EventItemSelected )
|
||||
self._tag_parents.Bind( wx.EVT_LIST_ITEM_DESELECTED, self.EventItemSelected )
|
||||
|
||||
self._tag_parents.Sort( 2 )
|
||||
|
||||
self._children = ClientGUIListBoxes.ListBoxTagsStringsAddRemove( self, self._service_key, show_sibling_text = False )
|
||||
self._parents = ClientGUIListBoxes.ListBoxTagsStringsAddRemove( self, self._service_key, show_sibling_text = False )
|
||||
|
||||
|
@ -3706,7 +3673,8 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
|
||||
#
|
||||
|
||||
self._status_st = ClientGUICommon.BetterStaticText( self, u'initialising\u2026' )
|
||||
self._status_st = ClientGUICommon.BetterStaticText( self, u'initialising\u2026' + os.linesep + '.' )
|
||||
self._count_st = ClientGUICommon.BetterStaticText( self, '' )
|
||||
|
||||
tags_box = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
|
@ -3721,6 +3689,7 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
vbox.Add( self._status_st, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.Add( self._count_st, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.Add( self._tag_parents, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
vbox.Add( self._add, CC.FLAGS_LONE_BUTTON )
|
||||
vbox.Add( tags_box, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
|
@ -3730,6 +3699,8 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
|
||||
#
|
||||
|
||||
self.Bind( ClientGUIListBoxes.EVT_LIST_BOX, self.EventListBoxChanged )
|
||||
|
||||
HG.client_controller.CallToThread( self.THREADInitialise, tags, self._service_key )
|
||||
|
||||
|
||||
|
@ -4030,8 +4001,65 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def _SetButtonStatus( self ):
|
||||
|
||||
if len( self._children.GetTags() ) == 0 or len( self._parents.GetTags() ) == 0: self._add.Disable()
|
||||
else: self._add.Enable()
|
||||
if len( self._children.GetTags() ) == 0 or len( self._parents.GetTags() ) == 0:
|
||||
|
||||
self._add.Disable()
|
||||
|
||||
else:
|
||||
|
||||
self._add.Enable()
|
||||
|
||||
|
||||
|
||||
def _UpdateListCtrlData( self ):
|
||||
|
||||
children = self._children.GetTags()
|
||||
parents = self._parents.GetTags()
|
||||
|
||||
pertinent_tags = children.union( parents )
|
||||
|
||||
self._tag_parents.DeleteDatas( self._tag_parents.GetData() )
|
||||
|
||||
all_pairs = set()
|
||||
|
||||
for ( status, pairs ) in self._current_statuses_to_pairs.items():
|
||||
|
||||
if status == HC.CONTENT_STATUS_DELETED:
|
||||
|
||||
continue
|
||||
|
||||
|
||||
|
||||
if len( pertinent_tags ) == 0:
|
||||
|
||||
if status == HC.CONTENT_STATUS_CURRENT:
|
||||
|
||||
continue
|
||||
|
||||
|
||||
# show all pending/petitioned
|
||||
|
||||
all_pairs.update( pairs )
|
||||
|
||||
else:
|
||||
|
||||
# show all appropriate
|
||||
|
||||
for pair in pairs:
|
||||
|
||||
( a, b ) = pair
|
||||
|
||||
if a in pertinent_tags or b in pertinent_tags:
|
||||
|
||||
all_pairs.add( pair )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
self._tag_parents.AddDatas( all_pairs )
|
||||
|
||||
self._tag_parents.Sort()
|
||||
|
||||
|
||||
def EnterChildren( self, tags ):
|
||||
|
@ -4042,6 +4070,8 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._children.EnterTags( tags )
|
||||
|
||||
self._UpdateListCtrlData()
|
||||
|
||||
self._SetButtonStatus()
|
||||
|
||||
|
||||
|
@ -4054,6 +4084,8 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._parents.EnterTags( tags )
|
||||
|
||||
self._UpdateListCtrlData()
|
||||
|
||||
self._SetButtonStatus()
|
||||
|
||||
|
||||
|
@ -4068,6 +4100,8 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
self._children.SetTags( [] )
|
||||
self._parents.SetTags( [] )
|
||||
|
||||
self._UpdateListCtrlData()
|
||||
|
||||
self._SetButtonStatus()
|
||||
|
||||
|
||||
|
@ -4076,6 +4110,11 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
self._SetButtonStatus()
|
||||
|
||||
|
||||
def EventListBoxChanged( self, event ):
|
||||
|
||||
self._UpdateListCtrlData()
|
||||
|
||||
|
||||
def GetContentUpdates( self ):
|
||||
|
||||
# we make it manually here because of the mass pending tags done (but not undone on a rescind) on a pending pair!
|
||||
|
@ -4134,11 +4173,12 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
self._original_statuses_to_pairs = original_statuses_to_pairs
|
||||
self._current_statuses_to_pairs = current_statuses_to_pairs
|
||||
|
||||
self._status_st.SetLabelText( 'Files with a tag on the left will also be given the tag on the right.' )
|
||||
self._status_st.SetLabelText( 'Files with a tag on the left will also be given the tag on the right.' + os.linesep + 'As an experiment, this panel will only display the \'current\' pairs for those tags entered below.' )
|
||||
self._count_st.SetLabelText( 'Starting with ' + HydrusData.ConvertIntToPrettyString( len( original_statuses_to_pairs[ HC.CONTENT_STATUS_CURRENT ] ) ) + ' pairs.' )
|
||||
|
||||
self._child_input.Enable()
|
||||
self._parent_input.Enable()
|
||||
|
||||
'''
|
||||
all_pairs = set()
|
||||
|
||||
for ( status, pairs ) in self._original_statuses_to_pairs.items():
|
||||
|
@ -4154,8 +4194,12 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
self._tag_parents.AddDatas( all_pairs )
|
||||
|
||||
self._tag_parents.Sort( 2 )
|
||||
|
||||
if tags is not None:
|
||||
'''
|
||||
if tags is None:
|
||||
|
||||
self._UpdateListCtrlData()
|
||||
|
||||
else:
|
||||
|
||||
self.EnterChildren( tags )
|
||||
|
||||
|
@ -4332,6 +4376,7 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
|||
#
|
||||
|
||||
self._status_st = ClientGUICommon.BetterStaticText( self, u'initialising\u2026' )
|
||||
self._count_st = ClientGUICommon.BetterStaticText( self, '' )
|
||||
|
||||
new_sibling_box = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
|
@ -4352,6 +4397,7 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
|||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
vbox.Add( self._status_st, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.Add( self._count_st, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.Add( self._tag_siblings, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
vbox.Add( self._add, CC.FLAGS_LONE_BUTTON )
|
||||
vbox.Add( text_box, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
|
@ -4843,6 +4889,7 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
|||
self._current_statuses_to_pairs = current_statuses_to_pairs
|
||||
|
||||
self._status_st.SetLabelText( 'Tags on the left will be replaced by those on the right.' )
|
||||
self._count_st.SetLabelText( 'Starting with ' + HydrusData.ConvertIntToPrettyString( len( original_statuses_to_pairs[ HC.CONTENT_STATUS_CURRENT ] ) ) + ' pairs.' )
|
||||
|
||||
self._old_input.Enable()
|
||||
self._new_input.Enable()
|
||||
|
|
|
@ -269,7 +269,7 @@ class FullscreenHoverFrameTop( FullscreenHoverFrame ):
|
|||
command = ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'inbox_file' )
|
||||
|
||||
|
||||
HG.client_controller.pub( 'canvas_application_command', self._canvas_key, command )
|
||||
HG.client_controller.pub( 'canvas_application_command', command, self._canvas_key )
|
||||
|
||||
|
||||
def _GetIdealSizeAndPosition( self ):
|
||||
|
@ -332,13 +332,13 @@ class FullscreenHoverFrameTop( FullscreenHoverFrame ):
|
|||
|
||||
self._zoom_text = ClientGUICommon.BetterStaticText( self, 'zoom' )
|
||||
|
||||
zoom_in = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.zoom_in, HG.client_controller.pub, 'canvas_application_command', self._canvas_key, ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'zoom_in' ) )
|
||||
zoom_in = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.zoom_in, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'zoom_in' ), self._canvas_key )
|
||||
zoom_in.SetToolTip( 'zoom in' )
|
||||
|
||||
zoom_out = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.zoom_out, HG.client_controller.pub, 'canvas_application_command', self._canvas_key, ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'zoom_out' ) )
|
||||
zoom_out = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.zoom_out, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'zoom_out' ), self._canvas_key )
|
||||
zoom_out.SetToolTip( 'zoom out' )
|
||||
|
||||
zoom_switch = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.zoom_switch, HG.client_controller.pub, 'canvas_application_command', self._canvas_key, ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'switch_between_100_percent_and_canvas_zoom' ) )
|
||||
zoom_switch = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.zoom_switch, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'switch_between_100_percent_and_canvas_zoom' ), self._canvas_key )
|
||||
zoom_switch.SetToolTip( 'zoom switch' )
|
||||
|
||||
menu_items = []
|
||||
|
@ -353,7 +353,7 @@ class FullscreenHoverFrameTop( FullscreenHoverFrame ):
|
|||
fullscreen_switch = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.fullscreen_switch, HG.client_controller.pub, 'canvas_fullscreen_switch', self._canvas_key )
|
||||
fullscreen_switch.SetToolTip( 'fullscreen switch' )
|
||||
|
||||
open_externally = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.open_externally, HG.client_controller.pub, 'canvas_application_command', self._canvas_key, ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'open_file_in_external_program' ) )
|
||||
open_externally = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.open_externally, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'open_file_in_external_program' ), self._canvas_key )
|
||||
open_externally.SetToolTip( 'open externally' )
|
||||
|
||||
close = ClientGUICommon.BetterButton( self, 'X', HG.client_controller.pub, 'canvas_close', self._canvas_key )
|
||||
|
@ -555,19 +555,19 @@ class FullscreenHoverFrameTopArchiveDeleteFilter( FullscreenHoverFrameTop ):
|
|||
|
||||
def _Archive( self ):
|
||||
|
||||
HG.client_controller.pub( 'canvas_application_command', self._canvas_key, ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'archive_file' ) )
|
||||
HG.client_controller.pub( 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'archive_file' ), self._canvas_key )
|
||||
|
||||
|
||||
def _PopulateLeftButtons( self ):
|
||||
|
||||
self._back_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.previous, HG.client_controller.pub, 'canvas_application_command', self._canvas_key, ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'archive_delete_filter_back' ) )
|
||||
self._back_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.previous, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'archive_delete_filter_back' ), self._canvas_key )
|
||||
self._back_button.SetToolTip( 'back' )
|
||||
|
||||
self._top_hbox.Add( self._back_button, CC.FLAGS_VCENTER )
|
||||
|
||||
FullscreenHoverFrameTop._PopulateLeftButtons( self )
|
||||
|
||||
self._skip_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.next, HG.client_controller.pub, 'canvas_application_command', self._canvas_key, ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'archive_delete_filter_skip' ) )
|
||||
self._skip_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.next, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'archive_delete_filter_skip' ), self._canvas_key )
|
||||
self._skip_button.SetToolTip( 'skip' )
|
||||
|
||||
self._top_hbox.Add( self._skip_button, CC.FLAGS_VCENTER )
|
||||
|
@ -583,12 +583,12 @@ class FullscreenHoverFrameTopNavigable( FullscreenHoverFrameTop ):
|
|||
|
||||
def _PopulateLeftButtons( self ):
|
||||
|
||||
self._previous_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.previous, HG.client_controller.pub, 'canvas_application_command', self._canvas_key, ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'view_previous' ) )
|
||||
self._previous_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.previous, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'view_previous' ), self._canvas_key )
|
||||
self._previous_button.SetToolTip( 'previous' )
|
||||
|
||||
self._index_text = ClientGUICommon.BetterStaticText( self, 'index' )
|
||||
|
||||
self._next_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.next, HG.client_controller.pub, 'canvas_application_command', self._canvas_key, ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'view_next' ) )
|
||||
self._next_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.next, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'view_next' ), self._canvas_key )
|
||||
self._next_button.SetToolTip( 'next' )
|
||||
|
||||
self._top_hbox.Add( self._previous_button, CC.FLAGS_VCENTER )
|
||||
|
@ -632,7 +632,7 @@ class FullscreenHoverFrameTopDuplicatesFilter( FullscreenHoverFrameTopNavigable
|
|||
|
||||
for ( label, tooltip, command ) in dupe_commands:
|
||||
|
||||
command_button = ClientGUICommon.BetterButton( self, label, HG.client_controller.pub, 'canvas_application_command', self._canvas_key, command )
|
||||
command_button = ClientGUICommon.BetterButton( self, label, HG.client_controller.pub, 'canvas_application_command', command, self._canvas_key )
|
||||
|
||||
command_button.SetToolTip( tooltip )
|
||||
|
||||
|
@ -684,14 +684,14 @@ class FullscreenHoverFrameTopDuplicatesFilter( FullscreenHoverFrameTopNavigable
|
|||
|
||||
def _PopulateLeftButtons( self ):
|
||||
|
||||
self._first_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.first, HG.client_controller.pub, 'canvas_application_command', self._canvas_key, ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'duplicate_filter_back' ) )
|
||||
self._first_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.first, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'duplicate_filter_back' ), self._canvas_key )
|
||||
self._first_button.SetToolTip( 'go back a pair' )
|
||||
|
||||
self._top_hbox.Add( self._first_button, CC.FLAGS_VCENTER )
|
||||
|
||||
FullscreenHoverFrameTopNavigable._PopulateLeftButtons( self )
|
||||
|
||||
self._last_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.last, HG.client_controller.pub, 'canvas_application_command', self._canvas_key, ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'duplicate_filter_skip' ) )
|
||||
self._last_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.last, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'duplicate_filter_skip' ), self._canvas_key )
|
||||
self._last_button.SetToolTip( 'show a different pair' )
|
||||
|
||||
self._top_hbox.Add( self._last_button, CC.FLAGS_VCENTER )
|
||||
|
@ -728,14 +728,14 @@ class FullscreenHoverFrameTopNavigableList( FullscreenHoverFrameTopNavigable ):
|
|||
|
||||
def _PopulateLeftButtons( self ):
|
||||
|
||||
self._first_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.first, HG.client_controller.pub, 'canvas_application_command', self._canvas_key, ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'view_first' ) )
|
||||
self._first_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.first, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'view_first' ), self._canvas_key )
|
||||
self._first_button.SetToolTip( 'first' )
|
||||
|
||||
self._top_hbox.Add( self._first_button, CC.FLAGS_VCENTER )
|
||||
|
||||
FullscreenHoverFrameTopNavigable._PopulateLeftButtons( self )
|
||||
|
||||
self._last_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.last, HG.client_controller.pub, 'canvas_application_command', self._canvas_key, ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'view_last' ) )
|
||||
self._last_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.last, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'view_last' ), self._canvas_key )
|
||||
self._last_button.SetToolTip( 'last' )
|
||||
|
||||
self._top_hbox.Add( self._last_button, CC.FLAGS_VCENTER )
|
||||
|
|
|
@ -1159,6 +1159,7 @@ class BetterListCtrlPanel( wx.Panel ):
|
|||
|
||||
def _ImportObject( self, obj ):
|
||||
|
||||
|
||||
bad_object_types = set()
|
||||
|
||||
if isinstance( obj, HydrusSerialisable.SerialisableList ):
|
||||
|
|
|
@ -123,7 +123,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
self._PublishSelectionChange()
|
||||
|
||||
self.Bind( wx.EVT_CHAR_HOOK, self.EventCharHook )
|
||||
self._my_shortcut_handler = ClientGUIShortcuts.ShortcutsHandler( self, [ 'media' ] )
|
||||
|
||||
|
||||
def _Archive( self ):
|
||||
|
@ -168,9 +168,19 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
def _CopyBMPToClipboard( self ):
|
||||
|
||||
media = self._focussed_media.GetDisplayMedia()
|
||||
|
||||
HG.client_controller.pub( 'clipboard', 'bmp', media )
|
||||
if self._focussed_media is not None:
|
||||
|
||||
media = self._focussed_media.GetDisplayMedia()
|
||||
|
||||
if media.GetMime() in HC.IMAGES and media.GetDuration() is None:
|
||||
|
||||
HG.client_controller.pub( 'clipboard', 'bmp', media )
|
||||
|
||||
else:
|
||||
|
||||
wx.MessageBox( 'Sorry, cannot take bmps of anything but static images right now!' )
|
||||
|
||||
|
||||
|
||||
|
||||
def _CopyFilesToClipboard( self ):
|
||||
|
@ -563,7 +573,16 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
s = num_files_string # 23 files
|
||||
|
||||
if num_selected > 0:
|
||||
if num_selected == 0:
|
||||
|
||||
if num_files > 0:
|
||||
|
||||
pretty_total_size = self._GetPrettyTotalSize()
|
||||
|
||||
s += ' - totalling ' + pretty_total_size
|
||||
|
||||
|
||||
else:
|
||||
|
||||
s += ' - '
|
||||
|
||||
|
@ -599,7 +618,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
inbox_phrase = HydrusData.ConvertIntToPrettyString( num_inbox ) + ' in inbox and ' + HydrusData.ConvertIntToPrettyString( num_selected - num_inbox ) + ' archived, '
|
||||
|
||||
|
||||
pretty_total_size = self._GetPrettyTotalSelectedSize()
|
||||
pretty_total_size = self._GetPrettyTotalSize( only_selected = True )
|
||||
|
||||
s += selected_files_string + ' selected, ' + inbox_phrase + 'totalling ' + pretty_total_size
|
||||
|
||||
|
@ -608,21 +627,42 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
return s
|
||||
|
||||
|
||||
def _GetPrettyTotalSelectedSize( self ):
|
||||
def _GetPrettyTotalSize( self, only_selected = False ):
|
||||
|
||||
total_size = sum( [ media.GetSize() for media in self._selected_media ] )
|
||||
|
||||
unknown_size = False in ( media.IsSizeDefinite() for media in self._selected_media )
|
||||
|
||||
if total_size == 0:
|
||||
if only_selected:
|
||||
|
||||
if unknown_size: return 'unknown size'
|
||||
else: return HydrusData.ConvertIntToBytes( 0 )
|
||||
media_source = self._selected_media
|
||||
|
||||
else:
|
||||
|
||||
if unknown_size: return HydrusData.ConvertIntToBytes( total_size ) + ' + some unknown size'
|
||||
else: return HydrusData.ConvertIntToBytes( total_size )
|
||||
media_source = self._sorted_media
|
||||
|
||||
|
||||
total_size = sum( [ media.GetSize() for media in media_source ] )
|
||||
|
||||
unknown_size = False in ( media.IsSizeDefinite() for media in media_source )
|
||||
|
||||
if total_size == 0:
|
||||
|
||||
if unknown_size:
|
||||
|
||||
return 'unknown size'
|
||||
|
||||
else:
|
||||
|
||||
return HydrusData.ConvertIntToBytes( 0 )
|
||||
|
||||
|
||||
else:
|
||||
|
||||
if unknown_size:
|
||||
|
||||
return HydrusData.ConvertIntToBytes( total_size ) + ' + some unknown size'
|
||||
|
||||
else:
|
||||
|
||||
return HydrusData.ConvertIntToBytes( total_size )
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -853,7 +893,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
with ClientGUITopLevelWindows.DialogEdit( self, title ) as dlg:
|
||||
|
||||
panel = ClientGUIScrolledPanels.EditSingleCtrlPanel( dlg )
|
||||
panel = ClientGUIScrolledPanels.EditSingleCtrlPanel( dlg, [ 'manage_file_notes' ] )
|
||||
|
||||
control = wx.TextCtrl( panel, style = wx.TE_MULTILINE )
|
||||
|
||||
|
@ -868,6 +908,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
dlg.SetPanel( panel )
|
||||
|
||||
wx.CallAfter( control.SetFocus )
|
||||
wx.CallAfter( control.SetInsertionPointEnd )
|
||||
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
|
||||
|
@ -1076,122 +1117,6 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
|
||||
|
||||
def _ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action == 'copy_bmp':
|
||||
|
||||
self._CopyBMPToClipboard()
|
||||
|
||||
elif action == 'copy_file':
|
||||
|
||||
self._CopyFilesToClipboard()
|
||||
|
||||
elif action == 'copy_path':
|
||||
|
||||
self._CopyPathsToClipboard()
|
||||
|
||||
elif action == 'copy_sha256_hash':
|
||||
|
||||
self._CopyHashesToClipboard( 'sha256' )
|
||||
|
||||
elif action == 'manage_file_ratings':
|
||||
|
||||
self._ManageRatings()
|
||||
|
||||
elif action == 'manage_file_tags':
|
||||
|
||||
self._ManageTags()
|
||||
|
||||
elif action == 'manage_file_urls':
|
||||
|
||||
self._ManageURLs()
|
||||
|
||||
elif action == 'manage_file_notes':
|
||||
|
||||
self._ManageNotes()
|
||||
|
||||
elif action == 'archive_file':
|
||||
|
||||
self._Archive()
|
||||
|
||||
elif action == 'delete_file':
|
||||
|
||||
self._Delete()
|
||||
|
||||
elif action == 'inbox_file':
|
||||
|
||||
self._Inbox()
|
||||
|
||||
elif action == 'remove_file_from_view':
|
||||
|
||||
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()
|
||||
|
||||
elif action == 'launch_the_archive_delete_filter':
|
||||
|
||||
self._ArchiveDeleteFilter()
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
elif command_type == CC.APPLICATION_COMMAND_TYPE_CONTENT:
|
||||
|
||||
command_processed = ClientGUICommon.ApplyContentApplicationCommandToMedia( self, command, self._GetSelectedFlatMedia() )
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
def _ProcessShortcut( self, shortcut ):
|
||||
|
||||
shortcut_processed = False
|
||||
|
||||
command = HG.client_controller.GetCommandFromShortcut( [ 'media' ], shortcut )
|
||||
|
||||
if command is not None:
|
||||
|
||||
command_processed = self._ProcessApplicationCommand( command )
|
||||
|
||||
shortcut_processed = command_processed
|
||||
|
||||
|
||||
return shortcut_processed
|
||||
|
||||
|
||||
def _PublishSelectionChange( self, force_reload = False ):
|
||||
|
||||
if HG.client_controller.gui.IsCurrentPage( self._page_key ):
|
||||
|
@ -1688,26 +1613,6 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
|
||||
|
||||
def EventCharHook( self, event ):
|
||||
|
||||
if ClientGUIShortcuts.IShouldCatchCharHook( self ):
|
||||
|
||||
shortcut = ClientData.ConvertKeyEventToShortcut( event )
|
||||
|
||||
if shortcut is not None:
|
||||
|
||||
shortcut_processed = self._ProcessShortcut( shortcut )
|
||||
|
||||
if shortcut_processed:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
event.Skip()
|
||||
|
||||
|
||||
def FileDumped( self, page_key, hash, status ):
|
||||
|
||||
if page_key == self._page_key:
|
||||
|
@ -1732,6 +1637,106 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
|||
self._PublishSelectionChange()
|
||||
|
||||
|
||||
def ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action == 'copy_bmp':
|
||||
|
||||
self._CopyBMPToClipboard()
|
||||
|
||||
elif action == 'copy_file':
|
||||
|
||||
self._CopyFilesToClipboard()
|
||||
|
||||
elif action == 'copy_path':
|
||||
|
||||
self._CopyPathsToClipboard()
|
||||
|
||||
elif action == 'copy_sha256_hash':
|
||||
|
||||
self._CopyHashesToClipboard( 'sha256' )
|
||||
|
||||
elif action == 'manage_file_ratings':
|
||||
|
||||
self._ManageRatings()
|
||||
|
||||
elif action == 'manage_file_tags':
|
||||
|
||||
self._ManageTags()
|
||||
|
||||
elif action == 'manage_file_urls':
|
||||
|
||||
self._ManageURLs()
|
||||
|
||||
elif action == 'manage_file_notes':
|
||||
|
||||
self._ManageNotes()
|
||||
|
||||
elif action == 'archive_file':
|
||||
|
||||
self._Archive()
|
||||
|
||||
elif action == 'delete_file':
|
||||
|
||||
self._Delete()
|
||||
|
||||
elif action == 'inbox_file':
|
||||
|
||||
self._Inbox()
|
||||
|
||||
elif action == 'remove_file_from_view':
|
||||
|
||||
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()
|
||||
|
||||
elif action == 'launch_the_archive_delete_filter':
|
||||
|
||||
self._ArchiveDeleteFilter()
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
elif command_type == CC.APPLICATION_COMMAND_TYPE_CONTENT:
|
||||
|
||||
command_processed = ClientGUICommon.ApplyContentApplicationCommandToMedia( self, command, self._GetSelectedFlatMedia() )
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
def ProcessContentUpdates( self, service_keys_to_content_updates ):
|
||||
|
||||
ClientMedia.ListeningMediaList.ProcessContentUpdates( self, service_keys_to_content_updates )
|
||||
|
@ -2664,8 +2669,11 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
# accelerator tables can't handle escape key in windows, gg
|
||||
|
||||
if event.GetKeyCode() == wx.WXK_ESCAPE: self._Select( 'none' )
|
||||
if event.GetKeyCode() in ( wx.WXK_PAGEUP, wx.WXK_PAGEDOWN ):
|
||||
if event.GetKeyCode() == wx.WXK_ESCAPE:
|
||||
|
||||
self._Select( 'none' )
|
||||
|
||||
elif event.GetKeyCode() in ( wx.WXK_PAGEUP, wx.WXK_PAGEDOWN ):
|
||||
|
||||
if event.GetKeyCode() == wx.WXK_PAGEUP:
|
||||
|
||||
|
@ -3092,7 +3100,7 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
if multiple_selected:
|
||||
|
||||
ClientGUIMenus.AppendMenuLabel( menu, HydrusData.ConvertIntToPrettyString( num_selected ) + ' files, ' + self._GetPrettyTotalSelectedSize() )
|
||||
ClientGUIMenus.AppendMenuLabel( menu, HydrusData.ConvertIntToPrettyString( num_selected ) + ' files, ' + self._GetPrettyTotalSize( only_selected = True ) )
|
||||
|
||||
else:
|
||||
|
||||
|
|
|
@ -1209,7 +1209,7 @@ class ReviewServicePanel( wx.Panel ):
|
|||
|
||||
except Exception as e:
|
||||
|
||||
wx.MessageBox( unicode( e ) )
|
||||
wx.MessageBox( HydrusData.ToUnicode( e ) )
|
||||
|
||||
return
|
||||
|
||||
|
|
|
@ -2660,7 +2660,7 @@ class EditPageParserPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
except Exception as e:
|
||||
|
||||
example_data = 'fetch failed:' + os.linesep * 2 + unicode( e )
|
||||
example_data = 'fetch failed:' + os.linesep * 2 + HydrusData.ToUnicode( e )
|
||||
|
||||
HydrusData.ShowException( e )
|
||||
|
||||
|
@ -3830,7 +3830,7 @@ class EditStringMatchPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
except HydrusExceptions.StringMatchException as e:
|
||||
|
||||
reason = unicode( e )
|
||||
reason = HydrusData.ToUnicode( e )
|
||||
|
||||
self._example_string_matches.SetLabelText( 'Example does not match - ' + reason )
|
||||
self._example_string_matches.SetForegroundColour( ( 128, 0, 0 ) )
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import ClientConstants as CC
|
||||
import ClientData
|
||||
import ClientGUICommon
|
||||
import ClientGUIControls
|
||||
import ClientGUIOptionsPanels
|
||||
import ClientRatings
|
||||
import ClientSearch
|
||||
|
@ -814,9 +815,7 @@ class PanelPredicateSystemSize( PanelPredicateSystem ):
|
|||
|
||||
self._sign = wx.RadioBox( self, choices = [ '<', u'\u2248', '=', '>' ] )
|
||||
|
||||
self._size = wx.SpinCtrl( self, max = 1048576, size = ( 60, -1 ) )
|
||||
|
||||
self._unit = wx.RadioBox( self, choices = [ 'B', 'KB', 'MB', 'GB' ] )
|
||||
self._bytes = ClientGUIControls.BytesControl( self )
|
||||
|
||||
system_predicates = HC.options[ 'file_system_predicates' ]
|
||||
|
||||
|
@ -824,25 +823,24 @@ class PanelPredicateSystemSize( PanelPredicateSystem ):
|
|||
|
||||
self._sign.SetStringSelection( sign )
|
||||
|
||||
self._size.SetValue( size )
|
||||
|
||||
self._unit.SetStringSelection( HydrusData.ConvertIntToUnit( unit ) )
|
||||
self._bytes.SetSeparatedValue( size, unit )
|
||||
|
||||
hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
hbox.Add( ClientGUICommon.BetterStaticText( self, 'system:size' ), CC.FLAGS_VCENTER )
|
||||
hbox.Add( self._sign, CC.FLAGS_VCENTER )
|
||||
hbox.Add( self._size, CC.FLAGS_VCENTER )
|
||||
hbox.Add( self._unit, CC.FLAGS_VCENTER )
|
||||
hbox.Add( self._bytes, CC.FLAGS_VCENTER )
|
||||
|
||||
self.SetSizer( hbox )
|
||||
|
||||
wx.CallAfter( self._size.SetFocus )
|
||||
wx.CallAfter( self._bytes.SetFocus )
|
||||
|
||||
|
||||
def GetInfo( self ):
|
||||
|
||||
info = ( self._sign.GetStringSelection(), self._size.GetValue(), HydrusData.ConvertUnitToInt( self._unit.GetStringSelection() ) )
|
||||
( size, unit ) = self._bytes.GetSeparatedValue()
|
||||
|
||||
info = ( self._sign.GetStringSelection(), size, unit )
|
||||
|
||||
return info
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import ClientConstants as CC
|
||||
import ClientGUIShortcuts
|
||||
import ClientGUITopLevelWindows
|
||||
import wx
|
||||
import wx.lib.scrolledpanel
|
||||
|
||||
|
@ -11,6 +13,11 @@ class ResizingScrolledPanel( wx.lib.scrolledpanel.ScrolledPanel ):
|
|||
self.Bind( CC.EVT_SIZE_CHANGED, self.EventSizeChanged )
|
||||
|
||||
|
||||
def _OKParent( self ):
|
||||
|
||||
wx.QueueEvent( self.GetEventHandler(), ClientGUITopLevelWindows.OKEvent( -1 ) )
|
||||
|
||||
|
||||
def EventSizeChanged( self, event ):
|
||||
|
||||
self.SetVirtualSize( self.GetBestVirtualSize() )
|
||||
|
@ -32,24 +39,61 @@ class EditPanel( ResizingScrolledPanel ):
|
|||
|
||||
class EditSingleCtrlPanel( EditPanel ):
|
||||
|
||||
def __init__( self, parent ):
|
||||
def __init__( self, parent, ok_on_these_commands = None ):
|
||||
|
||||
EditPanel.__init__( self, parent )
|
||||
|
||||
self._control = None
|
||||
|
||||
if ok_on_these_commands is None:
|
||||
|
||||
ok_on_these_commands = set()
|
||||
|
||||
|
||||
self._ok_on_these_commands = set( ok_on_these_commands )
|
||||
|
||||
#
|
||||
|
||||
self._vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
self.SetSizer( self._vbox )
|
||||
|
||||
self._my_shortcuts_handler = ClientGUIShortcuts.ShortcutsHandler( self, [ 'media' ] )
|
||||
|
||||
|
||||
def GetValue( self ):
|
||||
|
||||
return self._control.GetValue()
|
||||
|
||||
|
||||
def ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action in self._ok_on_these_commands:
|
||||
|
||||
self._OKParent()
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
def SetControl( self, control ):
|
||||
|
||||
self._control = control
|
||||
|
|
|
@ -710,19 +710,19 @@ class EditFileImportOptions( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
self._allow_decompression_bombs = wx.CheckBox( pre_import_panel )
|
||||
|
||||
self._min_size = ClientGUICommon.NoneableSpinCtrl( pre_import_panel, 'size', unit = 'KB', multiplier = 1024 )
|
||||
self._min_size.SetValue( 5120 )
|
||||
self._min_size = ClientGUIControls.NoneableBytesControl( pre_import_panel )
|
||||
self._min_size.SetValue( 5 * 1024 )
|
||||
|
||||
self._max_size = ClientGUICommon.NoneableSpinCtrl( pre_import_panel, 'size', unit = 'MB', multiplier = 1048576 )
|
||||
self._max_size.SetValue( 100 * 1024 )
|
||||
self._max_size = ClientGUIControls.NoneableBytesControl( pre_import_panel )
|
||||
self._max_size.SetValue( 100 * 1024 * 1024 )
|
||||
|
||||
self._max_gif_size = ClientGUICommon.NoneableSpinCtrl( pre_import_panel, 'size', unit = 'MB', multiplier = 1048576 )
|
||||
self._max_gif_size.SetValue( 32 * 1024 )
|
||||
self._max_gif_size = ClientGUIControls.NoneableBytesControl( pre_import_panel )
|
||||
self._max_gif_size.SetValue( 32 * 1024 * 1024 )
|
||||
|
||||
self._min_resolution = ClientGUICommon.NoneableSpinCtrl( pre_import_panel, 'resolution', num_dimensions = 2 )
|
||||
self._min_resolution = ClientGUICommon.NoneableSpinCtrl( pre_import_panel, num_dimensions = 2 )
|
||||
self._min_resolution.SetValue( ( 50, 50 ) )
|
||||
|
||||
self._max_resolution = ClientGUICommon.NoneableSpinCtrl( pre_import_panel, 'resolution', num_dimensions = 2 )
|
||||
self._max_resolution = ClientGUICommon.NoneableSpinCtrl( pre_import_panel, num_dimensions = 2 )
|
||||
self._max_resolution.SetValue( ( 8192, 8192 ) )
|
||||
|
||||
#
|
||||
|
@ -4398,14 +4398,14 @@ class EditURLMatchPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
except HydrusExceptions.StringConvertException as e:
|
||||
|
||||
reason = unicode( e )
|
||||
reason = HydrusData.ToUnicode( e )
|
||||
|
||||
self._api_url.SetValue( 'Could not convert - ' + reason )
|
||||
|
||||
|
||||
except HydrusExceptions.URLMatchException as e:
|
||||
|
||||
reason = unicode( e )
|
||||
reason = HydrusData.ToUnicode( e )
|
||||
|
||||
self._example_url_matches.SetLabelText( 'Example does not match - ' + reason )
|
||||
self._example_url_matches.SetForegroundColour( ( 128, 0, 0 ) )
|
||||
|
|
|
@ -14,6 +14,7 @@ import ClientGUIScrolledPanels
|
|||
import ClientGUIScrolledPanelsEdit
|
||||
import ClientGUIScrolledPanelsReview
|
||||
import ClientGUISerialisable
|
||||
import ClientGUIShortcuts
|
||||
import ClientGUITagSuggestions
|
||||
import ClientGUITopLevelWindows
|
||||
import ClientNetworking
|
||||
|
@ -690,7 +691,7 @@ class ManageClientServicesPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
except HydrusExceptions.VetoException as e:
|
||||
|
||||
message = unicode( e )
|
||||
message = HydrusData.ToUnicode( e )
|
||||
|
||||
if len( message ) > 0:
|
||||
|
||||
|
@ -870,7 +871,7 @@ class ManageClientServicesPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
except HydrusExceptions.VetoException as e:
|
||||
|
||||
message = unicode( e )
|
||||
message = HydrusData.ToUnicode( e )
|
||||
|
||||
if len( message ) > 0:
|
||||
|
||||
|
@ -970,7 +971,7 @@ class ManageClientServicesPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
except HydrusExceptions.VetoException as e:
|
||||
|
||||
message = unicode( e )
|
||||
message = HydrusData.ToUnicode( e )
|
||||
|
||||
if len( message ) > 0:
|
||||
|
||||
|
@ -3099,10 +3100,10 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
help_hbox = ClientGUICommon.WrapInText( disk_cache_help_button, disk_panel, 'help for this panel -->', wx.Colour( 0, 0, 255 ) )
|
||||
|
||||
self._disk_cache_init_period = ClientGUICommon.NoneableSpinCtrl( disk_panel, 'max disk cache init period', none_phrase = 'do not run', min = 1, max = 120 )
|
||||
self._disk_cache_init_period = ClientGUICommon.NoneableSpinCtrl( disk_panel, 'run disk cache on boot for this long', unit = 's', none_phrase = 'do not run', min = 1, max = 120 )
|
||||
self._disk_cache_init_period.SetToolTip( 'When the client boots, it can speed up operation by reading the front of the database into memory. This sets the max number of seconds it can spend doing that.' )
|
||||
|
||||
self._disk_cache_maintenance_mb = ClientGUICommon.NoneableSpinCtrl( disk_panel, 'disk cache maintenance (MB)', none_phrase = 'do not keep db cached', min = 32, max = 65536 )
|
||||
self._disk_cache_maintenance_mb = ClientGUICommon.NoneableSpinCtrl( disk_panel, 'disk cache maintenance', unit = 'MB', none_phrase = 'do not keep db cached', min = 32, max = 65536 )
|
||||
self._disk_cache_maintenance_mb.SetToolTip( 'The client can regularly check the front of its database is cached in memory. This represents how many megabytes it will ensure are cached.' )
|
||||
|
||||
#
|
||||
|
@ -4917,8 +4918,6 @@ class ManageTagsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
self.SetSizer( vbox )
|
||||
|
||||
self.Bind( wx.EVT_CHAR_HOOK, self.EventCharHook )
|
||||
|
||||
self.Bind( ClientGUIACDropdown.EVT_SELECT_UP, self.EventSelectUp )
|
||||
self.Bind( ClientGUIACDropdown.EVT_SELECT_DOWN, self.EventSelectDown )
|
||||
|
||||
|
@ -4930,6 +4929,8 @@ class ManageTagsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
HG.client_controller.sub( self, 'CanvasHasNewMedia', 'canvas_new_display_media' )
|
||||
|
||||
|
||||
self._my_shortcut_handler = ClientGUIShortcuts.ShortcutsHandler( self, [ 'media', 'main_gui' ] )
|
||||
|
||||
|
||||
def _GetServiceKeysToContentUpdates( self ):
|
||||
|
||||
|
@ -4948,62 +4949,6 @@ class ManageTagsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
return service_keys_to_content_updates
|
||||
|
||||
|
||||
def _OKParent( self ):
|
||||
|
||||
wx.QueueEvent( self.GetEventHandler(), ClientGUITopLevelWindows.OKEvent( -1 ) )
|
||||
|
||||
|
||||
def _ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action == 'manage_file_tags':
|
||||
|
||||
self._OKParent()
|
||||
|
||||
elif action == 'set_search_focus':
|
||||
|
||||
self._SetSearchFocus()
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
def _ProcessShortcut( self, shortcut ):
|
||||
|
||||
shortcut_processed = False
|
||||
|
||||
command = HG.client_controller.GetCommandFromShortcut( [ 'media', 'main_gui' ], shortcut )
|
||||
|
||||
if command is not None:
|
||||
|
||||
command_processed = self._ProcessApplicationCommand( command )
|
||||
|
||||
if command_processed:
|
||||
|
||||
shortcut_processed = True
|
||||
|
||||
|
||||
|
||||
return shortcut_processed
|
||||
|
||||
|
||||
def _SetSearchFocus( self ):
|
||||
|
||||
page = self._tag_repositories.GetCurrentPage()
|
||||
|
@ -5057,23 +5002,6 @@ class ManageTagsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
|
||||
|
||||
def EventCharHook( self, event ):
|
||||
|
||||
shortcut = ClientData.ConvertKeyEventToShortcut( event )
|
||||
|
||||
if shortcut is not None:
|
||||
|
||||
shortcut_processed = self._ProcessShortcut( shortcut )
|
||||
|
||||
if shortcut_processed:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
event.Skip()
|
||||
|
||||
|
||||
def EventSelectDown( self, event ):
|
||||
|
||||
self._tag_repositories.SelectDown()
|
||||
|
@ -5110,6 +5038,38 @@ class ManageTagsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
|
||||
|
||||
def ProcessApplicationCommand( self, command ):
|
||||
|
||||
command_processed = True
|
||||
|
||||
command_type = command.GetCommandType()
|
||||
data = command.GetData()
|
||||
|
||||
if command_type == CC.APPLICATION_COMMAND_TYPE_SIMPLE:
|
||||
|
||||
action = data
|
||||
|
||||
if action == 'manage_file_tags':
|
||||
|
||||
self._OKParent()
|
||||
|
||||
elif action == 'set_search_focus':
|
||||
|
||||
self._SetSearchFocus()
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
else:
|
||||
|
||||
command_processed = False
|
||||
|
||||
|
||||
return command_processed
|
||||
|
||||
|
||||
class _Panel( wx.Panel ):
|
||||
|
||||
def __init__( self, parent, file_service_key, tag_service_key, media, immediate_commit, canvas_key = None ):
|
||||
|
|
|
@ -328,7 +328,19 @@ class ReviewAllBandwidthPanel( ClientGUIScrolledPanels.ReviewPanel ):
|
|||
|
||||
#
|
||||
|
||||
self._history_time_delta_threshold.SetValue( 86400 * 7 )
|
||||
last_review_bandwidth_search_distance = self._controller.new_options.GetNoneableInteger( 'last_review_bandwidth_search_distance' )
|
||||
|
||||
if last_review_bandwidth_search_distance is None:
|
||||
|
||||
self._history_time_delta_threshold.SetValue( 86400 * 7 )
|
||||
self._history_time_delta_threshold.Disable()
|
||||
|
||||
self._history_time_delta_none.SetValue( True )
|
||||
|
||||
else:
|
||||
|
||||
self._history_time_delta_threshold.SetValue( last_review_bandwidth_search_distance )
|
||||
|
||||
|
||||
self._bandwidths.Sort( 0 )
|
||||
|
||||
|
@ -535,10 +547,16 @@ class ReviewAllBandwidthPanel( ClientGUIScrolledPanels.ReviewPanel ):
|
|||
|
||||
self._history_time_delta_threshold.Disable()
|
||||
|
||||
last_review_bandwidth_search_distance = None
|
||||
|
||||
else:
|
||||
|
||||
self._history_time_delta_threshold.Enable()
|
||||
|
||||
last_review_bandwidth_search_distance = self._history_time_delta_threshold.GetValue()
|
||||
|
||||
|
||||
self._controller.new_options.SetNoneableInteger( 'last_review_bandwidth_search_distance', last_review_bandwidth_search_distance )
|
||||
|
||||
self._update_job.MoveNextWorkTimeToNow()
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import ClientGUIMenus
|
|||
import ClientGUISerialisable
|
||||
import ClientGUIScrolledPanels
|
||||
import ClientGUITopLevelWindows
|
||||
import ClientImporting
|
||||
import ClientSerialisable
|
||||
import ClientThreading
|
||||
import HydrusConstants as HC
|
||||
|
@ -188,7 +189,7 @@ class EditSeedCachePanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
except Exception as e:
|
||||
|
||||
wx.MessageBox( unicode( e ) )
|
||||
wx.MessageBox( HydrusData.ToUnicode( e ) )
|
||||
|
||||
|
||||
|
||||
|
@ -409,13 +410,17 @@ class SeedCacheButton( ClientGUICommon.BetterBitmapButton ):
|
|||
|
||||
if sources[0].startswith( 'http' ):
|
||||
|
||||
seed_cache.AddURLs( sources )
|
||||
seed_type = ClientImporting.SEED_TYPE_URL
|
||||
|
||||
else:
|
||||
|
||||
seed_cache.AddPaths( sources )
|
||||
seed_type = ClientImporting.SEED_TYPE_HDD
|
||||
|
||||
|
||||
seeds = [ ClientImporting.Seed( seed_type, source ) for source in sources ]
|
||||
|
||||
seed_cache.AddSeeds( seeds )
|
||||
|
||||
|
||||
def _ExportToPng( self ):
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import ClientData
|
||||
import ClientGUICommon
|
||||
import HydrusConstants as HC
|
||||
import HydrusGlobals as HG
|
||||
|
@ -44,58 +45,88 @@ def IShouldCatchCharHook( evt_handler ):
|
|||
|
||||
class ShortcutsHandler( object ):
|
||||
|
||||
def __init__( self, parent, initial_shortcuts = None ):
|
||||
def __init__( self, parent, initial_shortcuts_names = None ):
|
||||
|
||||
if initial_shortcuts is None:
|
||||
if initial_shortcuts_names is None:
|
||||
|
||||
initial_shortcuts = []
|
||||
initial_shortcuts_names = []
|
||||
|
||||
|
||||
self._parent = parent
|
||||
self._all_shortcuts = {}
|
||||
|
||||
for shortcuts in initial_shortcuts:
|
||||
|
||||
self._all_shortcuts[ shortcuts.GetName() ] = shortcuts
|
||||
|
||||
self._shortcuts_names = list( initial_shortcuts_names )
|
||||
|
||||
self._parent.Bind( wx.EVT_CHAR_HOOK, self.EventCharHook )
|
||||
self._parent.Bind( wx.EVT_MOUSE_EVENTS, self.EventMouse )
|
||||
#self._parent.Bind( wx.EVT_MOUSE_EVENTS, self.EventMouse ) # let's not mess with this until we are doing something clever with it
|
||||
|
||||
|
||||
def _ProcessShortcut( self, shortcut ):
|
||||
|
||||
shortcut_processed = False
|
||||
|
||||
command = HG.client_controller.GetCommandFromShortcut( self._shortcuts_names, shortcut )
|
||||
|
||||
if command is not None:
|
||||
|
||||
command_processed = self._parent.ProcessApplicationCommand( command )
|
||||
|
||||
if command_processed:
|
||||
|
||||
shortcut_processed = True
|
||||
|
||||
|
||||
|
||||
return shortcut_processed
|
||||
|
||||
|
||||
def EventCharHook( self, event ):
|
||||
|
||||
# determine if the event came from a textctrl or a different tlp than my parent, in which case we want to skip it
|
||||
|
||||
# fetch the event details, convert to modifier and key
|
||||
# check with all my shortcuts for an action
|
||||
|
||||
# if action exists, post it to parent
|
||||
# else:
|
||||
if IShouldCatchCharHook( self._parent ):
|
||||
|
||||
shortcut = ClientData.ConvertKeyEventToShortcut( event )
|
||||
|
||||
if shortcut is not None:
|
||||
|
||||
shortcut_processed = self._ProcessShortcut( shortcut )
|
||||
|
||||
if shortcut_processed:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
event.Skip()
|
||||
|
||||
|
||||
def EventMouse( self, event ):
|
||||
|
||||
# fetch the event details, convert to modifier and key
|
||||
# check with all my shortcuts for an action
|
||||
shortcut = ClientData.ConvertMouseEventToShortcut( event )
|
||||
|
||||
# if action exists, post it to parent
|
||||
# else:
|
||||
if shortcut is not None:
|
||||
|
||||
shortcut_processed = self._ProcessShortcut( shortcut )
|
||||
|
||||
if shortcut_processed:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
event.Skip()
|
||||
|
||||
|
||||
def AddShortcuts( self, shortcuts ):
|
||||
def AddShortcuts( self, shortcuts_name ):
|
||||
|
||||
self._all_shortcuts[ shortcuts.GetName() ] = shortcuts
|
||||
if shortcuts_name not in self._shortcuts_names:
|
||||
|
||||
self._shortcuts_names.append( shortcuts_name )
|
||||
|
||||
|
||||
|
||||
def RemoveShortcuts( self, shortcuts_name ):
|
||||
|
||||
if shortcuts_name in self._all_shortcuts:
|
||||
if shortcuts_name in self._shortcuts_names:
|
||||
|
||||
del self._all_shortcuts[ shortcuts_name ]
|
||||
self._shortcuts_names.remove( shortcuts_name )
|
||||
|
||||
|
||||
|
|
|
@ -555,7 +555,7 @@ class DialogNullipotentVetoable( DialogThatTakesScrollablePanelClose ):
|
|||
|
||||
except HydrusExceptions.VetoException as e:
|
||||
|
||||
message = unicode( e )
|
||||
message = HydrusData.ToUnicode( e )
|
||||
|
||||
if len( message ) > 0:
|
||||
|
||||
|
@ -612,7 +612,7 @@ class DialogEdit( DialogThatTakesScrollablePanelApplyCancel ):
|
|||
|
||||
except HydrusExceptions.VetoException as e:
|
||||
|
||||
message = unicode( e )
|
||||
message = HydrusData.ToUnicode( e )
|
||||
|
||||
if len( message ) > 0:
|
||||
|
||||
|
@ -642,7 +642,7 @@ class DialogManage( DialogThatTakesScrollablePanelApplyCancel ):
|
|||
|
||||
except HydrusExceptions.VetoException as e:
|
||||
|
||||
message = unicode( e )
|
||||
message = HydrusData.ToUnicode( e )
|
||||
|
||||
if len( message ) > 0:
|
||||
|
||||
|
|
|
@ -675,6 +675,8 @@ class NetworkEngine( object ):
|
|||
self._jobs_ready_to_start = []
|
||||
self._jobs_downloading = []
|
||||
|
||||
self._pause_all_new_network_traffic = self.controller.new_options.GetBoolean( 'pause_all_new_network_traffic' )
|
||||
|
||||
self._is_running = False
|
||||
self._is_shutdown = False
|
||||
self._local_shutdown = False
|
||||
|
@ -862,11 +864,20 @@ class NetworkEngine( object ):
|
|||
|
||||
elif len( self._jobs_downloading ) < self.MAX_JOBS:
|
||||
|
||||
self.controller.CallToThread( job.Start )
|
||||
|
||||
self._jobs_downloading.append( job )
|
||||
|
||||
return False
|
||||
if self._pause_all_new_network_traffic:
|
||||
|
||||
job.SetStatus( u'all new network traffic is paused\u2026' )
|
||||
|
||||
return True
|
||||
|
||||
else:
|
||||
|
||||
self.controller.CallToThread( job.Start )
|
||||
|
||||
self._jobs_downloading.append( job )
|
||||
|
||||
return False
|
||||
|
||||
|
||||
else:
|
||||
|
||||
|
@ -926,6 +937,13 @@ class NetworkEngine( object ):
|
|||
self._is_shutdown = True
|
||||
|
||||
|
||||
def PausePlayNewJobs( self ):
|
||||
|
||||
self._pause_all_new_network_traffic = not self._pause_all_new_network_traffic
|
||||
|
||||
self.controller.new_options.SetBoolean( 'pause_all_new_network_traffic', self._pause_all_new_network_traffic )
|
||||
|
||||
|
||||
def Shutdown( self ):
|
||||
|
||||
self._local_shutdown = True
|
||||
|
|
|
@ -80,6 +80,16 @@ def ConvertURLIntoDomain( url ):
|
|||
|
||||
parser_result = urlparse.urlparse( url )
|
||||
|
||||
if parser_result.scheme == '':
|
||||
|
||||
raise HydrusExceptions.URLMatchException( 'URL "' + url + '" was not recognised--did you forget the http or https?' )
|
||||
|
||||
|
||||
if parser_result.netloc == '':
|
||||
|
||||
raise HydrusExceptions.URLMatchException( 'URL "' + url + '" was not recognised--is it missing a domain?' )
|
||||
|
||||
|
||||
domain = HydrusData.ToByteString( parser_result.netloc )
|
||||
|
||||
return domain
|
||||
|
@ -1258,7 +1268,7 @@ class URLMatch( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
except HydrusExceptions.StringMatchException as e:
|
||||
|
||||
raise HydrusExceptions.URLMatchException( unicode( e ) )
|
||||
raise HydrusExceptions.URLMatchException( HydrusData.ToUnicode( e ) )
|
||||
|
||||
|
||||
|
||||
|
@ -1286,7 +1296,7 @@ class URLMatch( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
except HydrusExceptions.StringMatchException as e:
|
||||
|
||||
raise HydrusExceptions.URLMatchException( unicode( e ) )
|
||||
raise HydrusExceptions.URLMatchException( HydrusData.ToUnicode( e ) )
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -770,7 +770,7 @@ class LoginStep( object ):
|
|||
|
||||
except HydrusExceptions.StringMatchException as e:
|
||||
|
||||
reason = unicode( e )
|
||||
reason = HydrusData.ToUnicode( e )
|
||||
|
||||
raise HydrusExceptions.ValidationException( 'The credential \'' + pretty_name + '\' did not match requirements:' + os.linesep + reason )
|
||||
|
||||
|
@ -829,7 +829,7 @@ class LoginStep( object ):
|
|||
|
||||
except HydrusExceptions.VetoException as e:
|
||||
|
||||
raise HydrusExceptions.ValidationException( unicode( e ) )
|
||||
raise HydrusExceptions.ValidationException( HydrusData.ToUnicode( e ) )
|
||||
|
||||
|
||||
# if content type is a temp variable:
|
||||
|
|
|
@ -1514,7 +1514,7 @@ class PageParser( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
except HydrusExceptions.StringConvertException as e:
|
||||
|
||||
raise HydrusExceptions.ParseException( unicode( e ) )
|
||||
raise HydrusExceptions.ParseException( HydrusData.ToUnicode( e ) )
|
||||
|
||||
|
||||
#
|
||||
|
|
|
@ -49,7 +49,7 @@ options = {}
|
|||
# Misc
|
||||
|
||||
NETWORK_VERSION = 18
|
||||
SOFTWARE_VERSION = 297
|
||||
SOFTWARE_VERSION = 298
|
||||
|
||||
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
||||
|
||||
|
|
|
@ -78,7 +78,15 @@ def ConvertFloatToPercentage( f ):
|
|||
|
||||
def ConvertIntToBytes( size ):
|
||||
|
||||
if size is None: return 'unknown size'
|
||||
if size is None:
|
||||
|
||||
return 'unknown size'
|
||||
|
||||
|
||||
if size < 1024:
|
||||
|
||||
return ConvertIntToPrettyString( size ) + 'B'
|
||||
|
||||
|
||||
suffixes = ( '', 'K', 'M', 'G', 'T', 'P' )
|
||||
|
||||
|
@ -86,16 +94,21 @@ def ConvertIntToBytes( size ):
|
|||
|
||||
size = float( size )
|
||||
|
||||
while size > 1024.0:
|
||||
while size >= 1024.0:
|
||||
|
||||
size = size / 1024.0
|
||||
|
||||
suffix_index += 1
|
||||
|
||||
|
||||
if size < 10.0: return '%.1f' % size + suffixes[ suffix_index ] + 'B'
|
||||
|
||||
return '%.0f' % size + suffixes[ suffix_index ] + 'B'
|
||||
if size < 10.0:
|
||||
|
||||
return '%.1f' % size + suffixes[ suffix_index ] + 'B'
|
||||
|
||||
else:
|
||||
|
||||
return '%.0f' % size + suffixes[ suffix_index ] + 'B'
|
||||
|
||||
|
||||
def ConvertIntToFirst( n ):
|
||||
|
||||
|
|
|
@ -28,7 +28,10 @@ def GetPDFNumWords( path ):
|
|||
return pdf_object.numPages * 350
|
||||
|
||||
|
||||
except: num_words = 0
|
||||
except:
|
||||
|
||||
num_words = 0
|
||||
|
||||
|
||||
return num_words
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ view_shutdown = False
|
|||
model_shutdown = False
|
||||
|
||||
import_folders_running = False
|
||||
export_folders_running = False
|
||||
subscriptions_running = False
|
||||
|
||||
callto_report_mode = False
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import collections
|
||||
import ClientConstants as CC
|
||||
import ClientData
|
||||
import HydrusConstants as HC
|
||||
import HydrusGlobals as HG
|
||||
import HydrusTags
|
||||
|
@ -35,6 +36,8 @@ class MockController( object ):
|
|||
|
||||
self.model_is_shutdown = False
|
||||
|
||||
self.new_options = ClientData.ClientOptions()
|
||||
|
||||
|
||||
def CallToThread( self, callable, *args, **kwargs ):
|
||||
|
||||
|
|
|
@ -418,7 +418,7 @@ class TestBandwidthTracker( unittest.TestCase ):
|
|||
|
||||
bandwidth_tracker = HydrusNetworking.BandwidthTracker()
|
||||
|
||||
self.assertEqual( bandwidth_tracker.GetCurrentMonthSummary(), 'used 0.0B in 0 requests this month' )
|
||||
self.assertEqual( bandwidth_tracker.GetCurrentMonthSummary(), 'used 0B in 0 requests this month' )
|
||||
|
||||
now = HydrusData.GetNow()
|
||||
|
||||
|
@ -447,7 +447,7 @@ class TestBandwidthTracker( unittest.TestCase ):
|
|||
bandwidth_tracker.ReportDataUsed( 1024 )
|
||||
bandwidth_tracker.ReportRequestUsed()
|
||||
|
||||
self.assertEqual( bandwidth_tracker.GetCurrentMonthSummary(), 'used 1024B in 1 requests this month' )
|
||||
self.assertEqual( bandwidth_tracker.GetCurrentMonthSummary(), 'used 1.0KB in 1 requests this month' )
|
||||
|
||||
self.assertEqual( bandwidth_tracker.GetUsage( HC.BANDWIDTH_TYPE_DATA, 0 ), 0 )
|
||||
self.assertEqual( bandwidth_tracker.GetUsage( HC.BANDWIDTH_TYPE_REQUESTS, 0 ), 0 )
|
||||
|
|
Loading…
Reference in New Issue