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
70 changes: 66 additions & 4 deletions hydrus/client/files/ClientFilesMaintenance.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from hydrus.client import ClientThreading
from hydrus.client.metadata import ClientContentUpdates
from hydrus.client.metadata import ClientTags
from hydrus.client.metadata import ClientTikTok

REGENERATE_FILE_DATA_JOB_FILE_METADATA = 0
REGENERATE_FILE_DATA_JOB_FORCE_THUMBNAIL = 1
Expand All @@ -52,6 +53,7 @@
REGENERATE_FILE_DATA_JOB_FILE_INTEGRITY_PRESENCE_DELETE_RECORD = 21
REGENERATE_FILE_DATA_JOB_BLURHASH = 22
REGENERATE_FILE_DATA_JOB_FILE_HAS_TRANSPARENCY = 23
REGENERATE_FILE_DATA_JOB_TIKTOK_TAG_ENRICHMENT = 24

regen_file_enum_to_str_lookup = {
REGENERATE_FILE_DATA_JOB_FILE_METADATA : 'regenerate file metadata',
Expand All @@ -77,7 +79,8 @@
REGENERATE_FILE_DATA_JOB_FILE_HAS_HUMAN_READABLE_EMBEDDED_METADATA : 'determine if the file has non-EXIF embedded metadata',
REGENERATE_FILE_DATA_JOB_FILE_HAS_ICC_PROFILE : 'determine if the file has an icc profile',
REGENERATE_FILE_DATA_JOB_PIXEL_HASH : 'regenerate pixel hashes',
REGENERATE_FILE_DATA_JOB_BLURHASH: 'regenerate blurhash'
REGENERATE_FILE_DATA_JOB_BLURHASH: 'regenerate blurhash',
REGENERATE_FILE_DATA_JOB_TIKTOK_TAG_ENRICHMENT : 'add tiktok site/creator tags from known URLs'
}

# wrapped in triple quotes so I don't have to backslash escape so much
Expand Down Expand Up @@ -145,7 +148,8 @@
REGENERATE_FILE_DATA_JOB_FILE_HAS_HUMAN_READABLE_EMBEDDED_METADATA : '''This loads the file to see if it has non-EXIF human-readable embedded metadata, which can be shown in the media viewer and searched with "system:image has human-readable embedded metadata".''',
REGENERATE_FILE_DATA_JOB_FILE_HAS_ICC_PROFILE : '''This loads the file to see if it has an ICC profile, which is used in "system:has icc profile" search.''',
REGENERATE_FILE_DATA_JOB_PIXEL_HASH : '''This generates a fast unique identifier for the pixels in a still image, which is used in duplicate pixel searches.''',
REGENERATE_FILE_DATA_JOB_BLURHASH : '''This generates a very small version of the file's thumbnail that can be used as a placeholder while the thumbnail loads.'''
REGENERATE_FILE_DATA_JOB_BLURHASH : '''This generates a very small version of the file's thumbnail that can be used as a placeholder while the thumbnail loads.''',
REGENERATE_FILE_DATA_JOB_TIKTOK_TAG_ENRICHMENT : '''This looks at a file's known URLs and adds downloader tags like "site:tiktok" and "creator:<handle>" if it detects TikTok URLs. No network requests are made.'''
}

NORMALISED_BIG_JOB_WEIGHT = 100
Expand Down Expand Up @@ -174,7 +178,8 @@
REGENERATE_FILE_DATA_JOB_FILE_HAS_HUMAN_READABLE_EMBEDDED_METADATA : 25,
REGENERATE_FILE_DATA_JOB_FILE_HAS_ICC_PROFILE : 25,
REGENERATE_FILE_DATA_JOB_PIXEL_HASH : 100,
REGENERATE_FILE_DATA_JOB_BLURHASH: 15
REGENERATE_FILE_DATA_JOB_BLURHASH: 15,
REGENERATE_FILE_DATA_JOB_TIKTOK_TAG_ENRICHMENT : 1
}

