Beispiel #1
0
    def _GetListCtrlMenu( self ):
        
        selected_file_seeds = self._list_ctrl.GetData( only_selected = True )
        
        if len( selected_file_seeds ) == 0:
            
            raise HydrusExceptions.DataMissing()
            
        
        menu = QW.QMenu()
        
        can_show_files_in_new_page = True in ( file_seed.HasHash() for file_seed in selected_file_seeds )
        
        if can_show_files_in_new_page:
            
            ClientGUIMenus.AppendMenuItem( menu, 'open selected import files in a new page', 'Show all the known selected files in a new thumbnail page. This is complicated, so cannot always be guaranteed, even if the import says \'success\'.', self._ShowSelectionInNewPage )
            
            ClientGUIMenus.AppendSeparator( menu )

        ClientGUIMenus.AppendMenuItem( menu, 'copy sources', 'Copy all the selected sources to clipboard.', self._CopySelectedFileSeedData )
        ClientGUIMenus.AppendMenuItem( menu, 'copy notes', 'Copy all the selected notes to clipboard.', self._CopySelectedNotes )
        
        ClientGUIMenus.AppendSeparator( menu )

        ClientGUIMenus.AppendMenuItem( menu, 'open sources', 'Open all the selected sources in your file explorer or web browser.', self._OpenSelectedFileSeedData )
        
        ClientGUIMenus.AppendSeparator( menu )

        ClientGUIMenus.AppendMenuItem( menu, 'try again', 'Reset the progress of all the selected imports.', HydrusData.Call( self._SetSelected, CC.STATUS_UNKNOWN ) )
        ClientGUIMenus.AppendMenuItem( menu, 'skip', 'Skip all the selected imports.', HydrusData.Call( self._SetSelected, CC.STATUS_SKIPPED ) )
        ClientGUIMenus.AppendMenuItem( menu, 'delete from list', 'Remove all the selected imports.', self._DeleteSelected )
        
        return menu
Beispiel #2
0
    def _GetListCtrlMenu( self ):
        
        selected_gallery_seeds = self._list_ctrl.GetData( only_selected = True )
        
        if len( selected_gallery_seeds ) == 0:
            
            raise HydrusExceptions.DataMissing()
            
        
        menu = QW.QMenu()

        ClientGUIMenus.AppendMenuItem( menu, 'copy urls', 'Copy all the selected urls to clipboard.', self._CopySelectedGalleryURLs )
        ClientGUIMenus.AppendMenuItem( menu, 'copy notes', 'Copy all the selected notes to clipboard.', self._CopySelectedNotes )
        
        ClientGUIMenus.AppendSeparator( menu )

        ClientGUIMenus.AppendMenuItem( menu, 'open urls', 'Open all the selected urls in your web browser.', self._OpenSelectedGalleryURLs )
        
        ClientGUIMenus.AppendSeparator( menu )
        
        if not self._read_only:
            
            ClientGUIMenus.AppendMenuItem( menu, 'try again (just this one page)', 'Schedule this url to occur again.', HydrusData.Call( self._TrySelectedAgain, False ) )
            
            if self._can_generate_more_pages:
                ClientGUIMenus.AppendMenuItem( menu, 'try again (and allow search to continue)', 'Schedule this url to occur again and continue.', HydrusData.Call( self._TrySelectedAgain, True ) )

        ClientGUIMenus.AppendMenuItem( menu, 'skip', 'Skip all the selected urls.', HydrusData.Call( self._SetSelected, CC.STATUS_SKIPPED ) )
        
        return menu
