def test_import_folders_daemon( self ): test_dir = HydrusTemp.GetTempDir() try: HG.test_controller.SetRead( 'hash_status', ClientImportFiles.FileImportStatus.STATICGetUnknownStatus() ) HydrusPaths.MakeSureDirectoryExists( test_dir ) hydrus_png_path = os.path.join( HC.STATIC_DIR, 'hydrus.png' ) HydrusPaths.MirrorFile( hydrus_png_path, os.path.join( test_dir, '0' ) ) HydrusPaths.MirrorFile( hydrus_png_path, os.path.join( test_dir, '1' ) ) # previously imported HydrusPaths.MirrorFile( hydrus_png_path, os.path.join( test_dir, '2' ) ) with open( os.path.join( test_dir, '3' ), 'wb' ) as f: f.write( b'blarg' ) # broken with open( os.path.join( test_dir, '4' ), 'wb' ) as f: f.write( b'blarg' ) # previously failed # actions = {} actions[ CC.STATUS_SUCCESSFUL_AND_NEW ] = CC.IMPORT_FOLDER_DELETE actions[ CC.STATUS_SUCCESSFUL_BUT_REDUNDANT ] = CC.IMPORT_FOLDER_DELETE actions[ CC.STATUS_DELETED ] = CC.IMPORT_FOLDER_DELETE actions[ CC.STATUS_ERROR ] = CC.IMPORT_FOLDER_IGNORE import_folder = ClientImportLocal.ImportFolder( 'imp', path = test_dir, actions = actions ) HG.test_controller.SetRead( 'serialisable_names', [ 'imp' ] ) HG.test_controller.SetRead( 'serialisable_named', import_folder ) HG.test_controller.ClearWrites( 'import_file' ) HG.test_controller.ClearWrites( 'serialisable' ) ClientDaemons.DAEMONCheckImportFolders() import_file = HG.test_controller.GetWrite( 'import_file' ) self.assertEqual( len( import_file ), 3 ) # I need to expand tests here with the new file system [ ( ( updated_import_folder, ), empty_dict ) ] = HG.test_controller.GetWrite( 'serialisable' ) self.assertEqual( updated_import_folder, import_folder ) self.assertTrue( not os.path.exists( os.path.join( test_dir, '0' ) ) ) self.assertTrue( not os.path.exists( os.path.join( test_dir, '1' ) ) ) self.assertTrue( not os.path.exists( os.path.join( test_dir, '2' ) ) ) self.assertTrue( os.path.exists( os.path.join( test_dir, '3' ) ) ) self.assertTrue( os.path.exists( os.path.join( test_dir, '4' ) ) ) finally: shutil.rmtree( test_dir )
def DumpToPNG(width, payload_bytes, title, payload_description, text, path): payload_bytes_length = len(payload_bytes) header_and_payload_bytes_length = payload_bytes_length + 4 payload_height = int(header_and_payload_bytes_length / width) if (header_and_payload_bytes_length / width) % 1.0 > 0: payload_height += 1 top_image = CreateTopImage(width, title, payload_description, text) payload_length_header = struct.pack('!I', payload_bytes_length) num_empty_bytes = payload_height * width - header_and_payload_bytes_length header_and_payload_bytes = payload_length_header + payload_bytes + b'\x00' * num_empty_bytes payload_image = numpy.fromstring(header_and_payload_bytes, dtype='uint8').reshape( (payload_height, width)) finished_image = numpy.concatenate((top_image, payload_image)) # this is to deal with unicode paths, which cv2 can't handle (os_file_handle, temp_path) = HydrusTemp.GetTempPath(suffix='.png') try: cv2.imwrite(temp_path, finished_image, [cv2.IMWRITE_PNG_COMPRESSION, 9]) HydrusPaths.MirrorFile(temp_path, path) except Exception as e: HydrusData.ShowException(e) raise Exception('Could not save the png!') finally: HydrusTemp.CleanUpTempPath(os_file_handle, temp_path)
def UpdateConf(self): mpv_config_path = HG.client_controller.GetMPVConfPath() if not os.path.exists(mpv_config_path): default_mpv_config_path = HG.client_controller.GetDefaultMPVConfPath( ) if not os.path.exists(default_mpv_config_path): HydrusData.ShowText( 'There is no default mpv configuration file to load! Perhaps there is a problem with your install?' ) return else: HydrusPaths.MirrorFile(default_mpv_config_path, mpv_config_path) #To load an existing config file (by default it doesn't load the user/global config like standalone mpv does): load_f = getattr(mpv, '_mpv_load_config_file', None) if load_f is not None and callable(load_f): try: load_f(self._player.handle, mpv_config_path.encode('utf-8')) # pylint: disable=E1102 except Exception as e: HydrusData.ShowText( 'MPV could not load its configuration file! This was probably due to an invalid parameter value inside the conf. The error follows:' ) HydrusData.ShowException(e) else: HydrusData.Print( 'Was unable to load mpv.conf--has the MPV API changed?')
def LoadFromPNG( path ): # this is to deal with unicode paths, which cv2 can't handle ( os_file_handle, temp_path ) = HydrusTemp.GetTempPath() try: HydrusPaths.MirrorFile( path, temp_path ) try: # unchanged because we want exact byte data, no conversions or other gubbins numpy_image = cv2.imread( temp_path, flags = IMREAD_UNCHANGED ) if numpy_image is None: raise Exception() except Exception as e: try: # dequantize = False because we don't want to convert to RGB pil_image = HydrusImageHandling.GeneratePILImage( temp_path, dequantize = False ) numpy_image = HydrusImageHandling.GenerateNumPyImageFromPILImage( pil_image ) except Exception as e: HydrusData.ShowException( e ) raise Exception( '"{}" did not appear to be a valid image!'.format( path ) ) finally: HydrusTemp.CleanUpTempPath( os_file_handle, temp_path ) return LoadFromNumPyImage( numpy_image )
def _DoExport( self ): query_hash_ids = HG.client_controller.Read( 'file_query_ids', self._file_search_context ) media_results = [] i = 0 base = 256 while i < len( query_hash_ids ): if HG.client_controller.new_options.GetBoolean( 'pause_export_folders_sync' ) or HydrusThreading.IsThreadShuttingDown(): return if i == 0: ( last_i, i ) = ( 0, base ) else: ( last_i, i ) = ( i, i + base ) sub_query_hash_ids = query_hash_ids[ last_i : i ] more_media_results = HG.client_controller.Read( 'media_results_from_ids', sub_query_hash_ids ) media_results.extend( more_media_results ) media_results.sort( key = lambda mr: mr.GetHashId() ) # terms = ParseExportPhrase( self._phrase ) previous_paths = set() for ( root, dirnames, filenames ) in os.walk( self._path ): previous_paths.update( ( os.path.join( root, filename ) for filename in filenames ) ) sync_paths = set() client_files_manager = HG.client_controller.client_files_manager num_copied = 0 for media_result in media_results: if HG.client_controller.new_options.GetBoolean( 'pause_export_folders_sync' ) or HydrusThreading.IsThreadShuttingDown(): return hash = media_result.GetHash() mime = media_result.GetMime() size = media_result.GetSize() try: source_path = client_files_manager.GetFilePath( hash, mime ) except HydrusExceptions.FileMissingException: raise Exception( 'A file to be exported, hash "{}", was missing! You should run file maintenance (under database->maintenance->files) to check the files for the export folder\'s search, and possibly all your files.' ) filename = GenerateExportFilename( self._path, media_result, terms ) dest_path = os.path.normpath( os.path.join( self._path, filename ) ) if not dest_path.startswith( self._path ): raise Exception( 'It seems a destination path for export folder "{}" was above the main export directory! The file was "{}" and its destination path was "{}".'.format( self._path, hash.hex(), dest_path ) ) dest_path_dir = os.path.dirname( dest_path ) HydrusPaths.MakeSureDirectoryExists( dest_path_dir ) if dest_path not in sync_paths: copied = HydrusPaths.MirrorFile( source_path, dest_path ) if copied: num_copied += 1 HydrusPaths.TryToGiveFileNicePermissionBits( dest_path ) sync_paths.add( dest_path ) if num_copied > 0: HydrusData.Print( 'Export folder ' + self._name + ' exported ' + HydrusData.ToHumanInt( num_copied ) + ' files.' ) if self._export_type == HC.EXPORT_FOLDER_TYPE_SYNCHRONISE: deletee_paths = previous_paths.difference( sync_paths ) for deletee_path in deletee_paths: ClientPaths.DeletePath( deletee_path ) deletee_dirs = set() for ( root, dirnames, filenames ) in os.walk( self._path, topdown = False ): if root == self._path: continue no_files = len( filenames ) == 0 useful_dirnames = [ dirname for dirname in dirnames if os.path.join( root, dirname ) not in deletee_dirs ] no_useful_dirs = len( useful_dirnames ) == 0 if no_useful_dirs and no_files: deletee_dirs.add( root ) for deletee_dir in deletee_dirs: if os.path.exists( deletee_dir ): HydrusPaths.DeletePath( deletee_dir ) if len( deletee_paths ) > 0: HydrusData.Print( 'Export folder {} deleted {} files and {} folders.'.format( self._name, HydrusData.ToHumanInt( len( deletee_paths ) ), HydrusData.ToHumanInt( len( deletee_dirs ) ) ) ) if self._delete_from_client_after_export: local_file_service_keys = HG.client_controller.services_manager.GetServiceKeys( ( HC.LOCAL_FILE_DOMAIN, ) ) service_keys_to_deletee_hashes = collections.defaultdict( list ) delete_lock_for_archived_files = HG.client_controller.new_options.GetBoolean( 'delete_lock_for_archived_files' ) for media_result in media_results: if delete_lock_for_archived_files and not media_result.GetInbox(): continue hash = media_result.GetHash() deletee_service_keys = media_result.GetLocationsManager().GetCurrent().intersection( local_file_service_keys ) for deletee_service_key in deletee_service_keys: service_keys_to_deletee_hashes[ deletee_service_key ].append( hash ) reason = 'Deleted after export to Export Folder "{}".'.format( self._path ) for ( service_key, deletee_hashes ) in service_keys_to_deletee_hashes.items(): chunks_of_hashes = HydrusData.SplitListIntoChunks( deletee_hashes, 64 ) for chunk_of_hashes in chunks_of_hashes: content_update = HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_DELETE, chunk_of_hashes, reason = reason ) HG.client_controller.WriteSynchronous( 'content_updates', { service_key : [ content_update ] } )
def _DoExport( self ): query_hash_ids = HG.client_controller.Read( 'file_query_ids', self._file_search_context ) media_results = [] i = 0 base = 256 while i < len( query_hash_ids ): if HC.options[ 'pause_export_folders_sync' ] or HydrusThreading.IsThreadShuttingDown(): return if i == 0: ( last_i, i ) = ( 0, base ) else: ( last_i, i ) = ( i, i + base ) sub_query_hash_ids = query_hash_ids[ last_i : i ] more_media_results = HG.client_controller.Read( 'media_results_from_ids', sub_query_hash_ids ) media_results.extend( more_media_results ) media_results.sort( key = lambda mr: mr.GetHashId() ) # terms = ParseExportPhrase( self._phrase ) previous_paths = set() for ( root, dirnames, filenames ) in os.walk( self._path ): previous_paths.update( ( os.path.join( root, filename ) for filename in filenames ) ) sync_paths = set() client_files_manager = HG.client_controller.client_files_manager num_copied = 0 for media_result in media_results: if HC.options[ 'pause_export_folders_sync' ] or HydrusThreading.IsThreadShuttingDown(): return hash = media_result.GetHash() mime = media_result.GetMime() size = media_result.GetSize() source_path = client_files_manager.GetFilePath( hash, mime ) filename = GenerateExportFilename( self._path, media_result, terms ) dest_path = os.path.normpath( os.path.join( self._path, filename ) ) if not dest_path.startswith( self._path ): raise Exception( 'It seems a destination path for export folder "{}" was above the main export directory! The file was "{}" and its destination path was "{}".'.format( self._path, hash.hex(), dest_path ) ) dest_path_dir = os.path.dirname( dest_path ) HydrusPaths.MakeSureDirectoryExists( dest_path_dir ) if dest_path not in sync_paths: copied = HydrusPaths.MirrorFile( source_path, dest_path ) if copied: num_copied += 1 HydrusPaths.MakeFileWritable( dest_path ) sync_paths.add( dest_path ) if num_copied > 0: HydrusData.Print( 'Export folder ' + self._name + ' exported ' + HydrusData.ToHumanInt( num_copied ) + ' files.' ) if self._export_type == HC.EXPORT_FOLDER_TYPE_SYNCHRONISE: deletee_paths = previous_paths.difference( sync_paths ) for deletee_path in deletee_paths: ClientPaths.DeletePath( deletee_path ) deletee_dirs = set() for ( root, dirnames, filenames ) in os.walk( self._path, topdown = False ): if root == self._path: continue no_files = len( filenames ) == 0 useful_dirnames = [ dirname for dirname in dirnames if os.path.join( root, dirname ) not in deletee_dirs ] no_useful_dirs = len( useful_dirnames ) == 0 if no_useful_dirs and no_files: deletee_dirs.add( root ) for deletee_dir in deletee_dirs: if os.path.exists( deletee_dir ): HydrusPaths.DeletePath( deletee_dir ) if len( deletee_paths ) > 0: HydrusData.Print( 'Export folder {} deleted {} files and {} folders.'.format( self._name, HydrusData.ToHumanInt( len( deletee_paths ) ), HydrusData.ToHumanInt( len( deletee_dirs ) ) ) ) if self._delete_from_client_after_export: deletee_hashes = { media_result.GetHash() for media_result in media_results } chunks_of_hashes = HydrusData.SplitListIntoChunks( deletee_hashes, 64 ) reason = 'Deleted after export to Export Folder "{}".'.format( self._path ) content_updates = [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_DELETE, chunk_of_hashes, reason = reason ) for chunk_of_hashes in chunks_of_hashes ] for content_update in content_updates: HG.client_controller.WriteSynchronous( 'content_updates', { CC.LOCAL_FILE_SERVICE_KEY : [ content_update ] } )
def LoadFromPNG( path ): # this is to deal with unicode paths, which cv2 can't handle ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: HydrusPaths.MirrorFile( path, temp_path ) numpy_image = cv2.imread( temp_path, flags = IMREAD_UNCHANGED ) except Exception as e: HydrusData.ShowException( e ) raise Exception( 'That did not appear to be a valid image!' ) finally: HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) try: try: ( height, width ) = numpy_image.shape except: raise Exception( 'The file did not appear to be monochrome!' ) try: complete_data = numpy_image.tostring() top_height_header = complete_data[:2] ( top_height, ) = struct.unpack( '!H', top_height_header ) payload_and_header_bytes = complete_data[ width * top_height : ] except: raise Exception( 'Header bytes were invalid!' ) try: payload_length_header = payload_and_header_bytes[:4] ( payload_bytes_length, ) = struct.unpack( '!I', payload_length_header ) payload_bytes = payload_and_header_bytes[ 4 : 4 + payload_bytes_length ] except: raise Exception( 'Payload bytes were invalid!' ) except Exception as e: message = 'The image loaded, but it did not seem to be a hydrus serialised png! The error was: {}'.format( str( e ) ) message += os.linesep * 2 message += 'If you believe this is a legit non-resized, non-converted hydrus serialised png, please send it to hydrus_dev.' raise Exception( message ) return payload_bytes
def LoadFromPNG(path): # this is to deal with unicode paths, which cv2 can't handle (os_file_handle, temp_path) = HydrusTemp.GetTempPath() try: HydrusPaths.MirrorFile(path, temp_path) try: # unchanged because we want exact byte data, no conversions or other gubbins numpy_image = cv2.imread(temp_path, flags=IMREAD_UNCHANGED) if numpy_image is None: raise Exception() except Exception as e: try: # dequantize = False because we don't want to convert to RGB pil_image = HydrusImageHandling.GeneratePILImage( temp_path, dequantize=False) numpy_image = HydrusImageHandling.GenerateNumPyImageFromPILImage( pil_image) except Exception as e: HydrusData.ShowException(e) raise Exception('That did not appear to be a valid image!') finally: HydrusTemp.CleanUpTempPath(os_file_handle, temp_path) try: height = numpy_image.shape[0] width = numpy_image.shape[1] if len(numpy_image.shape) > 2: depth = numpy_image.shape[2] if depth != 1: raise Exception('The file did not appear to be monochrome!') try: complete_data = numpy_image.tostring() top_height_header = complete_data[:2] (top_height, ) = struct.unpack('!H', top_height_header) payload_and_header_bytes = complete_data[width * top_height:] except: raise Exception('Header bytes were invalid!') try: payload_length_header = payload_and_header_bytes[:4] (payload_bytes_length, ) = struct.unpack('!I', payload_length_header) payload_bytes = payload_and_header_bytes[4:4 + payload_bytes_length] except: raise Exception('Payload bytes were invalid!') except Exception as e: HydrusData.PrintException(e) message = 'The image loaded, but it did not seem to be a hydrus serialised png! The error was: {}'.format( str(e)) message += os.linesep * 2 message += 'If you believe this is a legit non-resized, non-converted hydrus serialised png, please send it to hydrus_dev.' raise Exception(message) return payload_bytes
def DoFileExportDragDrop( window, page_key, media, alt_down ): drop_source = QG.QDrag( window ) data_object = QMimeDataHydrusFiles() # new_options = HG.client_controller.new_options do_secret_discord_dnd_fix = new_options.GetBoolean( 'secret_discord_dnd_fix' ) and alt_down # client_files_manager = HG.client_controller.client_files_manager original_paths = [] media_and_original_paths = [] total_size = 0 for m in media: hash = m.GetHash() mime = m.GetMime() total_size += m.GetSize() original_path = client_files_manager.GetFilePath( hash, mime, check_file_exists = False ) original_paths.append( original_path ) media_and_original_paths.append( ( m, original_path ) ) # discord_dnd_fix_possible = new_options.GetBoolean( 'discord_dnd_fix' ) and len( original_paths ) <= 50 and total_size < 200 * 1048576 temp_dir = HG.client_controller.temp_dir if do_secret_discord_dnd_fix: dnd_paths = original_paths flags = QC.Qt.MoveAction elif discord_dnd_fix_possible and os.path.exists( temp_dir ): fallback_filename_terms = ClientExporting.ParseExportPhrase( '{hash}' ) try: filename_pattern = new_options.GetString( 'discord_dnd_filename_pattern' ) filename_terms = ClientExporting.ParseExportPhrase( filename_pattern ) if len( filename_terms ) == 0: raise Exception() except: filename_terms = fallback_filename_terms dnd_paths = [] for ( m, original_path ) in media_and_original_paths: filename = ClientExporting.GenerateExportFilename( temp_dir, m, filename_terms ) if filename == HC.mime_ext_lookup[ m.GetMime() ]: filename = ClientExporting.GenerateExportFilename( temp_dir, m, fallback_filename_terms ) dnd_path = os.path.join( temp_dir, filename ) if not os.path.exists( dnd_path ): HydrusPaths.MirrorFile( original_path, dnd_path ) dnd_paths.append( dnd_path ) flags = QC.Qt.MoveAction | QC.Qt.CopyAction else: dnd_paths = original_paths flags = QC.Qt.CopyAction uri_list = [] for path in dnd_paths: uri_list.append( QC.QUrl.fromLocalFile( path ) ) data_object.setUrls( uri_list ) # hashes = [ m.GetHash() for m in media ] data_object.setHydrusFiles( page_key, hashes ) # old way of doing this that makes some external programs (discord) reject it ''' if page_key is None: encoded_page_key = None else: encoded_page_key = page_key.hex() data_obj = ( encoded_page_key, [ hash.hex() for hash in hashes ] ) data_str = json.dumps( data_obj ) data_bytes = bytes( data_str, 'utf-8' ) data_object.setData( 'application/hydrus-media', data_bytes ) ''' # drop_source.setMimeData( data_object ) result = drop_source.exec_( flags, QC.Qt.CopyAction ) return result
def do_it(directory, neighbouring_txt_tag_service_keys, delete_afterwards, export_symlinks, quit_afterwards): job_key = ClientThreading.JobKey(cancellable=True) job_key.SetStatusTitle('file export') HG.client_controller.pub('message', job_key) pauser = HydrusData.BigJobPauser() for (index, (ordering_index, media, path)) in enumerate(to_do): if job_key.IsCancelled(): break try: x_of_y = HydrusData.ConvertValueRangeToPrettyString( index + 1, num_to_do) job_key.SetVariable('popup_text_1', 'Done {}'.format(x_of_y)) job_key.SetVariable('popup_gauge_1', (index + 1, num_to_do)) QP.CallAfter(qt_update_label, x_of_y) hash = media.GetHash() mime = media.GetMime() path = os.path.normpath(path) if not path.startswith(directory): raise Exception( 'It seems a destination path was above the main export directory! The file was "{}" and its destination path was "{}".' .format(hash.hex(), path)) path_dir = os.path.dirname(path) HydrusPaths.MakeSureDirectoryExists(path_dir) if export_tag_txts: tags_manager = media.GetTagsManager() tags = set() for service_key in neighbouring_txt_tag_service_keys: current_tags = tags_manager.GetCurrent( service_key, ClientTags.TAG_DISPLAY_ACTUAL) tags.update(current_tags) tags = sorted(tags) txt_path = path + '.txt' with open(txt_path, 'w', encoding='utf-8') as f: f.write(os.linesep.join(tags)) source_path = client_files_manager.GetFilePath( hash, mime, check_file_exists=False) if export_symlinks: os.symlink(source_path, path) else: HydrusPaths.MirrorFile(source_path, path) HydrusPaths.MakeFileWriteable(path) except: QP.CallAfter( QW.QMessageBox.information, self, 'Information', 'Encountered a problem while attempting to export file with index ' + str(ordering_index + 1) + ':' + os.linesep * 2 + traceback.format_exc()) break pauser.Pause() if not job_key.IsCancelled() and delete_afterwards: QP.CallAfter(qt_update_label, 'deleting') delete_lock_for_archived_files = HG.client_controller.new_options.GetBoolean( 'delete_lock_for_archived_files') if delete_lock_for_archived_files: deletee_hashes = { media.GetHash() for (ordering_index, media, path) in to_do if not media.HasArchive() } else: deletee_hashes = { media.GetHash() for (ordering_index, media, path) in to_do } chunks_of_hashes = HydrusData.SplitListIntoChunks( deletee_hashes, 64) reason = 'Deleted after manual export to "{}".'.format( directory) content_updates = [ HydrusData.ContentUpdate(HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_DELETE, chunk_of_hashes, reason=reason) for chunk_of_hashes in chunks_of_hashes ] for content_update in content_updates: HG.client_controller.WriteSynchronous( 'content_updates', {CC.LOCAL_FILE_SERVICE_KEY: [content_update]}) job_key.DeleteVariable('popup_gauge_1') job_key.SetVariable('popup_text_1', 'Done!') job_key.Finish() job_key.Delete(5) QP.CallAfter(qt_update_label, 'done!') time.sleep(1) QP.CallAfter(qt_update_label, 'export') QP.CallAfter(qt_done, quit_afterwards)
def do_it(directory, neighbouring_txt_tag_service_keys, delete_afterwards, export_symlinks, quit_afterwards): pauser = HydrusData.BigJobPauser() for (index, (ordering_index, media)) in enumerate(to_do): try: QP.CallAfter( qt_update_label, HydrusData.ConvertValueRangeToPrettyString( index + 1, num_to_do)) hash = media.GetHash() mime = media.GetMime() path = self._GetPath(media) path = os.path.normpath(path) if not path.startswith(directory): raise Exception( 'It seems a destination path was above the main export directory! The file was "{}" and its destination path was "{}".' .format(hash.hex(), path)) path_dir = os.path.dirname(path) HydrusPaths.MakeSureDirectoryExists(path_dir) if export_tag_txts: tags_manager = media.GetTagsManager() tags = set() for service_key in neighbouring_txt_tag_service_keys: current_tags = tags_manager.GetCurrent( service_key, ClientTags.TAG_DISPLAY_SIBLINGS_AND_PARENTS) tags.update(current_tags) tags = sorted(tags) txt_path = path + '.txt' with open(txt_path, 'w', encoding='utf-8') as f: f.write(os.linesep.join(tags)) source_path = client_files_manager.GetFilePath( hash, mime, check_file_exists=False) if export_symlinks: os.symlink(source_path, path) else: HydrusPaths.MirrorFile(source_path, path) HydrusPaths.MakeFileWritable(path) except: QP.CallAfter( QW.QMessageBox.information, self, 'Information', 'Encountered a problem while attempting to export file with index ' + str(ordering_index + 1) + ':' + os.linesep * 2 + traceback.format_exc()) break pauser.Pause() if delete_afterwards: QP.CallAfter(qt_update_label, 'deleting') deletee_hashes = { media.GetHash() for (ordering_index, media) in to_do } chunks_of_hashes = HydrusData.SplitListIntoChunks( deletee_hashes, 64) reason = 'Deleted after manual export to "{}".'.format( directory) content_updates = [ HydrusData.ContentUpdate(HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_DELETE, chunk_of_hashes, reason=reason) for chunk_of_hashes in chunks_of_hashes ] for content_update in content_updates: HG.client_controller.WriteSynchronous( 'content_updates', {CC.LOCAL_FILE_SERVICE_KEY: [content_update]}) QP.CallAfter(qt_update_label, 'done!') time.sleep(1) QP.CallAfter(qt_update_label, 'export') QP.CallAfter(qt_done, quit_afterwards)