Skip to content

Commit

Permalink
Version 602
Browse files Browse the repository at this point in the history
  • Loading branch information
hydrusnetwork committed Dec 11, 2024
1 parent 533f6e7 commit e6847f5
Show file tree
Hide file tree
Showing 88 changed files with 2,444 additions and 1,538 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release_macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:

jobs:
build-macos:
runs-on: macos-12
runs-on: macos-13
steps:
-
name: Checkout
Expand Down
119 changes: 71 additions & 48 deletions docs/changelog.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/developer_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1559,8 +1559,8 @@ Wildcards and namespace searches are supported, so if you search for 'character:
* system:no audio
* system:has exif
* system:no exif
* system:has human-readable embedded metadata
* system:no human-readable embedded metadata
* system:has embedded metadata
* system:no embedded metadata
* system:has icc profile
* system:no icc profile
* system:has tags
Expand Down
58 changes: 56 additions & 2 deletions docs/old_changelog.html

Large diffs are not rendered by default.

17 changes: 13 additions & 4 deletions hydrus/client/ClientConstants.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,14 +446,23 @@
sort_type_string_lookup[ sort_type ] = s


special_sort_sort_override = {
SORT_FILES_BY_WIDTH : 'dimensions 0',
SORT_FILES_BY_HEIGHT : 'dimensions 1'
}

def magico_sort_sort( sort_type ):

# we just want to sort by sort_type_string_lookup values tbh, EXCEPT we want to put width above height in the dimensions list

ms = system_sort_type_submetatype_string_lookup[ sort_type ]
s = sort_type_basic_string_lookup[ sort_type ]

return ( ms if ms is not None else s, 'width' not in s, s )
if sort_type in special_sort_sort_override:

return special_sort_sort_override[ sort_type ]

else:

return sort_type_basic_string_lookup[ sort_type ]



SYSTEM_SORT_TYPES_SORT_CONTROL_SORTED = sorted( SYSTEM_SORT_TYPES, key = lambda sst: magico_sort_sort( sst ) )
Expand Down
7 changes: 7 additions & 0 deletions hydrus/client/ClientController.py
Original file line number Diff line number Diff line change
Expand Up @@ -1233,6 +1233,13 @@ def InitModel( self ):

self.frame_splash_status.SetSubtext( 'network' )

if self.new_options.GetBoolean( 'set_requests_ca_bundle_env' ):

from hydrus.client import ClientEnvironment

ClientEnvironment.SetRequestsCABundleEnv()


if self.new_options.GetBoolean( 'boot_with_network_traffic_paused' ):

CG.client_controller.new_options.SetBoolean( 'pause_all_new_network_traffic', True )
Expand Down
45 changes: 45 additions & 0 deletions hydrus/client/ClientEnvironment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import os

from hydrus.core import HydrusData

def SetRequestsCABundleEnv( pem_path = None ):

# TODO: we could initialise this with a custom pem in launch args pretty easy if we wanted to!
# but tbh the user can already set it in the launch env anyway so maybe whatever

env_var_name = 'REQUESTS_CA_BUNDLE'

if env_var_name in os.environ:

HydrusData.Print( f'Custom REQUESTS_CA_BUNDLE: {os.environ[env_var_name]}')

return


# could say "If CURL_CA_BUNDLE exists, use that instead of certifi"

if pem_path is None:

try:

import certifi

pem_path = certifi.where()

except:

HydrusData.Print( 'No certifi, so cannot set REQUESTS_CA_BUNDLE.' )

return



if os.path.exists( pem_path ):

os.environ[ env_var_name ] = pem_path

else:

HydrusData.Print( f'The given CA Bundle at "{pem_path}" does not exist, so cannot set REQUESTS_CA_BUNDLE!' )


4 changes: 2 additions & 2 deletions hydrus/client/ClientFiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
REGENERATE_FILE_DATA_JOB_FILE_MODIFIED_TIMESTAMP : 'regenerate file modified time',
REGENERATE_FILE_DATA_JOB_FILE_HAS_TRANSPARENCY: 'determine if the file has transparency',
REGENERATE_FILE_DATA_JOB_FILE_HAS_EXIF : 'determine if the file has EXIF metadata',
REGENERATE_FILE_DATA_JOB_FILE_HAS_HUMAN_READABLE_EMBEDDED_METADATA : 'determine if the file has non-EXIF human-readable embedded metadata',
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'
Expand Down Expand Up @@ -155,7 +155,7 @@
REGENERATE_FILE_DATA_JOB_FILE_MODIFIED_TIMESTAMP : '''This rechecks the file's modified timestamp and saves it to the database.''',
REGENERATE_FILE_DATA_JOB_FILE_HAS_TRANSPARENCY : '''This loads the file to see if it has an alpha channel with useful data (completely opaque/transparency alpha channels are discarded). Only works for images and animated gif.''',
REGENERATE_FILE_DATA_JOB_FILE_HAS_EXIF : '''This loads the file to see if it has EXIF metadata, which can be shown in the media viewer and searched with "system:image has exif".''',
REGENERATE_FILE_DATA_JOB_FILE_HAS_HUMAN_READABLE_EMBEDDED_METADATA : '''This loads the file to see if it has non-EXIF human-readable 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_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.'''
Expand Down
7 changes: 6 additions & 1 deletion hydrus/client/ClientOptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,12 @@ def _InitialiseDefaults( self ):
'use_listbook_for_tag_service_panels' : False,
'open_files_to_duplicate_filter_uses_all_my_files' : True,
'show_extended_single_file_info_in_status_bar' : False,
'hide_duplicates_needs_work_message_when_reasonably_caught_up' : True
'hide_duplicates_needs_work_message_when_reasonably_caught_up' : True,
'file_info_line_consider_archived_interesting' : True,
'file_info_line_consider_archived_time_interesting' : True,
'file_info_line_consider_file_services_interesting' : False,
'file_info_line_consider_file_services_import_times_interesting' : False,
'set_requests_ca_bundle_env' : False
}

