Esempio n. 1
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 AddServiceKeyLabelsToMenu(menu, service_keys, phrase):

    services_manager = HG.client_controller.services_manager

    if len(service_keys) == 1:

        (service_key, ) = service_keys

        name = services_manager.GetName(service_key)

        label = phrase + ' ' + name

        ClientGUIMenus.AppendMenuLabel(menu, label)

    else:

        submenu = QW.QMenu(menu)

        for service_key in service_keys:

            name = services_manager.GetName(service_key)

            ClientGUIMenus.AppendMenuLabel(submenu, name)

        ClientGUIMenus.AppendMenu(menu, submenu, phrase + '\u2026')
Esempio n. 3
0
 def PopupMenu( self, window: QW.QWidget, menu: QW.QMenu ):
     
     if HC.PLATFORM_MACOS and window.window().isModal():
         
         # Ok, seems like Big Sur can't do menus at the moment lmao. it shows the menu but the mouse can't interact with it
         
         from hydrus.core import HydrusGlobals as HG
         
         if HG.client_controller.new_options.GetBoolean( 'do_macos_debug_dialog_menus' ):
             
             from hydrus.client.gui import ClientGUICoreMenuDebug
             
             ClientGUICoreMenuDebug.ShowMenuDialog( window, menu )
             
             ClientGUIMenus.DestroyMenu( menu )
             
             return
             
         
     
     if not menu.isEmpty():
         
         self._menu_open = True
         
         menu.exec_( QG.QCursor.pos() ) # This could also be window.mapToGlobal( QC.QPoint( 0, 0 ) ), but in practice, popping up at the current cursor position feels better.
         
         self._menu_open = False
         
     
     ClientGUIMenus.DestroyMenu( menu )
def AddServiceKeysToMenu(event_handler, menu, service_keys, phrase,
                         description, call):

    services_manager = HG.client_controller.services_manager

    if len(service_keys) == 1:

        (service_key, ) = service_keys

        name = services_manager.GetName(service_key)

        label = phrase + ' ' + name

        ClientGUIMenus.AppendMenuItem(menu, label, description, call,
                                      service_key)

    else:

        submenu = QW.QMenu(menu)

        for service_key in service_keys:

            name = services_manager.GetName(service_key)

            ClientGUIMenus.AppendMenuItem(submenu, name, description, call,
                                          service_key)

        ClientGUIMenus.AppendMenu(menu, submenu, phrase + '\u2026')
Esempio n. 5
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
Esempio n. 6
0
def AddManageFileViewingStatsMenu( win: QW.QWidget, menu: QW.QMenu, flat_medias: typing.Collection[ ClientMedia.MediaSingleton ] ):
    
    # add test here for if media actually has stats, edit them, all that
    
    submenu = QW.QMenu( menu )
    
    ClientGUIMenus.AppendMenuItem( submenu, 'clear', 'Clear all the recorded file viewing stats for the selected files.', DoClearFileViewingStats, win, flat_medias )
    
    ClientGUIMenus.AppendMenu( menu, submenu, 'viewing stats' )
Esempio n. 7
0
 def _ShowErrorMenu( self ):
     
     if self._error_text is None:
         
         return
         
     
     menu = QW.QMenu()
     
     ClientGUIMenus.AppendMenuItem( menu, 'show error', 'Show the recent error in a messagebox.', self.ShowError )
     ClientGUIMenus.AppendMenuItem( menu, 'copy error', 'Copy the recent error to the clipboard.', self.CopyError )
     
     CGC.core().PopupMenu( self._cog_button, menu )
Esempio n. 8
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
Esempio n. 9
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 _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)
Esempio n. 11
0
 def PopupMenu( self, window, menu ):
     
     if not menu.isEmpty():
         
         self._menu_open = True
         
         menu.exec_( QG.QCursor.pos() ) # This could also be window.mapToGlobal( QC.QPoint( 0, 0 ) ), but in practice, popping up at the current cursor position feels better.
         
         self._menu_open = False
         
     
     ClientGUIMenus.DestroyMenu( 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 )
Esempio n. 13
0
 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 )
Esempio n. 14
0
def AddServiceKeysToMenu(menu, service_keys, submenu_name, description,
                         bare_call):

    menu_tuples = []

    services_manager = HG.client_controller.services_manager

    for service_key in service_keys:

        label = services_manager.GetName(service_key)

        this_call = HydrusData.Call(bare_call, service_key)

        menu_tuples.append((label, description, this_call))

    ClientGUIMenus.AppendMenuOrItem(menu, submenu_name, menu_tuples)
