def _GetPath(self, media): if media in self._media_to_paths: return self._media_to_paths[media] directory = self._directory_picker.GetPath() pattern = self._pattern.text() terms = ClientExporting.ParseExportPhrase(pattern) filename = ClientExporting.GenerateExportFilename( directory, media, terms, do_not_use_filenames=self._existing_filenames) path = os.path.join(directory, filename) path = os.path.normpath(path) self._existing_filenames.add(filename) self._media_to_paths[media] = path return path
def GetValue(self): name = self._name.text() path = self._path.GetPath() export_type = self._type.GetValue() delete_from_client_after_export = self._delete_from_client_after_export.isChecked( ) file_search_context = self._tag_autocomplete.GetFileSearchContext() run_regularly = self._run_regularly.isChecked() period = self._period.GetValue() if self._path.GetPath() in ('', None): raise HydrusExceptions.VetoException( 'You must enter a folder path to export to!') phrase = self._pattern.text() try: ClientExporting.ParseExportPhrase(phrase) except Exception as e: raise HydrusExceptions.VetoException( 'Could not parse that export phrase! ' + str(e)) run_now = self._run_now.isChecked() paused = self._paused.isChecked() last_error = self._export_folder.GetLastError() export_folder = ClientExporting.ExportFolder( name, path=path, export_type=export_type, delete_from_client_after_export=delete_from_client_after_export, file_search_context=file_search_context, run_regularly=run_regularly, period=period, phrase=phrase, last_checked=self._last_checked, paused=paused, run_now=run_now, last_error=last_error) return export_folder
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 _DoExport(self, quit_afterwards=False): delete_afterwards = self._delete_files_after_export.isChecked() export_symlinks = self._export_symlinks.isChecked( ) and not delete_afterwards if quit_afterwards: message = 'Export as shown?' if delete_afterwards: message += os.linesep * 2 message += 'THE FILES WILL BE DELETED FROM THE CLIENT AFTERWARDS' result = ClientGUIDialogsQuick.GetYesNo(self, message) if result != QW.QDialog.Accepted: self.parentWidget().close() return elif delete_afterwards: message = 'THE FILES WILL BE DELETED FROM THE CLIENT AFTERWARDS' result = ClientGUIDialogsQuick.GetYesNo(self, message) if result != QW.QDialog.Accepted: return self._RefreshPaths() export_tag_txts = self._export_tag_txts.isChecked() if self._export_tag_txts.isChecked(): neighbouring_txt_tag_service_keys = self._neighbouring_txt_tag_service_keys else: neighbouring_txt_tag_service_keys = [] directory = self._directory_picker.GetPath() HydrusPaths.MakeSureDirectoryExists(directory) pattern = self._pattern.text() HG.client_controller.new_options.SetString('export_phrase', pattern) try: terms = ClientExporting.ParseExportPhrase(pattern) except Exception as e: QW.QMessageBox.critical(self, 'Error', str(e)) return client_files_manager = HG.client_controller.client_files_manager self._export.setEnabled(False) to_do = self._paths.GetData() to_do = [(ordering_index, media, self._GetPath(media)) for (ordering_index, media) in to_do] num_to_do = len(to_do) def qt_update_label(text): if not QP.isValid(self) or not QP.isValid( self._export) or not self._export: return self._export.setText(text) def qt_done(quit_afterwards): if not QP.isValid(self) or not QP.isValid( self._export) or not self._export: return self._export.setEnabled(True) if quit_afterwards: QP.CallAfter(self.parentWidget().close) 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) HG.client_controller.CallToThread(do_it, directory, neighbouring_txt_tag_service_keys, delete_afterwards, export_symlinks, quit_afterwards)