コード例 #1
0
 def EventClear( self ):
     
     from hydrus.client.gui import ClientGUIDialogsQuick
     
     result = ClientGUIDialogsQuick.GetYesNo( self, 'Clear recent tags?' )
     
     if result == QW.QDialog.Accepted:
         
         HG.client_controller.Write( 'push_recent_tags', self._service_key, None )
         
         self._last_fetched_tags = []
         
         self._UpdateTagDisplay()
コード例 #2
0
    def UserIsOKToOK(self):

        if self._delete_from_client_after_export.isChecked():

            message = 'You have set this export folder to delete the files from the client after export! Are you absolutely sure this is what you want?'

            result = ClientGUIDialogsQuick.GetYesNo(self, message)

            if result != QW.QDialog.Accepted:

                return False

        return True
コード例 #3
0
    def _DeleteSelected(self):

        file_seeds_to_delete = self._list_ctrl.GetData(only_selected=True)

        if len(file_seeds_to_delete) > 0:

            message = 'Are you sure you want to delete the {} selected entries?'.format(
                HydrusData.ToHumanInt(len(file_seeds_to_delete)))

            result = ClientGUIDialogsQuick.GetYesNo(self, message)

            if result == QW.QDialog.Accepted:

                self._file_seed_cache.RemoveFileSeeds(file_seeds_to_delete)
コード例 #4
0
    def ImportFromDragDrop(self, paths):

        from hydrus.client.gui import ClientGUIDialogsQuick

        message = 'Try to import the ' + HydrusData.ToHumanInt(len(
            paths)) + ' dropped files to this list? I am expecting png files.'

        result = ClientGUIDialogsQuick.GetYesNo(self, message)

        if result == QW.QDialog.Accepted:

            self._ImportPngs(paths)

            self._listctrl.Sort()
コード例 #5
0
    def _DeleteSelected(self):

        gallery_seeds_to_delete = self._list_ctrl.GetData(only_selected=True)

        if len(gallery_seeds_to_delete) > 0:

            message = 'Are you sure you want to delete the {} selected entries? This is only useful if you have a really really huge list.'.format(
                HydrusData.ToHumanInt(len(gallery_seeds_to_delete)))

            result = ClientGUIDialogsQuick.GetYesNo(self, message)

            if result == QW.QDialog.Accepted:

                self._gallery_seed_log.RemoveGallerySeeds(
                    gallery_seeds_to_delete)
コード例 #6
0
    def _ClearGallerySeeds(self, statuses_to_remove):

        st_text = '/'.join(
            (CC.status_string_lookup[status] for status in statuses_to_remove))

        message = 'Are you sure you want to delete all the {} {} log entries? This is useful for cleaning up and de-laggifying a very large list, but be careful you aren\'t removing something you would want to revisit.'.format(
            st_text, self._gallery_type_string)

        result = ClientGUIDialogsQuick.GetYesNo(self, message)

        if result == QW.QDialog.Accepted:

            gallery_seed_log = self._gallery_seed_log_get_callable()

            gallery_seed_log.RemoveGallerySeedsByStatus(statuses_to_remove)
コード例 #7
0
    def _SetSelected(self, status_to_set):

        file_seeds = self._list_ctrl.GetData(only_selected=True)

        if status_to_set == CC.STATUS_UNKNOWN:

            deleted_and_clearable_file_seeds = [
                file_seed for file_seed in file_seeds
                if file_seed.IsDeleted() and file_seed.HasHash()
            ]

            if len(deleted_and_clearable_file_seeds) > 0:

                message = 'One or more of these files did not import due to being previously deleted. They will likely fail again unless you erase those deletion records. Would you like to do this now?'

                result = ClientGUIDialogsQuick.GetYesNo(self, message)

                if result == QW.QDialog.DialogCode.Accepted:

                    deletee_hashes = {
                        file_seed.GetHash()
                        for file_seed in deleted_and_clearable_file_seeds
                    }

                    content_update_erase_record = HydrusData.ContentUpdate(
                        HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ADVANCED,
                        ('delete_deleted', deletee_hashes))
                    content_update_undelete_from_trash = HydrusData.ContentUpdate(
                        HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_UNDELETE,
                        deletee_hashes)

                    service_keys_to_content_updates = {
                        CC.COMBINED_LOCAL_FILE_SERVICE_KEY: [
                            content_update_erase_record,
                            content_update_undelete_from_trash
                        ]
                    }

                    HG.client_controller.WriteSynchronous(
                        'content_updates', service_keys_to_content_updates)

        for file_seed in file_seeds:

            file_seed.SetStatus(status_to_set)

        self._file_seed_cache.NotifyFileSeedsUpdated(file_seeds)