Beispiel #3
0
    def ShowMenu( self ):
        
        menu = QW.QMenu()
        
        gallery_seed_log = self._gallery_seed_log_get_callable()
        
        if len( gallery_seed_log ) > 0:
            
            if not self._read_only and gallery_seed_log.CanRestartFailedSearch():
                
                ClientGUIMenus.AppendMenuItem( menu, 'restart and resume failed search', 'Requeue the last failed attempt and resume search from there.', gallery_seed_log.RestartFailedSearch )
                
                ClientGUIMenus.AppendSeparator( menu )
                
            
            submenu = QW.QMenu( menu )

            ClientGUIMenus.AppendMenuItem( submenu, 'to clipboard', 'Copy all the urls in this list to the clipboard.', self._ExportToClipboard )
            ClientGUIMenus.AppendMenuItem( submenu, 'to png', 'Export all the urls in this list to a png file.', self._ExportToPng )
            
            ClientGUIMenus.AppendMenu( menu, submenu, 'export all urls' )
            
        
        if not self._read_only:
            
            submenu = QW.QMenu( menu )

            ClientGUIMenus.AppendMenuItem( submenu, 'from clipboard', 'Import new urls to this list from the clipboard.', self._ImportFromClipboard )
            ClientGUIMenus.AppendMenuItem( submenu, 'from png', 'Import new urls to this list from a png file.', self._ImportFromPng )
            
            ClientGUIMenus.AppendMenu( menu, submenu, 'import new urls' )
            
        
        CGC.core().PopupMenu( self, menu )
 def _ShowCogMenu( self ):
     
     menu = QW.QMenu()
     
     if self._network_job is not None:
         
         if self._network_job.CurrentlyWaitingOnConnectionError():
             
             ClientGUIMenus.AppendMenuItem( menu, 'reattempt connection now', 'Stop waiting on a connection error and reattempt the job now.', self._network_job.OverrideConnectionErrorWait )
             
         
         if self._network_job.CurrentlyWaitingOnServersideBandwidth():
             
             ClientGUIMenus.AppendMenuItem( menu, 'reattempt request now (server reports low bandwidth)', 'Stop waiting on a serverside bandwidth delay and reattempt the job now.', self._network_job.OverrideServersideBandwidthWait )
             
         
         if self._network_job.ObeysBandwidth():
             
             ClientGUIMenus.AppendMenuItem( menu, 'override bandwidth rules for this job', 'Tell the current job to ignore existing bandwidth rules and go ahead anyway.', self._network_job.OverrideBandwidth )
             
         
         if not self._network_job.TokensOK():
             
             ClientGUIMenus.AppendMenuItem( menu, 'override gallery slot requirements for this job', 'Force-allow this download to proceed, ignoring the normal gallery wait times.', self._network_job.OverrideToken )
             
         
         ClientGUIMenus.AppendSeparator( menu )
         
     
     ClientGUIMenus.AppendMenuCheckItem( menu, 'auto-override bandwidth rules for all jobs here after five seconds', 'Ignore existing bandwidth rules for all jobs under this control, instead waiting a flat five seconds.', self._auto_override_bandwidth_rules, self.FlipAutoOverrideBandwidth )
     
     CGC.core().PopupMenu( self._cog_button, menu )
Beispiel #5
0
    def _EditLocation(self):

        services = ClientLocation.GetPossibleFileDomainServicesInOrder(
            self._IsAllKnownFilesServiceTypeAllowed(),
            self._only_importable_domains_allowed)

        menu = QW.QMenu()

        for service in services:

            location_context = ClientLocation.LocationContext.STATICCreateSimple(
                service.GetServiceKey())

            ClientGUIMenus.AppendMenuItem(
                menu, service.GetName(),
                'Change the current file domain to {}.'.format(
                    service.GetName()), self.SetValue, location_context)

        ClientGUIMenus.AppendSeparator(menu)

        ClientGUIMenus.AppendMenuItem(
            menu, 'multiple locations',
            'Change the current file domain to something with multiple locations.',
            self._EditMultipleLocationContext)

        CGC.core().PopupMenu(self, menu)
    def _RegenerateMenu(self):

        # I'm not a qwidget, but a qobject, so use my parent for this
        parent_widget = self.parent()

        new_menu = QW.QMenu(parent_widget)

        self._show_hide_menu_item = ClientGUIMenus.AppendMenuItem(
            new_menu, 'show/hide', 'Hide or show the hydrus client',
            self.flip_show_ui.emit)

        self._UpdateShowHideMenuItemLabel()

        ClientGUIMenus.AppendSeparator(new_menu)

        self._network_traffic_menu_item = ClientGUIMenus.AppendMenuItem(
            new_menu, 'network traffic', 'Pause/resume network traffic',
            self.flip_pause_network_jobs.emit)

        self._UpdateNetworkTrafficMenuItemLabel()

        self._subscriptions_paused_menu_item = ClientGUIMenus.AppendMenuItem(
            new_menu, 'subscriptions', 'Pause/resume subscriptions',
            self.flip_pause_subscription_jobs.emit)

        self._UpdateSubscriptionsMenuItemLabel()

        ClientGUIMenus.AppendSeparator(new_menu)

        ClientGUIMenus.AppendMenuItem(new_menu, 'exit',
                                      'Close the hydrus client',
                                      self.exit_client.emit)

        #

        old_menu = self.contextMenu()

        self.setContextMenu(new_menu)

        if old_menu is not None:

            ClientGUIMenus.DestroyMenu(old_menu)

        self._UpdateTooltip()
        def _DefaultsMenu(self):

            menu = QW.QMenu()

            ClientGUIMenus.AppendMenuItem(
                menu, 'set this as new default',
                'Set the current value of this as the new default for this predicate.',
                self._predicate_panel.SaveCustomDefault)

            if self._predicate_panel.UsesCustomDefault():

                ClientGUIMenus.AppendSeparator(menu)

                ClientGUIMenus.AppendMenuItem(
                    menu, 'reset to original default',
                    'Clear the custom default value for this predicate.',
                    self._predicate_panel.ClearCustomDefault)

            CGC.core().PopupMenu(self, menu)
 def _PopulateMenu( self, menu, menu_items ):
     
     for ( item_type, title, description, data ) in menu_items:
         
         if item_type == 'normal':
             
             func = data
             
             ClientGUIMenus.AppendMenuItem( menu, title, description, func )
             
         elif item_type == 'check':
             
             check_manager = data
             
             current_value = check_manager.GetCurrentValue()
             func = check_manager.Invert
             
             if current_value is not None:
                 
                 ClientGUIMenus.AppendMenuCheckItem( menu, title, description, current_value, func )
                 
             
         elif item_type == 'separator':
             
             ClientGUIMenus.AppendSeparator( menu )
             
         elif item_type == 'submenu':
             
             submenu = QW.QMenu( menu )
             
             self._PopulateMenu( submenu, data )
             
             ClientGUIMenus.AppendMenu( menu, submenu, title )
             
         elif item_type == 'label':
             
             ClientGUIMenus.AppendMenuLabel( menu, title, description = description )
