1376 lines
48 KiB
Python
1376 lines
48 KiB
Python
import os
|
|
import typing
|
|
|
|
from qtpy import QtCore as QC
|
|
from qtpy import QtWidgets as QW
|
|
|
|
from hydrus.core import HydrusConstants as HC
|
|
from hydrus.core import HydrusData
|
|
from hydrus.core import HydrusExceptions
|
|
from hydrus.core import HydrusGlobals as HG
|
|
from hydrus.core.networking import HydrusNetwork
|
|
from hydrus.core.networking import HydrusNetworking
|
|
|
|
from hydrus.client import ClientConstants as CC
|
|
from hydrus.client.gui import ClientGUIAsync
|
|
from hydrus.client.gui import ClientGUIDialogs
|
|
from hydrus.client.gui import ClientGUIDialogsQuick
|
|
from hydrus.client.gui import ClientGUIFunctions
|
|
from hydrus.client.gui import ClientGUIScrolledPanels
|
|
from hydrus.client.gui import ClientGUITime
|
|
from hydrus.client.gui import ClientGUITopLevelWindowsPanels
|
|
from hydrus.client.gui import QtPorting as QP
|
|
from hydrus.client.gui.lists import ClientGUIListBoxes
|
|
from hydrus.client.gui.lists import ClientGUIListConstants as CGLC
|
|
from hydrus.client.gui.lists import ClientGUIListCtrl
|
|
from hydrus.client.gui.widgets import ClientGUICommon
|
|
from hydrus.client.gui.widgets import ClientGUIControls
|
|
|
|
class EditAccountTypePanel( ClientGUIScrolledPanels.EditPanel ):
|
|
|
|
def __init__( self, parent: QW.QWidget, service_type: int, account_type: HydrusNetwork.AccountType ):
|
|
|
|
ClientGUIScrolledPanels.EditPanel.__init__( self, parent )
|
|
|
|
self._account_type_key = account_type.GetAccountTypeKey()
|
|
title = account_type.GetTitle()
|
|
permissions = account_type.GetPermissions()
|
|
bandwidth_rules = account_type.GetBandwidthRules()
|
|
|
|
auto_create_velocity = account_type.GetAutoCreateAccountVelocity()
|
|
self._auto_create_history = account_type.GetAutoCreateAccountHistory()
|
|
|
|
self._title = QW.QLineEdit( self )
|
|
|
|
permission_choices = self._GeneratePermissionChoices( service_type )
|
|
|
|
self._permission_controls = []
|
|
|
|
self._permissions_panel = ClientGUICommon.StaticBox( self, 'permissions' )
|
|
|
|
gridbox_rows = []
|
|
|
|
for ( content_type, action_rows ) in permission_choices:
|
|
|
|
choice_control = ClientGUICommon.BetterChoice( self._permissions_panel )
|
|
|
|
for ( label, action ) in action_rows:
|
|
|
|
choice_control.addItem( label, ( content_type, action ) )
|
|
|
|
|
|
if content_type in permissions:
|
|
|
|
selection_row = ( content_type, permissions[ content_type ] )
|
|
|
|
else:
|
|
|
|
selection_row = ( content_type, None )
|
|
|
|
|
|
try:
|
|
|
|
choice_control.SetValue( selection_row )
|
|
|
|
except:
|
|
|
|
choice_control.SetValue( ( content_type, None ) )
|
|
|
|
|
|
self._permission_controls.append( choice_control )
|
|
|
|
gridbox_label = HC.content_type_string_lookup[ content_type ]
|
|
|
|
gridbox_rows.append( ( gridbox_label, choice_control ) )
|
|
|
|
|
|
gridbox = ClientGUICommon.WrapInGrid( self._permissions_panel, gridbox_rows )
|
|
|
|
self._bandwidth_rules_control = ClientGUIControls.BandwidthRulesCtrl( self, bandwidth_rules )
|
|
|
|
self._auto_creation_box = ClientGUICommon.StaticBox( self, 'automatic account creation' )
|
|
|
|
min_unit_value = 0
|
|
max_unit_value = 65565
|
|
min_time_delta = 60 * 60
|
|
|
|
self._auto_create_velocity_control = ClientGUITime.VelocityCtrl( self._auto_creation_box, min_unit_value, max_unit_value, min_time_delta, days = True, hours = True, unit = 'accounts' )
|
|
|
|
self._auto_create_history_st = ClientGUICommon.BetterStaticText( self._auto_creation_box, label = 'initialising' )
|
|
|
|
#
|
|
|
|
self._title.setText( title )
|
|
|
|
self._auto_create_velocity_control.SetValue( auto_create_velocity )
|
|
|
|
#
|
|
|
|
intro = 'If you wish, you can allow new users to create their own accounts. They will be limited to a certain number over a particular time.'
|
|
intro += os.linesep * 2
|
|
intro += 'Set to 0 to disable auto-creation.'
|
|
|
|
st = ClientGUICommon.BetterStaticText( self._auto_creation_box, label = intro )
|
|
st.setWordWrap( True )
|
|
|
|
self._auto_creation_box.Add( st, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
self._auto_creation_box.Add( self._auto_create_history_st, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
self._auto_creation_box.Add( self._auto_create_velocity_control, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
|
|
t_hbox = ClientGUICommon.WrapInText( self._title, self, 'title: ' )
|
|
|
|
self._permissions_panel.Add( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
|
|
|
vbox = QP.VBoxLayout()
|
|
|
|
QP.AddToLayout( vbox, t_hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, self._permissions_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, self._bandwidth_rules_control, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, self._auto_creation_box, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
|
|
self.widget().setLayout( vbox )
|
|
|
|
#
|
|
|
|
self._UpdateAutoCreationHistoryText()
|
|
|
|
self._auto_create_velocity_control.velocityChanged.connect( self._UpdateAutoCreationHistoryText )
|
|
|
|
|
|
def _GeneratePermissionChoices( self, service_type ):
|
|
|
|
possible_permissions = HydrusNetwork.GetPossiblePermissions( service_type )
|
|
|
|
permission_choices = []
|
|
|
|
for ( content_type, possible_actions ) in possible_permissions:
|
|
|
|
choices = []
|
|
|
|
for action in possible_actions:
|
|
|
|
choices.append( ( HC.permission_pair_string_lookup[ ( content_type, action ) ], action ) )
|
|
|
|
|
|
permission_choices.append( ( content_type, choices ) )
|
|
|
|
|
|
return permission_choices
|
|
|
|
|
|
def _UpdateAutoCreationHistoryText( self ):
|
|
|
|
( accounts_per_time_delta, time_delta ) = self._auto_create_velocity_control.GetValue()
|
|
|
|
text = ''
|
|
|
|
if accounts_per_time_delta == 0:
|
|
|
|
text = 'Auto-creation disabled. '
|
|
|
|
|
|
num_created = self._auto_create_history.GetUsage( HC.BANDWIDTH_TYPE_DATA, time_delta )
|
|
|
|
text += '{} auto-created in the past {}.'.format( HydrusData.ToHumanInt( num_created ), HydrusData.TimeDeltaToPrettyTimeDelta( time_delta ) )
|
|
|
|
self._auto_create_history_st.setText( text )
|
|
|
|
|
|
def GetValue( self ) -> HydrusNetwork.AccountType:
|
|
|
|
title = self._title.text()
|
|
|
|
permissions = {}
|
|
|
|
for permission_control in self._permission_controls:
|
|
|
|
( content_type, action ) = permission_control.GetValue()
|
|
|
|
if action is not None:
|
|
|
|
permissions[ content_type ] = action
|
|
|
|
|
|
|
|
bandwidth_rules = self._bandwidth_rules_control.GetValue()
|
|
|
|
auto_creation_velocity = self._auto_create_velocity_control.GetValue()
|
|
|
|
return HydrusNetwork.AccountType(
|
|
account_type_key = self._account_type_key,
|
|
title = title,
|
|
permissions = permissions,
|
|
bandwidth_rules = bandwidth_rules,
|
|
auto_creation_velocity = auto_creation_velocity,
|
|
auto_creation_history = self._auto_create_history
|
|
)
|
|
|
|
|
|
class EditAccountTypesPanel( ClientGUIScrolledPanels.EditPanel ):
|
|
|
|
def __init__( self, parent, service_type, account_types ):
|
|
|
|
self._service_type = service_type
|
|
self._original_account_types = account_types
|
|
|
|
ClientGUIScrolledPanels.EditPanel.__init__( self, parent )
|
|
|
|
self._deletee_account_type_keys_to_new_account_type_keys = {}
|
|
|
|
self._account_types_listctrl = ClientGUIListCtrl.BetterListCtrl( self, CGLC.COLUMN_LIST_ACCOUNT_TYPES.ID, 20, self._ConvertAccountTypeToTuples, delete_key_callback = self._Delete, activation_callback = self._Edit )
|
|
|
|
self._add_button = ClientGUICommon.BetterButton( self, 'add', self._Add )
|
|
self._edit_button = ClientGUICommon.BetterButton( self, 'edit', self._Edit )
|
|
self._delete_button = ClientGUICommon.BetterButton( self, 'delete', self._Delete )
|
|
|
|
self._account_types_listctrl.AddDatas( self._original_account_types )
|
|
|
|
hbox = QP.HBoxLayout()
|
|
|
|
QP.AddToLayout( hbox, self._add_button, CC.FLAGS_CENTER_PERPENDICULAR )
|
|
QP.AddToLayout( hbox, self._edit_button, CC.FLAGS_CENTER_PERPENDICULAR )
|
|
QP.AddToLayout( hbox, self._delete_button, CC.FLAGS_CENTER_PERPENDICULAR )
|
|
|
|
vbox = QP.VBoxLayout()
|
|
|
|
QP.AddToLayout( vbox, self._account_types_listctrl, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
QP.AddToLayout( vbox, hbox, CC.FLAGS_ON_RIGHT )
|
|
|
|
self.widget().setLayout( vbox )
|
|
|
|
|
|
def _Add( self ):
|
|
|
|
title = 'new account type'
|
|
permissions = {}
|
|
bandwidth_rules = HydrusNetworking.BandwidthRules()
|
|
|
|
account_type = HydrusNetwork.AccountType.GenerateNewAccountType( title, permissions, bandwidth_rules )
|
|
|
|
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit account type' ) as dlg_edit:
|
|
|
|
panel = EditAccountTypePanel( dlg_edit, self._service_type, account_type )
|
|
|
|
dlg_edit.SetPanel( panel )
|
|
|
|
if dlg_edit.exec() == QW.QDialog.Accepted:
|
|
|
|
new_account_type = panel.GetValue()
|
|
|
|
self._account_types_listctrl.AddDatas( ( new_account_type, ) )
|
|
|
|
|
|
|
|
|
|
def _ConvertAccountTypeToTuples( self, account_type: HydrusNetwork.AccountType ):
|
|
|
|
title = account_type.GetTitle()
|
|
|
|
if account_type.IsNullAccount():
|
|
|
|
title = '{} (cannot be edited)'.format( title )
|
|
|
|
|
|
display_tuple = ( title, )
|
|
sort_tuple = ( title, )
|
|
|
|
return ( display_tuple, sort_tuple )
|
|
|
|
|
|
def _Delete( self ):
|
|
|
|
result = ClientGUIDialogsQuick.GetYesNo( self, 'Remove all selected?' )
|
|
|
|
if result == QW.QDialog.Accepted:
|
|
|
|
account_types_about_to_delete = self._account_types_listctrl.GetData( only_selected = True )
|
|
|
|
if True in ( at.IsNullAccount() for at in account_types_about_to_delete ):
|
|
|
|
QW.QMessageBox.critical( self, 'Error', 'You cannot delete the null account type!' )
|
|
|
|
return
|
|
|
|
|
|
all_real_account_types = set( [ at for at in self._account_types_listctrl.GetData() if not at.IsNullAccount() ] )
|
|
|
|
account_types_can_move_to = all_real_account_types.difference( account_types_about_to_delete )
|
|
|
|
if len( account_types_can_move_to ) == 0:
|
|
|
|
QW.QMessageBox.critical( self, 'Error', 'You cannot delete every account type!' )
|
|
|
|
return
|
|
|
|
|
|
for deletee_account_type in account_types_about_to_delete:
|
|
|
|
if len( account_types_can_move_to ) > 1:
|
|
|
|
deletee_title = deletee_account_type.GetTitle()
|
|
|
|
choice_tuples = [ ( account_type.GetTitle(), account_type ) for account_type in account_types_can_move_to ]
|
|
|
|
try:
|
|
|
|
new_account_type = ClientGUIDialogsQuick.SelectFromList( self, 'what should deleted ' + deletee_title + ' accounts become?', choice_tuples )
|
|
|
|
except HydrusExceptions.CancelledException:
|
|
|
|
return
|
|
|
|
|
|
else:
|
|
|
|
( new_account_type, ) = account_types_can_move_to
|
|
|
|
|
|
deletee_account_type_key = deletee_account_type.GetAccountTypeKey()
|
|
new_account_type_key = new_account_type.GetAccountTypeKey()
|
|
|
|
self._deletee_account_type_keys_to_new_account_type_keys[ deletee_account_type_key ] = new_account_type_key
|
|
|
|
|
|
self._account_types_listctrl.DeleteSelected()
|
|
|
|
|
|
|
|
def _Edit( self ):
|
|
|
|
datas = self._account_types_listctrl.GetData( only_selected = True )
|
|
|
|
if True in ( at.IsNullAccount() for at in datas ):
|
|
|
|
QW.QMessageBox.critical( self, 'Error', 'You cannot edit the null account type!' )
|
|
|
|
return
|
|
|
|
|
|
for account_type in datas:
|
|
|
|
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit account type' ) as dlg_edit:
|
|
|
|
panel = EditAccountTypePanel( dlg_edit, self._service_type, account_type )
|
|
|
|
dlg_edit.SetPanel( panel )
|
|
|
|
if dlg_edit.exec() == QW.QDialog.Accepted:
|
|
|
|
edited_account_type = panel.GetValue()
|
|
|
|
self._account_types_listctrl.ReplaceData( account_type, edited_account_type )
|
|
|
|
else:
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
def GetValue( self ):
|
|
|
|
account_types = [ at for at in self._original_account_types if at.IsNullAccount() ]
|
|
|
|
account_types.extend( [ at for at in self._account_types_listctrl.GetData() if not at.IsNullAccount() ] )
|
|
|
|
def key_transfer_not_collapsed():
|
|
|
|
keys = set( self._deletee_account_type_keys_to_new_account_type_keys.keys() )
|
|
values = set( self._deletee_account_type_keys_to_new_account_type_keys.values() )
|
|
|
|
return HydrusData.SetsIntersect( keys, values )
|
|
|
|
|
|
while key_transfer_not_collapsed():
|
|
|
|
# some deletees are going to other deletees, so lets collapse
|
|
|
|
deletee_account_type_keys = set( self._deletee_account_type_keys_to_new_account_type_keys.keys() )
|
|
|
|
account_type_keys_tuples = list(self._deletee_account_type_keys_to_new_account_type_keys.items())
|
|
|
|
for ( deletee_account_type_key, new_account_type_key ) in account_type_keys_tuples:
|
|
|
|
if new_account_type_key in deletee_account_type_keys:
|
|
|
|
better_new_account_type_key = self._deletee_account_type_keys_to_new_account_type_keys[ new_account_type_key ]
|
|
|
|
self._deletee_account_type_keys_to_new_account_type_keys[ deletee_account_type_key ] = better_new_account_type_key
|
|
|
|
|
|
|
|
|
|
return ( account_types, self._deletee_account_type_keys_to_new_account_type_keys )
|
|
|
|
|
|
class ListAccountsPanel( ClientGUIScrolledPanels.ReviewPanel ):
|
|
|
|
def __init__( self, parent: QW.QWidget, service_key: bytes, accounts: typing.Collection[ HydrusNetwork.Account ] ):
|
|
|
|
ClientGUIScrolledPanels.ReviewPanel.__init__( self, parent )
|
|
|
|
self._service_key = service_key
|
|
self._service = HG.client_controller.services_manager.GetService( self._service_key )
|
|
self._accounts = accounts
|
|
|
|
self._accounts_box = ClientGUICommon.StaticBox( self, 'accounts' )
|
|
|
|
self._account_list = ClientGUIListBoxes.BetterQListWidget( self._accounts_box )
|
|
self._account_list.setSelectionMode( QW.QListWidget.ExtendedSelection )
|
|
|
|
( min_width, min_height ) = ClientGUIFunctions.ConvertTextToPixels( self._account_list, ( 74, 16 ) )
|
|
|
|
self._account_list.setMinimumSize( min_width, min_height )
|
|
|
|
modify_button = ClientGUICommon.BetterButton( self._accounts_box, 'modify selected', self._ModifyAccounts )
|
|
|
|
#
|
|
|
|
my_admin_account_key = self._service.GetAccount().GetAccountKey()
|
|
|
|
accounts.sort( key = lambda a: ( a.GetAccountType().GetTitle(), a.GetAccountKey().hex() ) )
|
|
|
|
for account in accounts:
|
|
|
|
item = QW.QListWidgetItem()
|
|
|
|
account_key = account.GetAccountKey()
|
|
|
|
text = account.GetSingleLineTitle()
|
|
|
|
if account_key == my_admin_account_key:
|
|
|
|
text = 'THIS IS YOU: {}'.format( text )
|
|
|
|
|
|
item.setText( text )
|
|
|
|
item.setData( QC.Qt.UserRole, account )
|
|
|
|
self._account_list.addItem( item )
|
|
|
|
|
|
#
|
|
|
|
self._accounts_box.Add( self._account_list, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
|
|
vbox = QP.VBoxLayout()
|
|
|
|
QP.AddToLayout( vbox, self._accounts_box, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
QP.AddToLayout( vbox, modify_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
|
|
self.widget().setLayout( vbox )
|
|
|
|
#
|
|
|
|
self._account_list.itemDoubleClicked.connect( self._ModifyAccounts )
|
|
|
|
|
|
def _ModifyAccounts( self ):
|
|
|
|
accounts = self._account_list.GetData( only_selected = True )
|
|
|
|
if len( accounts ) > 0:
|
|
|
|
subject_account_identifiers = [ HydrusNetwork.AccountIdentifier( account_key = account.GetAccountKey() ) for account in accounts ]
|
|
|
|
frame = ClientGUITopLevelWindowsPanels.FrameThatTakesScrollablePanel( self.window().parentWidget(), 'manage accounts' )
|
|
|
|
panel = ModifyAccountsPanel( frame, self._service_key, subject_account_identifiers )
|
|
|
|
frame.SetPanel( panel )
|
|
|
|
|
|
|
|
class ReviewAccountsPanel( QW.QWidget ):
|
|
|
|
accountsFetchFinished = QC.Signal()
|
|
accountsFetchStarted = QC.Signal()
|
|
|
|
def __init__( self, parent: QW.QWidget, service_key: bytes, account_identifiers: typing.Collection[ HydrusNetwork.AccountIdentifier ] ):
|
|
|
|
QW.QWidget.__init__( self, parent )
|
|
|
|
self._service_key = service_key
|
|
self._service = HG.client_controller.services_manager.GetService( self._service_key )
|
|
self._account_identifiers = account_identifiers
|
|
|
|
self._done_first_fetch = False
|
|
self._accounts_loaded = False
|
|
self._account_keys_to_accounts = {}
|
|
self._account_keys_to_account_info = {}
|
|
|
|
self._accounts_box = ClientGUICommon.StaticBox( self, 'accounts' )
|
|
|
|
self._status_st = ClientGUICommon.BetterStaticText( self._accounts_box )
|
|
|
|
self._account_list = ClientGUICommon.BetterCheckBoxList( self._accounts_box )
|
|
self._account_list.setSelectionMode( QW.QAbstractItemView.SingleSelection )
|
|
|
|
( min_width, min_height ) = ClientGUIFunctions.ConvertTextToPixels( self._account_list, ( 74, 6 ) )
|
|
|
|
self._account_list.setMinimumSize( min_width, min_height )
|
|
|
|
self._account_info_box = QW.QTextEdit( self._accounts_box )
|
|
self._account_info_box.setReadOnly( True )
|
|
|
|
( min_width, min_height ) = ClientGUIFunctions.ConvertTextToPixels( self._account_info_box, ( 16, 8 ) )
|
|
|
|
self._account_info_box.setMinimumHeight( min_height )
|
|
|
|
self._copy_checked_account_keys_button = ClientGUICommon.BetterButton( self._accounts_box, 'copy checked account ids', self._CopyCheckedAccountKeys )
|
|
|
|
#
|
|
|
|
self._accounts_box.Add( self._status_st, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
self._accounts_box.Add( self._account_list, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
self._accounts_box.Add( self._account_info_box, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
self._accounts_box.Add( self._copy_checked_account_keys_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
|
|
vbox = QP.VBoxLayout()
|
|
|
|
QP.AddToLayout( vbox, self._accounts_box, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
|
|
self.setLayout( vbox )
|
|
|
|
#
|
|
|
|
self._account_list.itemClicked.connect( self._AccountClicked )
|
|
|
|
|
|
def _AccountClicked( self ):
|
|
|
|
selected_indices = sorted( self._account_list.GetSelectedIndices() )
|
|
|
|
if len( selected_indices ) > 0:
|
|
|
|
item = self._account_list.item( selected_indices[0] )
|
|
|
|
account_info_components = []
|
|
|
|
account_key = item.data( QC.Qt.UserRole )
|
|
|
|
my_admin_account = self._service.GetAccount()
|
|
|
|
if account_key == my_admin_account.GetAccountKey():
|
|
|
|
account_info_components.append( 'THIS IS YOU' )
|
|
|
|
|
|
if account_key in self._account_keys_to_accounts:
|
|
|
|
account = self._account_keys_to_accounts[ account_key ]
|
|
|
|
account_info_components.append( account.ToString() )
|
|
account_info_components.append( account.GetExpiresString() )
|
|
account_info_components.append( account.GetStatusInfo()[1] )
|
|
|
|
( message, message_created ) = account.GetMessageAndTimestamp()
|
|
|
|
if message != '':
|
|
|
|
account_info_components.append( 'Message: {}'.format( message ) )
|
|
|
|
else:
|
|
|
|
account_info_components.append( 'No message set.' )
|
|
|
|
|
|
if account_key in self._account_keys_to_account_info:
|
|
|
|
account_info_components.append( self._account_keys_to_account_info[ account_key ] )
|
|
|
|
else:
|
|
|
|
account_info_components.append( 'Could not find info for this account!' )
|
|
|
|
|
|
else:
|
|
|
|
account_info_components.append( 'Could not find this account!' )
|
|
|
|
|
|
joiner = os.linesep * 2
|
|
|
|
account_info = joiner.join( account_info_components )
|
|
|
|
else:
|
|
|
|
account_info = ''
|
|
|
|
|
|
self._account_info_box.setText( account_info )
|
|
|
|
|
|
def _CopyCheckedAccountKeys( self ):
|
|
|
|
checked_account_keys = self.GetCheckedAccountKeys()
|
|
|
|
if len( checked_account_keys ) > 0:
|
|
|
|
account_keys_text = os.linesep.join( ( account_key.hex() for account_key in checked_account_keys ) )
|
|
|
|
HG.client_controller.pub( 'clipboard', 'text', account_keys_text )
|
|
|
|
|
|
|
|
def _RefreshAccounts( self ):
|
|
|
|
# TODO: so, rework this guy, and modifyaccounts parent, to not hold account_identifiers, but account_keys. have an async lookup convert contents to account keys before launching this guy
|
|
|
|
account_identifiers = self._account_identifiers
|
|
service = self._service
|
|
|
|
selected_account_keys = self.GetCheckedAccountKeys()
|
|
|
|
def work_callable():
|
|
|
|
account_errors = set()
|
|
|
|
account_keys_to_accounts = {}
|
|
account_keys_to_account_info = {}
|
|
|
|
for account_identifier in account_identifiers:
|
|
|
|
try:
|
|
|
|
result = service.Request( HC.GET, 'other_account', { 'subject_identifier' : account_identifier } )
|
|
|
|
except Exception as e:
|
|
|
|
account_errors.add( str( e ) )
|
|
|
|
continue
|
|
|
|
|
|
if 'account' in result:
|
|
|
|
account = result[ 'account' ]
|
|
|
|
subject_account_key = account.GetAccountKey()
|
|
|
|
if subject_account_key in account_keys_to_accounts:
|
|
|
|
continue
|
|
|
|
|
|
account_keys_to_accounts[ subject_account_key ] = account
|
|
|
|
try:
|
|
|
|
response = self._service.Request( HC.GET, 'account_info', { 'subject_account_key' : subject_account_key } )
|
|
|
|
except Exception as e:
|
|
|
|
HydrusData.PrintException( e )
|
|
|
|
continue
|
|
|
|
|
|
account_string = str( response[ 'account_info' ] )
|
|
|
|
account_keys_to_account_info[ subject_account_key ] = account_string
|
|
|
|
|
|
|
|
return ( account_keys_to_accounts, account_keys_to_account_info, account_errors )
|
|
|
|
|
|
def publish_callable( result ):
|
|
|
|
( self._account_keys_to_accounts, self._account_keys_to_account_info, account_errors ) = result
|
|
|
|
if len( account_errors ) > 0:
|
|
|
|
account_errors = sorted( account_errors )
|
|
|
|
QW.QMessageBox.information( self, 'Information', 'Errors were encountered during account fetch:{}{}'.format( os.linesep * 2, os.linesep.join( account_errors ) ) )
|
|
|
|
|
|
if not self._done_first_fetch:
|
|
|
|
# if we launched with CPU-expensive mapping identifiers, let's move to nice account ids for future refreshes
|
|
|
|
self._account_identifiers = [ HydrusNetwork.AccountIdentifier( account_key = account_key ) for account_key in self._account_keys_to_accounts.keys() ]
|
|
|
|
|
|
#
|
|
|
|
account_keys_sorted = sorted(
|
|
list( self._account_keys_to_accounts.keys() ),
|
|
key = lambda sak: ( self._account_keys_to_accounts[ sak ].GetAccountType().GetTitle(), sak.hex() )
|
|
)
|
|
|
|
my_admin_account = self._service.GetAccount()
|
|
|
|
my_admin_account_key = my_admin_account.GetAccountKey()
|
|
|
|
for account_key in account_keys_sorted:
|
|
|
|
item = QW.QListWidgetItem()
|
|
|
|
item.setFlags( item.flags() | QC.Qt.ItemIsUserCheckable )
|
|
|
|
account = self._account_keys_to_accounts[ account_key ]
|
|
|
|
text = account.GetSingleLineTitle()
|
|
|
|
if account_key == my_admin_account_key:
|
|
|
|
text = 'THIS IS YOU: {}'.format( text )
|
|
|
|
|
|
item.setText( text )
|
|
|
|
if not self._done_first_fetch or account_key in selected_account_keys:
|
|
|
|
item.setCheckState( QC.Qt.Checked )
|
|
|
|
else:
|
|
|
|
item.setCheckState( QC.Qt.Unchecked )
|
|
|
|
|
|
item.setData( QC.Qt.UserRole, account_key )
|
|
|
|
self._account_list.addItem( item )
|
|
|
|
|
|
#
|
|
|
|
self._status_st.setVisible( False )
|
|
self._status_st.setText( '' )
|
|
|
|
if self._account_list.count() > 0:
|
|
|
|
self._account_list.item( 0 ).setSelected( True )
|
|
|
|
self._AccountClicked()
|
|
|
|
|
|
self._accounts_loaded = True
|
|
self._done_first_fetch = True
|
|
|
|
self.accountsFetchFinished.emit()
|
|
|
|
|
|
self._status_st.setVisible( True )
|
|
self._status_st.setText( 'fetching accounts\u2026' )
|
|
|
|
self._accounts_loaded = False
|
|
|
|
self._account_list.clear()
|
|
|
|
self._account_info_box.clear()
|
|
|
|
self._account_keys_to_accounts = {}
|
|
self._account_keys_to_account_info = {}
|
|
|
|
self.accountsFetchStarted.emit()
|
|
|
|
job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable )
|
|
|
|
job.start()
|
|
|
|
|
|
def AccountsLoaded( self ):
|
|
|
|
return self._accounts_loaded
|
|
|
|
|
|
def GetCheckedAccountKeys( self ):
|
|
|
|
account_keys = set()
|
|
|
|
for i in range( self._account_list.count() ):
|
|
|
|
item = self._account_list.item( i )
|
|
|
|
if item.checkState() == QC.Qt.Checked:
|
|
|
|
account_keys.add( item.data( QC.Qt.UserRole ) )
|
|
|
|
|
|
|
|
return account_keys
|
|
|
|
|
|
def GetCheckedAccounts( self ):
|
|
|
|
checked_account_keys = self.GetCheckedAccountKeys()
|
|
|
|
return { self._account_keys_to_accounts[ account_key ] for account_key in checked_account_keys }
|
|
|
|
|
|
def RefreshAccounts( self ):
|
|
|
|
self._RefreshAccounts()
|
|
|
|
|
|
def UncheckAccountKey( self, account_key: bytes ):
|
|
|
|
for i in range( self._account_list.count() ):
|
|
|
|
item = self._account_list.item( i )
|
|
|
|
checked_account_key = item.data( QC.Qt.UserRole )
|
|
|
|
if checked_account_key == account_key:
|
|
|
|
item.setCheckState( QC.Qt.Unchecked )
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
def UncheckNullAccount( self ):
|
|
|
|
for i in range( self._account_list.count() ):
|
|
|
|
item = self._account_list.item( i )
|
|
|
|
account_key = item.data( QC.Qt.UserRole )
|
|
|
|
account = self._account_keys_to_accounts[ account_key ]
|
|
|
|
if account.IsNullAccount():
|
|
|
|
item.setCheckState( QC.Qt.Unchecked )
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
class ModifyAccountsPanel( ClientGUIScrolledPanels.ReviewPanel ):
|
|
|
|
def __init__( self, parent: QW.QWidget, service_key: bytes, subject_identifiers: typing.Collection[ HydrusNetwork.AccountIdentifier ] ):
|
|
|
|
ClientGUIScrolledPanels.ReviewPanel.__init__( self, parent )
|
|
|
|
self._service_key = service_key
|
|
self._service = HG.client_controller.services_manager.GetService( service_key )
|
|
self._subject_identifiers = subject_identifiers
|
|
self._account_types = []
|
|
|
|
#
|
|
|
|
self._account_panel = ReviewAccountsPanel( self, service_key, subject_identifiers )
|
|
|
|
#
|
|
|
|
self._message_panel = ClientGUICommon.StaticBox( self, 'message' )
|
|
|
|
self._message_text = QW.QLineEdit( self._message_panel )
|
|
|
|
self._set_message_button = ClientGUICommon.BetterButton( self._message_panel, 'set message', self._DoSetMessage )
|
|
|
|
#
|
|
|
|
self._expiration_panel = ClientGUICommon.StaticBox( self, 'change expiration' )
|
|
|
|
self._add_to_expires = ClientGUICommon.BetterChoice( self._expiration_panel )
|
|
|
|
for ( label, value ) in HC.lifetimes:
|
|
|
|
if value is not None:
|
|
|
|
self._add_to_expires.addItem( label, value )
|
|
|
|
|
|
|
|
self._add_to_expires_button = ClientGUICommon.BetterButton( self._expiration_panel, 'ok', self._AddToExpires )
|
|
|
|
self._add_to_expires_button.SetYesNoText( 'Add time to account expiration?' )
|
|
|
|
self._set_expires = ClientGUICommon.BetterChoice( self._expiration_panel )
|
|
|
|
for ( label, value ) in HC.lifetimes:
|
|
|
|
self._set_expires.addItem( label, value )
|
|
|
|
|
|
self._set_expires_button = ClientGUICommon.BetterButton( self._expiration_panel, 'ok', self._SetExpires )
|
|
|
|
self._set_expires_button.SetYesNoText( 'Set new account expiration?' )
|
|
|
|
#
|
|
|
|
self._account_types_panel = ClientGUICommon.StaticBox( self, 'account types' )
|
|
|
|
self._account_types_choice = ClientGUICommon.BetterChoice( self._account_types_panel )
|
|
|
|
self._account_types_button = ClientGUICommon.BetterButton( self._account_types_panel, 'ok', self._DoAccountType )
|
|
|
|
self._account_types_button.SetYesNoText( 'Set new account type?' )
|
|
|
|
#
|
|
|
|
self._ban_panel = ClientGUICommon.StaticBox( self, 'bans' )
|
|
|
|
self._ban_reason = QW.QLineEdit( self._ban_panel )
|
|
|
|
self._ban_expires = ClientGUICommon.BetterChoice( self._ban_panel )
|
|
|
|
for ( label, value ) in HC.lifetimes:
|
|
|
|
self._ban_expires.addItem( label, value )
|
|
|
|
|
|
self._ban_button = ClientGUICommon.BetterButton( self._ban_panel, 'ban account', self._DoBan )
|
|
self._unban_button = ClientGUICommon.BetterButton( self._ban_panel, 'unban account', self._DoUnban )
|
|
|
|
self._unban_button.SetYesNoText( 'Unban the account(s)?' )
|
|
|
|
#
|
|
|
|
self._add_to_expires.SetValue( 3 * 31 * 86400 ) # three months
|
|
|
|
self._set_expires.SetValue( 3 * 31 * 86400 ) # three months
|
|
|
|
#
|
|
|
|
gridbox_rows = []
|
|
|
|
gridbox_rows.append( ( 'message:', self._message_text ) )
|
|
|
|
gridbox = ClientGUICommon.WrapInGrid( self._message_panel, gridbox_rows )
|
|
|
|
self._message_panel.Add( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
|
self._message_panel.Add( self._set_message_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
|
|
add_to_expires_box = QP.HBoxLayout()
|
|
|
|
QP.AddToLayout( add_to_expires_box, QW.QLabel( 'add to expires: ', self._expiration_panel ), CC.FLAGS_CENTER_PERPENDICULAR )
|
|
QP.AddToLayout( add_to_expires_box, self._add_to_expires, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
QP.AddToLayout( add_to_expires_box, self._add_to_expires_button, CC.FLAGS_CENTER_PERPENDICULAR )
|
|
|
|
set_expires_box = QP.HBoxLayout()
|
|
|
|
QP.AddToLayout( set_expires_box, QW.QLabel( 'set expires to: ', self._expiration_panel ), CC.FLAGS_CENTER_PERPENDICULAR )
|
|
QP.AddToLayout( set_expires_box, self._set_expires, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
QP.AddToLayout( set_expires_box, self._set_expires_button, CC.FLAGS_CENTER_PERPENDICULAR )
|
|
|
|
self._expiration_panel.Add( add_to_expires_box, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
self._expiration_panel.Add( set_expires_box, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
|
|
account_types_hbox = QP.HBoxLayout()
|
|
|
|
QP.AddToLayout( account_types_hbox, self._account_types_choice, CC.FLAGS_CENTER_PERPENDICULAR )
|
|
QP.AddToLayout( account_types_hbox, self._account_types_button, CC.FLAGS_CENTER_PERPENDICULAR )
|
|
|
|
self._account_types_panel.Add( account_types_hbox, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
|
|
gridbox_rows = []
|
|
|
|
gridbox_rows.append( ( 'ban reason:', self._ban_reason ) )
|
|
gridbox_rows.append( ( 'ban expiration:', self._ban_expires ) )
|
|
|
|
gridbox = ClientGUICommon.WrapInGrid( self._ban_panel, gridbox_rows )
|
|
|
|
self._ban_panel.Add( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
|
self._ban_panel.Add( self._ban_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
self._ban_panel.Add( self._unban_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
|
|
vbox = QP.VBoxLayout()
|
|
|
|
self._modification_status = ClientGUICommon.BetterStaticText( self )
|
|
|
|
QP.AddToLayout( vbox, self._modification_status, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, self._account_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
QP.AddToLayout( vbox, self._message_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, self._account_types_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, self._expiration_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, self._ban_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
|
|
self.widget().setLayout( vbox )
|
|
|
|
#
|
|
|
|
self._account_panel.accountsFetchStarted.connect( self._DisableUIForRefresh )
|
|
self._account_panel.accountsFetchFinished.connect( self._EnableUIAfterRefresh )
|
|
|
|
#
|
|
|
|
self._InitialiseAccountTypes()
|
|
|
|
self._account_panel.RefreshAccounts()
|
|
|
|
|
|
def _AddToExpires( self ):
|
|
|
|
expires_delta = self._add_to_expires.GetValue()
|
|
|
|
self._account_panel.UncheckNullAccount()
|
|
|
|
subject_accounts = self._account_panel.GetCheckedAccounts()
|
|
|
|
num_unchecked = 0
|
|
|
|
for subject_account in subject_accounts:
|
|
|
|
if subject_account.GetExpires() is None:
|
|
|
|
self._account_panel.UncheckAccountKey( subject_account.GetAccountKey() )
|
|
|
|
num_unchecked += 1
|
|
|
|
|
|
|
|
QW.QMessageBox.information( self, 'Information', '{} accounts do not expire, so could not have time added!'.format( HydrusData.ToHumanInt( num_unchecked ) ) )
|
|
|
|
subject_accounts = self._account_panel.GetCheckedAccounts()
|
|
|
|
subject_account_keys_and_current_expires = [ ( subject_account.GetAccountKey(), subject_account.GetExpires() ) for subject_account in subject_accounts ]
|
|
|
|
subject_account_keys_and_new_expires = [ ( subject_account_key, current_expires + expires_delta ) for ( subject_account_key, current_expires ) in subject_account_keys_and_current_expires ]
|
|
|
|
self._DoExpires( subject_account_keys_and_new_expires )
|
|
|
|
|
|
def _DisableUIForJob( self, message ):
|
|
|
|
self.setEnabled( False )
|
|
|
|
self._modification_status.setVisible( True )
|
|
|
|
self._modification_status.setText( message )
|
|
|
|
|
|
def _DisableUIForRefresh( self ):
|
|
|
|
self._DisableUIForJob( 'refreshing accounts\u2026' )
|
|
|
|
|
|
def _DoAccountType( self ):
|
|
|
|
self._account_panel.UncheckNullAccount()
|
|
|
|
subject_account_keys = self._account_panel.GetCheckedAccountKeys()
|
|
|
|
if len( subject_account_keys ) == 0:
|
|
|
|
QW.QMessageBox.information( self, 'Information', 'No accounts selected for action!' )
|
|
|
|
return
|
|
|
|
|
|
service = self._service
|
|
|
|
account_type = self._account_types_choice.GetValue()
|
|
|
|
account_type_key = account_type.GetAccountTypeKey()
|
|
|
|
def work_callable():
|
|
|
|
for subject_account_key in subject_account_keys:
|
|
|
|
service.Request( HC.POST, 'modify_account_account_type', { 'subject_account_key' : subject_account_key, 'account_type_key' : account_type_key } )
|
|
|
|
|
|
return 1
|
|
|
|
|
|
def publish_callable( gumpf ):
|
|
|
|
QW.QMessageBox.information( self, 'Information', 'Done!' )
|
|
|
|
self._account_panel.RefreshAccounts()
|
|
|
|
|
|
self._DisableUIForJob( 'setting new account type\u2026' )
|
|
|
|
job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable )
|
|
|
|
job.start()
|
|
|
|
|
|
def _DoBan( self ):
|
|
|
|
self._account_panel.UncheckNullAccount()
|
|
|
|
subject_accounts = self._account_panel.GetCheckedAccounts()
|
|
|
|
if len( subject_accounts ) == 0:
|
|
|
|
QW.QMessageBox.information( self, 'Information', 'No accounts selected for action!' )
|
|
|
|
return
|
|
|
|
|
|
some_are_banned = True in ( subject_account.IsBanned() for subject_account in subject_accounts )
|
|
|
|
if some_are_banned:
|
|
|
|
message = 'Some of these selected accounts are already banned. Sure you want to overwrite the bans?'
|
|
|
|
result = ClientGUIDialogsQuick.GetYesNo( self, message )
|
|
|
|
if result != QW.QDialog.Accepted:
|
|
|
|
return
|
|
|
|
|
|
|
|
subject_account_keys = [ subject_account.GetAccountKey() for subject_account in subject_accounts ]
|
|
|
|
reason = self._ban_reason.text()
|
|
|
|
if reason == '':
|
|
|
|
QW.QMessageBox.information( self, 'Information', 'The ban reason is empty!' )
|
|
|
|
return
|
|
|
|
|
|
message = 'Ban these user(s)? All of their pending petitions will be deleted serverside.'
|
|
|
|
result = ClientGUIDialogsQuick.GetYesNo( self, message )
|
|
|
|
if result != QW.QDialog.Accepted:
|
|
|
|
return
|
|
|
|
|
|
expires = self._ban_expires.GetValue()
|
|
|
|
if expires is not None:
|
|
|
|
expires += HydrusData.GetNow()
|
|
|
|
|
|
service = self._service
|
|
|
|
def work_callable():
|
|
|
|
for subject_account_key in subject_account_keys:
|
|
|
|
service.Request( HC.POST, 'modify_account_ban', { 'subject_account_key' : subject_account_key, 'reason' : reason, 'expires' : expires } )
|
|
|
|
|
|
return 1
|
|
|
|
|
|
def publish_callable( gumpf ):
|
|
|
|
QW.QMessageBox.information( self, 'Information', 'Done!' )
|
|
|
|
self._account_panel.RefreshAccounts()
|
|
|
|
|
|
self._DisableUIForJob( 'banning\u2026' )
|
|
|
|
job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable )
|
|
|
|
job.start()
|
|
|
|
|
|
def _DoExpires( self, subject_account_keys_and_new_expires ):
|
|
|
|
if len( subject_account_keys_and_new_expires ) == 0:
|
|
|
|
QW.QMessageBox.information( self, 'Information', 'No accounts selected for action!' )
|
|
|
|
return
|
|
|
|
|
|
service = self._service
|
|
|
|
def work_callable():
|
|
|
|
for ( subject_account_key, new_expires ) in subject_account_keys_and_new_expires:
|
|
|
|
service.Request( HC.POST, 'modify_account_expires', { 'subject_account_key' : subject_account_key, 'expires' : new_expires } )
|
|
|
|
|
|
return 1
|
|
|
|
|
|
def publish_callable( gumpf ):
|
|
|
|
QW.QMessageBox.information( self, 'Information', 'Done!' )
|
|
|
|
self._account_panel.RefreshAccounts()
|
|
|
|
|
|
self._DisableUIForJob( 'setting new expiry\u2026' )
|
|
|
|
job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable )
|
|
|
|
job.start()
|
|
|
|
|
|
def _DoSetMessage( self ):
|
|
|
|
self._account_panel.UncheckNullAccount()
|
|
|
|
subject_accounts = self._account_panel.GetCheckedAccounts()
|
|
|
|
if len( subject_accounts ) == 0:
|
|
|
|
QW.QMessageBox.information( self, 'Information', 'No accounts selected for action!' )
|
|
|
|
return
|
|
|
|
|
|
message = self._message_text.text()
|
|
|
|
if message == '':
|
|
|
|
yn_message = 'Clear message for the selected accounts?'
|
|
|
|
else:
|
|
|
|
yn_message = 'Set this message for the selected accounts?'
|
|
|
|
|
|
result = ClientGUIDialogsQuick.GetYesNo( self, yn_message )
|
|
|
|
if result != QW.QDialog.Accepted:
|
|
|
|
return
|
|
|
|
|
|
subject_account_keys = [ subject_account.GetAccountKey() for subject_account in subject_accounts ]
|
|
|
|
service = self._service
|
|
|
|
def work_callable():
|
|
|
|
for subject_account_key in subject_account_keys:
|
|
|
|
service.Request( HC.POST, 'modify_account_set_message', { 'subject_account_key' : subject_account_key, 'message': message } )
|
|
|
|
|
|
return 1
|
|
|
|
|
|
def publish_callable( gumpf ):
|
|
|
|
QW.QMessageBox.information( self, 'Information', 'Done!' )
|
|
|
|
self._account_panel.RefreshAccounts()
|
|
|
|
|
|
self._DisableUIForJob( 'setting message\u2026' )
|
|
|
|
job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable )
|
|
|
|
job.start()
|
|
|
|
|
|
def _DoUnban( self ):
|
|
|
|
self._account_panel.UncheckNullAccount()
|
|
|
|
subject_accounts = self._account_panel.GetCheckedAccounts()
|
|
|
|
if len( subject_accounts ) == 0:
|
|
|
|
QW.QMessageBox.information( self, 'Information', 'No accounts selected for action!' )
|
|
|
|
return
|
|
|
|
|
|
subject_accounts = [ subject_account for subject_account in subject_accounts if subject_account.IsBanned() ]
|
|
|
|
if len( subject_accounts ) == 0:
|
|
|
|
QW.QMessageBox.information( self, 'Information', 'None of the selected accounts are banned!' )
|
|
|
|
return
|
|
|
|
|
|
subject_account_keys = [ subject_account.GetAccountKey() for subject_account in subject_accounts ]
|
|
|
|
service = self._service
|
|
|
|
def work_callable():
|
|
|
|
for subject_account_key in subject_account_keys:
|
|
|
|
service.Request( HC.POST, 'modify_account_unban', { 'subject_account_key' : subject_account_key } )
|
|
|
|
|
|
return 1
|
|
|
|
|
|
def publish_callable( gumpf ):
|
|
|
|
QW.QMessageBox.information( self, 'Information', 'Done!' )
|
|
|
|
self._account_panel.RefreshAccounts()
|
|
|
|
|
|
self._DisableUIForJob( 'unbanning\u2026' )
|
|
|
|
job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable )
|
|
|
|
job.start()
|
|
|
|
|
|
def _EnableUIAfterRefresh( self ):
|
|
|
|
self._modification_status.setVisible( False )
|
|
|
|
self._modification_status.setText( '' )
|
|
|
|
self.setEnabled( True )
|
|
|
|
|
|
def _InitialiseAccountTypes( self ):
|
|
|
|
service = self._service
|
|
|
|
def work_callable():
|
|
|
|
response = service.Request( HC.GET, 'account_types' )
|
|
|
|
account_types = response[ 'account_types' ]
|
|
|
|
return account_types
|
|
|
|
|
|
def publish_callable( result ):
|
|
|
|
self._account_types = result
|
|
|
|
self._account_types_choice.setEnabled( True )
|
|
self._account_types_button.setEnabled( True )
|
|
|
|
self._account_types.sort( key = lambda at: str( at ) )
|
|
|
|
for account_type in self._account_types:
|
|
|
|
self._account_types_choice.addItem( str( account_type ), account_type )
|
|
|
|
|
|
|
|
self._account_types_choice.setEnabled( False )
|
|
self._account_types_button.setEnabled( False )
|
|
|
|
job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable )
|
|
|
|
job.start()
|
|
|
|
|
|
def _SetExpires( self ):
|
|
|
|
self._account_panel.UncheckNullAccount()
|
|
|
|
expires = self._set_expires.GetValue()
|
|
|
|
if expires is not None:
|
|
|
|
expires += HydrusData.GetNow()
|
|
|
|
|
|
subject_account_keys_and_new_expires = [ ( subject_account_key, expires ) for subject_account_key in self._account_panel.GetCheckedAccountKeys() ]
|
|
|
|
self._DoExpires( subject_account_keys_and_new_expires )
|
|
|
|
|