コード例 #8
0
    def ImportFromDragDrop(self, paths):

        from hydrus.client.gui import ClientGUIDialogsQuick

        message = 'Try to import the {} dropped files to this list? I am expecting json or png files.'.format(
            HydrusData.ToHumanInt(len(paths)))

        result = ClientGUIDialogsQuick.GetYesNo(self, message)

        if result == QW.QDialog.Accepted:

            (jsons, pngs) = HydrusData.PartitionIteratorIntoLists(
                lambda path: path.endswith('.png'), paths)

            self._ImportPNGs(pngs)
            self._ImportJSONs(jsons)

            self._listctrl.Sort()
コード例 #9
0
    def _OpenSelectedGalleryURLs(self):

        gallery_seeds = self._list_ctrl.GetData(only_selected=True)

        if len(gallery_seeds) > 0:

            if len(gallery_seeds) > 10:

                message = 'You have many objects selected--are you sure you want to open them all?'

                result = ClientGUIDialogsQuick.GetYesNo(self, message)

                if result != QW.QDialog.Accepted:

                    return

            for gallery_seed in gallery_seeds:

                ClientPaths.LaunchURLInWebBrowser(gallery_seed.url)
コード例 #10
0
def RemovePotentials(win, hashes):

    if len(hashes) == 1:

        message = 'Are you sure you want to remove all of this file\'s potentials?'
        message += os.linesep * 2
        message += 'This will mean it (or any of its duplicates) will not appear in the duplicate filter unless new potentials are found with new files. Use this command if the file has accidentally received many false positive potential relationships.'

    else:

        message = 'Are you sure you want to remove all of these {} files\' potentials?'.format(
            HydrusData.ToHumanInt(len(hashes)))
        message += os.linesep * 2
        message += 'This will mean they (or any of their duplicates) will not appear in the duplicate filter unless new potentials are found with new files. Use this command if the files have accidentally received many false positive potential relationships.'

    result = ClientGUIDialogsQuick.GetYesNo(win, message)

    if result == QW.QDialog.Accepted:

        HG.client_controller.Write('remove_potential_pairs', hashes)
コード例 #11
0
def ResetPotentialSearch(win, hashes):

    if len(hashes) == 1:

        message = 'Are you sure you want to search this file for potential duplicates again?'
        message += os.linesep * 2
        message += 'This will not remove any existing potential pairs, and will typically not find any new relationships unless an error has occured.'

    else:

        message = 'Are you sure you want to search these {} files for potential duplicates again?'.format(
            HydrusData.ToHumanInt(len(hashes)))
        message += os.linesep * 2
        message += 'This will not remove any existing potential pairs, and will typically not find any new relationships unless an error has occured.'

    result = ClientGUIDialogsQuick.GetYesNo(win, message)

    if result == QW.QDialog.Accepted:

        HG.client_controller.Write('reset_potential_search_status', hashes)
コード例 #12
0
    def _Remove(self):

        text = 'Remove these port mappings?'
        text += os.linesep * 2
        text += 'If a mapping does not disappear after a remove, it may be hard-added in the router\'s settings interface. In this case, you will have to go there to fix it.'

        result = ClientGUIDialogsQuick.GetYesNo(self,
                                                text,
                                                yes_label='do it',
                                                no_label='forget it')

        if result != QW.QDialog.Accepted:

            return

        selected_mappings = self._mappings_list.GetData(only_selected=True)

        def work_callable():

            for selected_mapping in selected_mappings:

                (description, internal_ip, internal_port, external_port,
                 protocol, duration) = selected_mapping

                HydrusNATPunch.RemoveUPnPMapping(external_port, protocol)

            return True

        def publish_callable(result):

            self._mappings_listctrl_panel.setEnabled(True)

            self._RefreshMappings()

        self._mappings_listctrl_panel.setEnabled(False)

        async_job = ClientGUIAsync.AsyncQtJob(self, work_callable,
                                              publish_callable)

        async_job.start()
