985 lines
30 KiB
Python
985 lines
30 KiB
Python
import os
|
|
import typing
|
|
|
|
from qtpy import QtCore as QC
|
|
from qtpy import QtWidgets as QW
|
|
|
|
from hydrus.core import HydrusConstants as HC
|
|
from hydrus.core import HydrusData
|
|
from hydrus.core import HydrusGlobals as HG
|
|
from hydrus.core import HydrusSerialisable
|
|
|
|
from hydrus.client import ClientApplicationCommand as CAC
|
|
from hydrus.client import ClientConstants as CC
|
|
from hydrus.client import ClientParsing
|
|
from hydrus.client import ClientSearch
|
|
from hydrus.client import ClientThreading
|
|
from hydrus.client.gui import ClientGUIDialogs
|
|
from hydrus.client.gui import QtPorting as QP
|
|
from hydrus.client.gui.lists import ClientGUIListBoxes
|
|
from hydrus.client.gui.lists import ClientGUIListBoxesData
|
|
from hydrus.client.gui.parsing import ClientGUIParsingLegacy
|
|
from hydrus.client.gui.widgets import ClientGUICommon
|
|
from hydrus.client.media import ClientMedia
|
|
from hydrus.client.metadata import ClientTags
|
|
from hydrus.client.metadata import ClientTagSorting
|
|
|
|
def FilterSuggestedPredicatesForMedia( predicates: typing.Sequence[ ClientSearch.Predicate ], medias: typing.Collection[ ClientMedia.Media ], service_key: bytes ) -> typing.List[ ClientSearch.Predicate ]:
|
|
|
|
tags = [ predicate.GetValue() for predicate in predicates ]
|
|
|
|
filtered_tags = FilterSuggestedTagsForMedia( tags, medias, service_key )
|
|
|
|
predicates = [ predicate for predicate in predicates if predicate.GetValue() in filtered_tags ]
|
|
|
|
return predicates
|
|
|
|
|
|
def FilterSuggestedTagsForMedia( tags: typing.Sequence[ str ], medias: typing.Collection[ ClientMedia.Media ], service_key: bytes ) -> typing.List[ str ]:
|
|
|
|
num_media = len( medias )
|
|
|
|
useful_tags_set = set( tags )
|
|
|
|
( current_tags_to_count, deleted_tags_to_count, pending_tags_to_count, petitioned_tags_to_count ) = ClientMedia.GetMediasTagCount( medias, service_key, ClientTags.TAG_DISPLAY_STORAGE )
|
|
|
|
current_tags_to_count.update( pending_tags_to_count )
|
|
|
|
# TODO: figure out a nicer way to filter out siblings and parents here
|
|
# maybe have to wait for when tags always know their siblings
|
|
# then we could also filter out worse/better siblings of the same count
|
|
|
|
# this is a sync way for now:
|
|
# db_tags_to_ideals_and_parents = HG.client_controller.Read( 'tag_display_decorators', service_key, tags_to_lookup )
|
|
|
|
for ( tag, count ) in current_tags_to_count.items():
|
|
|
|
if count == num_media:
|
|
|
|
useful_tags_set.discard( tag )
|
|
|
|
|
|
|
|
tags_filtered = [ tag for tag in tags if tag in useful_tags_set ]
|
|
|
|
return tags_filtered
|
|
|
|
class ListBoxTagsSuggestionsFavourites( ClientGUIListBoxes.ListBoxTagsStrings ):
|
|
|
|
def __init__( self, parent, service_key, activate_callable, sort_tags = True ):
|
|
|
|
ClientGUIListBoxes.ListBoxTagsStrings.__init__( self, parent, service_key = service_key, sort_tags = sort_tags, tag_display_type = ClientTags.TAG_DISPLAY_STORAGE )
|
|
|
|
self._activate_callable = activate_callable
|
|
|
|
width = HG.client_controller.new_options.GetInteger( 'suggested_tags_width' )
|
|
|
|
if width is not None:
|
|
|
|
self.setMinimumWidth( width )
|
|
|
|
|
|
|
|
def _Activate( self, ctrl_down, shift_down ) -> bool:
|
|
|
|
if len( self._selected_terms ) > 0:
|
|
|
|
tags = set( self._GetTagsFromTerms( self._selected_terms ) )
|
|
|
|
self._activate_callable( tags, only_add = True )
|
|
|
|
self._RemoveSelectedTerms()
|
|
|
|
self._DataHasChanged()
|
|
|
|
return True
|
|
|
|
|
|
return False
|
|
|
|
|
|
def _Sort( self ):
|
|
|
|
self._RegenTermsToIndices()
|
|
|
|
|
|
def ActivateAll( self ):
|
|
|
|
self._activate_callable( self.GetTags(), only_add = True )
|
|
|
|
|
|
def TakeFocusForUser( self ):
|
|
|
|
self.SelectTopItem()
|
|
|
|
self.setFocus( QC.Qt.OtherFocusReason )
|
|
|
|
|
|
class ListBoxTagsSuggestionsRelated( ClientGUIListBoxes.ListBoxTagsPredicates ):
|
|
|
|
def __init__( self, parent, service_key, activate_callable ):
|
|
|
|
ClientGUIListBoxes.ListBoxTagsPredicates.__init__( self, parent, tag_display_type = ClientTags.TAG_DISPLAY_STORAGE )
|
|
|
|
self._activate_callable = activate_callable
|
|
|
|
width = HG.client_controller.new_options.GetInteger( 'suggested_tags_width' )
|
|
|
|
self.setMinimumWidth( width )
|
|
|
|
|
|
def _Activate( self, ctrl_down, shift_down ) -> bool:
|
|
|
|
if len( self._selected_terms ) > 0:
|
|
|
|
tags = set( self._GetTagsFromTerms( self._selected_terms ) )
|
|
|
|
self._activate_callable( tags, only_add = True )
|
|
|
|
self._RemoveSelectedTerms()
|
|
|
|
self._DataHasChanged()
|
|
|
|
return True
|
|
|
|
|
|
return False
|
|
|
|
|
|
def _GenerateTermFromPredicate( self, predicate: ClientSearch.Predicate ) -> ClientGUIListBoxesData.ListBoxItemPredicate:
|
|
|
|
predicate = predicate.GetCountlessCopy()
|
|
|
|
return ClientGUIListBoxesData.ListBoxItemPredicate( predicate )
|
|
|
|
|
|
def _Sort( self ):
|
|
|
|
self._RegenTermsToIndices()
|
|
|
|
|
|
def TakeFocusForUser( self ):
|
|
|
|
self.SelectTopItem()
|
|
|
|
self.setFocus( QC.Qt.OtherFocusReason )
|
|
|
|
|
|
class FavouritesTagsPanel( QW.QWidget ):
|
|
|
|
mouseActivationOccurred = QC.Signal()
|
|
|
|
def __init__( self, parent, service_key, media, activate_callable ):
|
|
|
|
QW.QWidget.__init__( self, parent )
|
|
|
|
self._service_key = service_key
|
|
self._media = media
|
|
|
|
vbox = QP.VBoxLayout()
|
|
|
|
self._favourite_tags = ListBoxTagsSuggestionsFavourites( self, self._service_key, activate_callable, sort_tags = False )
|
|
|
|
QP.AddToLayout( vbox, self._favourite_tags, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
|
|
self.setLayout( vbox )
|
|
|
|
self._UpdateTagDisplay()
|
|
|
|
self._favourite_tags.mouseActivationOccurred.connect( self.mouseActivationOccurred )
|
|
|
|
|
|
def _UpdateTagDisplay( self ):
|
|
|
|
favourites = list( HG.client_controller.new_options.GetSuggestedTagsFavourites( self._service_key ) )
|
|
|
|
ClientTagSorting.SortTags( HG.client_controller.new_options.GetDefaultTagSort(), favourites )
|
|
|
|
tags = FilterSuggestedTagsForMedia( favourites, self._media, self._service_key )
|
|
|
|
self._favourite_tags.SetTags( tags )
|
|
|
|
|
|
def MediaUpdated( self ):
|
|
|
|
self._UpdateTagDisplay()
|
|
|
|
|
|
def SetMedia( self, media ):
|
|
|
|
self._media = media
|
|
|
|
self._UpdateTagDisplay()
|
|
|
|
|
|
def TakeFocusForUser( self ):
|
|
|
|
self._favourite_tags.TakeFocusForUser()
|
|
|
|
|
|
class RecentTagsPanel( QW.QWidget ):
|
|
|
|
mouseActivationOccurred = QC.Signal()
|
|
|
|
def __init__( self, parent, service_key, media, activate_callable ):
|
|
|
|
QW.QWidget.__init__( self, parent )
|
|
|
|
self._service_key = service_key
|
|
self._media = media
|
|
|
|
self._last_fetched_tags = []
|
|
|
|
self._new_options = HG.client_controller.new_options
|
|
|
|
vbox = QP.VBoxLayout()
|
|
|
|
clear_button = QW.QPushButton( 'clear', self )
|
|
clear_button.clicked.connect( self.EventClear )
|
|
|
|
self._recent_tags = ListBoxTagsSuggestionsFavourites( self, self._service_key, activate_callable, sort_tags = False )
|
|
|
|
QP.AddToLayout( vbox, clear_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, self._recent_tags, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
|
|
self.setLayout( vbox )
|
|
|
|
self._RefreshRecentTags()
|
|
|
|
self._recent_tags.mouseActivationOccurred.connect( self.mouseActivationOccurred )
|
|
|
|
|
|
def _RefreshRecentTags( self ):
|
|
|
|
def do_it( service_key ):
|
|
|
|
def qt_code( recent_tags ):
|
|
|
|
if not self or not QP.isValid( self ):
|
|
|
|
return
|
|
|
|
|
|
self._last_fetched_tags = recent_tags
|
|
|
|
self._UpdateTagDisplay()
|
|
|
|
if len( self._recent_tags.GetTags() ) > 0:
|
|
|
|
self._recent_tags.SelectTopItem()
|
|
|
|
|
|
|
|
recent_tags = HG.client_controller.Read( 'recent_tags', service_key )
|
|
|
|
QP.CallAfter( qt_code, recent_tags )
|
|
|
|
|
|
HG.client_controller.CallToThread( do_it, self._service_key )
|
|
|
|
|
|
def _UpdateTagDisplay( self ):
|
|
|
|
tags = FilterSuggestedTagsForMedia( self._last_fetched_tags, self._media, self._service_key )
|
|
|
|
self._recent_tags.SetTags( tags )
|
|
|
|
|
|
def EventClear( self ):
|
|
|
|
from hydrus.client.gui import ClientGUIDialogsQuick
|
|
|
|
result = ClientGUIDialogsQuick.GetYesNo( self, 'Clear recent tags?' )
|
|
|
|
if result == QW.QDialog.Accepted:
|
|
|
|
HG.client_controller.Write( 'push_recent_tags', self._service_key, None )
|
|
|
|
self._last_fetched_tags = []
|
|
|
|
self._UpdateTagDisplay()
|
|
|
|
|
|
|
|
def RefreshRecentTags( self ):
|
|
|
|
self._RefreshRecentTags()
|
|
|
|
|
|
def MediaUpdated( self ):
|
|
|
|
self._UpdateTagDisplay()
|
|
|
|
|
|
def SetMedia( self, media ):
|
|
|
|
self._media = media
|
|
|
|
self._UpdateTagDisplay()
|
|
|
|
self._RefreshRecentTags()
|
|
|
|
|
|
def TakeFocusForUser( self ):
|
|
|
|
self._recent_tags.TakeFocusForUser()
|
|
|
|
|
|
class RelatedTagsPanel( QW.QWidget ):
|
|
|
|
mouseActivationOccurred = QC.Signal()
|
|
|
|
def __init__( self, parent, service_key, media, activate_callable ):
|
|
|
|
QW.QWidget.__init__( self, parent )
|
|
|
|
self._service_key = service_key
|
|
self._media = media
|
|
|
|
self._last_fetched_predicates = []
|
|
|
|
self._have_done_search_with_this_media = False
|
|
|
|
self._selected_tags = set()
|
|
|
|
self._new_options = HG.client_controller.new_options
|
|
|
|
vbox = QP.VBoxLayout()
|
|
|
|
self._status_label = ClientGUICommon.BetterStaticText( self, label = 'ready' )
|
|
|
|
self._just_do_local_files = ClientGUICommon.OnOffButton( self, on_label = 'just for my files', off_label = 'for all known files', start_on = True )
|
|
self._just_do_local_files.setToolTip( 'Select how big the search is. Searching across all known files on a repository produces high quality results but takes a long time.' )
|
|
|
|
tt = 'If you select some tags, this will search using only those as reference!'
|
|
|
|
self._button_1 = QW.QPushButton( 'quick', self )
|
|
self._button_1.clicked.connect( self.RefreshQuick )
|
|
self._button_1.setMinimumWidth( 30 )
|
|
self._button_1.setToolTip( tt )
|
|
|
|
self._button_2 = QW.QPushButton( 'medium', self )
|
|
self._button_2.clicked.connect( self.RefreshMedium )
|
|
self._button_2.setMinimumWidth( 30 )
|
|
self._button_2.setToolTip( tt )
|
|
|
|
self._button_3 = QW.QPushButton( 'thorough', self )
|
|
self._button_3.clicked.connect( self.RefreshThorough )
|
|
self._button_3.setMinimumWidth( 30 )
|
|
self._button_3.setToolTip( tt )
|
|
|
|
if HG.client_controller.services_manager.GetServiceType( self._service_key ) == HC.LOCAL_TAG:
|
|
|
|
self._just_do_local_files.setVisible( False )
|
|
|
|
|
|
self._related_tags = ListBoxTagsSuggestionsRelated( self, service_key, activate_callable )
|
|
|
|
button_hbox = QP.HBoxLayout()
|
|
|
|
QP.AddToLayout( button_hbox, self._button_1, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
|
|
QP.AddToLayout( button_hbox, self._button_2, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
|
|
QP.AddToLayout( button_hbox, self._button_3, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
|
|
|
|
QP.AddToLayout( vbox, self._status_label, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, self._just_do_local_files, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, button_hbox, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, self._related_tags, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
|
|
self.setLayout( vbox )
|
|
|
|
self._related_tags.mouseActivationOccurred.connect( self.mouseActivationOccurred )
|
|
|
|
|
|
def _FetchRelatedTagsNew( self, max_time_to_take ):
|
|
|
|
def do_it( file_service_key, tag_service_key, search_tags ):
|
|
|
|
def qt_code( predicates, num_done, num_to_do, total_time_took ):
|
|
|
|
if not self or not QP.isValid( self ):
|
|
|
|
return
|
|
|
|
|
|
if num_to_do == len( search_tags ):
|
|
|
|
tags_s = 'tags'
|
|
|
|
else:
|
|
|
|
tags_s = 'tags ({} had no relations)'.format( HydrusData.ToHumanInt( len( search_tags ) - num_to_do ) )
|
|
|
|
|
|
if num_done == len( search_tags ):
|
|
|
|
num_done_s = 'Searched all {} {} in '.format( HydrusData.ToHumanInt( num_done ), tags_s )
|
|
|
|
elif num_done == num_to_do:
|
|
|
|
num_done_s = 'Searched {} {} in '.format( HydrusData.ToHumanInt( num_done ), tags_s )
|
|
|
|
else:
|
|
|
|
num_done_s = '{} {} searched fully in '.format( HydrusData.ConvertValueRangeToPrettyString( num_done, num_to_do ), tags_s )
|
|
|
|
|
|
label = '{}{}.'.format( num_done_s, HydrusData.TimeDeltaToPrettyTimeDelta( total_time_took ) )
|
|
|
|
self._status_label.setText( label )
|
|
|
|
self._last_fetched_predicates = predicates
|
|
|
|
self._UpdateTagDisplay()
|
|
|
|
self._have_done_search_with_this_media = True
|
|
|
|
|
|
start_time = HydrusData.GetNowPrecise()
|
|
|
|
( num_done, num_to_do, predicates ) = HG.client_controller.Read( 'related_tags', file_service_key, tag_service_key, search_tags, max_time_to_take = max_time_to_take )
|
|
|
|
total_time_took = HydrusData.GetNowPrecise() - start_time
|
|
|
|
predicates = ClientSearch.SortPredicates( predicates )
|
|
|
|
QP.CallAfter( qt_code, predicates, num_done, num_to_do, total_time_took )
|
|
|
|
|
|
self._related_tags.SetPredicates( [] )
|
|
|
|
if len( self._selected_tags ) == 0:
|
|
|
|
search_tags = ClientMedia.GetMediasTags( self._media, self._service_key, ClientTags.TAG_DISPLAY_STORAGE, ( HC.CONTENT_STATUS_CURRENT, HC.CONTENT_STATUS_PENDING ) )
|
|
|
|
else:
|
|
|
|
search_tags = self._selected_tags
|
|
|
|
|
|
if len( search_tags ) == 0:
|
|
|
|
self._status_label.setVisible( False )
|
|
|
|
return
|
|
|
|
|
|
self._status_label.setVisible( True )
|
|
|
|
self._status_label.setText( 'searching\u2026' )
|
|
|
|
if self._just_do_local_files.IsOn():
|
|
|
|
file_service_key = CC.COMBINED_LOCAL_MEDIA_SERVICE_KEY
|
|
|
|
else:
|
|
|
|
file_service_key = CC.COMBINED_FILE_SERVICE_KEY
|
|
|
|
|
|
tag_service_key = self._service_key
|
|
|
|
HG.client_controller.CallToThread( do_it, file_service_key, tag_service_key, search_tags )
|
|
|
|
|
|
def _UpdateTagDisplay( self ):
|
|
|
|
predicates = FilterSuggestedPredicatesForMedia( self._last_fetched_predicates, self._media, self._service_key )
|
|
|
|
self._related_tags.SetPredicates( predicates )
|
|
|
|
|
|
def RefreshQuick( self ):
|
|
|
|
max_time_to_take = self._new_options.GetInteger( 'related_tags_search_1_duration_ms' ) / 1000.0
|
|
|
|
self._FetchRelatedTagsNew( max_time_to_take )
|
|
|
|
|
|
def RefreshMedium( self ):
|
|
|
|
max_time_to_take = self._new_options.GetInteger( 'related_tags_search_2_duration_ms' ) / 1000.0
|
|
|
|
self._FetchRelatedTagsNew( max_time_to_take )
|
|
|
|
|
|
def RefreshThorough( self ):
|
|
|
|
max_time_to_take = self._new_options.GetInteger( 'related_tags_search_3_duration_ms' ) / 1000.0
|
|
|
|
self._FetchRelatedTagsNew( max_time_to_take )
|
|
|
|
|
|
def MediaUpdated( self ):
|
|
|
|
self._UpdateTagDisplay()
|
|
|
|
|
|
def NotifyUserLooking( self ):
|
|
|
|
if not self._have_done_search_with_this_media:
|
|
|
|
self.RefreshQuick()
|
|
|
|
|
|
|
|
def SetMedia( self, media ):
|
|
|
|
self._media = media
|
|
|
|
self._status_label.setText( 'ready' )
|
|
|
|
self._related_tags.SetPredicates( [] )
|
|
|
|
self._have_done_search_with_this_media = False
|
|
|
|
|
|
def SetSelectedTags( self, tags ):
|
|
|
|
self._selected_tags = tags
|
|
|
|
|
|
def TakeFocusForUser( self ):
|
|
|
|
self._related_tags.TakeFocusForUser()
|
|
|
|
|
|
class FileLookupScriptTagsPanel( QW.QWidget ):
|
|
|
|
mouseActivationOccurred = QC.Signal()
|
|
|
|
def __init__( self, parent, service_key, media, activate_callable ):
|
|
|
|
QW.QWidget.__init__( self, parent )
|
|
|
|
self._service_key = service_key
|
|
self._media = media
|
|
self._last_fetched_tags = []
|
|
|
|
self._script_choice = ClientGUICommon.BetterChoice( self )
|
|
|
|
self._script_choice.setEnabled( False )
|
|
|
|
self._have_fetched = False
|
|
|
|
self._fetch_button = ClientGUICommon.BetterButton( self, 'fetch tags', self.FetchTags )
|
|
|
|
self._fetch_button.setEnabled( False )
|
|
|
|
self._script_management = ClientGUIParsingLegacy.ScriptManagementControl( self )
|
|
|
|
self._tags = ListBoxTagsSuggestionsFavourites( self, self._service_key, activate_callable, sort_tags = True )
|
|
|
|
self._add_all = ClientGUICommon.BetterButton( self, 'add all', self._tags.ActivateAll )
|
|
|
|
vbox = QP.VBoxLayout()
|
|
|
|
QP.AddToLayout( vbox, self._script_choice, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, self._fetch_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, self._script_management, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, self._add_all, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
QP.AddToLayout( vbox, self._tags, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
|
|
self._SetTags( [] )
|
|
|
|
self.setLayout( vbox )
|
|
|
|
self._FetchScripts()
|
|
|
|
self._tags.mouseActivationOccurred.connect( self.mouseActivationOccurred )
|
|
|
|
|
|
def _FetchScripts( self ):
|
|
|
|
def do_it():
|
|
|
|
def qt_code():
|
|
|
|
if not self or not QP.isValid( self ):
|
|
|
|
return
|
|
|
|
|
|
script_names_to_scripts = { script.GetName() : script for script in scripts }
|
|
|
|
for ( name, script ) in list(script_names_to_scripts.items()):
|
|
|
|
self._script_choice.addItem( script.GetName(), script )
|
|
|
|
|
|
new_options = HG.client_controller.new_options
|
|
|
|
favourite_file_lookup_script = new_options.GetNoneableString( 'favourite_file_lookup_script' )
|
|
|
|
if favourite_file_lookup_script in script_names_to_scripts:
|
|
|
|
self._script_choice.SetValue( script_names_to_scripts[ favourite_file_lookup_script ] )
|
|
|
|
else:
|
|
|
|
self._script_choice.setCurrentIndex( 0 )
|
|
|
|
|
|
self._script_choice.setEnabled( True )
|
|
self._fetch_button.setEnabled( True )
|
|
|
|
|
|
scripts = HG.client_controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_PARSE_ROOT_FILE_LOOKUP )
|
|
|
|
QP.CallAfter( qt_code )
|
|
|
|
|
|
HG.client_controller.CallToThread( do_it )
|
|
|
|
|
|
def _SetTags( self, tags ):
|
|
|
|
self._last_fetched_tags = tags
|
|
|
|
self._UpdateTagDisplay()
|
|
|
|
|
|
def _UpdateTagDisplay( self ):
|
|
|
|
tags = FilterSuggestedTagsForMedia( self._last_fetched_tags, self._media, self._service_key )
|
|
|
|
self._tags.SetTags( tags )
|
|
|
|
if len( tags ) == 0:
|
|
|
|
self._add_all.setEnabled( False )
|
|
|
|
else:
|
|
|
|
self._add_all.setEnabled( True )
|
|
|
|
|
|
|
|
def FetchTags( self ):
|
|
|
|
script = self._script_choice.GetValue()
|
|
|
|
if script.UsesUserInput():
|
|
|
|
message = 'Enter the custom input for the file lookup script.'
|
|
|
|
with ClientGUIDialogs.DialogTextEntry( self, message ) as dlg:
|
|
|
|
if dlg.exec() != QW.QDialog.Accepted:
|
|
|
|
return
|
|
|
|
|
|
file_identifier = dlg.GetValue()
|
|
|
|
|
|
else:
|
|
|
|
( m, ) = self._media
|
|
|
|
file_identifier = script.ConvertMediaToFileIdentifier( m )
|
|
|
|
|
|
stop_time = HydrusData.GetNow() + 30
|
|
|
|
job_key = ClientThreading.JobKey( cancellable = True, stop_time = stop_time )
|
|
|
|
self._script_management.SetJobKey( job_key )
|
|
|
|
self._SetTags( [] )
|
|
|
|
HG.client_controller.CallToThread( self.THREADFetchTags, script, job_key, file_identifier )
|
|
|
|
|
|
def MediaUpdated( self ):
|
|
|
|
self._UpdateTagDisplay()
|
|
|
|
|
|
def SetMedia( self, media ):
|
|
|
|
self._media = media
|
|
|
|
self._UpdateTagDisplay()
|
|
|
|
|
|
def TakeFocusForUser( self ):
|
|
|
|
if self._have_fetched:
|
|
|
|
self._tags.TakeFocusForUser()
|
|
|
|
else:
|
|
|
|
self._fetch_button.setFocus( QC.Qt.OtherFocusReason )
|
|
|
|
|
|
|
|
def THREADFetchTags( self, script, job_key, file_identifier ):
|
|
|
|
def qt_code( tags ):
|
|
|
|
if not self or not QP.isValid( self ):
|
|
|
|
return
|
|
|
|
|
|
self._SetTags( tags )
|
|
|
|
self._have_fetched = True
|
|
|
|
|
|
parse_results = script.DoQuery( job_key, file_identifier )
|
|
|
|
tags = list( ClientParsing.GetTagsFromParseResults( parse_results ) )
|
|
|
|
tag_sort = ClientTagSorting.TagSort( ClientTagSorting.SORT_BY_HUMAN_TAG, sort_order = CC.SORT_ASC )
|
|
|
|
ClientTagSorting.SortTags( tag_sort, tags )
|
|
|
|
QP.CallAfter( qt_code, tags )
|
|
|
|
|
|
class SuggestedTagsPanel( QW.QWidget ):
|
|
|
|
mouseActivationOccurred = QC.Signal()
|
|
|
|
def __init__( self, parent, service_key, media, activate_callable ):
|
|
|
|
QW.QWidget.__init__( self, parent )
|
|
|
|
self._service_key = service_key
|
|
self._media = media
|
|
|
|
self._new_options = HG.client_controller.new_options
|
|
|
|
layout_mode = self._new_options.GetNoneableString( 'suggested_tags_layout' )
|
|
|
|
self._notebook = None
|
|
|
|
if layout_mode == 'notebook':
|
|
|
|
self._notebook = ClientGUICommon.BetterNotebook( self )
|
|
|
|
panel_parent = self._notebook
|
|
|
|
else:
|
|
|
|
panel_parent = self
|
|
|
|
|
|
panels = []
|
|
|
|
self._favourite_tags = None
|
|
|
|
favourites = HG.client_controller.new_options.GetSuggestedTagsFavourites( self._service_key )
|
|
|
|
if len( favourites ) > 0:
|
|
|
|
self._favourite_tags = FavouritesTagsPanel( panel_parent, service_key, media, activate_callable )
|
|
|
|
self._favourite_tags.mouseActivationOccurred.connect( self.mouseActivationOccurred )
|
|
|
|
panels.append( ( 'favourites', self._favourite_tags ) )
|
|
|
|
|
|
self._related_tags = None
|
|
|
|
if self._new_options.GetBoolean( 'show_related_tags' ):
|
|
|
|
self._related_tags = RelatedTagsPanel( panel_parent, service_key, media, activate_callable )
|
|
|
|
self._related_tags.mouseActivationOccurred.connect( self.mouseActivationOccurred )
|
|
|
|
panels.append( ( 'related', self._related_tags ) )
|
|
|
|
|
|
self._file_lookup_script_tags = None
|
|
|
|
if self._new_options.GetBoolean( 'show_file_lookup_script_tags' ) and len( media ) == 1:
|
|
|
|
self._file_lookup_script_tags = FileLookupScriptTagsPanel( panel_parent, service_key, media, activate_callable )
|
|
|
|
self._file_lookup_script_tags.mouseActivationOccurred.connect( self.mouseActivationOccurred )
|
|
|
|
panels.append( ( 'file lookup scripts', self._file_lookup_script_tags ) )
|
|
|
|
|
|
self._recent_tags = None
|
|
|
|
if self._new_options.GetNoneableInteger( 'num_recent_tags' ) is not None:
|
|
|
|
self._recent_tags = RecentTagsPanel( panel_parent, service_key, media, activate_callable )
|
|
|
|
self._recent_tags.mouseActivationOccurred.connect( self.mouseActivationOccurred )
|
|
|
|
panels.append( ( 'recent', self._recent_tags ) )
|
|
|
|
|
|
hbox = QP.HBoxLayout()
|
|
|
|
if layout_mode == 'notebook':
|
|
|
|
for ( name, panel ) in panels:
|
|
|
|
self._notebook.addTab( panel, name )
|
|
|
|
|
|
QP.AddToLayout( hbox, self._notebook, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
|
|
name_to_page_dict = {
|
|
'favourites' : self._favourite_tags,
|
|
'related' : self._related_tags,
|
|
'file_lookup_scripts' : self._file_lookup_script_tags,
|
|
'recent' : self._recent_tags
|
|
}
|
|
|
|
default_suggested_tags_notebook_page = self._new_options.GetString( 'default_suggested_tags_notebook_page' )
|
|
|
|
choice = name_to_page_dict.get( default_suggested_tags_notebook_page, None )
|
|
|
|
if choice is not None:
|
|
|
|
self._notebook.setCurrentWidget( choice )
|
|
|
|
|
|
self._notebook.currentChanged.connect( self._PageChanged )
|
|
|
|
elif layout_mode == 'columns':
|
|
|
|
for ( name, panel ) in panels:
|
|
|
|
box_panel = ClientGUICommon.StaticBox( self, name )
|
|
|
|
box_panel.Add( panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
|
|
QP.AddToLayout( hbox, box_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
|
|
|
|
|
|
|
self.setLayout( hbox )
|
|
|
|
if len( panels ) == 0:
|
|
|
|
self.hide()
|
|
|
|
else:
|
|
|
|
self._PageChanged()
|
|
|
|
|
|
|
|
def _PageChanged( self ):
|
|
|
|
if self._notebook is None:
|
|
|
|
self._related_tags.NotifyUserLooking()
|
|
|
|
return
|
|
|
|
|
|
current_page = self._notebook.currentWidget()
|
|
|
|
if current_page == self._related_tags:
|
|
|
|
self._related_tags.NotifyUserLooking()
|
|
|
|
|
|
|
|
def MediaUpdated( self ):
|
|
|
|
if self._favourite_tags is not None:
|
|
|
|
self._favourite_tags.MediaUpdated()
|
|
|
|
|
|
if self._recent_tags is not None:
|
|
|
|
self._recent_tags.MediaUpdated()
|
|
|
|
|
|
if self._file_lookup_script_tags is not None:
|
|
|
|
self._file_lookup_script_tags.MediaUpdated()
|
|
|
|
|
|
if self._related_tags is not None:
|
|
|
|
self._related_tags.MediaUpdated()
|
|
|
|
|
|
|
|
def RefreshRelatedThorough( self ):
|
|
|
|
if self._related_tags is not None:
|
|
|
|
self._related_tags.RefreshThorough()
|
|
|
|
|
|
|
|
def SetMedia( self, media ):
|
|
|
|
self._media = media
|
|
|
|
if self._favourite_tags is not None:
|
|
|
|
self._favourite_tags.SetMedia( media )
|
|
|
|
|
|
if self._recent_tags is not None:
|
|
|
|
self._recent_tags.SetMedia( media )
|
|
|
|
|
|
if self._file_lookup_script_tags is not None:
|
|
|
|
self._file_lookup_script_tags.SetMedia( media )
|
|
|
|
|
|
if self._related_tags is not None:
|
|
|
|
self._related_tags.SetMedia( media )
|
|
|
|
|
|
self._PageChanged()
|
|
|
|
|
|
def SetSelectedTags( self, tags ):
|
|
|
|
if self._related_tags is not None:
|
|
|
|
self._related_tags.SetSelectedTags( tags )
|
|
|
|
|
|
|
|
def TakeFocusForUser( self, command ):
|
|
|
|
if command == CAC.SIMPLE_SHOW_AND_FOCUS_MANAGE_TAGS_FAVOURITE_TAGS:
|
|
|
|
panel = self._favourite_tags
|
|
|
|
elif command == CAC.SIMPLE_SHOW_AND_FOCUS_MANAGE_TAGS_RELATED_TAGS:
|
|
|
|
panel = self._related_tags
|
|
|
|
elif command == CAC.SIMPLE_SHOW_AND_FOCUS_MANAGE_TAGS_FILE_LOOKUP_SCRIPT_TAGS:
|
|
|
|
panel = self._file_lookup_script_tags
|
|
|
|
elif command == CAC.SIMPLE_SHOW_AND_FOCUS_MANAGE_TAGS_RECENT_TAGS:
|
|
|
|
panel = self._recent_tags
|
|
|
|
|
|
if panel is not None:
|
|
|
|
if self._notebook is not None:
|
|
|
|
self._notebook.SelectPage( panel )
|
|
|
|
|
|
panel.TakeFocusForUser()
|
|
|
|
|
|
|