Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion hydrus/client/ClientConstants.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,9 @@
SORT_FILES_BY_AVERAGE_COLOUR_CHROMATICITY_GREEN_RED = 25
SORT_FILES_BY_AVERAGE_COLOUR_CHROMATICITY_BLUE_YELLOW = 26
SORT_FILES_BY_AVERAGE_COLOUR_HUE = 27
SORT_FILES_BY_SERIATION = 28
SORT_FILES_BY_SERIATION_TAGS = 29
SORT_FILES_BY_SERIATION_VISUAL_TAGS = 30

AVERAGE_COLOUR_FILE_SORTS = {
SORT_FILES_BY_AVERAGE_COLOUR_LIGHTNESS,
Expand Down Expand Up @@ -415,7 +418,10 @@
SORT_FILES_BY_AVERAGE_COLOUR_CHROMATIC_MAGNITUDE,
SORT_FILES_BY_AVERAGE_COLOUR_CHROMATICITY_GREEN_RED,
SORT_FILES_BY_AVERAGE_COLOUR_CHROMATICITY_BLUE_YELLOW,
SORT_FILES_BY_AVERAGE_COLOUR_HUE
SORT_FILES_BY_AVERAGE_COLOUR_HUE,
SORT_FILES_BY_SERIATION,
SORT_FILES_BY_SERIATION_TAGS,
SORT_FILES_BY_SERIATION_VISUAL_TAGS
}

system_sort_type_submetatype_string_lookup = {
Expand All @@ -437,6 +443,9 @@
SORT_FILES_BY_AVERAGE_COLOUR_CHROMATICITY_GREEN_RED : 'average colour',
SORT_FILES_BY_AVERAGE_COLOUR_CHROMATICITY_BLUE_YELLOW : 'average colour',
SORT_FILES_BY_AVERAGE_COLOUR_HUE : 'average colour',
SORT_FILES_BY_SERIATION : 'file',
SORT_FILES_BY_SERIATION_TAGS : 'tags',
SORT_FILES_BY_SERIATION_VISUAL_TAGS : 'file',
SORT_FILES_BY_MIME : 'file',
SORT_FILES_BY_HAS_AUDIO : 'file',
SORT_FILES_BY_RANDOM : None,
Expand All @@ -461,6 +470,9 @@
SORT_FILES_BY_AVERAGE_COLOUR_CHROMATICITY_GREEN_RED : 'balance - green-red',
SORT_FILES_BY_AVERAGE_COLOUR_CHROMATICITY_BLUE_YELLOW : 'balance - blue-yellow',
SORT_FILES_BY_AVERAGE_COLOUR_HUE : 'hue',
SORT_FILES_BY_SERIATION : 'seriation (blurhash)',
SORT_FILES_BY_SERIATION_TAGS : 'seriation (tags)',
SORT_FILES_BY_SERIATION_VISUAL_TAGS : 'seriation (visual+tags)',
SORT_FILES_BY_RATIO : 'resolution ratio',
SORT_FILES_BY_WIDTH : 'width',
SORT_FILES_BY_APPROX_BITRATE : 'approximate bitrate',
Expand Down
10 changes: 10 additions & 0 deletions hydrus/client/ClientOptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ def _InitialiseDefaults( self ):
'media_viewer_recenter_media_on_window_resize': True,
'allow_blurhash_fallback' : True,
'fade_thumbnails' : True,
'thumbnail_masonry' : False,
'slideshow_always_play_duration_media_once_through' : False,
'enable_truncated_images_pil' : True,
'do_icc_profile_normalisation' : True,
Expand Down Expand Up @@ -316,6 +317,7 @@ def _InitialiseDefaults( self ):
'mpv_loop_playlist_instead_of_file' : False,
'draw_thumbnail_rating_background' : True,
'draw_thumbnail_numerical_ratings_collapsed_always' : False,
'draw_thumbnail_header' : True,
'show_destination_page_when_dnd_url' : True,
'confirm_non_empty_downloader_page_close' : True,
'confirm_all_page_closes' : False,
Expand Down Expand Up @@ -497,6 +499,7 @@ def _InitialiseDefaults( self ):
'thumbnail_border' : 1,
'thumbnail_margin' : 2,
'thumbnail_dpr_percent' : 100,
'thumbnail_zoom_percent' : 100,
'file_maintenance_idle_throttle_files' : 1,
'file_maintenance_idle_throttle_time_delta' : 2,
'file_maintenance_active_throttle_files' : 1,
Expand Down Expand Up @@ -553,6 +556,11 @@ def _InitialiseDefaults( self ):
'tag_list_tag_display_type_sidebar' : ClientTags.TAG_DISPLAY_SELECTION_LIST,
'tag_list_tag_display_type_media_viewer_hover' : ClientTags.TAG_DISPLAY_SINGLE_MEDIA,
'command_palette_num_chars_for_results_threshold' : 0,
'seriation_visual_bin_size' : 32,
'seriation_max_visual_candidates' : 200,
'seriation_max_tag_candidates' : 200,
'seriation_max_tag_keys' : 5,
'seriation_max_hybrid_candidates' : 250,
}