コード例 #13
0
    def UserIsOKToCancel(self):

        if self._job_key.IsDone():

            self._ReleaseMessage()

        elif self._job_key.IsCancellable():

            text = 'Cancel/stop job?'

            self._yesno_open = True

            try:

                result = ClientGUIDialogsQuick.GetYesNo(self, text)

            finally:

                self._yesno_open = False

            if result == QW.QDialog.Accepted:

                self._job_key.Cancel()

                self._ReleaseMessage()

            else:

                return False

        else:

            QW.QMessageBox.warning(
                self, 'Warning',
                'Unfortunately, this job cannot be cancelled. If it really is taking too long, please kill the client through task manager.'
            )

            return False

        return True
コード例 #14
0
 def _OpenSelectedFileSeedData( self ):
     
     file_seeds = self._list_ctrl.GetData( only_selected = True )
     
     if len( file_seeds ) > 0:
         
         if len( file_seeds ) > 10:
             
             message = 'You have many objects selected--are you sure you want to open them all?'
             
             result = ClientGUIDialogsQuick.GetYesNo( self, message )
             
             if result != QW.QDialog.Accepted:
                 
                 return
                 
             
         
         if file_seeds[0].file_seed_data.startswith( 'http' ):
             
             for file_seed in file_seeds:
                 
                 ClientPaths.LaunchURLInWebBrowser( file_seed.file_seed_data )
                 
             
         else:
             
             try:
                 
                 for file_seed in file_seeds:
                     
                     HydrusPaths.OpenFileLocation( file_seed.file_seed_data )
                     
                 
             except Exception as e:
                 
                 QW.QMessageBox.critical( self, 'Error', str(e) )
コード例 #15
0
def DissolveDuplicateGroup(win, hashes):

    if len(hashes) == 1:

        message = 'Are you sure you want to dissolve this file\'s duplicate group?'
        message += os.linesep * 2
        message += 'This will split the duplicates group back into individual files and remove any alternate relations they have. They will be queued back up in the duplicate filter for reprocessing.'
        message += os.linesep * 2
        message += 'This could be a big change that throws away many previous decisions and cannot be undone. If you can achieve your result just by removing one or two members, do that instead.'

    else:

        message = 'Are you sure you want to dissolve these {} files\' duplicate groups?'.format(
            HydrusData.ToHumanInt(len(hashes)))
        message += os.linesep * 2
        message += 'This will split all the files\' duplicates groups back into individual files and remove any alternate relations they have. They will all be queued back up in the duplicate filter for reprocessing.'
        message += os.linesep * 2
        message += 'This could be a huge change that throws away many previous decisions and cannot be undone. If you can achieve your result just by removing some members, do that instead.'

    result = ClientGUIDialogsQuick.GetYesNo(win, message)

    if result == QW.QDialog.Accepted:

        HG.client_controller.Write('dissolve_duplicates_group', hashes)
コード例 #16
0
def RemoveFromAlternateGroup(win, hashes):

    if len(hashes) == 1:

        message = 'Are you sure you want to remove this file from its alternates group?'
        message += os.linesep * 2
        message += 'Alternate relationships are stored between duplicate groups, so this will pull any duplicates of your file with it.'
        message += os.linesep * 2
        message += 'The removed file (and any duplicates) will be queued up for another potential duplicates search, so you will likely see at least one again in the duplicate filter.'

    else:

        message = 'Are you sure you want to remove these {} files from their alternates groups?'.format(
            HydrusData.ToHumanInt(len(hashes)))
        message += os.linesep * 2
        message += 'Alternate relationships are stored between duplicate groups, so this will pull any duplicates of these files with them.'
        message += os.linesep * 2
        message += 'The removed files (and any duplicates) will be queued up for another potential duplicates search, so you will likely see some again in the duplicate filter.'

    result = ClientGUIDialogsQuick.GetYesNo(win, message)

    if result == QW.QDialog.Accepted:

        HG.client_controller.Write('remove_alternates_member', hashes)