def PopulateGallerySeedLogButton(
        win: QW.QWidget, menu: QW.QMenu,
        gallery_seed_log: ClientImportGallerySeeds.GallerySeedLog,
        read_only: bool, can_generate_more_pages: bool,
        gallery_type_string: str):

    num_successful = gallery_seed_log.GetGallerySeedCount(
        CC.STATUS_SUCCESSFUL_AND_NEW)
    num_vetoed = gallery_seed_log.GetGallerySeedCount(CC.STATUS_VETOED)
    num_errors = gallery_seed_log.GetGallerySeedCount(CC.STATUS_ERROR)
    num_skipped = gallery_seed_log.GetGallerySeedCount(CC.STATUS_SKIPPED)

    if num_successful > 0:

        ClientGUIMenus.AppendMenuItem(
            menu,
            'delete {} \'successful\' gallery log entries from the log'.format(
                HydrusData.ToHumanInt(num_successful)),
            'Tell this log to clear out successful records, reducing the size of the queue.',
            ClearGallerySeeds, win, gallery_seed_log,
            (CC.STATUS_SUCCESSFUL_AND_NEW, ), gallery_type_string)

    if num_errors > 0:

        ClientGUIMenus.AppendMenuItem(
            menu,
            'delete {} \'failed\' gallery log entries from the log'.format(
                HydrusData.ToHumanInt(num_errors)),
            'Tell this log to clear out errored records, reducing the size of the queue.',
            ClearGallerySeeds, win, gallery_seed_log, (CC.STATUS_ERROR, ),
            gallery_type_string)

    if num_vetoed > 0:

        ClientGUIMenus.AppendMenuItem(
            menu,
            'delete {} \'ignored\' gallery log entries from the log'.format(
                HydrusData.ToHumanInt(num_vetoed)),
            'Tell this log to clear out ignored records, reducing the size of the queue.',
            ClearGallerySeeds, win, gallery_seed_log, (CC.STATUS_VETOED, ),
            gallery_type_string)

    if num_skipped > 0:

        ClientGUIMenus.AppendMenuItem(
            menu,
            'delete {} \'skipped\' gallery log entries from the log'.format(
                HydrusData.ToHumanInt(num_skipped)),
            'Tell this log to clear out skipped records, reducing the size of the queue.',
            ClearGallerySeeds, win, gallery_seed_log, (CC.STATUS_SKIPPED, ),
            gallery_type_string)

    ClientGUIMenus.AppendSeparator(menu)

    if len(gallery_seed_log) > 0:

        if not read_only and gallery_seed_log.CanRestartFailedSearch():

            ClientGUIMenus.AppendMenuItem(
                menu, 'restart and resume failed search',
                'Requeue the last failed attempt and resume search from there.',
                gallery_seed_log.RestartFailedSearch)

            ClientGUIMenus.AppendSeparator(menu)

        submenu = QW.QMenu(menu)

        ClientGUIMenus.AppendMenuItem(
            submenu, 'to clipboard',
            'Copy all the urls in this list to the clipboard.',
            ExportToClipboard, gallery_seed_log)
        ClientGUIMenus.AppendMenuItem(
            submenu, 'to png',
            'Export all the urls in this list to a png file.', ExportToPNG,
            win, gallery_seed_log)

        ClientGUIMenus.AppendMenu(menu, submenu, 'export all urls')

    if not read_only:

        submenu = QW.QMenu(menu)

        ClientGUIMenus.AppendMenuItem(
            submenu, 'from clipboard',
            'Import new urls to this list from the clipboard.',
            ImportFromClipboard, win, gallery_seed_log,
            can_generate_more_pages)
        ClientGUIMenus.AppendMenuItem(
            submenu, 'from png',
            'Import new urls to this list from a png file.', ImportFromPNG,
            win, gallery_seed_log, can_generate_more_pages)

        ClientGUIMenus.AppendMenu(menu, submenu, 'import new urls')
