hydrus/hydrus/client/gui/ClientGUIMedia.py

429 lines
13 KiB
Python
Raw Normal View History

import itertools
2013-02-19 00:11:43 +00:00
import os
2013-03-15 02:38:12 +00:00
import time
2020-05-27 21:27:52 +00:00
import typing
2020-04-22 21:00:35 +00:00
2019-11-14 03:56:30 +00:00
from qtpy import QtWidgets as QW
2020-04-22 21:00:35 +00:00
2020-05-27 21:27:52 +00:00
from hydrus.core import HydrusConstants as HC
2020-04-22 21:00:35 +00:00
from hydrus.core import HydrusExceptions
from hydrus.core import HydrusPaths
from hydrus.core import HydrusData
from hydrus.core import HydrusGlobals as HG
2020-07-29 20:52:44 +00:00
2020-04-22 21:00:35 +00:00
from hydrus.client import ClientConstants as CC
2022-11-16 21:34:30 +00:00
from hydrus.client import ClientLocation
2020-04-22 21:00:35 +00:00
from hydrus.client import ClientPaths
from hydrus.client import ClientThreading
2023-12-06 22:13:50 +00:00
from hydrus.client.gui import ClientGUIDialogsMessage
2020-04-22 21:00:35 +00:00
from hydrus.client.gui import ClientGUIDialogsQuick
2022-11-16 21:34:30 +00:00
from hydrus.client.gui import ClientGUIScrolledPanelsEdit
from hydrus.client.gui import ClientGUITopLevelWindowsPanels
2020-07-29 20:52:44 +00:00
from hydrus.client.media import ClientMedia
2013-02-19 00:11:43 +00:00
2020-08-27 01:00:42 +00:00
def CopyHashesToClipboard( win: QW.QWidget, hash_type: str, medias: typing.Sequence[ ClientMedia.Media ] ):
2023-09-27 21:12:55 +00:00
hex_it = True
2023-09-27 21:12:55 +00:00
desired_hashes = []
flat_media = ClientMedia.FlattenMedia( medias )
sha256_hashes = [ media.GetHash() for media in flat_media ]
if hash_type in ( 'pixel_hash', 'blurhash' ):
file_info_managers = [ media.GetFileInfoManager() for media in flat_media ]
if hash_type == 'pixel_hash':
desired_hashes = [ fim.pixel_hash for fim in file_info_managers if fim.pixel_hash is not None ]
elif hash_type == 'blurhash':
desired_hashes = [ fim.blurhash for fim in file_info_managers if fim.blurhash is not None ]
hex_it = False
elif hash_type == 'sha256':
desired_hashes = sha256_hashes
else:
num_hashes = len( sha256_hashes )
2023-09-27 21:12:55 +00:00
num_remote_medias = len( [ not media.GetLocationsManager().IsLocal() for media in flat_media ] )
2022-11-30 22:06:58 +00:00
source_to_desired = HG.client_controller.Read( 'file_hashes', sha256_hashes, 'sha256', hash_type )
desired_hashes = [ source_to_desired[ source_hash ] for source_hash in sha256_hashes if source_hash in source_to_desired ]
num_missing = num_hashes - len( desired_hashes )
if num_missing > 0:
if num_missing == num_hashes:
message = 'Unfortunately, none of the {} hashes could be found.'.format( hash_type )
else:
message = 'Unfortunately, {} of the {} hashes could not be found.'.format( HydrusData.ToHumanInt( num_missing ), hash_type )
2023-09-27 21:12:55 +00:00
if num_remote_medias > 0:
2023-09-27 21:12:55 +00:00
message += ' {} of the files you wanted are not currently in this client. If they have never visited this client, the lookup is impossible.'.format( HydrusData.ToHumanInt( num_remote_medias ) )
2023-09-27 21:12:55 +00:00
if num_remote_medias < num_hashes:
message += ' It could be that some of the local files are currently missing this information in the hydrus database. A file maintenance job (under the database menu) can repopulate this data.'
2023-12-06 22:13:50 +00:00
ClientGUIDialogsMessage.ShowWarning( win, message )
if len( desired_hashes ) > 0:
2023-09-27 21:12:55 +00:00
if hex_it:
text_lines = [ desired_hash.hex() for desired_hash in desired_hashes ]
else:
text_lines = desired_hashes
2020-11-04 23:23:07 +00:00
if HG.client_controller.new_options.GetBoolean( 'prefix_hash_when_copying' ):
text_lines = [ '{}:{}'.format( hash_type, hex_hash ) for hex_hash in text_lines ]
hex_hashes_text = os.linesep.join( text_lines )
HG.client_controller.pub( 'clipboard', 'text', hex_hashes_text )
2023-11-15 22:40:54 +00:00
job_status = ClientThreading.JobStatus()
2023-11-15 22:40:54 +00:00
job_status.SetStatusText( '{} {} hashes copied'.format( HydrusData.ToHumanInt( len( desired_hashes ) ), hash_type ) )
2023-11-15 22:40:54 +00:00
HG.client_controller.pub( 'message', job_status )
2023-11-29 22:27:53 +00:00
job_status.FinishAndDismiss( 2 )
2018-08-22 21:10:59 +00:00
def CopyMediaURLs( medias ):
2018-08-15 20:40:30 +00:00
2018-08-22 21:10:59 +00:00
urls = set()
2018-08-15 20:40:30 +00:00
2018-08-22 21:10:59 +00:00
for media in medias:
2018-08-15 20:40:30 +00:00
2018-08-22 21:10:59 +00:00
media_urls = media.GetLocationsManager().GetURLs()
2018-08-15 20:40:30 +00:00
2018-08-22 21:10:59 +00:00
urls.update( media_urls )
2018-08-15 20:40:30 +00:00
2018-08-22 21:10:59 +00:00
2020-05-13 19:03:16 +00:00
urls = sorted( urls )
2018-08-22 21:10:59 +00:00
urls_string = os.linesep.join( urls )
HG.client_controller.pub( 'clipboard', 'text', urls_string )
2019-05-08 21:06:42 +00:00
def CopyMediaURLClassURLs( medias, url_class ):
2018-08-22 21:10:59 +00:00
urls = set()
for media in medias:
media_urls = media.GetLocationsManager().GetURLs()
for url in media_urls:
2020-12-16 22:29:51 +00:00
# can't do 'url_class.matches', as it will match too many
if HG.client_controller.network_engine.domain_manager.GetURLClass( url ) == url_class:
2018-08-22 21:10:59 +00:00
urls.add( url )
2020-05-13 19:03:16 +00:00
urls = sorted( urls )
2018-08-22 21:10:59 +00:00
urls_string = os.linesep.join( urls )
HG.client_controller.pub( 'clipboard', 'text', urls_string )
def DoClearFileViewingStats( win: QW.QWidget, flat_medias: typing.Collection[ ClientMedia.MediaSingleton ] ):
2020-05-27 21:27:52 +00:00
if len( flat_medias ) == 0:
return
if len( flat_medias ) == 1:
insert = 'this file'
else:
insert = 'these {} files'.format( HydrusData.ToHumanInt( len( flat_medias ) ) )
2022-01-26 21:57:04 +00:00
message = 'Clear the file viewing count/duration and \'last viewed time\' for {}?'.format( insert )
2020-05-27 21:27:52 +00:00
result = ClientGUIDialogsQuick.GetYesNo( win, message )
if result == QW.QDialog.Accepted:
hashes = { m.GetHash() for m in flat_medias }
content_update = HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILE_VIEWING_STATS, HC.CONTENT_UPDATE_DELETE, hashes )
HG.client_controller.Write( 'content_updates', { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ content_update ] } )
2019-03-20 21:22:10 +00:00
def DoOpenKnownURLFromShortcut( win, media ):
urls = media.GetLocationsManager().GetURLs()
matched_labels_and_urls = []
unmatched_urls = []
if len( urls ) > 0:
for url in urls:
2020-04-01 21:51:42 +00:00
try:
url_class = HG.client_controller.network_engine.domain_manager.GetURLClass( url )
except HydrusExceptions.URLClassException:
continue
2019-03-20 21:22:10 +00:00
2019-05-08 21:06:42 +00:00
if url_class is None:
2019-03-20 21:22:10 +00:00
unmatched_urls.append( url )
else:
2019-05-08 21:06:42 +00:00
label = url_class.GetName() + ': ' + url
2019-03-20 21:22:10 +00:00
matched_labels_and_urls.append( ( label, url ) )
matched_labels_and_urls.sort()
unmatched_urls.sort()
if len( matched_labels_and_urls ) == 0:
return
elif len( matched_labels_and_urls ) == 1:
url = matched_labels_and_urls[0][1]
else:
matched_labels_and_urls.extend( ( url, url ) for url in unmatched_urls )
try:
url = ClientGUIDialogsQuick.SelectFromList( win, 'Select which URL', matched_labels_and_urls, sort_tuples = False )
except HydrusExceptions.CancelledException:
return
ClientPaths.LaunchURLInWebBrowser( url )
2022-11-16 21:34:30 +00:00
2022-12-14 22:22:11 +00:00
def EditDuplicateContentMergeOptions( win: QW.QWidget, duplicate_type: int ):
2022-11-16 21:34:30 +00:00
new_options = HG.client_controller.new_options
2022-12-14 22:22:11 +00:00
duplicate_content_merge_options = new_options.GetDuplicateContentMergeOptions( duplicate_type )
2022-11-16 21:34:30 +00:00
with ClientGUITopLevelWindowsPanels.DialogEdit( win, 'edit duplicate merge options' ) as dlg:
2022-12-14 22:22:11 +00:00
panel = ClientGUIScrolledPanelsEdit.EditDuplicateContentMergeOptionsPanel( dlg, duplicate_type, duplicate_content_merge_options )
2022-11-16 21:34:30 +00:00
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
2022-12-14 22:22:11 +00:00
duplicate_content_merge_options = panel.GetValue()
2022-11-16 21:34:30 +00:00
2022-12-14 22:22:11 +00:00
new_options.SetDuplicateContentMergeOptions( duplicate_type, duplicate_content_merge_options )
2022-11-16 21:34:30 +00:00
2020-02-12 22:50:37 +00:00
def OpenExternally( media ):
hash = media.GetHash()
mime = media.GetMime()
client_files_manager = HG.client_controller.client_files_manager
path = client_files_manager.GetFilePath( hash, mime )
new_options = HG.client_controller.new_options
launch_path = new_options.GetMimeLaunch( mime )
HydrusPaths.LaunchFile( path, launch_path )
2023-05-24 20:44:12 +00:00
def OpenFileLocation( media ):
hash = media.GetHash()
mime = media.GetMime()
path = HG.client_controller.client_files_manager.GetFilePath( hash, mime )
HydrusPaths.OpenFileLocation( path )
2019-03-06 23:06:22 +00:00
def OpenURLs( urls ):
2020-05-13 19:03:16 +00:00
urls = sorted( urls )
2019-03-06 23:06:22 +00:00
if len( urls ) > 1:
message = 'Open the {} URLs in your web browser?'.format( len( urls ) )
if len( urls ) > 10:
message += ' This will take some time.'
2020-07-15 20:52:09 +00:00
tlw = HG.client_controller.GetMainTLW()
result = ClientGUIDialogsQuick.GetYesNo( tlw, message )
2019-09-05 00:05:32 +00:00
2019-11-14 03:56:30 +00:00
if result != QW.QDialog.Accepted:
2019-03-06 23:06:22 +00:00
2019-09-05 00:05:32 +00:00
return
2019-03-06 23:06:22 +00:00
def do_it( urls ):
2023-11-15 22:40:54 +00:00
job_status = None
2019-03-06 23:06:22 +00:00
num_urls = len( urls )
if num_urls > 5:
2023-11-15 22:40:54 +00:00
job_status = ClientThreading.JobStatus( pausable = True, cancellable = True )
2019-03-06 23:06:22 +00:00
2023-11-15 22:40:54 +00:00
job_status.SetStatusTitle( 'Opening URLs' )
2019-03-06 23:06:22 +00:00
2023-11-15 22:40:54 +00:00
HG.client_controller.pub( 'message', job_status )
2019-03-06 23:06:22 +00:00
try:
for ( i, url ) in enumerate( urls ):
2023-11-15 22:40:54 +00:00
if job_status is not None:
2019-03-06 23:06:22 +00:00
2023-11-15 22:40:54 +00:00
( i_paused, should_quit ) = job_status.WaitIfNeeded()
2019-03-13 21:04:21 +00:00
if should_quit:
2019-03-06 23:06:22 +00:00
return
2023-11-15 22:40:54 +00:00
job_status.SetStatusText( HydrusData.ConvertValueRangeToPrettyString( i + 1, num_urls ) )
job_status.SetVariable( 'popup_gauge_1', ( i + 1, num_urls ) )
2019-03-06 23:06:22 +00:00
ClientPaths.LaunchURLInWebBrowser( url )
time.sleep( 1 )
finally:
2023-11-15 22:40:54 +00:00
if job_status is not None:
2019-03-06 23:06:22 +00:00
2023-11-29 22:27:53 +00:00
job_status.FinishAndDismiss( 1 )
2019-03-06 23:06:22 +00:00
HG.client_controller.CallToThread( do_it, urls )
def OpenMediaURLs( medias ):
urls = set()
for media in medias:
media_urls = media.GetLocationsManager().GetURLs()
urls.update( media_urls )
OpenURLs( urls )
2019-05-08 21:06:42 +00:00
def OpenMediaURLClassURLs( medias, url_class ):
2019-03-06 23:06:22 +00:00
urls = set()
for media in medias:
media_urls = media.GetLocationsManager().GetURLs()
for url in media_urls:
2020-12-16 22:29:51 +00:00
# can't do 'url_class.matches', as it will match too many
if HG.client_controller.network_engine.domain_manager.GetURLClass( url ) == url_class:
2019-03-06 23:06:22 +00:00
urls.add( url )
OpenURLs( urls )
2022-11-16 21:34:30 +00:00
def ShowDuplicatesInNewPage( location_context: ClientLocation.LocationContext, hash, duplicate_type ):
2022-05-04 21:40:27 +00:00
2022-11-16 21:34:30 +00:00
# TODO: this can be replaced by a call to the MediaResult when it holds these hashes
2022-11-30 22:06:58 +00:00
# don't forget to return itself in position 0!
2022-11-16 21:34:30 +00:00
hashes = HG.client_controller.Read( 'file_duplicate_hashes', location_context, hash, duplicate_type )
2022-05-04 21:40:27 +00:00
2022-11-30 22:06:58 +00:00
if hashes is not None and len( hashes ) > 1:
2022-05-04 21:40:27 +00:00
2022-11-16 21:34:30 +00:00
HG.client_controller.pub( 'new_page_query', location_context, initial_hashes = hashes )
2022-05-04 21:40:27 +00:00
2023-05-31 20:54:09 +00:00
else:
location_context = ClientLocation.LocationContext.STATICCreateSimple( CC.COMBINED_FILE_SERVICE_KEY )
hashes = HG.client_controller.Read( 'file_duplicate_hashes', location_context, hash, duplicate_type )
if hashes is not None and len( hashes ) > 1:
HydrusData.ShowText( 'Could not find the members of this group in this location, so searched all known files and found more.' )
HG.client_controller.pub( 'new_page_query', location_context, initial_hashes = hashes )
else:
HydrusData.ShowText( 'Sorry, could not find the members of this group either at the given location or in all known files. There may be a problem here, so let hydev know.' )
2022-05-11 21:16:33 +00:00