Esempio n. 15
0
def AddFileViewingStatsMenu(menu,
                            medias: typing.Collection[ClientMedia.Media]):

    if len(medias) == 0:

        return

    view_style = HG.client_controller.new_options.GetInteger(
        'file_viewing_stats_menu_display')

    if view_style == CC.FILE_VIEWING_STATS_MENU_DISPLAY_NONE:

        return

    if len(medias) == 1:

        (media, ) = medias

        fvsm = media.GetFileViewingStatsManager()

    else:

        fvsm = ClientMediaManagers.FileViewingStatsManager.STATICGenerateCombinedManager(
            [media.GetFileViewingStatsManager() for media in medias])

    if view_style == CC.FILE_VIEWING_STATS_MENU_DISPLAY_MEDIA_AND_PREVIEW_SUMMED:

        combined_line = fvsm.GetPrettyViewsLine(
            (CC.CANVAS_MEDIA_VIEWER, CC.CANVAS_PREVIEW))

        ClientGUIMenus.AppendMenuLabel(menu, combined_line)

    else:

        media_line = fvsm.GetPrettyViewsLine((CC.CANVAS_MEDIA_VIEWER, ))
        preview_line = fvsm.GetPrettyViewsLine((CC.CANVAS_PREVIEW, ))

        if view_style == CC.FILE_VIEWING_STATS_MENU_DISPLAY_MEDIA_ONLY:

            ClientGUIMenus.AppendMenuLabel(menu, media_line)

        elif view_style == CC.FILE_VIEWING_STATS_MENU_DISPLAY_MEDIA_AND_PREVIEW_IN_SUBMENU:

            submenu = QW.QMenu(menu)

            ClientGUIMenus.AppendMenuLabel(submenu, preview_line)

            ClientGUIMenus.AppendMenu(menu, submenu, media_line)

        elif view_style == CC.FILE_VIEWING_STATS_MENU_DISPLAY_MEDIA_AND_PREVIEW_STACKED:

            ClientGUIMenus.AppendMenuLabel(menu, media_line)
            ClientGUIMenus.AppendMenuLabel(menu, preview_line)
    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()
Esempio n. 17
0
def AddFileViewingStatsMenu(menu, focus_media):

    view_style = HG.client_controller.new_options.GetInteger(
        'file_viewing_stats_menu_display')

    if view_style == CC.FILE_VIEWING_STATS_MENU_DISPLAY_NONE:

        return

    fvsm = focus_media.GetFileViewingStatsManager()

    if view_style == CC.FILE_VIEWING_STATS_MENU_DISPLAY_MEDIA_AND_PREVIEW_SUMMED:

        combined_line = fvsm.GetPrettyCombinedLine()

        ClientGUIMenus.AppendMenuLabel(menu, combined_line)

    else:

        media_line = fvsm.GetPrettyMediaLine()
        preview_line = fvsm.GetPrettyPreviewLine()

        if view_style == CC.FILE_VIEWING_STATS_MENU_DISPLAY_MEDIA_ONLY:

            ClientGUIMenus.AppendMenuLabel(menu, media_line)

        elif view_style == CC.FILE_VIEWING_STATS_MENU_DISPLAY_MEDIA_AND_PREVIEW_IN_SUBMENU:

            submenu = QW.QMenu(menu)

            ClientGUIMenus.AppendMenuLabel(submenu, preview_line)

            ClientGUIMenus.AppendMenu(menu, submenu, media_line)

        elif view_style == CC.FILE_VIEWING_STATS_MENU_DISPLAY_MEDIA_AND_PREVIEW_STACKED:

            ClientGUIMenus.AppendMenuLabel(menu, media_line)
            ClientGUIMenus.AppendMenuLabel(menu, preview_line)