#
Expand Down
8 changes: 4 additions & 4 deletions hydrus/client/ClientRendering.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ def _InitialiseErrorImage( self, e: Exception ):

painter = QG.QPainter( qt_image )

painter.setBackground( QG.QBrush( QC.Qt.white ) )
painter.setBackground( QG.QBrush( QC.Qt.GlobalColor.white ) )

painter.eraseRect( painter.viewport() )

Expand All @@ -325,7 +325,7 @@ def _InitialiseErrorImage( self, e: Exception ):
pen.setWidth( 5 )

painter.setPen( pen )
painter.setBrush( QC.Qt.NoBrush )
painter.setBrush( QC.Qt.BrushStyle.NoBrush )

painter.drawRect( 0, 0, width - 1, height - 1 )

Expand All @@ -343,7 +343,7 @@ def _InitialiseErrorImage( self, e: Exception ):
text += '\n'
text += 'Full info written to the log.'

painter.drawText( QC.QRectF( 0, 0, width, height ), QC.Qt.AlignCenter, text )
painter.drawText( QC.QRectF( 0, 0, width, height ), QC.Qt.AlignmentFlag.AlignCenter, text )

del painter

Expand Down Expand Up @@ -468,7 +468,7 @@ def GetQtPixmap( self, clip_rect = None, target_resolution = None ):

pixmap = QG.QPixmap( target_resolution )

pixmap.fill( QC.Qt.black )
pixmap.fill( QC.Qt.GlobalColor.black )

return pixmap

