hydrus/include/ClientGUIManagement.py

2486 lines
92 KiB
Python
Raw Normal View History

2013-02-19 00:11:43 +00:00
import HydrusConstants as HC
2013-05-29 20:19:54 +00:00
import HydrusAudioHandling
2013-04-10 18:10:37 +00:00
import HydrusDownloading
2013-07-24 20:26:00 +00:00
import HydrusExceptions
2013-07-17 20:56:13 +00:00
import HydrusFileHandling
2013-02-19 00:11:43 +00:00
import HydrusImageHandling
2015-03-18 21:46:29 +00:00
import HydrusNetworking
2014-05-21 21:37:35 +00:00
import HydrusThreading
2013-02-19 00:11:43 +00:00
import ClientConstants as CC
import ClientConstantsMessages
2015-03-18 21:46:29 +00:00
import ClientData
import ClientCaches
import ClientFiles
import ClientGUICollapsible
2013-02-19 00:11:43 +00:00
import ClientGUICommon
import ClientGUIDialogs
import ClientGUIMedia
2015-03-18 21:46:29 +00:00
import ClientMedia
2013-02-19 00:11:43 +00:00
import json
import os
import threading
import time
import traceback
import urllib
import urlparse
import wx
import wx.lib.scrolledpanel
CAPTCHA_FETCH_EVENT_TYPE = wx.NewEventType()
CAPTCHA_FETCH_EVENT = wx.PyEventBinder( CAPTCHA_FETCH_EVENT_TYPE )
ID_TIMER_CAPTCHA = wx.NewId()
ID_TIMER_DUMP = wx.NewId()
2014-01-08 18:40:02 +00:00
ID_TIMER_UPDATE = wx.NewId()
2013-02-19 00:11:43 +00:00
class CaptchaControl( wx.Panel ):
2014-09-10 22:37:38 +00:00
def __init__( self, parent, captcha_type, default ):
2013-02-19 00:11:43 +00:00
wx.Panel.__init__( self, parent )
self._captcha_key = default
self._captcha_challenge = None
self._captcha_runs_out = 0
self._bitmap = wx.EmptyBitmap( 0, 0, 24 )
self._timer = wx.Timer( self, ID_TIMER_CAPTCHA )
2014-02-05 20:54:28 +00:00
self.Bind( wx.EVT_TIMER, self.TIMEREvent, id = ID_TIMER_CAPTCHA )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
self._captcha_box_panel = ClientGUICommon.StaticBox( self, 'recaptcha' )
self._captcha_panel = ClientGUICommon.BufferedWindow( self._captcha_box_panel, size = ( 300, 57 ) )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
self._refresh_button = wx.Button( self._captcha_box_panel, label = '' )
2013-02-19 00:11:43 +00:00
self._refresh_button.Bind( wx.EVT_BUTTON, self.EventRefreshCaptcha )
self._refresh_button.Disable()
2013-03-15 02:38:12 +00:00
self._captcha_time_left = wx.StaticText( self._captcha_box_panel )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
self._captcha_entry = wx.TextCtrl( self._captcha_box_panel, style = wx.TE_PROCESS_ENTER )
2013-02-19 00:11:43 +00:00
self._captcha_entry.Bind( wx.EVT_KEY_DOWN, self.EventKeyDown )
2013-03-15 02:38:12 +00:00
self._ready_button = wx.Button( self._captcha_box_panel, label = '' )
2013-02-19 00:11:43 +00:00
self._ready_button.Bind( wx.EVT_BUTTON, self.EventReady )
sub_vbox = wx.BoxSizer( wx.VERTICAL )
2015-03-18 21:46:29 +00:00
sub_vbox.AddF( self._refresh_button, CC.FLAGS_EXPAND_BOTH_WAYS )
sub_vbox.AddF( self._captcha_time_left, CC.FLAGS_SMALL_INDENT )
2013-02-19 00:11:43 +00:00
hbox = wx.BoxSizer( wx.HORIZONTAL )
2015-03-18 21:46:29 +00:00
hbox.AddF( self._captcha_panel, CC.FLAGS_NONE )
hbox.AddF( sub_vbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
2013-02-19 00:11:43 +00:00
hbox2 = wx.BoxSizer( wx.HORIZONTAL )
2015-03-18 21:46:29 +00:00
hbox2.AddF( self._captcha_entry, CC.FLAGS_EXPAND_BOTH_WAYS )
hbox2.AddF( self._ready_button, CC.FLAGS_MIXED )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
self._captcha_box_panel.AddF( hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
self._captcha_box_panel.AddF( hbox2, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
vbox.AddF( self._captcha_box_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
2013-02-19 00:11:43 +00:00
self.SetSizer( vbox )
self.Disable()
def _DrawEntry( self, entry = None ):
if entry is None:
self._captcha_entry.SetValue( '' )
self._captcha_entry.Disable()
else: self._captcha_entry.SetValue( entry )
def _DrawMain( self ):
dc = self._captcha_panel.GetDC()
if self._captcha_challenge is None:
dc.SetBackground( wx.Brush( wx.WHITE ) )
dc.Clear()
self._refresh_button.SetLabel( '' )
self._refresh_button.Disable()
self._captcha_time_left.SetLabel( '' )
elif self._captcha_challenge == '':
dc.SetBackground( wx.Brush( wx.WHITE ) )
dc.Clear()
event = wx.NotifyEvent( CAPTCHA_FETCH_EVENT_TYPE )
self.ProcessEvent( event )
if event.IsAllowed():
self._refresh_button.SetLabel( 'get captcha' )
self._refresh_button.Enable()
else:
self._refresh_button.SetLabel( 'not yet' )
self._refresh_button.Disable()
self._captcha_time_left.SetLabel( '' )
else:
2014-11-20 01:48:04 +00:00
wx_bmp = self._bitmap.GetWxBitmap()
2013-02-19 00:11:43 +00:00
2014-11-20 01:48:04 +00:00
dc.DrawBitmap( wx_bmp, 0, 0 )
2013-02-19 00:11:43 +00:00
2014-11-20 01:48:04 +00:00
wx.CallAfter( wx_bmp.Destroy )
2013-02-19 00:11:43 +00:00
self._refresh_button.SetLabel( 'get new captcha' )
self._refresh_button.Enable()
2014-10-01 22:58:32 +00:00
self._captcha_time_left.SetLabel( HC.ConvertTimestampToPrettyExpires( self._captcha_runs_out ) )
2013-02-19 00:11:43 +00:00
del dc
def _DrawReady( self, ready = None ):
if ready is None:
self._ready_button.SetLabel( '' )
self._ready_button.Disable()
else:
if ready:
self._captcha_entry.Disable()
self._ready_button.SetLabel( 'edit' )
else:
self._captcha_entry.Enable()
self._ready_button.SetLabel( 'ready' )
self._ready_button.Enable()
def Disable( self ):
self._captcha_challenge = None
self._captcha_runs_out = 0
self._bitmap = wx.EmptyBitmap( 0, 0, 24 )
self._DrawMain()
self._DrawEntry()
self._DrawReady()
self._timer.Stop()
def Enable( self ):
self._captcha_challenge = ''
self._captcha_runs_out = 0
self._bitmap = wx.EmptyBitmap( 0, 0, 24 )
self._DrawMain()
self._DrawEntry()
self._DrawReady()
self._timer.Start( 1000, wx.TIMER_CONTINUOUS )
def EnableWithValues( self, challenge, bitmap, captcha_runs_out, entry, ready ):
2013-07-31 21:26:38 +00:00
if HC.GetNow() > captcha_runs_out: self.Enable()
2013-02-19 00:11:43 +00:00
else:
self._captcha_challenge = challenge
self._captcha_runs_out = captcha_runs_out
self._bitmap = bitmap
self._DrawMain()
self._DrawEntry( entry )
self._DrawReady( ready )
self._timer.Start( 1000, wx.TIMER_CONTINUOUS )
def EventKeyDown( self, event ):
if event.KeyCode in ( wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER ): self.EventReady( None )
else: event.Skip()
def EventReady( self, event ): self._DrawReady( not self._ready_button.GetLabel() == 'edit' )
def EventRefreshCaptcha( self, event ):
2014-01-29 21:59:42 +00:00
javascript_string = HC.http.Request( HC.GET, 'http://www.google.com/recaptcha/api/challenge?k=' + self._captcha_key )
( trash, rest ) = javascript_string.split( 'challenge : \'', 1 )
( self._captcha_challenge, trash ) = rest.split( '\'', 1 )
jpeg = HC.http.Request( HC.GET, 'http://www.google.com/recaptcha/api/image?c=' + self._captcha_challenge )
temp_path = HC.GetTempPath()
with open( temp_path, 'wb' ) as f: f.write( jpeg )
self._bitmap = HydrusImageHandling.GenerateHydrusBitmap( temp_path )
self._captcha_runs_out = HC.GetNow() + 5 * 60 - 15
self._DrawMain()
self._DrawEntry( '' )
self._DrawReady( False )
self._timer.Start( 1000, wx.TIMER_CONTINUOUS )
2013-02-19 00:11:43 +00:00
2014-02-05 20:54:28 +00:00
# change this to hold (current challenge, bmp, timestamp it runs out, value, whethere ready to post)
def GetValues( self ): return ( self._captcha_challenge, self._bitmap, self._captcha_runs_out, self._captcha_entry.GetValue(), self._ready_button.GetLabel() == 'edit' )
def TIMEREvent( self, event ):
2013-02-19 00:11:43 +00:00
2013-07-31 21:26:38 +00:00
if HC.GetNow() > self._captcha_runs_out: self.Enable()
2013-02-19 00:11:43 +00:00
else: self._DrawMain()
class Comment( wx.Panel ):
def __init__( self, parent ):
wx.Panel.__init__( self, parent )
self._initial_comment = ''
2013-03-15 02:38:12 +00:00
self._comment_panel = ClientGUICommon.StaticBox( self, 'comment' )
self._comment = wx.TextCtrl( self._comment_panel, value = '', style = wx.TE_MULTILINE | wx.TE_READONLY, size = ( -1, 120 ) )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
self._comment_append = wx.TextCtrl( self._comment_panel, value = '', style = wx.TE_MULTILINE | wx.TE_PROCESS_ENTER, size = ( -1, 120 ) )
2013-02-19 00:11:43 +00:00
self._comment_append.Bind( wx.EVT_KEY_UP, self.EventKeyDown )
2015-03-18 21:46:29 +00:00
self._comment_panel.AddF( self._comment, CC.FLAGS_EXPAND_PERPENDICULAR )
self._comment_panel.AddF( self._comment_append, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
vbox.AddF( self._comment_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
2013-02-19 00:11:43 +00:00
self.SetSizer( vbox )
def _SetComment( self ):
append = self._comment_append.GetValue()
2014-09-24 21:50:07 +00:00
if self._initial_comment != '' and append != '': comment = self._initial_comment + os.linesep * 2 + append
2013-02-19 00:11:43 +00:00
else: comment = self._initial_comment + append
self._comment.SetValue( comment )
def Disable( self ):
self._initial_comment = ''
self._comment_append.SetValue( '' )
self._comment_append.Disable()
self._SetComment()
def EnableWithValues( self, initial, append ):
self._initial_comment = initial
self._comment_append.SetValue( append )
self._comment_append.Enable()
self._SetComment()
def GetValues( self ): return ( self._initial_comment, self._comment_append.GetValue() )
def EventKeyDown( self, event ):
self._SetComment()
event.Skip()
class ManagementPanel( wx.lib.scrolledpanel.ScrolledPanel ):
2014-08-27 22:15:22 +00:00
def __init__( self, parent, page, page_key, file_service_key = HC.LOCAL_FILE_SERVICE_KEY, starting_from_session = False ):
2013-02-19 00:11:43 +00:00
wx.lib.scrolledpanel.ScrolledPanel.__init__( self, parent, style = wx.BORDER_NONE | wx.VSCROLL )
self.SetupScrolling()
2013-03-15 02:38:12 +00:00
#self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
self.SetBackgroundColour( wx.WHITE )
2013-02-19 00:11:43 +00:00
self._page = page
self._page_key = page_key
2014-08-27 22:15:22 +00:00
self._file_service_key = file_service_key
self._tag_service_key = HC.COMBINED_TAG_SERVICE_KEY
2013-12-04 22:44:16 +00:00
self._starting_from_session = starting_from_session
2013-02-19 00:11:43 +00:00
2013-09-11 21:28:19 +00:00
self._paused = False
2013-02-19 00:11:43 +00:00
HC.pubsub.sub( self, 'SetSearchFocus', 'set_search_focus' )
2013-09-11 21:28:19 +00:00
HC.pubsub.sub( self, 'Pause', 'pause' )
2014-01-08 18:40:02 +00:00
HC.pubsub.sub( self, 'Resume', 'resume' )
2013-02-19 00:11:43 +00:00
def _MakeCollect( self, sizer ):
2013-03-15 02:38:12 +00:00
self._collect_by = ClientGUICommon.CheckboxCollect( self, self._page_key )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
sizer.AddF( self._collect_by, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
def _MakeCurrentSelectionTagsBox( self, sizer ):
2015-02-03 20:40:21 +00:00
tags_box = ClientGUICommon.StaticBoxSorterForListBoxTags( self, 'selection tags' )
2014-03-19 20:27:07 +00:00
2015-02-18 20:06:43 +00:00
t = ClientGUICommon.ListBoxTagsSelectionManagementPanel( tags_box, self._page_key )
2014-03-19 20:27:07 +00:00
tags_box.SetTagsBox( t )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
sizer.AddF( tags_box, CC.FLAGS_EXPAND_BOTH_WAYS )
2013-02-19 00:11:43 +00:00
def _MakeSort( self, sizer ):
self._sort_by = ClientGUICommon.ChoiceSort( self, self._page_key )
2015-03-18 21:46:29 +00:00
sizer.AddF( self._sort_by, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def CleanBeforeDestroy( self ): pass
2013-09-11 21:28:19 +00:00
def Pause( self, page_key ):
if page_key == self._page_key: self._paused = True
2014-01-08 18:40:02 +00:00
def Resume( self, page_key ):
2013-09-11 21:28:19 +00:00
if page_key == self._page_key: self._paused = False
2014-01-08 18:40:02 +00:00
def SetSearchFocus( self, page_key ): pass
2014-01-22 21:11:22 +00:00
def TestAbleToClose( self ): pass
2014-01-08 18:40:02 +00:00
2013-02-19 00:11:43 +00:00
class ManagementPanelDumper( ManagementPanel ):
2013-12-04 22:44:16 +00:00
def __init__( self, parent, page, page_key, imageboard, media_results, starting_from_session = False ):
2013-02-19 00:11:43 +00:00
2013-12-04 22:44:16 +00:00
ManagementPanel.__init__( self, parent, page, page_key, starting_from_session = starting_from_session )
2013-02-19 00:11:43 +00:00
2013-07-10 20:25:57 +00:00
( self._4chan_token, pin, timeout ) = HC.app.Read( '4chan_pass' )
2013-02-19 00:11:43 +00:00
2013-07-31 21:26:38 +00:00
self._have_4chan_pass = timeout > HC.GetNow()
2013-02-19 00:11:43 +00:00
self._imageboard = imageboard
2013-09-25 20:20:10 +00:00
self._current_hash = None
2013-02-19 00:11:43 +00:00
self._dumping = False
self._actually_dumping = False
self._num_dumped = 0
self._next_dump_index = 0
self._next_dump_time = 0
self._file_post_name = 'upfile'
self._timer = wx.Timer( self, ID_TIMER_DUMP )
2014-02-05 20:54:28 +00:00
self.Bind( wx.EVT_TIMER, self.TIMEREvent, id = ID_TIMER_DUMP )
2013-02-19 00:11:43 +00:00
2014-02-05 20:54:28 +00:00
( self._post_url, self._flood_time, self._form_fields, self._restrictions ) = self._imageboard.GetBoardInfo()
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
# progress
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._import_queue_panel = ClientGUICommon.StaticBox( self, 'import queue' )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._progress_info = wx.StaticText( self._import_queue_panel )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._progress_gauge = ClientGUICommon.Gauge( self._import_queue_panel )
2013-03-15 02:38:12 +00:00
self._progress_gauge.SetRange( len( media_results ) )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._start_button = wx.Button( self._import_queue_panel, label = 'start' )
2013-03-15 02:38:12 +00:00
self._start_button.Bind( wx.EVT_BUTTON, self.EventStartButton )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
self._import_queue_panel.AddF( self._progress_info, CC.FLAGS_EXPAND_PERPENDICULAR )
self._import_queue_panel.AddF( self._progress_gauge, CC.FLAGS_EXPAND_PERPENDICULAR )
self._import_queue_panel.AddF( self._start_button, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
# thread options
2013-03-15 02:38:12 +00:00
self._thread_panel = ClientGUICommon.StaticBox( self, 'thread options' )
2013-02-19 00:11:43 +00:00
self._thread_fields = {}
gridbox = wx.FlexGridSizer( 0, 2 )
gridbox.AddGrowableCol( 1, 1 )
2014-09-10 22:37:38 +00:00
for ( name, field_type, default, editable ) in self._form_fields:
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
if field_type in ( CC.FIELD_TEXT, CC.FIELD_THREAD_ID ): field = wx.TextCtrl( self._thread_panel, value = default )
elif field_type == CC.FIELD_PASSWORD: field = wx.TextCtrl( self._thread_panel, value = default, style = wx.TE_PASSWORD )
2013-02-19 00:11:43 +00:00
else: continue
2014-09-10 22:37:38 +00:00
self._thread_fields[ name ] = ( field_type, field )
2013-02-19 00:11:43 +00:00
if editable:
2015-03-18 21:46:29 +00:00
gridbox.AddF( wx.StaticText( self._thread_panel, label = name + ':' ), CC.FLAGS_MIXED )
gridbox.AddF( field, CC.FLAGS_EXPAND_BOTH_WAYS )
2013-02-19 00:11:43 +00:00
else: field.Hide()
2015-03-18 21:46:29 +00:00
self._thread_panel.AddF( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
# post options
2013-03-15 02:38:12 +00:00
self._post_panel = ClientGUICommon.StaticBox( self, 'post options' )
2013-02-19 00:11:43 +00:00
self._post_fields = {}
postbox = wx.BoxSizer( wx.VERTICAL )
2013-03-15 02:38:12 +00:00
self._post_info = wx.StaticText( self._post_panel, label = 'no file selected', style = wx.ALIGN_CENTER | wx.ST_NO_AUTORESIZE )
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
for ( name, field_type, default, editable ) in self._form_fields:
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
if field_type == CC.FIELD_VERIFICATION_RECAPTCHA:
2013-02-19 00:11:43 +00:00
if self._have_4chan_pass: continue
2014-09-10 22:37:38 +00:00
field = CaptchaControl( self._post_panel, field_type, default )
2013-02-19 00:11:43 +00:00
field.Bind( CAPTCHA_FETCH_EVENT, self.EventCaptchaRefresh )
2014-09-10 22:37:38 +00:00
elif field_type == CC.FIELD_COMMENT: field = Comment( self._post_panel )
2013-02-19 00:11:43 +00:00
else: continue
2014-09-10 22:37:38 +00:00
self._post_fields[ name ] = ( field_type, field, default )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
postbox.AddF( field, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
gridbox = wx.FlexGridSizer( 0, 2 )
gridbox.AddGrowableCol( 1, 1 )
2014-09-10 22:37:38 +00:00
for ( name, field_type, default, editable ) in self._form_fields:
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
if field_type == CC.FIELD_CHECKBOX:
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
field = wx.CheckBox( self._post_panel )
2013-02-19 00:11:43 +00:00
field.SetValue( default == 'True' )
else: continue
2014-09-10 22:37:38 +00:00
self._post_fields[ name ] = ( field_type, field, default )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
gridbox.AddF( wx.StaticText( self._post_panel, label = name + ':' ), CC.FLAGS_MIXED )
gridbox.AddF( field, CC.FLAGS_EXPAND_BOTH_WAYS )
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
for ( name, field_type, default, editable ) in self._form_fields:
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
if field_type == CC.FIELD_FILE: self._file_post_name = name
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
self._post_panel.AddF( self._post_info, CC.FLAGS_EXPAND_PERPENDICULAR )
self._post_panel.AddF( postbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
self._post_panel.AddF( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
# misc
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
self._advanced_tag_options = ClientGUICollapsible.CollapsibleOptionsTags( self, namespaces = [ 'creator', 'series', 'title', 'volume', 'chapter', 'page', 'character', 'person', 'all others' ] )
2013-02-19 00:11:43 +00:00
# arrange stuff
vbox = wx.BoxSizer( wx.VERTICAL )
self._MakeSort( vbox )
2015-03-18 21:46:29 +00:00
vbox.AddF( self._import_queue_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.AddF( self._thread_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.AddF( self._post_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.AddF( self._advanced_tag_options, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
self._MakeCurrentSelectionTagsBox( vbox )
self.SetSizer( vbox )
HC.pubsub.sub( self, 'FocusChanged', 'focus_changed' )
HC.pubsub.sub( self, 'SortedMediaPulse', 'sorted_media_pulse' )
2013-09-25 20:20:10 +00:00
self._sorted_media_hashes = [ media_result.GetHash() for media_result in media_results ]
2015-03-18 21:46:29 +00:00
self._hashes_to_media = { media_result.GetHash() : ClientMedia.MediaSingleton( media_result ) for media_result in media_results }
2013-09-25 20:20:10 +00:00
self._hashes_to_dump_info = {}
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
for ( hash, media ) in self._hashes_to_media.items():
2013-02-19 00:11:43 +00:00
dump_status_enum = CC.DUMPER_NOT_DUMPED
dump_status_string = 'not yet dumped'
post_field_info = []
2014-09-10 22:37:38 +00:00
for ( name, ( field_type, field, default ) ) in self._post_fields.items():
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
if field_type == CC.FIELD_COMMENT:
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
post_field_info.append( ( name, field_type, ( self._GetInitialComment( media ), '' ) ) )
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
elif field_type == CC.FIELD_CHECKBOX: post_field_info.append( ( name, field_type, default == 'True' ) )
elif field_type == CC.FIELD_VERIFICATION_RECAPTCHA: post_field_info.append( ( name, field_type, None ) )
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
self._hashes_to_dump_info[ hash ] = ( dump_status_enum, dump_status_string, post_field_info )
2013-02-19 00:11:43 +00:00
self.Bind( wx.EVT_MENU, self.EventMenu )
self._timer.Start( 1000, wx.TIMER_CONTINUOUS )
2013-09-25 20:20:10 +00:00
def _THREADDoDump( self, hash, post_field_info, headers, body ):
2013-02-19 00:11:43 +00:00
try:
2014-02-05 20:54:28 +00:00
response = HC.http.Request( HC.POST, self._post_url, request_headers = headers, body = body )
2013-02-19 00:11:43 +00:00
2014-02-05 20:54:28 +00:00
( status, phrase ) = HydrusDownloading.Parse4chanPostScreen( response )
2013-02-19 00:11:43 +00:00
2015-03-04 22:44:32 +00:00
except Exception as e:
( status, phrase ) = ( 'big error', HC.u( e ) )
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
wx.CallAfter( self.CALLBACKDoneDump, hash, post_field_info, status, phrase )
2013-02-19 00:11:43 +00:00
def _FreezeCurrentMediaPostInfo( self ):
2013-09-25 20:20:10 +00:00
( dump_status_enum, dump_status_string, post_field_info ) = self._hashes_to_dump_info[ self._current_hash ]
2013-02-19 00:11:43 +00:00
post_field_info = []
2014-09-10 22:37:38 +00:00
for ( name, ( field_type, field, default ) ) in self._post_fields.items():
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
if field_type == CC.FIELD_COMMENT: post_field_info.append( ( name, field_type, field.GetValues() ) )
elif field_type == CC.FIELD_CHECKBOX: post_field_info.append( ( name, field_type, field.GetValue() ) )
elif field_type == CC.FIELD_VERIFICATION_RECAPTCHA: post_field_info.append( ( name, field_type, field.GetValues() ) )
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
self._hashes_to_dump_info[ self._current_hash ] = ( dump_status_enum, dump_status_string, post_field_info )
2013-02-19 00:11:43 +00:00
def _GetInitialComment( self, media ):
2013-09-25 20:20:10 +00:00
hash = media.GetHash()
try: index = self._sorted_media_hashes.index( hash )
2013-02-19 00:11:43 +00:00
except: return 'media removed'
2013-09-25 20:20:10 +00:00
num_files = len( self._sorted_media_hashes )
2013-02-19 00:11:43 +00:00
if index == 0:
2013-09-25 20:20:10 +00:00
total_size = sum( [ m.GetSize() for m in self._hashes_to_media.values() ] )
2013-02-19 00:11:43 +00:00
2014-09-24 21:50:07 +00:00
initial = 'Hydrus Network Client is starting a dump of ' + HC.u( num_files ) + ' files, totalling ' + HC.ConvertIntToBytes( total_size ) + ':' + os.linesep * 2
2013-02-19 00:11:43 +00:00
else: initial = ''
2013-07-31 21:26:38 +00:00
initial += HC.u( index + 1 ) + '/' + HC.u( num_files )
2013-02-19 00:11:43 +00:00
2013-04-10 18:10:37 +00:00
advanced_tag_options = self._advanced_tag_options.GetInfo()
2013-02-19 00:11:43 +00:00
2014-08-13 22:18:12 +00:00
for ( service_key, namespaces ) in advanced_tag_options.items():
2013-02-19 00:11:43 +00:00
2013-06-12 22:53:31 +00:00
tags_manager = media.GetTagsManager()
2013-05-29 20:19:54 +00:00
2014-08-13 22:18:12 +00:00
try: service = HC.app.GetManager( 'services' ).GetService( service_key )
2015-03-04 22:44:32 +00:00
except HydrusExceptions.NotFoundException: continue
2014-08-13 22:18:12 +00:00
2014-09-17 21:28:26 +00:00
service_key = service.GetServiceKey()
2014-08-13 22:18:12 +00:00
2014-08-27 22:15:22 +00:00
current = tags_manager.GetCurrent( service_key )
pending = tags_manager.GetPending( service_key )
2013-02-19 00:11:43 +00:00
tags = current.union( pending )
tags_to_include = []
for namespace in namespaces:
if namespace == 'all others': tags_to_include.extend( [ tag for tag in tags if not True in ( tag.startswith( n ) for n in namespaces if n != 'all others' ) ] )
else: tags_to_include.extend( [ tag for tag in tags if tag.startswith( namespace + ':' ) ] )
2014-09-24 21:50:07 +00:00
initial += os.linesep * 2 + ', '.join( tags_to_include )
2013-02-19 00:11:43 +00:00
return initial
def _ShowCurrentMedia( self ):
2013-09-25 20:20:10 +00:00
if self._current_hash is None:
2013-02-19 00:11:43 +00:00
self._post_info.SetLabel( 'no file selected' )
2014-09-10 22:37:38 +00:00
for ( name, ( field_type, field, default ) ) in self._post_fields.items():
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
if field_type == CC.FIELD_CHECKBOX: field.SetValue( False )
2013-02-19 00:11:43 +00:00
field.Disable()
else:
2013-09-25 20:20:10 +00:00
num_files = len( self._sorted_media_hashes )
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
( dump_status_enum, dump_status_string, post_field_info ) = self._hashes_to_dump_info[ self._current_hash ]
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
index = self._sorted_media_hashes.index( self._current_hash )
2013-02-19 00:11:43 +00:00
2013-07-31 21:26:38 +00:00
self._post_info.SetLabel( HC.u( index + 1 ) + '/' + HC.u( num_files ) + ': ' + dump_status_string )
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
for ( name, field_type, value ) in post_field_info:
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
( field_type, field, default ) = self._post_fields[ name ]
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
if field_type == CC.FIELD_COMMENT:
2013-02-19 00:11:43 +00:00
( initial, append ) = value
field.EnableWithValues( initial, append )
2014-09-10 22:37:38 +00:00
elif field_type == CC.FIELD_CHECKBOX:
2013-02-19 00:11:43 +00:00
field.SetValue( value )
field.Enable()
2014-09-10 22:37:38 +00:00
elif field_type == CC.FIELD_VERIFICATION_RECAPTCHA:
2013-02-19 00:11:43 +00:00
if value is None: field.Enable()
else:
( challenge, bitmap, captcha_runs_out, entry, ready ) = value
field.EnableWithValues( challenge, bitmap, captcha_runs_out, entry, ready )
if dump_status_enum in ( CC.DUMPER_DUMPED_OK, CC.DUMPER_UNRECOVERABLE_ERROR ):
2014-09-10 22:37:38 +00:00
for ( name, ( field_type, field, default ) ) in self._post_fields.items():
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
if field_type == CC.FIELD_CHECKBOX: field.SetValue( False )
2013-02-19 00:11:43 +00:00
field.Disable()
def _UpdatePendingInitialComments( self ):
2013-09-25 20:20:10 +00:00
hashes_to_dump = self._sorted_media_hashes[ self._next_dump_index : ]
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
for hash in hashes_to_dump:
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
if hash == self._current_hash: self._FreezeCurrentMediaPostInfo()
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
( dump_status_enum, dump_status_string, post_field_info ) = self._hashes_to_dump_info[ hash ]
2013-02-19 00:11:43 +00:00
new_post_field_info = []
2014-09-10 22:37:38 +00:00
for ( name, field_type, value ) in post_field_info:
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
if field_type == CC.FIELD_COMMENT:
2013-02-19 00:11:43 +00:00
( initial, append ) = value
2013-09-25 20:20:10 +00:00
media = self._hashes_to_media[ hash ]
initial = self._GetInitialComment( media )
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
new_post_field_info.append( ( name, field_type, ( initial, append ) ) )
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
else: new_post_field_info.append( ( name, field_type, value ) )
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
self._hashes_to_dump_info[ hash ] = ( dump_status_enum, dump_status_string, new_post_field_info )
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
if hash == self._current_hash: self._ShowCurrentMedia()
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
def CALLBACKDoneDump( self, hash, post_field_info, status, phrase ):
2013-02-19 00:11:43 +00:00
self._actually_dumping = False
2013-08-14 20:21:49 +00:00
if HC.options[ 'play_dumper_noises' ]:
2013-05-29 20:19:54 +00:00
if status == 'success': HydrusAudioHandling.PlayNoise( 'success' )
else: HydrusAudioHandling.PlayNoise( 'error' )
2013-02-19 00:11:43 +00:00
if status == 'success':
dump_status_enum = CC.DUMPER_DUMPED_OK
dump_status_string = 'dumped ok'
2013-09-25 20:20:10 +00:00
if hash == self._current_hash: HC.pubsub.pub( 'set_focus', self._page_key, None )
2013-02-19 00:11:43 +00:00
2013-07-31 21:26:38 +00:00
self._next_dump_time = HC.GetNow() + self._flood_time
2013-02-19 00:11:43 +00:00
self._num_dumped += 1
self._progress_gauge.SetValue( self._num_dumped )
self._next_dump_index += 1
elif status == 'captcha':
dump_status_enum = CC.DUMPER_RECOVERABLE_ERROR
dump_status_string = 'captcha was incorrect'
2013-07-31 21:26:38 +00:00
self._next_dump_time = HC.GetNow() + 10
2013-02-19 00:11:43 +00:00
new_post_field_info = []
2014-09-10 22:37:38 +00:00
for ( name, field_type, value ) in post_field_info:
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
if field_type == CC.FIELD_VERIFICATION_RECAPTCHA: new_post_field_info.append( ( name, field_type, None ) )
else: new_post_field_info.append( ( name, field_type, value ) )
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
if hash == self._current_hash:
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
( field_type, field, default ) = self._post_fields[ name ]
2013-02-19 00:11:43 +00:00
field.Enable()
post_field_info = new_post_field_info
elif status == 'too quick':
dump_status_enum = CC.DUMPER_RECOVERABLE_ERROR
dump_status_string = ''
self._progress_info.SetLabel( 'Flood limit hit, retrying.' )
2013-07-31 21:26:38 +00:00
self._next_dump_time = HC.GetNow() + self._flood_time
2013-02-19 00:11:43 +00:00
elif status == 'big error':
dump_status_enum = CC.DUMPER_UNRECOVERABLE_ERROR
dump_status_string = ''
2014-01-22 21:11:22 +00:00
HC.ShowText( phrase )
2013-08-07 22:25:18 +00:00
2013-02-19 00:11:43 +00:00
self._progress_info.SetLabel( 'error: ' + phrase )
self._start_button.Disable()
self._timer.Stop()
elif 'Thread specified does not exist' in phrase:
dump_status_enum = CC.DUMPER_UNRECOVERABLE_ERROR
dump_status_string = ''
self._progress_info.SetLabel( 'thread specified does not exist!' )
self._start_button.Disable()
self._timer.Stop()
else:
dump_status_enum = CC.DUMPER_UNRECOVERABLE_ERROR
dump_status_string = phrase
2013-09-25 20:20:10 +00:00
if hash == self._current_hash: HC.pubsub.pub( 'set_focus', self._page_key, None )
2013-02-19 00:11:43 +00:00
2013-07-31 21:26:38 +00:00
self._next_dump_time = HC.GetNow() + self._flood_time
2013-02-19 00:11:43 +00:00
self._next_dump_index += 1
2013-09-25 20:20:10 +00:00
self._hashes_to_dump_info[ hash ] = ( dump_status_enum, dump_status_string, post_field_info )
2013-02-19 00:11:43 +00:00
HC.pubsub.pub( 'file_dumped', self._page_key, hash, dump_status_enum )
2013-09-25 20:20:10 +00:00
if self._next_dump_index == len( self._sorted_media_hashes ):
2013-02-19 00:11:43 +00:00
2013-07-31 21:26:38 +00:00
self._progress_info.SetLabel( 'done - ' + HC.u( self._num_dumped ) + ' dumped' )
2013-02-19 00:11:43 +00:00
self._start_button.Disable()
self._timer.Stop()
2013-06-19 20:25:06 +00:00
self._dumping = False
2013-02-19 00:11:43 +00:00
def EventCaptchaRefresh( self, event ):
try:
2013-09-25 20:20:10 +00:00
index = self._sorted_media_hashes.index( self._current_hash )
2013-02-19 00:11:43 +00:00
if ( ( index + 1 ) - self._next_dump_index ) * ( self._flood_time + 10 ) > 5 * 60: event.Veto()
except: event.Veto()
def EventMenu( self, event ):
2015-03-18 21:46:29 +00:00
action = ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetAction( event.GetId() )
2013-02-19 00:11:43 +00:00
if action is not None:
2013-08-14 20:21:49 +00:00
( command, data ) = action
if command == 'advanced_tag_options_changed': self._UpdatePendingInitialComments()
else: event.Skip()
2013-02-19 00:11:43 +00:00
def EventStartButton( self, event ):
if self._start_button.GetLabel() in ( 'start', 'continue' ):
2014-09-10 22:37:38 +00:00
for ( name, ( field_type, field ) ) in self._thread_fields.items():
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
if field_type == CC.FIELD_THREAD_ID:
2013-02-19 00:11:43 +00:00
try: int( field.GetValue() )
except:
2013-08-07 22:25:18 +00:00
# let's assume they put the url in
2013-02-19 00:11:43 +00:00
2013-08-07 22:25:18 +00:00
value = field.GetValue()
thread_id = value.split( '/' )[ -1 ]
try: int( thread_id )
except:
self._progress_info.SetLabel( 'set thread_id field first' )
return
field.SetValue( thread_id )
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
for ( field_type, field ) in self._thread_fields.values(): field.Disable()
2013-02-19 00:11:43 +00:00
self._dumping = True
self._start_button.SetLabel( 'pause' )
2013-07-31 21:26:38 +00:00
if self._next_dump_time == 0: self._next_dump_time = HC.GetNow() + 5
2013-02-19 00:11:43 +00:00
# disable thread fields here
else:
2014-09-10 22:37:38 +00:00
for ( field_type, field ) in self._thread_fields.values(): field.Enable()
2013-02-19 00:11:43 +00:00
self._dumping = False
if self._num_dumped == 0: self._start_button.SetLabel( 'start' )
else: self._start_button.SetLabel( 'continue' )
2014-02-05 20:54:28 +00:00
def FocusChanged( self, page_key, media ):
if page_key == self._page_key:
if media is None: hash = None
else: hash = media.GetHash()
if hash != self._current_hash:
old_hash = self._current_hash
if old_hash is not None: self._FreezeCurrentMediaPostInfo()
self._current_hash = hash
self._ShowCurrentMedia()
def SortedMediaPulse( self, page_key, sorted_media ):
if page_key == self._page_key:
self._sorted_media_hashes = [ media.GetHash() for media in sorted_media ]
self._hashes_to_media = { hash : self._hashes_to_media[ hash ] for hash in self._sorted_media_hashes }
new_hashes_to_dump_info = {}
for ( hash, ( dump_status_enum, dump_status_string, post_field_info ) ) in self._hashes_to_dump_info.items():
if hash not in self._sorted_media_hashes: continue
new_post_field_info = []
2014-09-10 22:37:38 +00:00
for ( name, field_type, value ) in post_field_info:
2014-02-05 20:54:28 +00:00
2014-09-10 22:37:38 +00:00
if field_type == CC.FIELD_COMMENT:
2014-02-05 20:54:28 +00:00
( initial, append ) = value
media = self._hashes_to_media[ hash ]
initial = self._GetInitialComment( media )
value = ( initial, append )
2014-09-10 22:37:38 +00:00
new_post_field_info.append( ( name, field_type, value ) )
2014-02-05 20:54:28 +00:00
new_hashes_to_dump_info[ hash ] = ( dump_status_enum, dump_status_string, new_post_field_info )
self._hashes_to_dump_info = new_hashes_to_dump_info
self._ShowCurrentMedia()
if self._current_hash is None and len( self._sorted_media_hashes ) > 0:
hash_to_select = self._sorted_media_hashes[0]
media_to_select = self._hashes_to_media[ hash_to_select ]
HC.pubsub.pub( 'set_focus', self._page_key, media_to_select )
def TestAbleToClose( self ):
if self._dumping:
with ClientGUIDialogs.DialogYesNo( self, 'This page is still dumping. Are you sure you want to close it?' ) as dlg:
if dlg.ShowModal() == wx.ID_NO: raise Exception()
def TIMEREvent( self, event ):
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
if self._paused: return
if self._actually_dumping: return
if self._dumping:
2013-09-11 21:28:19 +00:00
2013-09-25 20:20:10 +00:00
time_left = self._next_dump_time - HC.GetNow()
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
if time_left < 1:
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
try:
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
hash = self._sorted_media_hashes[ self._next_dump_index ]
2013-08-07 22:25:18 +00:00
wait = False
2013-09-25 20:20:10 +00:00
if hash == self._current_hash: self._FreezeCurrentMediaPostInfo()
2013-08-07 22:25:18 +00:00
2013-09-25 20:20:10 +00:00
( dump_status_enum, dump_status_string, post_field_info ) = self._hashes_to_dump_info[ hash ]
2013-08-07 22:25:18 +00:00
2014-09-10 22:37:38 +00:00
for ( name, field_type, value ) in post_field_info:
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
if field_type == CC.FIELD_VERIFICATION_RECAPTCHA:
2013-02-19 00:11:43 +00:00
2013-08-07 22:25:18 +00:00
if value is None:
2013-02-19 00:11:43 +00:00
wait = True
break
2013-08-07 22:25:18 +00:00
else:
( challenge, bitmap, captcha_runs_out, entry, ready ) = value
if HC.GetNow() > captcha_runs_out or not ready:
wait = True
break
2013-02-19 00:11:43 +00:00
2013-08-07 22:25:18 +00:00
if wait: self._progress_info.SetLabel( 'waiting for captcha' )
else:
2013-02-19 00:11:43 +00:00
2013-08-07 22:25:18 +00:00
self._progress_info.SetLabel( 'dumping' ) # 100% cpu time here - may or may not be desirable
2013-02-19 00:11:43 +00:00
2013-08-07 22:25:18 +00:00
post_fields = []
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
for ( name, ( field_type, field ) ) in self._thread_fields.items():
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
post_fields.append( ( name, field_type, field.GetValue() ) )
2013-02-19 00:11:43 +00:00
2013-08-07 22:25:18 +00:00
2014-09-10 22:37:38 +00:00
for ( name, field_type, value ) in post_field_info:
2013-02-19 00:11:43 +00:00
2014-09-10 22:37:38 +00:00
if field_type == CC.FIELD_VERIFICATION_RECAPTCHA:
2013-08-07 22:25:18 +00:00
( challenge, bitmap, captcha_runs_out, entry, ready ) = value
2014-09-10 22:37:38 +00:00
post_fields.append( ( 'recaptcha_challenge_field', field_type, challenge ) )
post_fields.append( ( 'recaptcha_response_field', field_type, entry ) )
2013-08-07 22:25:18 +00:00
2014-09-10 22:37:38 +00:00
elif field_type == CC.FIELD_COMMENT:
2013-08-07 22:25:18 +00:00
( initial, append ) = value
comment = initial
2014-09-24 21:50:07 +00:00
if len( append ) > 0: comment += os.linesep * 2 + append
2013-08-07 22:25:18 +00:00
2014-09-10 22:37:38 +00:00
post_fields.append( ( name, field_type, comment ) )
2013-08-07 22:25:18 +00:00
2014-09-10 22:37:38 +00:00
else: post_fields.append( ( name, field_type, value ) )
2013-02-19 00:11:43 +00:00
2013-08-07 22:25:18 +00:00
2013-09-25 20:20:10 +00:00
media = self._hashes_to_media[ hash ]
mime = media.GetMime()
2013-08-14 20:21:49 +00:00
2015-03-18 21:46:29 +00:00
path = ClientFiles.GetFilePath( hash, mime )
2013-08-07 22:25:18 +00:00
2013-08-14 20:21:49 +00:00
with open( path, 'rb' ) as f: file = f.read()
2013-08-07 22:25:18 +00:00
post_fields.append( ( self._file_post_name, CC.FIELD_FILE, ( hash, mime, file ) ) )
2015-03-18 21:46:29 +00:00
( ct, body ) = HydrusNetworking.GenerateDumpMultipartFormDataCTAndBody( post_fields )
2013-08-07 22:25:18 +00:00
headers = {}
headers[ 'Content-Type' ] = ct
if self._have_4chan_pass: headers[ 'Cookie' ] = 'pass_enabled=1; pass_id=' + self._4chan_token
self._actually_dumping = True
2014-05-21 21:37:35 +00:00
HydrusThreading.CallToThread( self._THREADDoDump, hash, post_field_info, headers, body )
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
except Exception as e:
( status, phrase ) = ( 'big error', HC.u( e ) )
wx.CallAfter( self.CALLBACKDoneDump, hash, post_field_info, status, phrase )
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
else: self._progress_info.SetLabel( 'dumping next file in ' + HC.u( time_left ) + ' seconds' )
2013-02-19 00:11:43 +00:00
2013-09-25 20:20:10 +00:00
else:
2013-08-07 22:25:18 +00:00
2013-09-25 20:20:10 +00:00
if self._num_dumped == 0: self._progress_info.SetLabel( 'will dump to ' + self._imageboard.GetName() )
else: self._progress_info.SetLabel( 'paused after ' + HC.u( self._num_dumped ) + ' files dumped' )
2013-02-19 00:11:43 +00:00
class ManagementPanelImport( ManagementPanel ):
2014-01-22 21:11:22 +00:00
def __init__( self, parent, page, page_key, import_controller, starting_from_session = False ):
2013-02-19 00:11:43 +00:00
2013-12-04 22:44:16 +00:00
ManagementPanel.__init__( self, parent, page, page_key, starting_from_session = starting_from_session )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._import_controller = import_controller
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._import_panel = ClientGUICommon.StaticBox( self, 'current file' )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._import_current_info = wx.StaticText( self._import_panel )
self._import_gauge = ClientGUICommon.Gauge( self._import_panel )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._import_queue_panel = ClientGUICommon.StaticBox( self, 'import queue' )
2013-03-15 02:38:12 +00:00
2014-01-22 21:11:22 +00:00
self._import_overall_info = wx.StaticText( self._import_queue_panel )
self._import_queue_info = wx.StaticText( self._import_queue_panel )
self._import_queue_gauge = ClientGUICommon.Gauge( self._import_queue_panel )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._import_pause_button = wx.Button( self._import_queue_panel, label = 'pause' )
2014-01-08 18:40:02 +00:00
self._import_pause_button.Bind( wx.EVT_BUTTON, self.EventPauseImportQueue )
2013-02-19 00:11:43 +00:00
self._import_pause_button.Disable()
2014-01-22 21:11:22 +00:00
self._import_cancel_button = wx.Button( self._import_queue_panel, label = 'that\'s enough' )
self._import_cancel_button.Bind( wx.EVT_BUTTON, self.EventCancelImportQueue )
self._import_cancel_button.SetForegroundColour( ( 128, 0, 0 ) )
self._import_cancel_button.Disable()
#
vbox = wx.BoxSizer( wx.VERTICAL )
self._MakeSort( vbox )
2015-03-18 21:46:29 +00:00
self._import_panel.AddF( self._import_current_info, CC.FLAGS_EXPAND_PERPENDICULAR )
self._import_panel.AddF( self._import_gauge, CC.FLAGS_EXPAND_PERPENDICULAR )
2014-01-22 21:11:22 +00:00
2015-03-18 21:46:29 +00:00
vbox.AddF( self._import_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
2014-01-22 21:11:22 +00:00
c_p_hbox = wx.BoxSizer( wx.HORIZONTAL )
2015-03-18 21:46:29 +00:00
c_p_hbox.AddF( self._import_pause_button, CC.FLAGS_EXPAND_BOTH_WAYS )
c_p_hbox.AddF( self._import_cancel_button, CC.FLAGS_EXPAND_BOTH_WAYS )
2014-01-22 21:11:22 +00:00
2015-03-18 21:46:29 +00:00
self._import_queue_panel.AddF( self._import_overall_info, CC.FLAGS_EXPAND_PERPENDICULAR )
self._import_queue_panel.AddF( self._import_queue_info, CC.FLAGS_EXPAND_PERPENDICULAR )
self._import_queue_panel.AddF( self._import_queue_gauge, CC.FLAGS_EXPAND_PERPENDICULAR )
self._import_queue_panel.AddF( c_p_hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
2014-01-22 21:11:22 +00:00
2015-03-18 21:46:29 +00:00
vbox.AddF( self._import_queue_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
2014-01-22 21:11:22 +00:00
self._InitExtraVboxElements( vbox )
2015-03-18 21:46:29 +00:00
self._advanced_import_options = ClientGUICollapsible.CollapsibleOptionsImport( self )
2014-01-22 21:11:22 +00:00
2015-03-18 21:46:29 +00:00
vbox.AddF( self._advanced_import_options, CC.FLAGS_EXPAND_PERPENDICULAR )
2014-01-22 21:11:22 +00:00
self._MakeCurrentSelectionTagsBox( vbox )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self.SetSizer( vbox )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
#
2013-02-19 00:11:43 +00:00
2014-01-08 18:40:02 +00:00
self.Bind( wx.EVT_TIMER, self.TIMEREventUpdate, id = ID_TIMER_UPDATE )
self._timer_update = wx.Timer( self, id = ID_TIMER_UPDATE )
self._timer_update.Start( 100, wx.TIMER_CONTINUOUS )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def _InitExtraVboxElements( self, vbox ):
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
pass
2013-02-19 00:11:43 +00:00
2014-01-08 18:40:02 +00:00
def _UpdateGUI( self ):
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
import_controller_job_key = self._import_controller.GetJobKey( 'controller' )
import_job_key = self._import_controller.GetJobKey( 'import' )
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
2014-01-22 21:11:22 +00:00
2014-01-08 18:40:02 +00:00
# info
2013-02-19 00:11:43 +00:00
2014-01-08 18:40:02 +00:00
status_strings = []
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
num_successful = import_controller_job_key.GetVariable( 'num_successful' )
num_failed = import_controller_job_key.GetVariable( 'num_failed' )
num_deleted = import_controller_job_key.GetVariable( 'num_deleted' )
num_redundant = import_controller_job_key.GetVariable( 'num_redundant' )
if num_successful > 0: status_strings.append( HC.u( num_successful ) + ' successful' )
if num_failed > 0: status_strings.append( HC.u( num_failed ) + ' failed' )
if num_deleted > 0: status_strings.append( HC.u( num_deleted ) + ' already deleted' )
if num_redundant > 0: status_strings.append( HC.u( num_redundant ) + ' already in db' )
2013-02-19 00:11:43 +00:00
2014-01-08 18:40:02 +00:00
overall_info = ', '.join( status_strings )
if overall_info != self._import_overall_info.GetLabel(): self._import_overall_info.SetLabel( overall_info )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
import_status = import_job_key.GetVariable( 'status' )
if import_status != self._import_current_info.GetLabel(): self._import_current_info.SetLabel( import_status )
2015-01-14 22:27:55 +00:00
import_queue_status = import_queue_job_key.GetVariable( 'status' )
2014-01-22 21:11:22 +00:00
if import_queue_status != self._import_queue_info.GetLabel(): self._import_queue_info.SetLabel( import_queue_status )
2014-01-08 18:40:02 +00:00
# buttons
2015-01-14 22:27:55 +00:00
if import_queue_job_key.IsPaused():
2014-01-08 18:40:02 +00:00
if self._import_pause_button.GetLabel() != 'resume':
self._import_pause_button.SetLabel( 'resume' )
self._import_pause_button.SetForegroundColour( ( 0, 128, 0 ) )
else:
if self._import_pause_button.GetLabel() != 'pause':
self._import_pause_button.SetLabel( 'pause' )
self._import_pause_button.SetForegroundColour( ( 0, 0, 0 ) )
2015-01-14 22:27:55 +00:00
if import_queue_job_key.IsWorking() and not import_queue_job_key.IsCancelled():
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._import_pause_button.Enable()
self._import_cancel_button.Enable()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
else:
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._import_pause_button.Disable()
self._import_cancel_button.Disable()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
# gauges
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
range = import_job_key.GetVariable( 'range' )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
if range is None: self._import_gauge.Pulse()
2013-02-19 00:11:43 +00:00
else:
2014-01-22 21:11:22 +00:00
value = import_job_key.GetVariable( 'value' )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._import_gauge.SetRange( range )
self._import_gauge.SetValue( value )
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
queue = import_queue_builder_job_key.GetVariable( 'queue' )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
if len( queue ) == 0:
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
if import_queue_builder_job_key.IsWorking(): self._import_queue_gauge.Pulse()
2014-01-08 18:40:02 +00:00
else:
2014-01-22 21:11:22 +00:00
self._import_queue_gauge.SetRange( 1 )
self._import_queue_gauge.SetValue( 0 )
2014-01-08 18:40:02 +00:00
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
else:
2015-01-14 22:27:55 +00:00
queue_position = import_queue_job_key.GetVariable( 'queue_position' )
2014-01-22 21:11:22 +00:00
self._import_queue_gauge.SetRange( len( queue ) )
self._import_queue_gauge.SetValue( queue_position )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def EventCancelImportQueue( self, event ):
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
import_queue_job_key.Cancel()
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key.Cancel()
2014-01-22 21:11:22 +00:00
self._UpdateGUI()
2013-02-19 00:11:43 +00:00
2014-01-08 18:40:02 +00:00
2014-01-22 21:11:22 +00:00
def EventPauseImportQueue( self, event ):
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
2014-01-22 21:11:22 +00:00
2015-01-14 22:27:55 +00:00
import_queue_job_key.PauseResume()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._UpdateGUI()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def GetAdvancedImportOptions( self ): return self._advanced_import_options.GetInfo()
2014-01-08 18:40:02 +00:00
def TIMEREventUpdate( self, event ): self._UpdateGUI()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def TestAbleToClose( self ):
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
2014-01-22 21:11:22 +00:00
2015-01-14 22:27:55 +00:00
if import_queue_job_key.IsWorking() and not import_queue_job_key.IsPaused():
2013-02-19 00:11:43 +00:00
with ClientGUIDialogs.DialogYesNo( self, 'This page is still importing. Are you sure you want to close it?' ) as dlg:
if dlg.ShowModal() == wx.ID_NO: raise Exception()
2014-01-22 21:11:22 +00:00
class ManagementPanelImports( ManagementPanelImport ):
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def _InitExtraVboxElements( self, vbox ):
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
ManagementPanelImport._InitExtraVboxElements( self, vbox )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
#
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._building_import_queue_panel = ClientGUICommon.StaticBox( self, 'building import queue' )
2013-03-15 02:38:12 +00:00
2014-01-22 21:11:22 +00:00
self._building_import_queue_info = wx.StaticText( self._building_import_queue_panel )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._building_import_queue_pause_button = wx.Button( self._building_import_queue_panel, label = 'pause' )
2015-01-14 22:27:55 +00:00
self._building_import_queue_pause_button.Bind( wx.EVT_BUTTON, self.EventPauseImportQueueBuilder )
2014-01-22 21:11:22 +00:00
self._building_import_queue_pause_button.Disable()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._building_import_queue_cancel_button = wx.Button( self._building_import_queue_panel, label = 'that\'s enough' )
2015-01-14 22:27:55 +00:00
self._building_import_queue_cancel_button.Bind( wx.EVT_BUTTON, self.EventCancelImportQueueBuilder )
2014-01-22 21:11:22 +00:00
self._building_import_queue_cancel_button.SetForegroundColour( ( 128, 0, 0 ) )
self._building_import_queue_cancel_button.Disable()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
queue_pause_buttons_hbox = wx.BoxSizer( wx.HORIZONTAL )
2013-12-11 22:09:25 +00:00
2015-03-18 21:46:29 +00:00
queue_pause_buttons_hbox.AddF( self._building_import_queue_pause_button, CC.FLAGS_EXPAND_BOTH_WAYS )
queue_pause_buttons_hbox.AddF( self._building_import_queue_cancel_button, CC.FLAGS_EXPAND_BOTH_WAYS )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
self._building_import_queue_panel.AddF( self._building_import_queue_info, CC.FLAGS_EXPAND_PERPENDICULAR )
self._building_import_queue_panel.AddF( queue_pause_buttons_hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
vbox.AddF( self._building_import_queue_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
#
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._pending_import_queues_panel = ClientGUICommon.StaticBox( self, 'pending imports' )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._pending_import_queues_listbox = wx.ListBox( self._pending_import_queues_panel, size = ( -1, 200 ) )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._new_queue_input = wx.TextCtrl( self._pending_import_queues_panel, style = wx.TE_PROCESS_ENTER )
self._new_queue_input.Bind( wx.EVT_KEY_DOWN, self.EventKeyDown )
2013-05-01 17:21:53 +00:00
2014-01-22 21:11:22 +00:00
self._up = wx.Button( self._pending_import_queues_panel, label = u'\u2191' )
self._up.Bind( wx.EVT_BUTTON, self.EventUp )
2013-05-01 17:21:53 +00:00
2014-01-22 21:11:22 +00:00
self._remove = wx.Button( self._pending_import_queues_panel, label = 'X' )
self._remove.Bind( wx.EVT_BUTTON, self.EventRemove )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._down = wx.Button( self._pending_import_queues_panel, label = u'\u2193' )
self._down.Bind( wx.EVT_BUTTON, self.EventDown )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
queue_buttons_vbox = wx.BoxSizer( wx.VERTICAL )
2013-10-30 22:28:06 +00:00
2015-03-18 21:46:29 +00:00
queue_buttons_vbox.AddF( self._up, CC.FLAGS_MIXED )
queue_buttons_vbox.AddF( self._remove, CC.FLAGS_MIXED )
queue_buttons_vbox.AddF( self._down, CC.FLAGS_MIXED )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
queue_hbox = wx.BoxSizer( wx.HORIZONTAL )
2013-03-15 02:38:12 +00:00
2015-03-18 21:46:29 +00:00
queue_hbox.AddF( self._pending_import_queues_listbox, CC.FLAGS_EXPAND_BOTH_WAYS )
queue_hbox.AddF( queue_buttons_vbox, CC.FLAGS_MIXED )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
self._pending_import_queues_panel.AddF( queue_hbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
self._pending_import_queues_panel.AddF( self._new_queue_input, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-03-15 02:38:12 +00:00
2015-03-18 21:46:29 +00:00
vbox.AddF( self._pending_import_queues_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
wx.CallAfter( self._new_queue_input.SelectAll ) # to select the 'artist username' init gumpf
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def _UpdateGUI( self ):
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
ManagementPanelImport._UpdateGUI( self )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
import_job_key = self._import_controller.GetJobKey( 'import' )
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
# info
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
import_queue_builder_status = import_queue_builder_job_key.GetVariable( 'status' )
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
if import_queue_builder_status != self._building_import_queue_info.GetLabel(): self._building_import_queue_info.SetLabel( import_queue_builder_status )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
# buttons
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
#
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
if import_queue_builder_job_key.IsPaused():
2014-01-22 21:11:22 +00:00
if self._building_import_queue_pause_button.GetLabel() != 'resume':
self._building_import_queue_pause_button.SetLabel( 'resume' )
self._building_import_queue_pause_button.SetForegroundColour( ( 0, 128, 0 ) )
else:
if self._building_import_queue_pause_button.GetLabel() != 'pause':
self._building_import_queue_pause_button.SetLabel( 'pause' )
self._building_import_queue_pause_button.SetForegroundColour( ( 0, 0, 0 ) )
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
if import_queue_builder_job_key.IsWorking() and not import_queue_job_key.IsCancelled():
2014-01-22 21:11:22 +00:00
self._building_import_queue_pause_button.Enable()
self._building_import_queue_cancel_button.Enable()
else:
self._building_import_queue_pause_button.Disable()
self._building_import_queue_cancel_button.Disable()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
# gauge
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
range = import_job_key.GetVariable( 'range' )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
if range is None: self._import_gauge.Pulse()
else:
value = import_job_key.GetVariable( 'value' )
self._import_gauge.SetRange( range )
self._import_gauge.SetValue( value )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
# pending import queues
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
pending_import_queue_jobs = self._import_controller.GetPendingImportQueueJobs()
2013-05-01 17:21:53 +00:00
2015-01-14 22:27:55 +00:00
if pending_import_queue_jobs != self._pending_import_queues_listbox.GetItems():
2014-01-22 21:11:22 +00:00
2015-01-14 22:27:55 +00:00
self._pending_import_queues_listbox.SetItems( pending_import_queue_jobs )
2014-01-22 21:11:22 +00:00
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
def EventCancelImportQueueBuilder( self, event ):
2014-01-08 18:40:02 +00:00
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
2014-01-22 21:11:22 +00:00
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key.Cancel()
2014-01-08 18:40:02 +00:00
self._UpdateGUI()
2013-02-19 00:11:43 +00:00
def EventKeyDown( self, event ):
if event.KeyCode in ( wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER ):
2014-01-22 21:11:22 +00:00
s = self._new_queue_input.GetValue()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
if s != '':
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
self._import_controller.PendImportQueueJob( s )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._UpdateGUI()
2013-02-19 00:11:43 +00:00
self._new_queue_input.SetValue( '' )
else: event.Skip()
2015-01-14 22:27:55 +00:00
def EventPauseImportQueueBuilder( self, event ):
2014-01-22 21:11:22 +00:00
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
2014-01-22 21:11:22 +00:00
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key.PauseResume()
2014-01-22 21:11:22 +00:00
self._UpdateGUI()
2013-02-19 00:11:43 +00:00
def EventUp( self, event ):
2014-01-22 21:11:22 +00:00
selection = self._pending_import_queues_listbox.GetSelection()
2013-02-19 00:11:43 +00:00
if selection != wx.NOT_FOUND:
if selection > 0:
2014-01-22 21:11:22 +00:00
s = self._pending_import_queues_listbox.GetString( selection )
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
self._import_controller.MovePendingImportQueueJobUp( s )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._UpdateGUI()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._pending_import_queues_listbox.Select( selection - 1 )
2013-02-19 00:11:43 +00:00
def EventRemove( self, event ):
2014-01-22 21:11:22 +00:00
selection = self._pending_import_queues_listbox.GetSelection()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
if selection != wx.NOT_FOUND:
s = self._pending_import_queues_listbox.GetString( selection )
2015-01-14 22:27:55 +00:00
self._import_controller.RemovePendingImportQueueJob( s )
2014-01-22 21:11:22 +00:00
self._UpdateGUI()
2013-02-19 00:11:43 +00:00
def EventDown( self, event ):
2014-01-22 21:11:22 +00:00
selection = self._pending_import_queues_listbox.GetSelection()
2013-02-19 00:11:43 +00:00
if selection != wx.NOT_FOUND:
2014-01-22 21:11:22 +00:00
if selection + 1 < self._pending_import_queues_listbox.GetCount():
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
s = self._pending_import_queues_listbox.GetString( selection )
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
self._import_controller.MovePendingImportQueueJobDown( s )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._UpdateGUI()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._pending_import_queues_listbox.Select( selection + 1 )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def SetSearchFocus( self, page_key ):
2013-10-30 22:28:06 +00:00
2014-01-22 21:11:22 +00:00
if page_key == self._page_key: self._new_queue_input.SetFocus()
2013-10-30 22:28:06 +00:00
2014-01-22 21:11:22 +00:00
class ManagementPanelImportsGallery( ManagementPanelImports ):
2014-09-03 20:26:49 +00:00
def __init__( self, parent, page, page_key, import_controller, name, namespaces, ato, initial_search_value, starting_from_session = False ):
2014-01-22 21:11:22 +00:00
self._name = name
self._namespaces = namespaces
2014-09-03 20:26:49 +00:00
self._ato = ato
2014-01-22 21:11:22 +00:00
self._initial_search_value = initial_search_value
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
ManagementPanelImports.__init__( self, parent, page, page_key, import_controller, starting_from_session = starting_from_session )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def _InitExtraVboxElements( self, vbox ):
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
ManagementPanelImports._InitExtraVboxElements( self, vbox )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
#
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._new_queue_input.SetValue( self._initial_search_value )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
#
2014-01-08 18:40:02 +00:00
2015-03-18 21:46:29 +00:00
self._advanced_tag_options = ClientGUICollapsible.CollapsibleOptionsTags( self, self._namespaces )
2014-09-03 20:26:49 +00:00
self._advanced_tag_options.SetInfo( self._ato )
2014-01-08 18:40:02 +00:00
2015-03-18 21:46:29 +00:00
vbox.AddF( self._advanced_tag_options, CC.FLAGS_EXPAND_PERPENDICULAR )
2014-01-08 18:40:02 +00:00
2014-01-22 21:11:22 +00:00
def GetAdvancedTagOptions( self ): return self._advanced_tag_options.GetInfo()
class ManagementPanelImportsGalleryHentaiFoundry( ManagementPanelImportsGallery ):
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def _InitExtraVboxElements( self, vbox ):
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
ManagementPanelImportsGallery._InitExtraVboxElements( self, vbox )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
self._advanced_hentai_foundry_options = ClientGUICollapsible.CollapsibleOptionsHentaiFoundry( self )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
vbox.AddF( self._advanced_hentai_foundry_options, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def GetAdvancedHentaiFoundryOptions( self ): return self._advanced_hentai_foundry_options.GetInfo()
class ManagementPanelImportsURL( ManagementPanelImports ):
def _InitExtraVboxElements( self, vbox ):
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
ManagementPanelImports._InitExtraVboxElements( self, vbox )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._building_import_queue_pause_button.Hide()
self._building_import_queue_cancel_button.Hide()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
class ManagementPanelImportHDD( ManagementPanelImport ):
def __init__( self, *args, **kwargs ):
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
ManagementPanelImport.__init__( self, *args, **kwargs )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._advanced_import_options.Hide()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def _InitExtraVboxElements( self, vbox ):
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
ManagementPanelImport._InitExtraVboxElements( self, vbox )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._import_gauge.Hide()
self._import_cancel_button.Hide()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
def _InitExtraVboxElements( self, vbox ):
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
ManagementPanelImport._InitExtraVboxElements( self, vbox )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._import_cancel_button.Hide()
2013-04-17 21:48:18 +00:00
2014-01-22 21:11:22 +00:00
#
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
self._thread_panel = ClientGUICommon.StaticBox( self, 'thread checker' )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._thread_info = wx.StaticText( self._thread_panel, label = 'enter a 4chan thread url' )
2013-02-19 00:11:43 +00:00
2014-10-22 22:31:58 +00:00
( times_to_check, check_period ) = HC.options[ 'thread_checker_timings' ]
2014-10-08 20:17:55 +00:00
self._thread_times_to_check = wx.SpinCtrl( self._thread_panel, size = ( 60, -1 ), min = 0, max = 100 )
2014-10-22 22:31:58 +00:00
self._thread_times_to_check.SetValue( times_to_check )
2014-10-08 20:17:55 +00:00
self._thread_times_to_check.Bind( wx.EVT_SPINCTRL, self.EventThreadVariable )
2014-10-22 22:31:58 +00:00
self._thread_check_period = wx.SpinCtrl( self._thread_panel, size = ( 100, -1 ), min = 30, max = 86400 )
self._thread_check_period.SetValue( check_period )
self._thread_check_period.Bind( wx.EVT_SPINCTRL, self.EventThreadVariable )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
self._thread_input = wx.TextCtrl( self._thread_panel, style = wx.TE_PROCESS_ENTER )
2013-02-19 00:11:43 +00:00
self._thread_input.Bind( wx.EVT_KEY_DOWN, self.EventKeyDown )
2013-03-15 02:38:12 +00:00
self._thread_pause_button = wx.Button( self._thread_panel, label = 'pause' )
2015-01-14 22:27:55 +00:00
self._thread_pause_button.Bind( wx.EVT_BUTTON, self.EventPauseImportQueueBuilder )
self._thread_manual_refresh_button = wx.Button( self._thread_panel, label = 'check now' )
self._thread_manual_refresh_button.Bind( wx.EVT_BUTTON, self.EventManualRefresh )
2013-02-19 00:11:43 +00:00
hbox = wx.BoxSizer( wx.HORIZONTAL )
2015-03-18 21:46:29 +00:00
hbox.AddF( wx.StaticText( self._thread_panel, label = 'check ' ), CC.FLAGS_MIXED )
hbox.AddF( self._thread_times_to_check, CC.FLAGS_MIXED )
hbox.AddF( wx.StaticText( self._thread_panel, label = ' more times, every ' ), CC.FLAGS_MIXED )
hbox.AddF( self._thread_check_period, CC.FLAGS_MIXED )
hbox.AddF( wx.StaticText( self._thread_panel, label = ' seconds' ), CC.FLAGS_MIXED )
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
button_box = wx.BoxSizer( wx.HORIZONTAL )
2015-03-18 21:46:29 +00:00
button_box.AddF( self._thread_pause_button, CC.FLAGS_EXPAND_BOTH_WAYS )
button_box.AddF( self._thread_manual_refresh_button, CC.FLAGS_EXPAND_BOTH_WAYS )
2015-01-14 22:27:55 +00:00
2015-03-18 21:46:29 +00:00
self._thread_panel.AddF( self._thread_info, CC.FLAGS_EXPAND_PERPENDICULAR )
self._thread_panel.AddF( self._thread_input, CC.FLAGS_EXPAND_PERPENDICULAR )
self._thread_panel.AddF( hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
self._thread_panel.AddF( button_box, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
vbox.AddF( self._thread_panel, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
#
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
self._advanced_tag_options = ClientGUICollapsible.CollapsibleOptionsTags( self, namespaces = [ 'filename' ] )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
vbox.AddF( self._advanced_tag_options, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
2014-10-08 20:17:55 +00:00
def _SetThreadVariables( self ):
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
2013-02-19 00:11:43 +00:00
2014-10-22 22:31:58 +00:00
thread_time = self._thread_check_period.GetValue()
2014-10-08 20:17:55 +00:00
thread_times_to_check = self._thread_times_to_check.GetValue()
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key.SetVariable( 'manual_refresh', False )
import_queue_builder_job_key.SetVariable( 'thread_time', thread_time )
import_queue_builder_job_key.SetVariable( 'thread_times_to_check', thread_times_to_check )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def _UpdateGUI( self ):
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
ManagementPanelImport._UpdateGUI( self )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
import_job_key = self._import_controller.GetJobKey( 'import' )
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
# thread_info
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
status = import_queue_builder_job_key.GetVariable( 'status' )
2013-08-14 20:21:49 +00:00
2014-01-22 21:11:22 +00:00
if status != self._thread_info.GetLabel(): self._thread_info.SetLabel( status )
2013-08-14 20:21:49 +00:00
2014-01-22 21:11:22 +00:00
# button
2013-08-14 20:21:49 +00:00
2015-01-14 22:27:55 +00:00
if import_queue_builder_job_key.IsWorking():
2013-08-14 20:21:49 +00:00
2014-01-22 21:11:22 +00:00
self._thread_pause_button.Enable()
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
if import_queue_builder_job_key.IsPaused():
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
self._thread_pause_button.SetLabel( 'resume' )
self._thread_pause_button.SetForegroundColour( ( 0, 128, 0 ) )
2013-02-19 00:11:43 +00:00
else:
2014-01-22 21:11:22 +00:00
self._thread_pause_button.SetLabel( 'pause' )
self._thread_pause_button.SetForegroundColour( ( 0, 0, 0 ) )
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
else: self._thread_pause_button.Disable()
2013-02-19 00:11:43 +00:00
2014-10-08 20:17:55 +00:00
# times to check
try:
2015-01-14 22:27:55 +00:00
thread_times_to_check = import_queue_builder_job_key.GetVariable( 'thread_times_to_check' )
2014-10-08 20:17:55 +00:00
self._thread_times_to_check.SetValue( thread_times_to_check )
except: self._SetThreadVariables()
2015-01-14 22:27:55 +00:00
try:
manual_refresh = import_queue_builder_job_key.GetVariable( 'manual_refresh' )
if not import_queue_builder_job_key.IsWorking() or manual_refresh: self._thread_manual_refresh_button.Disable()
else: self._thread_manual_refresh_button.Enable()
except: self._SetThreadVariables()
2013-02-19 00:11:43 +00:00
def EventKeyDown( self, event ):
if event.KeyCode in ( wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER ):
2014-10-08 20:17:55 +00:00
self._SetThreadVariables()
2013-02-19 00:11:43 +00:00
url = self._thread_input.GetValue()
if url == '': return
try:
try:
parse_result = urlparse.urlparse( url )
host = parse_result.hostname
request = parse_result.path
if host is None or request is None: raise Exception()
except: raise Exception ( 'Could not understand that url!' )
2014-10-08 20:17:55 +00:00
is_4chan = '4chan.org' in host
2015-01-14 22:27:55 +00:00
is_8chan = '8chan.co' in host or '8ch.net' in host
2014-10-08 20:17:55 +00:00
2014-12-10 22:02:39 +00:00
if not ( is_4chan or is_8chan ): raise Exception( 'This only works for 4chan and 8chan right now!' )
2013-02-19 00:11:43 +00:00
2014-04-23 20:56:12 +00:00
try:
2014-10-08 20:17:55 +00:00
# 4chan
2014-04-23 20:56:12 +00:00
# /asp/thread/382059/post-your-favourite-martial-arts-video-if-martin
2014-10-08 20:17:55 +00:00
# http://a.4cdn.org/asp/thread/382059.json
# http://i.4cdn.org/asp/ for images
2014-04-23 20:56:12 +00:00
2014-10-08 20:17:55 +00:00
# 8chan
# /v/res/406061.html
# http://8chan.co/v/res/406061.json
# http://8chan.co/v/src/ for images
2014-04-23 20:56:12 +00:00
2014-10-08 20:17:55 +00:00
if is_4chan:
( board, rest_of_request ) = request[1:].split( '/thread/', 1 )
if '/' in rest_of_request: ( thread_id, gumpf ) = rest_of_request.split( '/' )
else: thread_id = rest_of_request
json_url = 'http://a.4cdn.org/' + board + '/thread/' + thread_id + '.json'
image_base = 'http://i.4cdn.org/' + board + '/'
elif is_8chan:
( board, rest_of_request ) = request[1:].split( '/res/', 1 )
json_url = url[:-4] + 'json'
2015-01-14 22:27:55 +00:00
image_base = 'http://8ch.net/' + board + '/src/'
2014-10-08 20:17:55 +00:00
2014-04-23 20:56:12 +00:00
2013-02-19 00:11:43 +00:00
except: raise Exception( 'Could not understand the board or thread id!' )
except Exception as e:
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
2014-10-08 20:17:55 +00:00
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key.SetVariable( 'status', HC.u( e ) )
2014-10-08 20:17:55 +00:00
HC.ShowException( e )
2013-02-19 00:11:43 +00:00
return
2014-01-22 21:11:22 +00:00
self._thread_input.Disable()
2013-02-19 00:11:43 +00:00
2014-10-08 20:17:55 +00:00
self._SetThreadVariables()
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
self._import_controller.PendImportQueueJob( ( json_url, image_base ) )
2013-02-19 00:11:43 +00:00
else: event.Skip()
2015-01-14 22:27:55 +00:00
def EventManualRefresh( self, event ):
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
2013-02-19 00:11:43 +00:00
2015-01-14 22:27:55 +00:00
import_queue_builder_job_key.SetVariable( 'manual_refresh', True )
self._thread_manual_refresh_button.Disable()
def EventPauseImportQueueBuilder( self, event ):
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
import_queue_builder_job_key.PauseResume()
2013-10-30 22:28:06 +00:00
2014-01-22 21:11:22 +00:00
self._UpdateGUI()
2013-10-30 22:28:06 +00:00
2014-10-08 20:17:55 +00:00
def EventThreadVariable( self, event ): self._SetThreadVariables()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def GetAdvancedTagOptions( self ): return self._advanced_tag_options.GetInfo()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def SetSearchFocus( self, page_key ):
2014-01-08 18:40:02 +00:00
2014-01-22 21:11:22 +00:00
if page_key == self._page_key: self._thread_input.SetFocus()
2014-01-08 18:40:02 +00:00
2014-03-19 20:27:07 +00:00
def TestAbleToClose( self ):
2015-01-14 22:27:55 +00:00
import_queue_builder_position_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
2014-03-19 20:27:07 +00:00
2015-01-14 22:27:55 +00:00
if self._thread_times_to_check.GetValue() > 0 and import_queue_builder_position_job_key.IsWorking() and not import_queue_builder_position_job_key.IsPaused():
2014-03-19 20:27:07 +00:00
with ClientGUIDialogs.DialogYesNo( self, 'This page is still importing. Are you sure you want to close it?' ) as dlg:
if dlg.ShowModal() == wx.ID_NO: raise Exception()
2013-02-19 00:11:43 +00:00
class ManagementPanelPetitions( ManagementPanel ):
2014-08-27 22:15:22 +00:00
def __init__( self, parent, page, page_key, file_service_key, petition_service_key, starting_from_session = False ):
2013-06-12 22:53:31 +00:00
2014-08-27 22:15:22 +00:00
self._petition_service_key = petition_service_key
2013-02-19 00:11:43 +00:00
2014-08-27 22:15:22 +00:00
ManagementPanel.__init__( self, parent, page, page_key, file_service_key, starting_from_session = starting_from_session )
2013-02-19 00:11:43 +00:00
2014-08-27 22:15:22 +00:00
self._service = HC.app.GetManager( 'services' ).GetService( self._petition_service_key )
2014-05-14 20:46:38 +00:00
self._can_ban = self._service.GetInfo( 'account' ).HasPermission( HC.MANAGE_USERS )
2013-02-19 00:11:43 +00:00
self._num_petitions = None
self._current_petition = None
2013-03-15 02:38:12 +00:00
self._petitions_info_panel = ClientGUICommon.StaticBox( self, 'petitions info' )
self._num_petitions_text = wx.StaticText( self._petitions_info_panel )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
refresh_num_petitions = wx.Button( self._petitions_info_panel, label = 'refresh' )
2013-02-19 00:11:43 +00:00
refresh_num_petitions.Bind( wx.EVT_BUTTON, self.EventRefreshNumPetitions )
2013-03-15 02:38:12 +00:00
self._get_petition = wx.Button( self._petitions_info_panel, label = 'get petition' )
2013-02-19 00:11:43 +00:00
self._get_petition.Bind( wx.EVT_BUTTON, self.EventGetPetition )
self._get_petition.Disable()
2013-03-15 02:38:12 +00:00
self._petition_panel = ClientGUICommon.StaticBox( self, 'petition' )
self._petition_info_text_ctrl = wx.TextCtrl( self._petition_panel, style = wx.TE_READONLY | wx.TE_MULTILINE )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
self._approve = wx.Button( self._petition_panel, label = 'approve' )
2013-02-19 00:11:43 +00:00
self._approve.Bind( wx.EVT_BUTTON, self.EventApprove )
self._approve.SetForegroundColour( ( 0, 128, 0 ) )
self._approve.Disable()
2013-03-15 02:38:12 +00:00
self._deny = wx.Button( self._petition_panel, label = 'deny' )
2013-02-19 00:11:43 +00:00
self._deny.Bind( wx.EVT_BUTTON, self.EventDeny )
self._deny.SetForegroundColour( ( 128, 0, 0 ) )
self._deny.Disable()
2013-03-15 02:38:12 +00:00
self._modify_petitioner = wx.Button( self._petition_panel, label = 'modify petitioner' )
2013-02-19 00:11:43 +00:00
self._modify_petitioner.Bind( wx.EVT_BUTTON, self.EventModifyPetitioner )
self._modify_petitioner.Disable()
if not self._can_ban: self._modify_petitioner.Hide()
2013-03-15 02:38:12 +00:00
num_petitions_hbox = wx.BoxSizer( wx.HORIZONTAL )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
num_petitions_hbox.AddF( self._num_petitions_text, CC.FLAGS_EXPAND_BOTH_WAYS )
num_petitions_hbox.AddF( refresh_num_petitions, CC.FLAGS_MIXED )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
self._petitions_info_panel.AddF( num_petitions_hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
self._petitions_info_panel.AddF( self._get_petition, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
p_hbox = wx.BoxSizer( wx.HORIZONTAL )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
p_hbox.AddF( self._approve, CC.FLAGS_EXPAND_BOTH_WAYS )
p_hbox.AddF( self._deny, CC.FLAGS_EXPAND_BOTH_WAYS )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
self._petition_panel.AddF( self._petition_info_text_ctrl, CC.FLAGS_EXPAND_BOTH_WAYS )
self._petition_panel.AddF( p_hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
self._petition_panel.AddF( self._modify_petitioner, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
self._MakeSort( vbox )
self._MakeCollect( vbox )
2015-03-18 21:46:29 +00:00
vbox.AddF( self._petitions_info_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.AddF( self._petition_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
2013-02-19 00:11:43 +00:00
self._MakeCurrentSelectionTagsBox( vbox )
self.SetSizer( vbox )
wx.CallAfter( self.EventRefreshNumPetitions, None )
HC.pubsub.sub( self, 'RefreshQuery', 'refresh_query' )
def _DrawCurrentPetition( self ):
if self._current_petition is None:
self._petition_info_text_ctrl.SetValue( '' )
self._approve.Disable()
self._deny.Disable()
if self._can_ban: self._modify_petitioner.Disable()
2014-08-27 22:15:22 +00:00
panel = ClientGUIMedia.MediaPanelNoQuery( self._page, self._page_key, self._file_service_key )
2013-02-19 00:11:43 +00:00
else:
self._petition_info_text_ctrl.SetValue( self._current_petition.GetPetitionString() )
self._approve.Enable()
self._deny.Enable()
if self._can_ban: self._modify_petitioner.Enable()
2014-08-27 22:15:22 +00:00
with wx.BusyCursor(): media_results = HC.app.Read( 'media_results', self._file_service_key, self._current_petition.GetHashes() )
2013-02-19 00:11:43 +00:00
2014-08-27 22:15:22 +00:00
panel = ClientGUIMedia.MediaPanelThumbnails( self._page, self._page_key, self._file_service_key, media_results )
2013-02-19 00:11:43 +00:00
panel.Collect( self._page_key, self._collect_by.GetChoice() )
panel.Sort( self._page_key, self._sort_by.GetChoice() )
HC.pubsub.pub( 'swap_media_panel', self._page_key, panel )
def _DrawNumPetitions( self ):
self._num_petitions_text.SetLabel( HC.ConvertIntToPrettyString( self._num_petitions ) + ' petitions' )
if self._num_petitions > 0: self._get_petition.Enable()
else: self._get_petition.Disable()
def EventApprove( self, event ):
2013-06-12 22:53:31 +00:00
update = self._current_petition.GetApproval()
2013-02-19 00:11:43 +00:00
2014-01-29 21:59:42 +00:00
self._service.Request( HC.POST, 'update', { 'update' : update } )
2013-02-19 00:11:43 +00:00
2014-08-27 22:15:22 +00:00
HC.app.Write( 'content_updates', { self._petition_service_key : update.GetContentUpdates( for_client = True ) } )
2013-02-19 00:11:43 +00:00
self._current_petition = None
self._DrawCurrentPetition()
self.EventRefreshNumPetitions( event )
def EventDeny( self, event ):
2013-06-12 22:53:31 +00:00
update = self._current_petition.GetDenial()
2013-02-19 00:11:43 +00:00
2014-01-29 21:59:42 +00:00
self._service.Request( HC.POST, 'update', { 'update' : update } )
2013-02-19 00:11:43 +00:00
self._current_petition = None
self._DrawCurrentPetition()
self.EventRefreshNumPetitions( event )
def EventGetPetition( self, event ):
try:
2014-01-29 21:59:42 +00:00
response = self._service.Request( HC.GET, 'petition' )
2013-10-02 22:06:06 +00:00
self._current_petition = response[ 'petition' ]
2013-02-19 00:11:43 +00:00
self._DrawCurrentPetition()
except:
wx.MessageBox( traceback.format_exc() )
self._current_petition = None
self._DrawCurrentPetition()
def EventModifyPetitioner( self, event ):
2014-08-27 22:15:22 +00:00
with ClientGUIDialogs.DialogModifyAccounts( self, self._petition_service_key, ( self._current_petition.GetPetitionerIdentifier(), ) ) as dlg: dlg.ShowModal()
2013-02-19 00:11:43 +00:00
def EventRefreshNumPetitions( self, event ):
self._num_petitions_text.SetLabel( u'Fetching\u2026' )
try:
2014-01-29 21:59:42 +00:00
response = self._service.Request( HC.GET, 'num_petitions' )
2013-10-02 22:06:06 +00:00
self._num_petitions = response[ 'num_petitions' ]
2013-02-19 00:11:43 +00:00
self._DrawNumPetitions()
if self._num_petitions > 0: self.EventGetPetition( event )
2015-03-04 22:44:32 +00:00
except Exception as e:
self._num_petitions_text.SetLabel( HC.u( e ) )
2013-02-19 00:11:43 +00:00
def RefreshQuery( self, page_key ):
if page_key == self._page_key: self._DrawCurrentPetition()
class ManagementPanelQuery( ManagementPanel ):
2014-08-27 22:15:22 +00:00
def __init__( self, parent, page, page_key, file_service_key, show_search = True, initial_predicates = [], starting_from_session = False ):
2013-02-19 00:11:43 +00:00
2014-08-27 22:15:22 +00:00
ManagementPanel.__init__( self, parent, page, page_key, file_service_key, starting_from_session = starting_from_session )
2013-02-19 00:11:43 +00:00
2014-12-10 22:02:39 +00:00
self._query_key = HC.JobKey( cancellable = True )
2013-02-19 00:11:43 +00:00
self._synchronised = True
self._include_current_tags = True
self._include_pending_tags = True
2014-03-26 21:23:10 +00:00
self._show_search = show_search
if self._show_search:
2013-09-04 16:48:44 +00:00
self._search_panel = ClientGUICommon.StaticBox( self, 'search' )
2015-02-03 20:40:21 +00:00
self._current_predicates_box = ClientGUICommon.ListBoxTagsPredicates( self._search_panel, self._page_key, initial_predicates )
2013-09-04 16:48:44 +00:00
2014-08-27 22:15:22 +00:00
self._searchbox = ClientGUICommon.AutoCompleteDropdownTagsRead( self._search_panel, self._page_key, self._file_service_key, HC.COMBINED_TAG_SERVICE_KEY, self._page.GetMedia )
2013-09-04 16:48:44 +00:00
2015-03-18 21:46:29 +00:00
self._search_panel.AddF( self._current_predicates_box, CC.FLAGS_EXPAND_PERPENDICULAR )
self._search_panel.AddF( self._searchbox, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-09-04 16:48:44 +00:00
2013-02-19 00:11:43 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
self._MakeSort( vbox )
self._MakeCollect( vbox )
2015-03-18 21:46:29 +00:00
if self._show_search: vbox.AddF( self._search_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
self._MakeCurrentSelectionTagsBox( vbox )
self.SetSizer( vbox )
2013-12-04 22:44:16 +00:00
if len( initial_predicates ) > 0 and not starting_from_session: wx.CallAfter( self._DoQuery )
2013-02-19 00:11:43 +00:00
2013-08-28 21:31:52 +00:00
HC.pubsub.sub( self, 'AddMediaResultsFromQuery', 'add_media_results_from_query' )
2013-02-19 00:11:43 +00:00
HC.pubsub.sub( self, 'AddPredicate', 'add_predicate' )
2014-03-19 20:27:07 +00:00
HC.pubsub.sub( self, 'ChangeFileRepositoryPubsub', 'change_file_repository' )
HC.pubsub.sub( self, 'ChangeTagRepositoryPubsub', 'change_tag_repository' )
2013-02-19 00:11:43 +00:00
HC.pubsub.sub( self, 'IncludeCurrent', 'notify_include_current' )
HC.pubsub.sub( self, 'IncludePending', 'notify_include_pending' )
HC.pubsub.sub( self, 'SearchImmediately', 'notify_search_immediately' )
HC.pubsub.sub( self, 'ShowQuery', 'file_query_done' )
HC.pubsub.sub( self, 'RefreshQuery', 'refresh_query' )
HC.pubsub.sub( self, 'RemovePredicate', 'remove_predicate' )
def _DoQuery( self ):
2013-08-28 21:31:52 +00:00
self._query_key.Cancel()
2013-09-11 21:28:19 +00:00
self._query_key = HC.JobKey()
2013-08-28 21:31:52 +00:00
2014-03-26 21:23:10 +00:00
if self._show_search and self._synchronised:
2013-02-19 00:11:43 +00:00
try:
current_predicates = self._current_predicates_box.GetPredicates()
if len( current_predicates ) > 0:
include_current = self._include_current_tags
include_pending = self._include_pending_tags
2015-03-18 21:46:29 +00:00
search_context = ClientData.FileSearchContext( self._file_service_key, self._tag_service_key, include_current, include_pending, current_predicates )
2013-02-19 00:11:43 +00:00
2013-08-28 21:31:52 +00:00
HC.app.StartFileQuery( self._query_key, search_context )
2013-02-19 00:11:43 +00:00
2014-08-27 22:15:22 +00:00
panel = ClientGUIMedia.MediaPanelLoading( self._page, self._page_key, self._file_service_key )
2013-02-19 00:11:43 +00:00
2014-08-27 22:15:22 +00:00
else: panel = ClientGUIMedia.MediaPanelNoQuery( self._page, self._page_key, self._file_service_key )
2013-02-19 00:11:43 +00:00
HC.pubsub.pub( 'swap_media_panel', self._page_key, panel )
except: wx.MessageBox( traceback.format_exc() )
2013-08-28 21:31:52 +00:00
def AddMediaResultsFromQuery( self, query_key, media_results ):
if query_key == self._query_key: HC.pubsub.pub( 'add_media_results', self._page_key, media_results, append = False )
2013-02-19 00:11:43 +00:00
def AddPredicate( self, page_key, predicate ):
2014-10-22 22:31:58 +00:00
if self._show_search and page_key == self._page_key:
2013-02-19 00:11:43 +00:00
if predicate is not None:
2015-01-07 23:09:00 +00:00
( predicate_type, value, inclusive ) = predicate.GetInfo()
2013-03-27 20:02:51 +00:00
if predicate_type == HC.PREDICATE_TYPE_SYSTEM:
( system_predicate_type, info ) = value
2013-02-19 00:11:43 +00:00
2013-04-03 20:56:07 +00:00
if system_predicate_type in [ HC.SYSTEM_PREDICATE_TYPE_NUM_TAGS, HC.SYSTEM_PREDICATE_TYPE_LIMIT, HC.SYSTEM_PREDICATE_TYPE_SIZE, HC.SYSTEM_PREDICATE_TYPE_AGE, HC.SYSTEM_PREDICATE_TYPE_HASH, HC.SYSTEM_PREDICATE_TYPE_WIDTH, HC.SYSTEM_PREDICATE_TYPE_HEIGHT, HC.SYSTEM_PREDICATE_TYPE_RATIO, HC.SYSTEM_PREDICATE_TYPE_DURATION, HC.SYSTEM_PREDICATE_TYPE_NUM_WORDS, HC.SYSTEM_PREDICATE_TYPE_MIME, HC.SYSTEM_PREDICATE_TYPE_RATING, HC.SYSTEM_PREDICATE_TYPE_SIMILAR_TO, HC.SYSTEM_PREDICATE_TYPE_FILE_SERVICE ]:
2013-02-19 00:11:43 +00:00
2013-03-27 20:02:51 +00:00
with ClientGUIDialogs.DialogInputFileSystemPredicate( self, system_predicate_type ) as dlg:
if dlg.ShowModal() == wx.ID_OK: predicate = dlg.GetPredicate()
else: return
2013-02-19 00:11:43 +00:00
2014-04-09 20:18:58 +00:00
elif system_predicate_type == HC.SYSTEM_PREDICATE_TYPE_UNTAGGED: predicate = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_NUM_TAGS, ( '=', 0 ) ) )
2013-02-19 00:11:43 +00:00
if self._current_predicates_box.HasPredicate( predicate ): self._current_predicates_box.RemovePredicate( predicate )
2013-03-27 20:02:51 +00:00
else: self._current_predicates_box.AddPredicate( predicate )
2013-02-19 00:11:43 +00:00
self._DoQuery()
2014-08-27 22:15:22 +00:00
def ChangeFileRepositoryPubsub( self, page_key, service_key ):
2013-02-19 00:11:43 +00:00
if page_key == self._page_key:
2014-08-27 22:15:22 +00:00
self._file_service_key = service_key
2013-02-19 00:11:43 +00:00
self._DoQuery()
2014-08-27 22:15:22 +00:00
def ChangeTagRepositoryPubsub( self, page_key, service_key ):
2013-02-19 00:11:43 +00:00
if page_key == self._page_key:
2014-08-27 22:15:22 +00:00
self._tag_service_key = service_key
2013-02-19 00:11:43 +00:00
2013-04-03 20:56:07 +00:00
self._DoQuery()
2013-02-19 00:11:43 +00:00
2014-01-22 21:11:22 +00:00
def CleanBeforeDestroy( self ):
ManagementPanel.CleanBeforeDestroy( self )
self._query_key.Cancel()
2014-01-08 18:40:02 +00:00
def GetPredicates( self ):
if hasattr( self, '_current_predicates_box' ): return self._current_predicates_box.GetPredicates()
else: return []
2013-11-27 18:27:11 +00:00
2013-02-19 00:11:43 +00:00
def IncludeCurrent( self, page_key, value ):
if page_key == self._page_key:
self._include_current_tags = value
self._DoQuery()
def IncludePending( self, page_key, value ):
if page_key == self._page_key:
self._include_pending_tags = value
self._DoQuery()
def RefreshQuery( self, page_key ):
if page_key == self._page_key: self._DoQuery()
def RemovePredicate( self, page_key, predicate ):
if page_key == self._page_key:
if self._current_predicates_box.HasPredicate( predicate ):
self._current_predicates_box.RemovePredicate( predicate )
self._DoQuery()
def SearchImmediately( self, page_key, value ):
if page_key == self._page_key:
self._synchronised = value
self._DoQuery()
def SetSearchFocus( self, page_key ):
2013-09-04 16:48:44 +00:00
if page_key == self._page_key:
try: self._searchbox.SetFocus() # there's a chance this doesn't exist!
2014-12-17 22:35:12 +00:00
except: HC.pubsub.pub( 'set_media_focus' )
2013-09-04 16:48:44 +00:00
2013-02-19 00:11:43 +00:00
2013-08-28 21:31:52 +00:00
def ShowQuery( self, query_key, media_results ):
2013-02-19 00:11:43 +00:00
try:
if query_key == self._query_key:
current_predicates = self._current_predicates_box.GetPredicates()
2014-08-27 22:15:22 +00:00
panel = ClientGUIMedia.MediaPanelThumbnails( self._page, self._page_key, self._file_service_key, media_results )
2013-02-19 00:11:43 +00:00
panel.Collect( self._page_key, self._collect_by.GetChoice() )
panel.Sort( self._page_key, self._sort_by.GetChoice() )
HC.pubsub.pub( 'swap_media_panel', self._page_key, panel )
except: wx.MessageBox( traceback.format_exc() )
class ManagementPanelMessages( wx.ScrolledWindow ):
2013-12-04 22:44:16 +00:00
def __init__( self, parent, page_key, identity, starting_from_session = False ):
2013-02-19 00:11:43 +00:00
wx.ScrolledWindow.__init__( self, parent, style = wx.BORDER_NONE | wx.HSCROLL | wx.VSCROLL )
self.SetScrollRate( 0, 20 )
self._page_key = page_key
self._identity = identity
2013-12-04 22:44:16 +00:00
self._starting_from_session = starting_from_session
2013-02-19 00:11:43 +00:00
2014-12-10 22:02:39 +00:00
self._query_key = HC.JobKey( cancellable = True )
2013-02-19 00:11:43 +00:00
# sort out push-refresh later
#self._refresh_inbox = wx.Button( self, label = 'refresh inbox' )
#self._refresh_inbox.Bind( wx.EVT_BUTTON, self.EventRefreshInbox )
#self._refresh_inbox.SetForegroundColour( ( 0, 128, 0 ) )
2013-03-15 02:38:12 +00:00
self._actions_panel = ClientGUICommon.StaticBox( self, 'actions' )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
self._compose = wx.Button( self._actions_panel, label = 'compose' )
2013-02-19 00:11:43 +00:00
self._compose.Bind( wx.EVT_BUTTON, self.EventCompose )
self._compose.SetForegroundColour( ( 0, 128, 0 ) )
2015-03-18 21:46:29 +00:00
self._actions_panel.AddF( self._compose, CC.FLAGS_EXPAND_PERPENDICULAR )
#vbox.AddF( self._refresh_inbox, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
self._search_panel = ClientGUICommon.StaticBox( self, 'search' )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
self._current_predicates_box = ClientGUICommon.ListBoxMessagesPredicates( self._search_panel, self._page_key, [ 'system:inbox' ] )
2013-02-19 00:11:43 +00:00
2014-10-01 22:58:32 +00:00
self._synchronised = ClientGUICommon.OnOffButton( self._search_panel, self._page_key, 'notify_search_immediately', on_label = 'searching immediately', off_label = 'waiting -- counts may be inaccurate' )
2013-02-19 00:11:43 +00:00
self._synchronised.SetToolTipString( 'select whether to renew the search as soon as a new predicate is entered' )
2013-03-15 02:38:12 +00:00
self._searchbox = ClientGUICommon.AutoCompleteDropdownMessageTerms( self._search_panel, self._page_key, self._identity )
2013-02-19 00:11:43 +00:00
2015-03-18 21:46:29 +00:00
self._search_panel.AddF( self._current_predicates_box, CC.FLAGS_EXPAND_BOTH_WAYS )
self._search_panel.AddF( self._synchronised, CC.FLAGS_EXPAND_PERPENDICULAR )
self._search_panel.AddF( self._searchbox, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
2015-03-18 21:46:29 +00:00
vbox.AddF( self._actions_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.AddF( self._search_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
2013-02-19 00:11:43 +00:00
self.SetSizer( vbox )
HC.pubsub.sub( self, 'AddPredicate', 'add_predicate' )
HC.pubsub.sub( self, 'SearchImmediately', 'notify_search_immediately' )
HC.pubsub.sub( self, 'ShowQuery', 'message_query_done' )
HC.pubsub.sub( self, 'RefreshQuery', 'refresh_query' )
HC.pubsub.sub( self, 'RemovePredicate', 'remove_predicate' )
wx.CallAfter( self._DoQuery )
def _DoQuery( self ):
if self._synchronised.IsOn():
try:
current_predicates = self._current_predicates_box.GetPredicates()
HC.pubsub.pub( 'set_conversations', self._page_key, [] )
2013-08-28 21:31:52 +00:00
self._query_key.Cancel()
2014-12-10 22:02:39 +00:00
self._query_key = HC.JobKey( cancellable = True )
2013-08-28 21:31:52 +00:00
2013-02-19 00:11:43 +00:00
if len( current_predicates ) > 0:
search_context = ClientConstantsMessages.MessageSearchContext( self._identity, current_predicates )
2013-07-10 20:25:57 +00:00
HC.app.Read( 'do_message_query', self._query_key, search_context )
2013-02-19 00:11:43 +00:00
except: wx.MessageBox( traceback.format_exc() )
def AddPredicate( self, page_key, predicate ):
if page_key == self._page_key:
if predicate is not None:
if predicate in ( 'system:started_by', 'system:from', 'system:to', 'system:age', 'system:numattachments' ):
with ClientGUIDialogs.DialogInputMessageSystemPredicate( self, predicate ) as dlg:
if dlg.ShowModal() == wx.ID_OK: predicate = dlg.GetString()
else: return
elif predicate == 'system:unread': predicate = 'system:status=unread'
elif predicate == 'system:drafts': predicate = 'system:draft'
if self._current_predicates_box.HasPredicate( predicate ): self._current_predicates_box.RemovePredicate( predicate )
else:
if predicate in ( 'system:inbox', 'system:archive' ):
if predicate == 'system:inbox': removee = 'system:archive'
elif predicate == 'system:archive': removee = 'system:inbox'
else:
if predicate.startswith( '-' ): removee = predicate[1:]
else: removee = '-' + predicate
if self._current_predicates_box.HasPredicate( removee ): self._current_predicates_box.RemovePredicate( removee )
self._current_predicates_box.AddPredicate( predicate )
self._DoQuery()
def EventCompose( self, event ): HC.pubsub.pub( 'new_compose_frame', self._identity )
def EventRefreshInbox( self, event ):
# tell db to do it, and that'll spam the appropriate pubsubs (which will tell this to just refresh query, I think is best)
pass
def RefreshQuery( self, page_key ):
if page_key == self._page_key: self._DoQuery()
def RemovePredicate( self, page_key, predicate ):
if page_key == self._page_key:
if self._current_predicates_box.HasPredicate( predicate ):
self._current_predicates_box.RemovePredicate( predicate )
self._DoQuery()
def SearchImmediately( self, page_key, value ):
if page_key == self._page_key and value: self._DoQuery()
def SetSearchFocus( self, page_key ):
if page_key == self._page_key: self._searchbox.SetFocus()
def ShowQuery( self, query_key, conversations ):
try:
if query_key == self._query_key: HC.pubsub.pub( 'set_conversations', self._page_key, conversations )
except: wx.MessageBox( traceback.format_exc() )
2014-01-22 21:11:22 +00:00
def TestAbleToClose( self ):
2013-02-19 00:11:43 +00:00
pass
# if have a open draft, save it!