hydrus/include/ClientGUIFileSeedCache.py

762 lines
27 KiB
Python
Raw Normal View History

2017-07-27 00:47:13 +00:00
import ClientConstants as CC
import ClientGUICommon
import ClientGUIDialogs
2017-08-02 21:32:54 +00:00
import ClientGUIListCtrl
2017-07-27 00:47:13 +00:00
import ClientGUIMenus
2017-12-20 22:55:48 +00:00
import ClientGUISerialisable
2017-07-27 00:47:13 +00:00
import ClientGUIScrolledPanels
import ClientGUITopLevelWindows
2018-06-27 19:27:05 +00:00
import ClientImportFileSeeds
2018-05-09 20:23:00 +00:00
import ClientPaths
2017-12-20 22:55:48 +00:00
import ClientSerialisable
2018-01-03 22:37:30 +00:00
import ClientThreading
2017-07-27 00:47:13 +00:00
import HydrusConstants as HC
import HydrusData
2018-09-19 21:54:51 +00:00
import HydrusExceptions
2017-07-27 00:47:13 +00:00
import HydrusGlobals as HG
2017-12-13 22:33:07 +00:00
import HydrusPaths
2017-12-20 22:55:48 +00:00
import HydrusText
2017-07-27 00:47:13 +00:00
import os
import wx
2018-06-27 19:27:05 +00:00
class EditFileSeedCachePanel( ClientGUIScrolledPanels.EditPanel ):
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
def __init__( self, parent, controller, file_seed_cache ):
2017-07-27 00:47:13 +00:00
ClientGUIScrolledPanels.EditPanel.__init__( self, parent )
self._controller = controller
2018-06-27 19:27:05 +00:00
self._file_seed_cache = file_seed_cache
2017-07-27 00:47:13 +00:00
self._text = ClientGUICommon.BetterStaticText( self, 'initialising' )
2018-06-27 19:27:05 +00:00
# add index control row here, hide it if needed and hook into showing/hiding and postsizechangedevent on file_seed add/remove
2017-07-27 00:47:13 +00:00
2017-09-27 21:52:54 +00:00
columns = [ ( '#', 3 ), ( 'source', -1 ), ( 'status', 12 ), ( 'added', 23 ), ( 'last modified', 23 ), ( 'source time', 23 ), ( 'note', 20 ) ]
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
self._list_ctrl = ClientGUIListCtrl.BetterListCtrl( self, 'file_seed_cache', 30, 30, columns, self._ConvertFileSeedToListCtrlTuples, delete_key_callback = self._DeleteSelected )
2017-07-27 00:47:13 +00:00
#
2018-06-27 19:27:05 +00:00
self._list_ctrl.AddDatas( self._file_seed_cache.GetFileSeeds() )
2017-07-27 00:47:13 +00:00
2017-08-30 20:27:47 +00:00
self._list_ctrl.Sort( 0 )
2017-07-27 00:47:13 +00:00
#
vbox = wx.BoxSizer( wx.VERTICAL )
2018-01-03 22:37:30 +00:00
vbox.Add( self._text, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.Add( self._list_ctrl, CC.FLAGS_EXPAND_BOTH_WAYS )
2017-07-27 00:47:13 +00:00
self.SetSizer( vbox )
2018-09-19 21:54:51 +00:00
self._list_ctrl.AddMenuCallable( self._GetListCtrlMenu )
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
self._controller.sub( self, 'NotifyFileSeedsUpdated', 'file_seed_cache_file_seeds_updated' )
2017-07-27 00:47:13 +00:00
wx.CallAfter( self._UpdateText )
2018-06-27 19:27:05 +00:00
def _ConvertFileSeedToListCtrlTuples( self, file_seed ):
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
try:
file_seed_index = self._file_seed_cache.GetFileSeedIndex( file_seed )
except:
file_seed_index = '--'
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
file_seed_data = file_seed.file_seed_data
status = file_seed.status
added = file_seed.created
modified = file_seed.modified
source_time = file_seed.source_time
note = file_seed.note
2017-07-27 00:47:13 +00:00
2018-07-04 20:48:28 +00:00
pretty_file_seed_index = HydrusData.ToHumanInt( file_seed_index )
2018-06-27 19:27:05 +00:00
pretty_file_seed_data = HydrusData.ToUnicode( file_seed_data )
2017-07-27 00:47:13 +00:00
pretty_status = CC.status_string_lookup[ status ]
2018-07-04 20:48:28 +00:00
pretty_added = HydrusData.TimestampToPrettyTimeDelta( added )
pretty_modified = HydrusData.TimestampToPrettyTimeDelta( modified )
2017-09-27 21:52:54 +00:00
2017-11-29 21:48:23 +00:00
if source_time is None:
2017-09-27 21:52:54 +00:00
pretty_source_time = 'unknown'
else:
2018-07-04 20:48:28 +00:00
pretty_source_time = HydrusData.TimestampToPrettyTimeDelta( source_time )
2017-09-27 21:52:54 +00:00
2017-07-27 00:47:13 +00:00
pretty_note = note.split( os.linesep )[0]
2018-06-27 19:27:05 +00:00
display_tuple = ( pretty_file_seed_index, pretty_file_seed_data, pretty_status, pretty_added, pretty_modified, pretty_source_time, pretty_note )
sort_tuple = ( file_seed_index, file_seed_data, status, added, modified, source_time, note )
2017-07-27 00:47:13 +00:00
return ( display_tuple, sort_tuple )
def _CopySelectedNotes( self ):
notes = []
2018-06-27 19:27:05 +00:00
for file_seed in self._list_ctrl.GetData( only_selected = True ):
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
note = file_seed.note
2017-07-27 00:47:13 +00:00
if note != '':
notes.append( note )
if len( notes ) > 0:
separator = os.linesep * 2
text = separator.join( notes )
HG.client_controller.pub( 'clipboard', 'text', text )
2018-06-27 19:27:05 +00:00
def _CopySelectedFileSeedData( self ):
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
file_seeds = self._list_ctrl.GetData( only_selected = True )
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
if len( file_seeds ) > 0:
2017-07-27 00:47:13 +00:00
separator = os.linesep * 2
2018-06-27 19:27:05 +00:00
text = separator.join( ( file_seed.file_seed_data for file_seed in file_seeds ) )
2017-07-27 00:47:13 +00:00
HG.client_controller.pub( 'clipboard', 'text', text )
def _DeleteSelected( self ):
2018-06-27 19:27:05 +00:00
file_seeds_to_delete = self._list_ctrl.GetData( only_selected = True )
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
if len( file_seeds_to_delete ) > 0:
2017-07-27 00:47:13 +00:00
message = 'Are you sure you want to delete all the selected entries?'
with ClientGUIDialogs.DialogYesNo( self, message ) as dlg:
if dlg.ShowModal() == wx.ID_YES:
2018-06-27 19:27:05 +00:00
self._file_seed_cache.RemoveFileSeeds( file_seeds_to_delete )
2017-07-27 00:47:13 +00:00
2018-09-19 21:54:51 +00:00
def _GetListCtrlMenu( self ):
selected_file_seeds = self._list_ctrl.GetData( only_selected = True )
if len( selected_file_seeds ) == 0:
raise HydrusExceptions.DataMissing()
menu = wx.Menu()
can_show_files_in_new_page = True in ( file_seed.HasHash() for file_seed in selected_file_seeds )
if can_show_files_in_new_page:
ClientGUIMenus.AppendMenuItem( self, menu, 'open selected import files in a new page', 'Show all the known selected files in a new thumbnail page. This is complicated, so cannot always be guaranteed, even if the import says \'success\'.', self._ShowSelectionInNewPage )
ClientGUIMenus.AppendSeparator( menu )
ClientGUIMenus.AppendMenuItem( self, menu, 'copy sources', 'Copy all the selected sources to clipboard.', self._CopySelectedFileSeedData )
ClientGUIMenus.AppendMenuItem( self, menu, 'copy notes', 'Copy all the selected notes to clipboard.', self._CopySelectedNotes )
ClientGUIMenus.AppendSeparator( menu )
ClientGUIMenus.AppendMenuItem( self, menu, 'open sources', 'Open all the selected sources in your file explorer or web browser.', self._OpenSelectedFileSeedData )
ClientGUIMenus.AppendSeparator( menu )
ClientGUIMenus.AppendMenuItem( self, menu, 'try again', 'Reset the progress of all the selected imports.', HydrusData.Call( self._SetSelected, CC.STATUS_UNKNOWN ) )
ClientGUIMenus.AppendMenuItem( self, menu, 'skip', 'Skip all the selected imports.', HydrusData.Call( self._SetSelected, CC.STATUS_SKIPPED ) )
ClientGUIMenus.AppendMenuItem( self, menu, 'delete from list', 'Remove all the selected imports.', self._DeleteSelected )
return menu
2018-06-27 19:27:05 +00:00
def _OpenSelectedFileSeedData( self ):
2017-12-13 22:33:07 +00:00
2018-06-27 19:27:05 +00:00
file_seeds = self._list_ctrl.GetData( only_selected = True )
2017-12-13 22:33:07 +00:00
2018-06-27 19:27:05 +00:00
if len( file_seeds ) > 0:
2017-12-13 22:33:07 +00:00
2018-06-27 19:27:05 +00:00
if len( file_seeds ) > 10:
2017-12-13 22:33:07 +00:00
message = 'You have many objects selected--are you sure you want to open them all?'
with ClientGUIDialogs.DialogYesNo( self, message ) as dlg:
if dlg.ShowModal() != wx.ID_YES:
return
2018-06-27 19:27:05 +00:00
if file_seeds[0].file_seed_data.startswith( 'http' ):
2017-12-13 22:33:07 +00:00
2018-06-27 19:27:05 +00:00
for file_seed in file_seeds:
2017-12-13 22:33:07 +00:00
2018-06-27 19:27:05 +00:00
ClientPaths.LaunchURLInWebBrowser( file_seed.file_seed_data )
2017-12-13 22:33:07 +00:00
else:
try:
2018-06-27 19:27:05 +00:00
for file_seed in file_seeds:
2017-12-13 22:33:07 +00:00
2018-06-27 19:27:05 +00:00
HydrusPaths.OpenFileLocation( file_seed.file_seed_data )
2017-12-13 22:33:07 +00:00
except Exception as e:
2018-03-14 21:01:02 +00:00
wx.MessageBox( HydrusData.ToUnicode( e ) )
2017-12-13 22:33:07 +00:00
2017-07-27 00:47:13 +00:00
def _SetSelected( self, status_to_set ):
2018-06-27 19:27:05 +00:00
file_seeds = self._list_ctrl.GetData( only_selected = True )
2017-11-29 21:48:23 +00:00
2018-10-03 21:00:15 +00:00
if status_to_set == CC.STATUS_UNKNOWN:
2018-10-24 21:34:02 +00:00
deleted_and_clearable_file_seeds = [ file_seed for file_seed in file_seeds if file_seed.IsDeleted() and file_seed.HasHash() ]
2018-10-03 21:00:15 +00:00
2018-10-24 21:34:02 +00:00
if len( deleted_and_clearable_file_seeds ) > 0:
2018-10-03 21:00:15 +00:00
message = 'One or more of these files did not import due to being previously deleted. They will likely fail again unless you erase those deletion records. Would you like to do this now?'
with ClientGUIDialogs.DialogYesNo( self, message ) as dlg:
if dlg.ShowModal() == wx.ID_YES:
2018-10-24 21:34:02 +00:00
deletee_hashes = { file_seed.GetHash() for file_seed in deleted_and_clearable_file_seeds }
2018-10-03 21:00:15 +00:00
content_update_erase_record = HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ADVANCED, ( 'delete_deleted', deletee_hashes ) )
content_update_undelete_from_trash = HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_UNDELETE, deletee_hashes )
service_keys_to_content_updates = { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ content_update_erase_record, content_update_undelete_from_trash ] }
HG.client_controller.WriteSynchronous( 'content_updates', service_keys_to_content_updates )
2018-06-27 19:27:05 +00:00
for file_seed in file_seeds:
2017-11-29 21:48:23 +00:00
2018-06-27 19:27:05 +00:00
file_seed.SetStatus( status_to_set )
2017-11-29 21:48:23 +00:00
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
self._file_seed_cache.NotifyFileSeedsUpdated( file_seeds )
2017-07-27 00:47:13 +00:00
2018-05-09 20:23:00 +00:00
def _ShowSelectionInNewPage( self ):
hashes = []
2018-06-27 19:27:05 +00:00
for file_seed in self._list_ctrl.GetData( only_selected = True ):
2018-05-09 20:23:00 +00:00
2018-06-27 19:27:05 +00:00
if file_seed.HasHash():
2018-05-09 20:23:00 +00:00
2018-06-27 19:27:05 +00:00
hashes.append( file_seed.GetHash() )
2018-05-09 20:23:00 +00:00
if len( hashes ) > 0:
HG.client_controller.pub( 'new_page_query', CC.LOCAL_FILE_SERVICE_KEY, initial_hashes = hashes )
2018-06-27 19:27:05 +00:00
def _UpdateListCtrl( self, file_seeds ):
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
file_seeds_to_add = []
file_seeds_to_update = []
file_seeds_to_delete = []
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
for file_seed in file_seeds:
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
if self._file_seed_cache.HasFileSeed( file_seed ):
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
if self._list_ctrl.HasData( file_seed ):
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
file_seeds_to_update.append( file_seed )
2017-07-27 00:47:13 +00:00
else:
2018-06-27 19:27:05 +00:00
file_seeds_to_add.append( file_seed )
2017-07-27 00:47:13 +00:00
else:
2018-06-27 19:27:05 +00:00
if self._list_ctrl.HasData( file_seed ):
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
file_seeds_to_delete.append( file_seed )
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
self._list_ctrl.DeleteDatas( file_seeds_to_delete )
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
if len( file_seeds_to_add ) > 0:
2018-06-20 20:20:22 +00:00
2018-06-27 19:27:05 +00:00
self._list_ctrl.AddDatas( file_seeds_to_add )
2018-06-20 20:20:22 +00:00
2018-06-27 19:27:05 +00:00
# if file_seeds are inserted, then all subsequent indices need to be shuffled up, hence just update all here
2018-06-20 20:20:22 +00:00
self._list_ctrl.UpdateDatas()
else:
2018-06-27 19:27:05 +00:00
self._list_ctrl.UpdateDatas( file_seeds_to_update )
2018-06-20 20:20:22 +00:00
2017-07-27 00:47:13 +00:00
def _UpdateText( self ):
2018-07-04 20:48:28 +00:00
( status, simple_status, ( total_processed, total ) ) = self._file_seed_cache.GetStatus()
2017-07-27 00:47:13 +00:00
self._text.SetLabelText( status )
self.Layout()
def GetValue( self ):
2018-06-27 19:27:05 +00:00
return self._file_seed_cache
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
def NotifyFileSeedsUpdated( self, file_seed_cache_key, file_seeds ):
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
if file_seed_cache_key == self._file_seed_cache.GetFileSeedCacheKey():
2017-07-27 00:47:13 +00:00
self._UpdateText()
2018-06-27 19:27:05 +00:00
self._UpdateListCtrl( file_seeds )
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
class FileSeedCacheButton( ClientGUICommon.BetterBitmapButton ):
2017-10-18 19:41:25 +00:00
2018-06-27 19:27:05 +00:00
def __init__( self, parent, controller, file_seed_cache_get_callable, file_seed_cache_set_callable = None ):
2017-10-18 19:41:25 +00:00
2018-06-27 19:27:05 +00:00
ClientGUICommon.BetterBitmapButton.__init__( self, parent, CC.GlobalBMPs.listctrl, self._ShowFileSeedCacheFrame )
2017-10-18 19:41:25 +00:00
self._controller = controller
2018-06-27 19:27:05 +00:00
self._file_seed_cache_get_callable = file_seed_cache_get_callable
self._file_seed_cache_set_callable = file_seed_cache_set_callable
2017-10-18 19:41:25 +00:00
2018-01-03 22:37:30 +00:00
self.SetToolTip( 'open detailed file import status--right-click for quick actions, if applicable' )
2017-10-18 19:41:25 +00:00
self.Bind( wx.EVT_RIGHT_DOWN, self.EventShowMenu )
2018-06-27 19:27:05 +00:00
def _ClearFileSeeds( self, statuses_to_remove ):
2017-10-18 19:41:25 +00:00
2018-05-09 20:23:00 +00:00
message = 'Are you sure you want to delete all the ' + '/'.join( ( CC.status_string_lookup[ status ] for status in statuses_to_remove ) ) + ' file import items? This is useful for cleaning up and de-laggifying a very large list, but be careful you aren\'t removing something you would want to revisit or what watcher/subscription may be using for future check time calculations.'
2017-10-18 19:41:25 +00:00
with ClientGUIDialogs.DialogYesNo( self, message ) as dlg:
if dlg.ShowModal() == wx.ID_YES:
2018-06-27 19:27:05 +00:00
file_seed_cache = self._file_seed_cache_get_callable()
2017-10-18 19:41:25 +00:00
2018-06-27 19:27:05 +00:00
file_seed_cache.RemoveFileSeedsByStatus( statuses_to_remove )
2018-01-10 22:41:51 +00:00
2017-12-20 22:55:48 +00:00
def _GetExportableSourcesString( self ):
2018-06-27 19:27:05 +00:00
file_seed_cache = self._file_seed_cache_get_callable()
2017-12-20 22:55:48 +00:00
2018-06-27 19:27:05 +00:00
file_seeds = file_seed_cache.GetFileSeeds()
2017-12-20 22:55:48 +00:00
2018-06-27 19:27:05 +00:00
sources = [ file_seed.file_seed_data for file_seed in file_seeds ]
2017-12-20 22:55:48 +00:00
return os.linesep.join( sources )
def _GetSourcesFromSourcesString( self, sources_string ):
sources_string = HydrusData.ToUnicode( sources_string )
sources = HydrusText.DeserialiseNewlinedTexts( sources_string )
return sources
def _ImportFromClipboard( self ):
raw_text = HG.client_controller.GetClipboardText()
sources = self._GetSourcesFromSourcesString( raw_text )
try:
self._ImportSources( sources )
except:
wx.MessageBox( 'Could not import!' )
raise
def _ImportFromPng( self ):
with wx.FileDialog( self, 'select the png with the sources', wildcard = 'PNG (*.png)|*.png' ) as dlg:
if dlg.ShowModal() == wx.ID_OK:
path = HydrusData.ToUnicode( dlg.GetPath() )
payload = ClientSerialisable.LoadFromPng( path )
try:
sources = self._GetSourcesFromSourcesString( payload )
self._ImportSources( sources )
except:
wx.MessageBox( 'Could not import!' )
raise
def _ImportSources( self, sources ):
2018-06-27 19:27:05 +00:00
file_seed_cache = self._file_seed_cache_get_callable()
2017-12-20 22:55:48 +00:00
if sources[0].startswith( 'http' ):
2018-06-27 19:27:05 +00:00
file_seed_type = ClientImportFileSeeds.FILE_SEED_TYPE_URL
2017-12-20 22:55:48 +00:00
else:
2018-06-27 19:27:05 +00:00
file_seed_type = ClientImportFileSeeds.FILE_SEED_TYPE_HDD
2017-12-20 22:55:48 +00:00
2018-06-27 19:27:05 +00:00
file_seeds = [ ClientImportFileSeeds.FileSeed( file_seed_type, source ) for source in sources ]
2018-03-14 21:01:02 +00:00
2018-06-27 19:27:05 +00:00
file_seed_cache.AddFileSeeds( file_seeds )
2018-03-14 21:01:02 +00:00
2017-12-20 22:55:48 +00:00
def _ExportToPng( self ):
payload = self._GetExportableSourcesString()
with ClientGUITopLevelWindows.DialogNullipotent( self, 'export to png' ) as dlg:
panel = ClientGUISerialisable.PngExportPanel( dlg, payload )
dlg.SetPanel( panel )
dlg.ShowModal()
def _ExportToClipboard( self ):
payload = self._GetExportableSourcesString()
HG.client_controller.pub( 'clipboard', 'text', payload )
2018-04-25 22:07:52 +00:00
def _RetryErrors( self ):
2017-10-18 19:41:25 +00:00
2018-04-25 22:07:52 +00:00
message = 'Are you sure you want to retry all the files that encountered errors?'
2017-10-18 19:41:25 +00:00
with ClientGUIDialogs.DialogYesNo( self, message ) as dlg:
if dlg.ShowModal() == wx.ID_YES:
2018-06-27 19:27:05 +00:00
file_seed_cache = self._file_seed_cache_get_callable()
2017-10-18 19:41:25 +00:00
2018-06-27 19:27:05 +00:00
file_seed_cache.RetryFailures()
2017-10-18 19:41:25 +00:00
2018-07-11 20:23:51 +00:00
def _RetryIgnored( self ):
message = 'Are you sure you want to retry all the files that were ignored/vetoed?'
with ClientGUIDialogs.DialogYesNo( self, message ) as dlg:
if dlg.ShowModal() == wx.ID_YES:
file_seed_cache = self._file_seed_cache_get_callable()
file_seed_cache.RetryIgnored()
2018-06-27 19:27:05 +00:00
def _ShowFileSeedCacheFrame( self ):
2017-10-18 19:41:25 +00:00
2018-06-27 19:27:05 +00:00
file_seed_cache = self._file_seed_cache_get_callable()
2017-10-18 19:41:25 +00:00
tlp = ClientGUICommon.GetTLP( self )
if isinstance( tlp, wx.Dialog ):
2018-06-27 19:27:05 +00:00
if self._file_seed_cache_set_callable is None: # throw up a dialog that edits the file_seed cache in place
2017-10-18 19:41:25 +00:00
with ClientGUITopLevelWindows.DialogNullipotent( self, 'file import status' ) as dlg:
2018-06-27 19:27:05 +00:00
panel = EditFileSeedCachePanel( dlg, self._controller, file_seed_cache )
2017-10-18 19:41:25 +00:00
dlg.SetPanel( panel )
dlg.ShowModal()
2018-06-27 19:27:05 +00:00
else: # throw up a dialog that edits the file_seed cache but can be cancelled
2017-10-18 19:41:25 +00:00
2018-06-27 19:27:05 +00:00
dupe_file_seed_cache = file_seed_cache.Duplicate()
2017-10-18 19:41:25 +00:00
with ClientGUITopLevelWindows.DialogEdit( self, 'file import status' ) as dlg:
2018-06-27 19:27:05 +00:00
panel = EditFileSeedCachePanel( dlg, self._controller, dupe_file_seed_cache )
2017-10-18 19:41:25 +00:00
dlg.SetPanel( panel )
if dlg.ShowModal() == wx.ID_OK:
2018-06-27 19:27:05 +00:00
self._file_seed_cache_set_callable( dupe_file_seed_cache )
2017-10-18 19:41:25 +00:00
2018-06-27 19:27:05 +00:00
else: # throw up a frame that edits the file_seed cache in place
2017-10-18 19:41:25 +00:00
title = 'file import status'
frame_key = 'file_import_status'
frame = ClientGUITopLevelWindows.FrameThatTakesScrollablePanel( self, title, frame_key )
2018-06-27 19:27:05 +00:00
panel = EditFileSeedCachePanel( frame, self._controller, file_seed_cache )
2017-10-18 19:41:25 +00:00
frame.SetPanel( panel )
def EventShowMenu( self, event ):
2017-12-20 22:55:48 +00:00
menu = wx.Menu()
2017-10-18 19:41:25 +00:00
2018-06-27 19:27:05 +00:00
file_seed_cache = self._file_seed_cache_get_callable()
2017-10-18 19:41:25 +00:00
2018-06-27 19:27:05 +00:00
num_file_seeds = len( file_seed_cache )
num_successful = file_seed_cache.GetFileSeedCount( CC.STATUS_SUCCESSFUL_AND_NEW ) + file_seed_cache.GetFileSeedCount( CC.STATUS_SUCCESSFUL_BUT_REDUNDANT )
2018-07-04 20:48:28 +00:00
num_vetoed = file_seed_cache.GetFileSeedCount( CC.STATUS_VETOED )
num_deleted_and_vetoed = file_seed_cache.GetFileSeedCount( CC.STATUS_DELETED ) + num_vetoed
2018-06-27 19:27:05 +00:00
num_errors = file_seed_cache.GetFileSeedCount( CC.STATUS_ERROR )
num_skipped = file_seed_cache.GetFileSeedCount( CC.STATUS_SKIPPED )
2017-10-18 19:41:25 +00:00
2018-04-25 22:07:52 +00:00
if num_errors > 0:
2017-10-18 19:41:25 +00:00
2018-07-04 20:48:28 +00:00
ClientGUIMenus.AppendMenuItem( self, menu, 'retry ' + HydrusData.ToHumanInt( num_errors ) + ' error failures', 'Tell this cache to reattempt all its error failures.', self._RetryErrors )
2017-10-18 19:41:25 +00:00
2018-07-04 20:48:28 +00:00
if num_vetoed > 0:
2018-07-18 21:07:15 +00:00
ClientGUIMenus.AppendMenuItem( self, menu, 'retry ' + HydrusData.ToHumanInt( num_vetoed ) + ' ignored', 'Tell this cache to reattempt all its ignored/vetoed results.', self._RetryIgnored )
2018-07-04 20:48:28 +00:00
ClientGUIMenus.AppendSeparator( menu )
2018-01-10 22:41:51 +00:00
if num_successful > 0:
2018-05-09 20:23:00 +00:00
num_deletees = num_successful
2018-07-04 20:48:28 +00:00
ClientGUIMenus.AppendMenuItem( self, menu, 'delete ' + HydrusData.ToHumanInt( num_deletees ) + ' successful file import items from the queue', 'Tell this cache to clear out successful files, reducing the size of the queue.', self._ClearFileSeeds, ( CC.STATUS_SUCCESSFUL_AND_NEW, CC.STATUS_SUCCESSFUL_BUT_REDUNDANT ) )
2018-01-10 22:41:51 +00:00
2018-05-09 20:23:00 +00:00
if num_deleted_and_vetoed > 0:
num_deletees = num_deleted_and_vetoed
2018-07-04 20:48:28 +00:00
ClientGUIMenus.AppendMenuItem( self, menu, 'delete ' + HydrusData.ToHumanInt( num_deletees ) + ' deleted/ignored file import items from the queue', 'Tell this cache to clear out deleted and ignored files, reducing the size of the queue.', self._ClearFileSeeds, ( CC.STATUS_DELETED, CC.STATUS_VETOED ) )
2018-05-09 20:23:00 +00:00
2017-10-18 19:41:25 +00:00
2018-05-09 20:23:00 +00:00
if num_errors + num_skipped > 0:
num_deletees = num_errors + num_skipped
2017-10-18 19:41:25 +00:00
2018-07-04 20:48:28 +00:00
ClientGUIMenus.AppendMenuItem( self, menu, 'delete ' + HydrusData.ToHumanInt( num_deletees ) + ' error/skipped file import items from the queue', 'Tell this cache to clear out errored and skipped files, reducing the size of the queue.', self._ClearFileSeeds, ( CC.STATUS_ERROR, CC.STATUS_SKIPPED ) )
2017-10-18 19:41:25 +00:00
2017-12-20 22:55:48 +00:00
ClientGUIMenus.AppendSeparator( menu )
2018-06-27 19:27:05 +00:00
if len( file_seed_cache ) > 0:
2017-10-18 19:41:25 +00:00
2017-12-20 22:55:48 +00:00
submenu = wx.Menu()
2017-10-18 19:41:25 +00:00
2017-12-20 22:55:48 +00:00
ClientGUIMenus.AppendMenuItem( self, submenu, 'to clipboard', 'Copy all the sources in this list to the clipboard.', self._ExportToClipboard )
ClientGUIMenus.AppendMenuItem( self, submenu, 'to png', 'Export all the sources in this list to a png file.', self._ExportToPng )
2017-10-18 19:41:25 +00:00
2017-12-20 22:55:48 +00:00
ClientGUIMenus.AppendMenu( menu, submenu, 'export all sources' )
2017-10-18 19:41:25 +00:00
2017-12-20 22:55:48 +00:00
submenu = wx.Menu()
ClientGUIMenus.AppendMenuItem( self, submenu, 'from clipboard', 'Import new urls or paths to this list from the clipboard.', self._ImportFromClipboard )
ClientGUIMenus.AppendMenuItem( self, submenu, 'from png', 'Import new urls or paths to this list from a png file.', self._ImportFromPng )
ClientGUIMenus.AppendMenu( menu, submenu, 'import new sources' )
HG.client_controller.PopupMenu( self, menu )
2017-10-18 19:41:25 +00:00
2018-06-27 19:27:05 +00:00
class FileSeedCacheStatusControl( wx.Panel ):
2017-07-27 00:47:13 +00:00
2018-05-09 20:23:00 +00:00
def __init__( self, parent, controller, page_key = None ):
2017-07-27 00:47:13 +00:00
wx.Panel.__init__( self, parent, style = wx.BORDER_DOUBLE )
self._controller = controller
2018-05-09 20:23:00 +00:00
self._page_key = page_key
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
self._file_seed_cache = None
2017-07-27 00:47:13 +00:00
2018-08-15 20:40:30 +00:00
self._import_summary_st = ClientGUICommon.BetterStaticText( self, style = wx.ST_ELLIPSIZE_END )
self._progress_st = ClientGUICommon.BetterStaticText( self, style = wx.ST_ELLIPSIZE_END )
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
self._file_seed_cache_button = FileSeedCacheButton( self, self._controller, self._GetFileSeedCache )
2017-07-27 00:47:13 +00:00
self._progress_gauge = ClientGUICommon.Gauge( self )
#
self._Update()
#
hbox = wx.BoxSizer( wx.HORIZONTAL )
2018-01-03 22:37:30 +00:00
hbox.Add( self._progress_st, CC.FLAGS_VCENTER_EXPAND_DEPTH_ONLY )
2018-06-27 19:27:05 +00:00
hbox.Add( self._file_seed_cache_button, CC.FLAGS_VCENTER )
2017-07-27 00:47:13 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
2018-01-03 22:37:30 +00:00
vbox.Add( self._import_summary_st, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.Add( hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
vbox.Add( self._progress_gauge, CC.FLAGS_EXPAND_PERPENDICULAR )
2017-07-27 00:47:13 +00:00
self.SetSizer( vbox )
#
2018-02-14 21:47:18 +00:00
HG.client_controller.gui.RegisterUIUpdateWindow( self )
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
def _GetFileSeedCache( self ):
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
return self._file_seed_cache
2017-07-27 00:47:13 +00:00
def _Update( self ):
2018-06-27 19:27:05 +00:00
if self._file_seed_cache is None:
2017-07-27 00:47:13 +00:00
self._import_summary_st.SetLabelText( '' )
self._progress_st.SetLabelText( '' )
self._progress_gauge.SetRange( 1 )
self._progress_gauge.SetValue( 0 )
2018-06-27 19:27:05 +00:00
if self._file_seed_cache_button.IsEnabled():
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
self._file_seed_cache_button.Disable()
2017-07-27 00:47:13 +00:00
else:
2018-07-04 20:48:28 +00:00
( import_summary, simple_status, ( num_done, num_to_do ) ) = self._file_seed_cache.GetStatus()
2017-07-27 00:47:13 +00:00
self._import_summary_st.SetLabelText( import_summary )
if num_to_do == 0:
self._progress_st.SetLabelText( '' )
else:
self._progress_st.SetLabelText( HydrusData.ConvertValueRangeToPrettyString( num_done, num_to_do ) )
self._progress_gauge.SetRange( num_to_do )
self._progress_gauge.SetValue( num_done )
2018-06-27 19:27:05 +00:00
if not self._file_seed_cache_button.IsEnabled():
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
self._file_seed_cache_button.Enable()
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
def SetFileSeedCache( self, file_seed_cache ):
2017-07-27 00:47:13 +00:00
2018-02-14 21:47:18 +00:00
if not self:
2017-07-27 00:47:13 +00:00
2018-02-14 21:47:18 +00:00
return
2017-07-27 00:47:13 +00:00
2018-06-27 19:27:05 +00:00
self._file_seed_cache = file_seed_cache
2018-02-14 21:47:18 +00:00
2017-07-27 00:47:13 +00:00
2018-02-14 21:47:18 +00:00
def TIMERUIUpdate( self ):
2017-07-27 00:47:13 +00:00
2018-05-09 20:23:00 +00:00
do_it_anyway = False
2018-06-27 19:27:05 +00:00
if self._file_seed_cache is not None:
2018-05-09 20:23:00 +00:00
2018-07-04 20:48:28 +00:00
( import_summary, simple_status, ( num_done, num_to_do ) ) = self._file_seed_cache.GetStatus()
2018-05-09 20:23:00 +00:00
( old_num_done, old_num_to_do ) = self._progress_gauge.GetValueRange()
if old_num_done != num_done or old_num_to_do != num_to_do:
if self._page_key is not None:
do_it_anyway = True # to update the gauge
HG.client_controller.pub( 'refresh_page_name', self._page_key )
if self._controller.gui.IShouldRegularlyUpdate( self ) or do_it_anyway:
2017-07-27 00:47:13 +00:00
self._Update()