コード例 #17
0
def ClearFalsePositives(win, hashes):

    if len(hashes) == 1:

        message = 'Are you sure you want to clear this file of its false-positive relations?'
        message += os.linesep * 2
        message += 'False-positive relations are recorded between alternate groups, so this change will also affect any files this file is alternate to.'
        message += os.linesep * 2
        message += 'All affected files will be queued up for another potential duplicates search, so you will likely see at least one of them again in the duplicate filter.'

    else:

        message = 'Are you sure you want to clear these {} files of their false-positive relations?'.format(
            HydrusData.ToHumanInt(len(hashes)))
        message += os.linesep * 2
        message += 'False-positive relations are recorded between alternate groups, so this change will also affect all alternate files to your selection.'
        message += os.linesep * 2
        message += 'All affected files will be queued up for another potential duplicates search, so you will likely see some of them again in the duplicate filter.'

    result = ClientGUIDialogsQuick.GetYesNo(win, message)

    if result == QW.QDialog.Accepted:

        HG.client_controller.Write('clear_false_positive_relations', hashes)
コード例 #18
0
def DissolveAlternateGroup(win, hashes):

    if len(hashes) == 1:

        message = 'Are you sure you want to dissolve this file\'s entire alternates group?'
        message += os.linesep * 2
        message += 'This will completely remove all duplicate, alternate, and false-positive relations for all files in the group and set them to come up again in the duplicate filter.'
        message += os.linesep * 2
        message += 'This is a potentially big change that throws away many previous decisions and cannot be undone. If you can achieve your result just by removing some alternate members, do that instead.'

    else:

        message = 'Are you sure you want to dissolve these {} files\' entire alternates groups?'.format(
            HydrusData.ToHumanInt(len(hashes)))
        message += os.linesep * 2
        message += 'This will completely remove all duplicate, alternate, and false-positive relations for all alternate groups of all files selected and set them to come up again in the duplicate filter.'
        message += os.linesep * 2
        message += 'This is a potentially huge change that throws away many previous decisions and cannot be undone. If you can achieve your result just by removing some alternate members, do that instead.'

    result = ClientGUIDialogsQuick.GetYesNo(win, message)

    if result == QW.QDialog.Accepted:

        HG.client_controller.Write('dissolve_alternates_group', hashes)
コード例 #19
0
def RemoveFromDuplicateGroup(win, hashes):

    if len(hashes) == 1:

        message = 'Are you sure you want to remove this file from its duplicate group?'
        message += os.linesep * 2
        message += 'The remaining group will be otherwise unaffected and will keep its alternate relationships.'
        message += os.linesep * 2
        message += 'The removed file will be queued up for another potential duplicates search, so you will likely see it again in the duplicate filter.'

    else:

        message = 'Are you sure you want to remove these {} files from their duplicate groups?'.format(
            HydrusData.ToHumanInt(len(hashes)))
        message += os.linesep * 2
        message += 'The remaining groups will be otherwise unaffected and keep their alternate relationships.'
        message += os.linesep * 2
        message += 'The removed files will be queued up for another potential duplicates search, so you will likely see them again in the duplicate filter.'

    result = ClientGUIDialogsQuick.GetYesNo(win, message)

    if result == QW.QDialog.Accepted:

        HG.client_controller.Write('remove_duplicates_member', hashes)
