hydrus/include/ClientGUIHoverFrames.py

1071 lines
41 KiB
Python

import ClientConstants as CC
import ClientData
import ClientDragDrop
import ClientGUICanvas
import ClientGUICommon
import ClientGUIDialogs
import ClientGUIListBoxes
import ClientGUITopLevelWindows
import ClientGUIScrolledPanelsEdit
import ClientGUIScrolledPanelsManagement
import ClientMedia
import HydrusConstants as HC
import HydrusData
import HydrusGlobals as HG
import HydrusSerialisable
import urlparse
import os
import wx
import wx.adv
class FullscreenHoverFrame( wx.Frame ):
def __init__( self, parent, canvas_key ):
if HC.PLATFORM_WINDOWS:
border_style = wx.BORDER_RAISED
else:
border_style = wx.BORDER_SIMPLE
wx.Frame.__init__( self, parent, style = wx.FRAME_TOOL_WINDOW | wx.FRAME_NO_TASKBAR | wx.FRAME_FLOAT_ON_PARENT | border_style )
self._canvas_key = canvas_key
self._current_media = None
self._last_ideal_position = None
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_FRAMEBK ) )
self.SetCursor( wx.Cursor( wx.CURSOR_ARROW ) )
self._hide_until = None
HG.client_controller.sub( self, 'SetDisplayMedia', 'canvas_new_display_media' )
HG.client_controller.gui.RegisterUIUpdateWindow( self )
def _GetIdealSizeAndPosition( self ):
raise NotImplementedError()
def _SizeAndPosition( self ):
if self.GetParent().IsShown(): # Can't ClientToScreen if not shown, like in init
( should_resize, my_ideal_size, my_ideal_position ) = self._GetIdealSizeAndPosition()
if should_resize:
self.Fit()
self.SetSize( my_ideal_size )
self.SetPosition( my_ideal_position )
def SetDisplayMedia( self, canvas_key, media ):
if canvas_key == self._canvas_key:
self._current_media = media
def TIMERUIUpdate( self ):
new_options = HG.client_controller.new_options
if new_options.GetBoolean( 'always_show_hover_windows' ):
self._SizeAndPosition()
self.Show()
return
if self._hide_until is not None:
if HydrusData.TimeHasPassed( self._hide_until ):
self._hide_until = None
else:
return
if self._current_media is None or not self.GetParent().IsShown(): # Can't ClientToScreen if not shown, like in init
if self.IsShown():
if HG.hover_window_report_mode:
HydrusData.ShowText( repr( self ) + ' - hiding because nothing to show or parent hidden.' )
self.Hide()
else:
( mouse_x, mouse_y ) = wx.GetMousePosition()
( my_width, my_height ) = self.GetSize()
( should_resize, ( my_ideal_width, my_ideal_height ), ( my_ideal_x, my_ideal_y ) ) = self._GetIdealSizeAndPosition()
if my_ideal_width == -1:
my_ideal_width = max( my_width, 50 )
if my_ideal_height == -1:
my_ideal_height = max( my_height, 50 )
( my_x, my_y ) = self.GetPosition()
in_ideal_x = my_ideal_x <= mouse_x and mouse_x <= my_ideal_x + my_ideal_width
in_ideal_y = my_ideal_y <= mouse_y and mouse_y <= my_ideal_y + my_ideal_height
in_actual_x = my_x <= mouse_x and mouse_x <= my_x + my_width
in_actual_y = my_y <= mouse_y and mouse_y <= my_y + my_height
# we test both ideal and actual here because setposition is not always honoured by the OS
# for instance, in Linux on a fullscreen view, the top taskbar is hidden, but when hover window is shown, it takes focus and causes taskbar to reappear
# 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 )
menu_open = HG.client_controller.MenuIsOpen()
dialog_open = False
tlps = wx.GetTopLevelWindows()
for tlp in tlps:
if isinstance( tlp, wx.Dialog ):
dialog_open = True
mime = self._current_media.GetMime()
mouse_is_over_interactable_media = mime == HC.APPLICATION_FLASH and self.GetParent().MouseIsOverMedia()
mouse_is_near_animation_bar = self.GetParent().MouseIsNearAnimationBar()
mouse_is_over_something_important = mouse_is_over_interactable_media or mouse_is_near_animation_bar
focus_is_good = ClientGUICommon.TLPHasFocus( self ) or ClientGUICommon.TLPHasFocus( self.GetParent() )
ready_to_show = in_position and not mouse_is_over_something_important and focus_is_good and not dialog_open and not menu_open
ready_to_hide = not menu_open and ( not in_position or dialog_open or not focus_is_good )
def get_logic_report_string():
tuples = []
tuples.append( ( 'in position: ', in_position ) )
tuples.append( ( 'menu open: ', menu_open ) )
tuples.append( ( 'dialog open: ', dialog_open ) )
tuples.append( ( 'mouse over interactable media: ', mouse_is_over_interactable_media ) )
tuples.append( ( 'mouse near animation bar: ', mouse_is_near_animation_bar ) )
tuples.append( ( 'focus is good: ', focus_is_good ) )
message = os.linesep * 2 + os.linesep.join( ( a + str( b ) for ( a, b ) in tuples ) ) + os.linesep
return message
if ready_to_show:
self._SizeAndPosition()
if not self.IsShown():
if HG.hover_window_report_mode:
HydrusData.ShowText( repr( self ) + ' - showing.' + get_logic_report_string() )
self.Show()
elif ready_to_hide:
if self.IsShown():
if HG.hover_window_report_mode:
HydrusData.ShowText( repr( self ) + ' - hiding.' + get_logic_report_string() )
self.Hide()
class FullscreenHoverFrameTop( FullscreenHoverFrame ):
def __init__( self, parent, canvas_key ):
FullscreenHoverFrame.__init__( self, parent, canvas_key )
self._current_zoom = 1.0
self._current_index_string = ''
self._top_hbox = wx.BoxSizer( wx.HORIZONTAL )
self._title_text = ClientGUICommon.BetterStaticText( self, 'title' )
self._info_text = ClientGUICommon.BetterStaticText( self, 'info' )
self._additional_info_text = ClientGUICommon.BetterStaticText( self, '', style = wx.ALIGN_CENTER )
self._button_hbox = wx.BoxSizer( wx.HORIZONTAL )
self._PopulateLeftButtons()
self._top_hbox.Add( ( 20, 20 ), CC.FLAGS_EXPAND_BOTH_WAYS )
self._PopulateCenterButtons()
self._top_hbox.Add( ( 20, 20 ), CC.FLAGS_EXPAND_BOTH_WAYS )
self._PopulateRightButtons()
vbox = wx.BoxSizer( wx.VERTICAL )
vbox.Add( self._top_hbox, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.Add( self._title_text, CC.FLAGS_CENTER )
vbox.Add( self._info_text, CC.FLAGS_CENTER )
vbox.Add( self._additional_info_text, CC.FLAGS_CENTER )
vbox.Add( self._button_hbox, CC.FLAGS_CENTER )
self.SetSizer( vbox )
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' )
self.Bind( wx.EVT_MOUSEWHEEL, self.EventMouseWheel )
def _Archive( self ):
if self._current_media.HasInbox():
command = ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'archive_file' )
else:
command = ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'inbox_file' )
HG.client_controller.pub( 'canvas_application_command', command, self._canvas_key )
def _GetIdealSizeAndPosition( self ):
parent = self.GetParent()
( parent_width, parent_height ) = parent.GetClientSize()
( my_width, my_height ) = self.GetSize()
my_ideal_width = int( parent_width * 0.6 )
should_resize = my_ideal_width != my_width
ideal_size = ( my_ideal_width, -1 )
ideal_position = parent.ClientToScreen( ( int( parent_width * 0.2 ), 0 ) )
return ( should_resize, ideal_size, ideal_position )
def _ManageShortcuts( self ):
with ClientGUITopLevelWindows.DialogManage( self, 'manage shortcuts' ) as dlg:
panel = ClientGUIScrolledPanelsManagement.ManageShortcutsPanel( dlg )
dlg.SetPanel( panel )
dlg.ShowModal()
def _PopulateCenterButtons( self ):
self._archive_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.archive, self._Archive )
self._trash_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.delete, HG.client_controller.pub, 'canvas_delete', self._canvas_key )
self._trash_button.SetToolTip( 'send to trash' )
self._delete_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.trash_delete, HG.client_controller.pub, 'canvas_delete', self._canvas_key )
self._delete_button.SetToolTip( 'delete completely' )
self._undelete_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.undelete, HG.client_controller.pub, 'canvas_undelete', self._canvas_key )
self._undelete_button.SetToolTip( 'undelete' )
self._top_hbox.Add( self._archive_button, CC.FLAGS_VCENTER )
self._top_hbox.Add( self._trash_button, CC.FLAGS_VCENTER )
self._top_hbox.Add( self._delete_button, CC.FLAGS_VCENTER )
self._top_hbox.Add( self._undelete_button, CC.FLAGS_VCENTER )
def _PopulateLeftButtons( self ):
self._index_text = ClientGUICommon.BetterStaticText( self, 'index' )
self._top_hbox.Add( self._index_text, CC.FLAGS_VCENTER )
def _PopulateRightButtons( self ):
self._zoom_text = ClientGUICommon.BetterStaticText( self, 'zoom' )
zoom_in = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.zoom_in, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'zoom_in' ), self._canvas_key )
zoom_in.SetToolTip( 'zoom in' )
zoom_out = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.zoom_out, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'zoom_out' ), self._canvas_key )
zoom_out.SetToolTip( 'zoom out' )
zoom_switch = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.zoom_switch, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'switch_between_100_percent_and_canvas_zoom' ), self._canvas_key )
zoom_switch.SetToolTip( 'zoom switch' )
menu_items = []
menu_items.append( ( 'normal', 'edit shortcuts', 'edit your sets of shortcuts, and change what shortcuts are currently active on this media viewer', self._ManageShortcuts ) )
menu_items.append( ( 'normal', 'set current shortcuts', 'change which custom shortcuts are active on this media viewers', HydrusData.Call( HG.client_controller.pub, 'edit_media_viewer_custom_shortcuts', self._canvas_key ) ) )
menu_items.append( ( 'normal', 'set default shortcuts', 'change which custom shortcuts are typically active on new media viewers', self._SetDefaultShortcuts ) )
shortcuts = ClientGUICommon.MenuBitmapButton( self, CC.GlobalBMPs.keyboard, menu_items )
shortcuts.SetToolTip( 'shortcuts' )
fullscreen_switch = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.fullscreen_switch, HG.client_controller.pub, 'canvas_fullscreen_switch', self._canvas_key )
fullscreen_switch.SetToolTip( 'fullscreen switch' )
open_externally = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.open_externally, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'open_file_in_external_program' ), self._canvas_key )
open_externally.SetToolTip( 'open externally' )
drag_button = wx.BitmapButton( self, bitmap = CC.GlobalBMPs.drag )
drag_button.SetToolTip( 'drag from here to export file' )
drag_button.Bind( wx.EVT_LEFT_DOWN, self.EventDragButton )
close = ClientGUICommon.BetterButton( self, 'X', HG.client_controller.pub, 'canvas_close', self._canvas_key )
close.SetToolTip( 'close' )
self._top_hbox.Add( self._zoom_text, CC.FLAGS_VCENTER )
self._top_hbox.Add( zoom_in, CC.FLAGS_VCENTER )
self._top_hbox.Add( zoom_out, CC.FLAGS_VCENTER )
self._top_hbox.Add( zoom_switch, CC.FLAGS_VCENTER )
self._top_hbox.Add( shortcuts, CC.FLAGS_VCENTER )
self._top_hbox.Add( fullscreen_switch, CC.FLAGS_VCENTER )
self._top_hbox.Add( open_externally, CC.FLAGS_VCENTER )
self._top_hbox.Add( drag_button, CC.FLAGS_VCENTER )
self._top_hbox.Add( close, CC.FLAGS_VCENTER )
def _ResetArchiveButton( self ):
if self._current_media.HasInbox():
ClientGUICommon.SetBitmapButtonBitmap( self._archive_button, CC.GlobalBMPs.archive )
self._archive_button.SetToolTip( 'archive' )
else:
ClientGUICommon.SetBitmapButtonBitmap( self._archive_button, CC.GlobalBMPs.to_inbox )
self._archive_button.SetToolTip( 'return to inbox' )
def _ResetButtons( self ):
if self._current_media is not None:
self._ResetArchiveButton()
current_locations = self._current_media.GetLocationsManager().GetCurrent()
if CC.LOCAL_FILE_SERVICE_KEY in current_locations:
self._trash_button.Show()
self._delete_button.Hide()
self._undelete_button.Hide()
elif CC.TRASH_SERVICE_KEY in current_locations:
self._trash_button.Hide()
self._delete_button.Show()
self._undelete_button.Show()
self.Fit()
self._SizeAndPosition()
def _ResetText( self ):
if self._current_media is None:
self._title_text.Hide()
self._info_text.Hide()
else:
label = self._current_media.GetTitleString()
if len( label ) > 0:
self._title_text.SetLabelText( label )
self._title_text.Show()
else: self._title_text.Hide()
lines = self._current_media.GetPrettyInfoLines()
label = ' | '.join( lines )
self._info_text.SetLabelText( label )
self._info_text.Show()
if self._additional_info_text.GetLabelText() == '':
self._additional_info_text.Hide()
else:
self._additional_info_text.Show()
def _SetDefaultShortcuts( self ):
new_options = HG.client_controller.new_options
default_media_viewer_custom_shortcuts = new_options.GetStringList( 'default_media_viewer_custom_shortcuts' )
all_shortcut_names = HG.client_controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_SHORTCUTS )
custom_shortcuts_names = [ name for name in all_shortcut_names if name not in CC.SHORTCUTS_RESERVED_NAMES ]
if len( custom_shortcuts_names ) == 0:
wx.MessageBox( 'You have no custom shortcuts set up, so you cannot choose any!' )
return
with ClientGUITopLevelWindows.DialogEdit( self, 'choose shortcuts' ) as dlg:
choice_tuples = [ ( name, name, name in default_media_viewer_custom_shortcuts ) for name in custom_shortcuts_names ]
panel = ClientGUIScrolledPanelsEdit.EditChooseMultiple( dlg, choice_tuples )
dlg.SetPanel( panel )
if dlg.ShowModal() == wx.ID_OK:
new_default_media_viewer_custom_shortcuts = panel.GetValue()
new_options.SetStringList( 'default_media_viewer_custom_shortcuts', new_default_media_viewer_custom_shortcuts )
def EventDragButton( self, event ):
if self._current_media is None:
event.Skip()
return
page_key = None
media = [ self._current_media ]
cmd_down = event.CmdDown()
result = ClientDragDrop.DoFileExportDragDrop( self, page_key, media, cmd_down )
if result not in ( wx.DragError, wx.DragNone ):
HG.client_controller.pub( 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'pause_media' ), self._canvas_key )
def EventMouseWheel( self, event ):
event.ResumePropagation( 1 )
event.Skip()
def ProcessContentUpdates( self, service_keys_to_content_updates ):
if self._current_media is not None:
my_hash = self._current_media.GetHash()
do_redraw = False
for ( service_key, content_updates ) in service_keys_to_content_updates.items():
if True in ( my_hash in content_update.GetHashes() for content_update in content_updates ):
do_redraw = True
break
if do_redraw:
self._ResetButtons()
def SetCurrentZoom( self, canvas_key, zoom ):
if canvas_key == self._canvas_key:
self._current_zoom = zoom
label = ClientData.ConvertZoomToPercentage( self._current_zoom )
self._zoom_text.SetLabelText( label )
self._top_hbox.Layout()
def SetDisplayMedia( self, canvas_key, media ):
if canvas_key == self._canvas_key:
FullscreenHoverFrame.SetDisplayMedia( self, canvas_key, media )
self._ResetText()
self._ResetButtons()
def SetIndexString( self, canvas_key, text ):
if canvas_key == self._canvas_key:
self._current_index_string = text
self._index_text.SetLabelText( self._current_index_string )
self._top_hbox.Layout()
class FullscreenHoverFrameTopArchiveDeleteFilter( FullscreenHoverFrameTop ):
def _Archive( self ):
HG.client_controller.pub( 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'archive_file' ), self._canvas_key )
def _PopulateLeftButtons( self ):
self._back_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.previous, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'archive_delete_filter_back' ), self._canvas_key )
self._back_button.SetToolTip( 'back' )
self._top_hbox.Add( self._back_button, CC.FLAGS_VCENTER )
FullscreenHoverFrameTop._PopulateLeftButtons( self )
self._skip_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.next, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'archive_delete_filter_skip' ), self._canvas_key )
self._skip_button.SetToolTip( 'skip' )
self._top_hbox.Add( self._skip_button, CC.FLAGS_VCENTER )
def _ResetArchiveButton( self ):
ClientGUICommon.SetBitmapButtonBitmap( self._archive_button, CC.GlobalBMPs.archive )
self._archive_button.SetToolTip( 'archive' )
class FullscreenHoverFrameTopNavigable( FullscreenHoverFrameTop ):
def _PopulateLeftButtons( self ):
self._previous_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.previous, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'view_previous' ), self._canvas_key )
self._previous_button.SetToolTip( 'previous' )
self._index_text = ClientGUICommon.BetterStaticText( self, 'index' )
self._next_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.next, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'view_next' ), self._canvas_key )
self._next_button.SetToolTip( 'next' )
self._top_hbox.Add( self._previous_button, CC.FLAGS_VCENTER )
self._top_hbox.Add( self._index_text, CC.FLAGS_VCENTER )
self._top_hbox.Add( self._next_button, CC.FLAGS_VCENTER )
class FullscreenHoverFrameTopDuplicatesFilter( FullscreenHoverFrameTopNavigable ):
def __init__( self, parent, canvas_key ):
FullscreenHoverFrameTopNavigable.__init__( self, parent, canvas_key )
HG.client_controller.sub( self, 'SetDuplicatePair', 'canvas_new_duplicate_pair' )
def _PopulateCenterButtons( self ):
menu_items = []
menu_items.append( ( 'normal', 'edit duplicate action 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 action options for \'same quality\'', 'edit what content is merged when you filter files', HydrusData.Call( self._EditMergeOptions, HC.DUPLICATE_SAME_QUALITY ) ) )
menu_items.append( ( 'normal', 'edit duplicate action options for \'alternates\'', 'edit what content is merged when you filter files', HydrusData.Call( self._EditMergeOptions, HC.DUPLICATE_ALTERNATE ) ) )
menu_items.append( ( 'normal', 'edit duplicate action options for \'not duplicates\'', 'edit what content is merged when you filter files', HydrusData.Call( self._EditMergeOptions, HC.DUPLICATE_NOT_DUPLICATE ) ) )
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 ) )
cog_button = ClientGUICommon.MenuBitmapButton( self, CC.GlobalBMPs.cog, menu_items )
self._top_hbox.Add( cog_button, CC.FLAGS_SIZER_VCENTER )
FullscreenHoverFrameTopNavigable._PopulateCenterButtons( self )
dupe_commands = []
dupe_commands.append( ( 'this is better', 'Set that the current file you are looking at is better than the other in the pair.', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'duplicate_filter_this_is_better' ) ) )
dupe_commands.append( ( 'same quality', 'Set that the two files are duplicates of very similar quality.', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'duplicate_filter_exactly_the_same' ) ) )
dupe_commands.append( ( '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.', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'duplicate_filter_alternates' ) ) )
dupe_commands.append( ( 'not duplicates', 'Set that the files are not duplicates or otherwise related--that this pair is a false-positive match.', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'duplicate_filter_not_dupes' ) ) )
dupe_commands.append( ( 'custom action', 'Choose one of the other actions but customise the merge and delete options for this specific decision.', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'duplicate_filter_custom_action' ) ) )
for ( label, tooltip, command ) in dupe_commands:
command_button = ClientGUICommon.BetterButton( self, label, HG.client_controller.pub, 'canvas_application_command', command, self._canvas_key )
command_button.SetToolTip( tooltip )
self._button_hbox.Add( command_button, CC.FLAGS_VCENTER )
def _EditBackgroundSwitchIntensity( self ):
new_options = HG.client_controller.new_options
value = new_options.GetNoneableInteger( 'duplicate_background_switch_intensity' )
with ClientGUITopLevelWindows.DialogEdit( self, 'edit lighten/darken intensity' ) as dlg:
panel = ClientGUIScrolledPanelsEdit.EditNoneableIntegerPanel( dlg, value, message = 'intensity: ', none_phrase = 'do not change', min = 1, max = 9 )
dlg.SetPanel( panel )
if dlg.ShowModal() == wx.ID_OK:
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 )
with ClientGUITopLevelWindows.DialogEdit( self, 'edit duplicate merge options' ) as dlg:
panel = ClientGUIScrolledPanelsEdit.EditDuplicateActionOptionsPanel( dlg, duplicate_type, duplicate_action_options )
dlg.SetPanel( panel )
if dlg.ShowModal() == wx.ID_OK:
duplicate_action_options = panel.GetValue()
new_options.SetDuplicateActionOptions( duplicate_type, duplicate_action_options )
def _PopulateLeftButtons( self ):
self._first_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.first, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'duplicate_filter_back' ), self._canvas_key )
self._first_button.SetToolTip( 'go back a pair' )
self._top_hbox.Add( self._first_button, CC.FLAGS_VCENTER )
FullscreenHoverFrameTopNavigable._PopulateLeftButtons( self )
self._last_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.last, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'duplicate_filter_skip' ), self._canvas_key )
self._last_button.SetToolTip( 'show a different pair' )
self._top_hbox.Add( self._last_button, CC.FLAGS_VCENTER )
def SetDisplayMedia( self, canvas_key, media ):
if canvas_key == self._canvas_key:
if media is None:
self._additional_info_text.SetLabelText( '' )
FullscreenHoverFrameTopNavigable.SetDisplayMedia( self, canvas_key, media )
def SetDuplicatePair( self, canvas_key, shown_media, comparison_media ):
if canvas_key == self._canvas_key:
( statements, score ) = ClientMedia.GetDuplicateComparisonStatements( shown_media, comparison_media )
self._additional_info_text.SetLabelText( os.linesep.join( statements ) )
self._ResetText()
self._ResetButtons()
class FullscreenHoverFrameTopNavigableList( FullscreenHoverFrameTopNavigable ):
def _PopulateLeftButtons( self ):
self._first_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.first, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'view_first' ), self._canvas_key )
self._first_button.SetToolTip( 'first' )
self._top_hbox.Add( self._first_button, CC.FLAGS_VCENTER )
FullscreenHoverFrameTopNavigable._PopulateLeftButtons( self )
self._last_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalBMPs.last, HG.client_controller.pub, 'canvas_application_command', ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, 'view_last' ), self._canvas_key )
self._last_button.SetToolTip( 'last' )
self._top_hbox.Add( self._last_button, CC.FLAGS_VCENTER )
class FullscreenHoverFrameTopRight( FullscreenHoverFrame ):
def __init__( self, parent, canvas_key ):
FullscreenHoverFrame.__init__( self, parent, canvas_key )
vbox = wx.BoxSizer( wx.VERTICAL )
self._icon_panel = wx.Panel( self )
self._trash_icon = ClientGUICommon.BufferedWindowIcon( self._icon_panel, CC.GlobalBMPs.trash )
self._inbox_icon = ClientGUICommon.BufferedWindowIcon( self._icon_panel, CC.GlobalBMPs.inbox )
icon_hbox = wx.BoxSizer( wx.HORIZONTAL )
icon_hbox.Add( ( 16, 16 ), CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
icon_hbox.Add( self._trash_icon, CC.FLAGS_VCENTER )
icon_hbox.Add( self._inbox_icon, CC.FLAGS_VCENTER )
self._icon_panel.SetSizer( icon_hbox )
# repo strings
self._file_repos = wx.StaticText( self, label = '', style = wx.ALIGN_RIGHT )
# urls
self._last_seen_urls = []
self._urls_vbox = wx.BoxSizer( wx.VERTICAL )
# likes
like_hbox = wx.BoxSizer( wx.HORIZONTAL )
like_hbox.Add( ( 16, 16 ), CC.FLAGS_EXPAND_BOTH_WAYS )
like_services = HG.client_controller.services_manager.GetServices( ( HC.LOCAL_RATING_LIKE, ), randomised = False )
for service in like_services:
service_key = service.GetServiceKey()
control = ClientGUICommon.RatingLikeCanvas( self, service_key, canvas_key )
like_hbox.Add( control, CC.FLAGS_NONE )
# each numerical one in turn
vbox.Add( like_hbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
numerical_services = HG.client_controller.services_manager.GetServices( ( HC.LOCAL_RATING_NUMERICAL, ), randomised = False )
for service in numerical_services:
service_key = service.GetServiceKey()
control = ClientGUICommon.RatingNumericalCanvas( self, service_key, canvas_key )
hbox = wx.BoxSizer( wx.HORIZONTAL )
hbox.Add( ( 16, 16 ), CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
hbox.Add( control, CC.FLAGS_NONE )
vbox.Add( hbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
vbox.Add( self._icon_panel, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
vbox.Add( self._file_repos, CC.FLAGS_EXPAND_PERPENDICULAR )
vbox.Add( self._urls_vbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
self.SetSizer( vbox )
self._ResetData()
HG.client_controller.sub( self, 'ProcessContentUpdates', 'content_updates_gui' )
self.Bind( wx.EVT_MOUSEWHEEL, self.EventMouseWheel )
def _GetIdealSizeAndPosition( self ):
parent = self.GetParent()
( parent_width, parent_height ) = parent.GetClientSize()
( my_width, my_height ) = self.GetSize()
my_ideal_width = int( parent_width * 0.2 )
should_resize = my_ideal_width != my_width
ideal_size = ( my_ideal_width, -1 )
ideal_position = parent.ClientToScreen( ( int( parent_width * 0.8 ), 0 ) )
return ( should_resize, ideal_size, ideal_position )
def _ResetData( self ):
if self._current_media is not None:
has_inbox = self._current_media.HasInbox()
has_trash = CC.TRASH_SERVICE_KEY in self._current_media.GetLocationsManager().GetCurrent()
if has_inbox or has_trash:
self._icon_panel.Show()
if has_inbox:
self._inbox_icon.Show()
else:
self._inbox_icon.Hide()
if has_trash:
self._trash_icon.Show()
else:
self._trash_icon.Hide()
else:
self._icon_panel.Hide()
remote_strings = self._current_media.GetLocationsManager().GetRemoteLocationStrings()
if len( remote_strings ) == 0:
self._file_repos.Hide()
else:
remote_string = os.linesep.join( remote_strings )
self._file_repos.SetLabelText( remote_string )
self._file_repos.Show()
# urls
urls = self._current_media.GetLocationsManager().GetURLs()
if urls != self._last_seen_urls:
self._last_seen_urls = list( urls )
self._urls_vbox.Clear( delete_windows = True )
url_tuples = HG.client_controller.network_engine.domain_manager.ConvertURLsToMediaViewerTuples( urls )
for ( display_string, url ) in url_tuples:
link = wx.adv.HyperlinkCtrl( self, id = -1, label = display_string, url = url )
link.SetToolTip( url )
self._urls_vbox.Add( link, CC.FLAGS_EXPAND_PERPENDICULAR )
self.Fit()
self._SizeAndPosition()
def EventMouseWheel( self, event ):
event.ResumePropagation( 1 )
event.Skip()
def ProcessContentUpdates( self, service_keys_to_content_updates ):
if self._current_media is not None:
my_hash = self._current_media.GetHash()
do_redraw = False
for ( service_key, content_updates ) in service_keys_to_content_updates.items():
# 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 ):
do_redraw = True
break
if do_redraw:
self._ResetData()
def SetDisplayMedia( self, canvas_key, media ):
if canvas_key == self._canvas_key:
FullscreenHoverFrame.SetDisplayMedia( self, canvas_key, media )
self._ResetData()
class FullscreenHoverFrameTags( FullscreenHoverFrame ):
def __init__( self, parent, canvas_key ):
FullscreenHoverFrame.__init__( self, parent, canvas_key )
vbox = wx.BoxSizer( wx.VERTICAL )
self._tags = ClientGUIListBoxes.ListBoxTagsSelectionHoverFrame( self, self._canvas_key )
vbox.Add( self._tags, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
self.SetSizer( vbox )
HG.client_controller.sub( self, 'ProcessContentUpdates', 'content_updates_gui' )
def _GetIdealSizeAndPosition( self ):
parent = self.GetParent()
( parent_width, parent_height ) = parent.GetClientSize()
( my_width, my_height ) = self.GetSize()
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
ideal_size = ( my_ideal_width, my_ideal_height )
ideal_position = parent.ClientToScreen( ( 0, 0 ) )
return ( should_resize, ideal_size, ideal_position )
def _ResetTags( self ):
if self._current_media is not None:
self._tags.SetTagsByMedia( [ self._current_media ], force_reload = True )
def ProcessContentUpdates( self, service_keys_to_content_updates ):
if self._current_media is not None:
my_hash = self._current_media.GetHash()
do_redraw = False
for ( service_key, content_updates ) in service_keys_to_content_updates.items():
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:
FullscreenHoverFrame.SetDisplayMedia( self, canvas_key, media )
self._ResetTags()