Expand Down
2 changes: 1 addition & 1 deletion hydrus/client/ClientSVGHandling.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def GenerateThumbnailNumPyFromSVGPath( path: str, target_resolution: typing.Tupl

qt_image = QG.QImage( target_width, target_height, QG.QImage.Format_RGBA8888 )

qt_image.fill( QC.Qt.transparent )
qt_image.fill( QC.Qt.GlobalColor.transparent )

painter = QG.QPainter( qt_image )

Expand Down
2 changes: 1 addition & 1 deletion hydrus/client/ClientSerialisable.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def CreateTopImage( width, title, payload_description, text ):

painter = QG.QPainter( top_qt_image )

painter.setBackground( QG.QBrush( QC.Qt.white ) )
painter.setBackground( QG.QBrush( QC.Qt.GlobalColor.white ) )

painter.eraseRect( painter.viewport() )

Expand Down
39 changes: 3 additions & 36 deletions hydrus/client/ClientServices.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,45 +724,12 @@ def ConvertRatingStateAndRatingToString( self, rating_state: int, rating: float

def ConvertRatingToStars( self, rating: float ) -> int:

if self._allow_zero:

stars = int( round( rating * self._num_stars ) )

else:

stars = int( round( rating * ( self._num_stars - 1 ) ) ) + 1


return stars
return ClientRatings.ConvertRatingToStars( self._num_stars, self._allow_zero, rating )


def ConvertStarsToRating( self, stars: int ) -> float:

if stars > self._num_stars:

stars = self._num_stars


if self._allow_zero:

if stars < 0:

stars = 0


rating = stars / self._num_stars

else:

if stars < 1:

stars = 1


rating = ( stars - 1 ) / ( self._num_stars - 1 )

def ConvertStarsToRating( self, stars: int ):

return rating
return ClientRatings.ConvertStarsToRating( self._num_stars, self._allow_zero, stars )


def GetNumStars( self ):
Expand Down
49 changes: 46 additions & 3 deletions hydrus/client/db/ClientDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -4997,6 +4997,11 @@ def _ImportFile( self, file_import_job: ClientImportFiles.FileImportJob ):
HydrusData.ShowText( 'File import job archiving new file' )


if hash_id not in self.modules_files_inbox.inbox_hash_ids:

self.modules_files_inbox.InboxFiles( ( hash_id, ) )


self.modules_files_inbox.ArchiveFiles( ( hash_id, ) )

content_update = ClientContentUpdates.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, ( hash, ) )
Expand Down Expand Up @@ -5128,6 +5133,8 @@ def _InitCommandsToMethods( self ):
'ideal_client_files_locations' : self.modules_files_physical_storage.GetIdealClientFilesLocations,
'last_shutdown_work_time' : self.modules_db_maintenance.GetLastShutdownWorkTime,
'media_predicates' : self.modules_tag_display.GetMediaPredicates,
'missing_archive_timestamps_import_test' : self.modules_files_inbox.WeHaveMissingImportArchiveTimestamps,
'missing_archive_timestamps_legacy_test' : self.modules_files_inbox.WeHaveMissingLegacyArchiveTimestamps,
'missing_repository_update_hashes' : self.modules_repositories.GetRepositoryUpdateHashesIDoNotHave,
'num_deferred_file_deletes' : self.modules_files_storage.GetDeferredPhysicalDeleteCounts,
'recent_tags' : self.modules_recent_tags.GetRecentTags,
Expand Down Expand Up @@ -5226,6 +5233,8 @@ def _InitCommandsToMethods( self ):
'ideal_client_files_locations' : self.modules_files_physical_storage.SetIdealClientFilesLocations,
'maintain_hashed_serialisables' : self.modules_serialisable.MaintainHashedStorage,
'maintain_similar_files_tree' : self.modules_similar_files.MaintainTree,
'missing_archive_timestamps_import_fillin' : self.modules_files_inbox.FillInMissingImportArchiveTimestamps,
'missing_archive_timestamps_legacy_fillin' : self.modules_files_inbox.FillInMissingLegacyArchiveTimestamps,
'process_repository_definitions' : self.modules_repositories.ProcessRepositoryDefinitions,
'push_recent_tags' : self.modules_recent_tags.PushRecentTags,
'regenerate_similar_files' : self.modules_similar_files.RegenerateTree,
Expand Down Expand Up @@ -5359,7 +5368,7 @@ def _LoadModules( self ):

#

self.modules_files_inbox = ClientDBFilesInbox.ClientDBFilesInbox( self._c, self.modules_files_storage, self.modules_files_timestamps )
self.modules_files_inbox = ClientDBFilesInbox.ClientDBFilesInbox( self._c, self.modules_services, self.modules_files_storage, self.modules_files_timestamps )

self._modules.append( self.modules_files_inbox )

Expand Down Expand Up @@ -5995,7 +6004,7 @@ def _PerceptualHashesSearchForPotentialDuplicates( self, search_distance, mainte
group_of_hash_ids = self._STL( self._Execute( 'SELECT hash_id FROM shape_search_cache WHERE searched_distance IS NULL or searched_distance < ?;', ( search_distance, ) ).fetchmany( 10 ) )

while len( group_of_hash_ids ) > 0:

text = 'searching potential duplicates: {}'.format( HydrusNumbers.ToHumanInt( num_done ) )

CG.client_controller.frame_splash_status.SetSubtext( text )
Expand Down Expand Up @@ -11392,6 +11401,40 @@ def ask_what_to_do_false_positive_modified_dates():



if version == 601:

try:

self._controller.frame_splash_status.SetText( f'scanning for missing import archive timestamps' )

we_have_missing_import_archive_timestamps = self.modules_files_inbox.WeHaveMissingImportArchiveTimestamps()

if not we_have_missing_import_archive_timestamps:

self._controller.frame_splash_status.SetText( f'scanning for missing legacy archive timestamps' )

we_have_missing_legacy_archive_timestamps = self.modules_files_inbox.WeHaveMissingLegacyArchiveTimestamps()

else:

we_have_missing_legacy_archive_timestamps = False


if we_have_missing_import_archive_timestamps or we_have_missing_legacy_archive_timestamps:

self.pub_initial_message( 'Hey, I discovered you have some missing file archived times, which we can now fill in with synthetic values. Hit up the new "database->file maintenance->fix missing file archived times" job to review your options!' )


except Exception as e:

HydrusData.PrintException( e )

message = 'Trying to check for archived time gaps failed! Please let hydrus dev know!'

self.pub_initial_message( message )



self._controller.frame_splash_status.SetTitleText( 'updated db to v{}'.format( HydrusNumbers.ToHumanInt( version + 1 ) ) )

self._Execute( 'UPDATE version SET version = ?;', ( version + 1, ) )
Expand Down Expand Up @@ -11890,7 +11933,7 @@ def pub_service_updates_after_commit( self, service_keys_to_service_updates ):

def publish_status_update( self ):

self._controller.pub( 'set_status_bar_dirty' )
self._controller.pub( 'set_status_bar_db_dirty' )


def GetInitialMessages( self ):
Expand Down
Loading

0 comments on commit e6847f5

Please sign in to comment.