コード例 #20
0
    def _ImportURLs(self, urls):

        gallery_seed_log = self._gallery_seed_log_get_callable()

        urls = HydrusData.DedupeList(urls)

        filtered_urls = [
            url for url in urls if not gallery_seed_log.HasGalleryURL(url)
        ]

        urls_to_add = urls

        if len(filtered_urls) < len(urls):

            num_urls = len(urls)
            num_removed = num_urls - len(filtered_urls)

            message = 'Of the ' + HydrusData.ToHumanInt(
                num_urls
            ) + ' URLs you mean to add, ' + HydrusData.ToHumanInt(
                num_removed
            ) + ' are already in the search log. Would you like to only add new URLs or add everything (which will force a re-check of the duplicates)?'

            (result, was_cancelled) = ClientGUIDialogsQuick.GetYesNo(
                self,
                message,
                yes_label='only add new urls',
                no_label='add all urls, even duplicates',
                check_for_cancelled=True)

            if was_cancelled:

                return

            if result == QW.QDialog.Accepted:

                urls_to_add = filtered_urls

            elif result == QW.QDialog.Rejected:

                return

        can_generate_more_pages = False

        if self._can_generate_more_pages:

            message = 'Would you like these urls to only check for new files, or would you like them to also generate subsequent gallery pages, like a regular search would?'

            (result, was_cancelled) = ClientGUIDialogsQuick.GetYesNo(
                self,
                message,
                yes_label='just check what I am adding',
                no_label='start a potential new search for every url added',
                check_for_cancelled=True)

            if was_cancelled:

                return

            can_generate_more_pages = result == QW.QDialog.Rejected

        gallery_seeds = [
            ClientImportGallerySeeds.GallerySeed(
                url, can_generate_more_pages=can_generate_more_pages)
            for url in urls_to_add
        ]

        gallery_seed_log.AddGallerySeeds(gallery_seeds)
コード例 #21
0
    def _Delete(self):

        result = ClientGUIDialogsQuick.GetYesNo(self, 'Remove all selected?')

        if result == QW.QDialog.Accepted:

            account_types_about_to_delete = self._account_types_listctrl.GetData(
                only_selected=True)

            if True in (at.IsNullAccount()
                        for at in account_types_about_to_delete):

                QW.QMessageBox.critical(
                    self, 'Error', 'You cannot delete the null account type!')

                return

            all_real_account_types = set([
                at for at in self._account_types_listctrl.GetData()
                if not at.IsNullAccount()
            ])

            account_types_can_move_to = all_real_account_types.difference(
                account_types_about_to_delete)

            if len(account_types_can_move_to) == 0:

                QW.QMessageBox.critical(
                    self, 'Error', 'You cannot delete every account type!')

                return

            for deletee_account_type in account_types_about_to_delete:

                if len(account_types_can_move_to) > 1:

                    deletee_title = deletee_account_type.GetTitle()

                    choice_tuples = [
                        (account_type.GetTitle(), account_type)
                        for account_type in account_types_can_move_to
                    ]

                    try:

                        new_account_type = ClientGUIDialogsQuick.SelectFromList(
                            self, 'what should deleted ' + deletee_title +
                            ' accounts become?', choice_tuples)

                    except HydrusExceptions.CancelledException:

                        return

                else:

                    (new_account_type, ) = account_types_can_move_to

                deletee_account_type_key = deletee_account_type.GetAccountTypeKey(
                )
                new_account_type_key = new_account_type.GetAccountTypeKey()

                self._deletee_account_type_keys_to_new_account_type_keys[
                    deletee_account_type_key] = new_account_type_key

            self._account_types_listctrl.DeleteSelected()
