Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
    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)