self._dictionary[ 'floats' ] = {
Expand All @@ -568,6 +576,8 @@ def _InitialiseDefaults( self ):
'dialog_rating_icon_size_px' : ClientGUIPainterShapes.SIZE.width(),
'dialog_rating_incdec_width_px' : ClientGUIPainterShapes.SIZE.width() * 2, #deprecated
'dialog_rating_incdec_height_px' : ClientGUIPainterShapes.SIZE.height(),
'seriation_visual_weight' : 0.7,
'seriation_tag_weight' : 0.3,
}

#
Expand Down
2 changes: 2 additions & 0 deletions hydrus/client/gui/canvas/ClientGUICanvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ def __init__( self, parent, location_context: ClientLocation.LocationContext ):
super().__init__( parent )

self.setObjectName( 'HydrusMediaViewer' )
self.setAttribute( QC.Qt.WidgetAttribute.WA_OpaquePaintEvent, True )

self.setSizePolicy( QW.QSizePolicy.Policy.Expanding, QW.QSizePolicy.Policy.Expanding )

Expand Down Expand Up @@ -857,6 +858,7 @@ def paintEvent( self, event ):
try:

painter = QG.QPainter( self )
painter.setClipRegion( event.region() )

self._DrawBackgroundBitmap( painter )

Expand Down
10 changes: 10 additions & 0 deletions hydrus/client/gui/canvas/ClientGUICanvasMedia.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,8 @@ def __init__( self, parent, canvas_type, background_colour_generator ):

super().__init__( parent )

self.setAttribute( QC.Qt.WidgetAttribute.WA_OpaquePaintEvent, True )

self._canvas_type = canvas_type
self._background_colour_generator = background_colour_generator

Expand Down Expand Up @@ -720,6 +722,7 @@ def paintEvent( self, event ):


painter = QG.QPainter( self )
painter.setClipRegion( event.region() )

if self._canvas_qt_pixmap is None:

Expand Down Expand Up @@ -990,6 +993,8 @@ def __init__( self, parent ):

super().__init__( parent )

self.setAttribute( QC.Qt.WidgetAttribute.WA_OpaquePaintEvent, True )