コード例 #22
0
def MoveOrDuplicateLocalFiles( win: QW.QWidget, dest_service_key: bytes, action: int, media: typing.Collection[ ClientMedia.MediaSingleton ], source_service_key: typing.Optional[ bytes ] = None ):
    
    dest_service_name = HG.client_controller.services_manager.GetName( dest_service_key )
    
    applicable_media = [ m for m in media if m.GetLocationsManager().IsLocal() and dest_service_key not in m.GetLocationsManager().GetCurrent() and m.GetMime() not in HC.HYDRUS_UPDATE_FILES ]
    
    if len( applicable_media ) == 0:
        
        return
        
    
    ( local_duplicable_to_file_service_keys, local_moveable_from_and_to_file_service_keys ) = GetLocalFileActionServiceKeys( media )
    
    do_yes_no = True
    yes_no_text = 'Add {} files to {}?'.format( HydrusData.ToHumanInt( len( applicable_media ) ), dest_service_name )
    
    if action == HC.CONTENT_UPDATE_MOVE:
        
        local_moveable_from_and_to_file_service_keys = { pair for pair in local_moveable_from_and_to_file_service_keys if pair[1] == dest_service_key }
        
        potential_source_service_keys = { pair[0] for pair in local_moveable_from_and_to_file_service_keys }
        
        potential_source_service_keys_to_applicable_media = collections.defaultdict( list )
        
        for m in applicable_media:
            
            current = m.GetLocationsManager().GetCurrent()
            
            for potential_source_service_key in potential_source_service_keys:
                
                if potential_source_service_key in current:
                    
                    potential_source_service_keys_to_applicable_media[ potential_source_service_key ].append( m )
                    
                
            
        
        if source_service_key is None:
            
            if len( potential_source_service_keys ) == 0:
                
                return
                
            elif len( potential_source_service_keys ) == 1:
                
                ( source_service_key, ) = potential_source_service_keys
                
            else:
                
                do_yes_no = False
                
                num_applicable_media = len( applicable_media )
                
                choice_tuples = []
                
                for potential_source_service_key in potential_source_service_keys:
                    
                    potential_source_service_name = HG.client_controller.services_manager.GetName( potential_source_service_key )
                    
                    text = 'move {} in "{}" to "{}"'.format( len( potential_source_service_keys_to_applicable_media[ potential_source_service_key ] ), potential_source_service_name, dest_service_name )
                    
                    description = 'Move from {} to {}.'.format( potential_source_service_name, dest_service_name )
                    
                    choice_tuples.append( ( text, potential_source_service_key, description ) )
                    
                
                choice_tuples.sort()
                
                try:
                    
                    source_service_key = ClientGUIDialogsQuick.SelectFromListButtons( win, 'select source service', choice_tuples, message = 'Select where we are moving from. Note this may not cover all files.' )
                    
                except HydrusExceptions.CancelledException:
                    
                    return
                    
                
            
        
        source_service_name = HG.client_controller.services_manager.GetName( source_service_key )
        
        applicable_media = potential_source_service_keys_to_applicable_media[ source_service_key ]
        
        yes_no_text = 'Move {} files from {} to {}?'.format( HydrusData.ToHumanInt( len( applicable_media ) ), source_service_name, dest_service_name )
        
    
    if len( applicable_media ) == 0:
        
        return
        
    
    if do_yes_no:
        
        result = ClientGUIDialogsQuick.GetYesNo( win, yes_no_text )
        
        if result != QW.QDialog.Accepted:
            
            return
            
        
    
    def work_callable():
        
        job_key = ClientThreading.JobKey( cancellable = True )
        
        title = 'moving files' if action == HC.CONTENT_UPDATE_MOVE else 'adding files'
        
        job_key.SetStatusTitle( title )
        
        BLOCK_SIZE = 64
        
        if len( applicable_media ) > BLOCK_SIZE:
            
            HG.client_controller.pub( 'message', job_key )
            
        
        pauser = HydrusData.BigJobPauser()
        
        num_to_do = len( applicable_media )
        
        now = HydrusData.GetNow()
        
        for ( i, block_of_media ) in enumerate( HydrusData.SplitListIntoChunks( applicable_media, BLOCK_SIZE ) ):
            
            if job_key.IsCancelled():
                
                break
                
            
            job_key.SetVariable( 'popup_text_1', HydrusData.ConvertValueRangeToPrettyString( i * BLOCK_SIZE, num_to_do ) )
            job_key.SetVariable( 'popup_gauge_1', ( i * BLOCK_SIZE, num_to_do ) )
            
            content_updates = []
            undelete_hashes = set()
            
            for m in block_of_media:
                
                if dest_service_key in m.GetLocationsManager().GetDeleted():
                    
                    undelete_hashes.add( m.GetHash() )
                    
                else:
                    
                    content_updates.append( HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ADD, ( m.GetMediaResult().GetFileInfoManager(), now ) ) )
                    
                
            
            if len( undelete_hashes ) > 0:
                
                content_updates.append( HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_UNDELETE, undelete_hashes ) )
                
            
            HG.client_controller.WriteSynchronous( 'content_updates', { dest_service_key : content_updates } )
            
            if action == HC.CONTENT_UPDATE_MOVE:
                
                block_of_hashes = [ m.GetHash() for m in block_of_media ]
                
                content_updates = [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_DELETE, block_of_hashes, reason = 'Moved to {}'.format( dest_service_name ) ) ]
                
                HG.client_controller.WriteSynchronous( 'content_updates', { source_service_key : content_updates } )
                
            
            pauser.Pause()
            
        
        job_key.Delete()
        
    
    def publish_callable( result ):
        
        pass
        
    
    job = ClientGUIAsync.AsyncQtJob( win, work_callable, publish_callable )
    
    job.start()
