hydrus/hydrus/client/gui/ClientGUIControls.py

751 lines
23 KiB
Python
Raw Normal View History

2020-05-13 19:03:16 +00:00
import typing
2019-11-14 03:56:30 +00:00
from qtpy import QtCore as QC
from qtpy import QtWidgets as QW
2020-04-22 21:00:35 +00:00
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 import HydrusNetworking
from hydrus.core import HydrusText
from hydrus.client import ClientConstants as CC
from hydrus.client.gui import ClientGUICommon
from hydrus.client.gui import ClientGUICore as CGC
from hydrus.client.gui import ClientGUIFunctions
from hydrus.client.gui import ClientGUIMenus
from hydrus.client.gui import ClientGUIScrolledPanels
from hydrus.client.gui import ClientGUITime
2020-04-29 21:44:12 +00:00
from hydrus.client.gui import ClientGUITopLevelWindowsPanels
2020-04-22 21:00:35 +00:00
from hydrus.client.gui import QtPorting as QP
2020-07-15 20:52:09 +00:00
from hydrus.client.gui.lists import ClientGUIListConstants as CGLC
from hydrus.client.gui.lists import ClientGUIListCtrl
2017-03-02 02:14:56 +00:00
class BandwidthRulesCtrl( ClientGUICommon.StaticBox ):
def __init__( self, parent, bandwidth_rules ):
ClientGUICommon.StaticBox.__init__( self, parent, 'bandwidth rules' )
2017-10-18 19:41:25 +00:00
listctrl_panel = ClientGUIListCtrl.BetterListCtrlPanel( self )
2017-03-02 02:14:56 +00:00
2020-07-15 20:52:09 +00:00
# example for later:
'''
def sort_call( desired_columns, rule ):
( bandwidth_type, time_delta, max_allowed ) = rule
sort_time_delta = SafeNoneInt( time_delta )
result = {}
result[ CGLC.COLUMN_LIST_BANDWIDTH_RULES.MAX_ALLOWED ] = max_allowed
result[ CGLC.COLUMN_LIST_BANDWIDTH_RULES.EVERY ] = sort_time_delta
return result
2018-08-01 20:44:57 +00:00
2020-07-15 20:52:09 +00:00
def display_call( desired_columns, rule ):
( bandwidth_type, time_delta, max_allowed ) = rule
if bandwidth_type == HC.BANDWIDTH_TYPE_DATA:
pretty_max_allowed = HydrusData.ToHumanBytes( max_allowed )
elif bandwidth_type == HC.BANDWIDTH_TYPE_REQUESTS:
pretty_max_allowed = '{} requests'.format( HydrusData.ToHumanInt( max_allowed ) )
pretty_time_delta = HydrusData.TimeDeltaToPrettyTimeDelta( time_delta )
result = {}
result[ CGLC.COLUMN_LIST_BANDWIDTH_RULES.MAX_ALLOWED ] = pretty_max_allowed
result[ CGLC.COLUMN_LIST_BANDWIDTH_RULES.EVERY ] = pretty_time_delta
return result
'''
self._listctrl = ClientGUIListCtrl.BetterListCtrl( listctrl_panel, CGLC.COLUMN_LIST_BANDWIDTH_RULES.ID, 8, self._ConvertRuleToListCtrlTuples, use_simple_delete = True, activation_callback = self._Edit )
2017-07-27 00:47:13 +00:00
listctrl_panel.SetListCtrl( self._listctrl )
listctrl_panel.AddButton( 'add', self._Add )
listctrl_panel.AddButton( 'edit', self._Edit, enabled_only_on_selection = True )
2018-10-17 21:00:09 +00:00
listctrl_panel.AddDeleteButton()
2017-03-02 02:14:56 +00:00
#
2017-10-18 19:41:25 +00:00
self._listctrl.AddDatas( bandwidth_rules.GetRules() )
2020-07-15 20:52:09 +00:00
self._listctrl.Sort()
2017-03-02 02:14:56 +00:00
#
2018-01-03 22:37:30 +00:00
self.Add( listctrl_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
2017-03-02 02:14:56 +00:00
def _Add( self ):
rule = ( HC.BANDWIDTH_TYPE_DATA, None, 1024 * 1024 * 100 )
2020-04-29 21:44:12 +00:00
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit rule' ) as dlg:
2017-03-02 02:14:56 +00:00
panel = self._EditPanel( dlg, rule )
dlg.SetPanel( panel )
2019-11-14 03:56:30 +00:00
if dlg.exec() == QW.QDialog.Accepted:
2017-03-02 02:14:56 +00:00
new_rule = panel.GetValue()
2017-10-18 19:41:25 +00:00
self._listctrl.AddDatas( ( new_rule, ) )
2017-03-02 02:14:56 +00:00
2017-10-18 19:41:25 +00:00
self._listctrl.Sort()
2017-03-02 02:14:56 +00:00
2018-10-17 21:00:09 +00:00
def _ConvertRuleToListCtrlTuples( self, rule ):
2017-03-02 02:14:56 +00:00
( bandwidth_type, time_delta, max_allowed ) = rule
2018-07-04 20:48:28 +00:00
pretty_time_delta = HydrusData.TimeDeltaToPrettyTimeDelta( time_delta )
2017-03-02 02:14:56 +00:00
if bandwidth_type == HC.BANDWIDTH_TYPE_DATA:
2019-01-09 22:59:03 +00:00
pretty_max_allowed = HydrusData.ToHumanBytes( max_allowed )
2017-03-02 02:14:56 +00:00
elif bandwidth_type == HC.BANDWIDTH_TYPE_REQUESTS:
2018-07-04 20:48:28 +00:00
pretty_max_allowed = HydrusData.ToHumanInt( max_allowed ) + ' requests'
2017-03-02 02:14:56 +00:00
2019-01-09 22:59:03 +00:00
sort_time_delta = ClientGUIListCtrl.SafeNoneInt( time_delta )
sort_tuple = ( max_allowed, sort_time_delta )
2018-03-14 21:01:02 +00:00
display_tuple = ( pretty_max_allowed, pretty_time_delta )
2017-10-18 19:41:25 +00:00
return ( display_tuple, sort_tuple )
2017-03-02 02:14:56 +00:00
def _Edit( self ):
2017-10-18 19:41:25 +00:00
selected_rules = self._listctrl.GetData( only_selected = True )
2017-03-02 02:14:56 +00:00
2017-10-18 19:41:25 +00:00
for rule in selected_rules:
2017-03-02 02:14:56 +00:00
2020-04-29 21:44:12 +00:00
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit rule' ) as dlg:
2017-03-02 02:14:56 +00:00
panel = self._EditPanel( dlg, rule )
dlg.SetPanel( panel )
2019-11-14 03:56:30 +00:00
if dlg.exec() == QW.QDialog.Accepted:
2017-03-02 02:14:56 +00:00
edited_rule = panel.GetValue()
2017-10-18 19:41:25 +00:00
self._listctrl.DeleteDatas( ( rule, ) )
2017-03-02 02:14:56 +00:00
2017-10-18 19:41:25 +00:00
self._listctrl.AddDatas( ( edited_rule, ) )
2017-03-02 02:14:56 +00:00
else:
break
2017-10-18 19:41:25 +00:00
self._listctrl.Sort()
2017-03-02 02:14:56 +00:00
def GetValue( self ):
bandwidth_rules = HydrusNetworking.BandwidthRules()
2017-10-18 19:41:25 +00:00
for rule in self._listctrl.GetData():
( bandwidth_type, time_delta, max_allowed ) = rule
2017-03-02 02:14:56 +00:00
bandwidth_rules.AddRule( bandwidth_type, time_delta, max_allowed )
return bandwidth_rules
class _EditPanel( ClientGUIScrolledPanels.EditPanel ):
def __init__( self, parent, rule ):
ClientGUIScrolledPanels.EditPanel.__init__( self, parent )
self._bandwidth_type = ClientGUICommon.BetterChoice( self )
2019-11-14 03:56:30 +00:00
self._bandwidth_type.addItem( 'data', HC.BANDWIDTH_TYPE_DATA )
self._bandwidth_type.addItem( 'requests', HC.BANDWIDTH_TYPE_REQUESTS )
2017-03-02 02:14:56 +00:00
2019-11-14 03:56:30 +00:00
self._bandwidth_type.currentIndexChanged.connect( self._UpdateEnabled )
2017-03-02 02:14:56 +00:00
2018-03-14 21:01:02 +00:00
self._max_allowed_bytes = BytesControl( self )
2019-11-14 03:56:30 +00:00
self._max_allowed_requests = QP.MakeQSpinBox( self, min=1, max=1048576 )
2017-03-02 02:14:56 +00:00
2018-03-14 21:01:02 +00:00
self._time_delta = ClientGUITime.TimeDeltaButton( self, min = 1, days = True, hours = True, minutes = True, seconds = True, monthly_allowed = True )
2017-03-02 02:14:56 +00:00
#
( bandwidth_type, time_delta, max_allowed ) = rule
2019-07-24 21:39:02 +00:00
self._bandwidth_type.SetValue( bandwidth_type )
2017-03-02 02:14:56 +00:00
self._time_delta.SetValue( time_delta )
if bandwidth_type == HC.BANDWIDTH_TYPE_DATA:
2018-03-14 21:01:02 +00:00
self._max_allowed_bytes.SetValue( max_allowed )
else:
2019-11-14 03:56:30 +00:00
self._max_allowed_requests.setValue( max_allowed )
2017-03-02 02:14:56 +00:00
2018-03-14 21:01:02 +00:00
self._UpdateEnabled()
2017-03-02 02:14:56 +00:00
#
2019-11-14 03:56:30 +00:00
hbox = QP.HBoxLayout()
2017-03-02 02:14:56 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( hbox, self._max_allowed_bytes, CC.FLAGS_VCENTER )
QP.AddToLayout( hbox, self._max_allowed_requests, CC.FLAGS_VCENTER )
QP.AddToLayout( hbox, self._bandwidth_type, CC.FLAGS_VCENTER )
QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,' every '), CC.FLAGS_VCENTER )
QP.AddToLayout( hbox, self._time_delta, CC.FLAGS_VCENTER )
2017-03-02 02:14:56 +00:00
2019-11-14 03:56:30 +00:00
self.widget().setLayout( hbox )
2017-03-02 02:14:56 +00:00
2018-03-14 21:01:02 +00:00
def _UpdateEnabled( self ):
2017-03-02 02:14:56 +00:00
2019-07-24 21:39:02 +00:00
bandwidth_type = self._bandwidth_type.GetValue()
2017-03-02 02:14:56 +00:00
if bandwidth_type == HC.BANDWIDTH_TYPE_DATA:
2019-11-14 03:56:30 +00:00
self._max_allowed_bytes.show()
self._max_allowed_requests.hide()
2017-03-02 02:14:56 +00:00
elif bandwidth_type == HC.BANDWIDTH_TYPE_REQUESTS:
2019-11-14 03:56:30 +00:00
self._max_allowed_bytes.hide()
self._max_allowed_requests.show()
2017-03-02 02:14:56 +00:00
def GetValue( self ):
2019-07-24 21:39:02 +00:00
bandwidth_type = self._bandwidth_type.GetValue()
2017-03-02 02:14:56 +00:00
time_delta = self._time_delta.GetValue()
if bandwidth_type == HC.BANDWIDTH_TYPE_DATA:
2018-03-14 21:01:02 +00:00
max_allowed = self._max_allowed_bytes.GetValue()
elif bandwidth_type == HC.BANDWIDTH_TYPE_REQUESTS:
2019-11-14 03:56:30 +00:00
max_allowed = self._max_allowed_requests.value()
2017-03-02 02:14:56 +00:00
return ( bandwidth_type, time_delta, max_allowed )
2017-03-08 23:23:12 +00:00
2019-11-14 03:56:30 +00:00
class BytesControl( QW.QWidget ):
valueChanged = QC.Signal()
2018-03-14 21:01:02 +00:00
def __init__( self, parent, initial_value = 65536 ):
2019-11-14 03:56:30 +00:00
QW.QWidget.__init__( self, parent )
2018-03-22 00:03:33 +00:00
2019-11-14 03:56:30 +00:00
self._spin = QP.MakeQSpinBox( self, min=0, max=1048576 )
2018-03-14 21:01:02 +00:00
self._unit = ClientGUICommon.BetterChoice( self )
2019-11-14 03:56:30 +00:00
self._unit.addItem( 'B', 1 )
self._unit.addItem( 'KB', 1024 )
self._unit.addItem( 'MB', 1024 * 1024 )
self._unit.addItem( 'GB', 1024 * 1024 * 1024 )
2018-03-14 21:01:02 +00:00
#
self.SetValue( initial_value )
#
2019-11-14 03:56:30 +00:00
hbox = QP.HBoxLayout()
2018-04-25 22:07:52 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( hbox, self._spin, CC.FLAGS_VCENTER )
QP.AddToLayout( hbox, self._unit, CC.FLAGS_VCENTER )
2018-04-25 22:07:52 +00:00
2019-11-14 03:56:30 +00:00
self.setLayout( hbox )
2018-04-25 22:07:52 +00:00
2019-11-14 03:56:30 +00:00
self._spin.valueChanged.connect( self._HandleValueChanged )
self._unit.currentIndexChanged.connect( self._HandleValueChanged )
2018-04-25 22:07:52 +00:00
2019-11-14 03:56:30 +00:00
def _HandleValueChanged( self, val ):
2018-04-25 22:07:52 +00:00
2019-11-14 03:56:30 +00:00
self.valueChanged.emit()
2018-04-25 22:07:52 +00:00
2018-03-14 21:01:02 +00:00
def GetSeparatedValue( self ):
2019-11-14 03:56:30 +00:00
return (self._spin.value(), self._unit.GetValue())
2018-03-14 21:01:02 +00:00
def GetValue( self ):
2019-11-14 03:56:30 +00:00
return self._spin.value() * self._unit.GetValue()
2018-03-14 21:01:02 +00:00
def SetSeparatedValue( self, value, unit ):
2019-11-14 03:56:30 +00:00
return (self._spin.setValue( value ), self._unit.SetValue( unit ))
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
def SetValue( self, value: int ):
2018-03-14 21:01:02 +00:00
max_unit = 1024 * 1024 * 1024
unit = 1
while value % 1024 == 0 and unit < max_unit:
2019-01-09 22:59:03 +00:00
value //= 1024
2018-03-14 21:01:02 +00:00
unit *= 1024
2019-11-14 03:56:30 +00:00
self._spin.setValue( value )
2019-07-24 21:39:02 +00:00
self._unit.SetValue( unit )
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
class NoneableBytesControl( QW.QWidget ):
valueChanged = QC.Signal()
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
def __init__( self, parent, initial_value = 65536, none_label = 'no limit' ):
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
QW.QWidget.__init__( self, parent )
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
self._bytes = BytesControl( self )
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
self._none_checkbox = QW.QCheckBox( none_label, self )
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
#
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
self.SetValue( initial_value )
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
#
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
hbox = QP.HBoxLayout()
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
QP.AddToLayout( hbox, self._bytes, CC.FLAGS_SIZER_VCENTER )
QP.AddToLayout( hbox, self._none_checkbox, CC.FLAGS_VCENTER )
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
self.setLayout( hbox )
2018-03-14 21:01:02 +00:00
#
2020-05-13 19:03:16 +00:00
self._none_checkbox.clicked.connect( self._UpdateEnabled )
self._bytes.valueChanged.connect( self._HandleValueChanged )
self._none_checkbox.clicked.connect( self._HandleValueChanged )
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
def _UpdateEnabled( self ):
if self._none_checkbox.isChecked():
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
self._bytes.setEnabled( False )
2018-03-14 21:01:02 +00:00
else:
2020-05-13 19:03:16 +00:00
self._bytes.setEnabled( True )
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
def _HandleValueChanged( self ):
2018-04-25 22:07:52 +00:00
2020-05-13 19:03:16 +00:00
self.valueChanged.emit()
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
def GetValue( self ):
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
if self._none_checkbox.isChecked():
return None
else:
return self._bytes.GetValue()
2018-03-22 00:03:33 +00:00
2020-05-13 19:03:16 +00:00
def setToolTip( self, text ):
2018-03-22 00:03:33 +00:00
2020-05-13 19:03:16 +00:00
QW.QWidget.setToolTip( self, text )
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
for c in self.children():
if isinstance( c, QW.QWidget ):
c.setToolTip( text )
2018-03-22 00:03:33 +00:00
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
def SetValue( self, value ):
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
if value is None:
2020-02-05 22:55:21 +00:00
2020-05-13 19:03:16 +00:00
self._none_checkbox.setChecked( True )
2020-02-05 22:55:21 +00:00
2020-05-13 19:03:16 +00:00
else:
2020-02-05 22:55:21 +00:00
2020-05-13 19:03:16 +00:00
self._none_checkbox.setChecked( False )
2020-02-05 22:55:21 +00:00
2020-05-13 19:03:16 +00:00
self._bytes.SetValue( value )
2020-02-05 22:55:21 +00:00
2020-05-13 19:03:16 +00:00
self._UpdateEnabled()
2018-03-14 21:01:02 +00:00
2020-05-13 19:03:16 +00:00
class NetworkJobControl( QW.QFrame ):
def __init__( self, parent ):
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
QW.QFrame.__init__( self, parent )
2017-07-27 00:47:13 +00:00
2020-05-13 19:03:16 +00:00
self.setFrameStyle( QW.QFrame.Box | QW.QFrame.Raised )
2018-08-01 20:44:57 +00:00
2020-05-13 19:03:16 +00:00
self._network_job = None
self._download_started = False
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
self._auto_override_bandwidth_rules = False
2017-07-27 00:47:13 +00:00
2020-05-13 19:03:16 +00:00
self._left_text = ClientGUICommon.BetterStaticText( self, ellipsize_end = True )
self._right_text = ClientGUICommon.BetterStaticText( self )
self._right_text.setAlignment( QC.Qt.AlignRight | QC.Qt.AlignVCenter )
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
self._last_right_min_width = 0
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
self._gauge = ClientGUICommon.Gauge( self )
2017-12-06 22:06:56 +00:00
2020-05-13 19:03:16 +00:00
self._cog_button = ClientGUICommon.BetterBitmapButton( self, CC.global_pixmaps().cog, self._ShowCogMenu )
self._cancel_button = ClientGUICommon.BetterBitmapButton( self, CC.global_pixmaps().stop, self.Cancel )
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
#
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
self._Update()
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
#
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
st_hbox = QP.HBoxLayout()
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
QP.AddToLayout( st_hbox, self._left_text, CC.FLAGS_EXPAND_BOTH_WAYS )
QP.AddToLayout( st_hbox, self._right_text, CC.FLAGS_VCENTER )
2017-12-06 22:06:56 +00:00
2020-05-13 19:03:16 +00:00
left_vbox = QP.VBoxLayout()
2017-12-06 22:06:56 +00:00
2020-05-13 19:03:16 +00:00
QP.AddToLayout( left_vbox, st_hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
QP.AddToLayout( left_vbox, self._gauge, CC.FLAGS_EXPAND_BOTH_WAYS )
2017-12-06 22:06:56 +00:00
2020-05-13 19:03:16 +00:00
hbox = QP.HBoxLayout()
QP.AddToLayout( hbox, left_vbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
QP.AddToLayout( hbox, self._cog_button, CC.FLAGS_VCENTER )
QP.AddToLayout( hbox, self._cancel_button, CC.FLAGS_VCENTER )
self.setLayout( hbox )
2017-12-06 22:06:56 +00:00
2020-05-13 19:03:16 +00:00
def _ShowCogMenu( self ):
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
menu = QW.QMenu()
if self._network_job is not None:
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
if self._network_job.CurrentlyWaitingOnConnectionError():
ClientGUIMenus.AppendMenuItem( menu, 'reattempt connection now', 'Stop waiting on a connection error and reattempt the job now.', self._network_job.OverrideConnectionErrorWait )
2019-07-24 21:39:02 +00:00
2020-05-13 19:03:16 +00:00
if self._network_job.CurrentlyWaitingOnServersideBandwidth():
ClientGUIMenus.AppendMenuItem( menu, 'reattempt request now (server reports low bandwidth)', 'Stop waiting on a serverside bandwidth delay and reattempt the job now.', self._network_job.OverrideServersideBandwidthWait )
2019-07-24 21:39:02 +00:00
2020-05-13 19:03:16 +00:00
if self._network_job.ObeysBandwidth():
ClientGUIMenus.AppendMenuItem( menu, 'override bandwidth rules for this job', 'Tell the current job to ignore existing bandwidth rules and go ahead anyway.', self._network_job.OverrideBandwidth )
2019-07-24 21:39:02 +00:00
2020-05-13 19:03:16 +00:00
if not self._network_job.TokensOK():
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
ClientGUIMenus.AppendMenuItem( menu, 'override gallery slot requirements for this job', 'Force-allow this download to proceed, ignoring the normal gallery wait times.', self._network_job.OverrideToken )
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
ClientGUIMenus.AppendSeparator( menu )
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
ClientGUIMenus.AppendMenuCheckItem( menu, 'auto-override bandwidth rules for all jobs here after five seconds', 'Ignore existing bandwidth rules for all jobs under this control, instead waiting a flat five seconds.', self._auto_override_bandwidth_rules, self.FlipAutoOverrideBandwidth )
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
CGC.core().PopupMenu( self._cog_button, menu )
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
def _OverrideBandwidthIfAppropriate( self ):
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
if self._network_job is None or self._network_job.NoEngineYet():
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
return
else:
if self._auto_override_bandwidth_rules and HydrusData.TimeHasPassed( self._network_job.GetCreationTime() + 5 ):
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
self._network_job.OverrideBandwidth()
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
def _Update( self ):
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
if self._network_job is None or self._network_job.NoEngineYet():
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
self._left_text.setText( '' )
self._right_text.setText( '' )
self._gauge.SetRange( 1 )
self._gauge.SetValue( 0 )
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
can_cancel = False
else:
if self._network_job.IsDone():
2020-02-05 22:55:21 +00:00
2020-05-13 19:03:16 +00:00
can_cancel = False
2020-02-05 22:55:21 +00:00
2020-05-13 19:03:16 +00:00
else:
2020-02-05 22:55:21 +00:00
2020-05-13 19:03:16 +00:00
can_cancel = True
2020-02-05 22:55:21 +00:00
2020-05-13 19:03:16 +00:00
( status_text, current_speed, bytes_read, bytes_to_read ) = self._network_job.GetStatus()
self._left_text.setText( status_text )
if not self._download_started and current_speed > 0:
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
self._download_started = True
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
speed_text = ''
if self._download_started and not self._network_job.HasError():
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
if bytes_read is not None:
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
if bytes_to_read is not None and bytes_read != bytes_to_read:
speed_text += HydrusData.ConvertValueRangeToBytes( bytes_read, bytes_to_read )
else:
speed_text += HydrusData.ToHumanBytes( bytes_read )
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
if current_speed != bytes_to_read: # if it is a real quick download, just say its size
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
speed_text += ' ' + HydrusData.ToHumanBytes( current_speed ) + '/s'
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
self._right_text.setText( speed_text )
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
right_width = ClientGUIFunctions.ConvertTextToPixelWidth( self._right_text, len( speed_text ) )
right_min_width = right_width
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
if right_min_width != self._last_right_min_width:
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
self._last_right_min_width = right_min_width
self._right_text.setMinimumWidth( right_min_width )
2018-10-17 21:00:09 +00:00
2017-12-06 22:06:56 +00:00
2020-05-13 19:03:16 +00:00
self._gauge.SetRange( bytes_to_read )
self._gauge.SetValue( bytes_read )
2017-12-06 22:06:56 +00:00
2020-05-13 19:03:16 +00:00
if can_cancel:
if not self._cancel_button.isEnabled():
self._cancel_button.setEnabled( True )
else:
if self._cancel_button.isEnabled():
self._cancel_button.setEnabled( False )
2017-03-22 22:38:15 +00:00
2020-05-13 19:03:16 +00:00
def Cancel( self ):
2017-07-05 21:09:28 +00:00
2020-05-13 19:03:16 +00:00
if self._network_job is not None:
self._network_job.Cancel( 'Cancelled by user.' )
2017-07-05 21:09:28 +00:00
2020-05-13 19:03:16 +00:00
def ClearNetworkJob( self ):
2017-07-12 20:03:45 +00:00
2020-05-13 19:03:16 +00:00
self.SetNetworkJob( None )
2017-08-16 21:58:06 +00:00
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
def FlipAutoOverrideBandwidth( self ):
2017-07-12 20:03:45 +00:00
2020-05-13 19:03:16 +00:00
self._auto_override_bandwidth_rules = not self._auto_override_bandwidth_rules
2017-07-05 21:09:28 +00:00
2020-05-13 19:03:16 +00:00
def SetNetworkJob( self, network_job ):
2017-07-05 21:09:28 +00:00
2020-05-13 19:03:16 +00:00
if network_job is None:
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
if self._network_job is not None:
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
self._network_job = None
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
self._Update()
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
HG.client_controller.gui.UnregisterUIUpdateWindow( self )
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
else:
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
if self._network_job != network_job:
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
self._network_job = network_job
self._download_started = False
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
HG.client_controller.gui.RegisterUIUpdateWindow( self )
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
def TIMERUIUpdate( self ):
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
self._OverrideBandwidthIfAppropriate()
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
if HG.client_controller.gui.IShouldRegularlyUpdate( self ):
2018-10-17 21:00:09 +00:00
2020-05-13 19:03:16 +00:00
self._Update()
2018-10-17 21:00:09 +00:00
2018-02-07 23:40:33 +00:00
2019-11-14 03:56:30 +00:00
class TextAndPasteCtrl( QW.QWidget ):
2018-05-16 20:09:50 +00:00
2018-08-08 20:29:54 +00:00
def __init__( self, parent, add_callable, allow_empty_input = False ):
2018-05-16 20:09:50 +00:00
self._add_callable = add_callable
2018-08-08 20:29:54 +00:00
self._allow_empty_input = allow_empty_input
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
QW.QWidget.__init__( self, parent )
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
self._text_input = QW.QLineEdit( self )
self._text_input.installEventFilter( ClientGUICommon.TextCatchEnterEventFilter( self._text_input, self.EnterText ) )
2018-05-16 20:09:50 +00:00
2020-03-11 21:52:11 +00:00
self._paste_button = ClientGUICommon.BetterBitmapButton( self, CC.global_pixmaps().paste, self._Paste )
2019-11-14 03:56:30 +00:00
self._paste_button.setToolTip( 'Paste multiple inputs from the clipboard. Assumes the texts are newline-separated.' )
2018-05-16 20:09:50 +00:00
self.setFocusProxy( self._text_input )
2018-05-16 20:09:50 +00:00
#
2019-11-14 03:56:30 +00:00
hbox = QP.HBoxLayout()
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( hbox, self._text_input, CC.FLAGS_EXPAND_BOTH_WAYS )
QP.AddToLayout( hbox, self._paste_button, CC.FLAGS_VCENTER )
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
self.setLayout( hbox )
2018-05-16 20:09:50 +00:00
def _Paste( self ):
2019-06-19 22:08:48 +00:00
try:
raw_text = HG.client_controller.GetClipboardText()
except HydrusExceptions.DataMissing as e:
2019-11-14 03:56:30 +00:00
QW.QMessageBox.critical( self, 'Error', str(e) )
2019-06-19 22:08:48 +00:00
return
2018-05-16 20:09:50 +00:00
try:
2018-08-08 20:29:54 +00:00
texts = [ text for text in HydrusText.DeserialiseNewlinedTexts( raw_text ) ]
if not self._allow_empty_input:
texts = [ text for text in texts if text != '' ]
2018-05-16 20:09:50 +00:00
if len( texts ) > 0:
self._add_callable( texts )
except:
2019-11-14 03:56:30 +00:00
QW.QMessageBox.critical( self, 'Error', 'I could not understand what was in the clipboard' )
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
def EnterText( self ):
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
text = self._text_input.text()
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
text = HydrusText.StripIOInputLine( text )
if text == '' and not self._allow_empty_input:
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
return
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
self._add_callable( ( text, ) )
self._text_input.setText( '' )
2018-05-16 20:09:50 +00:00
def GetValue( self ):
2019-11-14 03:56:30 +00:00
return self._text_input.text()
def setPlaceholderText( self, text ):
self._text_input.setPlaceholderText( text )
2018-05-16 20:09:50 +00:00
def SetValue( self, text ):
2019-11-14 03:56:30 +00:00
self._text_input.setText( text )
2018-05-16 20:09:50 +00:00