def AddKnownURLsViewCopyMenu(win, menu, focus_media, selected_media=None):

    # figure out which urls this focused file has

    focus_urls = focus_media.GetLocationsManager().GetURLs()

    focus_matched_labels_and_urls = []
    focus_unmatched_urls = []
    focus_labels_and_urls = []

    if len(focus_urls) > 0:

        for url in focus_urls:

            try:

                url_class = HG.client_controller.network_engine.domain_manager.GetURLClass(
                    url)

            except HydrusExceptions.URLClassException:

                continue

            if url_class is None:

                focus_unmatched_urls.append(url)

            else:

                label = url_class.GetName() + ': ' + url

                focus_matched_labels_and_urls.append((label, url))

        focus_matched_labels_and_urls.sort()
        focus_unmatched_urls.sort()

        focus_labels_and_urls = list(focus_matched_labels_and_urls)

        focus_labels_and_urls.extend(
            ((url, url) for url in focus_unmatched_urls))

    # figure out which urls these selected files have

    selected_media_url_classes = set()
    multiple_or_unmatching_selection_url_classes = False

    if selected_media is not None and len(selected_media) > 1:

        selected_media = ClientMedia.FlattenMedia(selected_media)

        SAMPLE_SIZE = 256

        if len(selected_media) > SAMPLE_SIZE:

            selected_media_sample = random.sample(selected_media, SAMPLE_SIZE)

        else:

            selected_media_sample = selected_media

        for media in selected_media_sample:

            media_urls = media.GetLocationsManager().GetURLs()

            for url in media_urls:

                try:

                    url_class = HG.client_controller.network_engine.domain_manager.GetURLClass(
                        url)

                except HydrusExceptions.URLClassException:

                    continue

                if url_class is None:

                    multiple_or_unmatching_selection_url_classes = True

                else:

                    selected_media_url_classes.add(url_class)

        if len(selected_media_url_classes) > 1:

            multiple_or_unmatching_selection_url_classes = True

    if len(focus_labels_and_urls) > 0 or len(
            selected_media_url_classes
    ) > 0 or multiple_or_unmatching_selection_url_classes:

        urls_menu = QW.QMenu(menu)

        urls_visit_menu = QW.QMenu(urls_menu)
        urls_copy_menu = QW.QMenu(urls_menu)

        # copy each this file's urls (of a particular type)

        if len(focus_labels_and_urls) > 0:

            for (label, url) in focus_labels_and_urls:

                ClientGUIMenus.AppendMenuItem(
                    urls_visit_menu, label,
                    'Open this url in your web browser.',
                    ClientPaths.LaunchURLInWebBrowser, url)
                ClientGUIMenus.AppendMenuItem(
                    urls_copy_menu, label, 'Copy this url to your clipboard.',
                    HG.client_controller.pub, 'clipboard', 'text', url)

        # copy this file's urls

        there_are_focus_url_classes_to_action = len(
            focus_matched_labels_and_urls) > 1
        multiple_or_unmatching_focus_url_classes = len(
            focus_unmatched_urls) > 0 and len(
                focus_labels_and_urls
            ) > 1  # if there are unmatched urls and more than one thing total

        if there_are_focus_url_classes_to_action or multiple_or_unmatching_focus_url_classes:

            ClientGUIMenus.AppendSeparator(urls_visit_menu)
            ClientGUIMenus.AppendSeparator(urls_copy_menu)

        if there_are_focus_url_classes_to_action:

            urls = [url for (label, url) in focus_matched_labels_and_urls]

            label = 'open this file\'s ' + HydrusData.ToHumanInt(
                len(urls)) + ' recognised urls in your web browser'

            ClientGUIMenus.AppendMenuItem(
                urls_visit_menu, label, 'Open these urls in your web browser.',
                OpenURLs, urls)

            urls_string = os.linesep.join(urls)

            label = 'copy this file\'s ' + HydrusData.ToHumanInt(
                len(urls)) + ' recognised urls to your clipboard'

            ClientGUIMenus.AppendMenuItem(
                urls_copy_menu, label, 'Copy these urls to your clipboard.',
                HG.client_controller.pub, 'clipboard', 'text', urls_string)

        if multiple_or_unmatching_focus_url_classes:

            urls = [url for (label, url) in focus_labels_and_urls]

            label = 'open this file\'s ' + HydrusData.ToHumanInt(
                len(urls)) + ' urls in your web browser'

            ClientGUIMenus.AppendMenuItem(
                urls_visit_menu, label, 'Open these urls in your web browser.',
                OpenURLs, urls)

            urls_string = os.linesep.join(urls)

            label = 'copy this file\'s ' + HydrusData.ToHumanInt(
                len(urls)) + ' urls to your clipboard'

            ClientGUIMenus.AppendMenuItem(urls_copy_menu, label,
                                          'Copy this url to your clipboard.',
                                          HG.client_controller.pub,
                                          'clipboard', 'text', urls_string)

        # now by url match type

        there_are_selection_url_classes_to_action = len(
            selected_media_url_classes) > 0

        if there_are_selection_url_classes_to_action or multiple_or_unmatching_selection_url_classes:

            ClientGUIMenus.AppendSeparator(urls_visit_menu)
            ClientGUIMenus.AppendSeparator(urls_copy_menu)

        if there_are_selection_url_classes_to_action:

            selected_media_url_classes = list(selected_media_url_classes)

            selected_media_url_classes.sort(
                key=lambda url_class: url_class.GetName())

            for url_class in selected_media_url_classes:

                label = 'open files\' ' + url_class.GetName(
                ) + ' urls in your web browser'

                ClientGUIMenus.AppendMenuItem(
                    urls_visit_menu, label,
                    'Open this url class in your web browser for all files.',
                    OpenMediaURLClassURLs, selected_media, url_class)

                label = 'copy files\' ' + url_class.GetName() + ' urls'

                ClientGUIMenus.AppendMenuItem(
                    urls_copy_menu, label,
                    'Copy this url class for all files.',
                    CopyMediaURLClassURLs, selected_media, url_class)

        # now everything

        if multiple_or_unmatching_selection_url_classes:

            label = 'open all files\' urls'

            ClientGUIMenus.AppendMenuItem(
                urls_visit_menu, label,
                'Open urls in your web browser for all files.', OpenMediaURLs,
                selected_media)

            label = 'copy all files\' urls'

            ClientGUIMenus.AppendMenuItem(urls_copy_menu, label,
                                          'Copy urls for all files.',
                                          CopyMediaURLs, selected_media)

        #

        ClientGUIMenus.AppendMenu(urls_menu, urls_visit_menu, 'open')
        ClientGUIMenus.AppendMenu(urls_menu, urls_copy_menu, 'copy')

        ClientGUIMenus.AppendMenu(menu, urls_menu, 'known urls')