regen_file_enum_to_overruled_jobs = {
Expand All @@ -201,7 +206,8 @@
REGENERATE_FILE_DATA_JOB_FILE_HAS_HUMAN_READABLE_EMBEDDED_METADATA : [],
REGENERATE_FILE_DATA_JOB_FILE_HAS_ICC_PROFILE : [],
REGENERATE_FILE_DATA_JOB_PIXEL_HASH : [],
REGENERATE_FILE_DATA_JOB_BLURHASH: []
REGENERATE_FILE_DATA_JOB_BLURHASH: [],
REGENERATE_FILE_DATA_JOB_TIKTOK_TAG_ENRICHMENT : []
}

ALL_REGEN_JOBS_IN_RUN_ORDER = [
Expand All @@ -214,6 +220,7 @@
REGENERATE_FILE_DATA_JOB_FILE_INTEGRITY_DATA_REMOVE_RECORD,
REGENERATE_FILE_DATA_JOB_FILE_INTEGRITY_DATA_SILENT_DELETE,
REGENERATE_FILE_DATA_JOB_FILE_INTEGRITY_PRESENCE_LOG_ONLY,
REGENERATE_FILE_DATA_JOB_TIKTOK_TAG_ENRICHMENT,
REGENERATE_FILE_DATA_JOB_FILE_METADATA,
REGENERATE_FILE_DATA_JOB_REFIT_THUMBNAIL,
REGENERATE_FILE_DATA_JOB_FORCE_THUMBNAIL,
Expand Down Expand Up @@ -241,6 +248,7 @@
REGENERATE_FILE_DATA_JOB_FILE_INTEGRITY_DATA_REMOVE_RECORD,
REGENERATE_FILE_DATA_JOB_FILE_INTEGRITY_DATA_SILENT_DELETE,
REGENERATE_FILE_DATA_JOB_FILE_INTEGRITY_PRESENCE_LOG_ONLY,
REGENERATE_FILE_DATA_JOB_TIKTOK_TAG_ENRICHMENT,
REGENERATE_FILE_DATA_JOB_FILE_METADATA,
REGENERATE_FILE_DATA_JOB_REFIT_THUMBNAIL,
REGENERATE_FILE_DATA_JOB_FORCE_THUMBNAIL,
Expand Down Expand Up @@ -1045,6 +1053,56 @@ def _RegenBlurhash( self, media_result ):



def _EnrichTikTokTags( self, media_result ):

urls = media_result.GetLocationsManager().GetURLs()

if len( urls ) == 0:

return None


tags_to_add = ClientTikTok.GetTikTokTagsFromURLs( urls )

description_text = ClientTikTok.GetTikTokDescriptionTextFromNotes( media_result.GetNotesManager() )

if description_text is not None:

tags_to_add.update( ClientTikTok.GetTikTokHashtagTagsFromText( description_text ) )

if len( tags_to_add ) == 0:

return None


tags_manager = media_result.GetTagsManager()
existing_tags = tags_manager.GetCurrentAndPending( CC.DEFAULT_LOCAL_DOWNLOADER_TAG_SERVICE_KEY, ClientTags.TAG_DISPLAY_STORAGE )

tags_to_add.difference_update( existing_tags )

if len( tags_to_add ) == 0:

return None


hash = media_result.GetHash()

content_updates = [
ClientContentUpdates.ContentUpdate( HC.CONTENT_TYPE_MAPPINGS, HC.CONTENT_UPDATE_ADD, ( tag, { hash } ) )
for tag in tags_to_add
]

content_update_package = ClientContentUpdates.ContentUpdatePackage.STATICCreateFromContentUpdates(
CC.DEFAULT_LOCAL_DOWNLOADER_TAG_SERVICE_KEY,
content_updates
)

CG.client_controller.WriteSynchronous( 'content_updates', content_update_package )

return len( tags_to_add )




def _RegenSimilarFilesMetadata( self, media_result ):

Expand Down Expand Up @@ -1212,6 +1270,10 @@ def _RunJob( self, media_results_to_job_types, job_status, job_done_hook = None

additional_data = self._RegenBlurhash( media_result )

elif job_type == REGENERATE_FILE_DATA_JOB_TIKTOK_TAG_ENRICHMENT:

additional_data = self._EnrichTikTokTags( media_result )

elif job_type in (
REGENERATE_FILE_DATA_JOB_FILE_INTEGRITY_PRESENCE_REMOVE_RECORD,
REGENERATE_FILE_DATA_JOB_FILE_INTEGRITY_PRESENCE_DELETE_RECORD,
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
Loading