hydrus/hydrus/client/gui/search/ClientGUIPredicatesMultiple.py

598 lines
18 KiB
Python

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 HydrusGlobals as HG
from hydrus.client import ClientConstants as CC
from hydrus.client import ClientGlobals as CG
from hydrus.client.gui import ClientGUIFunctions
from hydrus.client.gui import ClientGUIRatings
from hydrus.client.gui import QtPorting as QP
from hydrus.client.gui.search import ClientGUIPredicatesSingle
from hydrus.client.gui.widgets import ClientGUICommon
from hydrus.client.metadata import ClientRatings
from hydrus.client.search import ClientSearch
class PredicateSystemRatingIncDecControl( QW.QWidget ):
def __init__( self, parent: QW.QWidget, service_key: bytes, predicate: typing.Optional[ ClientSearch.Predicate ] ):
QW.QWidget.__init__( self, parent )
self._service_key = service_key
service = CG.client_controller.services_manager.GetService( self._service_key )
name = service.GetName()
name_st = ClientGUICommon.BetterStaticText( self, name )
name_st.setAlignment( QC.Qt.AlignLeft | QC.Qt.AlignVCenter )
choices = [
( 'more than', '>' ),
( 'less than', '<' ),
( 'is', '=' ),
( 'is about', HC.UNICODE_APPROX_EQUAL ),
( 'do not search', '' )
]
self._choice = QP.DataRadioBox( self, choices, vertical = True )
self._rating_value = ClientGUICommon.BetterSpinBox( self, initial = 0, min = 0, max = 1000000 )
self._choice.SetValue( '' )
#
if predicate is not None:
value = predicate.GetValue()
if value is not None:
( operator, rating, service_key ) = value
self._choice.SetValue( operator )
self._rating_value.setValue( rating )
#
hbox = QP.HBoxLayout()
QP.AddToLayout( hbox, name_st, CC.FLAGS_EXPAND_BOTH_WAYS )
QP.AddToLayout( hbox, self._choice, CC.FLAGS_CENTER_PERPENDICULAR )
QP.AddToLayout( hbox, self._rating_value, CC.FLAGS_CENTER_PERPENDICULAR )
self.setLayout( hbox )
self._choice.radioBoxChanged.connect( self._UpdateControls )
self._UpdateControls()
def _UpdateControls( self ):
choice = self._choice.GetValue()
spinctrl_matters = choice != ''
self._rating_value.setEnabled( spinctrl_matters )
def GetPredicates( self ):
choice = self._choice.GetValue()
if choice == '':
return []
operator = choice
rating = self._rating_value.value()
predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_RATING, ( operator, rating, self._service_key ) )
return [ predicate ]
class PredicateSystemRatingLikeControl( QW.QWidget ):
def __init__( self, parent: QW.QWidget, service_key: bytes, predicate: typing.Optional[ ClientSearch.Predicate ] ):
QW.QWidget.__init__( self, parent )
self.setToolTip( ClientGUIFunctions.WrapToolTip( 'Set "is" and leave rating null to search for "unrated".' ) )
self._service_key = service_key
service = CG.client_controller.services_manager.GetService( self._service_key )
name = service.GetName()
name_st = ClientGUICommon.BetterStaticText( self, name )
name_st.setAlignment( QC.Qt.AlignLeft | QC.Qt.AlignVCenter )
choices = [
( 'has rating', 'rated' ),
( 'is', '=' ),
( 'do not search', '' )
]
self._choice = QP.DataRadioBox( self, choices, vertical = True )
self._rating_control = ClientGUIRatings.RatingLikeDialog( self, service_key )
#
self._choice.SetValue( '' )
if predicate is not None:
value = predicate.GetValue()
if value is not None:
( operator, rating, service_key ) = value
if rating == 'rated':
self._choice.SetValue( 'rated' )
else:
self._choice.SetValue( '=' )
if rating == 'not rated':
self._rating_control.SetRatingState( ClientRatings.NULL )
elif rating == 0:
self._rating_control.SetRatingState( ClientRatings.DISLIKE )
else:
self._rating_control.SetRatingState( ClientRatings.LIKE )
#
hbox = QP.HBoxLayout()
QP.AddToLayout( hbox, name_st, CC.FLAGS_EXPAND_BOTH_WAYS )
QP.AddToLayout( hbox, self._choice, CC.FLAGS_CENTER_PERPENDICULAR )
QP.AddToLayout( hbox, self._rating_control, CC.FLAGS_CENTER_PERPENDICULAR )
self.setLayout( hbox )
self._choice.radioBoxChanged.connect( self._UpdateControls )
self._rating_control.valueChanged.connect( self._RatingChanged )
self._UpdateControls()
def _RatingChanged( self ):
if self._choice.GetValue() in ( 'rated', '' ):
self._choice.SetValue( '=' )
def _UpdateControls( self ):
choice = self._choice.GetValue()
if choice in ( 'rated', '' ):
self._rating_control.blockSignals( True )
self._rating_control.SetRatingState( ClientRatings.NULL )
self._rating_control.blockSignals( False )
def GetPredicates( self ):
choice = self._choice.GetValue()
if choice == '':
return []
if choice == 'rated':
rating = 'rated'
else:
rating_state = self._rating_control.GetRatingState()
if rating_state == ClientRatings.LIKE:
rating = 1
elif rating_state == ClientRatings.DISLIKE:
rating = 0
else:
rating = 'not rated'
predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_RATING, ( '=', rating, self._service_key ) )
return [ predicate ]
class PredicateSystemRatingNumericalControl( QW.QWidget ):
def __init__( self, parent: QW.QWidget, service_key: bytes, predicate: typing.Optional[ ClientSearch.Predicate ] ):
QW.QWidget.__init__( self, parent )
self.setToolTip( ClientGUIFunctions.WrapToolTip( 'Set "is" and leave rating null to search for "unrated".' ) )
self._service_key = service_key
service = CG.client_controller.services_manager.GetService( self._service_key )
name = service.GetName()
name_st = ClientGUICommon.BetterStaticText( self, name )
name_st.setAlignment( QC.Qt.AlignLeft | QC.Qt.AlignVCenter )
choices = [
( 'has rating', 'rated' ),
( 'more than', '>' ),
( 'less than', '<' ),
( 'is', '=' ),
( 'is about', HC.UNICODE_APPROX_EQUAL ),
( 'do not search', '' )
]
self._choice = QP.DataRadioBox( self, choices, vertical = True )
self._rating_control = ClientGUIRatings.RatingNumericalDialog( self, service_key )
self._choice.SetValue( '' )
#
if predicate is not None:
value = predicate.GetValue()
if value is not None:
( operator, rating, service_key ) = value
if rating == 'rated':
self._choice.SetValue( 'rated' )
elif rating == 'not rated':
self._choice.SetValue( '=' )
self._rating_control.SetRating( None )
else:
self._choice.SetValue( operator )
self._rating_control.SetRating( rating )
#
hbox = QP.HBoxLayout()
QP.AddToLayout( hbox, name_st, CC.FLAGS_EXPAND_BOTH_WAYS )
QP.AddToLayout( hbox, self._choice, CC.FLAGS_CENTER_PERPENDICULAR )
QP.AddToLayout( hbox, self._rating_control, CC.FLAGS_CENTER_PERPENDICULAR )
self.setLayout( hbox )
self._choice.radioBoxChanged.connect( self._UpdateControls )
self._rating_control.valueChanged.connect( self._RatingChanged )
self._UpdateControls()
def _RatingChanged( self ):
if self._choice.GetValue() in ( 'rated', '' ):
self._choice.SetValue( '=' )
def _UpdateControls( self ):
choice = self._choice.GetValue()
if choice in ( 'rated', '' ):
self._rating_control.blockSignals( True )
self._rating_control.SetRating( None )
self._rating_control.blockSignals( False )
def GetPredicates( self ):
choice = self._choice.GetValue()
if choice == '':
return []
operator = '='
rating = None
if choice == 'rated':
operator = '='
rating = 'rated'
else:
operator = choice
if self._rating_control.GetRatingState() == ClientRatings.NULL:
if operator != '=':
return []
rating = 'not rated'
else:
rating = self._rating_control.GetRating()
predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_RATING, ( operator, rating, self._service_key ) )
return [ predicate ]
class PanelPredicateSystemMultiple( ClientGUIPredicatesSingle.PanelPredicateSystem ):
def _FilterWhatICanEdit( self, predicates: typing.Collection[ ClientSearch.Predicate ] ) -> typing.Collection[ ClientSearch.Predicate ]:
raise NotImplementedError()
def _GetPredicatesToInitialisePanelWith( self, predicates: typing.Collection[ ClientSearch.Predicate ] ) -> typing.Collection[ ClientSearch.Predicate ]:
raise NotImplementedError()
def ClearCustomDefault( self ):
raise NotImplementedError()
def GetDefaultPredicates( self ) -> typing.Collection[ ClientSearch.Predicate ]:
raise NotImplementedError()
def GetPredicates( self ):
raise NotImplementedError()
def SaveCustomDefault( self ):
raise NotImplementedError()
def UsesCustomDefault( self ) -> bool:
raise NotImplementedError()
class PanelPredicateSystemRating( PanelPredicateSystemMultiple ):
def __init__( self, parent, predicates ):
PanelPredicateSystemMultiple.__init__( self, parent )
#
local_like_services = CG.client_controller.services_manager.GetServices( ( HC.LOCAL_RATING_LIKE, ) )
gridbox = QP.GridLayout( cols = 5 )
gridbox.setColumnStretch( 0, 1 )
predicates = self._GetPredicatesToInitialisePanelWith( predicates )
service_keys_to_predicates = { predicate.GetValue()[2] : predicate for predicate in predicates }
self._rating_panels = []
for service in local_like_services:
service_key = service.GetServiceKey()
if service_key in service_keys_to_predicates:
predicate = service_keys_to_predicates[ service_key ]
else:
predicate = None
panel = PredicateSystemRatingLikeControl( self, service_key, predicate )
self._rating_panels.append( panel )
#
local_numerical_services = CG.client_controller.services_manager.GetServices( ( HC.LOCAL_RATING_NUMERICAL, ) )
for service in local_numerical_services:
service_key = service.GetServiceKey()
if service_key in service_keys_to_predicates:
predicate = service_keys_to_predicates[ service_key ]
else:
predicate = None
panel = PredicateSystemRatingNumericalControl( self, service_key, predicate )
self._rating_panels.append( panel )
#
local_incdec_services = CG.client_controller.services_manager.GetServices( ( HC.LOCAL_RATING_INCDEC, ) )
for service in local_incdec_services:
service_key = service.GetServiceKey()
if service_key in service_keys_to_predicates:
predicate = service_keys_to_predicates[ service_key ]
else:
predicate = None
panel = PredicateSystemRatingIncDecControl( self, service_key, predicate )
self._rating_panels.append( panel )
#
vbox = QP.VBoxLayout()
for panel in self._rating_panels:
QP.AddToLayout( vbox, panel, CC.FLAGS_EXPAND_PERPENDICULAR )
self.setLayout( vbox )
def _FilterWhatICanEdit( self, predicates: typing.Collection[ ClientSearch.Predicate ] ) -> typing.Collection[ ClientSearch.Predicate ]:
local_rating_service_keys = CG.client_controller.services_manager.GetServiceKeys( HC.RATINGS_SERVICES )
good_predicates = []
for predicate in predicates:
value = predicate.GetValue()
if value is not None:
( operator, rating, service_key ) = value
if service_key in local_rating_service_keys:
good_predicates.append( predicate )
return good_predicates
def _GetPredicatesToInitialisePanelWith( self, predicates: typing.Collection[ ClientSearch.Predicate ] ) -> typing.Collection[ ClientSearch.Predicate ]:
predicates = self._FilterWhatICanEdit( predicates )
if len( predicates ) > 0:
return predicates
custom_default_predicates = CG.client_controller.new_options.GetCustomDefaultSystemPredicates( predicate_type = ClientSearch.PREDICATE_TYPE_SYSTEM_RATING )
custom_default_predicates = self._FilterWhatICanEdit( custom_default_predicates )
if len( custom_default_predicates ) > 0:
return custom_default_predicates
default_predicates = self.GetDefaultPredicates()
return default_predicates
def ClearCustomDefault( self ):
CG.client_controller.new_options.ClearCustomDefaultSystemPredicates( predicate_type = ClientSearch.PREDICATE_TYPE_SYSTEM_RATING )
def GetDefaultPredicates( self ):
return []
def GetPredicates( self ):
predicates = []
for panel in self._rating_panels:
predicates.extend( panel.GetPredicates() )
return predicates
def SaveCustomDefault( self ):
predicates = self.GetPredicates()
CG.client_controller.new_options.SetCustomDefaultSystemPredicates( predicate_type = ClientSearch.PREDICATE_TYPE_SYSTEM_RATING, predicates = predicates )
def UsesCustomDefault( self ) -> bool:
custom_default_predicates = CG.client_controller.new_options.GetCustomDefaultSystemPredicates( predicate_type = ClientSearch.PREDICATE_TYPE_SYSTEM_RATING )
custom_default_predicates = self._FilterWhatICanEdit( custom_default_predicates )
return len( custom_default_predicates ) > 0