2015-03-18 21:46:29 +00:00
import ClientCaches
import ClientData
2013-02-19 00:11:43 +00:00
import ClientConstants as CC
2016-11-16 20:21:43 +00:00
import ClientGUIMenus
2017-05-24 20:28:24 +00:00
import ClientGUITopLevelWindows
2017-08-09 21:33:51 +00:00
import ClientMedia
2015-05-13 20:22:39 +00:00
import ClientRatings
2017-03-08 23:23:12 +00:00
import ClientThreading
2017-03-15 20:13:04 +00:00
import HydrusConstants as HC
import HydrusData
import HydrusExceptions
2017-05-10 21:33:58 +00:00
import HydrusGlobals as HG
2017-12-13 22:33:07 +00:00
import HydrusText
2013-02-19 00:11:43 +00:00
import os
2013-08-14 20:21:49 +00:00
import sys
2017-02-01 21:11:17 +00:00
import threading
2013-02-19 00:11:43 +00:00
import time
import traceback
import wx
2016-05-18 20:07:14 +00:00
import wx . lib . newevent
2013-02-19 00:11:43 +00:00
ID_TIMER_ANIMATED = wx . NewId ( )
ID_TIMER_SLIDESHOW = wx . NewId ( )
ID_TIMER_MEDIA_INFO_DISPLAY = wx . NewId ( )
2018-01-17 22:52:10 +00:00
def ApplyContentApplicationCommandToMedia ( parent , command , media ) :
data = command . GetData ( )
( service_key , content_type , action , value ) = data
try :
service = HG . client_controller . services_manager . GetService ( service_key )
except HydrusExceptions . DataMissing :
command_processed = False
return command_processed
service_type = service . GetServiceType ( )
hashes = set ( )
for m in media :
hashes . update ( m . GetHashes ( ) )
if service_type in HC . TAG_SERVICES :
tag = value
can_add = False
can_pend = False
can_delete = False
can_petition = True
can_rescind_pend = False
can_rescind_petition = False
for m in media :
tags_manager = m . GetTagsManager ( )
current = tags_manager . GetCurrent ( service_key )
pending = tags_manager . GetPending ( service_key )
petitioned = tags_manager . GetPetitioned ( service_key )
if tag not in current :
can_add = True
if tag not in current and tag not in pending :
can_pend = True
if tag in current and action == HC . CONTENT_UPDATE_FLIP :
can_delete = True
if tag in current and tag not in petitioned and action == HC . CONTENT_UPDATE_FLIP :
can_petition = True
if tag in pending and action == HC . CONTENT_UPDATE_FLIP :
can_rescind_pend = True
if tag in petitioned :
can_rescind_petition = True
if service_type == HC . LOCAL_TAG :
tags = [ tag ]
if can_add :
content_update_action = HC . CONTENT_UPDATE_ADD
tag_parents_manager = HG . client_controller . GetManager ( ' tag_parents ' )
parents = tag_parents_manager . GetParents ( service_key , tag )
tags . extend ( parents )
elif can_delete :
content_update_action = HC . CONTENT_UPDATE_DELETE
else :
return True
rows = [ ( tag , hashes ) for tag in tags ]
else :
if can_rescind_petition :
content_update_action = HC . CONTENT_UPDATE_RESCIND_PETITION
rows = [ ( tag , hashes ) ]
elif can_pend :
tags = [ tag ]
content_update_action = HC . CONTENT_UPDATE_PEND
tag_parents_manager = HG . client_controller . GetManager ( ' tag_parents ' )
parents = tag_parents_manager . GetParents ( service_key , tag )
tags . extend ( parents )
rows = [ ( tag , hashes ) for tag in tags ]
elif can_rescind_pend :
content_update_action = HC . CONTENT_UPDATE_RESCIND_PEND
rows = [ ( tag , hashes ) ]
elif can_petition :
message = ' Enter a reason for this tag to be removed. A janitor will review your petition. '
import ClientGUIDialogs
with ClientGUIDialogs . DialogTextEntry ( parent , message ) as dlg :
if dlg . ShowModal ( ) == wx . ID_OK :
content_update_action = HC . CONTENT_UPDATE_PETITION
rows = [ ( dlg . GetValue ( ) , tag , hashes ) ]
else :
return True
else :
return True
content_updates = [ HydrusData . ContentUpdate ( HC . CONTENT_TYPE_MAPPINGS , content_update_action , row ) for row in rows ]
elif service_type in ( HC . LOCAL_RATING_LIKE , HC . LOCAL_RATING_NUMERICAL ) :
rating = value
can_set = False
can_unset = False
for m in media :
ratings_manager = m . GetRatingsManager ( )
current_rating = ratings_manager . GetRating ( service_key )
if current_rating == rating and action == HC . CONTENT_UPDATE_FLIP :
can_unset = True
else :
can_set = True
if can_set :
row = ( rating , hashes )
elif can_unset :
row = ( None , hashes )
else :
return True
content_updates = [ HydrusData . ContentUpdate ( HC . CONTENT_TYPE_RATINGS , HC . CONTENT_UPDATE_ADD , row ) ]
else :
return False
HG . client_controller . Write ( ' content_updates ' , { service_key : content_updates } )
return True
2017-09-06 20:18:20 +00:00
def GetFocusTLP ( ) :
2017-04-05 21:16:40 +00:00
focus = wx . Window . FindFocus ( )
2017-09-06 20:18:20 +00:00
return GetTLP ( focus )
def GetTLP ( window ) :
if window is None :
2017-04-05 21:16:40 +00:00
2017-09-06 20:18:20 +00:00
return None
2017-04-05 21:16:40 +00:00
2017-09-06 20:18:20 +00:00
elif isinstance ( window , wx . TopLevelWindow ) :
return window
else :
return window . GetTopLevelParent ( )
2017-04-05 21:16:40 +00:00
2017-04-19 20:58:30 +00:00
2017-11-22 21:03:07 +00:00
def GetTLPParents ( window ) :
if not isinstance ( window , wx . TopLevelWindow ) :
window = GetTLP ( window )
parents = [ ]
parent = window . GetParent ( )
while parent is not None :
parents . append ( parent )
parent = parent . GetParent ( )
return parents
2017-11-29 21:48:23 +00:00
def GetXYTopTLP ( screen_position ) :
2017-11-22 21:03:07 +00:00
tlps = wx . GetTopLevelWindows ( )
2017-11-29 21:48:23 +00:00
hittest_tlps = [ tlp for tlp in tlps if tlp . HitTest ( tlp . ScreenToClient ( screen_position ) ) == wx . HT_WINDOW_INSIDE and tlp . IsShown ( ) ]
2017-11-22 21:03:07 +00:00
if len ( hittest_tlps ) == 0 :
return None
most_childish = hittest_tlps [ 0 ]
for tlp in hittest_tlps [ 1 : ] :
if most_childish in GetTLPParents ( tlp ) :
most_childish = tlp
return most_childish
2018-01-03 22:37:30 +00:00
def IsWXAncestor ( child , ancestor , through_tlws = False ) :
2017-04-19 20:58:30 +00:00
2017-09-06 20:18:20 +00:00
parent = child
2017-04-19 20:58:30 +00:00
2018-01-03 22:37:30 +00:00
if through_tlws :
2017-04-05 21:16:40 +00:00
2018-01-03 22:37:30 +00:00
while not parent is None :
2017-04-05 21:16:40 +00:00
2018-01-03 22:37:30 +00:00
if parent == ancestor :
return True
parent = parent . GetParent ( )
2017-04-05 21:16:40 +00:00
2018-01-03 22:37:30 +00:00
else :
while not isinstance ( parent , wx . TopLevelWindow ) :
if parent == ancestor :
return True
parent = parent . GetParent ( )
2017-04-19 20:58:30 +00:00
2017-04-05 21:16:40 +00:00
return False
2017-09-06 20:18:20 +00:00
def NotebookScreenToHitTest ( notebook , screen_position ) :
2017-04-19 20:58:30 +00:00
2017-09-06 20:18:20 +00:00
if HC . PLATFORM_OSX :
2017-04-05 21:16:40 +00:00
2017-09-06 20:18:20 +00:00
# OS X has some unusual coordinates for its notebooks
# the notebook tabs are not considered to be in the client area (they are actually negative on getscreenposition())
# its hittest works on window coords, not client coords
# hence to get hittest position, we get our parent's client position and adjust by our given position in that
2017-04-05 21:16:40 +00:00
2017-09-06 20:18:20 +00:00
# this also seems to cause menus popped on notebooks to spawn high and left, wew
2017-04-05 21:16:40 +00:00
2017-09-06 20:18:20 +00:00
( my_x , my_y ) = notebook . GetPosition ( )
( p_x , p_y ) = notebook . GetParent ( ) . ScreenToClient ( wx . GetMousePosition ( ) )
position = ( p_x - my_x , p_y - my_y )
2017-04-05 21:16:40 +00:00
else :
2017-09-06 20:18:20 +00:00
position = notebook . ScreenToClient ( screen_position )
2017-04-05 21:16:40 +00:00
2017-09-06 20:18:20 +00:00
return notebook . HitTest ( position )
2018-01-10 22:41:51 +00:00
def SetBitmapButtonBitmap ( button , bitmap ) :
# the button's bitmap, retrieved via GetBitmap, is not the same as the one we gave it!
# hence testing bitmap vs that won't work to save time on an update loop, so we'll just save it here custom
# this isn't a big memory deal for our purposes since they are small and mostly if not all from the GlobalBMPs library so shared anyway
if hasattr ( button , ' last_bitmap ' ) :
if button . last_bitmap == bitmap :
return
button . SetBitmap ( bitmap )
button . last_bitmap = bitmap
2017-04-19 20:58:30 +00:00
def TLPHasFocus ( window ) :
focus_tlp = GetFocusTLP ( )
window_tlp = GetTLP ( window )
2017-04-05 21:16:40 +00:00
return window_tlp == focus_tlp
def WindowHasFocus ( window ) :
focus = wx . Window . FindFocus ( )
if focus is None :
return False
return window == focus
2017-09-06 20:18:20 +00:00
def WindowOrAnyTLPChildHasFocus ( window ) :
2017-04-05 21:16:40 +00:00
2017-09-06 20:18:20 +00:00
focus = wx . Window . FindFocus ( )
2017-04-05 21:16:40 +00:00
2017-09-06 20:18:20 +00:00
while focus is not None :
2017-04-05 21:16:40 +00:00
2017-09-06 20:18:20 +00:00
if focus == window :
2017-04-05 21:16:40 +00:00
return True
2017-09-06 20:18:20 +00:00
focus = focus . GetParent ( )
return False
def WindowOrSameTLPChildHasFocus ( window ) :
focus = wx . Window . FindFocus ( )
while focus is not None :
if focus == window :
return True
if isinstance ( focus , wx . TopLevelWindow ) :
return False
focus = focus . GetParent ( )
2017-04-05 21:16:40 +00:00
return False
2016-08-31 19:55:14 +00:00
def WrapInGrid ( parent , rows , expand_text = False ) :
2018-01-03 22:37:30 +00:00
gridbox = wx . FlexGridSizer ( 2 )
2016-08-31 19:55:14 +00:00
if expand_text :
gridbox . AddGrowableCol ( 0 , 1 )
text_flags = CC . FLAGS_VCENTER_EXPAND_DEPTH_ONLY # Trying to expand both ways nixes the center. This seems to work right.
control_flags = CC . FLAGS_VCENTER
2016-09-07 20:01:05 +00:00
sizer_flags = CC . FLAGS_SIZER_VCENTER
2016-08-31 19:55:14 +00:00
else :
gridbox . AddGrowableCol ( 1 , 1 )
text_flags = CC . FLAGS_VCENTER
control_flags = CC . FLAGS_EXPAND_BOTH_WAYS
2016-09-07 20:01:05 +00:00
sizer_flags = CC . FLAGS_EXPAND_SIZER_BOTH_WAYS
2016-08-31 19:55:14 +00:00
for ( text , control ) in rows :
2016-09-07 20:01:05 +00:00
if isinstance ( control , wx . Sizer ) :
cflags = sizer_flags
else :
cflags = control_flags
2017-04-19 20:58:30 +00:00
st = BetterStaticText ( parent , text )
2018-01-03 22:37:30 +00:00
gridbox . Add ( st , text_flags )
gridbox . Add ( control , cflags )
2016-08-31 19:55:14 +00:00
return gridbox
2018-02-28 22:30:36 +00:00
def WrapInText ( control , parent , text , colour = None ) :
2016-08-17 20:07:22 +00:00
hbox = wx . BoxSizer ( wx . HORIZONTAL )
2017-04-19 20:58:30 +00:00
st = BetterStaticText ( parent , text )
2018-02-28 22:30:36 +00:00
if colour is not None :
st . SetForegroundColour ( colour )
2018-01-03 22:37:30 +00:00
hbox . Add ( st , CC . FLAGS_VCENTER )
hbox . Add ( control , CC . FLAGS_EXPAND_BOTH_WAYS )
2016-08-17 20:07:22 +00:00
return hbox
2017-01-18 22:52:39 +00:00
class BetterBitmapButton ( wx . BitmapButton ) :
2017-01-25 22:56:55 +00:00
def __init__ ( self , parent , bitmap , func , * args , * * kwargs ) :
2017-01-18 22:52:39 +00:00
wx . BitmapButton . __init__ ( self , parent , bitmap = bitmap )
2017-01-25 22:56:55 +00:00
self . _func = func
2017-01-18 22:52:39 +00:00
self . _args = args
self . _kwargs = kwargs
self . Bind ( wx . EVT_BUTTON , self . EventButton )
def EventButton ( self , event ) :
2017-01-25 22:56:55 +00:00
self . _func ( * self . _args , * * self . _kwargs )
2017-01-18 22:52:39 +00:00
2016-10-19 20:02:56 +00:00
class BetterButton ( wx . Button ) :
2017-01-25 22:56:55 +00:00
def __init__ ( self , parent , label , func , * args , * * kwargs ) :
2016-10-19 20:02:56 +00:00
2017-04-19 20:58:30 +00:00
wx . Button . __init__ ( self , parent , style = wx . BU_EXACTFIT )
self . SetLabelText ( label )
2016-10-19 20:02:56 +00:00
2017-01-25 22:56:55 +00:00
self . _func = func
2016-12-07 22:12:52 +00:00
self . _args = args
self . _kwargs = kwargs
2016-10-19 20:02:56 +00:00
self . Bind ( wx . EVT_BUTTON , self . EventButton )
def EventButton ( self , event ) :
2017-01-25 22:56:55 +00:00
self . _func ( * self . _args , * * self . _kwargs )
2016-10-19 20:02:56 +00:00
2017-05-31 21:50:53 +00:00
class BetterCheckListBox ( wx . CheckListBox ) :
def GetChecked ( self ) :
result = [ self . GetClientData ( index ) for index in wx . CheckListBox . GetChecked ( self ) ]
return result
2016-10-19 20:02:56 +00:00
class BetterChoice ( wx . Choice ) :
2017-10-11 17:38:14 +00:00
def Append ( self , display_string , client_data ) :
wx . Choice . Append ( self , display_string , client_data )
if self . GetCount ( ) == 1 :
self . Select ( 0 )
2016-10-19 20:02:56 +00:00
def GetChoice ( self ) :
selection = self . GetSelection ( )
if selection != wx . NOT_FOUND : return self . GetClientData ( selection )
2016-11-09 23:13:22 +00:00
elif self . GetCount ( ) > 0 : return self . GetClientData ( 0 )
else : return None
2016-10-19 20:02:56 +00:00
def SelectClientData ( self , client_data ) :
for i in range ( self . GetCount ( ) ) :
if client_data == self . GetClientData ( i ) :
self . Select ( i )
return
2016-11-09 23:13:22 +00:00
if self . GetCount ( ) > 0 :
self . Select ( 0 )
2016-10-19 20:02:56 +00:00
2017-01-04 22:48:23 +00:00
class BetterRadioBox ( wx . RadioBox ) :
def __init__ ( self , * args , * * kwargs ) :
self . _indices_to_data = { i : data for ( i , ( s , data ) ) in enumerate ( kwargs [ ' choices ' ] ) }
kwargs [ ' choices ' ] = [ s for ( s , data ) in kwargs [ ' choices ' ] ]
wx . RadioBox . __init__ ( self , * args , * * kwargs )
def GetChoice ( self ) :
index = self . GetSelection ( )
return self . _indices_to_data [ index ]
2017-04-19 20:58:30 +00:00
class BetterStaticText ( wx . StaticText ) :
2017-04-26 21:58:12 +00:00
def __init__ ( self , parent , label = None , * * kwargs ) :
2017-04-19 20:58:30 +00:00
2017-04-26 21:58:12 +00:00
wx . StaticText . __init__ ( self , parent , * * kwargs )
2017-04-19 20:58:30 +00:00
if label is not None :
# to escape mnemonic '&' swallowing
self . SetLabelText ( label )
# at some point, rewrite this to be a control that'll produce a custom geteffectiveminsize and use wx.lib.wordwrap to dc draw the text
# st.Wrap is a pain to deal with here, seems to sometimes/always not be able to increase after an initial non-zero call
2017-07-12 20:03:45 +00:00
def SetLabelText ( self , text ) :
if text != self . GetLabelText ( ) :
wx . StaticText . SetLabelText ( self , text )
2013-03-15 02:38:12 +00:00
class BufferedWindow ( wx . Window ) :
def __init__ ( self , * args , * * kwargs ) :
wx . Window . __init__ ( self , * args , * * kwargs )
if ' size ' in kwargs :
( x , y ) = kwargs [ ' size ' ]
2018-01-03 22:37:30 +00:00
self . _canvas_bmp = wx . Bitmap ( x , y , 24 )
2013-03-15 02:38:12 +00:00
2015-11-18 22:44:07 +00:00
else :
2018-01-03 22:37:30 +00:00
self . _canvas_bmp = wx . Bitmap ( 20 , 20 , 24 )
2015-11-18 22:44:07 +00:00
self . _dirty = True
2013-03-15 02:38:12 +00:00
self . Bind ( wx . EVT_PAINT , self . EventPaint )
self . Bind ( wx . EVT_SIZE , self . EventResize )
2015-02-25 19:34:30 +00:00
self . Bind ( wx . EVT_ERASE_BACKGROUND , self . EventEraseBackground )
2013-03-15 02:38:12 +00:00
2015-11-18 22:44:07 +00:00
def _Draw ( self , dc ) :
raise NotImplementedError ( )
2013-03-15 02:38:12 +00:00
2015-02-25 19:34:30 +00:00
def EventEraseBackground ( self , event ) : pass
2015-11-18 22:44:07 +00:00
def EventPaint ( self , event ) :
dc = wx . BufferedPaintDC ( self , self . _canvas_bmp )
if self . _dirty :
self . _Draw ( dc )
2013-03-15 02:38:12 +00:00
def EventResize ( self , event ) :
( my_width , my_height ) = self . GetClientSize ( )
( current_bmp_width , current_bmp_height ) = self . _canvas_bmp . GetSize ( )
2015-11-18 22:44:07 +00:00
if my_width != current_bmp_width or my_height != current_bmp_height :
2018-01-03 22:37:30 +00:00
self . _canvas_bmp = wx . Bitmap ( my_width , my_height , 24 )
2015-11-18 22:44:07 +00:00
self . _dirty = True
2015-12-02 22:32:18 +00:00
self . Refresh ( )
2013-03-15 02:38:12 +00:00
2015-05-13 20:22:39 +00:00
class BufferedWindowIcon ( BufferedWindow ) :
def __init__ ( self , parent , bmp ) :
BufferedWindow . __init__ ( self , parent , size = bmp . GetSize ( ) )
self . _bmp = bmp
2015-11-18 22:44:07 +00:00
def _Draw ( self , dc ) :
2015-05-13 20:22:39 +00:00
background_colour = self . GetParent ( ) . GetBackgroundColour ( )
dc . SetBackground ( wx . Brush ( background_colour ) )
dc . Clear ( )
2015-11-18 22:44:07 +00:00
dc . DrawBitmap ( self . _bmp , 0 , 0 )
self . _dirty = False
2015-05-13 20:22:39 +00:00
2018-01-03 22:37:30 +00:00
class CheckboxCollect ( wx . ComboCtrl ) :
2013-03-15 02:38:12 +00:00
2013-04-03 20:56:07 +00:00
def __init__ ( self , parent , page_key = None ) :
2013-03-15 02:38:12 +00:00
2018-01-03 22:37:30 +00:00
wx . ComboCtrl . __init__ ( self , parent , style = wx . CB_READONLY )
2013-03-15 02:38:12 +00:00
self . _page_key = page_key
2017-08-09 21:33:51 +00:00
self . _collect_by = HC . options [ ' default_collect ' ]
popup = self . _Popup ( self . _collect_by )
2013-03-15 02:38:12 +00:00
#self.UseAltPopupWindow( True )
self . SetPopupControl ( popup )
2017-08-09 21:33:51 +00:00
self . SetValue ( ' no collections ' )
2017-05-24 20:28:24 +00:00
def GetChoice ( self ) :
2013-12-04 22:44:16 +00:00
2017-05-24 20:28:24 +00:00
return self . _collect_by
2013-12-04 22:44:16 +00:00
2013-03-15 02:38:12 +00:00
2017-05-24 20:28:24 +00:00
def SetCollectTypes ( self , collect_by , description ) :
2013-03-15 02:38:12 +00:00
2017-05-24 20:28:24 +00:00
self . _collect_by = collect_by
self . SetValue ( description )
2013-03-15 02:38:12 +00:00
2017-05-10 21:33:58 +00:00
HG . client_controller . pub ( ' collect_media ' , self . _page_key , self . _collect_by )
2013-03-15 02:38:12 +00:00
2018-01-03 22:37:30 +00:00
class _Popup ( wx . ComboPopup ) :
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
def __init__ ( self , collect_by ) :
2013-03-15 02:38:12 +00:00
2018-01-03 22:37:30 +00:00
wx . ComboPopup . __init__ ( self )
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
self . _initial_collect_by = collect_by
2018-01-10 22:41:51 +00:00
self . _control = None
2013-03-15 02:38:12 +00:00
2013-03-23 17:57:29 +00:00
def Create ( self , parent ) :
2018-01-03 22:37:30 +00:00
self . _control = self . _Control ( parent , self . GetComboCtrl ( ) , self . _initial_collect_by )
2013-03-23 17:57:29 +00:00
return True
2013-03-15 02:38:12 +00:00
2013-03-23 17:57:29 +00:00
def GetAdjustedSize ( self , preferred_width , preferred_height , max_height ) :
return ( ( preferred_width , - 1 ) )
2013-03-15 02:38:12 +00:00
2017-05-24 20:28:24 +00:00
def GetControl ( self ) :
return self . _control
2013-03-15 02:38:12 +00:00
2018-01-10 22:41:51 +00:00
def GetStringValue ( self ) :
# this is an abstract method that provides the strin to put in the comboctrl
# I've never used/needed it, but one user reported getting the NotImplemented thing by repeatedly clicking, so let's add it anyway
if self . _control is None :
return ' initialising '
else :
return self . _control . GetDescription ( )
2013-03-23 17:57:29 +00:00
class _Control ( wx . CheckListBox ) :
2017-08-09 21:33:51 +00:00
def __init__ ( self , parent , special_parent , collect_by ) :
2017-05-24 20:28:24 +00:00
text_and_data_tuples = set ( )
sort_by = HC . options [ ' sort_by ' ]
for ( sort_by_type , namespaces ) in sort_by :
text_and_data_tuples . update ( namespaces )
text_and_data_tuples = list ( [ ( namespace , ( ' namespace ' , namespace ) ) for namespace in text_and_data_tuples ] )
text_and_data_tuples . sort ( )
2017-06-28 20:23:21 +00:00
ratings_services = HG . client_controller . services_manager . GetServices ( ( HC . LOCAL_RATING_LIKE , HC . LOCAL_RATING_NUMERICAL ) )
2013-04-03 20:56:07 +00:00
2017-05-24 20:28:24 +00:00
for ratings_service in ratings_services :
text_and_data_tuples . append ( ( ratings_service . GetName ( ) , ( ' rating ' , ratings_service . GetServiceKey ( ) ) ) )
texts = [ text for ( text , data ) in text_and_data_tuples ] # we do this so it sizes its height properly on init
2013-04-03 20:56:07 +00:00
wx . CheckListBox . __init__ ( self , parent , choices = texts )
2013-03-23 17:57:29 +00:00
2013-04-03 20:56:07 +00:00
self . Clear ( )
2017-05-24 20:28:24 +00:00
for ( text , data ) in text_and_data_tuples :
self . Append ( text , data )
2013-03-23 17:57:29 +00:00
self . _special_parent = special_parent
2017-05-24 20:28:24 +00:00
self . Bind ( wx . EVT_CHECKLISTBOX , self . EventChanged )
self . Bind ( wx . EVT_LEFT_DOWN , self . EventLeftDown )
2017-08-09 21:33:51 +00:00
wx . CallAfter ( self . SetValue , collect_by )
2017-05-24 20:28:24 +00:00
def _BroadcastCollect ( self ) :
( collect_by , description ) = self . _GetValues ( )
self . _special_parent . SetCollectTypes ( collect_by , description )
def _GetValues ( self ) :
collect_by = [ ]
for index in self . GetChecked ( ) :
2013-09-04 16:48:44 +00:00
2017-05-24 20:28:24 +00:00
collect_by . append ( self . GetClientData ( index ) )
2013-09-04 16:48:44 +00:00
2017-05-24 20:28:24 +00:00
collect_by_strings = self . GetCheckedStrings ( )
if len ( collect_by ) > 0 :
2013-09-04 16:48:44 +00:00
2017-05-24 20:28:24 +00:00
description = ' collect by ' + ' - ' . join ( collect_by_strings )
else :
description = ' no collections '
2013-09-04 16:48:44 +00:00
2013-03-23 17:57:29 +00:00
2017-05-24 20:28:24 +00:00
return ( collect_by , description )
2013-03-23 17:57:29 +00:00
# as inspired by http://trac.wxwidgets.org/attachment/ticket/14413/test_clb_workaround.py
# what a clusterfuck
def EventLeftDown ( self , event ) :
index = self . HitTest ( event . GetPosition ( ) )
if index != wx . NOT_FOUND :
self . Check ( index , not self . IsChecked ( index ) )
self . EventChanged ( event )
event . Skip ( )
def EventChanged ( self , event ) :
2017-05-24 20:28:24 +00:00
self . _BroadcastCollect ( )
2013-12-04 22:44:16 +00:00
2018-01-10 22:41:51 +00:00
def GetDescription ( self ) :
( collect_by , description ) = self . _GetValues ( )
return description
2017-05-24 20:28:24 +00:00
def SetValue ( self , collect_by ) :
2013-12-04 22:44:16 +00:00
2017-05-24 20:28:24 +00:00
# an old possible value, now collapsed to []
if collect_by is None :
collect_by = [ ]
desired_collect_by_rows = set ( collect_by )
2013-04-03 20:56:07 +00:00
2017-05-24 20:28:24 +00:00
indices_to_check = [ ]
2013-04-03 20:56:07 +00:00
2017-05-24 20:28:24 +00:00
for index in range ( self . GetCount ( ) ) :
if self . GetClientData ( index ) in desired_collect_by_rows :
indices_to_check . append ( index )
2013-03-23 17:57:29 +00:00
2017-08-09 21:33:51 +00:00
if len ( indices_to_check ) > 0 :
self . SetChecked ( indices_to_check )
self . _BroadcastCollect ( )
2013-03-23 17:57:29 +00:00
2013-03-15 02:38:12 +00:00
2017-09-27 21:52:54 +00:00
class CheckboxManager ( object ) :
def GetCurrentValue ( self ) :
raise NotImplementedError ( )
def Invert ( self ) :
raise NotImplementedError ( )
class CheckboxManagerCalls ( CheckboxManager ) :
def __init__ ( self , invert_call , value_call ) :
CheckboxManager . __init__ ( self )
self . _invert_call = invert_call
self . _value_call = value_call
def GetCurrentValue ( self ) :
return self . _value_call ( )
def Invert ( self ) :
self . _invert_call ( )
class CheckboxManagerOptions ( CheckboxManager ) :
def __init__ ( self , boolean_name ) :
CheckboxManager . __init__ ( self )
self . _boolean_name = boolean_name
def GetCurrentValue ( self ) :
2017-12-06 22:06:56 +00:00
new_options = HG . client_controller . new_options
2017-09-27 21:52:54 +00:00
return new_options . GetBoolean ( self . _boolean_name )
def Invert ( self ) :
2017-12-06 22:06:56 +00:00
new_options = HG . client_controller . new_options
2017-09-27 21:52:54 +00:00
new_options . InvertBoolean ( self . _boolean_name )
2017-08-09 21:33:51 +00:00
class ChoiceSort ( wx . Panel ) :
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
def __init__ ( self , parent , management_controller = None ) :
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
wx . Panel . __init__ ( self , parent )
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
self . _management_controller = management_controller
self . _sort_type_choice = BetterChoice ( self )
self . _sort_asc_choice = BetterChoice ( self )
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
asc_width = ClientData . ConvertTextToPixelWidth ( self . _sort_asc_choice , 15 )
2017-05-24 20:28:24 +00:00
2017-08-09 21:33:51 +00:00
self . _sort_asc_choice . SetMinSize ( ( asc_width , - 1 ) )
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
sort_types = ClientData . GetSortTypeChoices ( )
for sort_type in sort_types :
2017-05-24 20:28:24 +00:00
2017-08-09 21:33:51 +00:00
example_sort = ClientMedia . MediaSort ( sort_type , CC . SORT_ASC )
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
self . _sort_type_choice . Append ( example_sort . GetSortTypeString ( ) , sort_type )
type_width = ClientData . ConvertTextToPixelWidth ( self . _sort_type_choice , 10 )
self . _sort_type_choice . SetMinSize ( ( type_width , - 1 ) )
self . _sort_asc_choice . Append ( ' ' , CC . SORT_ASC )
self . _UpdateAscLabels ( )
#
hbox = wx . BoxSizer ( wx . HORIZONTAL )
2018-01-03 22:37:30 +00:00
hbox . Add ( self . _sort_type_choice , CC . FLAGS_EXPAND_BOTH_WAYS )
hbox . Add ( self . _sort_asc_choice , CC . FLAGS_VCENTER )
2017-08-09 21:33:51 +00:00
self . SetSizer ( hbox )
self . _sort_type_choice . Bind ( wx . EVT_CHOICE , self . EventSortTypeChoice )
self . _sort_asc_choice . Bind ( wx . EVT_CHOICE , self . EventSortAscChoice )
HG . client_controller . sub ( self , ' ACollectHappened ' , ' collect_media ' )
2017-10-18 19:41:25 +00:00
HG . client_controller . sub ( self , ' BroadcastSort ' , ' do_page_sort ' )
2017-08-09 21:33:51 +00:00
if self . _management_controller is not None and self . _management_controller . HasVariable ( ' media_sort ' ) :
media_sort = self . _management_controller . GetVariable ( ' media_sort ' )
try :
2014-08-27 22:15:22 +00:00
2017-08-09 21:33:51 +00:00
self . SetSort ( media_sort )
2014-08-27 22:15:22 +00:00
2017-08-09 21:33:51 +00:00
except :
2014-08-27 22:15:22 +00:00
2017-08-09 21:33:51 +00:00
default_sort = ClientMedia . MediaSort ( ( ' system ' , CC . SORT_FILES_BY_FILESIZE ) , CC . SORT_ASC )
2014-08-27 22:15:22 +00:00
2017-08-09 21:33:51 +00:00
self . SetSort ( default_sort )
2014-08-27 22:15:22 +00:00
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
def _BroadcastSort ( self ) :
media_sort = self . _GetCurrentSort ( )
if self . _management_controller is not None :
self . _management_controller . SetVariable ( ' media_sort ' , media_sort )
page_key = self . _management_controller . GetKey ( ' page ' )
HG . client_controller . pub ( ' sort_media ' , page_key , media_sort )
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
def _GetCurrentSort ( self ) :
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
sort_type = self . _sort_type_choice . GetChoice ( )
sort_asc = self . _sort_asc_choice . GetChoice ( )
media_sort = ClientMedia . MediaSort ( sort_type , sort_asc )
return media_sort
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
def _UpdateAscLabels ( self ) :
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
media_sort = self . _GetCurrentSort ( )
self . _sort_asc_choice . Clear ( )
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
if media_sort . CanAsc ( ) :
( asc_str , desc_str ) = media_sort . GetSortAscStrings ( )
self . _sort_asc_choice . Append ( asc_str , CC . SORT_ASC )
self . _sort_asc_choice . Append ( desc_str , CC . SORT_DESC )
self . _sort_asc_choice . SelectClientData ( media_sort . sort_asc )
self . _sort_asc_choice . Enable ( )
else :
self . _sort_asc_choice . Append ( ' ' , CC . SORT_ASC )
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
self . _sort_asc_choice . SelectClientData ( CC . SORT_ASC )
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
self . _sort_asc_choice . Disable ( )
2013-03-15 02:38:12 +00:00
def ACollectHappened ( self , page_key , collect_by ) :
2017-08-09 21:33:51 +00:00
if self . _management_controller is not None :
2017-05-24 20:28:24 +00:00
2017-08-09 21:33:51 +00:00
my_page_key = self . _management_controller . GetKey ( ' page ' )
if page_key == my_page_key :
self . _BroadcastSort ( )
2017-05-24 20:28:24 +00:00
2017-10-18 19:41:25 +00:00
def BroadcastSort ( self , page_key = None ) :
if page_key is not None and page_key != self . _management_controller . GetKey ( ' page ' ) :
return
2017-05-24 20:28:24 +00:00
self . _BroadcastSort ( )
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
def EventSortAscChoice ( self , event ) :
2013-03-15 02:38:12 +00:00
2017-08-09 21:33:51 +00:00
self . _BroadcastSort ( )
def EventSortTypeChoice ( self , event ) :
self . _UpdateAscLabels ( )
self . _BroadcastSort ( )
def GetSort ( self ) :
return self . _GetCurrentSort ( )
def SetSort ( self , media_sort ) :
self . _sort_type_choice . SelectClientData ( media_sort . sort_type )
self . _sort_asc_choice . SelectClientData ( media_sort . sort_asc )
self . _UpdateAscLabels ( )
2013-03-15 02:38:12 +00:00
2018-03-07 22:48:29 +00:00
class AlphaColourControl ( wx . Panel ) :
def __init__ ( self , parent ) :
wx . Panel . __init__ ( self , parent )
self . _colour_picker = wx . ColourPickerCtrl ( self )
self . _alpha_selector = wx . SpinCtrl ( self , min = 0 , max = 255 )
hbox = wx . BoxSizer ( wx . HORIZONTAL )
hbox . Add ( self . _colour_picker , CC . FLAGS_VCENTER )
hbox . Add ( BetterStaticText ( self , ' alpha: ' ) , CC . FLAGS_VCENTER )
hbox . Add ( self . _alpha_selector , CC . FLAGS_VCENTER )
self . SetSizer ( hbox )
def GetValue ( self ) :
colour = self . _colour_picker . GetColour ( )
( r , g , b , a ) = colour . Get ( ) # no alpha support here, so it'll be 255
a = self . _alpha_selector . GetValue ( )
colour = wx . Colour ( r , g , b , a )
return colour
def SetValue ( self , colour ) :
( r , g , b , a ) = colour . Get ( )
picker_colour = wx . Colour ( r , g , b )
self . _colour_picker . SetColour ( picker_colour )
self . _alpha_selector . SetValue ( a )
2017-08-30 20:27:47 +00:00
class ExportPatternButton ( BetterButton ) :
2014-02-26 22:09:54 +00:00
def __init__ ( self , parent ) :
2017-08-30 20:27:47 +00:00
BetterButton . __init__ ( self , parent , ' pattern shortcuts ' , self . _Hit )
2014-02-26 22:09:54 +00:00
2017-08-30 20:27:47 +00:00
def _Hit ( self ) :
2014-02-26 22:09:54 +00:00
menu = wx . Menu ( )
2017-08-30 20:27:47 +00:00
ClientGUIMenus . AppendMenuLabel ( menu , ' click on a phrase to copy to clipboard ' )
2014-02-26 22:09:54 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus . AppendSeparator ( menu )
2014-02-26 22:09:54 +00:00
2017-08-30 20:27:47 +00:00
ClientGUIMenus . AppendMenuItem ( self , menu , ' the file \' s hash - {hash} ' , ' copy " {hash} " to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , ' {hash} ' )
ClientGUIMenus . AppendMenuItem ( self , menu , ' all the file \' s tags - {tags} ' , ' copy " {tags} " to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , ' {tags} ' )
ClientGUIMenus . AppendMenuItem ( self , menu , ' all the file \' s non-namespaced tags - { nn tags} ' , ' copy " { nn tags} " to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , ' { nn tags} ' )
2014-02-26 22:09:54 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus . AppendSeparator ( menu )
2014-02-26 22:09:54 +00:00
2017-08-30 20:27:47 +00:00
ClientGUIMenus . AppendMenuItem ( self , menu , u ' all instances of a particular namespace - [ \u2026 ] ' , u ' copy " [ \u2026 ] " to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , u ' [ \u2026 ] ' )
2014-02-26 22:09:54 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus . AppendSeparator ( menu )
2014-02-26 22:09:54 +00:00
2017-08-30 20:27:47 +00:00
ClientGUIMenus . AppendMenuItem ( self , menu , u ' a particular tag, if the file has it - ( \u2026 ) ' , u ' copy " ( \u2026 ) " to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , u ' ( \u2026 ) ' )
2014-02-26 22:09:54 +00:00
2017-05-10 21:33:58 +00:00
HG . client_controller . PopupMenu ( self , menu )
2014-02-26 22:09:54 +00:00
2014-04-16 20:31:59 +00:00
class FitResistantStaticText ( wx . StaticText ) :
2014-04-23 20:56:12 +00:00
# this is a huge damn mess! I think I really need to be doing this inside or before the parent's fit, or something
def __init__ ( self , * args , * * kwargs ) :
wx . StaticText . __init__ ( self , * args , * * kwargs )
self . _wrap = 380
if ' label ' in kwargs : self . _last_label = kwargs [ ' label ' ]
else : self . _last_label = ' '
2014-04-16 20:31:59 +00:00
def Wrap ( self , width ) :
2014-04-23 20:56:12 +00:00
self . _wrap = width
wx . StaticText . Wrap ( self , self . _wrap )
2014-04-16 20:31:59 +00:00
( x , y ) = self . GetSize ( )
2014-04-23 20:56:12 +00:00
if x > self . _wrap : x = self . _wrap
if x < 150 : x = 150
2014-04-16 20:31:59 +00:00
self . SetMinSize ( ( x , y ) )
2014-04-23 20:56:12 +00:00
self . SetMaxSize ( ( self . _wrap , - 1 ) )
2016-03-23 19:42:56 +00:00
def SetLabelText ( self , label ) :
2014-04-23 20:56:12 +00:00
if label != self . _last_label :
self . _last_label = label
2016-03-23 19:42:56 +00:00
wx . StaticText . SetLabelText ( self , label )
2014-04-23 20:56:12 +00:00
self . Wrap ( self . _wrap )
2014-04-16 20:31:59 +00:00
2013-03-15 02:38:12 +00:00
class Gauge ( wx . Gauge ) :
def __init__ ( self , * args , * * kwargs ) :
wx . Gauge . __init__ ( self , * args , * * kwargs )
2017-07-12 20:03:45 +00:00
self . _actual_range = None
self . _is_pulsing = False
2013-03-15 02:38:12 +00:00
2017-07-12 20:03:45 +00:00
def SetRange ( self , range ) :
2013-03-15 02:38:12 +00:00
2017-07-12 20:03:45 +00:00
if range is None :
2017-01-25 22:56:55 +00:00
self . Pulse ( )
2017-07-12 20:03:45 +00:00
self . _is_pulsing = True
2013-03-15 02:38:12 +00:00
else :
2017-07-12 20:48:21 +00:00
if self . _is_pulsing :
self . StopPulsing ( )
2017-07-12 20:03:45 +00:00
if range > 1000 :
self . _actual_range = range
range = 1000
else :
self . _actual_range = None
if range != self . GetRange ( ) :
wx . Gauge . SetRange ( self , range )
2013-03-15 02:38:12 +00:00
def SetValue ( self , value ) :
2017-07-12 20:48:21 +00:00
if not self . _is_pulsing :
2017-01-25 22:56:55 +00:00
2017-07-12 20:48:21 +00:00
if value is None :
2017-07-12 20:03:45 +00:00
2017-07-12 20:48:21 +00:00
self . Pulse ( )
2017-07-12 20:03:45 +00:00
2017-07-12 20:48:21 +00:00
self . _is_pulsing = True
else :
if self . _actual_range is not None :
value = min ( int ( 1000 * ( float ( value ) / self . _actual_range ) ) , 1000 )
2017-07-12 20:03:45 +00:00
2017-08-09 21:33:51 +00:00
value = min ( value , self . GetRange ( ) )
2017-07-12 20:48:21 +00:00
if value != self . GetValue ( ) :
wx . Gauge . SetValue ( self , value )
2017-07-12 20:03:45 +00:00
2017-01-25 22:56:55 +00:00
2013-03-15 02:38:12 +00:00
2017-07-12 20:48:21 +00:00
def StopPulsing ( self ) :
self . _is_pulsing = False
self . SetRange ( 1 )
self . SetValue ( 1 )
self . SetValue ( 0 )
2013-03-15 02:38:12 +00:00
class ListBook ( wx . Panel ) :
def __init__ ( self , * args , * * kwargs ) :
wx . Panel . __init__ ( self , * args , * * kwargs )
2016-08-10 19:04:08 +00:00
self . SetBackgroundColour ( wx . SystemSettings . GetColour ( wx . SYS_COLOUR_FRAMEBK ) )
2013-03-15 02:38:12 +00:00
2016-05-18 20:07:14 +00:00
self . _keys_to_active_pages = { }
self . _keys_to_proto_pages = { }
2015-05-06 20:26:18 +00:00
2016-05-25 21:54:03 +00:00
# Don't use LB_SORT! Linux can't handle clientdata that jumps around!
self . _list_box = wx . ListBox ( self , style = wx . LB_SINGLE )
2013-03-15 02:38:12 +00:00
self . _empty_panel = wx . Panel ( self )
2016-08-10 19:04:08 +00:00
self . _empty_panel . SetBackgroundColour ( wx . SystemSettings . GetColour ( wx . SYS_COLOUR_FRAMEBK ) )
2013-03-15 02:38:12 +00:00
2016-05-18 20:07:14 +00:00
self . _current_key = None
2013-03-15 02:38:12 +00:00
self . _current_panel = self . _empty_panel
self . _panel_sizer = wx . BoxSizer ( wx . VERTICAL )
2018-01-03 22:37:30 +00:00
self . _panel_sizer . Add ( self . _empty_panel , CC . FLAGS_EXPAND_BOTH_WAYS )
2013-03-15 02:38:12 +00:00
hbox = wx . BoxSizer ( wx . HORIZONTAL )
2018-01-03 22:37:30 +00:00
hbox . Add ( self . _list_box , CC . FLAGS_EXPAND_PERPENDICULAR )
hbox . Add ( self . _panel_sizer , CC . FLAGS_EXPAND_SIZER_BOTH_WAYS )
2013-03-15 02:38:12 +00:00
self . _list_box . Bind ( wx . EVT_LISTBOX , self . EventSelection )
self . SetSizer ( hbox )
2016-05-18 20:07:14 +00:00
def _ActivatePage ( self , key ) :
( classname , args , kwargs ) = self . _keys_to_proto_pages [ key ]
page = classname ( * args , * * kwargs )
page . Hide ( )
2018-01-03 22:37:30 +00:00
self . _panel_sizer . Add ( page , CC . FLAGS_EXPAND_SIZER_BOTH_WAYS )
2016-05-18 20:07:14 +00:00
self . _keys_to_active_pages [ key ] = page
del self . _keys_to_proto_pages [ key ]
2016-07-06 21:13:15 +00:00
self . _panel_sizer . CalcMin ( )
2016-05-18 20:07:14 +00:00
self . _RecalcListBoxWidth ( )
2013-12-18 22:49:24 +00:00
2016-05-18 20:07:14 +00:00
def _GetIndex ( self , key ) :
for i in range ( self . _list_box . GetCount ( ) ) :
2013-12-18 22:49:24 +00:00
2016-05-18 20:07:14 +00:00
i_key = self . _list_box . GetClientData ( i )
if i_key == key :
2013-12-18 22:49:24 +00:00
2016-05-18 20:07:14 +00:00
return i
2013-12-18 22:49:24 +00:00
2016-05-18 20:07:14 +00:00
return wx . NOT_FOUND
2013-12-18 22:49:24 +00:00
2016-07-06 21:13:15 +00:00
def _RecalcListBoxWidth ( self ) :
self . Layout ( )
2013-03-15 02:38:12 +00:00
def _Select ( self , selection ) :
2016-05-18 20:07:14 +00:00
if selection == wx . NOT_FOUND :
self . _current_key = None
else :
self . _current_key = self . _list_box . GetClientData ( selection )
2013-03-23 17:57:29 +00:00
self . _current_panel . Hide ( )
self . _list_box . SetSelection ( selection )
2016-05-18 20:07:14 +00:00
if selection == wx . NOT_FOUND :
self . _current_panel = self . _empty_panel
2013-03-23 17:57:29 +00:00
else :
2013-03-15 02:38:12 +00:00
2016-05-18 20:07:14 +00:00
if self . _current_key in self . _keys_to_proto_pages :
2013-03-23 17:57:29 +00:00
2016-05-18 20:07:14 +00:00
self . _ActivatePage ( self . _current_key )
2013-03-15 02:38:12 +00:00
2016-05-18 20:07:14 +00:00
self . _current_panel = self . _keys_to_active_pages [ self . _current_key ]
2013-03-23 17:57:29 +00:00
2013-03-15 02:38:12 +00:00
self . _current_panel . Show ( )
self . Layout ( )
2013-09-11 21:28:19 +00:00
self . Refresh ( )
2016-11-30 20:24:17 +00:00
# this tells any parent scrolled panel to update its virtualsize and recalc its scrollbars
event = wx . NotifyEvent ( wx . wxEVT_SIZE , self . GetId ( ) )
2016-07-06 21:13:15 +00:00
2018-02-21 21:59:37 +00:00
wx . QueueEvent ( self . GetEventHandler ( ) , event )
2016-07-06 21:13:15 +00:00
2016-11-30 20:24:17 +00:00
# now the virtualsize is updated, we now tell any parent resizing frame/dialog that is interested in resizing that now is the time
2017-05-24 20:28:24 +00:00
ClientGUITopLevelWindows . PostSizeChangedEvent ( self )
2016-07-06 21:13:15 +00:00
2013-03-15 02:38:12 +00:00
event = wx . NotifyEvent ( wx . wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED , - 1 )
2018-02-21 21:59:37 +00:00
wx . QueueEvent ( self . GetEventHandler ( ) , event )
2013-03-15 02:38:12 +00:00
2016-05-18 20:07:14 +00:00
def AddPage ( self , display_name , key , page , select = False ) :
if self . _GetIndex ( key ) != wx . NOT_FOUND :
raise HydrusExceptions . NameException ( ' That entry already exists! ' )
2013-03-15 02:38:12 +00:00
2016-01-13 22:08:19 +00:00
if not isinstance ( page , tuple ) :
2013-03-15 02:38:12 +00:00
page . Hide ( )
2018-01-03 22:37:30 +00:00
self . _panel_sizer . Add ( page , CC . FLAGS_EXPAND_SIZER_BOTH_WAYS )
2013-03-15 02:38:12 +00:00
2013-02-19 00:11:43 +00:00
2016-05-25 21:54:03 +00:00
# Can't do LB_SORT because of Linux not being able to track clientdata, have to do it manually.
current_display_names = self . _list_box . GetStrings ( )
insertion_index = len ( current_display_names )
for ( i , current_display_name ) in enumerate ( current_display_names ) :
2017-02-01 21:11:17 +00:00
if current_display_name > display_name :
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
insertion_index = i
2016-02-17 22:06:47 +00:00
2017-02-01 21:11:17 +00:00
break
2016-01-06 21:17:20 +00:00
2014-08-13 22:18:12 +00:00
2017-02-01 21:11:17 +00:00
self . _list_box . Insert ( display_name , insertion_index , key )
self . _keys_to_active_pages [ key ] = page
self . _RecalcListBoxWidth ( )
if self . _list_box . GetCount ( ) == 1 :
2016-04-27 19:20:37 +00:00
2017-02-01 21:11:17 +00:00
self . _Select ( 0 )
elif select :
index = self . _GetIndex ( key )
self . _Select ( index )
2016-04-27 19:20:37 +00:00
2014-02-26 22:09:54 +00:00
2017-02-01 21:11:17 +00:00
def AddPageArgs ( self , display_name , key , classname , args , kwargs ) :
2013-07-24 20:26:00 +00:00
2017-02-01 21:11:17 +00:00
if self . _GetIndex ( key ) != wx . NOT_FOUND :
raise HydrusExceptions . NameException ( ' That entry already exists! ' )
2013-08-14 20:21:49 +00:00
2017-02-01 21:11:17 +00:00
# Can't do LB_SORT because of Linux not being able to track clientdata, have to do it manually.
2013-08-14 20:21:49 +00:00
2017-02-01 21:11:17 +00:00
current_display_names = self . _list_box . GetStrings ( )
2013-08-14 20:21:49 +00:00
2017-02-01 21:11:17 +00:00
insertion_index = len ( current_display_names )
for ( i , current_display_name ) in enumerate ( current_display_names ) :
if current_display_name > display_name :
insertion_index = i
break
2013-07-24 20:26:00 +00:00
2017-02-01 21:11:17 +00:00
self . _list_box . Insert ( display_name , insertion_index , key )
2013-07-24 20:26:00 +00:00
2017-02-01 21:11:17 +00:00
self . _keys_to_proto_pages [ key ] = ( classname , args , kwargs )
2014-02-26 22:09:54 +00:00
2017-02-01 21:11:17 +00:00
self . _RecalcListBoxWidth ( )
2014-02-26 22:09:54 +00:00
2017-02-01 21:11:17 +00:00
if self . _list_box . GetCount ( ) == 1 :
self . _Select ( 0 )
2014-02-26 22:09:54 +00:00
2013-07-31 21:26:38 +00:00
2017-02-01 21:11:17 +00:00
def DeleteAllPages ( self ) :
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
self . _panel_sizer . Detach ( self . _empty_panel )
2016-03-16 22:19:14 +00:00
2018-01-03 22:37:30 +00:00
self . _panel_sizer . Clear ( delete_windows = True )
2016-01-06 21:17:20 +00:00
2018-01-03 22:37:30 +00:00
self . _panel_sizer . Add ( self . _empty_panel , CC . FLAGS_EXPAND_SIZER_BOTH_WAYS )
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
self . _current_key = None
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
self . _current_panel = self . _empty_panel
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
self . _keys_to_active_pages = { }
self . _keys_to_proto_pages = { }
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
self . _list_box . Clear ( )
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
def DeleteCurrentPage ( self ) :
2013-07-31 21:26:38 +00:00
2017-02-01 21:11:17 +00:00
selection = self . _list_box . GetSelection ( )
2013-08-14 20:21:49 +00:00
2017-02-01 21:11:17 +00:00
if selection != wx . NOT_FOUND :
2013-07-31 21:26:38 +00:00
2017-02-01 21:11:17 +00:00
key_to_delete = self . _current_key
page_to_delete = self . _current_panel
2013-07-31 21:26:38 +00:00
2017-02-01 21:11:17 +00:00
next_selection = selection + 1
previous_selection = selection - 1
2014-12-10 22:02:39 +00:00
2017-02-01 21:11:17 +00:00
if next_selection < self . _list_box . GetCount ( ) :
self . _Select ( next_selection )
elif previous_selection > = 0 :
self . _Select ( previous_selection )
else :
self . _Select ( wx . NOT_FOUND )
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
self . _panel_sizer . Detach ( page_to_delete )
2013-07-31 21:26:38 +00:00
2017-02-01 21:11:17 +00:00
page_to_delete . Destroy ( )
2013-07-31 21:26:38 +00:00
2017-02-01 21:11:17 +00:00
del self . _keys_to_active_pages [ key_to_delete ]
2015-02-03 20:40:21 +00:00
2017-02-01 21:11:17 +00:00
self . _list_box . Delete ( selection )
2015-02-03 20:40:21 +00:00
2017-02-01 21:11:17 +00:00
self . _RecalcListBoxWidth ( )
2015-02-03 20:40:21 +00:00
2017-02-01 21:11:17 +00:00
def EventSelection ( self , event ) :
if self . _list_box . GetSelection ( ) != self . _GetIndex ( self . _current_key ) :
event = wx . NotifyEvent ( wx . wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING , - 1 )
2018-02-21 21:59:37 +00:00
wx . QueueEvent ( self . GetEventHandler ( ) , event )
2017-02-01 21:11:17 +00:00
if event . IsAllowed ( ) :
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
self . _Select ( self . _list_box . GetSelection ( ) )
2016-01-06 21:17:20 +00:00
else :
2017-02-01 21:11:17 +00:00
self . _list_box . SetSelection ( self . _GetIndex ( self . _current_key ) )
2016-01-06 21:17:20 +00:00
2013-08-14 20:21:49 +00:00
2013-07-24 20:26:00 +00:00
2017-02-01 21:11:17 +00:00
def GetCurrentKey ( self ) :
2016-07-13 17:37:44 +00:00
2017-02-01 21:11:17 +00:00
return self . _current_key
2016-07-13 17:37:44 +00:00
2017-02-01 21:11:17 +00:00
def GetCurrentPage ( self ) :
2015-10-28 21:29:05 +00:00
2017-02-01 21:11:17 +00:00
if self . _current_panel == self . _empty_panel :
return None
else :
return self . _current_panel
2015-10-28 21:29:05 +00:00
2017-02-01 21:11:17 +00:00
def GetActivePages ( self ) :
2015-10-28 21:29:05 +00:00
2017-02-01 21:11:17 +00:00
return self . _keys_to_active_pages . values ( )
2016-12-07 22:12:52 +00:00
2017-02-01 21:11:17 +00:00
def GetPage ( self , key ) :
2016-12-07 22:12:52 +00:00
2017-02-01 21:11:17 +00:00
if key in self . _keys_to_proto_pages :
self . _ActivatePage ( key )
2015-10-28 21:29:05 +00:00
2017-02-01 21:11:17 +00:00
if key in self . _keys_to_active_pages :
return self . _keys_to_active_pages [ key ]
2013-07-24 20:26:00 +00:00
2017-02-01 21:11:17 +00:00
raise Exception ( ' That page not found! ' )
2013-08-14 20:21:49 +00:00
2017-02-01 21:11:17 +00:00
2017-03-22 22:38:15 +00:00
def GetPageCount ( self ) :
return len ( self . _keys_to_active_pages ) + len ( self . _keys_to_proto_pages )
2017-02-01 21:11:17 +00:00
def KeyExists ( self , key ) :
2015-02-03 20:40:21 +00:00
2017-02-01 21:11:17 +00:00
return key in self . _keys_to_active_pages or key in self . _keys_to_proto_pages
2014-10-29 21:39:01 +00:00
2017-02-01 21:11:17 +00:00
def RenamePage ( self , key , new_name ) :
2013-07-24 20:26:00 +00:00
2017-02-01 21:11:17 +00:00
index = self . _GetIndex ( key )
2015-02-03 20:40:21 +00:00
2017-02-01 21:11:17 +00:00
if index != wx . NOT_FOUND :
2015-10-28 21:29:05 +00:00
2017-02-01 21:11:17 +00:00
self . _list_box . SetString ( index , new_name )
2015-10-28 21:29:05 +00:00
2013-07-24 20:26:00 +00:00
2017-02-01 21:11:17 +00:00
self . _RecalcListBoxWidth ( )
2013-07-24 20:26:00 +00:00
2017-02-01 21:11:17 +00:00
def Select ( self , key ) :
2015-12-09 23:16:41 +00:00
2017-02-01 21:11:17 +00:00
index = self . _GetIndex ( key )
2015-12-09 23:16:41 +00:00
2017-02-01 21:11:17 +00:00
if index != wx . NOT_FOUND and index != self . _list_box . GetSelection ( ) :
2015-12-09 23:16:41 +00:00
2017-02-01 21:11:17 +00:00
event = wx . NotifyEvent ( wx . wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING , - 1 )
2015-12-09 23:16:41 +00:00
2018-02-21 21:59:37 +00:00
wx . QueueEvent ( self . GetEventHandler ( ) , event )
2015-12-09 23:16:41 +00:00
2017-02-01 21:11:17 +00:00
if event . IsAllowed ( ) :
self . _Select ( index )
2015-12-09 23:16:41 +00:00
2017-02-01 21:11:17 +00:00
def SelectDown ( self ) :
2013-07-24 20:26:00 +00:00
2017-02-01 21:11:17 +00:00
current_selection = self . _list_box . GetSelection ( )
if current_selection != wx . NOT_FOUND :
2016-12-21 22:30:54 +00:00
2017-02-01 21:11:17 +00:00
num_entries = self . _list_box . GetCount ( )
2016-12-21 22:30:54 +00:00
2017-02-01 21:11:17 +00:00
if current_selection == num_entries - 1 : selection = 0
else : selection = current_selection + 1
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
if selection != current_selection :
self . _Select ( selection )
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
def SelectPage ( self , page_to_select ) :
2013-07-24 20:26:00 +00:00
2017-02-01 21:11:17 +00:00
for ( key , page ) in self . _keys_to_active_pages . items ( ) :
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
if page == page_to_select :
self . _Select ( self . _GetIndex ( key ) )
return
2016-01-06 21:17:20 +00:00
2013-07-24 20:26:00 +00:00
2015-02-03 20:40:21 +00:00
2017-02-01 21:11:17 +00:00
def SelectUp ( self ) :
2013-07-24 20:26:00 +00:00
2017-02-01 21:11:17 +00:00
current_selection = self . _list_box . GetSelection ( )
2015-10-28 21:29:05 +00:00
2017-02-01 21:11:17 +00:00
if current_selection != wx . NOT_FOUND :
num_entries = self . _list_box . GetCount ( )
if current_selection == 0 : selection = num_entries - 1
else : selection = current_selection - 1
2015-10-28 21:29:05 +00:00
2017-02-01 21:11:17 +00:00
if selection != current_selection :
self . _Select ( selection )
2015-10-28 21:29:05 +00:00
2015-02-03 20:40:21 +00:00
2017-03-15 20:13:04 +00:00
class MenuBitmapButton ( BetterBitmapButton ) :
def __init__ ( self , parent , bitmap , menu_items ) :
BetterBitmapButton . __init__ ( self , parent , bitmap , self . DoMenu )
self . _menu_items = menu_items
2017-01-25 22:56:55 +00:00
2017-01-18 22:52:39 +00:00
def DoMenu ( self ) :
menu = wx . Menu ( )
2017-01-25 22:56:55 +00:00
for ( item_type , title , description , data ) in self . _menu_items :
2017-01-18 22:52:39 +00:00
2017-01-25 22:56:55 +00:00
if item_type == ' normal ' :
2017-03-15 20:13:04 +00:00
func = data
2017-01-25 22:56:55 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus . AppendMenuItem ( self , menu , title , description , func )
2017-01-25 22:56:55 +00:00
elif item_type == ' check ' :
2017-03-15 20:13:04 +00:00
check_manager = data
2017-01-25 22:56:55 +00:00
2017-03-15 20:13:04 +00:00
current_value = check_manager . GetCurrentValue ( )
func = check_manager . Invert
2017-01-25 22:56:55 +00:00
2017-08-16 21:58:06 +00:00
if current_value is not None :
ClientGUIMenus . AppendMenuCheckItem ( self , menu , title , description , current_value , func )
2017-01-25 22:56:55 +00:00
elif item_type == ' separator ' :
2017-03-15 20:13:04 +00:00
ClientGUIMenus . AppendSeparator ( menu )
2017-01-25 22:56:55 +00:00
2017-01-18 22:52:39 +00:00
2017-05-10 21:33:58 +00:00
HG . client_controller . PopupMenu ( self , menu )
2017-01-18 22:52:39 +00:00
2016-11-16 20:21:43 +00:00
class MenuButton ( BetterButton ) :
def __init__ ( self , parent , label , menu_items ) :
BetterButton . __init__ ( self , parent , label , self . DoMenu )
self . _menu_items = menu_items
def DoMenu ( self ) :
menu = wx . Menu ( )
2017-01-25 22:56:55 +00:00
for ( item_type , title , description , data ) in self . _menu_items :
2016-11-16 20:21:43 +00:00
2017-01-25 22:56:55 +00:00
if item_type == ' normal ' :
callable = data
ClientGUIMenus . AppendMenuItem ( self , menu , title , description , callable )
elif item_type == ' check ' :
2017-03-15 20:13:04 +00:00
check_manager = data
2017-01-25 22:56:55 +00:00
2017-03-15 20:13:04 +00:00
initial_value = check_manager . GetInitialValue ( )
2017-01-25 22:56:55 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus . AppendMenuCheckItem ( self , menu , title , description , initial_value , check_manager . Invert )
2017-01-25 22:56:55 +00:00
2017-08-16 21:58:06 +00:00
2017-01-25 22:56:55 +00:00
elif item_type == ' separator ' :
2017-03-15 20:13:04 +00:00
ClientGUIMenus . AppendSeparator ( menu )
2017-01-25 22:56:55 +00:00
2017-03-02 02:14:56 +00:00
elif item_type == ' label ' :
ClientGUIMenus . AppendMenuLabel ( menu , title , description )
2016-11-16 20:21:43 +00:00
2017-05-10 21:33:58 +00:00
HG . client_controller . PopupMenu ( self , menu )
2016-11-16 20:21:43 +00:00
2017-03-02 02:14:56 +00:00
def SetMenuItems ( self , menu_items ) :
self . _menu_items = menu_items
2017-10-11 17:38:14 +00:00
class NetworkContextButton ( BetterButton ) :
2018-03-22 00:03:33 +00:00
def __init__ ( self , parent , network_context , limited_types = None , allow_default = True ) :
2017-10-11 17:38:14 +00:00
BetterButton . __init__ ( self , parent , network_context . ToUnicode ( ) , self . _Edit )
self . _network_context = network_context
2018-03-22 00:03:33 +00:00
self . _limited_types = limited_types
self . _allow_default = allow_default
2017-10-11 17:38:14 +00:00
def _Edit ( self ) :
import ClientGUITopLevelWindows
import ClientGUIScrolledPanelsEdit
with ClientGUITopLevelWindows . DialogEdit ( self , ' edit network context ' ) as dlg :
2018-03-22 00:03:33 +00:00
panel = ClientGUIScrolledPanelsEdit . EditNetworkContextPanel ( dlg , self . _network_context , limited_types = self . _limited_types , allow_default = self . _allow_default )
2017-10-11 17:38:14 +00:00
dlg . SetPanel ( panel )
if dlg . ShowModal ( ) == wx . ID_OK :
self . _network_context = panel . GetValue ( )
self . _Update ( )
def _Update ( self ) :
self . SetLabelText ( self . _network_context . ToUnicode ( ) )
def GetValue ( self ) :
return self . _network_context
def SetValue ( self , network_context ) :
self . _network_context = network_context
self . _Update ( )
2015-02-03 20:40:21 +00:00
class NoneableSpinCtrl ( wx . Panel ) :
2017-03-02 02:14:56 +00:00
def __init__ ( self , parent , message = ' ' , none_phrase = ' no limit ' , min = 0 , max = 1000000 , unit = None , multiplier = 1 , num_dimensions = 1 ) :
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
wx . Panel . __init__ ( self , parent )
2013-02-19 00:11:43 +00:00
2015-12-02 22:32:18 +00:00
self . _unit = unit
2015-02-03 20:40:21 +00:00
self . _multiplier = multiplier
2015-12-02 22:32:18 +00:00
self . _num_dimensions = num_dimensions
2013-03-15 02:38:12 +00:00
2017-04-19 20:58:30 +00:00
self . _checkbox = wx . CheckBox ( self )
2015-02-03 20:40:21 +00:00
self . _checkbox . Bind ( wx . EVT_CHECKBOX , self . EventCheckBox )
2017-04-19 20:58:30 +00:00
self . _checkbox . SetLabelText ( none_phrase )
2013-02-19 00:11:43 +00:00
2018-03-22 00:03:33 +00:00
self . _one = wx . SpinCtrl ( self , min = min , max = max )
2018-03-28 21:55:58 +00:00
width = ClientData . ConvertTextToPixelWidth ( self . _one , len ( str ( max ) ) + 5 )
2018-03-22 00:03:33 +00:00
self . _one . SetInitialSize ( ( width , - 1 ) )
2013-02-19 00:11:43 +00:00
2015-12-23 22:51:04 +00:00
if num_dimensions == 2 :
2018-03-22 00:03:33 +00:00
self . _two = wx . SpinCtrl ( self , initial = 0 , min = min , max = max )
2018-03-28 21:55:58 +00:00
width = ClientData . ConvertTextToPixelWidth ( self . _two , len ( str ( max ) ) + 5 )
2018-03-22 00:03:33 +00:00
self . _two . SetInitialSize ( ( width , - 1 ) )
2015-12-23 22:51:04 +00:00
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
hbox = wx . BoxSizer ( wx . HORIZONTAL )
2013-02-19 00:11:43 +00:00
2015-07-15 20:28:26 +00:00
if len ( message ) > 0 :
2018-01-03 22:37:30 +00:00
hbox . Add ( BetterStaticText ( self , message + ' : ' ) , CC . FLAGS_VCENTER )
2015-07-15 20:28:26 +00:00
2018-01-03 22:37:30 +00:00
hbox . Add ( self . _one , CC . FLAGS_VCENTER )
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
if self . _num_dimensions == 2 :
2018-01-03 22:37:30 +00:00
hbox . Add ( BetterStaticText ( self , ' x ' ) , CC . FLAGS_VCENTER )
hbox . Add ( self . _two , CC . FLAGS_VCENTER )
2015-02-03 20:40:21 +00:00
2013-02-19 00:11:43 +00:00
2015-12-02 22:32:18 +00:00
if self . _unit is not None :
2018-01-03 22:37:30 +00:00
hbox . Add ( BetterStaticText ( self , self . _unit ) , CC . FLAGS_VCENTER )
2015-12-02 22:32:18 +00:00
2018-01-03 22:37:30 +00:00
hbox . Add ( self . _checkbox , CC . FLAGS_VCENTER )
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
self . SetSizer ( hbox )
2013-02-19 00:11:43 +00:00
2015-04-01 20:44:54 +00:00
def Bind ( self , event_type , callback ) :
self . _checkbox . Bind ( wx . EVT_CHECKBOX , callback )
2017-09-27 21:52:54 +00:00
2015-04-01 20:44:54 +00:00
self . _one . Bind ( wx . EVT_SPINCTRL , callback )
2017-09-27 21:52:54 +00:00
if self . _num_dimensions == 2 :
self . _two . Bind ( wx . EVT_SPINCTRL , callback )
2015-04-01 20:44:54 +00:00
2015-02-03 20:40:21 +00:00
def EventCheckBox ( self , event ) :
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
if self . _checkbox . GetValue ( ) :
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
self . _one . Disable ( )
if self . _num_dimensions == 2 : self . _two . Disable ( )
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
else :
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
self . _one . Enable ( )
if self . _num_dimensions == 2 : self . _two . Enable ( )
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
def GetValue ( self ) :
2013-02-19 00:11:43 +00:00
2017-10-18 19:41:25 +00:00
if self . _checkbox . GetValue ( ) :
return None
2015-02-03 20:40:21 +00:00
else :
2017-10-18 19:41:25 +00:00
if self . _num_dimensions == 2 :
return ( self . _one . GetValue ( ) * self . _multiplier , self . _two . GetValue ( ) * self . _multiplier )
else :
return self . _one . GetValue ( ) * self . _multiplier
2015-02-03 20:40:21 +00:00
2013-02-19 00:11:43 +00:00
2018-01-03 22:37:30 +00:00
def SetToolTip ( self , text ) :
2016-06-22 20:59:24 +00:00
2018-01-03 22:37:30 +00:00
wx . Panel . SetToolTip ( self , text )
2016-06-22 20:59:24 +00:00
for c in self . GetChildren ( ) :
2018-01-03 22:37:30 +00:00
c . SetToolTip ( text )
2016-06-22 20:59:24 +00:00
2015-02-03 20:40:21 +00:00
def SetValue ( self , value ) :
2013-03-15 02:38:12 +00:00
2015-02-03 20:40:21 +00:00
if value is None :
self . _checkbox . SetValue ( True )
self . _one . Disable ( )
if self . _num_dimensions == 2 : self . _two . Disable ( )
else :
self . _checkbox . SetValue ( False )
if self . _num_dimensions == 2 :
self . _two . Enable ( )
( value , y ) = value
self . _two . SetValue ( y / self . _multiplier )
self . _one . Enable ( )
self . _one . SetValue ( value / self . _multiplier )
2013-02-19 00:11:43 +00:00
2017-10-18 19:41:25 +00:00
class NoneableTextCtrl ( wx . Panel ) :
def __init__ ( self , parent , message = ' ' , none_phrase = ' no limit ' ) :
wx . Panel . __init__ ( self , parent )
self . _checkbox = wx . CheckBox ( self )
self . _checkbox . Bind ( wx . EVT_CHECKBOX , self . EventCheckBox )
self . _checkbox . SetLabelText ( none_phrase )
self . _text = wx . TextCtrl ( self )
hbox = wx . BoxSizer ( wx . HORIZONTAL )
if len ( message ) > 0 :
2018-01-03 22:37:30 +00:00
hbox . Add ( BetterStaticText ( self , message + ' : ' ) , CC . FLAGS_VCENTER )
2017-10-18 19:41:25 +00:00
2018-01-03 22:37:30 +00:00
hbox . Add ( self . _text , CC . FLAGS_VCENTER )
hbox . Add ( self . _checkbox , CC . FLAGS_VCENTER )
2017-10-18 19:41:25 +00:00
self . SetSizer ( hbox )
def Bind ( self , event_type , callback ) :
self . _checkbox . Bind ( wx . EVT_CHECKBOX , callback )
self . _text . Bind ( wx . EVT_TEXT , callback )
def EventCheckBox ( self , event ) :
if self . _checkbox . GetValue ( ) :
self . _text . Disable ( )
else :
self . _text . Enable ( )
def GetValue ( self ) :
if self . _checkbox . GetValue ( ) :
return None
else :
return self . _text . GetValue ( )
2018-01-03 22:37:30 +00:00
def SetToolTip ( self , text ) :
2017-10-18 19:41:25 +00:00
2018-01-03 22:37:30 +00:00
wx . Panel . SetToolTip ( self , text )
2017-10-18 19:41:25 +00:00
for c in self . GetChildren ( ) :
2018-01-03 22:37:30 +00:00
c . SetToolTip ( text )
2017-10-18 19:41:25 +00:00
def SetValue ( self , value ) :
if value is None :
self . _checkbox . SetValue ( True )
self . _text . Disable ( )
else :
self . _checkbox . SetValue ( False )
self . _text . Enable ( )
self . _text . SetValue ( value )
2015-02-03 20:40:21 +00:00
class OnOffButton ( wx . Button ) :
2013-03-15 02:38:12 +00:00
2015-02-03 20:40:21 +00:00
def __init__ ( self , parent , page_key , topic , on_label , off_label = None , start_on = True ) :
2013-03-15 02:38:12 +00:00
2015-02-03 20:40:21 +00:00
if start_on : label = on_label
else : label = off_label
2013-03-15 02:38:12 +00:00
2015-02-03 20:40:21 +00:00
wx . Button . __init__ ( self , parent , label = label )
2013-03-15 02:38:12 +00:00
2015-02-03 20:40:21 +00:00
self . _page_key = page_key
self . _topic = topic
self . _on_label = on_label
2013-03-15 02:38:12 +00:00
2015-02-03 20:40:21 +00:00
if off_label is None : self . _off_label = on_label
else : self . _off_label = off_label
2013-09-18 17:23:30 +00:00
2015-02-03 20:40:21 +00:00
self . _on = start_on
2013-09-18 17:23:30 +00:00
2015-02-03 20:40:21 +00:00
if self . _on : self . SetForegroundColour ( ( 0 , 128 , 0 ) )
else : self . SetForegroundColour ( ( 128 , 0 , 0 ) )
2013-09-18 17:23:30 +00:00
2015-02-03 20:40:21 +00:00
self . Bind ( wx . EVT_BUTTON , self . EventButton )
2013-09-18 17:23:30 +00:00
2017-05-10 21:33:58 +00:00
HG . client_controller . sub ( self , ' HitButton ' , ' hit_on_off_button ' )
2013-09-18 17:23:30 +00:00
2015-02-03 20:40:21 +00:00
def EventButton ( self , event ) :
2013-09-18 17:23:30 +00:00
2015-02-03 20:40:21 +00:00
if self . _on :
2013-09-18 17:23:30 +00:00
2015-02-03 20:40:21 +00:00
self . _on = False
2013-09-18 17:23:30 +00:00
2016-03-23 19:42:56 +00:00
self . SetLabelText ( self . _off_label )
2013-09-18 17:23:30 +00:00
2015-02-03 20:40:21 +00:00
self . SetForegroundColour ( ( 128 , 0 , 0 ) )
2013-09-18 17:23:30 +00:00
2017-05-10 21:33:58 +00:00
HG . client_controller . pub ( self . _topic , self . _page_key , False )
2013-09-18 17:23:30 +00:00
2015-02-03 20:40:21 +00:00
else :
2013-09-18 17:23:30 +00:00
2015-02-03 20:40:21 +00:00
self . _on = True
2013-09-18 17:23:30 +00:00
2016-03-23 19:42:56 +00:00
self . SetLabelText ( self . _on_label )
2013-09-18 17:23:30 +00:00
2015-02-03 20:40:21 +00:00
self . SetForegroundColour ( ( 0 , 128 , 0 ) )
2014-02-12 23:09:38 +00:00
2017-05-10 21:33:58 +00:00
HG . client_controller . pub ( self . _topic , self . _page_key , True )
2014-02-12 23:09:38 +00:00
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
def IsOn ( self ) : return self . _on
2014-09-03 20:26:49 +00:00
2017-07-27 00:47:13 +00:00
class RatingLike ( wx . Window ) :
2014-02-12 23:09:38 +00:00
2017-07-27 00:47:13 +00:00
def __init__ ( self , parent , service_key ) :
2014-09-03 20:26:49 +00:00
2017-07-27 00:47:13 +00:00
wx . Window . __init__ ( self , parent )
2014-09-03 20:26:49 +00:00
2017-07-27 00:47:13 +00:00
self . _service_key = service_key
2014-09-03 20:26:49 +00:00
2018-01-03 22:37:30 +00:00
self . _canvas_bmp = wx . Bitmap ( 16 , 16 , 24 )
2016-09-07 20:01:05 +00:00
2017-07-27 00:47:13 +00:00
self . Bind ( wx . EVT_PAINT , self . EventPaint )
self . Bind ( wx . EVT_ERASE_BACKGROUND , self . EventEraseBackground )
2016-09-07 20:01:05 +00:00
2017-07-27 00:47:13 +00:00
self . Bind ( wx . EVT_LEFT_DOWN , self . EventLeftDown )
self . Bind ( wx . EVT_LEFT_DCLICK , self . EventLeftDown )
self . Bind ( wx . EVT_RIGHT_DOWN , self . EventRightDown )
self . Bind ( wx . EVT_RIGHT_DCLICK , self . EventRightDown )
2016-09-07 20:01:05 +00:00
2017-07-27 00:47:13 +00:00
self . SetMinSize ( ( 16 , 16 ) )
self . _dirty = True
2016-09-07 20:01:05 +00:00
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
def _Draw ( self , dc ) :
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
raise NotImplementedError ( )
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
def EventEraseBackground ( self , event ) : pass
def EventLeftDown ( self , event ) :
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
raise NotImplementedError ( )
2013-03-15 02:38:12 +00:00
2017-07-27 00:47:13 +00:00
def EventPaint ( self , event ) :
2013-09-18 17:23:30 +00:00
2017-07-27 00:47:13 +00:00
dc = wx . BufferedPaintDC ( self , self . _canvas_bmp )
2013-09-18 17:23:30 +00:00
2017-07-27 00:47:13 +00:00
if self . _dirty :
self . _Draw ( dc )
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
def EventRightDown ( self , event ) :
2016-09-07 20:01:05 +00:00
2017-07-27 00:47:13 +00:00
raise NotImplementedError ( )
2016-09-07 20:01:05 +00:00
2014-09-03 20:26:49 +00:00
2017-07-27 00:47:13 +00:00
def GetServiceKey ( self ) :
2016-09-07 20:01:05 +00:00
2017-07-27 00:47:13 +00:00
return self . _service_key
2016-09-07 20:01:05 +00:00
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
class RatingLikeDialog ( RatingLike ) :
def __init__ ( self , parent , service_key ) :
2016-09-07 20:01:05 +00:00
2017-07-27 00:47:13 +00:00
RatingLike . __init__ ( self , parent , service_key )
2016-09-07 20:01:05 +00:00
2017-07-27 00:47:13 +00:00
self . _rating_state = ClientRatings . NULL
2014-02-12 23:09:38 +00:00
2017-07-27 00:47:13 +00:00
def _Draw ( self , dc ) :
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
dc . SetBackground ( wx . Brush ( self . GetParent ( ) . GetBackgroundColour ( ) ) )
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
dc . Clear ( )
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
( pen_colour , brush_colour ) = ClientRatings . GetPenAndBrushColours ( self . _service_key , self . _rating_state )
2013-03-15 02:38:12 +00:00
2017-07-27 00:47:13 +00:00
ClientRatings . DrawLike ( dc , 0 , 0 , self . _service_key , self . _rating_state )
2013-03-15 02:38:12 +00:00
2017-07-27 00:47:13 +00:00
self . _dirty = False
2013-03-15 02:38:12 +00:00
2017-07-27 00:47:13 +00:00
def EventLeftDown ( self , event ) :
2013-03-15 02:38:12 +00:00
2017-07-27 00:47:13 +00:00
if self . _rating_state == ClientRatings . LIKE : self . _rating_state = ClientRatings . NULL
else : self . _rating_state = ClientRatings . LIKE
2013-03-15 02:38:12 +00:00
2017-07-27 00:47:13 +00:00
self . _dirty = True
2017-01-25 22:56:55 +00:00
2017-07-27 00:47:13 +00:00
self . Refresh ( )
2016-05-25 21:54:03 +00:00
2017-07-27 00:47:13 +00:00
def EventRightDown ( self , event ) :
2013-03-15 02:38:12 +00:00
2017-07-27 00:47:13 +00:00
if self . _rating_state == ClientRatings . DISLIKE : self . _rating_state = ClientRatings . NULL
else : self . _rating_state = ClientRatings . DISLIKE
2013-03-15 02:38:12 +00:00
2017-07-27 00:47:13 +00:00
self . _dirty = True
2013-03-15 02:38:12 +00:00
2017-07-27 00:47:13 +00:00
self . Refresh ( )
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
def GetRatingState ( self ) :
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
return self . _rating_state
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
def SetRatingState ( self , rating_state ) :
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
self . _rating_state = rating_state
2015-03-18 21:46:29 +00:00
2017-07-27 00:47:13 +00:00
self . _dirty = True
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
self . Refresh ( )
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
class RatingLikeCanvas ( RatingLike ) :
def __init__ ( self , parent , service_key , canvas_key ) :
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
RatingLike . __init__ ( self , parent , service_key )
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
self . _canvas_key = canvas_key
self . _current_media = None
self . _rating_state = None
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
service = HG . client_controller . services_manager . GetService ( service_key )
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
name = service . GetName ( )
2013-02-19 00:11:43 +00:00
2018-01-03 22:37:30 +00:00
self . SetToolTip ( name )
2015-07-15 20:28:26 +00:00
2017-07-27 00:47:13 +00:00
HG . client_controller . sub ( self , ' ProcessContentUpdates ' , ' content_updates_gui ' )
HG . client_controller . sub ( self , ' SetDisplayMedia ' , ' canvas_new_display_media ' )
2015-07-15 20:28:26 +00:00
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
def _Draw ( self , dc ) :
2016-05-25 21:54:03 +00:00
2017-07-27 00:47:13 +00:00
dc . SetBackground ( wx . Brush ( self . GetParent ( ) . GetBackgroundColour ( ) ) )
dc . Clear ( )
2016-05-25 21:54:03 +00:00
2017-07-27 00:47:13 +00:00
if self . _current_media is not None :
2016-09-28 18:48:01 +00:00
2017-07-27 00:47:13 +00:00
self . _rating_state = ClientRatings . GetLikeStateFromMedia ( ( self . _current_media , ) , self . _service_key )
2016-09-28 18:48:01 +00:00
2017-07-27 00:47:13 +00:00
ClientRatings . DrawLike ( dc , 0 , 0 , self . _service_key , self . _rating_state )
2016-09-28 18:48:01 +00:00
2016-05-25 21:54:03 +00:00
2017-07-27 00:47:13 +00:00
self . _dirty = False
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
def EventLeftDown ( self , event ) :
2015-10-07 21:56:22 +00:00
2017-07-27 00:47:13 +00:00
if self . _current_media is not None :
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
if self . _rating_state == ClientRatings . LIKE : rating = None
else : rating = 1
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
content_update = HydrusData . ContentUpdate ( HC . CONTENT_TYPE_RATINGS , HC . CONTENT_UPDATE_ADD , ( rating , self . _hashes ) )
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
HG . client_controller . Write ( ' content_updates ' , { self . _service_key : ( content_update , ) } )
2015-02-03 20:40:21 +00:00
2013-09-18 17:23:30 +00:00
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
def EventRightDown ( self , event ) :
2016-09-28 18:48:01 +00:00
2017-07-27 00:47:13 +00:00
if self . _current_media is not None :
if self . _rating_state == ClientRatings . DISLIKE : rating = None
else : rating = 0
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
content_update = HydrusData . ContentUpdate ( HC . CONTENT_TYPE_RATINGS , HC . CONTENT_UPDATE_ADD , ( rating , self . _hashes ) )
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
HG . client_controller . Write ( ' content_updates ' , { self . _service_key : ( content_update , ) } )
2015-02-03 20:40:21 +00:00
2013-03-15 02:38:12 +00:00
2013-04-17 21:48:18 +00:00
2017-07-27 00:47:13 +00:00
def ProcessContentUpdates ( self , service_keys_to_content_updates ) :
2013-04-10 18:10:37 +00:00
2017-07-27 00:47:13 +00:00
if self . _current_media is not None :
for ( service_key , content_updates ) in service_keys_to_content_updates . items ( ) :
for content_update in content_updates :
( data_type , action , row ) = content_update . ToTuple ( )
if data_type == HC . CONTENT_TYPE_RATINGS :
hashes = content_update . GetHashes ( )
if len ( self . _hashes . intersection ( hashes ) ) > 0 :
self . _dirty = True
self . Refresh ( )
return
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
def SetDisplayMedia ( self , canvas_key , media ) :
if canvas_key == self . _canvas_key :
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
self . _current_media = media
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
if self . _current_media is None :
self . _hashes = set ( )
else :
self . _hashes = self . _current_media . GetHashes ( )
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
self . _dirty = True
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
self . Refresh ( )
2015-02-03 20:40:21 +00:00
2013-04-10 18:10:37 +00:00
2013-03-15 02:38:12 +00:00
2017-07-27 00:47:13 +00:00
class RatingNumerical ( wx . Window ) :
def __init__ ( self , parent , service_key ) :
2016-04-14 01:54:29 +00:00
2017-07-27 00:47:13 +00:00
wx . Window . __init__ ( self , parent )
2016-04-14 01:54:29 +00:00
2017-07-27 00:47:13 +00:00
self . _service_key = service_key
2014-02-12 23:09:38 +00:00
2017-07-27 00:47:13 +00:00
self . _service = HG . client_controller . services_manager . GetService ( self . _service_key )
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
self . _num_stars = self . _service . GetNumStars ( )
self . _allow_zero = self . _service . AllowZero ( )
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
my_width = ClientRatings . GetNumericalWidth ( self . _service_key )
2016-09-07 20:01:05 +00:00
2018-01-03 22:37:30 +00:00
self . _canvas_bmp = wx . Bitmap ( my_width , 16 , 24 )
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
self . Bind ( wx . EVT_PAINT , self . EventPaint )
self . Bind ( wx . EVT_ERASE_BACKGROUND , self . EventEraseBackground )
2016-09-28 18:48:01 +00:00
2017-07-27 00:47:13 +00:00
self . Bind ( wx . EVT_LEFT_DOWN , self . EventLeftDown )
self . Bind ( wx . EVT_LEFT_DCLICK , self . EventLeftDown )
self . Bind ( wx . EVT_RIGHT_DOWN , self . EventRightDown )
self . Bind ( wx . EVT_RIGHT_DCLICK , self . EventRightDown )
2016-09-28 18:48:01 +00:00
2017-07-27 00:47:13 +00:00
self . SetMinSize ( ( my_width , 16 ) )
2016-09-28 18:48:01 +00:00
2017-07-27 00:47:13 +00:00
self . _dirty = True
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
def _Draw ( self , dc ) :
2016-09-28 18:48:01 +00:00
2017-07-27 00:47:13 +00:00
raise NotImplementedError ( )
2013-02-19 00:11:43 +00:00
2017-07-27 00:47:13 +00:00
def _GetRatingFromClickEvent ( self , event ) :
x = event . GetX ( )
y = event . GetY ( )
( my_width , my_height ) = self . GetClientSize ( )
# assuming a border of 2 on every side here
2013-03-15 02:38:12 +00:00
2017-07-27 00:47:13 +00:00
my_active_width = my_width - 4
my_active_height = my_height - 4
x_adjusted = x - 2
y_adjusted = y - 2
2016-09-28 18:48:01 +00:00
2017-07-27 00:47:13 +00:00
if 0 < = y and y < = my_active_height :
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
if 0 < = x and x < = my_active_width :
2015-02-03 20:40:21 +00:00
2017-07-27 00:47:13 +00:00
proportion_filled = float ( x_adjusted ) / my_active_width
2016-09-28 18:48:01 +00:00
2017-07-27 00:47:13 +00:00
if self . _allow_zero :
rating = round ( proportion_filled * self . _num_stars ) / self . _num_stars
else :
rating = float ( int ( proportion_filled * self . _num_stars ) ) / ( self . _num_stars - 1 )
return rating
2016-09-28 18:48:01 +00:00
2017-07-27 00:47:13 +00:00
return None
2015-05-20 21:31:40 +00:00
def EventEraseBackground ( self , event ) : pass
def EventLeftDown ( self , event ) :
raise NotImplementedError ( )
def EventPaint ( self , event ) :
2015-11-18 22:44:07 +00:00
dc = wx . BufferedPaintDC ( self , self . _canvas_bmp )
2015-05-20 21:31:40 +00:00
if self . _dirty :
2015-11-18 22:44:07 +00:00
self . _Draw ( dc )
2015-05-20 21:31:40 +00:00
def EventRightDown ( self , event ) :
raise NotImplementedError ( )
2015-07-01 22:02:07 +00:00
def GetServiceKey ( self ) :
return self . _service_key
2015-05-20 21:31:40 +00:00
class RatingNumericalDialog ( RatingNumerical ) :
def __init__ ( self , parent , service_key ) :
RatingNumerical . __init__ ( self , parent , service_key )
self . _rating_state = ClientRatings . NULL
2015-10-21 21:53:10 +00:00
self . _rating = None
2015-05-20 21:31:40 +00:00
2015-11-18 22:44:07 +00:00
def _Draw ( self , dc ) :
2015-05-20 21:31:40 +00:00
dc . SetBackground ( wx . Brush ( self . GetParent ( ) . GetBackgroundColour ( ) ) )
dc . Clear ( )
2015-06-10 19:40:25 +00:00
ClientRatings . DrawNumerical ( dc , 0 , 0 , self . _service_key , self . _rating_state , self . _rating )
2015-05-20 21:31:40 +00:00
self . _dirty = False
def EventLeftDown ( self , event ) :
rating = self . _GetRatingFromClickEvent ( event )
if rating is not None :
self . _rating_state = ClientRatings . SET
self . _rating = rating
self . _dirty = True
self . Refresh ( )
def EventRightDown ( self , event ) :
self . _rating_state = ClientRatings . NULL
self . _dirty = True
self . Refresh ( )
def GetRating ( self ) :
return self . _rating
def GetRatingState ( self ) :
return self . _rating_state
def SetRating ( self , rating ) :
self . _rating_state = ClientRatings . SET
self . _rating = rating
self . _dirty = True
self . Refresh ( )
def SetRatingState ( self , rating_state ) :
self . _rating_state = rating_state
self . _dirty = True
self . Refresh ( )
class RatingNumericalCanvas ( RatingNumerical ) :
def __init__ ( self , parent , service_key , canvas_key ) :
RatingNumerical . __init__ ( self , parent , service_key )
self . _canvas_key = canvas_key
self . _current_media = None
self . _rating_state = None
self . _rating = None
name = self . _service . GetName ( )
2018-01-03 22:37:30 +00:00
self . SetToolTip ( name )
2015-05-20 21:31:40 +00:00
2017-05-10 21:33:58 +00:00
HG . client_controller . sub ( self , ' ProcessContentUpdates ' , ' content_updates_gui ' )
HG . client_controller . sub ( self , ' SetDisplayMedia ' , ' canvas_new_display_media ' )
2015-05-20 21:31:40 +00:00
2015-11-18 22:44:07 +00:00
def _Draw ( self , dc ) :
2015-05-20 21:31:40 +00:00
dc . SetBackground ( wx . Brush ( self . GetParent ( ) . GetBackgroundColour ( ) ) )
dc . Clear ( )
if self . _current_media is not None :
( self . _rating_state , self . _rating ) = ClientRatings . GetNumericalStateFromMedia ( ( self . _current_media , ) , self . _service_key )
2015-06-10 19:40:25 +00:00
ClientRatings . DrawNumerical ( dc , 0 , 0 , self . _service_key , self . _rating_state , self . _rating )
2015-05-20 21:31:40 +00:00
self . _dirty = False
def EventLeftDown ( self , event ) :
if self . _current_media is not None :
rating = self . _GetRatingFromClickEvent ( event )
if rating is not None :
2015-10-14 21:02:25 +00:00
content_update = HydrusData . ContentUpdate ( HC . CONTENT_TYPE_RATINGS , HC . CONTENT_UPDATE_ADD , ( rating , self . _hashes ) )
2015-05-20 21:31:40 +00:00
2017-05-10 21:33:58 +00:00
HG . client_controller . Write ( ' content_updates ' , { self . _service_key : ( content_update , ) } )
2015-05-20 21:31:40 +00:00
def EventRightDown ( self , event ) :
if self . _current_media is not None :
rating = None
2015-10-14 21:02:25 +00:00
content_update = HydrusData . ContentUpdate ( HC . CONTENT_TYPE_RATINGS , HC . CONTENT_UPDATE_ADD , ( rating , self . _hashes ) )
2015-05-20 21:31:40 +00:00
2017-05-10 21:33:58 +00:00
HG . client_controller . Write ( ' content_updates ' , { self . _service_key : ( content_update , ) } )
2015-05-20 21:31:40 +00:00
def ProcessContentUpdates ( self , service_keys_to_content_updates ) :
if self . _current_media is not None :
for ( service_key , content_updates ) in service_keys_to_content_updates . items ( ) :
for content_update in content_updates :
( data_type , action , row ) = content_update . ToTuple ( )
2015-10-14 21:02:25 +00:00
if data_type == HC . CONTENT_TYPE_RATINGS :
2015-05-20 21:31:40 +00:00
hashes = content_update . GetHashes ( )
if len ( self . _hashes . intersection ( hashes ) ) > 0 :
self . _dirty = True
self . Refresh ( )
return
def SetDisplayMedia ( self , canvas_key , media ) :
if canvas_key == self . _canvas_key :
self . _current_media = media
2015-11-18 22:44:07 +00:00
if self . _current_media is None :
self . _hashes = set ( )
else :
self . _hashes = self . _current_media . GetHashes ( )
2015-05-20 21:31:40 +00:00
self . _dirty = True
self . Refresh ( )
2015-05-13 20:22:39 +00:00
2017-09-06 20:18:20 +00:00
class RegexButton ( BetterButton ) :
2015-02-03 20:40:21 +00:00
def __init__ ( self , parent ) :
2013-07-24 20:26:00 +00:00
2017-09-06 20:18:20 +00:00
BetterButton . __init__ ( self , parent , ' regex shortcuts ' , self . _ShowMenu )
2013-07-24 20:26:00 +00:00
2015-02-03 20:40:21 +00:00
2017-09-06 20:18:20 +00:00
def _ShowMenu ( self ) :
2013-11-06 18:22:07 +00:00
2015-02-03 20:40:21 +00:00
menu = wx . Menu ( )
2013-07-24 20:26:00 +00:00
2017-09-06 20:18:20 +00:00
ClientGUIMenus . AppendMenuLabel ( menu , ' click on a phrase to copy it to the clipboard ' )
2013-07-24 20:26:00 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus . AppendSeparator ( menu )
2014-03-12 22:08:23 +00:00
2015-09-23 21:21:02 +00:00
submenu = wx . Menu ( )
2015-02-03 20:40:21 +00:00
2017-09-06 20:18:20 +00:00
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' whitespace character - \ s ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' \ s ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' number character - \ d ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' \ d ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' alphanumeric or backspace character - \ w ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' \ w ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' any character - . ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' . ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' backslash character - \\ ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' \\ ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' beginning of line - ^ ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' ^ ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' end of line - $ ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' $ ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , u ' any of these - [ \u2026 ] ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , u ' [ \u2026 ] ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , u ' anything other than these - [^ \u2026 ] ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , u ' [^ \u2026 ] ' )
2015-02-03 20:40:21 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus . AppendSeparator ( submenu )
2015-02-03 20:40:21 +00:00
2017-09-06 20:18:20 +00:00
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' 0 or more matches, consuming as many as possible - * ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' * ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' 1 or more matches, consuming as many as possible - + ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' + ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' 0 or 1 matches, preferring 1 - ? ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' ? ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' 0 or more matches, consuming as few as possible - *? ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' *? ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' 1 or more matches, consuming as few as possible - +? ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' +? ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' 0 or 1 matches, preferring 0 - ?? ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' ?? ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' exactly m matches - {m} ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' {m} ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' m to n matches, consuming as many as possible - { m,n} ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' { m,n} ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' m to n matches, consuming as few as possible - { m,n}? ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' { m,n}? ' )
2015-02-03 20:40:21 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus . AppendSeparator ( submenu )
2015-02-03 20:40:21 +00:00
2017-09-06 20:18:20 +00:00
ClientGUIMenus . AppendMenuItem ( self , submenu , u ' the next characters are: (non-consuming) - (?= \u2026 ) ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , u ' (?= \u2026 ) ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , u ' the next characters are not: (non-consuming) - (?! \u2026 ) ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , u ' (?! \u2026 ) ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , u ' the previous characters are: (non-consuming) - (?<= \u2026 ) ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , u ' (?<= \u2026 ) ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , u ' the previous characters are not: (non-consuming) - (?<! \u2026 ) ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , u ' (?<! \u2026 ) ' )
2015-02-03 20:40:21 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus . AppendSeparator ( submenu )
2015-02-03 20:40:21 +00:00
2017-09-06 20:18:20 +00:00
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' 0074 -> 74 - [1-9]+ \ d* ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , r ' [1-9]+ \ d* ' )
ClientGUIMenus . AppendMenuItem ( self , submenu , r ' filename - (?<= ' + os . path . sep . encode ( ' string_escape ' ) + r ' )[^ ' + os . path . sep . encode ( ' string_escape ' ) + r ' ]*?(?= \ ..*$) ' , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , ' (?<= ' + os . path . sep . encode ( ' string_escape ' ) + r ' )[^ ' + os . path . sep . encode ( ' string_escape ' ) + r ' ]*?(?= \ ..*$) ' )
2015-09-23 21:21:02 +00:00
2017-09-06 20:18:20 +00:00
ClientGUIMenus . AppendMenu ( menu , submenu , ' regex components ' )
2015-09-23 21:21:02 +00:00
submenu = wx . Menu ( )
2017-09-06 20:18:20 +00:00
ClientGUIMenus . AppendMenuItem ( self , submenu , ' manage favourites ' , ' manage some custom favourite phrases ' , self . _ManageFavourites )
2015-09-23 21:21:02 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus . AppendSeparator ( submenu )
2015-09-23 21:21:02 +00:00
2017-09-06 20:18:20 +00:00
for ( regex_phrase , description ) in HC . options [ ' regex_favourites ' ] :
2015-09-23 21:21:02 +00:00
2017-09-06 20:18:20 +00:00
ClientGUIMenus . AppendMenuItem ( self , submenu , description , ' copy this phrase to the clipboard ' , HG . client_controller . pub , ' clipboard ' , ' text ' , regex_phrase )
2015-09-23 21:21:02 +00:00
2015-02-03 20:40:21 +00:00
2017-09-06 20:18:20 +00:00
ClientGUIMenus . AppendMenu ( menu , submenu , ' favourites ' )
2015-02-03 20:40:21 +00:00
2017-05-10 21:33:58 +00:00
HG . client_controller . PopupMenu ( self , menu )
2014-03-12 22:08:23 +00:00
2017-09-06 20:18:20 +00:00
def _ManageFavourites ( self ) :
2013-02-19 00:11:43 +00:00
2017-11-08 22:07:12 +00:00
regex_favourites = HC . options [ ' regex_favourites ' ]
2013-02-19 00:11:43 +00:00
2017-11-08 22:07:12 +00:00
with ClientGUITopLevelWindows . DialogEdit ( self , ' manage regex favourites ' ) as dlg :
2015-09-23 21:21:02 +00:00
2017-11-08 22:07:12 +00:00
import ClientGUIScrolledPanelsEdit
panel = ClientGUIScrolledPanelsEdit . EditRegexFavourites ( dlg , regex_favourites )
dlg . SetPanel ( panel )
if dlg . ShowModal ( ) == wx . ID_OK :
regex_favourites = panel . GetValue ( )
HC . options [ ' regex_favourites ' ] = regex_favourites
HG . client_controller . Write ( ' save_options ' , HC . options )
2015-09-23 21:21:02 +00:00
2013-02-19 00:11:43 +00:00
2016-11-02 21:09:14 +00:00
class SaneMultilineTextCtrl ( wx . TextCtrl ) :
def __init__ ( self , parent , style = None ) :
if style is None :
style = wx . TE_MULTILINE
else :
style | = wx . TE_MULTILINE
wx . TextCtrl . __init__ ( self , parent , style = style )
self . Bind ( wx . EVT_KEY_DOWN , self . EventKeyDown )
def EventKeyDown ( self , event ) :
ctrl = event . CmdDown ( )
key_code = event . GetKeyCode ( )
if ctrl and key_code in ( ord ( ' A ' ) , ord ( ' a ' ) ) :
self . SelectAll ( )
else :
event . Skip ( )
2017-04-12 21:46:46 +00:00
class Shortcut ( wx . Panel ) :
2013-10-09 18:13:42 +00:00
2017-04-12 21:46:46 +00:00
def __init__ ( self , parent ) :
wx . Panel . __init__ ( self , parent )
self . _mouse_radio = wx . RadioButton ( self , style = wx . RB_GROUP , label = ' mouse ' )
self . _mouse_shortcut = ShortcutMouse ( self , self . _mouse_radio )
self . _keyboard_radio = wx . RadioButton ( self , label = ' keyboard ' )
self . _keyboard_shortcut = ShortcutKeyboard ( self , self . _keyboard_radio )
#
vbox = wx . BoxSizer ( wx . VERTICAL )
2018-01-03 22:37:30 +00:00
vbox . Add ( BetterStaticText ( self , ' Mouse events only work for the duplicate and archive/delete filters atm! ' ) , CC . FLAGS_EXPAND_PERPENDICULAR )
2017-04-12 21:46:46 +00:00
2018-01-03 22:37:30 +00:00
gridbox = wx . FlexGridSizer ( 2 )
2017-04-12 21:46:46 +00:00
gridbox . AddGrowableCol ( 1 , 1 )
2018-01-03 22:37:30 +00:00
gridbox . Add ( self . _mouse_radio , CC . FLAGS_VCENTER )
gridbox . Add ( self . _mouse_shortcut , CC . FLAGS_EXPAND_BOTH_WAYS )
gridbox . Add ( self . _keyboard_radio , CC . FLAGS_VCENTER )
gridbox . Add ( self . _keyboard_shortcut , CC . FLAGS_EXPAND_BOTH_WAYS )
2017-04-12 21:46:46 +00:00
2018-01-03 22:37:30 +00:00
vbox . Add ( gridbox , CC . FLAGS_EXPAND_BOTH_WAYS )
2017-04-12 21:46:46 +00:00
self . SetSizer ( vbox )
def GetValue ( self ) :
if self . _mouse_radio . GetValue ( ) == True :
return self . _mouse_shortcut . GetValue ( )
else :
return self . _keyboard_shortcut . GetValue ( )
def SetValue ( self , shortcut ) :
if shortcut . GetShortcutType ( ) == CC . SHORTCUT_TYPE_MOUSE :
self . _mouse_radio . SetValue ( True )
self . _mouse_shortcut . SetValue ( shortcut )
else :
self . _keyboard_radio . SetValue ( True )
self . _keyboard_shortcut . SetValue ( shortcut )
class ShortcutKeyboard ( wx . TextCtrl ) :
def __init__ ( self , parent , related_radio = None ) :
self . _shortcut = ClientData . Shortcut ( CC . SHORTCUT_TYPE_KEYBOARD , wx . WXK_F7 , [ ] )
2015-02-03 20:40:21 +00:00
2017-04-12 21:46:46 +00:00
self . _related_radio = related_radio
2015-02-03 20:40:21 +00:00
wx . TextCtrl . __init__ ( self , parent , style = wx . TE_PROCESS_ENTER )
self . Bind ( wx . EVT_KEY_DOWN , self . EventKeyDown )
self . _SetShortcutString ( )
2013-10-09 18:13:42 +00:00
2015-02-03 20:40:21 +00:00
def _SetShortcutString ( self ) :
2013-10-09 18:13:42 +00:00
2017-04-12 21:46:46 +00:00
display_string = self . _shortcut . ToString ( )
2015-02-03 20:40:21 +00:00
wx . TextCtrl . SetValue ( self , display_string )
def EventKeyDown ( self , event ) :
2017-04-12 21:46:46 +00:00
shortcut = ClientData . ConvertKeyEventToShortcut ( event )
if shortcut is not None :
self . _shortcut = shortcut
if self . _related_radio is not None :
self . _related_radio . SetValue ( True )
self . _SetShortcutString ( )
def GetValue ( self ) :
return self . _shortcut
def SetValue ( self , shortcut ) :
self . _shortcut = shortcut
self . _SetShortcutString ( )
class ShortcutMouse ( wx . Button ) :
def __init__ ( self , parent , related_radio = None ) :
self . _shortcut = ClientData . Shortcut ( CC . SHORTCUT_TYPE_MOUSE , CC . SHORTCUT_MOUSE_LEFT , [ ] )
2017-04-05 21:16:40 +00:00
2017-04-12 21:46:46 +00:00
self . _related_radio = related_radio
wx . Button . __init__ ( self , parent )
self . Bind ( wx . EVT_MOUSE_EVENTS , self . EventMouse )
self . _SetShortcutString ( )
def _SetShortcutString ( self ) :
display_string = self . _shortcut . ToString ( )
self . SetLabel ( display_string )
def EventMouse ( self , event ) :
2017-09-13 20:50:41 +00:00
self . SetFocus ( )
2017-04-12 21:46:46 +00:00
shortcut = ClientData . ConvertMouseEventToShortcut ( event )
if shortcut is not None :
2013-10-09 18:13:42 +00:00
2017-04-12 21:46:46 +00:00
self . _shortcut = shortcut
if self . _related_radio is not None :
self . _related_radio . SetValue ( True )
2013-10-09 18:13:42 +00:00
2015-02-03 20:40:21 +00:00
self . _SetShortcutString ( )
2017-04-12 21:46:46 +00:00
2013-10-09 18:13:42 +00:00
2015-02-03 20:40:21 +00:00
2017-04-12 21:46:46 +00:00
def GetValue ( self ) :
return self . _shortcut
2015-02-03 20:40:21 +00:00
2017-04-12 21:46:46 +00:00
def SetValue ( self , shortcut ) :
2013-10-09 18:13:42 +00:00
2017-04-12 21:46:46 +00:00
self . _shortcut = shortcut
2015-02-03 20:40:21 +00:00
self . _SetShortcutString ( )
2013-10-09 18:13:42 +00:00
2015-02-03 20:40:21 +00:00
class StaticBox ( wx . Panel ) :
2013-10-09 18:13:42 +00:00
2015-02-03 20:40:21 +00:00
def __init__ ( self , parent , title ) :
2013-10-09 18:13:42 +00:00
2015-02-03 20:40:21 +00:00
wx . Panel . __init__ ( self , parent , style = wx . BORDER_DOUBLE )
2013-10-09 18:13:42 +00:00
2016-08-10 19:04:08 +00:00
self . SetBackgroundColour ( wx . SystemSettings . GetColour ( wx . SYS_COLOUR_FRAMEBK ) )
2015-02-03 20:40:21 +00:00
self . _sizer = wx . BoxSizer ( wx . VERTICAL )
normal_font = wx . SystemSettings . GetFont ( wx . SYS_DEFAULT_GUI_FONT )
normal_font_size = normal_font . GetPointSize ( )
normal_font_family = normal_font . GetFamily ( )
title_font = wx . Font ( int ( normal_font_size ) , normal_font_family , wx . FONTSTYLE_NORMAL , wx . FONTWEIGHT_BOLD )
title_text = wx . StaticText ( self , label = title , style = wx . ALIGN_CENTER )
title_text . SetFont ( title_font )
2018-01-03 22:37:30 +00:00
self . _sizer . Add ( title_text , CC . FLAGS_EXPAND_PERPENDICULAR )
2015-02-03 20:40:21 +00:00
self . SetSizer ( self . _sizer )
2013-10-09 18:13:42 +00:00
2018-01-31 22:58:15 +00:00
def Add ( self , widget , flags ) :
self . _sizer . Add ( widget , flags )
2015-02-03 20:40:21 +00:00
class StaticBoxSorterForListBoxTags ( StaticBox ) :
def __init__ ( self , parent , title ) :
2013-10-09 18:13:42 +00:00
2015-02-03 20:40:21 +00:00
StaticBox . __init__ ( self , parent , title )
self . _sorter = wx . Choice ( self )
self . _sorter . Append ( ' lexicographic (a-z) ' , CC . SORT_BY_LEXICOGRAPHIC_ASC )
self . _sorter . Append ( ' lexicographic (z-a) ' , CC . SORT_BY_LEXICOGRAPHIC_DESC )
2016-04-27 19:20:37 +00:00
self . _sorter . Append ( ' lexicographic (a-z) (grouped by namespace) ' , CC . SORT_BY_LEXICOGRAPHIC_NAMESPACE_ASC )
self . _sorter . Append ( ' lexicographic (z-a) (grouped by namespace) ' , CC . SORT_BY_LEXICOGRAPHIC_NAMESPACE_DESC )
2015-02-03 20:40:21 +00:00
self . _sorter . Append ( ' incidence (desc) ' , CC . SORT_BY_INCIDENCE_DESC )
self . _sorter . Append ( ' incidence (asc) ' , CC . SORT_BY_INCIDENCE_ASC )
2016-09-28 18:48:01 +00:00
self . _sorter . Append ( ' incidence (desc) (grouped by namespace) ' , CC . SORT_BY_INCIDENCE_NAMESPACE_DESC )
self . _sorter . Append ( ' incidence (asc) (grouped by namespace) ' , CC . SORT_BY_INCIDENCE_NAMESPACE_ASC )
2015-02-03 20:40:21 +00:00
if HC . options [ ' default_tag_sort ' ] == CC . SORT_BY_LEXICOGRAPHIC_ASC : self . _sorter . Select ( 0 )
elif HC . options [ ' default_tag_sort ' ] == CC . SORT_BY_LEXICOGRAPHIC_DESC : self . _sorter . Select ( 1 )
2016-04-27 19:20:37 +00:00
elif HC . options [ ' default_tag_sort ' ] == CC . SORT_BY_LEXICOGRAPHIC_NAMESPACE_ASC : self . _sorter . Select ( 2 )
elif HC . options [ ' default_tag_sort ' ] == CC . SORT_BY_LEXICOGRAPHIC_NAMESPACE_DESC : self . _sorter . Select ( 3 )
elif HC . options [ ' default_tag_sort ' ] == CC . SORT_BY_INCIDENCE_DESC : self . _sorter . Select ( 4 )
elif HC . options [ ' default_tag_sort ' ] == CC . SORT_BY_INCIDENCE_ASC : self . _sorter . Select ( 5 )
2016-09-28 18:48:01 +00:00
elif HC . options [ ' default_tag_sort ' ] == CC . SORT_BY_INCIDENCE_NAMESPACE_DESC : self . _sorter . Select ( 6 )
elif HC . options [ ' default_tag_sort ' ] == CC . SORT_BY_INCIDENCE_NAMESPACE_ASC : self . _sorter . Select ( 7 )
2015-02-03 20:40:21 +00:00
self . _sorter . Bind ( wx . EVT_CHOICE , self . EventSort )
2018-01-03 22:37:30 +00:00
self . Add ( self . _sorter , CC . FLAGS_EXPAND_PERPENDICULAR )
2015-02-03 20:40:21 +00:00
2016-01-13 22:08:19 +00:00
def ChangeTagService ( self , service_key ) : self . _tags_box . ChangeTagService ( service_key )
2015-02-03 20:40:21 +00:00
def EventSort ( self , event ) :
selection = self . _sorter . GetSelection ( )
if selection != wx . NOT_FOUND :
2013-10-09 18:13:42 +00:00
2015-02-03 20:40:21 +00:00
sort = self . _sorter . GetClientData ( selection )
2013-10-09 18:13:42 +00:00
2015-02-03 20:40:21 +00:00
self . _tags_box . SetSort ( sort )
2013-10-09 18:13:42 +00:00
2015-02-03 20:40:21 +00:00
def SetTagsBox ( self , tags_box ) :
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
self . _tags_box = tags_box
2013-02-19 00:11:43 +00:00
2018-01-03 22:37:30 +00:00
self . Add ( self . _tags_box , CC . FLAGS_EXPAND_BOTH_WAYS )
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
2015-11-11 21:20:41 +00:00
def SetTagsByMedia ( self , media , force_reload = False ) :
self . _tags_box . SetTagsByMedia ( media , force_reload = force_reload )
2015-02-03 20:40:21 +00:00
2017-09-27 21:52:54 +00:00
class RadioBox ( StaticBox ) :
def __init__ ( self , parent , title , choice_pairs , initial_index = None ) :
StaticBox . __init__ ( self , parent , title )
self . _indices_to_radio_buttons = { }
self . _radio_buttons_to_data = { }
first_button = True
for ( index , ( text , data ) ) in enumerate ( choice_pairs ) :
if first_button :
style = wx . RB_GROUP
first_button = False
else : style = 0
radio_button = wx . RadioButton ( self , label = text , style = style )
2018-01-03 22:37:30 +00:00
self . Add ( radio_button , CC . FLAGS_EXPAND_PERPENDICULAR )
2017-09-27 21:52:54 +00:00
self . _indices_to_radio_buttons [ index ] = radio_button
self . _radio_buttons_to_data [ radio_button ] = data
if initial_index is not None and initial_index in self . _indices_to_radio_buttons : self . _indices_to_radio_buttons [ initial_index ] . SetValue ( True )
def GetSelectedClientData ( self ) :
for radio_button in self . _radio_buttons_to_data . keys ( ) :
if radio_button . GetValue ( ) == True : return self . _radio_buttons_to_data [ radio_button ]
2017-11-29 21:48:23 +00:00
def SetSelection ( self , index ) :
self . _indices_to_radio_buttons [ index ] . SetValue ( True )
2017-09-27 21:52:54 +00:00
2017-11-29 21:48:23 +00:00
def SetString ( self , index , text ) :
self . _indices_to_radio_buttons [ index ] . SetLabelText ( text )
2017-09-27 21:52:54 +00:00
2017-01-11 22:31:30 +00:00
class TextAndGauge ( wx . Panel ) :
def __init__ ( self , parent ) :
wx . Panel . __init__ ( self , parent )
2017-04-19 20:58:30 +00:00
self . _st = BetterStaticText ( self )
2017-01-11 22:31:30 +00:00
self . _gauge = Gauge ( self )
vbox = wx . BoxSizer ( wx . VERTICAL )
2018-01-03 22:37:30 +00:00
vbox . Add ( self . _st , CC . FLAGS_EXPAND_PERPENDICULAR )
vbox . Add ( self . _gauge , CC . FLAGS_EXPAND_PERPENDICULAR )
2017-01-11 22:31:30 +00:00
self . SetSizer ( vbox )
def SetValue ( self , text , value , range ) :
2017-11-29 21:48:23 +00:00
if not self :
return
2017-07-05 21:09:28 +00:00
if text != self . _st . GetLabelText ( ) :
self . _st . SetLabelText ( text )
2017-01-11 22:31:30 +00:00
2017-07-12 20:03:45 +00:00
self . _gauge . SetRange ( range )
self . _gauge . SetValue ( value )
2017-01-11 22:31:30 +00:00
2017-12-13 22:33:07 +00:00
class TextAndPasteCtrl ( wx . Panel ) :
def __init__ ( self , parent , add_callable ) :
self . _add_callable = add_callable
wx . Panel . __init__ ( self , parent )
self . _text_input = wx . TextCtrl ( self , style = wx . TE_PROCESS_ENTER )
self . _text_input . Bind ( wx . EVT_KEY_DOWN , self . EventKeyDown )
self . _paste_button = BetterBitmapButton ( self , CC . GlobalBMPs . paste , self . _Paste )
2018-01-03 22:37:30 +00:00
self . _paste_button . SetToolTip ( ' Paste multiple inputs from the clipboard. Assumes the texts are newline-separated. ' )
2017-12-13 22:33:07 +00:00
#
hbox = wx . BoxSizer ( wx . HORIZONTAL )
2018-01-03 22:37:30 +00:00
hbox . Add ( self . _text_input , CC . FLAGS_EXPAND_BOTH_WAYS )
hbox . Add ( self . _paste_button , CC . FLAGS_VCENTER )
2017-12-13 22:33:07 +00:00
self . SetSizer ( hbox )
def _Paste ( self ) :
raw_text = HG . client_controller . GetClipboardText ( )
try :
texts = [ text for text in HydrusText . DeserialiseNewlinedTexts ( raw_text ) if text != ' ' ]
if len ( texts ) > 0 :
self . _add_callable ( texts )
except :
wx . MessageBox ( ' I could not understand what was in the clipboard ' )
def EventKeyDown ( self , event ) :
( modifier , key ) = ClientData . ConvertKeyEventToSimpleTuple ( event )
if key in ( wx . WXK_RETURN , wx . WXK_NUMPAD_ENTER ) :
text = self . _text_input . GetValue ( )
if text != ' ' :
self . _add_callable ( ( text , ) )
self . _text_input . SetValue ( ' ' )
else :
event . Skip ( )
def GetValue ( self ) :
return self . _text_input . GetValue ( )
def SetValue ( self , text ) :
self . _text_input . SetValue ( text )
2017-02-01 21:11:17 +00:00
class ThreadToGUIUpdater ( object ) :
2018-03-07 22:48:29 +00:00
def __init__ ( self , win , func ) :
2017-02-01 21:11:17 +00:00
2018-03-07 22:48:29 +00:00
self . _win = win
2017-02-01 21:11:17 +00:00
self . _func = func
self . _lock = threading . Lock ( )
self . _dirty_count = 0
2018-03-07 22:48:29 +00:00
2017-02-01 21:11:17 +00:00
self . _args = None
self . _kwargs = None
2018-03-07 22:48:29 +00:00
self . _doing_it = False
2017-02-01 21:11:17 +00:00
2018-03-07 22:48:29 +00:00
def WXDoIt ( self ) :
2017-02-01 21:11:17 +00:00
with self . _lock :
2018-03-07 22:48:29 +00:00
if not self . _win :
self . _win = None
return
2017-06-21 21:15:59 +00:00
try :
self . _func ( * self . _args , * * self . _kwargs )
except HydrusExceptions . ShutdownException :
pass
2017-02-01 21:11:17 +00:00
self . _dirty_count = 0
2018-03-07 22:48:29 +00:00
self . _doing_it = False
2017-02-01 21:11:17 +00:00
2018-03-07 22:48:29 +00:00
# the point here is that we can spam this a hundred times a second, updating the args and kwargs, and wx will catch up to it when it can
2017-02-01 21:11:17 +00:00
# if wx feels like running fast, it'll update at 60fps
# if not, we won't get bungled up with 10,000+ pubsub events in the event queue
def Update ( self , * args , * * kwargs ) :
with self . _lock :
self . _args = args
self . _kwargs = kwargs
2018-03-07 22:48:29 +00:00
if not self . _doing_it and not HG . view_shutdown :
2017-02-01 21:11:17 +00:00
2018-03-07 22:48:29 +00:00
wx . CallAfter ( self . WXDoIt )
2017-02-01 21:11:17 +00:00
2018-03-07 22:48:29 +00:00
self . _doing_it = True
2017-02-01 21:11:17 +00:00
self . _dirty_count + = 1
take_a_break = self . _dirty_count % 1000 == 0
# just in case we are choking the wx thread, let's give it a break every now and then
if take_a_break :
time . sleep ( 0.25 )