Beispiel #11
0
 def _ShowCogMenu( self ):
     
     menu = QW.QMenu()
     
     if self._network_job is not None and self._network_job.engine is not None:
         
         url = self._network_job.GetURL()
         
         ClientGUIMenus.AppendMenuLabel( menu, url, description = 'copy URL to the clipboard' )
         
         ClientGUIMenus.AppendSeparator( menu )
         
         network_contexts = self._network_job.GetNetworkContexts()
         
         if len( network_contexts ) > 0:
             
             bandwidth_manager = self._network_job.engine.bandwidth_manager
             
             submenu = QW.QMenu( menu )
             
             menu_network_contexts = []
             
             network_contexts_used = set()
             
             for network_context in network_contexts:
                 
                 uses_default = False
                 
                 if bandwidth_manager.UsesDefaultRules( network_context ):
                     
                     uses_default = True
                     
                     default_network_context = network_context.GetDefault()
                     
                     if default_network_context not in network_contexts_used:
                         
                         menu_network_contexts.append( ( False, default_network_context, network_context ) )
                         
                         network_contexts_used.add( default_network_context )
                         
                     
                 
                 if not network_context.IsEphemeral():
                     
                     menu_network_contexts.append( ( uses_default, network_context, network_context ) )
                     
                 
             
             for ( uses_default, network_context_to_edit, network_context_to_test ) in menu_network_contexts:
                 
                 network_context_text = network_context_to_edit.ToString()
                 
                 if uses_default:
                     
                     network_context_text = 'set rules for {}'.format( network_context_text )
                     
                 else:
                     
                     ( waiting_estimate, gumpf ) = bandwidth_manager.GetWaitingEstimateAndContext( [ network_context_to_test ] )
                     
                     if waiting_estimate > 0:
                         
                         network_context_text = '{} ({})'.format( network_context_text, HydrusData.TimeDeltaToPrettyTimeDelta( waiting_estimate ) )
                         
                     
                 
                 ClientGUIMenus.AppendMenuItem( submenu, network_context_text, 'edit the bandwidth rules for this network context', self._EditBandwidthRules, network_context_to_edit )
                 
             
             ClientGUIMenus.AppendMenu( menu, submenu, 'edit bandwidth rules' )
             
             ClientGUIMenus.AppendSeparator( menu )
             
         
         if self._network_job.CurrentlyWaitingOnConnectionError():
             
             ClientGUIMenus.AppendMenuItem( menu, 'reattempt connection now', 'Stop waiting on a connection error and reattempt the job now.', self._network_job.OverrideConnectionErrorWait )
             
         
         if not self._network_job.DomainOK():
             
             ClientGUIMenus.AppendMenuItem( menu, 'scrub domain errors', 'Clear recent domain errors and allow this job to go now.', self._network_job.ScrubDomainErrors )
             
         
         if self._network_job.CurrentlyWaitingOnServersideBandwidth():
             
             ClientGUIMenus.AppendMenuItem( menu, 'reattempt request now (server reports low bandwidth)', 'Stop waiting on a serverside bandwidth delay and reattempt the job now.', self._network_job.OverrideServersideBandwidthWait )
             
         
         if self._network_job.ObeysBandwidth():
             
             ClientGUIMenus.AppendMenuItem( menu, 'override bandwidth rules for this job', 'Tell the current job to ignore existing bandwidth rules and go ahead anyway.', self._network_job.OverrideBandwidth )
             
         
         if not self._network_job.TokensOK():
             
             ClientGUIMenus.AppendMenuItem( menu, 'override forced gallery wait times for this job', 'Force-allow this download to proceed, ignoring the normal gallery wait times.', self._network_job.OverrideToken )
             
         
         ClientGUIMenus.AppendSeparator( menu )
         
     
     ClientGUIMenus.AppendMenuCheckItem( menu, 'auto-override bandwidth rules for all jobs here after five seconds', 'Ignore existing bandwidth rules for all jobs under this control, instead waiting a flat five seconds.', self._auto_override_bandwidth_rules, self.FlipAutoOverrideBandwidth )
     
     CGC.core().PopupMenu( self._cog_button, menu )
    def ShowMenu(self):

        menu = QW.QMenu()

        file_seed_cache = self._file_seed_cache_get_callable()

        num_file_seeds = len(file_seed_cache)
        num_successful = file_seed_cache.GetFileSeedCount(
            CC.STATUS_SUCCESSFUL_AND_NEW) + file_seed_cache.GetFileSeedCount(
                CC.STATUS_SUCCESSFUL_BUT_REDUNDANT)
        num_vetoed = file_seed_cache.GetFileSeedCount(CC.STATUS_VETOED)
        num_deleted_and_vetoed = file_seed_cache.GetFileSeedCount(
            CC.STATUS_DELETED) + num_vetoed
        num_errors = file_seed_cache.GetFileSeedCount(CC.STATUS_ERROR)
        num_skipped = file_seed_cache.GetFileSeedCount(CC.STATUS_SKIPPED)

        if num_errors > 0:

            ClientGUIMenus.AppendMenuItem(
                menu, 'retry ' + HydrusData.ToHumanInt(num_errors) +
                ' error failures',
                'Tell this cache to reattempt all its error failures.',
                self._RetryErrors)

        if num_vetoed > 0:

            ClientGUIMenus.AppendMenuItem(
                menu,
                'retry ' + HydrusData.ToHumanInt(num_vetoed) + ' ignored',
                'Tell this cache to reattempt all its ignored/vetoed results.',
                self._RetryIgnored)

        ClientGUIMenus.AppendSeparator(menu)

        if num_successful > 0:

            num_deletees = num_successful

            ClientGUIMenus.AppendMenuItem(
                menu, 'delete ' + HydrusData.ToHumanInt(num_deletees) +
                ' successful file import items from the queue',
                'Tell this cache to clear out successful files, reducing the size of the queue.',
                self._ClearFileSeeds, (CC.STATUS_SUCCESSFUL_AND_NEW,
                                       CC.STATUS_SUCCESSFUL_BUT_REDUNDANT))

        if num_deleted_and_vetoed > 0:

            num_deletees = num_deleted_and_vetoed

            ClientGUIMenus.AppendMenuItem(
                menu, 'delete ' + HydrusData.ToHumanInt(num_deletees) +
                ' deleted/ignored file import items from the queue',
                'Tell this cache to clear out deleted and ignored files, reducing the size of the queue.',
                self._ClearFileSeeds, (CC.STATUS_DELETED, CC.STATUS_VETOED))

        if num_errors + num_skipped > 0:

            num_deletees = num_errors + num_skipped

            ClientGUIMenus.AppendMenuItem(
                menu, 'delete ' + HydrusData.ToHumanInt(num_deletees) +
                ' error/skipped file import items from the queue',
                'Tell this cache to clear out errored and skipped files, reducing the size of the queue.',
                self._ClearFileSeeds, (CC.STATUS_ERROR, CC.STATUS_SKIPPED))

        ClientGUIMenus.AppendSeparator(menu)

        ClientGUIMenus.AppendMenuItem(
            menu,
            'show new files in a new page',
            'Gather the new files in this import list and show them in a new page.',
            self._ShowFilesInNewPage,
            show='new')
        ClientGUIMenus.AppendMenuItem(
            menu, 'show all files in a new page',
            'Gather the files in this import list and show them in a new page.',
            self._ShowFilesInNewPage)

        ClientGUIMenus.AppendSeparator(menu)

        if len(file_seed_cache) > 0:

            submenu = QW.QMenu(menu)

            ClientGUIMenus.AppendMenuItem(
                submenu, 'to clipboard',
                'Copy all the sources in this list to the clipboard.',
                self._ExportToClipboard)
            ClientGUIMenus.AppendMenuItem(
                submenu, 'to png',
                'Export all the sources in this list to a png file.',
                self._ExportToPNG)

            ClientGUIMenus.AppendMenu(menu, submenu, 'export all sources')

        submenu = QW.QMenu(menu)

        ClientGUIMenus.AppendMenuItem(
            submenu, 'from clipboard',
            'Import new urls or paths to this list from the clipboard.',
            self._ImportFromClipboard)
        ClientGUIMenus.AppendMenuItem(
            submenu, 'from png',
            'Import new urls or paths to this list from a png file.',
            self._ImportFromPNG)

        ClientGUIMenus.AppendMenu(menu, submenu, 'import new sources')

        CGC.core().PopupMenu(self, menu)
    def _GetListCtrlMenu(self):

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

        if len(selected_file_seeds) == 0:

            raise HydrusExceptions.DataMissing()

        menu = QW.QMenu()

        can_show_files_in_new_page = True in (
            file_seed.HasHash() for file_seed in selected_file_seeds)

        if can_show_files_in_new_page:

            ClientGUIMenus.AppendMenuItem(
                menu, 'open selected import files in a new page',
                'Show all the known selected files in a new thumbnail page. This is complicated, so cannot always be guaranteed, even if the import says \'success\'.',
                self._ShowSelectionInNewPage)

            ClientGUIMenus.AppendSeparator(menu)

        ClientGUIMenus.AppendMenuItem(
            menu, 'copy sources',
            'Copy all the selected sources to clipboard.',
            self._CopySelectedFileSeedData)
        ClientGUIMenus.AppendMenuItem(
            menu, 'copy notes', 'Copy all the selected notes to clipboard.',
            self._CopySelectedNotes)

        if len(selected_file_seeds) == 1:

            ClientGUIMenus.AppendSeparator(menu)

            (selected_file_seed, ) = selected_file_seeds

            hash_types_to_hashes = selected_file_seed.GetHashTypesToHashes()

            if len(hash_types_to_hashes) == 0:

                ClientGUIMenus.AppendMenuLabel(menu, 'no hashes yet')

            else:

                hash_submenu = QW.QMenu(menu)

                for hash_type in ('sha256', 'md5', 'sha1', 'sha512'):

                    if hash_type in hash_types_to_hashes:

                        h = hash_types_to_hashes[hash_type]

                        ClientGUIMenus.AppendMenuLabel(
                            hash_submenu, '{}:{}'.format(hash_type, h.hex()))

                ClientGUIMenus.AppendMenu(menu, hash_submenu, 'hashes')

            #

            if selected_file_seed.IsURLFileImport():

                referral_url = selected_file_seed.GetReferralURL()
                primary_urls = sorted(selected_file_seed.GetPrimaryURLs())
                source_urls = sorted(selected_file_seed.GetSourceURLs())

                if referral_url is None and len(primary_urls) + len(
                        source_urls) == 0:

                    ClientGUIMenus.AppendMenuLabel(menu, 'no additional urls')

                else:

                    url_submenu = QW.QMenu(menu)

                    if referral_url is not None:

                        ClientGUIMenus.AppendMenuLabel(url_submenu,
                                                       'referral url:')
                        ClientGUIMenus.AppendMenuLabel(url_submenu,
                                                       referral_url)

                    if len(primary_urls) > 0:

                        ClientGUIMenus.AppendSeparator(url_submenu)

                        ClientGUIMenus.AppendMenuLabel(url_submenu,
                                                       'primary urls:')

                        for url in primary_urls:

                            ClientGUIMenus.AppendMenuLabel(url_submenu, url)

                    if len(source_urls) > 0:

                        ClientGUIMenus.AppendSeparator(url_submenu)

                        ClientGUIMenus.AppendMenuLabel(url_submenu,
                                                       'source urls:')

                        for url in source_urls:

                            ClientGUIMenus.AppendMenuLabel(url_submenu, url)

                    ClientGUIMenus.AppendMenu(menu, url_submenu,
                                              'additional urls')

                #

                tags = list(selected_file_seed.GetExternalTags())

                tag_sort = ClientTagSorting.TagSort(
                    sort_type=ClientTagSorting.SORT_BY_HUMAN_TAG,
                    sort_order=CC.SORT_ASC)

                ClientTagSorting.SortTags(tag_sort, tags)

                if len(tags) == 0:

                    ClientGUIMenus.AppendMenuLabel(menu, 'no parsed tags')

                else:

                    tag_submenu = QW.QMenu(menu)

                    for tag in tags:

                        ClientGUIMenus.AppendMenuLabel(tag_submenu, tag)

                    ClientGUIMenus.AppendMenu(menu, tag_submenu, 'parsed tags')

        ClientGUIMenus.AppendSeparator(menu)

        ClientGUIMenus.AppendMenuItem(
            menu, 'open sources',
            'Open all the selected sources in your file explorer or web browser.',
            self._OpenSelectedFileSeedData)

        ClientGUIMenus.AppendSeparator(menu)

        ClientGUIMenus.AppendMenuItem(
            menu, 'try again',
            'Reset the progress of all the selected imports.',
            HydrusData.Call(self._SetSelected, CC.STATUS_UNKNOWN))

        ClientGUIMenus.AppendMenuItem(
            menu, 'skip', 'Skip all the selected imports.',
            HydrusData.Call(self._SetSelected, CC.STATUS_SKIPPED))

        ClientGUIMenus.AppendMenuItem(menu, 'delete from list',
                                      'Remove all the selected imports.',
                                      HydrusData.Call(self._DeleteSelected))

        return menu
