hydrus/include/ClientGUIDialogs.py

1330 lines
42 KiB
Python
Raw Normal View History

2019-01-09 22:59:03 +00:00
from . import HydrusConstants as HC
from . import ClientConstants as CC
from . import ClientData
from . import ClientDefaults
from . import ClientDownloading
from . import ClientDragDrop
from . import ClientExporting
from . import ClientCaches
from . import ClientFiles
from . import ClientGUIACDropdown
from . import ClientGUIFrames
from . import ClientGUICommon
from . import ClientGUIDialogsQuick
2019-06-26 21:27:18 +00:00
from . import ClientGUIFunctions
2019-01-09 22:59:03 +00:00
from . import ClientGUIImport
from . import ClientGUIListBoxes
from . import ClientGUIListCtrl
from . import ClientGUIPredicates
from . import ClientGUIShortcuts
from . import ClientGUITime
from . import ClientGUITopLevelWindows
from . import ClientImporting
2019-02-27 23:03:30 +00:00
from . import ClientTags
2019-01-09 22:59:03 +00:00
from . import ClientThreading
2013-02-19 00:11:43 +00:00
import collections
2014-01-01 20:01:00 +00:00
import gc
2019-01-09 22:59:03 +00:00
from . import HydrusExceptions
from . import HydrusFileHandling
from . import HydrusNATPunch
from . import HydrusNetwork
from . import HydrusPaths
from . import HydrusSerialisable
from . import HydrusTags
from . import HydrusThreading
2013-06-12 22:53:31 +00:00
import itertools
2013-02-19 00:11:43 +00:00
import os
import random
import re
2019-01-09 22:59:03 +00:00
import queue
2013-08-14 20:21:49 +00:00
import shutil
2013-11-20 21:12:21 +00:00
import stat
2013-07-17 20:56:13 +00:00
import string
2013-09-11 21:28:19 +00:00
import threading
2013-02-19 00:11:43 +00:00
import time
import traceback
import wx
2016-03-23 19:42:56 +00:00
import wx.lib.agw.customtreectrl
2013-02-19 00:11:43 +00:00
import yaml
2019-01-09 22:59:03 +00:00
from . import HydrusData
from . import ClientSearch
from . import HydrusGlobals as HG
2013-02-19 00:11:43 +00:00
# Option Enums
ID_NULL = wx.NewId()
ID_TIMER_UPDATE = wx.NewId()
2017-03-02 02:14:56 +00:00
def SelectServiceKey( service_types = HC.ALL_SERVICES, service_keys = None, unallowed = None ):
2013-02-19 00:11:43 +00:00
2014-08-27 22:15:22 +00:00
if service_keys is None:
2013-02-19 00:11:43 +00:00
2017-06-28 20:23:21 +00:00
services = HG.client_controller.services_manager.GetServices( service_types )
2013-02-19 00:11:43 +00:00
2014-09-17 21:28:26 +00:00
service_keys = [ service.GetServiceKey() for service in services ]
2013-02-19 00:11:43 +00:00
2017-03-02 02:14:56 +00:00
if unallowed is not None:
service_keys.difference_update( unallowed )
2013-02-19 00:11:43 +00:00
2017-03-02 02:14:56 +00:00
if len( service_keys ) == 0:
return None
2014-08-27 22:15:22 +00:00
elif len( service_keys ) == 1:
2013-02-19 00:11:43 +00:00
2014-08-27 22:15:22 +00:00
( service_key, ) = service_keys
2013-02-19 00:11:43 +00:00
2014-08-27 22:15:22 +00:00
return service_key
2013-02-19 00:11:43 +00:00
else:
2017-06-28 20:23:21 +00:00
services = { HG.client_controller.services_manager.GetService( service_key ) for service_key in service_keys }
2013-02-19 00:11:43 +00:00
2018-08-08 20:29:54 +00:00
choice_tuples = [ ( service.GetName(), service.GetServiceKey() ) for service in services ]
2014-08-27 22:15:22 +00:00
2018-11-14 23:10:55 +00:00
try:
2013-02-19 00:11:43 +00:00
2018-11-14 23:10:55 +00:00
service_key = ClientGUIDialogsQuick.SelectFromList( HG.client_controller.GetGUI(), 'select service', choice_tuples )
return service_key
except HydrusExceptions.CancelledException:
return None
2013-02-19 00:11:43 +00:00
class Dialog( wx.Dialog ):
def __init__( self, parent, title, style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, position = 'topleft' ):
2013-07-31 21:26:38 +00:00
if parent is not None and position == 'topleft':
2013-02-19 00:11:43 +00:00
2016-01-13 22:08:19 +00:00
if isinstance( parent, wx.TopLevelWindow ):
parent_tlp = parent
else:
parent_tlp = parent.GetTopLevelParent()
2015-02-25 19:34:30 +00:00
2018-01-03 22:37:30 +00:00
( pos_x, pos_y ) = parent_tlp.GetPosition()
2013-02-19 00:11:43 +00:00
2016-06-22 20:59:24 +00:00
pos = ( pos_x + 50, pos_y + 50 )
2013-02-19 00:11:43 +00:00
2016-01-13 22:08:19 +00:00
else:
pos = wx.DefaultPosition
2015-08-26 21:18:39 +00:00
if not HC.PLATFORM_LINUX and parent is not None:
style |= wx.FRAME_FLOAT_ON_PARENT
2013-02-19 00:11:43 +00:00
wx.Dialog.__init__( self, parent, title = title, style = style, pos = pos )
2017-12-06 22:06:56 +00:00
self._new_options = HG.client_controller.new_options
2016-06-29 19:55:46 +00:00
2016-08-10 19:04:08 +00:00
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_FRAMEBK ) )
2013-02-19 00:11:43 +00:00
2017-11-15 22:35:49 +00:00
self.SetIcon( HG.client_controller.frame_icon )
2013-02-19 00:11:43 +00:00
2019-02-27 23:03:30 +00:00
self.Bind( wx.EVT_CHAR_HOOK, self.EventCharHook )
2013-07-24 20:26:00 +00:00
2015-08-26 21:18:39 +00:00
if parent is not None and position == 'center':
wx.CallAfter( self.Center )
2014-02-05 20:54:28 +00:00
2017-05-10 21:33:58 +00:00
HG.client_controller.ResetIdleTimer()
2014-12-03 22:56:40 +00:00
2013-07-24 20:26:00 +00:00
2019-02-27 23:03:30 +00:00
def EventCharHook( self, event ):
( modifier, key ) = ClientGUIShortcuts.ConvertKeyEventToSimpleTuple( event )
if key == wx.WXK_ESCAPE:
self.EndModal( wx.ID_CANCEL )
else:
event.Skip()
2019-01-09 22:59:03 +00:00
def SetInitialSize( self, size ):
( width, height ) = size
2015-01-07 23:09:00 +00:00
2016-12-21 22:30:54 +00:00
( display_width, display_height ) = ClientGUITopLevelWindows.GetDisplaySize( self )
2015-11-11 21:20:41 +00:00
width = min( display_width, width )
height = min( display_height, height )
2015-01-07 23:09:00 +00:00
wx.Dialog.SetInitialSize( self, ( width, height ) )
min_width = min( 240, width )
2015-11-18 22:44:07 +00:00
min_height = min( 240, height )
2015-01-07 23:09:00 +00:00
self.SetMinSize( ( min_width, min_height ) )
2013-03-15 02:38:12 +00:00
class DialogChooseNewServiceMethod( Dialog ):
def __init__( self, parent ):
2015-05-20 21:31:40 +00:00
Dialog.__init__( self, parent, 'how to set up the account?', position = 'center' )
2013-07-31 21:26:38 +00:00
2015-05-20 21:31:40 +00:00
register_message = 'I want to initialise a new account with the server. I have a registration key (a key starting with \'r\').'
2013-03-15 02:38:12 +00:00
2015-05-20 21:31:40 +00:00
self._register = wx.Button( self, label = register_message )
self._register.Bind( wx.EVT_BUTTON, self.EventRegister )
2013-03-15 02:38:12 +00:00
2015-05-20 21:31:40 +00:00
setup_message = 'The account is already initialised; I just want to add it to this client. I have a normal access key.'
2013-03-15 02:38:12 +00:00
2015-05-20 21:31:40 +00:00
self._setup = wx.Button( self, id = wx.ID_OK, label = setup_message )
2013-07-31 21:26:38 +00:00
2015-05-20 21:31:40 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
2018-01-03 22:37:30 +00:00
vbox.Add( self._register, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.Add( wx.StaticText( self, label = '-or-', style = wx.ALIGN_CENTER ), CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.Add( self._setup, CC.FLAGS_EXPAND_PERPENDICULAR )
2015-05-20 21:31:40 +00:00
self.SetSizer( vbox )
( x, y ) = self.GetEffectiveMinSize()
self.SetInitialSize( ( x, y ) )
2013-03-15 02:38:12 +00:00
2013-07-24 20:26:00 +00:00
self._should_register = False
2013-03-15 02:38:12 +00:00
2013-07-31 21:26:38 +00:00
wx.CallAfter( self._register.SetFocus )
2013-03-15 02:38:12 +00:00
def EventRegister( self, event ):
2013-07-24 20:26:00 +00:00
self._should_register = True
2013-03-15 02:38:12 +00:00
self.EndModal( wx.ID_OK )
2019-05-22 22:35:06 +00:00
def GetRegister( self ):
return self._should_register
2013-03-15 02:38:12 +00:00
2013-11-27 18:27:11 +00:00
class DialogGenerateNewAccounts( Dialog ):
2014-08-27 22:15:22 +00:00
def __init__( self, parent, service_key ):
2013-11-27 18:27:11 +00:00
2015-12-09 23:16:41 +00:00
Dialog.__init__( self, parent, 'configure new accounts' )
2013-11-27 18:27:11 +00:00
2015-12-09 23:16:41 +00:00
self._service_key = service_key
2013-11-27 18:27:11 +00:00
2015-12-09 23:16:41 +00:00
self._num = wx.SpinCtrl( self, min = 1, max = 10000, size = ( 80, -1 ) )
2013-11-27 18:27:11 +00:00
2017-03-02 02:14:56 +00:00
self._account_types = ClientGUICommon.BetterChoice( self )
2013-11-27 18:27:11 +00:00
2017-03-02 02:14:56 +00:00
self._lifetime = ClientGUICommon.BetterChoice( self )
2015-12-09 23:16:41 +00:00
2019-05-22 22:35:06 +00:00
self._ok = wx.Button( self, id = wx.ID_OK, label = 'OK' )
2015-12-09 23:16:41 +00:00
self._ok.Bind( wx.EVT_BUTTON, self.EventOK )
self._ok.SetForegroundColour( ( 0, 128, 0 ) )
self._cancel = wx.Button( self, id = wx.ID_CANCEL, label = 'Cancel' )
self._cancel.SetForegroundColour( ( 128, 0, 0 ) )
#
self._num.SetValue( 1 )
2017-06-28 20:23:21 +00:00
service = HG.client_controller.services_manager.GetService( service_key )
2015-12-09 23:16:41 +00:00
response = service.Request( HC.GET, 'account_types' )
account_types = response[ 'account_types' ]
2017-03-02 02:14:56 +00:00
for account_type in account_types:
self._account_types.Append( account_type.GetTitle(), account_type )
self._account_types.Select( 0 )
2017-03-15 20:13:04 +00:00
for ( s, value ) in HC.lifetimes:
2017-03-02 02:14:56 +00:00
2017-03-15 20:13:04 +00:00
self._lifetime.Append( s, value )
2017-03-02 02:14:56 +00:00
2015-12-09 23:16:41 +00:00
self._lifetime.SetSelection( 3 ) # one year
2013-11-27 18:27:11 +00:00
2015-12-09 23:16:41 +00:00
#
ctrl_box = wx.BoxSizer( wx.HORIZONTAL )
2018-01-03 22:37:30 +00:00
ctrl_box.Add( ClientGUICommon.BetterStaticText( self, 'generate' ), CC.FLAGS_VCENTER )
ctrl_box.Add( self._num, CC.FLAGS_VCENTER )
ctrl_box.Add( self._account_types, CC.FLAGS_VCENTER )
ctrl_box.Add( ClientGUICommon.BetterStaticText( self, 'accounts, to expire in' ), CC.FLAGS_VCENTER )
ctrl_box.Add( self._lifetime, CC.FLAGS_VCENTER )
2013-11-27 18:27:11 +00:00
2015-12-09 23:16:41 +00:00
b_box = wx.BoxSizer( wx.HORIZONTAL )
2018-01-03 22:37:30 +00:00
b_box.Add( self._ok, CC.FLAGS_VCENTER )
b_box.Add( self._cancel, CC.FLAGS_VCENTER )
2013-11-27 18:27:11 +00:00
2015-12-09 23:16:41 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
2018-01-03 22:37:30 +00:00
vbox.Add( ctrl_box, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
vbox.Add( b_box, CC.FLAGS_BUTTON_SIZER )
2015-12-09 23:16:41 +00:00
self.SetSizer( vbox )
( x, y ) = self.GetEffectiveMinSize()
self.SetInitialSize( ( x, y ) )
2013-11-27 18:27:11 +00:00
wx.CallAfter( self._ok.SetFocus )
def EventOK( self, event ):
num = self._num.GetValue()
2019-07-24 21:39:02 +00:00
account_type = self._account_types.GetValue()
2017-03-02 02:14:56 +00:00
account_type_key = account_type.GetAccountTypeKey()
2013-11-27 18:27:11 +00:00
2019-07-24 21:39:02 +00:00
lifetime = self._lifetime.GetValue()
2013-11-27 18:27:11 +00:00
2017-03-02 02:14:56 +00:00
if lifetime is None:
expires = None
else:
expires = HydrusData.GetNow() + lifetime
2013-11-27 18:27:11 +00:00
2017-06-28 20:23:21 +00:00
service = HG.client_controller.services_manager.GetService( self._service_key )
2013-11-27 18:27:11 +00:00
try:
2017-03-15 20:13:04 +00:00
request_args = { 'num' : num, 'account_type_key' : account_type_key }
if expires is not None:
request_args[ 'expires' ] = expires
2013-11-27 18:27:11 +00:00
2014-01-29 21:59:42 +00:00
response = service.Request( HC.GET, 'registration_keys', request_args )
2013-11-27 18:27:11 +00:00
registration_keys = response[ 'registration_keys' ]
2016-11-02 21:09:14 +00:00
ClientGUIFrames.ShowKeys( 'registration', registration_keys )
2013-11-27 18:27:11 +00:00
2017-03-02 02:14:56 +00:00
finally:
self.EndModal( wx.ID_OK )
2013-11-27 18:27:11 +00:00
2014-07-09 22:15:14 +00:00
class DialogInputLocalBooruShare( Dialog ):
def __init__( self, parent, share_key, name, text, timeout, hashes, new_share = False ):
2015-12-09 23:16:41 +00:00
Dialog.__init__( self, parent, 'configure local booru share' )
2014-07-09 22:15:14 +00:00
2015-12-09 23:16:41 +00:00
self._name = wx.TextCtrl( self )
2014-07-09 22:15:14 +00:00
2016-11-02 21:09:14 +00:00
self._text = ClientGUICommon.SaneMultilineTextCtrl( self )
2015-12-09 23:16:41 +00:00
self._text.SetMinSize( ( -1, 100 ) )
message = 'expires in'
self._timeout_number = ClientGUICommon.NoneableSpinCtrl( self, message, none_phrase = 'no expiration', max = 1000000, multiplier = 1 )
self._timeout_multiplier = ClientGUICommon.BetterChoice( self )
self._timeout_multiplier.Append( 'minutes', 60 )
self._timeout_multiplier.Append( 'hours', 60 * 60 )
self._timeout_multiplier.Append( 'days', 60 * 60 * 24 )
self._copy_internal_share_link = wx.Button( self, label = 'copy internal share link' )
self._copy_internal_share_link.Bind( wx.EVT_BUTTON, self.EventCopyInternalShareURL )
self._copy_external_share_link = wx.Button( self, label = 'copy external share link' )
self._copy_external_share_link.Bind( wx.EVT_BUTTON, self.EventCopyExternalShareURL )
self._ok = wx.Button( self, id = wx.ID_OK, label = 'ok' )
self._ok.SetForegroundColour( ( 0, 128, 0 ) )
self._cancel = wx.Button( self, id = wx.ID_CANCEL, label = 'cancel' )
self._cancel.SetForegroundColour( ( 128, 0, 0 ) )
#
self._share_key = share_key
self._name.SetValue( name )
self._text.SetValue( text )
if timeout is None:
2014-07-09 22:15:14 +00:00
2015-12-09 23:16:41 +00:00
self._timeout_number.SetValue( None )
2014-07-09 22:15:14 +00:00
2019-07-24 21:39:02 +00:00
self._timeout_multiplier.SetValue( 60 )
2014-07-09 22:15:14 +00:00
2015-12-09 23:16:41 +00:00
else:
2014-07-09 22:15:14 +00:00
2018-02-14 21:47:18 +00:00
time_left = HydrusData.GetTimeDeltaUntilTime( timeout )
2014-07-09 22:15:14 +00:00
2015-12-09 23:16:41 +00:00
if time_left < 60 * 60 * 12: time_value = 60
elif time_left < 60 * 60 * 24 * 7: time_value = 60 * 60
else: time_value = 60 * 60 * 24
2014-07-09 22:15:14 +00:00
2019-01-09 22:59:03 +00:00
self._timeout_number.SetValue( time_left // time_value )
2014-07-09 22:15:14 +00:00
2019-07-24 21:39:02 +00:00
self._timeout_multiplier.SetValue( time_value )
2014-07-09 22:15:14 +00:00
2015-12-09 23:16:41 +00:00
self._hashes = hashes
2017-12-06 22:06:56 +00:00
self._service = HG.client_controller.services_manager.GetService( CC.LOCAL_BOORU_SERVICE_KEY )
internal_port = self._service.GetPort()
if internal_port is None:
self._copy_internal_share_link.Disable()
self._copy_external_share_link.Disable()
2015-12-09 23:16:41 +00:00
#
2016-08-31 19:55:14 +00:00
rows = []
2015-12-09 23:16:41 +00:00
2016-08-31 19:55:14 +00:00
rows.append( ( 'share name: ', self._name ) )
rows.append( ( 'share text: ', self._text ) )
2015-12-09 23:16:41 +00:00
2016-08-31 19:55:14 +00:00
gridbox = ClientGUICommon.WrapInGrid( self, rows )
2015-12-09 23:16:41 +00:00
timeout_box = wx.BoxSizer( wx.HORIZONTAL )
2018-01-03 22:37:30 +00:00
timeout_box.Add( self._timeout_number, CC.FLAGS_EXPAND_BOTH_WAYS )
timeout_box.Add( self._timeout_multiplier, CC.FLAGS_EXPAND_BOTH_WAYS )
2015-12-09 23:16:41 +00:00
link_box = wx.BoxSizer( wx.HORIZONTAL )
2018-01-03 22:37:30 +00:00
link_box.Add( self._copy_internal_share_link, CC.FLAGS_VCENTER )
link_box.Add( self._copy_external_share_link, CC.FLAGS_VCENTER )
2015-12-09 23:16:41 +00:00
b_box = wx.BoxSizer( wx.HORIZONTAL )
2018-01-03 22:37:30 +00:00
b_box.Add( self._ok, CC.FLAGS_VCENTER )
b_box.Add( self._cancel, CC.FLAGS_VCENTER )
2015-12-09 23:16:41 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
2018-07-04 20:48:28 +00:00
intro = 'Sharing ' + HydrusData.ToHumanInt( len( self._hashes ) ) + ' files.'
2015-12-09 23:16:41 +00:00
intro += os.linesep + 'Title and text are optional.'
if new_share: intro += os.linesep + 'The link will not work until you ok this dialog.'
2018-01-03 22:37:30 +00:00
vbox.Add( ClientGUICommon.BetterStaticText( self, intro ), CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.Add( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
vbox.Add( timeout_box, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
vbox.Add( link_box, CC.FLAGS_BUTTON_SIZER )
vbox.Add( b_box, CC.FLAGS_BUTTON_SIZER )
2015-12-09 23:16:41 +00:00
self.SetSizer( vbox )
2014-07-09 22:15:14 +00:00
2015-12-09 23:16:41 +00:00
( x, y ) = self.GetEffectiveMinSize()
2014-07-09 22:15:14 +00:00
2015-12-09 23:16:41 +00:00
x = max( x, 350 )
2014-07-09 22:15:14 +00:00
2015-12-09 23:16:41 +00:00
self.SetInitialSize( ( x, y ) )
2014-07-09 22:15:14 +00:00
wx.CallAfter( self._ok.SetFocus )
def EventCopyExternalShareURL( self, event ):
2019-05-22 22:35:06 +00:00
internal_port = self._service.GetPort()
2014-07-09 22:15:14 +00:00
2019-05-22 22:35:06 +00:00
if internal_port is None:
2017-03-02 02:14:56 +00:00
2019-05-22 22:35:06 +00:00
wx.MessageBox( 'The local booru is not currently running!' )
2017-03-02 02:14:56 +00:00
2014-07-09 22:15:14 +00:00
2019-05-22 22:35:06 +00:00
try:
url = self._service.GetExternalShareURL( self._share_key )
except Exception as e:
HydrusData.ShowException( e )
wx.MessageBox( 'Unfortunately, could not generate an external URL: {}'.format( e ) )
return
2014-07-09 22:15:14 +00:00
2017-05-10 21:33:58 +00:00
HG.client_controller.pub( 'clipboard', 'text', url )
2014-07-09 22:15:14 +00:00
def EventCopyInternalShareURL( self, event ):
2017-06-28 20:23:21 +00:00
self._service = HG.client_controller.services_manager.GetService( CC.LOCAL_BOORU_SERVICE_KEY )
2014-07-09 22:15:14 +00:00
internal_ip = '127.0.0.1'
2017-03-02 02:14:56 +00:00
internal_port = self._service.GetPort()
2014-07-09 22:15:14 +00:00
2019-01-09 22:59:03 +00:00
url = 'http://' + internal_ip + ':' + str( internal_port ) + '/gallery?share_key=' + self._share_key.hex()
2014-07-09 22:15:14 +00:00
2017-05-10 21:33:58 +00:00
HG.client_controller.pub( 'clipboard', 'text', url )
2014-07-09 22:15:14 +00:00
def GetInfo( self ):
name = self._name.GetValue()
text = self._text.GetValue()
timeout = self._timeout_number.GetValue()
2019-07-24 21:39:02 +00:00
if timeout is not None: timeout = timeout * self._timeout_multiplier.GetValue() + HydrusData.GetNow()
2014-07-09 22:15:14 +00:00
return ( self._share_key, name, text, timeout, self._hashes )
2013-07-31 21:26:38 +00:00
class DialogInputNamespaceRegex( Dialog ):
def __init__( self, parent, namespace = '', regex = '' ):
2015-10-14 21:02:25 +00:00
Dialog.__init__( self, parent, 'configure quick namespace' )
2013-07-31 21:26:38 +00:00
2015-10-14 21:02:25 +00:00
self._namespace = wx.TextCtrl( self )
2013-07-31 21:26:38 +00:00
2015-10-14 21:02:25 +00:00
self._regex = wx.TextCtrl( self )
self._shortcuts = ClientGUICommon.RegexButton( self )
2018-08-29 20:20:41 +00:00
self._regex_intro_link = ClientGUICommon.BetterHyperLink( self, 'a good regex introduction', 'http://www.aivosto.com/vbtips/regex.html' )
self._regex_practise_link = ClientGUICommon.BetterHyperLink( self, 'regex practise', 'http://regexr.com/3cvmf' )
2015-10-14 21:02:25 +00:00
2017-06-07 22:05:15 +00:00
self._ok = wx.Button( self, id = wx.ID_OK, label = 'OK' )
2015-10-14 21:02:25 +00:00
self._ok.Bind( wx.EVT_BUTTON, self.EventOK )
self._ok.SetForegroundColour( ( 0, 128, 0 ) )
self._cancel = wx.Button( self, id = wx.ID_CANCEL, label = 'Cancel' )
self._cancel.SetForegroundColour( ( 128, 0, 0 ) )
#
self._namespace.SetValue( namespace )
self._regex.SetValue( regex )
#
control_box = wx.BoxSizer( wx.HORIZONTAL )
2018-01-03 22:37:30 +00:00
control_box.Add( self._namespace, CC.FLAGS_EXPAND_BOTH_WAYS )
control_box.Add( ClientGUICommon.BetterStaticText( self, ':' ), CC.FLAGS_VCENTER )
control_box.Add( self._regex, CC.FLAGS_EXPAND_BOTH_WAYS )
2015-10-14 21:02:25 +00:00
b_box = wx.BoxSizer( wx.HORIZONTAL )
2018-01-03 22:37:30 +00:00
b_box.Add( self._ok, CC.FLAGS_VCENTER )
b_box.Add( self._cancel, CC.FLAGS_VCENTER )
2015-10-14 21:02:25 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
2017-03-15 20:13:04 +00:00
intro = r'Put the namespace (e.g. page) on the left.' + os.linesep + r'Put the regex (e.g. [1-9]+\d*(?=.{4}$)) on the right.' + os.linesep + r'All files will be tagged with "namespace:regex".'
2015-10-14 21:02:25 +00:00
2018-01-03 22:37:30 +00:00
vbox.Add( ClientGUICommon.BetterStaticText( self, intro ), CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.Add( control_box, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
vbox.Add( self._shortcuts, CC.FLAGS_LONE_BUTTON )
vbox.Add( self._regex_intro_link, CC.FLAGS_LONE_BUTTON )
vbox.Add( self._regex_practise_link, CC.FLAGS_LONE_BUTTON )
vbox.Add( b_box, CC.FLAGS_BUTTON_SIZER )
2015-10-14 21:02:25 +00:00
self.SetSizer( vbox )
( x, y ) = self.GetEffectiveMinSize()
self.SetInitialSize( ( x, y ) )
wx.CallAfter( self._ok.SetFocus )
def EventOK( self, event ):
( namespace, regex ) = self.GetInfo()
if namespace == '':
2013-07-31 21:26:38 +00:00
2015-10-14 21:02:25 +00:00
wx.MessageBox( 'Please enter something for the namespace.' )
2013-07-31 21:26:38 +00:00
2015-10-14 21:02:25 +00:00
return
2013-07-31 21:26:38 +00:00
2015-10-14 21:02:25 +00:00
try:
2013-07-31 21:26:38 +00:00
2019-01-09 22:59:03 +00:00
re.compile( regex )
2014-03-12 22:08:23 +00:00
2015-10-14 21:02:25 +00:00
except Exception as e:
2013-07-31 21:26:38 +00:00
2015-10-14 21:02:25 +00:00
text = 'That regex would not compile!'
text += os.linesep * 2
2019-01-09 22:59:03 +00:00
text += str( e )
2013-07-31 21:26:38 +00:00
2015-10-14 21:02:25 +00:00
wx.MessageBox( text )
2013-07-31 21:26:38 +00:00
2015-10-14 21:02:25 +00:00
return
2013-07-31 21:26:38 +00:00
2015-10-14 21:02:25 +00:00
self.EndModal( wx.ID_OK )
2013-07-31 21:26:38 +00:00
def GetInfo( self ):
namespace = self._namespace.GetValue()
regex = self._regex.GetValue()
return ( namespace, regex )
2015-10-21 21:53:10 +00:00
class DialogInputTags( Dialog ):
2018-04-11 22:30:40 +00:00
def __init__( self, parent, service_key, tags, message = '' ):
2015-10-21 21:53:10 +00:00
Dialog.__init__( self, parent, 'input tags' )
2016-05-25 21:54:03 +00:00
self._service_key = service_key
2017-02-01 21:11:17 +00:00
self._tags = ClientGUIListBoxes.ListBoxTagsStringsAddRemove( self, service_key = service_key )
2015-10-21 21:53:10 +00:00
2015-10-28 21:29:05 +00:00
expand_parents = True
2019-06-26 21:27:18 +00:00
self._tag_box = ClientGUIACDropdown.AutoCompleteDropdownTagsWrite( self, self.EnterTags, expand_parents, CC.LOCAL_FILE_SERVICE_KEY, service_key, null_entry_callable = self.OK, show_paste_button = True )
2015-10-21 21:53:10 +00:00
2019-05-22 22:35:06 +00:00
self._ok = ClientGUICommon.BetterButton( self, 'OK', self.EndModal, wx.ID_OK )
2015-10-21 21:53:10 +00:00
self._ok.SetForegroundColour( ( 0, 128, 0 ) )
self._cancel = wx.Button( self, id = wx.ID_CANCEL, label = 'Cancel' )
self._cancel.SetForegroundColour( ( 128, 0, 0 ) )
#
self._tags.SetTags( tags )
#
b_box = wx.BoxSizer( wx.HORIZONTAL )
2018-01-03 22:37:30 +00:00
b_box.Add( self._ok, CC.FLAGS_VCENTER )
b_box.Add( self._cancel, CC.FLAGS_VCENTER )
2015-10-21 21:53:10 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
2018-04-11 22:30:40 +00:00
if message != '':
vbox.Add( ClientGUICommon.BetterStaticText( self, message ), CC.FLAGS_EXPAND_PERPENDICULAR )
2018-01-03 22:37:30 +00:00
vbox.Add( self._tags, CC.FLAGS_EXPAND_BOTH_WAYS )
vbox.Add( self._tag_box, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.Add( b_box, CC.FLAGS_BUTTON_SIZER )
2015-10-21 21:53:10 +00:00
self.SetSizer( vbox )
( x, y ) = self.GetEffectiveMinSize()
x = max( x, 300 )
self.SetInitialSize( ( x, y ) )
wx.CallAfter( self._tag_box.SetFocus )
2016-05-25 21:54:03 +00:00
def EnterTags( self, tags ):
2019-04-17 21:51:50 +00:00
tag_parents_manager = HG.client_controller.tag_parents_manager
2016-05-25 21:54:03 +00:00
parents = set()
2015-10-21 21:53:10 +00:00
2016-05-25 21:54:03 +00:00
for tag in tags:
2015-10-21 21:53:10 +00:00
2016-05-25 21:54:03 +00:00
some_parents = tag_parents_manager.GetParents( self._service_key, tag )
parents.update( some_parents )
2015-10-21 21:53:10 +00:00
2015-10-28 21:29:05 +00:00
if len( tags ) > 0:
2015-10-21 21:53:10 +00:00
2015-10-28 21:29:05 +00:00
self._tags.EnterTags( tags )
self._tags.AddTags( parents )
2015-10-21 21:53:10 +00:00
def GetTags( self ):
return self._tags.GetTags()
2017-06-07 22:05:15 +00:00
def OK( self ):
2015-10-28 21:29:05 +00:00
self.EndModal( wx.ID_OK )
2013-09-25 20:20:10 +00:00
class DialogInputUPnPMapping( Dialog ):
2014-04-23 20:56:12 +00:00
def __init__( self, parent, external_port, protocol_type, internal_port, description, duration ):
2013-09-25 20:20:10 +00:00
2016-06-01 20:04:15 +00:00
Dialog.__init__( self, parent, 'configure upnp mapping' )
2013-09-25 20:20:10 +00:00
2016-06-01 20:04:15 +00:00
self._external_port = wx.SpinCtrl( self, min = 0, max = 65535 )
2013-09-25 20:20:10 +00:00
2016-06-01 20:04:15 +00:00
self._protocol_type = ClientGUICommon.BetterChoice( self )
self._protocol_type.Append( 'TCP', 'TCP' )
self._protocol_type.Append( 'UDP', 'UDP' )
2013-09-25 20:20:10 +00:00
2016-06-01 20:04:15 +00:00
self._internal_port = wx.SpinCtrl( self, min = 0, max = 65535 )
self._description = wx.TextCtrl( self )
self._duration = wx.SpinCtrl( self, min = 0, max = 86400 )
2013-09-25 20:20:10 +00:00
2019-05-22 22:35:06 +00:00
self._ok = ClientGUICommon.BetterButton( self, 'OK', self.EndModal, wx.ID_OK )
2016-06-01 20:04:15 +00:00
self._ok.SetForegroundColour( ( 0, 128, 0 ) )
2013-09-25 20:20:10 +00:00
2016-06-01 20:04:15 +00:00
self._cancel = wx.Button( self, id = wx.ID_CANCEL, label = 'Cancel' )
self._cancel.SetForegroundColour( ( 128, 0, 0 ) )
#
self._external_port.SetValue( external_port )
if protocol_type == 'TCP': self._protocol_type.Select( 0 )
elif protocol_type == 'UDP': self._protocol_type.Select( 1 )
self._internal_port.SetValue( internal_port )
self._description.SetValue( description )
self._duration.SetValue( duration )
#
2016-08-31 19:55:14 +00:00
rows = []
2016-06-01 20:04:15 +00:00
2016-08-31 19:55:14 +00:00
rows.append( ( 'external port: ', self._external_port ) )
rows.append( ( 'protocol type: ', self._protocol_type ) )
rows.append( ( 'internal port: ', self._internal_port ) )
rows.append( ( 'description: ', self._description ) )
rows.append( ( 'duration (0 = indefinite): ', self._duration ) )
2016-06-01 20:04:15 +00:00
2016-08-31 19:55:14 +00:00
gridbox = ClientGUICommon.WrapInGrid( self, rows )
2016-06-01 20:04:15 +00:00
b_box = wx.BoxSizer( wx.HORIZONTAL )
2018-01-03 22:37:30 +00:00
b_box.Add( self._ok, CC.FLAGS_VCENTER )
b_box.Add( self._cancel, CC.FLAGS_VCENTER )
2016-06-01 20:04:15 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
2018-01-03 22:37:30 +00:00
vbox.Add( gridbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
vbox.Add( b_box, CC.FLAGS_BUTTON_SIZER )
2016-06-01 20:04:15 +00:00
self.SetSizer( vbox )
( x, y ) = self.GetEffectiveMinSize()
self.SetInitialSize( ( x, y ) )
2013-09-25 20:20:10 +00:00
wx.CallAfter( self._ok.SetFocus )
def GetInfo( self ):
external_port = self._external_port.GetValue()
2019-07-24 21:39:02 +00:00
protocol_type = self._protocol_type.GetValue()
2013-09-25 20:20:10 +00:00
internal_port = self._internal_port.GetValue()
description = self._description.GetValue()
2014-04-23 20:56:12 +00:00
duration = self._duration.GetValue()
2013-09-25 20:20:10 +00:00
2014-04-23 20:56:12 +00:00
return ( external_port, protocol_type, internal_port, description, duration )
2013-09-25 20:20:10 +00:00
2013-02-19 00:11:43 +00:00
class DialogModifyAccounts( Dialog ):
2014-08-27 22:15:22 +00:00
def __init__( self, parent, service_key, subject_identifiers ):
2013-02-19 00:11:43 +00:00
2016-06-01 20:04:15 +00:00
Dialog.__init__( self, parent, 'modify account' )
2013-02-19 00:11:43 +00:00
2017-06-28 20:23:21 +00:00
self._service = HG.client_controller.services_manager.GetService( service_key )
2016-06-01 20:04:15 +00:00
self._subject_identifiers = list( subject_identifiers )
#
self._account_info_panel = ClientGUICommon.StaticBox( self, 'account info' )
self._subject_text = wx.StaticText( self._account_info_panel )
#
self._account_types_panel = ClientGUICommon.StaticBox( self, 'account types' )
self._account_types = wx.Choice( self._account_types_panel )
2017-06-07 22:05:15 +00:00
self._account_types_ok = wx.Button( self._account_types_panel, label = 'OK' )
2016-06-01 20:04:15 +00:00
self._account_types_ok.Bind( wx.EVT_BUTTON, self.EventChangeAccountType )
#
self._expiration_panel = ClientGUICommon.StaticBox( self, 'change expiration' )
self._add_to_expires = wx.Choice( self._expiration_panel )
2017-06-07 22:05:15 +00:00
self._add_to_expires_ok = wx.Button( self._expiration_panel, label = 'OK' )
2016-06-01 20:04:15 +00:00
self._add_to_expires_ok.Bind( wx.EVT_BUTTON, self.EventAddToExpires )
self._set_expires = wx.Choice( self._expiration_panel )
2017-06-07 22:05:15 +00:00
self._set_expires_ok = wx.Button( self._expiration_panel, label = 'OK' )
2016-06-01 20:04:15 +00:00
self._set_expires_ok.Bind( wx.EVT_BUTTON, self.EventSetExpires )
#
self._ban_panel = ClientGUICommon.StaticBox( self, 'bans' )
self._ban = wx.Button( self._ban_panel, label = 'ban user' )
self._ban.Bind( wx.EVT_BUTTON, self.EventBan )
self._ban.SetBackgroundColour( ( 255, 0, 0 ) )
self._ban.SetForegroundColour( ( 255, 255, 0 ) )
self._superban = wx.Button( self._ban_panel, label = 'ban user and delete every contribution they have ever made' )
self._superban.Bind( wx.EVT_BUTTON, self.EventSuperban )
self._superban.SetBackgroundColour( ( 255, 0, 0 ) )
self._superban.SetForegroundColour( ( 255, 255, 0 ) )
self._exit = wx.Button( self, id = wx.ID_CANCEL, label = 'Exit' )
#
if len( self._subject_identifiers ) == 1:
2013-02-19 00:11:43 +00:00
2016-06-01 20:04:15 +00:00
( subject_identifier, ) = self._subject_identifiers
2013-02-19 00:11:43 +00:00
2016-06-01 20:04:15 +00:00
response = self._service.Request( HC.GET, 'account_info', { 'subject_identifier' : subject_identifier } )
2013-02-19 00:11:43 +00:00
2019-01-09 22:59:03 +00:00
subject_string = str( response[ 'account_info' ] )
else:
subject_string = 'modifying ' + HydrusData.ToHumanInt( len( self._subject_identifiers ) ) + ' accounts'
2013-02-19 00:11:43 +00:00
2016-06-01 20:04:15 +00:00
self._subject_text.SetLabelText( subject_string )
#
response = self._service.Request( HC.GET, 'account_types' )
account_types = response[ 'account_types' ]
for account_type in account_types: self._account_types.Append( account_type.ConvertToString(), account_type )
self._account_types.SetSelection( 0 )
#
for ( string, value ) in HC.lifetimes:
2013-02-19 00:11:43 +00:00
2017-03-02 02:14:56 +00:00
if value is not None:
self._add_to_expires.Append( string, value ) # don't want 'add no limit'
2013-02-19 00:11:43 +00:00
2016-06-01 20:04:15 +00:00
self._add_to_expires.SetSelection( 1 ) # three months
for ( string, value ) in HC.lifetimes: self._set_expires.Append( string, value )
self._set_expires.SetSelection( 1 ) # three months
#
2013-02-19 00:11:43 +00:00
2018-01-03 22:37:30 +00:00
self._account_info_panel.Add( self._subject_text, CC.FLAGS_EXPAND_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2016-06-01 20:04:15 +00:00
account_types_hbox = wx.BoxSizer( wx.HORIZONTAL )
2013-02-19 00:11:43 +00:00
2018-01-03 22:37:30 +00:00
account_types_hbox.Add( self._account_types, CC.FLAGS_VCENTER )
account_types_hbox.Add( self._account_types_ok, CC.FLAGS_VCENTER )
2013-07-31 21:26:38 +00:00
2018-01-03 22:37:30 +00:00
self._account_types_panel.Add( account_types_hbox, CC.FLAGS_EXPAND_PERPENDICULAR )
2016-06-01 20:04:15 +00:00
add_to_expires_box = wx.BoxSizer( wx.HORIZONTAL )
2018-01-03 22:37:30 +00:00
add_to_expires_box.Add( wx.StaticText( self._expiration_panel, label = 'add to expires: ' ), CC.FLAGS_VCENTER )
add_to_expires_box.Add( self._add_to_expires, CC.FLAGS_EXPAND_BOTH_WAYS )
add_to_expires_box.Add( self._add_to_expires_ok, CC.FLAGS_VCENTER )
2016-06-01 20:04:15 +00:00
set_expires_box = wx.BoxSizer( wx.HORIZONTAL )
2018-01-03 22:37:30 +00:00
set_expires_box.Add( wx.StaticText( self._expiration_panel, label = 'set expires to: ' ), CC.FLAGS_VCENTER )
set_expires_box.Add( self._set_expires, CC.FLAGS_EXPAND_BOTH_WAYS )
set_expires_box.Add( self._set_expires_ok, CC.FLAGS_VCENTER )
2016-06-01 20:04:15 +00:00
2018-01-03 22:37:30 +00:00
self._expiration_panel.Add( add_to_expires_box, CC.FLAGS_EXPAND_PERPENDICULAR )
self._expiration_panel.Add( set_expires_box, CC.FLAGS_EXPAND_PERPENDICULAR )
2016-06-01 20:04:15 +00:00
2018-01-03 22:37:30 +00:00
self._ban_panel.Add( self._ban, CC.FLAGS_EXPAND_PERPENDICULAR )
self._ban_panel.Add( self._superban, CC.FLAGS_EXPAND_PERPENDICULAR )
2016-06-01 20:04:15 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
2018-01-03 22:37:30 +00:00
vbox.Add( self._account_info_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.Add( self._account_types_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.Add( self._expiration_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.Add( self._ban_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.Add( self._exit, CC.FLAGS_BUTTON_SIZER )
2016-06-01 20:04:15 +00:00
self.SetSizer( vbox )
( x, y ) = self.GetEffectiveMinSize()
self.SetInitialSize( ( x, y ) )
2013-07-31 21:26:38 +00:00
wx.CallAfter( self._exit.SetFocus )
2013-02-19 00:11:43 +00:00
2017-03-02 02:14:56 +00:00
def _DoModification( self ):
2015-10-14 21:02:25 +00:00
2017-03-02 02:14:56 +00:00
# change this to saveaccounts or whatever. the previous func changes the accounts, and then we push that change
2018-07-18 21:07:15 +00:00
# generate accounts, with the modification having occurred
2013-08-14 20:21:49 +00:00
2017-03-02 02:14:56 +00:00
self._service.Request( HC.POST, 'account', { 'accounts' : self._accounts } )
2013-08-14 20:21:49 +00:00
if len( self._subject_identifiers ) == 1:
2013-02-19 00:11:43 +00:00
2013-08-14 20:21:49 +00:00
( subject_identifier, ) = self._subject_identifiers
2013-02-19 00:11:43 +00:00
2014-01-29 21:59:42 +00:00
response = self._service.Request( HC.GET, 'account_info', { 'subject_identifier' : subject_identifier } )
2013-10-02 22:06:06 +00:00
account_info = response[ 'account_info' ]
2019-01-09 22:59:03 +00:00
self._subject_text.SetLabelText( str( account_info ) )
2013-02-19 00:11:43 +00:00
if len( self._subject_identifiers ) > 1: wx.MessageBox( 'Done!' )
2017-03-02 02:14:56 +00:00
def EventAddToExpires( self, event ):
2018-05-09 20:23:00 +00:00
raise NotImplementedError()
#self._DoModification( HC.ADD_TO_EXPIRES, timespan = self._add_to_expires.GetClientData( self._add_to_expires.GetSelection() ) )
2017-03-02 02:14:56 +00:00
2013-02-19 00:11:43 +00:00
def EventBan( self, event ):
2014-09-24 21:50:07 +00:00
with DialogTextEntry( self, 'Enter reason for the ban.' ) as dlg:
2013-02-19 00:11:43 +00:00
2018-05-09 20:23:00 +00:00
if dlg.ShowModal() == wx.ID_OK:
raise NotImplementedError()
#self._DoModification( HC.BAN, reason = dlg.GetValue() )
2013-02-19 00:11:43 +00:00
2017-03-02 02:14:56 +00:00
def EventChangeAccountType( self, event ):
2018-05-09 20:23:00 +00:00
raise NotImplementedError()
2019-07-24 21:39:02 +00:00
#self._DoModification( HC.CHANGE_ACCOUNT_TYPE, account_type_key = self._account_types.GetValue() )
2017-03-02 02:14:56 +00:00
2013-02-19 00:11:43 +00:00
2014-10-01 22:58:32 +00:00
def EventSetExpires( self, event ):
2013-07-24 20:26:00 +00:00
2014-10-01 22:58:32 +00:00
expires = self._set_expires.GetClientData( self._set_expires.GetSelection() )
2013-07-24 20:26:00 +00:00
2018-05-09 20:23:00 +00:00
if expires is not None:
expires += HydrusData.GetNow()
2013-07-24 20:26:00 +00:00
2018-05-09 20:23:00 +00:00
raise NotImplementedError()
#self._DoModification( HC.SET_EXPIRES, expires = expires )
2013-07-24 20:26:00 +00:00
2013-02-19 00:11:43 +00:00
def EventSuperban( self, event ):
2014-09-24 21:50:07 +00:00
with DialogTextEntry( self, 'Enter reason for the superban.' ) as dlg:
2013-02-19 00:11:43 +00:00
2018-05-09 20:23:00 +00:00
if dlg.ShowModal() == wx.ID_OK:
raise NotImplementedError()
#self._DoModification( HC.SUPERBAN, reason = dlg.GetValue() )
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
class DialogSelectFromURLTree( Dialog ):
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
def __init__( self, parent, url_tree ):
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
Dialog.__init__( self, parent, 'select items' )
agwStyle = wx.lib.agw.customtreectrl.TR_DEFAULT_STYLE | wx.lib.agw.customtreectrl.TR_AUTO_CHECK_CHILD
self._tree = wx.lib.agw.customtreectrl.CustomTreeCtrl( self, agwStyle = agwStyle )
2019-05-22 22:35:06 +00:00
self._ok = ClientGUICommon.BetterButton( self, 'OK', self.EndModal, wx.ID_OK )
2016-03-23 19:42:56 +00:00
self._ok.SetForegroundColour( ( 0, 128, 0 ) )
2019-05-22 22:35:06 +00:00
self._cancel = wx.Button( self, id = wx.ID_CANCEL, label = 'Cancel' )
2016-03-23 19:42:56 +00:00
self._cancel.SetForegroundColour( ( 128, 0, 0 ) )
#
( text_gumpf, name, size, children ) = url_tree
root_name = self._RenderItemName( name, size )
root_item = self._tree.AddRoot( root_name, ct_type = 1 )
self._AddDirectory( root_item, children )
self._tree.CheckItem( root_item )
self._tree.Expand( root_item )
#
button_hbox = wx.BoxSizer( wx.HORIZONTAL )
2018-01-03 22:37:30 +00:00
button_hbox.Add( self._ok, CC.FLAGS_VCENTER )
button_hbox.Add( self._cancel, CC.FLAGS_VCENTER )
2016-03-23 19:42:56 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
2018-01-03 22:37:30 +00:00
vbox.Add( self._tree, CC.FLAGS_EXPAND_BOTH_WAYS )
vbox.Add( button_hbox, CC.FLAGS_BUTTON_SIZER )
2016-03-23 19:42:56 +00:00
self.SetSizer( vbox )
( x, y ) = self.GetEffectiveMinSize()
2016-05-25 21:54:03 +00:00
x = max( x, 640 )
2016-03-23 19:42:56 +00:00
y = max( y, 640 )
self.SetInitialSize( ( x, y ) )
def _AddDirectory( self, root, children ):
for ( child_type, name, size, data ) in children:
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
item_name = self._RenderItemName( name, size )
2014-02-19 22:37:23 +00:00
2016-03-23 19:42:56 +00:00
if child_type == 'file':
self._tree.AppendItem( root, item_name, ct_type = 1, data = data )
else:
subroot = self._tree.AppendItem( root, item_name, ct_type = 1 )
self._AddDirectory( subroot, data )
2013-02-19 00:11:43 +00:00
2013-07-31 21:26:38 +00:00
2016-03-23 19:42:56 +00:00
def _GetSelectedChildrenData( self, parent_item ):
result = []
cookie = 0
( child_item, cookie ) = self._tree.GetNextChild( parent_item, cookie )
while child_item is not None:
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
data = self._tree.GetItemPyData( child_item )
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
if data is None:
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
result.extend( self._GetSelectedChildrenData( child_item ) )
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
else:
if self._tree.IsItemChecked( child_item ):
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
result.append( data )
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
( child_item, cookie ) = self._tree.GetNextChild( parent_item, cookie )
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
return result
def _RenderItemName( self, name, size ):
2019-01-09 22:59:03 +00:00
return name + ' - ' + HydrusData.ToHumanBytes( size )
2016-03-23 19:42:56 +00:00
def GetURLs( self ):
root_item = self._tree.GetRootItem()
urls = self._GetSelectedChildrenData( root_item )
return urls
class DialogSelectImageboard( Dialog ):
def __init__( self, parent ):
Dialog.__init__( self, parent, 'select imageboard' )
self._tree = wx.TreeCtrl( self )
self._tree.Bind( wx.EVT_TREE_ITEM_ACTIVATED, self.EventActivate )
#
2017-05-10 21:33:58 +00:00
all_imageboards = HG.client_controller.Read( 'imageboards' )
2016-03-23 19:42:56 +00:00
root_item = self._tree.AddRoot( 'all sites' )
2019-01-09 22:59:03 +00:00
for ( site, imageboards ) in list(all_imageboards.items()):
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
site_item = self._tree.AppendItem( root_item, site )
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
for imageboard in imageboards:
name = imageboard.GetName()
self._tree.AppendItem( site_item, name, data = wx.TreeItemData( imageboard ) )
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
self._tree.Expand( root_item )
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
#
2013-02-19 00:11:43 +00:00
2016-03-23 19:42:56 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
2013-07-31 21:26:38 +00:00
2018-01-03 22:37:30 +00:00
vbox.Add( self._tree, CC.FLAGS_EXPAND_BOTH_WAYS )
2016-03-23 19:42:56 +00:00
self.SetSizer( vbox )
( x, y ) = self.GetEffectiveMinSize()
if x < 320: x = 320
if y < 640: y = 640
self.SetInitialSize( ( x, y ) )
2013-02-19 00:11:43 +00:00
2014-02-19 22:37:23 +00:00
def EventActivate( self, event ):
2013-02-19 00:11:43 +00:00
item = self._tree.GetSelection()
2013-03-15 02:38:12 +00:00
data_object = self._tree.GetItemData( item )
if data_object is None: self._tree.Toggle( item )
2013-02-19 00:11:43 +00:00
else: self.EndModal( wx.ID_OK )
def GetImageboard( self ): return self._tree.GetItemData( self._tree.GetSelection() ).GetData()
2014-08-06 20:29:17 +00:00
class DialogTextEntry( Dialog ):
2017-08-02 21:32:54 +00:00
def __init__( self, parent, message, default = '', allow_blank = False, suggestions = None, max_chars = None ):
2016-12-07 22:12:52 +00:00
if suggestions is None:
suggestions = []
2014-08-06 20:29:17 +00:00
Dialog.__init__( self, parent, 'enter text', position = 'center' )
2016-12-07 22:12:52 +00:00
self._chosen_suggestion = None
2014-08-06 20:29:17 +00:00
self._allow_blank = allow_blank
2017-08-02 21:32:54 +00:00
self._max_chars = max_chars
2014-08-06 20:29:17 +00:00
2016-12-07 22:12:52 +00:00
button_choices = []
for text in suggestions:
button_choices.append( ClientGUICommon.BetterButton( self, text, self.ButtonChoice, text ) )
2016-03-30 22:56:50 +00:00
self._text = wx.TextCtrl( self, style = wx.TE_PROCESS_ENTER )
self._text.Bind( wx.EVT_TEXT, self.EventText )
self._text.Bind( wx.EVT_TEXT_ENTER, self.EventEnter )
2014-08-06 20:29:17 +00:00
2017-08-02 21:32:54 +00:00
if self._max_chars is not None:
self._text.SetMaxLength( self._max_chars )
2019-05-22 22:35:06 +00:00
self._ok = ClientGUICommon.BetterButton( self, 'ok', self.EndModal, wx.ID_OK )
2016-03-30 22:56:50 +00:00
self._ok.SetForegroundColour( ( 0, 128, 0 ) )
2014-08-06 20:29:17 +00:00
2016-03-30 22:56:50 +00:00
self._cancel = wx.Button( self, id = wx.ID_CANCEL, label = 'cancel' )
self._cancel.SetForegroundColour( ( 128, 0, 0 ) )
#
self._text.SetValue( default )
self._CheckText()
#
hbox = wx.BoxSizer( wx.HORIZONTAL )
2018-01-03 22:37:30 +00:00
hbox.Add( self._ok, CC.FLAGS_SMALL_INDENT )
hbox.Add( self._cancel, CC.FLAGS_SMALL_INDENT )
2016-03-30 22:56:50 +00:00
2017-04-19 20:58:30 +00:00
st_message = ClientGUICommon.BetterStaticText( self, message )
2018-07-04 20:48:28 +00:00
st_message.SetWrapWidth( 480 )
2016-03-30 22:56:50 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
2018-01-03 22:37:30 +00:00
vbox.Add( st_message, CC.FLAGS_BIG_INDENT )
2016-12-07 22:12:52 +00:00
for button in button_choices:
2018-01-03 22:37:30 +00:00
vbox.Add( button, CC.FLAGS_EXPAND_PERPENDICULAR )
2016-12-07 22:12:52 +00:00
2018-01-03 22:37:30 +00:00
vbox.Add( self._text, CC.FLAGS_EXPAND_BOTH_WAYS )
vbox.Add( hbox, CC.FLAGS_BUTTON_SIZER )
2016-03-30 22:56:50 +00:00
self.SetSizer( vbox )
( x, y ) = self.GetEffectiveMinSize()
x = max( x, 250 )
self.SetInitialSize( ( x, y ) )
2014-08-06 20:29:17 +00:00
def _CheckText( self ):
if not self._allow_blank:
2017-08-02 21:32:54 +00:00
if self._text.GetValue() == '':
self._ok.Disable()
else:
self._ok.Enable()
2014-08-06 20:29:17 +00:00
2016-12-07 22:12:52 +00:00
def ButtonChoice( self, text ):
self._chosen_suggestion = text
self.EndModal( wx.ID_OK )
2015-07-29 19:11:35 +00:00
def EventText( self, event ):
2014-08-06 20:29:17 +00:00
wx.CallAfter( self._CheckText )
event.Skip()
def EventEnter( self, event ):
2016-12-07 22:12:52 +00:00
if self._text.GetValue() != '':
self.EndModal( wx.ID_OK )
2014-08-06 20:29:17 +00:00
2016-12-07 22:12:52 +00:00
def GetValue( self ):
if self._chosen_suggestion is None:
return self._text.GetValue()
else:
return self._chosen_suggestion
2014-08-06 20:29:17 +00:00
2017-06-07 22:05:15 +00:00
class DialogYesYesNo( Dialog ):
def __init__( self, parent, message, title = 'Are you sure?', yes_tuples = None, no_label = 'no' ):
if yes_tuples is None:
yes_tuples = [ ( 'yes', 'yes' ) ]
Dialog.__init__( self, parent, title, position = 'center' )
self._value = None
yes_buttons = []
for ( label, data ) in yes_tuples:
yes_button = ClientGUICommon.BetterButton( self, label, self._DoYes, data )
yes_button.SetForegroundColour( ( 0, 128, 0 ) )
yes_buttons.append( yes_button )
2019-05-22 22:35:06 +00:00
self._no = ClientGUICommon.BetterButton( self, no_label, self.EndModal, wx.ID_NO )
2017-06-07 22:05:15 +00:00
self._no.SetForegroundColour( ( 128, 0, 0 ) )
#
hbox = wx.BoxSizer( wx.HORIZONTAL )
for yes_button in yes_buttons:
2018-01-03 22:37:30 +00:00
hbox.Add( yes_button, CC.FLAGS_SMALL_INDENT )
2017-06-07 22:05:15 +00:00
2018-01-03 22:37:30 +00:00
hbox.Add( self._no, CC.FLAGS_SMALL_INDENT )
2017-06-07 22:05:15 +00:00
vbox = wx.BoxSizer( wx.VERTICAL )
text = ClientGUICommon.BetterStaticText( self, message )
2018-07-04 20:48:28 +00:00
text.SetWrapWidth( 480 )
2017-06-07 22:05:15 +00:00
2018-01-03 22:37:30 +00:00
vbox.Add( text, CC.FLAGS_BIG_INDENT )
vbox.Add( hbox, CC.FLAGS_BUTTON_SIZER )
2017-06-07 22:05:15 +00:00
self.SetSizer( vbox )
( x, y ) = self.GetEffectiveMinSize()
x = max( x, 250 )
self.SetInitialSize( ( x, y ) )
wx.CallAfter( yes_buttons[0].SetFocus )
def _DoYes( self, value ):
self._value = value
self.EndModal( wx.ID_YES )
def GetValue( self ):
return self._value