Esempio n. 18
0
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')
Esempio n. 19
0
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')
Esempio n. 20
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 )
Esempio n. 21
0
def AddLocalFilesMoveAddToMenu(
        win: QW.QWidget, menu: QW.QMenu,
        local_duplicable_to_file_service_keys: typing.Collection[bytes],
        local_moveable_from_and_to_file_service_keys: typing.Collection[
            typing.Tuple[bytes, bytes]], multiple_selected: bool,
        process_application_command_call):

    if len(local_duplicable_to_file_service_keys) == 0 and len(
            local_moveable_from_and_to_file_service_keys) == 0:

        return

    local_action_menu = QW.QMenu(menu)

    if len(local_duplicable_to_file_service_keys) > 0:

        menu_tuples = []

        for s_k in local_duplicable_to_file_service_keys:

            application_command = CAC.ApplicationCommand(
                command_type=CAC.APPLICATION_COMMAND_TYPE_CONTENT,
                data=(s_k, HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ADD, None))

            label = HG.client_controller.services_manager.GetName(s_k)
            description = 'Duplicate the files to this local file service.'
            call = HydrusData.Call(process_application_command_call,
                                   application_command)

            menu_tuples.append((label, description, call))

        if multiple_selected:

            submenu_name = 'add selected to'

        else:

            submenu_name = 'add to'

        ClientGUIMenus.AppendMenuOrItem(local_action_menu, submenu_name,
                                        menu_tuples)

    if len(local_moveable_from_and_to_file_service_keys) > 0:

        menu_tuples = []

        for (source_s_k,
             dest_s_k) in local_moveable_from_and_to_file_service_keys:

            application_command = CAC.ApplicationCommand(
                command_type=CAC.APPLICATION_COMMAND_TYPE_CONTENT,
                data=(dest_s_k, HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_MOVE,
                      source_s_k))

            label = 'from {} to {}'.format(
                HG.client_controller.services_manager.GetName(source_s_k),
                HG.client_controller.services_manager.GetName(dest_s_k))
            description = 'Add the files to the destination and delete from the source.'
            call = HydrusData.Call(process_application_command_call,
                                   application_command)

            menu_tuples.append((label, description, call))

        if multiple_selected:

            submenu_name = 'move selected'

        else:

            submenu_name = 'move'

        ClientGUIMenus.AppendMenuOrItem(local_action_menu, submenu_name,
                                        menu_tuples)

    ClientGUIMenus.AppendMenu(menu, local_action_menu, 'local services')
    def _PopulateSortMenuOrList(self, menu=None):

        sort_types = []

        menu_items_and_sort_types = []

        submetatypes_to_menus = {}

        for system_sort_type in CC.SYSTEM_SORT_TYPES_SORT_CONTROL_SORTED:

            sort_type = ('system', system_sort_type)

            sort_types.append(sort_type)

            if menu is not None:

                submetatype = CC.system_sort_type_submetatype_string_lookup[
                    system_sort_type]

                if submetatype is None:

                    menu_to_add_to = menu

                else:

                    if submetatype not in submetatypes_to_menus:

                        submenu = QW.QMenu(menu)

                        submetatypes_to_menus[submetatype] = submenu

                        ClientGUIMenus.AppendMenu(menu, submenu, submetatype)

                    menu_to_add_to = submetatypes_to_menus[submetatype]

                label = CC.sort_type_basic_string_lookup[system_sort_type]

                menu_item = ClientGUIMenus.AppendMenuItem(
                    menu_to_add_to, label, 'Select this sort type.',
                    self._SetSortTypeFromUser, sort_type)

                menu_items_and_sort_types.append((menu_item, sort_type))

        default_namespace_sorts = HG.client_controller.new_options.GetDefaultNamespaceSorts(
        )

        if menu is not None:

            submenu = QW.QMenu(menu)

            ClientGUIMenus.AppendMenu(menu, submenu, 'namespaces')

        for namespace_sort in default_namespace_sorts:

            sort_type = namespace_sort.sort_type

            sort_types.append(sort_type)

            if menu is not None:

                example_sort = ClientMedia.MediaSort(sort_type, CC.SORT_ASC)

                label = example_sort.GetSortTypeString()

                menu_item = ClientGUIMenus.AppendMenuItem(
                    submenu, label, 'Select this sort type.',
                    self._SetSortTypeFromUser, sort_type)

                menu_items_and_sort_types.append((menu_item, sort_type))

        if menu is not None:

            ClientGUIMenus.AppendMenuItem(submenu, 'custom',
                                          'Set a custom namespace sort',
                                          self._SetCustomNamespaceSortFromUser)

        rating_service_keys = HG.client_controller.services_manager.GetServiceKeys(
            (HC.LOCAL_RATING_LIKE, HC.LOCAL_RATING_NUMERICAL))

        if len(rating_service_keys) > 0:

            if menu is not None:

                submenu = QW.QMenu(menu)

                ClientGUIMenus.AppendMenu(menu, submenu, 'ratings')

            for service_key in rating_service_keys:

                sort_type = ('rating', service_key)

                sort_types.append(sort_type)

                if menu is not None:

                    example_sort = ClientMedia.MediaSort(
                        sort_type, CC.SORT_ASC)

                    label = example_sort.GetSortTypeString()

                    menu_item = ClientGUIMenus.AppendMenuItem(
                        submenu, label, 'Select this sort type.',
                        self._SetSortTypeFromUser, sort_type)

                    menu_items_and_sort_types.append((menu_item, sort_type))

        if menu is not None:

            for (menu_item, sort_choice) in menu_items_and_sort_types:

                if sort_choice == self._sort_type:

                    menu_item.setCheckable(True)
                    menu_item.setChecked(True)

        return sort_types
    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)
Esempio n. 24
0
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')
Esempio n. 25
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)

        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