self._qss_colours = {
'hab_border' : QG.QColor( 0, 0, 0 ),
'hab_background' : QG.QColor( 240, 240, 240 ),
Expand Down Expand Up @@ -1328,6 +1333,7 @@ def paintEvent( self, event ):
try:

painter = QG.QPainter( self )
painter.setClipRegion( event.region() )

if self._CurrentMediaWindowIsBad() or self._next_draw_info is None:

Expand Down Expand Up @@ -3075,6 +3081,8 @@ def __init__( self, parent, background_colour_generator ):

super().__init__( parent )

self.setAttribute( QC.Qt.WidgetAttribute.WA_OpaquePaintEvent, True )

self._background_colour_generator = background_colour_generator

self._media = None
Expand Down Expand Up @@ -3161,6 +3169,7 @@ def paintEvent( self, event ):
try:

painter = QG.QPainter( self )
painter.setClipRegion( event.region() )

self._Redraw( painter )

Expand Down Expand Up @@ -3939,6 +3948,7 @@ def paintEvent( self, event ):


painter = QG.QPainter( self )
painter.setClipRegion( event.region() )

if self._image_renderer is None or not self._image_renderer.IsReady():

Expand Down
160 changes: 160 additions & 0 deletions hydrus/client/gui/pages/ClientGUIMediaResultsPanel.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from hydrus.core import HydrusConstants as HC
from hydrus.core import HydrusData
from hydrus.core import HydrusExceptions
from hydrus.core import HydrusLists
from hydrus.core import HydrusNumbers
from hydrus.core import HydrusPaths
from hydrus.core import HydrusTime
Expand Down Expand Up @@ -131,6 +132,8 @@ def __init__( self, parent, page_key, page_manager: ClientGUIPageManager.PageMan
CG.client_controller.sub( self, 'SelectByTags', 'select_files_with_tags' )

self._had_changes_to_tag_presentation_while_hidden = False
self._sort_generation = 0
self._seriation_sort_in_progress = False

self._my_shortcut_handler = ClientGUIShortcuts.ShortcutsHandler( self, self, [ 'media', 'thumbnails' ] )

Expand Down Expand Up @@ -1988,6 +1991,161 @@ def Collect( self, media_collect = None ):
self.Sort()


def _IsSeriationSort( self, media_sort ):

if media_sort is None:

return False


( sort_metatype, sort_data ) = media_sort.sort_type

if sort_metatype != 'system':

return False


return sort_data in (
CC.SORT_FILES_BY_SERIATION,
CC.SORT_FILES_BY_SERIATION_TAGS,
CC.SORT_FILES_BY_SERIATION_VISUAL_TAGS
)


def _SortFinished( self ):

pass


def _QTApplySeriationSort( self, sort_generation, ordered_medias, exception ):

if not QP.isValid( self ):

return


if sort_generation != self._sort_generation:

return


self._seriation_sort_in_progress = False

if exception is not None:

HydrusData.ShowException( exception )

return


if ordered_medias is None:

return


order_lookup = { media : i for ( i, media ) in enumerate( ordered_medias ) }
max_index = len( order_lookup )

self._sorted_media.sort( key = lambda m: order_lookup.get( m, max_index ), reverse = False )

self._RecalcHashes()

self._SortFinished()


def _THREADSeriationSort( self, sort_generation, media_sort, medias_snapshot ):

ordered_medias = None
exception = None

try:

( sort_metatype, sort_data ) = media_sort.sort_type
reverse = media_sort.sort_order == CC.SORT_DESC

if sort_data == CC.SORT_FILES_BY_SERIATION:

ordered_medias = ClientMedia.GetSeriationOrderingForMediasByBlurhash( medias_snapshot, reverse )

elif sort_data == CC.SORT_FILES_BY_SERIATION_TAGS:

ordered_medias = ClientMedia.GetSeriationOrderingForMediasByTags( medias_snapshot, reverse, media_sort.tag_context )

elif sort_data == CC.SORT_FILES_BY_SERIATION_VISUAL_TAGS:

ordered_medias = ClientMedia.GetSeriationOrderingForMediasByVisualAndTags( medias_snapshot, reverse, media_sort.tag_context )

else:

ordered_medias = medias_snapshot


except Exception as e:

exception = e


CG.client_controller.CallAfterQtSafe(
self,
self._QTApplySeriationSort,
sort_generation,
ordered_medias,
exception
)


def Sort( self, media_sort = None, secondary_sort = None ):

self._sort_generation += 1
sort_generation = self._sort_generation

if media_sort is None:

media_sort = self._media_sort


if secondary_sort is None:

if self._secondary_media_sort is None:

secondary_sort = CG.client_controller.new_options.GetFallbackSort()

else:

secondary_sort = self._secondary_media_sort



if not self._IsSeriationSort( media_sort ):

self._seriation_sort_in_progress = False

ClientMedia.ListeningMediaList.Sort( self, media_sort = media_sort, secondary_sort = secondary_sort )

self._SortFinished()

return


self._seriation_sort_in_progress = True

self._media_sort = media_sort
self._secondary_media_sort = secondary_sort

for media in self._collected_media:

media.Sort( media_sort = media_sort, secondary_sort = secondary_sort )


medias_snapshot = HydrusLists.FastIndexUniqueList( list( self._sorted_media ) )

self._secondary_media_sort.Sort( self._location_context, self._tag_context, medias_snapshot )

medias_snapshot = list( medias_snapshot )

CG.client_controller.CallToThread( self._THREADSeriationSort, sort_generation, media_sort, medias_snapshot )


def GetColour( self, colour_type ):

if CG.client_controller.new_options.GetBoolean( 'override_stylesheet_colours' ):
Expand Down Expand Up @@ -2791,6 +2949,7 @@ def __init__( self, parent: "MediaResultsPanel" ):

super().__init__( parent )

self.setAttribute( QC.Qt.WidgetAttribute.WA_OpaquePaintEvent, True )
self._parent = parent


Expand All @@ -2799,6 +2958,7 @@ def paintEvent( self, event ):
try:

painter = QG.QPainter( self )
painter.setClipRegion( event.region() )

bg_colour = self._parent.GetColour( CC.COLOUR_THUMBGRID_BACKGROUND )

Expand Down
Loading