コード例 #23
0
def OpenURLs(urls):

    urls = sorted(urls)

    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.'

        tlw = HG.client_controller.GetMainTLW()

        result = ClientGUIDialogsQuick.GetYesNo(tlw, message)

        if result != QW.QDialog.Accepted:

            return

    def do_it(urls):

        job_key = None

        num_urls = len(urls)

        if num_urls > 5:

            job_key = ClientThreading.JobKey(pausable=True, cancellable=True)

            job_key.SetVariable('popup_title', 'Opening URLs')

            HG.client_controller.pub('message', job_key)

        try:

            for (i, url) in enumerate(urls):

                if job_key is not None:

                    (i_paused, should_quit) = job_key.WaitIfNeeded()

                    if should_quit:

                        return

                    job_key.SetVariable(
                        'popup_text_1',
                        HydrusData.ConvertValueRangeToPrettyString(
                            i + 1, num_urls))
                    job_key.SetVariable('popup_gauge_1', (i + 1, num_urls))

                ClientPaths.LaunchURLInWebBrowser(url)

                time.sleep(1)

        finally:

            if job_key is not None:

                job_key.Finish()

                job_key.Delete(1)

    HG.client_controller.CallToThread(do_it, urls)
コード例 #24
0
def UndeleteMedia( win, media ):
    
    media_deleted_service_keys = HydrusData.MassUnion( ( m.GetLocationsManager().GetDeleted() for m in media ) )
    
    local_file_services = HG.client_controller.services_manager.GetServices( ( HC.LOCAL_FILE_DOMAIN, ) )
    
    undeletable_services = [ local_file_service for local_file_service in local_file_services if local_file_service.GetServiceKey() in media_deleted_service_keys ]
    
    if len( undeletable_services ) > 0:
        
        do_it = False
        
        if len( undeletable_services ) > 1:
            
            choice_tuples = []
            
            for ( i, service ) in enumerate( undeletable_services ):
                
                choice_tuples.append( ( service.GetName(), service, 'Undelete back to {}.'.format( service.GetName() ) ) )
                
            
            if len( choice_tuples ) > 1:
                
                service = HG.client_controller.services_manager.GetService( CC.COMBINED_LOCAL_MEDIA_SERVICE_KEY )
                
                choice_tuples.append( ( 'all the above', service, 'Undelete back to all services the files have been deleted from.' ) )
                
            
            try:
                
                undelete_service = ClientGUIDialogsQuick.SelectFromListButtons( win, 'Undelete for?', choice_tuples )
                
                do_it = True
                
            except HydrusExceptions.CancelledException:
                
                return
                
            
        else:
    
            ( undelete_service, ) = undeletable_services
            
            if HC.options[ 'confirm_trash' ]:
                
                result = ClientGUIDialogsQuick.GetYesNo( win, 'Undelete this file back to {}?'.format( undelete_service.GetName() ) )
                
                if result == QW.QDialog.Accepted:
                    
                    do_it = True
                    
                
            else:
                
                do_it = True
                
            
        
        if do_it:
            
            for chunk_of_media in HydrusData.SplitIteratorIntoChunks( media, 64 ):
                
                service_keys_to_content_updates = collections.defaultdict( list )
                
                service_key = undelete_service.GetServiceKey()
                
                undeletee_hashes = [ m.GetHash() for m in chunk_of_media if service_key in m.GetLocationsManager().GetDeleted() ]
                
                service_keys_to_content_updates[ service_key ] = [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_UNDELETE, undeletee_hashes ) ]
                
                HG.client_controller.Write( 'content_updates', service_keys_to_content_updates )
