2015-06-17 20:01:41 +00:00
import os
2020-04-22 21:00:35 +00:00
2019-11-14 03:56:30 +00:00
from qtpy import QtCore as QC
from qtpy import QtWidgets as QW
from qtpy import QtGui as QG
2020-04-22 21:00:35 +00:00
from hydrus . core import HydrusConstants as HC
from hydrus . core import HydrusData
from hydrus . core import HydrusGlobals as HG
from hydrus . core import HydrusSerialisable
2020-07-29 20:52:44 +00:00
2020-07-08 22:00:33 +00:00
from hydrus . client import ClientApplicationCommand as CAC
2020-04-22 21:00:35 +00:00
from hydrus . client import ClientConstants as CC
from hydrus . client import ClientData
from hydrus . client . gui import ClientGUIDragDrop
from hydrus . client . gui import ClientGUICore as CGC
from hydrus . client . gui import ClientGUIFunctions
from hydrus . client . gui import ClientGUIMediaControls
from hydrus . client . gui import ClientGUIMenus
from hydrus . client . gui import ClientGUIMPV
2020-08-05 20:10:36 +00:00
from hydrus . client . gui import ClientGUIRatings
2020-04-22 21:00:35 +00:00
from hydrus . client . gui import ClientGUIScrolledPanelsEdit
from hydrus . client . gui import ClientGUIShortcuts
from hydrus . client . gui import ClientGUIShortcutControls
2020-04-29 21:44:12 +00:00
from hydrus . client . gui import ClientGUITopLevelWindows
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 ClientGUIListBoxes
2021-03-17 21:59:28 +00:00
from hydrus . client . gui . widgets import ClientGUICommon
from hydrus . client . gui . widgets import ClientGUIMenuButton
2020-07-29 20:52:44 +00:00
from hydrus . client . media import ClientMedia
2020-08-05 20:10:36 +00:00
from hydrus . client . metadata import ClientRatings
2015-06-17 20:01:41 +00:00
2020-08-05 20:10:36 +00:00
class RatingLikeCanvas ( ClientGUIRatings . RatingLike ) :
2020-03-25 21:15:57 +00:00
def __init__ ( self , parent , service_key , canvas_key ) :
2020-08-05 20:10:36 +00:00
ClientGUIRatings . RatingLike . __init__ ( self , parent , service_key )
2020-03-25 21:15:57 +00:00
self . _canvas_key = canvas_key
self . _current_media = None
self . _rating_state = None
service = HG . client_controller . services_manager . GetService ( service_key )
name = service . GetName ( )
self . setToolTip ( name )
HG . client_controller . sub ( self , ' ProcessContentUpdates ' , ' content_updates_gui ' )
HG . client_controller . sub ( self , ' SetDisplayMedia ' , ' canvas_new_display_media ' )
def _Draw ( self , painter ) :
painter . setBackground ( QG . QBrush ( QP . GetBackgroundColour ( self . parentWidget ( ) ) ) )
painter . eraseRect ( painter . viewport ( ) )
if self . _current_media is not None :
self . _rating_state = ClientRatings . GetLikeStateFromMedia ( ( self . _current_media , ) , self . _service_key )
2020-08-05 20:10:36 +00:00
ClientGUIRatings . DrawLike ( painter , 0 , 0 , self . _service_key , self . _rating_state )
2020-03-25 21:15:57 +00:00
self . _dirty = False
def EventLeftDown ( self , event ) :
if self . _current_media is not None :
if self . _rating_state == ClientRatings . LIKE : rating = None
else : rating = 1
content_update = HydrusData . ContentUpdate ( HC . CONTENT_TYPE_RATINGS , HC . CONTENT_UPDATE_ADD , ( rating , self . _hashes ) )
HG . client_controller . Write ( ' content_updates ' , { self . _service_key : ( content_update , ) } )
def EventRightDown ( self , event ) :
if self . _current_media is not None :
if self . _rating_state == ClientRatings . DISLIKE : rating = None
else : rating = 0
content_update = HydrusData . ContentUpdate ( HC . CONTENT_TYPE_RATINGS , HC . CONTENT_UPDATE_ADD , ( rating , self . _hashes ) )
HG . client_controller . Write ( ' content_updates ' , { self . _service_key : ( content_update , ) } )
def ProcessContentUpdates ( self , service_keys_to_content_updates ) :
if self . _current_media is not None :
2021-04-28 21:43:16 +00:00
for ( service_key , content_updates ) in service_keys_to_content_updates . items ( ) :
2020-03-25 21:15:57 +00:00
for content_update in content_updates :
( data_type , action , row ) = content_update . ToTuple ( )
if data_type == HC . CONTENT_TYPE_RATINGS :
hashes = content_update . GetHashes ( )
2020-10-28 22:20:33 +00:00
if HydrusData . SetsIntersect ( self . _hashes , hashes ) :
2020-03-25 21:15:57 +00:00
self . _dirty = True
self . update ( )
return
def SetDisplayMedia ( self , canvas_key , media ) :
if canvas_key == self . _canvas_key :
self . _current_media = media
if self . _current_media is None :
self . _hashes = set ( )
else :
self . _hashes = self . _current_media . GetHashes ( )
self . _dirty = True
self . update ( )
2020-08-05 20:10:36 +00:00
class RatingNumericalCanvas ( ClientGUIRatings . RatingNumerical ) :
2020-03-25 21:15:57 +00:00
def __init__ ( self , parent , service_key , canvas_key ) :
2020-08-05 20:10:36 +00:00
ClientGUIRatings . RatingNumerical . __init__ ( self , parent , service_key )
2020-03-25 21:15:57 +00:00
self . _canvas_key = canvas_key
self . _current_media = None
self . _rating_state = None
self . _rating = None
self . _hashes = set ( )
name = self . _service . GetName ( )
self . setToolTip ( name )
HG . client_controller . sub ( self , ' ProcessContentUpdates ' , ' content_updates_gui ' )
HG . client_controller . sub ( self , ' SetDisplayMedia ' , ' canvas_new_display_media ' )
def _ClearRating ( self ) :
2020-08-05 20:10:36 +00:00
ClientGUIRatings . RatingNumerical . _ClearRating ( self )
2020-03-25 21:15:57 +00:00
if self . _current_media is not None :
rating = None
content_update = HydrusData . ContentUpdate ( HC . CONTENT_TYPE_RATINGS , HC . CONTENT_UPDATE_ADD , ( rating , self . _hashes ) )
HG . client_controller . Write ( ' content_updates ' , { self . _service_key : ( content_update , ) } )
def _Draw ( self , painter ) :
painter . setBackground ( QG . QBrush ( QP . GetBackgroundColour ( self . parentWidget ( ) ) ) )
painter . eraseRect ( painter . viewport ( ) )
if self . _current_media is not None :
( self . _rating_state , self . _rating ) = ClientRatings . GetNumericalStateFromMedia ( ( self . _current_media , ) , self . _service_key )
2020-08-05 20:10:36 +00:00
ClientGUIRatings . DrawNumerical ( painter , 0 , 0 , self . _service_key , self . _rating_state , self . _rating )
2020-03-25 21:15:57 +00:00
self . _dirty = False
def _SetRating ( self , rating ) :
2020-08-05 20:10:36 +00:00
ClientGUIRatings . RatingNumerical . _SetRating ( self , rating )
2020-03-25 21:15:57 +00:00
if self . _current_media is not None and rating is not None :
content_update = HydrusData . ContentUpdate ( HC . CONTENT_TYPE_RATINGS , HC . CONTENT_UPDATE_ADD , ( rating , self . _hashes ) )
HG . client_controller . Write ( ' content_updates ' , { self . _service_key : ( content_update , ) } )
def ProcessContentUpdates ( self , service_keys_to_content_updates ) :
if self . _current_media is not None :
for ( service_key , content_updates ) in service_keys_to_content_updates . items ( ) :
for content_update in content_updates :
( data_type , action , row ) = content_update . ToTuple ( )
if data_type == HC . CONTENT_TYPE_RATINGS :
hashes = content_update . GetHashes ( )
2020-10-28 22:20:33 +00:00
if HydrusData . SetsIntersect ( self . _hashes , hashes ) :
2020-03-25 21:15:57 +00:00
self . _dirty = True
self . update ( )
return
def SetDisplayMedia ( self , canvas_key , media ) :
if canvas_key == self . _canvas_key :
self . _current_media = media
if self . _current_media is None :
self . _hashes = set ( )
else :
self . _hashes = self . _current_media . GetHashes ( )
self . _dirty = True
self . update ( )
class CanvasHoverFrame ( QW . QFrame ) :
2015-06-17 20:01:41 +00:00
2018-12-05 22:35:30 +00:00
def __init__ ( self , parent , my_canvas , canvas_key ) :
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
QW . QFrame . __init__ ( self , parent )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
self . setWindowFlags ( QC . Qt . FramelessWindowHint | QC . Qt . Tool )
2019-12-05 05:29:32 +00:00
2019-11-14 03:56:30 +00:00
self . setAttribute ( QC . Qt . WA_ShowWithoutActivating )
self . setAttribute ( QC . Qt . WA_DeleteOnClose )
2015-06-17 20:01:41 +00:00
2019-12-05 05:29:32 +00:00
self . setFrameStyle ( QW . QFrame . Panel | QW . QFrame . Raised )
self . setLineWidth ( 2 )
2020-08-19 22:38:20 +00:00
self . _my_parent_tlw = parent . window ( )
2018-12-05 22:35:30 +00:00
self . _my_canvas = my_canvas
2015-06-17 20:01:41 +00:00
self . _canvas_key = canvas_key
self . _current_media = None
2019-05-08 21:06:42 +00:00
self . _always_on_top = False
2015-12-02 22:32:18 +00:00
self . _last_ideal_position = None
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
self . setCursor ( QG . QCursor ( QC . Qt . ArrowCursor ) )
2015-06-17 20:01:41 +00:00
2016-12-07 22:12:52 +00:00
self . _hide_until = None
2020-01-22 21:04:43 +00:00
self . _position_initialised = False
2019-06-26 21:27:18 +00:00
2020-08-19 22:38:20 +00:00
self . _my_parent_tlw . installEventFilter ( self )
2017-05-10 21:33:58 +00:00
HG . client_controller . sub ( self , ' SetDisplayMedia ' , ' canvas_new_display_media ' )
2015-06-17 20:01:41 +00:00
2018-01-03 22:37:30 +00:00
HG . client_controller . gui . RegisterUIUpdateWindow ( self )
2015-06-17 20:01:41 +00:00
def _GetIdealSizeAndPosition ( self ) :
raise NotImplementedError ( )
2019-12-11 23:18:37 +00:00
def _SizeAndPosition ( self , force = False ) :
2015-06-17 20:01:41 +00:00
2019-12-11 23:18:37 +00:00
if self . parentWidget ( ) . isVisible ( ) or force :
2017-05-17 21:53:02 +00:00
2017-05-24 20:28:24 +00:00
( should_resize , my_ideal_size , my_ideal_position ) = self . _GetIdealSizeAndPosition ( )
2017-05-17 21:53:02 +00:00
2017-05-24 20:28:24 +00:00
if should_resize :
2020-08-19 22:38:20 +00:00
self . resize ( my_ideal_size )
2020-02-26 22:28:52 +00:00
2020-08-19 22:38:20 +00:00
if my_ideal_position != self . pos ( ) :
2020-02-26 22:28:52 +00:00
self . move ( my_ideal_position )
2017-05-24 20:28:24 +00:00
2015-06-17 20:01:41 +00:00
2020-01-22 21:04:43 +00:00
self . _position_initialised = True
2015-06-17 20:01:41 +00:00
2016-12-07 22:12:52 +00:00
2020-08-19 22:38:20 +00:00
def eventFilter ( self , watched , event ) :
if watched == self . _my_parent_tlw :
if event . type ( ) in ( QC . QEvent . Move , QC . QEvent . Resize ) :
self . _position_initialised = False
return False
2015-06-17 20:01:41 +00:00
def SetDisplayMedia ( self , canvas_key , media ) :
if canvas_key == self . _canvas_key :
self . _current_media = media
2018-01-03 22:37:30 +00:00
def TIMERUIUpdate ( self ) :
2020-01-22 21:04:43 +00:00
if not self . _position_initialised :
self . _SizeAndPosition ( )
2019-12-11 23:18:37 +00:00
current_focus_tlw = QW . QApplication . activeWindow ( )
2019-05-15 20:35:00 +00:00
2019-12-11 23:18:37 +00:00
focus_is_on_descendant = ClientGUIFunctions . IsQtAncestor ( current_focus_tlw , self . _my_canvas . window ( ) , through_tlws = True )
2020-03-25 21:15:57 +00:00
focus_has_right_window_type = isinstance ( current_focus_tlw , ( ClientGUITopLevelWindows . FrameThatResizesWithHovers , CanvasHoverFrame ) )
2019-05-15 20:35:00 +00:00
focus_is_good = focus_is_on_descendant and focus_has_right_window_type
2020-02-05 22:55:21 +00:00
mouse_is_over_self_or_child = False
for tlw in QW . QApplication . topLevelWidgets ( ) :
if tlw == self or ClientGUIFunctions . IsQtAncestor ( tlw , self , through_tlws = True ) :
if tlw . underMouse ( ) :
mouse_is_over_self_or_child = True
break
2019-12-11 23:18:37 +00:00
if self . _always_on_top :
2015-06-17 20:01:41 +00:00
2018-01-03 22:37:30 +00:00
self . _SizeAndPosition ( )
2017-09-13 20:50:41 +00:00
2019-11-14 03:56:30 +00:00
self . show ( )
2017-09-13 20:50:41 +00:00
2018-01-03 22:37:30 +00:00
return
2016-12-07 22:12:52 +00:00
2018-01-03 22:37:30 +00:00
if self . _hide_until is not None :
if HydrusData . TimeHasPassed ( self . _hide_until ) :
2015-06-17 20:01:41 +00:00
2018-01-03 22:37:30 +00:00
self . _hide_until = None
2015-06-17 20:01:41 +00:00
2015-11-18 22:44:07 +00:00
else :
2015-06-17 20:01:41 +00:00
2018-01-03 22:37:30 +00:00
return
2015-11-18 22:44:07 +00:00
2018-01-03 22:37:30 +00:00
2019-11-14 03:56:30 +00:00
if self . _current_media is None or not self . _my_canvas . isVisible ( ) :
2018-01-03 22:37:30 +00:00
2019-11-14 03:56:30 +00:00
if self . isVisible ( ) :
2018-01-17 22:52:10 +00:00
if HG . hover_window_report_mode :
HydrusData . ShowText ( repr ( self ) + ' - hiding because nothing to show or parent hidden. ' )
2019-11-14 03:56:30 +00:00
self . hide ( )
2018-01-17 22:52:10 +00:00
2018-01-03 22:37:30 +00:00
else :
2020-02-26 22:28:52 +00:00
mouse_pos = QG . QCursor . pos ( )
mouse_x = mouse_pos . x ( )
mouse_y = mouse_pos . y ( )
my_size = self . size ( )
my_width = my_size . width ( )
my_height = my_size . height ( )
2018-01-03 22:37:30 +00:00
2020-02-26 22:28:52 +00:00
my_pos = self . pos ( )
2018-01-03 22:37:30 +00:00
2020-02-26 22:28:52 +00:00
my_x = my_pos . x ( )
my_y = my_pos . y ( )
( should_resize , my_ideal_size , my_ideal_pos ) = self . _GetIdealSizeAndPosition ( )
my_ideal_width = my_ideal_size . width ( )
my_ideal_height = my_ideal_size . height ( )
my_ideal_x = my_ideal_pos . x ( )
my_ideal_y = my_ideal_pos . y ( )
2018-01-03 22:37:30 +00:00
if my_ideal_width == - 1 :
2015-11-18 22:44:07 +00:00
2018-01-03 22:37:30 +00:00
my_ideal_width = max ( my_width , 50 )
2015-11-18 22:44:07 +00:00
2018-01-03 22:37:30 +00:00
if my_ideal_height == - 1 :
2015-11-18 22:44:07 +00:00
2018-01-03 22:37:30 +00:00
my_ideal_height = max ( my_height , 50 )
2015-06-17 20:01:41 +00:00
2018-01-03 22:37:30 +00:00
2020-02-26 22:28:52 +00:00
in_ideal_x = my_ideal_x < = mouse_x < = my_ideal_x + my_ideal_width
in_ideal_y = my_ideal_y < = mouse_y < = my_ideal_y + my_ideal_height
2018-01-03 22:37:30 +00:00
2020-02-26 22:28:52 +00:00
in_actual_x = my_x < = mouse_x < = my_x + my_width
in_actual_y = my_y < = mouse_y < = my_y + my_height
2018-01-03 22:37:30 +00:00
# we test both ideal and actual here because setposition is not always honoured by the OS
2019-06-26 21:27:18 +00:00
# for instance, in some Linux window managers on a fullscreen view, the top taskbar is hidden, but when hover window is shown, it takes focus and causes taskbar to reappear
2018-01-03 22:37:30 +00:00
# the reappearance shuffles the screen coordinates down a bit so the hover sits +20px y despite wanting to be lined up with the underlying fullscreen viewer
# wew lad
in_position = ( in_ideal_x or in_actual_x ) and ( in_ideal_y or in_actual_y )
2020-03-04 22:12:53 +00:00
menu_open = CGC . core ( ) . MenuIsOpen ( )
2018-01-03 22:37:30 +00:00
2020-02-26 22:28:52 +00:00
dialog_is_open = ClientGUIFunctions . DialogIsOpen ( )
2015-11-18 22:44:07 +00:00
2019-05-08 21:06:42 +00:00
mouse_is_near_animation_bar = self . _my_canvas . MouseIsNearAnimationBar ( )
2015-11-18 22:44:07 +00:00
2020-02-05 22:55:21 +00:00
# this used to have the flash media window test to ensure mouse over flash window hid hovers going over it
mouse_is_over_something_else_important = mouse_is_near_animation_bar
2015-11-18 22:44:07 +00:00
2019-12-11 23:18:37 +00:00
hide_focus_is_good = focus_is_good or current_focus_tlw is None # don't hide if focus is either gone to another problem or temporarily sperging-out due to a click-transition or similar
2019-06-26 21:27:18 +00:00
2020-02-26 22:28:52 +00:00
ready_to_show = in_position and not mouse_is_over_something_else_important and focus_is_good and not dialog_is_open and not menu_open
ready_to_hide = not menu_open and not mouse_is_over_self_or_child and ( not in_position or dialog_is_open or not hide_focus_is_good )
2018-01-03 22:37:30 +00:00
2018-01-17 22:52:10 +00:00
def get_logic_report_string ( ) :
tuples = [ ]
2019-06-05 19:42:39 +00:00
tuples . append ( ( ' mouse: ' , ( mouse_x , mouse_y ) ) )
tuples . append ( ( ' winpos: ' , ( my_x , my_y ) ) )
2019-06-26 21:27:18 +00:00
tuples . append ( ( ' ideal winpos: ' , ( my_ideal_x , my_ideal_y ) ) )
2019-06-05 19:42:39 +00:00
tuples . append ( ( ' winsize: ' , ( my_width , my_height ) ) )
2019-06-26 21:27:18 +00:00
tuples . append ( ( ' ideal winsize: ' , ( my_ideal_width , my_ideal_height ) ) )
2018-01-17 22:52:10 +00:00
tuples . append ( ( ' in position: ' , in_position ) )
tuples . append ( ( ' menu open: ' , menu_open ) )
2020-02-26 22:28:52 +00:00
tuples . append ( ( ' dialog open: ' , dialog_is_open ) )
2018-01-17 22:52:10 +00:00
tuples . append ( ( ' mouse near animation bar: ' , mouse_is_near_animation_bar ) )
tuples . append ( ( ' focus is good: ' , focus_is_good ) )
2019-06-19 22:08:48 +00:00
tuples . append ( ( ' focus is on descendant: ' , focus_is_on_descendant ) )
2019-12-11 23:18:37 +00:00
tuples . append ( ( ' current focus tlw: ' , current_focus_tlw ) )
2018-01-17 22:52:10 +00:00
2019-06-05 19:42:39 +00:00
message = os . linesep * 2 + os . linesep . join ( ( a + str ( b ) for ( a , b ) in tuples ) )
2018-01-17 22:52:10 +00:00
return message
2018-01-03 22:37:30 +00:00
if ready_to_show :
self . _SizeAndPosition ( )
2019-11-14 03:56:30 +00:00
if not self . isVisible ( ) :
2018-01-17 22:52:10 +00:00
if HG . hover_window_report_mode :
HydrusData . ShowText ( repr ( self ) + ' - showing. ' + get_logic_report_string ( ) )
2019-11-14 03:56:30 +00:00
self . show ( )
2018-01-17 22:52:10 +00:00
2018-01-03 22:37:30 +00:00
elif ready_to_hide :
2019-11-14 03:56:30 +00:00
if self . isVisible ( ) :
2018-01-17 22:52:10 +00:00
if HG . hover_window_report_mode :
HydrusData . ShowText ( repr ( self ) + ' - hiding. ' + get_logic_report_string ( ) )
2019-11-14 03:56:30 +00:00
self . hide ( )
2018-01-17 22:52:10 +00:00
2018-01-03 22:37:30 +00:00
2017-03-29 19:39:34 +00:00
2020-03-25 21:15:57 +00:00
class CanvasHoverFrameRightDuplicates ( CanvasHoverFrame ) :
2019-05-08 21:06:42 +00:00
def __init__ ( self , parent , my_canvas , canvas_key ) :
2020-03-25 21:15:57 +00:00
CanvasHoverFrame . __init__ ( self , parent , my_canvas , canvas_key )
2019-05-08 21:06:42 +00:00
self . _always_on_top = True
self . _current_index_string = ' '
self . _comparison_media = None
2020-03-11 21:52:11 +00:00
self . _trash_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . delete , HG . client_controller . pub , ' canvas_delete ' , self . _canvas_key )
2019-11-14 03:56:30 +00:00
self . _trash_button . setToolTip ( ' send to trash ' )
2019-06-05 19:42:39 +00:00
2019-05-08 21:06:42 +00:00
menu_items = [ ]
2019-05-29 21:34:43 +00:00
menu_items . append ( ( ' normal ' , ' edit duplicate metadata merge options for \' this is better \' ' , ' edit what content is merged when you filter files ' , HydrusData . Call ( self . _EditMergeOptions , HC . DUPLICATE_BETTER ) ) )
menu_items . append ( ( ' normal ' , ' edit duplicate metadata merge options for \' same quality \' ' , ' edit what content is merged when you filter files ' , HydrusData . Call ( self . _EditMergeOptions , HC . DUPLICATE_SAME_QUALITY ) ) )
2019-06-05 19:42:39 +00:00
if HG . client_controller . new_options . GetBoolean ( ' advanced_mode ' ) :
menu_items . append ( ( ' normal ' , ' edit duplicate metadata merge options for \' alternates \' (advanced!) ' , ' edit what content is merged when you filter files ' , HydrusData . Call ( self . _EditMergeOptions , HC . DUPLICATE_ALTERNATE ) ) )
2019-05-08 21:06:42 +00:00
menu_items . append ( ( ' separator ' , None , None , None ) )
menu_items . append ( ( ' normal ' , ' edit background lighten/darken switch intensity ' , ' edit how much the background will brighten or darken as you switch between the pair ' , self . _EditBackgroundSwitchIntensity ) )
2021-03-17 21:59:28 +00:00
self . _cog_button = ClientGUIMenuButton . MenuBitmapButton ( self , CC . global_pixmaps ( ) . cog , menu_items )
2019-06-05 19:42:39 +00:00
2020-03-11 21:52:11 +00:00
close_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . stop , HG . client_controller . pub , ' canvas_close ' , self . _canvas_key )
2019-11-14 03:56:30 +00:00
close_button . setToolTip ( ' close filter ' )
2019-07-31 22:01:02 +00:00
2021-08-25 21:59:05 +00:00
self . _back_a_pair = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . first , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_DUPLICATE_FILTER_BACK ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
self . _back_a_pair . SetToolTipWithShortcuts ( ' go back a pair ' , CAC . SIMPLE_DUPLICATE_FILTER_BACK )
2019-05-08 21:06:42 +00:00
self . _index_text = ClientGUICommon . BetterStaticText ( self , ' index ' )
2021-08-25 21:59:05 +00:00
self . _next_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . pair , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_VIEW_NEXT ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
self . _next_button . SetToolTipWithShortcuts ( ' next ' , CAC . SIMPLE_VIEW_NEXT )
2019-05-08 21:06:42 +00:00
2021-08-25 21:59:05 +00:00
self . _skip_a_pair = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . last , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_DUPLICATE_FILTER_SKIP ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
self . _skip_a_pair . SetToolTipWithShortcuts ( ' show a different pair ' , CAC . SIMPLE_DUPLICATE_FILTER_SKIP )
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
command_button_vbox = QP . VBoxLayout ( )
2019-05-22 22:35:06 +00:00
dupe_boxes = [ ]
dupe_commands = [ ]
2021-08-25 21:59:05 +00:00
dupe_commands . append ( ( ' this is better, and delete the other ' , ' Set that the current file you are looking at is better than the other in the pair, and set the other file to be deleted. ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_DUPLICATE_FILTER_THIS_IS_BETTER_AND_DELETE_OTHER ) ) )
dupe_commands . append ( ( ' this is better, but keep both ' , ' Set that the current file you are looking at is better than the other in the pair, but keep both files. ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_DUPLICATE_FILTER_THIS_IS_BETTER_BUT_KEEP_BOTH ) ) )
dupe_commands . append ( ( ' they are the same quality ' , ' Set that the two files are duplicates of very similar quality. ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_DUPLICATE_FILTER_EXACTLY_THE_SAME ) ) )
2019-05-22 22:35:06 +00:00
dupe_boxes . append ( ( ' they are duplicates ' , dupe_commands ) )
2019-05-08 21:06:42 +00:00
dupe_commands = [ ]
2021-08-25 21:59:05 +00:00
dupe_commands . append ( ( ' they are related alternates ' , ' Set that the files are not duplicates, but that one is derived from the other or that they are both descendants of a common ancestor. ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_DUPLICATE_FILTER_ALTERNATES ) ) )
dupe_commands . append ( ( ' they are not related ' , ' Set that the files are not duplicates or otherwise related--that this potential pair is a false positive match. ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_DUPLICATE_FILTER_FALSE_POSITIVE ) ) )
dupe_commands . append ( ( ' custom action ' , ' Choose one of the other actions but customise the merge and delete options for this specific decision. ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_DUPLICATE_FILTER_CUSTOM_ACTION ) ) )
2019-05-08 21:06:42 +00:00
2019-05-22 22:35:06 +00:00
dupe_boxes . append ( ( ' other ' , dupe_commands ) )
2019-05-08 21:06:42 +00:00
2019-05-22 22:35:06 +00:00
for ( panel_name , dupe_commands ) in dupe_boxes :
2019-05-08 21:06:42 +00:00
2019-05-22 22:35:06 +00:00
button_panel = ClientGUICommon . StaticBox ( self , panel_name )
2019-05-08 21:06:42 +00:00
2019-05-22 22:35:06 +00:00
for ( label , tooltip , command ) in dupe_commands :
command_button = ClientGUICommon . BetterButton ( button_panel , label , HG . client_controller . pub , ' canvas_application_command ' , command , self . _canvas_key )
2021-08-25 21:59:05 +00:00
command_button . SetToolTipWithShortcuts ( tooltip , command . GetSimpleAction ( ) )
2019-05-22 22:35:06 +00:00
button_panel . Add ( command_button , CC . FLAGS_EXPAND_PERPENDICULAR )
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
QP . AddToLayout ( command_button_vbox , button_panel , CC . FLAGS_EXPAND_PERPENDICULAR )
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
self . _comparison_statements_vbox = QP . VBoxLayout ( )
2019-05-08 21:06:42 +00:00
2019-07-31 22:01:02 +00:00
self . _comparison_statement_names = [ ' filesize ' , ' resolution ' , ' ratio ' , ' mime ' , ' num_tags ' , ' time_imported ' , ' jpeg_quality ' , ' pixel_duplicates ' ]
2019-05-08 21:06:42 +00:00
self . _comparison_statements_sts = { }
for name in self . _comparison_statement_names :
2019-11-14 03:56:30 +00:00
panel = QW . QWidget ( self )
2019-05-08 21:06:42 +00:00
st = ClientGUICommon . BetterStaticText ( panel , ' init ' )
self . _comparison_statements_sts [ name ] = ( panel , st )
2019-11-14 03:56:30 +00:00
hbox = QP . HBoxLayout ( )
2019-05-08 21:06:42 +00:00
2020-07-22 20:59:16 +00:00
QP . AddToLayout ( hbox , st , CC . FLAGS_CENTER )
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
panel . setLayout ( hbox )
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
panel . setVisible ( False )
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
QP . AddToLayout ( self . _comparison_statements_vbox , panel , CC . FLAGS_EXPAND_SIZER_PERPENDICULAR )
2019-05-08 21:06:42 +00:00
#
2019-11-14 03:56:30 +00:00
top_button_hbox = QP . HBoxLayout ( )
2019-06-05 19:42:39 +00:00
2021-02-11 01:59:52 +00:00
QP . AddToLayout ( top_button_hbox , self . _next_button , CC . FLAGS_EXPAND_BOTH_WAYS )
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( top_button_hbox , self . _trash_button , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( top_button_hbox , self . _cog_button , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( top_button_hbox , close_button , CC . FLAGS_CENTER_PERPENDICULAR )
2019-06-05 19:42:39 +00:00
2019-11-14 03:56:30 +00:00
navigation_button_hbox = QP . HBoxLayout ( )
2019-05-08 21:06:42 +00:00
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( navigation_button_hbox , self . _back_a_pair , CC . FLAGS_CENTER_PERPENDICULAR )
2020-07-22 20:59:16 +00:00
navigation_button_hbox . addStretch ( 1 )
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( navigation_button_hbox , self . _index_text , CC . FLAGS_CENTER_PERPENDICULAR )
2020-07-22 20:59:16 +00:00
navigation_button_hbox . addStretch ( 1 )
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( navigation_button_hbox , self . _skip_a_pair , CC . FLAGS_CENTER_PERPENDICULAR )
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
vbox = QP . VBoxLayout ( )
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
QP . AddToLayout ( vbox , navigation_button_hbox , CC . FLAGS_EXPAND_SIZER_PERPENDICULAR )
2021-02-11 01:59:52 +00:00
#QP.AddToLayout( vbox, self._next_button, CC.FLAGS_EXPAND_PERPENDICULAR )
QP . AddToLayout ( vbox , top_button_hbox , CC . FLAGS_EXPAND_PERPENDICULAR )
2019-11-14 03:56:30 +00:00
QP . AddToLayout ( vbox , command_button_vbox , CC . FLAGS_EXPAND_SIZER_PERPENDICULAR )
QP . AddToLayout ( vbox , self . _comparison_statements_vbox , CC . FLAGS_EXPAND_SIZER_PERPENDICULAR )
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
self . setLayout ( vbox )
2019-05-08 21:06:42 +00:00
HG . client_controller . sub ( self , ' SetDuplicatePair ' , ' canvas_new_duplicate_pair ' )
HG . client_controller . sub ( self , ' SetIndexString ' , ' canvas_new_index_string ' )
def _EditBackgroundSwitchIntensity ( self ) :
new_options = HG . client_controller . new_options
value = new_options . GetNoneableInteger ( ' duplicate_background_switch_intensity ' )
2020-04-29 21:44:12 +00:00
with ClientGUITopLevelWindowsPanels . DialogEdit ( self , ' edit lighten/darken intensity ' ) as dlg :
2019-05-08 21:06:42 +00:00
panel = ClientGUIScrolledPanelsEdit . EditNoneableIntegerPanel ( dlg , value , message = ' intensity: ' , none_phrase = ' do not change ' , min = 1 , max = 9 )
dlg . SetPanel ( panel )
2019-11-14 03:56:30 +00:00
if dlg . exec ( ) == QW . QDialog . Accepted :
2019-05-08 21:06:42 +00:00
new_value = panel . GetValue ( )
new_options . SetNoneableInteger ( ' duplicate_background_switch_intensity ' , new_value )
def _EditMergeOptions ( self , duplicate_type ) :
new_options = HG . client_controller . new_options
duplicate_action_options = new_options . GetDuplicateActionOptions ( duplicate_type )
2020-04-29 21:44:12 +00:00
with ClientGUITopLevelWindowsPanels . DialogEdit ( self , ' edit duplicate merge options ' ) as dlg :
2019-05-08 21:06:42 +00:00
panel = ClientGUIScrolledPanelsEdit . EditDuplicateActionOptionsPanel ( dlg , duplicate_type , duplicate_action_options )
dlg . SetPanel ( panel )
2019-11-14 03:56:30 +00:00
if dlg . exec ( ) == QW . QDialog . Accepted :
2019-05-08 21:06:42 +00:00
duplicate_action_options = panel . GetValue ( )
new_options . SetDuplicateActionOptions ( duplicate_type , duplicate_action_options )
def _GetIdealSizeAndPosition ( self ) :
2019-11-14 03:56:30 +00:00
parent_window = self . parentWidget ( ) . window ( )
2019-05-08 21:06:42 +00:00
2020-02-26 22:28:52 +00:00
parent_size = parent_window . size ( )
parent_width = parent_size . width ( )
parent_height = parent_size . height ( )
my_size = self . size ( )
2019-05-08 21:06:42 +00:00
2020-02-26 22:28:52 +00:00
my_width = my_size . width ( )
my_height = my_size . height ( )
2019-05-08 21:06:42 +00:00
2020-08-05 20:10:36 +00:00
my_ideal_width = max ( int ( parent_width * 0.2 ) , self . sizeHint ( ) . width ( ) )
2020-07-22 20:59:16 +00:00
my_ideal_height = self . sizeHint ( ) . height ( )
2019-05-08 21:06:42 +00:00
2020-01-02 03:05:35 +00:00
should_resize = my_ideal_width != my_width or my_ideal_height != my_height
2019-05-08 21:06:42 +00:00
2020-02-26 22:28:52 +00:00
ideal_size = QC . QSize ( my_ideal_width , my_ideal_height )
ideal_position = ClientGUIFunctions . ClientToScreen ( parent_window , QC . QPoint ( int ( parent_width - my_ideal_width ) , int ( parent_height * 0.3 ) ) )
2019-05-08 21:06:42 +00:00
2020-02-26 22:28:52 +00:00
return ( should_resize , ideal_size , ideal_position )
2019-05-08 21:06:42 +00:00
def _ResetComparisonStatements ( self ) :
statements_and_scores = ClientMedia . GetDuplicateComparisonStatements ( self . _current_media , self . _comparison_media )
for name in self . _comparison_statement_names :
( panel , st ) = self . _comparison_statements_sts [ name ]
2021-09-08 21:41:52 +00:00
got_data = name in statements_and_scores
show_panel = got_data
if panel . isVisible ( ) != show_panel :
2019-05-08 21:06:42 +00:00
2021-09-08 21:41:52 +00:00
panel . setVisible ( show_panel )
2019-05-08 21:06:42 +00:00
2021-09-08 21:41:52 +00:00
if got_data :
( statement , score ) = statements_and_scores [ name ]
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
st . setText ( statement )
2019-05-08 21:06:42 +00:00
if score > 0 :
2021-09-08 21:41:52 +00:00
object_name = ' HydrusValid '
2019-05-08 21:06:42 +00:00
elif score < 0 :
2021-09-08 21:41:52 +00:00
object_name = ' HydrusInvalid '
2019-05-08 21:06:42 +00:00
else :
2021-09-08 21:41:52 +00:00
object_name = ' HydrusIndeterminate '
2019-05-08 21:06:42 +00:00
2021-09-08 21:41:52 +00:00
st . setObjectName ( object_name )
2019-05-08 21:06:42 +00:00
2021-09-08 21:41:52 +00:00
st . style ( ) . polish ( st )
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
def wheelEvent ( self , event ) :
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
QW . QApplication . sendEvent ( self . parentWidget ( ) , event )
2019-05-08 21:06:42 +00:00
def SetDuplicatePair ( self , canvas_key , shown_media , comparison_media ) :
if canvas_key == self . _canvas_key :
self . _current_media = shown_media
self . _comparison_media = comparison_media
self . _ResetComparisonStatements ( )
2020-01-02 03:05:35 +00:00
# minimumsize is not immediately updated without this
self . layout ( ) . activate ( )
self . _SizeAndPosition ( force = True )
2019-05-08 21:06:42 +00:00
def SetIndexString ( self , canvas_key , text ) :
if canvas_key == self . _canvas_key :
self . _current_index_string = text
2019-11-14 03:56:30 +00:00
self . _index_text . setText ( self . _current_index_string )
2019-05-08 21:06:42 +00:00
2020-03-25 21:15:57 +00:00
class CanvasHoverFrameTop ( CanvasHoverFrame ) :
2015-06-17 20:01:41 +00:00
2018-12-05 22:35:30 +00:00
def __init__ ( self , parent , my_canvas , canvas_key ) :
2015-06-17 20:01:41 +00:00
2020-03-25 21:15:57 +00:00
CanvasHoverFrame . __init__ ( self , parent , my_canvas , canvas_key )
2015-06-17 20:01:41 +00:00
self . _current_zoom = 1.0
self . _current_index_string = ' '
2019-11-14 03:56:30 +00:00
self . _top_hbox = QP . HBoxLayout ( )
2019-11-20 23:10:46 +00:00
2019-11-14 03:56:30 +00:00
self . _title_text = ClientGUICommon . BetterStaticText ( self , ' title ' , ellipsize_end = True )
self . _info_text = ClientGUICommon . BetterStaticText ( self , ' info ' , ellipsize_end = True )
2017-03-29 19:39:34 +00:00
2019-11-20 23:10:46 +00:00
self . _title_text . setAlignment ( QC . Qt . AlignHCenter | QC . Qt . AlignVCenter )
self . _info_text . setAlignment ( QC . Qt . AlignHCenter | QC . Qt . AlignVCenter )
2017-03-29 19:39:34 +00:00
self . _PopulateLeftButtons ( )
2020-07-22 20:59:16 +00:00
self . _top_hbox . addStretch ( 1 )
2017-03-29 19:39:34 +00:00
self . _PopulateCenterButtons ( )
2020-07-22 20:59:16 +00:00
self . _top_hbox . addStretch ( 1 )
2017-03-29 19:39:34 +00:00
self . _PopulateRightButtons ( )
2019-11-14 03:56:30 +00:00
vbox = QP . VBoxLayout ( )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
QP . AddToLayout ( vbox , self . _top_hbox , CC . FLAGS_EXPAND_SIZER_PERPENDICULAR )
2019-11-20 23:10:46 +00:00
QP . AddToLayout ( vbox , self . _title_text , CC . FLAGS_EXPAND_PERPENDICULAR )
QP . AddToLayout ( vbox , self . _info_text , CC . FLAGS_EXPAND_PERPENDICULAR )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
self . setLayout ( vbox )
2015-06-17 20:01:41 +00:00
2017-05-10 21:33:58 +00:00
HG . client_controller . sub ( self , ' ProcessContentUpdates ' , ' content_updates_gui ' )
HG . client_controller . sub ( self , ' SetCurrentZoom ' , ' canvas_new_zoom ' )
HG . client_controller . sub ( self , ' SetIndexString ' , ' canvas_new_index_string ' )
2015-06-17 20:01:41 +00:00
2017-03-29 19:39:34 +00:00
def _Archive ( self ) :
2015-06-17 20:01:41 +00:00
2017-03-29 19:39:34 +00:00
if self . _current_media . HasInbox ( ) :
2021-08-25 21:59:05 +00:00
command = CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_ARCHIVE_FILE )
2017-03-29 19:39:34 +00:00
else :
2021-08-25 21:59:05 +00:00
command = CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_INBOX_FILE )
2017-03-29 19:39:34 +00:00
2018-03-14 21:01:02 +00:00
HG . client_controller . pub ( ' canvas_application_command ' , command , self . _canvas_key )
2017-05-10 21:33:58 +00:00
2017-03-29 19:39:34 +00:00
def _GetIdealSizeAndPosition ( self ) :
2015-06-17 20:01:41 +00:00
2019-12-11 23:18:37 +00:00
# clip this and friends to availableScreenGeometry for size and position, not rely 100% on parent
2019-11-14 03:56:30 +00:00
parent_window = self . parentWidget ( ) . window ( )
2017-03-29 19:39:34 +00:00
2020-02-26 22:28:52 +00:00
parent_size = parent_window . size ( )
2017-03-29 19:39:34 +00:00
2020-02-26 22:28:52 +00:00
parent_width = parent_size . width ( )
my_size = self . size ( )
my_width = my_size . width ( )
my_height = my_size . height ( )
2017-03-29 19:39:34 +00:00
2020-08-19 22:38:20 +00:00
my_ideal_width = max ( int ( parent_width * 0.6 ) , self . sizeHint ( ) . width ( ) )
2017-03-29 19:39:34 +00:00
2019-11-14 03:56:30 +00:00
my_ideal_height = self . sizeHint ( ) . height ( )
should_resize = my_ideal_width != my_width or my_ideal_height != my_height
2017-03-29 19:39:34 +00:00
2020-02-26 22:28:52 +00:00
ideal_size = QC . QSize ( my_ideal_width , my_ideal_height )
ideal_position = ClientGUIFunctions . ClientToScreen ( parent_window , QC . QPoint ( int ( parent_width * 0.2 ) , 0 ) )
2017-03-29 19:39:34 +00:00
2020-02-26 22:28:52 +00:00
return ( should_resize , ideal_size , ideal_position )
2017-03-29 19:39:34 +00:00
def _PopulateCenterButtons ( self ) :
2020-03-11 21:52:11 +00:00
self . _archive_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . archive , self . _Archive )
2017-03-29 19:39:34 +00:00
2020-03-11 21:52:11 +00:00
self . _trash_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . delete , HG . client_controller . pub , ' canvas_delete ' , self . _canvas_key )
2019-11-14 03:56:30 +00:00
self . _trash_button . setToolTip ( ' send to trash ' )
2015-08-05 18:42:35 +00:00
2020-03-11 21:52:11 +00:00
self . _delete_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . trash_delete , HG . client_controller . pub , ' canvas_delete ' , self . _canvas_key )
2019-11-14 03:56:30 +00:00
self . _delete_button . setToolTip ( ' delete completely ' )
2015-08-05 18:42:35 +00:00
2020-03-11 21:52:11 +00:00
self . _undelete_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . undelete , HG . client_controller . pub , ' canvas_undelete ' , self . _canvas_key )
2019-11-14 03:56:30 +00:00
self . _undelete_button . setToolTip ( ' undelete ' )
2015-06-17 20:01:41 +00:00
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( self . _top_hbox , self . _archive_button , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( self . _top_hbox , self . _trash_button , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( self . _top_hbox , self . _delete_button , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( self . _top_hbox , self . _undelete_button , CC . FLAGS_CENTER_PERPENDICULAR )
2017-03-29 19:39:34 +00:00
def _PopulateLeftButtons ( self ) :
2017-04-19 20:58:30 +00:00
self . _index_text = ClientGUICommon . BetterStaticText ( self , ' index ' )
2017-03-29 19:39:34 +00:00
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( self . _top_hbox , self . _index_text , CC . FLAGS_CENTER_PERPENDICULAR )
2017-03-29 19:39:34 +00:00
def _PopulateRightButtons ( self ) :
2017-04-19 20:58:30 +00:00
self . _zoom_text = ClientGUICommon . BetterStaticText ( self , ' zoom ' )
2015-06-17 20:01:41 +00:00
2021-08-25 21:59:05 +00:00
zoom_in = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . zoom_in , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_ZOOM_IN_VIEWER_CENTER ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
zoom_in . SetToolTipWithShortcuts ( ' zoom in ' , CAC . SIMPLE_ZOOM_IN )
2015-06-17 20:01:41 +00:00
2021-08-25 21:59:05 +00:00
zoom_out = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . zoom_out , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_ZOOM_OUT_VIEWER_CENTER ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
zoom_out . SetToolTipWithShortcuts ( ' zoom out ' , CAC . SIMPLE_ZOOM_OUT )
2015-06-17 20:01:41 +00:00
2021-08-25 21:59:05 +00:00
zoom_switch = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . zoom_switch , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_SWITCH_BETWEEN_100_PERCENT_AND_CANVAS_ZOOM_VIEWER_CENTER ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
zoom_switch . SetToolTipWithShortcuts ( ' zoom switch ' , CAC . SIMPLE_SWITCH_BETWEEN_100_PERCENT_AND_CANVAS_ZOOM )
2015-06-17 20:01:41 +00:00
2020-02-05 22:55:21 +00:00
self . _volume_control = ClientGUIMediaControls . VolumeControl ( self , ClientGUICommon . CANVAS_MEDIA_VIEWER )
2020-01-22 21:04:43 +00:00
if not ClientGUIMPV . MPV_IS_AVAILABLE :
2020-02-05 22:55:21 +00:00
self . _volume_control . hide ( )
2020-01-22 21:04:43 +00:00
2020-03-11 21:52:11 +00:00
shortcuts = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . keyboard , self . _ShowShortcutMenu )
2019-11-14 03:56:30 +00:00
shortcuts . setToolTip ( ' shortcuts ' )
2015-06-17 20:01:41 +00:00
2020-03-11 21:52:11 +00:00
fullscreen_switch = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . fullscreen_switch , HG . client_controller . pub , ' canvas_fullscreen_switch ' , self . _canvas_key )
2019-11-14 03:56:30 +00:00
fullscreen_switch . setToolTip ( ' fullscreen switch ' )
2015-08-05 18:42:35 +00:00
2019-11-20 23:10:46 +00:00
if HC . PLATFORM_MACOS :
2019-11-14 03:56:30 +00:00
fullscreen_switch . hide ( )
2018-03-28 21:55:58 +00:00
2021-08-25 21:59:05 +00:00
open_externally = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . open_externally , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_OPEN_FILE_IN_EXTERNAL_PROGRAM ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
open_externally . SetToolTipWithShortcuts ( ' open externally ' , CAC . SIMPLE_OPEN_FILE_IN_EXTERNAL_PROGRAM )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
drag_button = QW . QPushButton ( self )
2020-03-11 21:52:11 +00:00
drag_button . setIcon ( QG . QIcon ( CC . global_pixmaps ( ) . drag ) )
drag_button . setIconSize ( CC . global_pixmaps ( ) . drag . size ( ) )
2019-11-14 03:56:30 +00:00
drag_button . setToolTip ( ' drag from here to export file ' )
drag_button . pressed . connect ( self . EventDragButton )
2020-03-11 21:52:11 +00:00
close = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . stop , HG . client_controller . pub , ' canvas_close ' , self . _canvas_key )
2019-11-14 03:56:30 +00:00
close . setToolTip ( ' close ' )
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( self . _top_hbox , self . _zoom_text , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( self . _top_hbox , zoom_in , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( self . _top_hbox , zoom_out , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( self . _top_hbox , zoom_switch , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( self . _top_hbox , self . _volume_control , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( self . _top_hbox , shortcuts , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( self . _top_hbox , fullscreen_switch , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( self . _top_hbox , open_externally , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( self . _top_hbox , drag_button , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( self . _top_hbox , close , CC . FLAGS_CENTER_PERPENDICULAR )
2015-06-17 20:01:41 +00:00
2017-03-29 19:39:34 +00:00
def _ResetArchiveButton ( self ) :
2015-06-17 20:01:41 +00:00
2017-03-29 19:39:34 +00:00
if self . _current_media . HasInbox ( ) :
2020-03-11 21:52:11 +00:00
ClientGUIFunctions . SetBitmapButtonBitmap ( self . _archive_button , CC . global_pixmaps ( ) . archive )
2019-11-14 03:56:30 +00:00
self . _archive_button . setToolTip ( ' archive ' )
2017-03-29 19:39:34 +00:00
else :
2020-03-11 21:52:11 +00:00
ClientGUIFunctions . SetBitmapButtonBitmap ( self . _archive_button , CC . global_pixmaps ( ) . to_inbox )
2019-11-14 03:56:30 +00:00
self . _archive_button . setToolTip ( ' return to inbox ' )
2017-03-29 19:39:34 +00:00
2015-06-17 20:01:41 +00:00
def _ResetButtons ( self ) :
if self . _current_media is not None :
2017-03-29 19:39:34 +00:00
self . _ResetArchiveButton ( )
2015-06-17 20:01:41 +00:00
2021-04-28 21:43:16 +00:00
locations_manager = self . _current_media . GetLocationsManager ( )
2015-08-05 18:42:35 +00:00
2021-04-28 21:43:16 +00:00
if CC . LOCAL_FILE_SERVICE_KEY in locations_manager . GetCurrent ( ) :
2015-08-05 18:42:35 +00:00
2019-11-14 03:56:30 +00:00
self . _trash_button . show ( )
self . _delete_button . hide ( )
self . _undelete_button . hide ( )
2015-08-05 18:42:35 +00:00
2021-04-28 21:43:16 +00:00
elif locations_manager . IsTrashed ( ) :
2015-08-05 18:42:35 +00:00
2019-11-14 03:56:30 +00:00
self . _trash_button . hide ( )
self . _delete_button . show ( )
self . _undelete_button . show ( )
2015-08-05 18:42:35 +00:00
2015-06-17 20:01:41 +00:00
def _ResetText ( self ) :
if self . _current_media is None :
2019-11-14 03:56:30 +00:00
self . _title_text . hide ( )
self . _info_text . hide ( )
2015-06-17 20:01:41 +00:00
else :
label = self . _current_media . GetTitleString ( )
if len ( label ) > 0 :
2019-11-14 03:56:30 +00:00
self . _title_text . setText ( label )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
self . _title_text . show ( )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
else : self . _title_text . hide ( )
2015-06-17 20:01:41 +00:00
2016-04-20 20:42:21 +00:00
lines = self . _current_media . GetPrettyInfoLines ( )
label = ' | ' . join ( lines )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
self . _info_text . setText ( label )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
self . _info_text . show ( )
2015-06-17 20:01:41 +00:00
2018-12-05 22:35:30 +00:00
def _FlipActiveDefaultCustomShortcut ( self , name ) :
2017-04-19 20:58:30 +00:00
2017-12-06 22:06:56 +00:00
new_options = HG . client_controller . new_options
2017-04-19 20:58:30 +00:00
2018-12-05 22:35:30 +00:00
default_media_viewer_custom_shortcuts = list ( new_options . GetStringList ( ' default_media_viewer_custom_shortcuts ' ) )
if name in default_media_viewer_custom_shortcuts :
default_media_viewer_custom_shortcuts . remove ( name )
else :
default_media_viewer_custom_shortcuts . append ( name )
default_media_viewer_custom_shortcuts . sort ( )
new_options . SetStringList ( ' default_media_viewer_custom_shortcuts ' , default_media_viewer_custom_shortcuts )
def _ShowShortcutMenu ( self ) :
2017-04-19 20:58:30 +00:00
2019-06-05 19:42:39 +00:00
all_shortcut_names = HG . client_controller . Read ( ' serialisable_names ' , HydrusSerialisable . SERIALISABLE_TYPE_SHORTCUT_SET )
2017-04-19 20:58:30 +00:00
2020-02-19 21:48:36 +00:00
custom_shortcuts_names = [ name for name in all_shortcut_names if name not in ClientGUIShortcuts . SHORTCUTS_RESERVED_NAMES ]
2017-04-19 20:58:30 +00:00
2019-11-14 03:56:30 +00:00
menu = QW . QMenu ( )
2020-03-25 21:15:57 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' edit shortcuts ' , ' edit your sets of shortcuts, and change what shortcuts are currently active on this media viewer ' , ClientGUIShortcutControls . ManageShortcuts , self )
2018-12-05 22:35:30 +00:00
if len ( custom_shortcuts_names ) > 0 :
2017-04-19 20:58:30 +00:00
2018-12-05 22:35:30 +00:00
my_canvas_active_custom_shortcuts = self . _my_canvas . GetActiveCustomShortcutNames ( )
default_media_viewer_custom_shortcuts = HG . client_controller . new_options . GetStringList ( ' default_media_viewer_custom_shortcuts ' )
2017-04-19 20:58:30 +00:00
2019-11-14 03:56:30 +00:00
current_menu = QW . QMenu ( menu )
2017-04-19 20:58:30 +00:00
2018-12-05 22:35:30 +00:00
for name in custom_shortcuts_names :
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuCheckItem ( current_menu , name , ' turn this shortcut set on/off ' , name in my_canvas_active_custom_shortcuts , self . _my_canvas . FlipActiveCustomShortcutName , name )
2018-12-05 22:35:30 +00:00
2017-04-19 20:58:30 +00:00
2018-12-05 22:35:30 +00:00
ClientGUIMenus . AppendMenu ( menu , current_menu , ' set current shortcuts ' )
2017-04-19 20:58:30 +00:00
2019-11-14 03:56:30 +00:00
defaults_menu = QW . QMenu ( menu )
2017-04-19 20:58:30 +00:00
2018-12-05 22:35:30 +00:00
for name in custom_shortcuts_names :
2017-04-19 20:58:30 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuCheckItem ( defaults_menu , name , ' turn this shortcut set on/off by default ' , name in default_media_viewer_custom_shortcuts , self . _FlipActiveDefaultCustomShortcut , name )
2017-04-19 20:58:30 +00:00
2018-12-05 22:35:30 +00:00
ClientGUIMenus . AppendMenu ( menu , defaults_menu , ' set default shortcuts ' )
2020-03-04 22:12:53 +00:00
CGC . core ( ) . PopupMenu ( self , menu )
2017-04-19 20:58:30 +00:00
2019-11-14 03:56:30 +00:00
def EventDragButton ( self ) :
2018-03-28 21:55:58 +00:00
if self . _current_media is None :
2019-11-14 03:56:30 +00:00
return True # was: event.ignore()
2018-03-28 21:55:58 +00:00
page_key = None
media = [ self . _current_media ]
2019-11-14 03:56:30 +00:00
alt_down = QW . QApplication . keyboardModifiers ( ) & QC . Qt . AltModifier
2018-03-28 21:55:58 +00:00
2020-03-11 21:52:11 +00:00
result = ClientGUIDragDrop . DoFileExportDragDrop ( self , page_key , media , alt_down )
2018-03-28 21:55:58 +00:00
2019-11-14 03:56:30 +00:00
if result != QC . Qt . IgnoreAction :
2018-03-28 21:55:58 +00:00
2021-08-25 21:59:05 +00:00
HG . client_controller . pub ( ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_PAUSE_MEDIA ) , self . _canvas_key )
2018-03-28 21:55:58 +00:00
2019-11-14 03:56:30 +00:00
def resizeEvent ( self , event ) :
# reset wrap width
self . _ResetText ( )
event . ignore ( )
def wheelEvent ( self , event ) :
2015-09-16 18:11:00 +00:00
2019-11-14 03:56:30 +00:00
QW . QApplication . sendEvent ( self . parentWidget ( ) , event )
2015-09-16 18:11:00 +00:00
2015-06-17 20:01:41 +00:00
def ProcessContentUpdates ( self , service_keys_to_content_updates ) :
if self . _current_media is not None :
my_hash = self . _current_media . GetHash ( )
do_redraw = False
2021-04-28 21:43:16 +00:00
for ( service_key , content_updates ) in service_keys_to_content_updates . items ( ) :
2015-06-17 20:01:41 +00:00
if True in ( my_hash in content_update . GetHashes ( ) for content_update in content_updates ) :
do_redraw = True
break
if do_redraw :
2021-08-18 21:10:01 +00:00
self . _ResetText ( )
2015-06-17 20:01:41 +00:00
self . _ResetButtons ( )
def SetCurrentZoom ( self , canvas_key , zoom ) :
if canvas_key == self . _canvas_key :
self . _current_zoom = zoom
2015-08-26 21:18:39 +00:00
label = ClientData . ConvertZoomToPercentage ( self . _current_zoom )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
self . _zoom_text . setText ( label )
2015-06-17 20:01:41 +00:00
def SetDisplayMedia ( self , canvas_key , media ) :
if canvas_key == self . _canvas_key :
2020-03-25 21:15:57 +00:00
CanvasHoverFrame . SetDisplayMedia ( self , canvas_key , media )
2015-06-17 20:01:41 +00:00
self . _ResetText ( )
2017-03-29 19:39:34 +00:00
self . _ResetButtons ( )
2015-07-15 20:28:26 +00:00
2019-12-11 23:18:37 +00:00
# minimumsize is not immediately updated without this
self . layout ( ) . activate ( )
self . _SizeAndPosition ( force = True )
2015-06-17 20:01:41 +00:00
def SetIndexString ( self , canvas_key , text ) :
if canvas_key == self . _canvas_key :
self . _current_index_string = text
2019-11-14 03:56:30 +00:00
self . _index_text . setText ( self . _current_index_string )
2015-06-17 20:01:41 +00:00
2020-03-25 21:15:57 +00:00
class CanvasHoverFrameTopArchiveDeleteFilter ( CanvasHoverFrameTop ) :
2017-05-10 21:33:58 +00:00
def _Archive ( self ) :
2021-08-25 21:59:05 +00:00
HG . client_controller . pub ( ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_ARCHIVE_FILE ) , self . _canvas_key )
2017-05-10 21:33:58 +00:00
def _PopulateLeftButtons ( self ) :
2021-08-25 21:59:05 +00:00
self . _back_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . previous , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_ARCHIVE_DELETE_FILTER_BACK ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
self . _back_button . SetToolTipWithShortcuts ( ' back ' , CAC . SIMPLE_ARCHIVE_DELETE_FILTER_BACK )
2017-05-31 21:50:53 +00:00
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( self . _top_hbox , self . _back_button , CC . FLAGS_CENTER_PERPENDICULAR )
2017-05-31 21:50:53 +00:00
2020-03-25 21:15:57 +00:00
CanvasHoverFrameTop . _PopulateLeftButtons ( self )
2017-05-10 21:33:58 +00:00
2021-08-25 21:59:05 +00:00
self . _skip_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . next_bmp , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_ARCHIVE_DELETE_FILTER_SKIP ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
self . _skip_button . SetToolTipWithShortcuts ( ' skip ' , CAC . SIMPLE_ARCHIVE_DELETE_FILTER_SKIP )
2017-05-31 21:50:53 +00:00
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( self . _top_hbox , self . _skip_button , CC . FLAGS_CENTER_PERPENDICULAR )
2017-05-10 21:33:58 +00:00
def _ResetArchiveButton ( self ) :
2020-03-11 21:52:11 +00:00
ClientGUIFunctions . SetBitmapButtonBitmap ( self . _archive_button , CC . global_pixmaps ( ) . archive )
2019-11-14 03:56:30 +00:00
self . _archive_button . setToolTip ( ' archive ' )
2017-05-10 21:33:58 +00:00
2020-03-25 21:15:57 +00:00
class CanvasHoverFrameTopNavigable ( CanvasHoverFrameTop ) :
2017-05-31 21:50:53 +00:00
def _PopulateLeftButtons ( self ) :
2021-08-25 21:59:05 +00:00
self . _previous_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . previous , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_VIEW_PREVIOUS ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
self . _previous_button . SetToolTipWithShortcuts ( ' previous ' , CAC . SIMPLE_VIEW_PREVIOUS )
2017-05-31 21:50:53 +00:00
self . _index_text = ClientGUICommon . BetterStaticText ( self , ' index ' )
2021-08-25 21:59:05 +00:00
self . _next_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . next_bmp , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_VIEW_NEXT ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
self . _next_button . SetToolTipWithShortcuts ( ' next ' , CAC . SIMPLE_VIEW_NEXT )
2017-05-31 21:50:53 +00:00
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( self . _top_hbox , self . _previous_button , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( self . _top_hbox , self . _index_text , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( self . _top_hbox , self . _next_button , CC . FLAGS_CENTER_PERPENDICULAR )
2017-05-31 21:50:53 +00:00
2020-03-25 21:15:57 +00:00
class CanvasHoverFrameTopDuplicatesFilter ( CanvasHoverFrameTopNavigable ) :
2017-03-29 19:39:34 +00:00
def _PopulateLeftButtons ( self ) :
2021-08-25 21:59:05 +00:00
self . _first_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . first , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_DUPLICATE_FILTER_BACK ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
self . _first_button . SetToolTipWithShortcuts ( ' go back a pair ' , CAC . SIMPLE_DUPLICATE_FILTER_BACK )
2017-05-17 21:53:02 +00:00
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( self . _top_hbox , self . _first_button , CC . FLAGS_CENTER_PERPENDICULAR )
2017-05-17 21:53:02 +00:00
2020-03-25 21:15:57 +00:00
CanvasHoverFrameTopNavigable . _PopulateLeftButtons ( self )
2017-03-29 19:39:34 +00:00
2021-08-25 21:59:05 +00:00
self . _last_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . last , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_DUPLICATE_FILTER_SKIP ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
self . _last_button . SetToolTipWithShortcuts ( ' show a different pair ' , CAC . SIMPLE_DUPLICATE_FILTER_SKIP )
2017-03-29 19:39:34 +00:00
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( self . _top_hbox , self . _last_button , CC . FLAGS_CENTER_PERPENDICULAR )
2017-03-29 19:39:34 +00:00
2020-03-25 21:15:57 +00:00
class CanvasHoverFrameTopNavigableList ( CanvasHoverFrameTopNavigable ) :
2017-03-29 19:39:34 +00:00
def _PopulateLeftButtons ( self ) :
2021-08-25 21:59:05 +00:00
self . _first_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . first , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_VIEW_FIRST ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
self . _first_button . SetToolTipWithShortcuts ( ' first ' , CAC . SIMPLE_VIEW_FIRST )
2017-03-29 19:39:34 +00:00
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( self . _top_hbox , self . _first_button , CC . FLAGS_CENTER_PERPENDICULAR )
2017-03-29 19:39:34 +00:00
2020-03-25 21:15:57 +00:00
CanvasHoverFrameTopNavigable . _PopulateLeftButtons ( self )
2017-03-29 19:39:34 +00:00
2021-08-25 21:59:05 +00:00
self . _last_button = ClientGUICommon . BetterBitmapButton ( self , CC . global_pixmaps ( ) . last , HG . client_controller . pub , ' canvas_application_command ' , CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_VIEW_LAST ) , self . _canvas_key )
2020-07-08 22:00:33 +00:00
self . _last_button . SetToolTipWithShortcuts ( ' last ' , CAC . SIMPLE_VIEW_LAST )
2017-03-29 19:39:34 +00:00
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( self . _top_hbox , self . _last_button , CC . FLAGS_CENTER_PERPENDICULAR )
2017-03-29 19:39:34 +00:00
2020-03-25 21:15:57 +00:00
class CanvasHoverFrameTopRight ( CanvasHoverFrame ) :
2015-06-17 20:01:41 +00:00
2020-08-05 20:10:36 +00:00
def __init__ ( self , parent , my_canvas , top_hover : CanvasHoverFrameTop , canvas_key ) :
2015-06-17 20:01:41 +00:00
2020-03-25 21:15:57 +00:00
CanvasHoverFrame . __init__ ( self , parent , my_canvas , canvas_key )
2015-06-17 20:01:41 +00:00
2020-08-05 20:10:36 +00:00
self . _top_hover = top_hover
2019-11-14 03:56:30 +00:00
vbox = QP . VBoxLayout ( )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
self . _icon_panel = QW . QWidget ( self )
2015-06-17 20:01:41 +00:00
2020-03-11 21:52:11 +00:00
self . _trash_icon = ClientGUICommon . BufferedWindowIcon ( self . _icon_panel , CC . global_pixmaps ( ) . trash )
2020-05-06 21:31:41 +00:00
self . _inbox_icon = ClientGUICommon . BufferedWindowIcon ( self . _icon_panel , CC . global_pixmaps ( ) . inbox , click_callable = self . _Archive )
self . _notes_icon = ClientGUICommon . BufferedWindowIcon ( self . _icon_panel , CC . global_pixmaps ( ) . notes , click_callable = self . _EditNotes )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
icon_hbox = QP . HBoxLayout ( spacing = 0 )
2015-06-17 20:01:41 +00:00
2020-07-22 20:59:16 +00:00
icon_hbox . addStretch ( 1 )
2020-07-29 20:52:44 +00:00
QP . AddToLayout ( icon_hbox , self . _inbox_icon , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( icon_hbox , self . _trash_icon , CC . FLAGS_CENTER_PERPENDICULAR )
QP . AddToLayout ( icon_hbox , self . _notes_icon , CC . FLAGS_CENTER_PERPENDICULAR )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
self . _icon_panel . setLayout ( icon_hbox )
2015-06-17 20:01:41 +00:00
# repo strings
2019-11-14 03:56:30 +00:00
self . _file_repos = QP . MakeQLabelWithAlignment ( ' ' , self , QC . Qt . AlignRight | QC . Qt . AlignVCenter )
2015-06-17 20:01:41 +00:00
2017-04-26 21:58:12 +00:00
# urls
self . _last_seen_urls = [ ]
2019-11-14 03:56:30 +00:00
self . _urls_vbox = QP . VBoxLayout ( )
2017-04-26 21:58:12 +00:00
2015-06-17 20:01:41 +00:00
# likes
2019-11-14 03:56:30 +00:00
like_hbox = QP . HBoxLayout ( spacing = 0 )
2015-06-17 20:01:41 +00:00
2020-03-11 21:52:11 +00:00
like_services = HG . client_controller . services_manager . GetServices ( ( HC . LOCAL_RATING_LIKE , ) )
2015-06-17 20:01:41 +00:00
2018-08-15 20:40:30 +00:00
if len ( like_services ) > 0 :
2020-07-22 20:59:16 +00:00
like_hbox . addStretch ( 1 )
2018-08-15 20:40:30 +00:00
2015-06-17 20:01:41 +00:00
for service in like_services :
service_key = service . GetServiceKey ( )
2020-03-25 21:15:57 +00:00
control = RatingLikeCanvas ( self , service_key , canvas_key )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
QP . AddToLayout ( like_hbox , control , CC . FLAGS_NONE )
2015-06-17 20:01:41 +00:00
# each numerical one in turn
2019-11-14 03:56:30 +00:00
QP . AddToLayout ( vbox , like_hbox , CC . FLAGS_EXPAND_SIZER_BOTH_WAYS )
2015-06-17 20:01:41 +00:00
2020-03-11 21:52:11 +00:00
numerical_services = HG . client_controller . services_manager . GetServices ( ( HC . LOCAL_RATING_NUMERICAL , ) )
2015-06-17 20:01:41 +00:00
for service in numerical_services :
service_key = service . GetServiceKey ( )
2020-03-25 21:15:57 +00:00
control = RatingNumericalCanvas ( self , service_key , canvas_key )
2015-06-17 20:01:41 +00:00
2020-07-22 20:59:16 +00:00
QP . AddToLayout ( vbox , control , CC . FLAGS_NONE )
2015-06-17 20:01:41 +00:00
2020-07-22 20:59:16 +00:00
vbox . setAlignment ( control , QC . Qt . AlignRight )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
QP . AddToLayout ( vbox , self . _icon_panel , CC . FLAGS_EXPAND_SIZER_PERPENDICULAR )
QP . AddToLayout ( vbox , self . _file_repos , CC . FLAGS_EXPAND_PERPENDICULAR )
QP . AddToLayout ( vbox , self . _urls_vbox , CC . FLAGS_EXPAND_SIZER_PERPENDICULAR )
2017-05-10 21:33:58 +00:00
2019-11-14 03:56:30 +00:00
self . setLayout ( vbox )
2015-06-17 20:01:41 +00:00
self . _ResetData ( )
2017-05-10 21:33:58 +00:00
HG . client_controller . sub ( self , ' ProcessContentUpdates ' , ' content_updates_gui ' )
2015-09-16 18:11:00 +00:00
2015-06-17 20:01:41 +00:00
2020-05-06 21:31:41 +00:00
def _Archive ( self ) :
if self . _current_media . HasInbox ( ) :
2021-08-25 21:59:05 +00:00
command = CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_ARCHIVE_FILE )
2020-05-06 21:31:41 +00:00
else :
2021-08-25 21:59:05 +00:00
command = CAC . ApplicationCommand . STATICCreateSimpleCommand ( CAC . SIMPLE_INBOX_FILE )
2020-05-06 21:31:41 +00:00
HG . client_controller . pub ( ' canvas_application_command ' , command , self . _canvas_key )
def _EditNotes ( self ) :
HG . client_controller . pub ( ' canvas_manage_notes ' , self . _canvas_key )
2015-06-17 20:01:41 +00:00
def _GetIdealSizeAndPosition ( self ) :
2019-11-14 03:56:30 +00:00
parent_window = self . parentWidget ( ) . window ( )
2015-06-17 20:01:41 +00:00
2020-02-26 22:28:52 +00:00
parent_size = parent_window . size ( )
parent_width = parent_size . width ( )
2015-06-17 20:01:41 +00:00
2020-02-26 22:28:52 +00:00
my_size = self . size ( )
my_width = my_size . width ( )
my_height = my_size . height ( )
2015-06-17 20:01:41 +00:00
2020-08-19 22:38:20 +00:00
# don't use .rect() here, it (sometimes) isn't updated on a hidden window until next show, I think
top_hover_bottom_right = QC . QPoint ( self . _top_hover . x ( ) + self . _top_hover . width ( ) , self . _top_hover . y ( ) + self . _top_hover . height ( ) )
width_beside_top_hover = ClientGUIFunctions . ClientToScreen ( parent_window , parent_window . rect ( ) . topRight ( ) ) . x ( ) - top_hover_bottom_right . x ( )
2020-08-05 20:10:36 +00:00
my_ideal_width = max ( self . sizeHint ( ) . width ( ) , width_beside_top_hover )
2015-06-17 20:01:41 +00:00
2020-07-22 20:59:16 +00:00
my_ideal_height = self . sizeHint ( ) . height ( )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
should_resize = my_ideal_width != my_width or my_ideal_height != my_height
2020-02-26 22:28:52 +00:00
ideal_size = QC . QSize ( my_ideal_width , my_ideal_height )
2020-08-05 20:10:36 +00:00
2020-02-26 22:28:52 +00:00
ideal_position = ClientGUIFunctions . ClientToScreen ( parent_window , QC . QPoint ( int ( parent_width - my_ideal_width ) , 0 ) )
2015-06-17 20:01:41 +00:00
2020-08-05 20:10:36 +00:00
if top_hover_bottom_right . x ( ) > ideal_position . x ( ) :
ideal_position . setY ( top_hover_bottom_right . y ( ) )
2020-02-26 22:28:52 +00:00
return ( should_resize , ideal_size , ideal_position )
2015-06-17 20:01:41 +00:00
def _ResetData ( self ) :
if self . _current_media is not None :
2015-07-08 21:45:38 +00:00
has_inbox = self . _current_media . HasInbox ( )
2021-04-28 21:43:16 +00:00
has_trash = self . _current_media . GetLocationsManager ( ) . IsTrashed ( )
2020-05-06 21:31:41 +00:00
has_notes = self . _current_media . HasNotes ( )
2015-07-08 21:45:38 +00:00
2020-05-06 21:31:41 +00:00
if has_inbox or has_trash or has_notes :
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
self . _icon_panel . show ( )
2015-06-17 20:01:41 +00:00
2015-07-08 21:45:38 +00:00
if has_inbox :
2019-11-14 03:56:30 +00:00
self . _inbox_icon . show ( )
2015-07-08 21:45:38 +00:00
else :
2019-11-14 03:56:30 +00:00
self . _inbox_icon . hide ( )
2015-07-08 21:45:38 +00:00
if has_trash :
2019-11-14 03:56:30 +00:00
self . _trash_icon . show ( )
2015-07-08 21:45:38 +00:00
else :
2019-11-14 03:56:30 +00:00
self . _trash_icon . hide ( )
2015-07-08 21:45:38 +00:00
2020-05-06 21:31:41 +00:00
if has_notes :
self . _notes_icon . show ( )
else :
self . _notes_icon . hide ( )
2015-06-17 20:01:41 +00:00
else :
2019-11-14 03:56:30 +00:00
self . _icon_panel . setVisible ( False )
2015-06-17 20:01:41 +00:00
2016-02-24 21:42:54 +00:00
remote_strings = self . _current_media . GetLocationsManager ( ) . GetRemoteLocationStrings ( )
2015-06-17 20:01:41 +00:00
2016-02-24 21:42:54 +00:00
if len ( remote_strings ) == 0 :
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
self . _file_repos . hide ( )
2015-06-17 20:01:41 +00:00
else :
2016-02-24 21:42:54 +00:00
remote_string = os . linesep . join ( remote_strings )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
self . _file_repos . setText ( remote_string )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
self . _file_repos . show ( )
2015-06-17 20:01:41 +00:00
2017-04-26 21:58:12 +00:00
# urls
urls = self . _current_media . GetLocationsManager ( ) . GetURLs ( )
if urls != self . _last_seen_urls :
self . _last_seen_urls = list ( urls )
2019-12-05 05:29:32 +00:00
QP . ClearLayout ( self . _urls_vbox , delete_widgets = True )
2017-04-26 21:58:12 +00:00
2017-12-06 22:06:56 +00:00
url_tuples = HG . client_controller . network_engine . domain_manager . ConvertURLsToMediaViewerTuples ( urls )
for ( display_string , url ) in url_tuples :
2017-04-26 21:58:12 +00:00
2018-08-29 20:20:41 +00:00
link = ClientGUICommon . BetterHyperLink ( self , display_string , url )
2017-09-20 19:47:31 +00:00
2020-07-22 20:59:16 +00:00
link . setAlignment ( QC . Qt . AlignRight )
2019-12-05 05:29:32 +00:00
2020-07-22 20:59:16 +00:00
QP . AddToLayout ( self . _urls_vbox , link , CC . FLAGS_EXPAND_PERPENDICULAR )
2019-12-05 05:29:32 +00:00
2015-06-17 20:01:41 +00:00
self . _SizeAndPosition ( )
2019-11-14 03:56:30 +00:00
def wheelEvent ( self , event ) :
2015-09-16 18:11:00 +00:00
2019-12-05 05:29:32 +00:00
QW . QApplication . sendEvent ( self . parentWidget ( ) , event )
2015-09-16 18:11:00 +00:00
2015-06-17 20:01:41 +00:00
def ProcessContentUpdates ( self , service_keys_to_content_updates ) :
if self . _current_media is not None :
my_hash = self . _current_media . GetHash ( )
do_redraw = False
2021-04-28 21:43:16 +00:00
for ( service_key , content_updates ) in service_keys_to_content_updates . items ( ) :
2015-06-17 20:01:41 +00:00
2017-07-27 00:47:13 +00:00
# ratings updates do not change the shape of this hover but file changes of several kinds do
if True in ( my_hash in content_update . GetHashes ( ) for content_update in content_updates if content_update . GetDataType ( ) == HC . CONTENT_TYPE_FILES ) :
2015-06-17 20:01:41 +00:00
2017-05-10 21:33:58 +00:00
do_redraw = True
break
2015-06-17 20:01:41 +00:00
if do_redraw :
self . _ResetData ( )
def SetDisplayMedia ( self , canvas_key , media ) :
if canvas_key == self . _canvas_key :
2020-03-25 21:15:57 +00:00
CanvasHoverFrame . SetDisplayMedia ( self , canvas_key , media )
2015-06-17 20:01:41 +00:00
self . _ResetData ( )
2015-07-15 20:28:26 +00:00
2020-07-22 20:59:16 +00:00
# size is not immediately updated without this
2019-12-11 23:18:37 +00:00
self . layout ( ) . activate ( )
self . _SizeAndPosition ( force = True )
2015-07-15 20:28:26 +00:00
2017-04-19 20:58:30 +00:00
2020-03-25 21:15:57 +00:00
class CanvasHoverFrameTags ( CanvasHoverFrame ) :
2015-06-17 20:01:41 +00:00
2020-08-05 20:10:36 +00:00
def __init__ ( self , parent , my_canvas , top_hover : CanvasHoverFrameTop , canvas_key ) :
2015-06-17 20:01:41 +00:00
2020-03-25 21:15:57 +00:00
CanvasHoverFrame . __init__ ( self , parent , my_canvas , canvas_key )
2015-06-17 20:01:41 +00:00
2020-08-05 20:10:36 +00:00
self . _top_hover = top_hover
2019-11-14 03:56:30 +00:00
vbox = QP . VBoxLayout ( )
2015-06-17 20:01:41 +00:00
2020-03-25 21:15:57 +00:00
self . _tags = ClientGUIListBoxes . ListBoxTagsMediaHoverFrame ( self , self . _canvas_key )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
QP . AddToLayout ( vbox , self . _tags , CC . FLAGS_EXPAND_SIZER_BOTH_WAYS )
2015-06-17 20:01:41 +00:00
2019-11-14 03:56:30 +00:00
self . setLayout ( vbox )
2015-06-17 20:01:41 +00:00
2017-05-10 21:33:58 +00:00
HG . client_controller . sub ( self , ' ProcessContentUpdates ' , ' content_updates_gui ' )
2015-06-17 20:01:41 +00:00
def _GetIdealSizeAndPosition ( self ) :
2019-11-14 03:56:30 +00:00
parent_window = self . parentWidget ( ) . window ( )
2015-06-17 20:01:41 +00:00
2020-02-26 22:28:52 +00:00
parent_size = parent_window . size ( )
parent_width = parent_size . width ( )
parent_height = parent_size . height ( )
my_size = self . size ( )
2015-06-17 20:01:41 +00:00
2020-02-26 22:28:52 +00:00
my_width = my_size . width ( )
my_height = my_size . height ( )
2015-06-17 20:01:41 +00:00
my_ideal_width = int ( parent_width * 0.2 )
my_ideal_height = parent_height
should_resize = my_ideal_width != my_width or my_ideal_height != my_height
2020-02-26 22:28:52 +00:00
ideal_size = QC . QSize ( my_ideal_width , my_ideal_height )
ideal_position = ClientGUIFunctions . ClientToScreen ( parent_window , QC . QPoint ( 0 , 0 ) )
2015-06-17 20:01:41 +00:00
2020-02-26 22:28:52 +00:00
return ( should_resize , ideal_size , ideal_position )
2015-06-17 20:01:41 +00:00
def _ResetTags ( self ) :
2015-10-28 21:29:05 +00:00
if self . _current_media is not None :
2015-06-17 20:01:41 +00:00
2020-03-25 21:15:57 +00:00
self . _tags . SetTagsByMedia ( [ self . _current_media ] )
2015-06-17 20:01:41 +00:00
def ProcessContentUpdates ( self , service_keys_to_content_updates ) :
if self . _current_media is not None :
my_hash = self . _current_media . GetHash ( )
do_redraw = False
2021-04-28 21:43:16 +00:00
for ( service_key , content_updates ) in service_keys_to_content_updates . items ( ) :
2015-06-17 20:01:41 +00:00
if True in ( my_hash in content_update . GetHashes ( ) for content_update in content_updates ) :
do_redraw = True
break
if do_redraw :
self . _ResetTags ( )
def SetDisplayMedia ( self , canvas_key , media ) :
if canvas_key == self . _canvas_key :
2020-03-25 21:15:57 +00:00
CanvasHoverFrame . SetDisplayMedia ( self , canvas_key , media )
2015-06-17 20:01:41 +00:00
self . _ResetTags ( )
2016-12-07 22:12:52 +00:00