hydrus/hydrus/client/gui/ClientGUIStringControls.py

680 lines
21 KiB
Python
Raw Normal View History

2020-05-20 21:36:02 +00:00
import os
2020-05-13 19:03:16 +00:00
import typing
from qtpy import QtCore as QC
from qtpy import QtWidgets as QW
2020-07-29 20:52:44 +00:00
from hydrus.core import HydrusText
2020-05-13 19:03:16 +00:00
from hydrus.client import ClientConstants as CC
from hydrus.client import ClientParsing
from hydrus.client.gui import ClientGUICommon
from hydrus.client.gui import ClientGUIDialogs
from hydrus.client.gui import ClientGUIScrolledPanels
from hydrus.client.gui import ClientGUIStringPanels
from hydrus.client.gui import ClientGUITopLevelWindowsPanels
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
2020-05-13 19:03:16 +00:00
class StringConverterButton( ClientGUICommon.BetterButton ):
2020-05-20 21:36:02 +00:00
valueChanged = QC.Signal()
2020-05-13 19:03:16 +00:00
def __init__( self, parent, string_converter: ClientParsing.StringConverter ):
ClientGUICommon.BetterButton.__init__( self, parent, 'edit string converter', self._Edit )
self._string_converter = string_converter
self._example_string_override = None
self._UpdateLabel()
def _Edit( self ):
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit string converter', frame_key = 'deeply_nested_dialog' ) as dlg:
panel = ClientGUIStringPanels.EditStringConverterPanel( dlg, self._string_converter, example_string_override = self._example_string_override )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
self._string_converter = panel.GetValue()
self._UpdateLabel()
2020-05-20 21:36:02 +00:00
self.valueChanged.emit()
2020-05-13 19:03:16 +00:00
def _UpdateLabel( self ):
label = self._string_converter.ToString()
2020-05-20 21:36:02 +00:00
self.setToolTip( label )
elided_label = HydrusText.ElideText( label, 64 )
self.setText( elided_label )
2020-05-13 19:03:16 +00:00
2020-05-20 21:36:02 +00:00
def GetValue( self ) -> ClientParsing.StringConverter:
2020-05-13 19:03:16 +00:00
return self._string_converter
2020-05-20 21:36:02 +00:00
def SetExampleString( self, example_string: str ):
2020-05-13 19:03:16 +00:00
self._example_string_override = example_string
2020-05-20 21:36:02 +00:00
def SetValue( self, string_converter: ClientParsing.StringConverter ):
2020-05-13 19:03:16 +00:00
self._string_converter = string_converter
self._UpdateLabel()
2020-05-20 21:36:02 +00:00
self.valueChanged.emit()
2020-05-13 19:03:16 +00:00
class StringMatchButton( ClientGUICommon.BetterButton ):
2020-05-20 21:36:02 +00:00
valueChanged = QC.Signal()
2020-05-13 19:03:16 +00:00
def __init__( self, parent, string_match: ClientParsing.StringMatch ):
ClientGUICommon.BetterButton.__init__( self, parent, 'edit string match', self._Edit )
self._string_match = string_match
self._UpdateLabel()
def _Edit( self ):
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit string match', frame_key = 'deeply_nested_dialog' ) as dlg:
panel = ClientGUIStringPanels.EditStringMatchPanel( dlg, self._string_match )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
self._string_match = panel.GetValue()
self._UpdateLabel()
def _UpdateLabel( self ):
label = self._string_match.ToString()
self.setText( label )
2020-05-20 21:36:02 +00:00
def GetValue( self ) -> ClientParsing.StringMatch:
2020-05-13 19:03:16 +00:00
return self._string_match
2020-05-20 21:36:02 +00:00
def SetValue( self, string_match: ClientParsing.StringMatch ):
2020-05-13 19:03:16 +00:00
self._string_match = string_match
self._UpdateLabel()
2020-05-20 21:36:02 +00:00
class StringProcessorButton( ClientGUICommon.BetterButton ):
def __init__( self, parent, string_processor: ClientParsing.StringProcessor, test_data_callable: typing.Callable[ [], ClientParsing.ParsingTestData ] ):
ClientGUICommon.BetterButton.__init__( self, parent, 'edit string processor', self._Edit )
self._string_processor = string_processor
self._test_data_callable = test_data_callable
self._UpdateLabel()
def _Edit( self ):
test_data = self._test_data_callable()
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit string processor', frame_key = 'deeply_nested_dialog' ) as dlg:
panel = ClientGUIStringPanels.EditStringProcessorPanel( dlg, self._string_processor, test_data )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
self._string_processor = panel.GetValue()
self._UpdateLabel()
def _UpdateLabel( self ):
statements = self._string_processor.GetProcessingStrings()
if len( statements ) == 0:
label = self._string_processor.ToString()
else:
statements = [ HydrusText.ElideText( statement, 64 ) for statement in statements ]
label = os.linesep.join( statements )
self.setText( label )
def GetValue( self ) -> ClientParsing.StringProcessor:
return self._string_processor
def SetValue( self, string_processor: ClientParsing.StringProcessor ):
self._string_processor = string_processor
self._UpdateLabel()
2020-05-13 19:03:16 +00:00
class StringMatchToStringMatchDictControl( QW.QWidget ):
def __init__( self, parent, initial_dict: typing.Dict[ ClientParsing.StringMatch, ClientParsing.StringMatch ], min_height = 10, key_name = 'key' ):
QW.QWidget.__init__( self, parent )
self._key_name = key_name
listctrl_panel = ClientGUIListCtrl.BetterListCtrlPanel( self )
2020-07-15 20:52:09 +00:00
column_types_to_name_overrides = { CGLC.COLUMN_LIST_KEY_TO_STRING_MATCH.KEY : self._key_name }
2020-05-13 19:03:16 +00:00
2020-07-15 20:52:09 +00:00
self._listctrl = ClientGUIListCtrl.BetterListCtrl( listctrl_panel, CGLC.COLUMN_LIST_KEY_TO_STRING_MATCH.ID, min_height, self._ConvertDataToListCtrlTuples, use_simple_delete = True, activation_callback = self._Edit, column_types_to_name_overrides = column_types_to_name_overrides )
2020-05-13 19:03:16 +00:00
listctrl_panel.SetListCtrl( self._listctrl )
listctrl_panel.AddButton( 'add', self._Add )
listctrl_panel.AddButton( 'edit', self._Edit, enabled_only_on_selection = True )
listctrl_panel.AddDeleteButton()
#
self._listctrl.AddDatas( list(initial_dict.items()) )
2020-07-15 20:52:09 +00:00
self._listctrl.Sort()
2020-05-13 19:03:16 +00:00
#
vbox = QP.VBoxLayout()
QP.AddToLayout( vbox, listctrl_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
self.setLayout( vbox )
def _ConvertDataToListCtrlTuples( self, data ):
( key_string_match, value_string_match ) = data
pretty_key = key_string_match.ToString()
pretty_value = value_string_match.ToString()
display_tuple = ( pretty_key, pretty_value )
sort_tuple = ( pretty_key, pretty_value )
return ( display_tuple, sort_tuple )
def _Add( self ):
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit ' + self._key_name ) as dlg:
string_match = ClientParsing.StringMatch()
panel = ClientGUIStringPanels.EditStringMatchPanel( dlg, string_match )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
key_string_match = panel.GetValue()
else:
return
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit match' ) as dlg:
string_match = ClientParsing.StringMatch()
panel = ClientGUIStringPanels.EditStringMatchPanel( dlg, string_match )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
value_string_match = panel.GetValue()
data = ( key_string_match, value_string_match )
self._listctrl.AddDatas( ( data, ) )
def _Edit( self ):
for data in self._listctrl.GetData( only_selected = True ):
( key_string_match, value_string_match ) = data
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit ' + self._key_name ) as dlg:
panel = ClientGUIStringPanels.EditStringMatchPanel( dlg, key_string_match )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
key_string_match = panel.GetValue()
else:
break
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit match' ) as dlg:
panel = ClientGUIStringPanels.EditStringMatchPanel( dlg, value_string_match )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
value_string_match = panel.GetValue()
else:
break
self._listctrl.DeleteDatas( ( data, ) )
edited_data = ( key_string_match, value_string_match )
self._listctrl.AddDatas( ( edited_data, ) )
self._listctrl.Sort()
def GetValue( self ) -> typing.Dict[ str, ClientParsing.StringMatch ]:
value_dict = dict( self._listctrl.GetData() )
return value_dict
class StringToStringDictButton( ClientGUICommon.BetterButton ):
def __init__( self, parent, label ):
ClientGUICommon.BetterButton.__init__( self, parent, label, self._Edit )
2020-06-17 21:31:54 +00:00
self._value = {}
2020-05-13 19:03:16 +00:00
def _Edit( self ):
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit string dictionary' ) as dlg:
panel = ClientGUIScrolledPanels.EditSingleCtrlPanel( dlg )
control = StringToStringDictControl( panel, self._value )
panel.SetControl( control )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
self._value = control.GetValue()
def GetValue( self ) -> typing.Dict[ str, str ]:
return self._value
def SetValue( self, value ):
self._value = value
class StringToStringDictControl( QW.QWidget ):
2020-07-15 20:52:09 +00:00
columnListContentsChanged = QC.Signal()
2020-05-13 19:03:16 +00:00
def __init__( self, parent, initial_dict: typing.Dict[ str, str ], min_height = 10, key_name = 'key', value_name = 'value', allow_add_delete = True, edit_keys = True ):
QW.QWidget.__init__( self, parent )
self._key_name = key_name
self._value_name = value_name
self._edit_keys = edit_keys
listctrl_panel = ClientGUIListCtrl.BetterListCtrlPanel( self )
use_simple_delete = allow_add_delete
2020-07-15 20:52:09 +00:00
column_types_to_name_overrides = { CGLC.COLUMN_LIST_KEY_TO_VALUE.KEY : self._key_name }
self._listctrl = ClientGUIListCtrl.BetterListCtrl( listctrl_panel, CGLC.COLUMN_LIST_KEY_TO_VALUE.ID, min_height, self._ConvertDataToListCtrlTuples, use_simple_delete = use_simple_delete, activation_callback = self._Edit, column_types_to_name_overrides = column_types_to_name_overrides )
self._listctrl.columnListContentsChanged.connect( self.columnListContentsChanged )
2020-05-13 19:03:16 +00:00
listctrl_panel.SetListCtrl( self._listctrl )
if allow_add_delete:
listctrl_panel.AddButton( 'add', self._Add )
listctrl_panel.AddButton( 'edit', self._Edit, enabled_only_on_selection = True )
if allow_add_delete:
listctrl_panel.AddDeleteButton()
#
self._listctrl.AddDatas( list(initial_dict.items()) )
2020-07-15 20:52:09 +00:00
self._listctrl.Sort()
2020-05-13 19:03:16 +00:00
#
vbox = QP.VBoxLayout()
QP.AddToLayout( vbox, listctrl_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
self.setLayout( vbox )
def _ConvertDataToListCtrlTuples( self, data ):
( key, value ) = data
display_tuple = ( key, value )
sort_tuple = ( key, value )
return ( display_tuple, sort_tuple )
def _Add( self ):
with ClientGUIDialogs.DialogTextEntry( self, 'enter the ' + self._key_name, allow_blank = False ) as dlg:
if dlg.exec() == QW.QDialog.Accepted:
key = dlg.GetValue()
if key in self._GetExistingKeys():
QW.QMessageBox.warning( self, 'Warning', 'That {} already exists!'.format( self._key_name ) )
return
with ClientGUIDialogs.DialogTextEntry( self, 'enter the ' + self._value_name, allow_blank = True ) as dlg:
if dlg.exec() == QW.QDialog.Accepted:
value = dlg.GetValue()
data = ( key, value )
self._listctrl.AddDatas( ( data, ) )
def _Edit( self ):
for data in self._listctrl.GetData( only_selected = True ):
( key, value ) = data
if self._edit_keys:
with ClientGUIDialogs.DialogTextEntry( self, 'edit the ' + self._key_name, default = key, allow_blank = False ) as dlg:
if dlg.exec() == QW.QDialog.Accepted:
edited_key = dlg.GetValue()
if edited_key != key and edited_key in self._GetExistingKeys():
QW.QMessageBox.warning( self, 'Warning', 'That {} already exists!'.format( self._key_name ) )
break
else:
break
else:
edited_key = key
with ClientGUIDialogs.DialogTextEntry( self, 'edit the ' + self._value_name, default = value, allow_blank = True ) as dlg:
if dlg.exec() == QW.QDialog.Accepted:
edited_value = dlg.GetValue()
else:
break
self._listctrl.DeleteDatas( ( data, ) )
edited_data = ( edited_key, edited_value )
self._listctrl.AddDatas( ( edited_data, ) )
self._listctrl.Sort()
def _GetExistingKeys( self ):
return { key for ( key, value ) in self._listctrl.GetData() }
def GetValue( self ) -> typing.Dict[ str, str ]:
value_dict = dict( self._listctrl.GetData() )
return value_dict
class StringToStringMatchDictControl( QW.QWidget ):
def __init__( self, parent, initial_dict: typing.Dict[ str, ClientParsing.StringMatch ], min_height = 10, key_name = 'key' ):
QW.QWidget.__init__( self, parent )
self._key_name = key_name
listctrl_panel = ClientGUIListCtrl.BetterListCtrlPanel( self )
2020-07-15 20:52:09 +00:00
column_types_to_name_overrides = { CGLC.COLUMN_LIST_KEY_TO_STRING_MATCH.KEY : self._key_name }
2020-05-13 19:03:16 +00:00
2020-07-15 20:52:09 +00:00
self._listctrl = ClientGUIListCtrl.BetterListCtrl( listctrl_panel, CGLC.COLUMN_LIST_KEY_TO_STRING_MATCH.ID, min_height, self._ConvertDataToListCtrlTuples, use_simple_delete = True, activation_callback = self._Edit, column_types_to_name_overrides = column_types_to_name_overrides )
2020-05-13 19:03:16 +00:00
listctrl_panel.SetListCtrl( self._listctrl )
listctrl_panel.AddButton( 'add', self._Add )
listctrl_panel.AddButton( 'edit', self._Edit, enabled_only_on_selection = True )
listctrl_panel.AddDeleteButton()
#
self._listctrl.AddDatas( initial_dict.items() )
2020-07-15 20:52:09 +00:00
self._listctrl.Sort()
2020-05-13 19:03:16 +00:00
#
vbox = QP.VBoxLayout()
QP.AddToLayout( vbox, listctrl_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
self.setLayout( vbox )
def _ConvertDataToListCtrlTuples( self, data ):
( key, string_match ) = data
pretty_string_match = string_match.ToString()
display_tuple = ( key, pretty_string_match )
sort_tuple = ( key, pretty_string_match )
return ( display_tuple, sort_tuple )
def _Add( self ):
with ClientGUIDialogs.DialogTextEntry( self, 'enter the ' + self._key_name, allow_blank = False ) as dlg:
if dlg.exec() == QW.QDialog.Accepted:
key = dlg.GetValue()
if key in self._GetExistingKeys():
QW.QMessageBox.warning( self, 'Warning', 'That {} already exists!'.format( self._key_name ) )
return
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit match' ) as dlg:
string_match = ClientParsing.StringMatch()
panel = ClientGUIStringPanels.EditStringMatchPanel( dlg, string_match )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
string_match = panel.GetValue()
data = ( key, string_match )
self._listctrl.AddDatas( ( data, ) )
def _Edit( self ):
for data in self._listctrl.GetData( only_selected = True ):
( key, string_match ) = data
with ClientGUIDialogs.DialogTextEntry( self, 'edit the ' + self._key_name, default = key, allow_blank = False ) as dlg:
if dlg.exec() == QW.QDialog.Accepted:
edited_key = dlg.GetValue()
if edited_key != key and edited_key in self._GetExistingKeys():
QW.QMessageBox.warning( self, 'Warning', 'That {} already exists!'.format( self._key_name ) )
break
else:
break
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit match' ) as dlg:
string_match = ClientParsing.StringMatch()
panel = ClientGUIStringPanels.EditStringMatchPanel( dlg, string_match )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
edited_string_match = panel.GetValue()
else:
break
self._listctrl.DeleteDatas( ( data, ) )
edited_data = ( edited_key, edited_string_match )
self._listctrl.AddDatas( ( edited_data, ) )
self._listctrl.Sort()
def _GetExistingKeys( self ):
return { key for ( key, value ) in self._listctrl.GetData() }
def GetValue( self ) -> typing.Dict[ str, ClientParsing.StringMatch ]:
value_dict = dict( self._listctrl.GetData() )
return value_dict