def PopulateFileSeedCacheMenu(
        win: QW.QWidget, menu: QW.QMenu,
        file_seed_cache: ClientImportFileSeeds.FileSeedCache):

    num_successful = file_seed_cache.GetFileSeedCount(
        CC.STATUS_SUCCESSFUL_AND_NEW) + file_seed_cache.GetFileSeedCount(
            CC.STATUS_SUCCESSFUL_BUT_REDUNDANT)
    num_vetoed = file_seed_cache.GetFileSeedCount(CC.STATUS_VETOED)
    num_deleted = file_seed_cache.GetFileSeedCount(CC.STATUS_DELETED)
    num_errors = file_seed_cache.GetFileSeedCount(CC.STATUS_ERROR)
    num_skipped = file_seed_cache.GetFileSeedCount(CC.STATUS_SKIPPED)

    if num_errors > 0:

        ClientGUIMenus.AppendMenuItem(
            menu, 'retry ' + HydrusData.ToHumanInt(num_errors) + ' failures',
            'Tell this log to reattempt all its error failures.', RetryErrors,
            win, file_seed_cache)

    if num_vetoed > 0:

        ClientGUIMenus.AppendMenuItem(
            menu, 'retry ' + HydrusData.ToHumanInt(num_vetoed) + ' ignored',
            'Tell this log to reattempt all its ignored/vetoed results.',
            RetryIgnored, win, file_seed_cache)

    ClientGUIMenus.AppendSeparator(menu)

    if num_successful > 0:

        ClientGUIMenus.AppendMenuItem(
            menu,
            'delete {} \'successful\' file import items from the queue'.format(
                HydrusData.ToHumanInt(num_successful)),
            'Tell this log to clear out successful files, reducing the size of the queue.',
            ClearFileSeeds, win, file_seed_cache,
            (CC.STATUS_SUCCESSFUL_AND_NEW, CC.STATUS_SUCCESSFUL_BUT_REDUNDANT,
             CC.STATUS_SUCCESSFUL_AND_CHILD_FILES))

    if num_deleted > 0:

        ClientGUIMenus.AppendMenuItem(
            menu,
            'delete {} \'previously deleted\' file import items from the queue'
            .format(HydrusData.ToHumanInt(num_deleted)),
            'Tell this log to clear out deleted files, reducing the size of the queue.',
            ClearFileSeeds, win, file_seed_cache, (CC.STATUS_DELETED, ))

    if num_errors > 0:

        ClientGUIMenus.AppendMenuItem(
            menu,
            'delete {} \'failed\' file import items from the queue'.format(
                HydrusData.ToHumanInt(num_errors)),
            'Tell this log to clear out errored files, reducing the size of the queue.',
            ClearFileSeeds, win, file_seed_cache, (CC.STATUS_ERROR, ))

    if num_vetoed > 0:

        ClientGUIMenus.AppendMenuItem(
            menu,
            'delete {} \'ignored\' file import items from the queue'.format(
                HydrusData.ToHumanInt(num_vetoed)),
            'Tell this log to clear out ignored files, reducing the size of the queue.',
            ClearFileSeeds, win, file_seed_cache, (CC.STATUS_VETOED, ))

    if num_skipped > 0:

        ClientGUIMenus.AppendMenuItem(
            menu,
            'delete {} \'skipped\' file import items from the queue'.format(
                HydrusData.ToHumanInt(num_skipped)),
            'Tell this log to clear out skipped files, reducing the size of the queue.',
            ClearFileSeeds, win, file_seed_cache, (CC.STATUS_SKIPPED, ))

    ClientGUIMenus.AppendSeparator(menu)

    if num_successful > 0:

        ClientGUIMenus.AppendMenuItem(
            menu,
            'show new files in a new page',
            'Gather the new files in this import list and show them in a new page.',
            ShowFilesInNewPage,
            file_seed_cache,
            show='new')
        ClientGUIMenus.AppendMenuItem(
            menu, 'show all files in a new page',
            'Gather the files in this import list and show them in a new page.',
            ShowFilesInNewPage, file_seed_cache)

    ClientGUIMenus.AppendSeparator(menu)

    if len(file_seed_cache) > 0:

        submenu = QW.QMenu(menu)

        ClientGUIMenus.AppendMenuItem(
            submenu, 'to clipboard',
            'Copy all the sources in this list to the clipboard.',
            ExportToClipboard, file_seed_cache)
        ClientGUIMenus.AppendMenuItem(
            submenu, 'to png',
            'Export all the sources in this list to a png file.', ExportToPNG,
            win, file_seed_cache)

        ClientGUIMenus.AppendMenu(menu, submenu, 'export all sources')

    submenu = QW.QMenu(menu)

    ClientGUIMenus.AppendMenuItem(
        submenu, 'from clipboard',
        'Import new urls or paths to this list from the clipboard.',
        ImportFromClipboard, win, file_seed_cache)
    ClientGUIMenus.AppendMenuItem(
        submenu, 'from png',
        'Import new urls or paths to this list from a png file.',
        ImportFromPNG, win, file_seed_cache)

    ClientGUIMenus.AppendMenu(menu, submenu, 'import new sources')