コード例 #25
0
ファイル: ClientGUIExport.py プロジェクト: floogulinc/hydrus
    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)
コード例 #26
0
 def _DoBan( self ):
     
     subject_accounts = self._account_panel.GetCheckedAccounts()
     
     if len( subject_accounts ) == 0:
         
         QW.QMessageBox.information( self, 'Information', 'No accounts selected for action!' )
         
         return
         
     
     some_are_banned =  True in ( subject_account.IsBanned() for subject_account in subject_accounts )
     
     if some_are_banned:
         
         message = 'Some of these selected accounts are already banned. Sure you want to overwrite the bans?'
         
         result = ClientGUIDialogsQuick.GetYesNo( self, message )
         
         if result != QW.QDialog.Accepted:
             
             return
             
         
     
     subject_account_keys = [ subject_account.GetAccountKey() for subject_account in subject_accounts ]
     
     reason = self._ban_reason.text()
     
     if reason == '':
         
         QW.QMessageBox.information( self, 'Information', 'The ban reason is empty!' )
         
         return
         
     
     message = 'Ban these user(s)? All of their pending petitions will be deleted serverside.'
     
     result = ClientGUIDialogsQuick.GetYesNo( self, message )
     
     if result != QW.QDialog.Accepted:
         
         return
         
     
     expires = self._ban_expires.GetValue()
     
     if expires is not None:
         
         expires += HydrusData.GetNow()
         
     
     service = self._service
     
     def work_callable():
         
         for subject_account_key in subject_account_keys:
             
             service.Request( HC.POST, 'modify_account_ban', { 'subject_identifier' : HydrusNetwork.AccountIdentifier( account_key = subject_account_key ), 'reason' : reason, 'expires' : expires } )
             
         
         return 1
         
     
     def publish_callable( gumpf ):
         
         QW.QMessageBox.information( self, 'Information', 'Done!' )
         
         self._account_panel.RefreshAccounts()
         
     
     self._DisableUIForJob( 'banning\u2026' )
     
     job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable )
     
     job.start()
コード例 #27
0
    def _Add(self):

        external_port = HC.DEFAULT_SERVICE_PORT
        protocol = 'TCP'
        internal_port = HC.DEFAULT_SERVICE_PORT
        description = 'hydrus service'
        duration = 0

        with ClientGUIDialogs.DialogInputUPnPMapping(self, external_port,
                                                     protocol, internal_port,
                                                     description,
                                                     duration) as dlg:

            if dlg.exec() == QW.QDialog.Accepted:

                (external_port, protocol, internal_port, description,
                 duration) = dlg.GetInfo()

                remove_existing = False

                if self._MappingExists(external_port, protocol):

                    remove_existing = True

                    text = '{}:({}) is already mapped! Ok to overwrite whatever it currently is?'

                    result = ClientGUIDialogsQuick.GetYesNo(
                        self, text, yes_label='do it', no_label='forget it')

                    if result != QW.QDialog.Accepted:

                        return

                def work_callable():

                    if remove_existing:

                        HydrusNATPunch.RemoveUPnPMapping(
                            external_port, protocol)

                    internal_client = HydrusNATPunch.GetLocalIP()

                    HydrusNATPunch.AddUPnPMapping(internal_client,
                                                  internal_port,
                                                  external_port,
                                                  protocol,
                                                  description,
                                                  duration=duration)

                    return True

                def publish_callable(result):

                    self._mappings_listctrl_panel.setEnabled(True)

                    self._RefreshMappings()

                self._mappings_listctrl_panel.setEnabled(False)

                async_job = ClientGUIAsync.AsyncQtJob(self, work_callable,
                                                      publish_callable)

                async_job.start()