482 lines
13 KiB
Python
482 lines
13 KiB
Python
from qtpy import QtCore as QC
|
|
from qtpy import QtGui as QG
|
|
from qtpy import QtWidgets as QW
|
|
|
|
from hydrus.core import HydrusExceptions
|
|
from hydrus.core import HydrusGlobals as HG
|
|
|
|
from hydrus.client.gui import QtPorting as QP
|
|
from hydrus.client.metadata import ClientRatings
|
|
|
|
default_like_colours = {}
|
|
|
|
default_like_colours[ ClientRatings.LIKE ] = ( ( 0, 0, 0 ), ( 80, 200, 120 ) )
|
|
default_like_colours[ ClientRatings.DISLIKE ] = ( ( 0, 0, 0 ), ( 200, 80, 120 ) )
|
|
default_like_colours[ ClientRatings.NULL ] = ( ( 0, 0, 0 ), ( 191, 191, 191 ) )
|
|
default_like_colours[ ClientRatings.MIXED ] = ( ( 0, 0, 0 ), ( 95, 95, 95 ) )
|
|
|
|
default_numerical_colours = {}
|
|
|
|
default_numerical_colours[ ClientRatings.LIKE ] = ( ( 0, 0, 0 ), ( 80, 200, 120 ) )
|
|
default_numerical_colours[ ClientRatings.DISLIKE ] = ( ( 0, 0, 0 ), ( 255, 255, 255 ) )
|
|
default_numerical_colours[ ClientRatings.NULL ] = ( ( 0, 0, 0 ), ( 191, 191, 191 ) )
|
|
default_numerical_colours[ ClientRatings.MIXED ] = ( ( 0, 0, 0 ), ( 95, 95, 95 ) )
|
|
|
|
STAR_COORDS = []
|
|
|
|
STAR_COORDS.append( QC.QPoint( 6, 0 ) ) # top
|
|
STAR_COORDS.append( QC.QPoint( 9, 4 ) )
|
|
STAR_COORDS.append( QC.QPoint( 12, 4 ) ) # right
|
|
STAR_COORDS.append( QC.QPoint( 9, 8 ) )
|
|
STAR_COORDS.append( QC.QPoint( 10, 12 ) ) # bottom right
|
|
STAR_COORDS.append( QC.QPoint( 6, 10 ) )
|
|
STAR_COORDS.append( QC.QPoint( 2, 12 ) ) # bottom left
|
|
STAR_COORDS.append( QC.QPoint( 3, 8 ) )
|
|
STAR_COORDS.append( QC.QPoint( 0, 4 ) ) # left
|
|
STAR_COORDS.append( QC.QPoint( 3, 4 ) )
|
|
|
|
def DrawLike( painter, x, y, service_key, rating_state ):
|
|
|
|
shape = ClientRatings.GetShape( service_key )
|
|
|
|
( pen_colour, brush_colour ) = GetPenAndBrushColours( service_key, rating_state )
|
|
|
|
painter.setPen( QG.QPen( pen_colour ) )
|
|
painter.setBrush( QG.QBrush( brush_colour ) )
|
|
|
|
if shape == ClientRatings.CIRCLE:
|
|
|
|
painter.drawEllipse( QC.QPointF( x+7, y+7 ), 6, 6 )
|
|
|
|
elif shape == ClientRatings.SQUARE:
|
|
|
|
painter.drawRect( x+2, y+2, 12, 12 )
|
|
|
|
elif shape == ClientRatings.STAR:
|
|
|
|
offset = QC.QPoint( x + 1, y + 1 )
|
|
|
|
painter.translate( offset )
|
|
|
|
painter.drawPolygon( QG.QPolygonF( STAR_COORDS ) )
|
|
|
|
painter.translate( -offset )
|
|
|
|
|
|
def DrawNumerical( painter, x, y, service_key, rating_state, rating ):
|
|
|
|
( shape, stars ) = GetStars( service_key, rating_state, rating )
|
|
|
|
x_delta = 0
|
|
x_step = 12
|
|
|
|
for ( num_stars, pen_colour, brush_colour ) in stars:
|
|
|
|
painter.setPen( QG.QPen( pen_colour ) )
|
|
painter.setBrush( QG.QBrush( brush_colour ) )
|
|
|
|
for i in range( num_stars ):
|
|
|
|
if shape == ClientRatings.CIRCLE:
|
|
|
|
painter.drawEllipse( QC.QPointF( x + 7 + x_delta, y + 7 ), 6, 6 )
|
|
|
|
elif shape == ClientRatings.SQUARE:
|
|
|
|
painter.drawRect( x + 2 + x_delta, y + 2, 12, 12 )
|
|
|
|
elif shape == ClientRatings.STAR:
|
|
|
|
offset = QC.QPoint( x + 1 + x_delta, y + 1 )
|
|
|
|
painter.translate( offset )
|
|
|
|
painter.drawPolygon( QG.QPolygonF( STAR_COORDS ) )
|
|
|
|
painter.translate( -offset )
|
|
|
|
|
|
x_delta += x_step
|
|
|
|
|
|
|
|
def GetNumericalWidth( service_key ):
|
|
|
|
try:
|
|
|
|
service = HG.client_controller.services_manager.GetService( service_key )
|
|
|
|
num_stars = service.GetNumStars()
|
|
|
|
except HydrusExceptions.DataMissing:
|
|
|
|
num_stars = 1
|
|
|
|
|
|
return 4 + 12 * num_stars
|
|
|
|
def GetPenAndBrushColours( service_key, rating_state ):
|
|
|
|
try:
|
|
|
|
service = HG.client_controller.services_manager.GetService( service_key )
|
|
|
|
colour = service.GetColour( rating_state )
|
|
|
|
except HydrusExceptions.DataMissing:
|
|
|
|
colour = ( ( 0, 0, 0 ), ( 0, 0, 0 ) )
|
|
|
|
|
|
( pen_rgb, brush_rgb ) = colour
|
|
|
|
pen_colour = QG.QColor( *pen_rgb )
|
|
brush_colour = QG.QColor( *brush_rgb )
|
|
|
|
return ( pen_colour, brush_colour )
|
|
|
|
def GetStars( service_key, rating_state, rating ):
|
|
|
|
try:
|
|
|
|
service = HG.client_controller.services_manager.GetService( service_key )
|
|
|
|
except HydrusExceptions.DataMissing:
|
|
|
|
return ( ClientRatings.STAR, 0 )
|
|
|
|
|
|
shape = service.GetShape()
|
|
|
|
num_stars = service.GetNumStars()
|
|
|
|
stars = []
|
|
|
|
if rating_state in ( ClientRatings.NULL, ClientRatings.MIXED ):
|
|
|
|
( pen_colour, brush_colour ) = GetPenAndBrushColours( service_key, rating_state )
|
|
|
|
stars.append( ( num_stars, pen_colour, brush_colour ) )
|
|
|
|
else:
|
|
|
|
num_stars_on = service.ConvertRatingToStars( rating )
|
|
|
|
num_stars_off = num_stars - num_stars_on
|
|
|
|
( pen_colour, brush_colour ) = GetPenAndBrushColours( service_key, ClientRatings.LIKE )
|
|
|
|
stars.append( ( num_stars_on, pen_colour, brush_colour ) )
|
|
|
|
( pen_colour, brush_colour ) = GetPenAndBrushColours( service_key, ClientRatings.DISLIKE )
|
|
|
|
stars.append( ( num_stars_off, pen_colour, brush_colour ) )
|
|
|
|
|
|
return ( shape, stars )
|
|
|
|
|
|
class RatingLike( QW.QWidget ):
|
|
|
|
def __init__( self, parent, service_key ):
|
|
|
|
QW.QWidget.__init__( self, parent )
|
|
|
|
self._service_key = service_key
|
|
|
|
self._widget_event_filter = QP.WidgetEventFilter( self )
|
|
|
|
self._widget_event_filter.EVT_LEFT_DOWN( self.EventLeftDown )
|
|
self._widget_event_filter.EVT_LEFT_DCLICK( self.EventLeftDown )
|
|
self._widget_event_filter.EVT_RIGHT_DOWN( self.EventRightDown )
|
|
self._widget_event_filter.EVT_RIGHT_DCLICK( self.EventRightDown )
|
|
|
|
self.setMinimumSize( QC.QSize( 16, 16 ) )
|
|
|
|
self._dirty = True
|
|
|
|
|
|
def _Draw( self, painter ):
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
def EventLeftDown( self, event ):
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
def paintEvent( self, event ):
|
|
|
|
painter = QG.QPainter( self )
|
|
|
|
self._Draw( painter )
|
|
|
|
|
|
def EventRightDown( self, event ):
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
def GetServiceKey( self ):
|
|
|
|
return self._service_key
|
|
|
|
|
|
class RatingLikeDialog( RatingLike ):
|
|
|
|
def __init__( self, parent, service_key ):
|
|
|
|
RatingLike.__init__( self, parent, service_key )
|
|
|
|
self._rating_state = ClientRatings.NULL
|
|
|
|
|
|
def _Draw( self, painter ):
|
|
|
|
painter.setBackground( QG.QBrush( QP.GetBackgroundColour( self.parentWidget() ) ) )
|
|
|
|
painter.eraseRect( painter.viewport() )
|
|
|
|
( pen_colour, brush_colour ) = GetPenAndBrushColours( self._service_key, self._rating_state )
|
|
|
|
DrawLike( painter, 0, 0, self._service_key, self._rating_state )
|
|
|
|
self._dirty = False
|
|
|
|
|
|
def EventLeftDown( self, event ):
|
|
|
|
if self._rating_state == ClientRatings.LIKE: self._rating_state = ClientRatings.NULL
|
|
else: self._rating_state = ClientRatings.LIKE
|
|
|
|
self._dirty = True
|
|
|
|
self.update()
|
|
|
|
|
|
def EventRightDown( self, event ):
|
|
|
|
if self._rating_state == ClientRatings.DISLIKE: self._rating_state = ClientRatings.NULL
|
|
else: self._rating_state = ClientRatings.DISLIKE
|
|
|
|
self._dirty = True
|
|
|
|
self.update()
|
|
|
|
|
|
def GetRatingState( self ):
|
|
|
|
return self._rating_state
|
|
|
|
|
|
def SetRatingState( self, rating_state ):
|
|
|
|
self._rating_state = rating_state
|
|
|
|
self._dirty = True
|
|
|
|
self.update()
|
|
|
|
|
|
class RatingNumerical( QW.QWidget ):
|
|
|
|
def __init__( self, parent, service_key ):
|
|
|
|
QW.QWidget.__init__( self, parent )
|
|
|
|
self._service_key = service_key
|
|
|
|
self._service = HG.client_controller.services_manager.GetService( self._service_key )
|
|
|
|
self._num_stars = self._service.GetNumStars()
|
|
self._allow_zero = self._service.AllowZero()
|
|
|
|
my_width = GetNumericalWidth( self._service_key )
|
|
|
|
self._widget_event_filter = QP.WidgetEventFilter( self )
|
|
|
|
self._widget_event_filter.EVT_LEFT_DOWN( self.EventLeftDown )
|
|
self._widget_event_filter.EVT_LEFT_DCLICK( self.EventLeftDown )
|
|
self._widget_event_filter.EVT_RIGHT_DOWN( self.EventRightDown )
|
|
self._widget_event_filter.EVT_RIGHT_DCLICK( self.EventRightDown )
|
|
|
|
self.setMinimumSize( QC.QSize( my_width, 16 ) )
|
|
|
|
self._last_rating_set = None
|
|
|
|
self._dirty = True
|
|
|
|
|
|
def _ClearRating( self ):
|
|
|
|
self._last_rating_set = None
|
|
|
|
|
|
def _Draw( self, painter ):
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
def _GetRatingFromClickEvent( self, event ):
|
|
|
|
click_pos = event.pos()
|
|
|
|
x = event.pos().x()
|
|
y = event.pos().y()
|
|
|
|
BORDER = 1
|
|
|
|
my_active_size = self.size() - QC.QSize( BORDER * 2, BORDER * 2 )
|
|
|
|
adjusted_click_pos = click_pos - QC.QPoint( BORDER, BORDER )
|
|
|
|
my_active_rect = QC.QRect( QC.QPoint( 0, 0 ), my_active_size )
|
|
|
|
if my_active_rect.contains( adjusted_click_pos ):
|
|
|
|
x_adjusted = x - BORDER
|
|
|
|
proportion_filled = x_adjusted / my_active_size.width()
|
|
|
|
if self._allow_zero:
|
|
|
|
stars = round( proportion_filled * self._num_stars )
|
|
|
|
else:
|
|
|
|
stars = int( proportion_filled * self._num_stars )
|
|
|
|
if proportion_filled <= 1.0:
|
|
|
|
stars += 1
|
|
|
|
|
|
|
|
rating = self._service.ConvertStarsToRating( stars )
|
|
|
|
return rating
|
|
|
|
|
|
return None
|
|
|
|
|
|
def _SetRating( self, rating ):
|
|
|
|
self._last_rating_set = rating
|
|
|
|
|
|
def EventLeftDown( self, event ):
|
|
|
|
rating = self._GetRatingFromClickEvent( event )
|
|
|
|
self._SetRating( rating )
|
|
|
|
|
|
def EventRightDown( self, event ):
|
|
|
|
self._ClearRating()
|
|
|
|
|
|
def GetServiceKey( self ):
|
|
|
|
return self._service_key
|
|
|
|
|
|
def mouseMoveEvent( self, event ):
|
|
|
|
if event.buttons() & QC.Qt.LeftButton:
|
|
|
|
rating = self._GetRatingFromClickEvent( event )
|
|
|
|
if rating != self._last_rating_set:
|
|
|
|
self._SetRating( rating )
|
|
|
|
|
|
|
|
|
|
def paintEvent( self, event ):
|
|
|
|
painter = QG.QPainter( self )
|
|
|
|
self._Draw( painter )
|
|
|
|
|
|
class RatingNumericalDialog( RatingNumerical ):
|
|
|
|
def __init__( self, parent, service_key ):
|
|
|
|
RatingNumerical.__init__( self, parent, service_key )
|
|
|
|
self._rating_state = ClientRatings.NULL
|
|
self._rating = None
|
|
|
|
|
|
def _ClearRating( self ):
|
|
|
|
RatingNumerical._ClearRating( self )
|
|
|
|
self._rating_state = ClientRatings.NULL
|
|
|
|
self._dirty = True
|
|
|
|
self.update()
|
|
|
|
|
|
def _Draw( self, painter ):
|
|
|
|
painter.setBackground( QG.QBrush( QP.GetBackgroundColour( self.parentWidget() ) ) )
|
|
|
|
painter.eraseRect( painter.viewport() )
|
|
|
|
DrawNumerical( painter, 0, 0, self._service_key, self._rating_state, self._rating )
|
|
|
|
self._dirty = False
|
|
|
|
|
|
def _SetRating( self, rating ):
|
|
|
|
RatingNumerical._SetRating( self, rating )
|
|
|
|
if rating is None:
|
|
|
|
self._ClearRating()
|
|
|
|
else:
|
|
|
|
self._rating_state = ClientRatings.SET
|
|
|
|
self._rating = rating
|
|
|
|
self._dirty = True
|
|
|
|
self.update()
|
|
|
|
|
|
|
|
def GetRating( self ):
|
|
|
|
return self._rating
|
|
|
|
|
|
def GetRatingState( self ):
|
|
|
|
return self._rating_state
|
|
|
|
|
|
def SetRating( self, rating ):
|
|
|
|
self._SetRating( rating )
|
|
|
|
|
|
def SetRatingState( self, rating_state ):
|
|
|
|
self._rating_state = rating_state
|
|
|
|
self._dirty = True
|
|
|
|
self.update()
|
|
|
|
|