hydrus/include/ClientGUIExport.py

962 lines
33 KiB
Python

from . import ClientConstants as CC
from . import ClientExporting
from . import ClientGUIACDropdown
from . import ClientGUICommon
from . import ClientGUIDialogsQuick
from . import ClientGUIListBoxes
from . import ClientGUIListCtrl
from . import ClientGUIScrolledPanels
from . import ClientGUIScrolledPanelsEdit
from . import ClientGUITime
from . import ClientGUITopLevelWindows
from . import ClientSearch
from . import ClientTags
from . import HydrusConstants as HC
from . import HydrusData
from . import HydrusExceptions
from . import HydrusGlobals as HG
from . import HydrusPaths
import os
import time
import traceback
from qtpy import QtCore as QC
from qtpy import QtWidgets as QW
from . import QtPorting as QP
class EditExportFoldersPanel( ClientGUIScrolledPanels.EditPanel ):
def __init__( self, parent, export_folders ):
ClientGUIScrolledPanels.EditPanel.__init__( self, parent )
self._export_folders_panel = ClientGUIListCtrl.BetterListCtrlPanel( self )
columns = [ ( 'name', 20 ), ( 'path', -1 ), ( 'type', 12 ), ( 'query', 16 ), ( 'paused', 8 ), ( 'period', 16 ), ( 'phrase', 20 ) ]
self._export_folders = ClientGUIListCtrl.BetterListCtrl( self._export_folders_panel, 'export_folders', 6, 40, columns, self._ConvertExportFolderToListCtrlTuples, use_simple_delete = True, activation_callback = self._Edit )
self._export_folders_panel.SetListCtrl( self._export_folders )
self._export_folders_panel.AddButton( 'add', self._AddFolder )
self._export_folders_panel.AddButton( 'edit', self._Edit, enabled_only_on_selection = True )
self._export_folders_panel.AddDeleteButton()
#
self._export_folders.AddDatas( export_folders )
vbox = QP.VBoxLayout()
intro = 'Here you can set the client to regularly export a certain query to a particular location.'
QP.AddToLayout( vbox, ClientGUICommon.BetterStaticText(self,intro), CC.FLAGS_EXPAND_PERPENDICULAR )
QP.AddToLayout( vbox, self._export_folders_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
self.widget().setLayout( vbox )
def _AddFolder( self ):
new_options = HG.client_controller.new_options
phrase = new_options.GetString( 'export_phrase' )
name = 'export folder'
path = ''
export_type = HC.EXPORT_FOLDER_TYPE_REGULAR
delete_from_client_after_export = False
file_search_context = ClientSearch.FileSearchContext( file_service_key = CC.LOCAL_FILE_SERVICE_KEY )
period = 15 * 60
export_folder = ClientExporting.ExportFolder( name, path, export_type = export_type, delete_from_client_after_export = delete_from_client_after_export, file_search_context = file_search_context, period = period, phrase = phrase )
with ClientGUITopLevelWindows.DialogEdit( self, 'edit export folder' ) as dlg:
panel = EditExportFolderPanel( dlg, export_folder )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
export_folder = panel.GetValue()
export_folder.SetNonDupeName( self._GetExistingNames() )
self._export_folders.AddDatas( ( export_folder, ) )
def _ConvertExportFolderToListCtrlTuples( self, export_folder ):
( name, path, export_type, delete_from_client_after_export, file_search_context, run_regularly, period, phrase, last_checked, paused, run_now ) = export_folder.ToTuple()
if export_type == HC.EXPORT_FOLDER_TYPE_REGULAR:
pretty_export_type = 'regular'
elif export_type == HC.EXPORT_FOLDER_TYPE_SYNCHRONISE:
pretty_export_type = 'synchronise'
if delete_from_client_after_export:
pretty_export_type += ' and deleting from the client!'
pretty_file_search_context = ', '.join( predicate.ToString( with_count = False ) for predicate in file_search_context.GetPredicates() )
if run_regularly:
pretty_period = HydrusData.TimeDeltaToPrettyTimeDelta( period )
else:
pretty_period = 'not running regularly'
if run_now:
pretty_period += ' (running after dialog ok)'
if paused:
pretty_paused = 'yes'
else:
pretty_paused = ''
pretty_phrase = phrase
display_tuple = ( name, path, pretty_export_type, pretty_file_search_context, pretty_paused, pretty_period, pretty_phrase )
sort_tuple = ( name, path, pretty_export_type, pretty_file_search_context, paused, period, phrase )
return ( display_tuple, sort_tuple )
def _Edit( self ):
export_folders = self._export_folders.GetData( only_selected = True )
for export_folder in export_folders:
with ClientGUITopLevelWindows.DialogEdit( self, 'edit export folder' ) as dlg:
panel = EditExportFolderPanel( dlg, export_folder )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
edited_export_folder = panel.GetValue()
self._export_folders.DeleteDatas( ( export_folder, ) )
edited_export_folder.SetNonDupeName( self._GetExistingNames() )
self._export_folders.AddDatas( ( edited_export_folder, ) )
else:
return
def _GetExistingNames( self ):
existing_names = { export_folder.GetName() for export_folder in self._export_folders.GetData() }
return existing_names
def GetValue( self ):
export_folders = self._export_folders.GetData()
return export_folders
class EditExportFolderPanel( ClientGUIScrolledPanels.EditPanel ):
def __init__( self, parent, export_folder ):
ClientGUIScrolledPanels.EditPanel.__init__( self, parent )
self._export_folder = export_folder
( name, path, export_type, delete_from_client_after_export, file_search_context, run_regularly, period, phrase, self._last_checked, paused, run_now ) = self._export_folder.ToTuple()
self._path_box = ClientGUICommon.StaticBox( self, 'name and location' )
self._name = QW.QLineEdit( self._path_box )
self._path = QP.DirPickerCtrl( self._path_box )
#
self._type_box = ClientGUICommon.StaticBox( self, 'type of export' )
self._type = ClientGUICommon.BetterChoice( self._type_box )
self._type.addItem( 'regular', HC.EXPORT_FOLDER_TYPE_REGULAR )
self._type.addItem( 'synchronise', HC.EXPORT_FOLDER_TYPE_SYNCHRONISE )
self._delete_from_client_after_export = QW.QCheckBox( self._type_box )
#
self._query_box = ClientGUICommon.StaticBox( self, 'query to export' )
self._page_key = 'export folders placeholder'
self._tag_autocomplete = ClientGUIACDropdown.AutoCompleteDropdownTagsRead( self._query_box, self._page_key, file_search_context, allow_all_known_files = False, force_system_everything = True )
#
self._period_box = ClientGUICommon.StaticBox( self, 'export period' )
self._period = ClientGUITime.TimeDeltaButton( self._period_box, min = 3 * 60, days = True, hours = True, minutes = True )
self._run_regularly = QW.QCheckBox( self._period_box )
self._paused = QW.QCheckBox( self._period_box )
self._run_now = QW.QCheckBox( self._period_box )
#
self._phrase_box = ClientGUICommon.StaticBox( self, 'filenames' )
self._pattern = QW.QLineEdit( self._phrase_box )
self._examples = ClientGUICommon.ExportPatternButton( self._phrase_box )
#
self._name.setText( name )
self._path.SetPath( path )
self._type.SetValue( export_type )
self._delete_from_client_after_export.setChecked( delete_from_client_after_export )
self._period.SetValue( period )
self._run_regularly.setChecked( run_regularly )
self._paused.setChecked( paused )
self._run_now.setChecked( run_now )
self._pattern.setText( phrase )
#
rows = []
rows.append( ( 'name: ', self._name ) )
rows.append( ( 'folder path: ', self._path ) )
gridbox = ClientGUICommon.WrapInGrid( self._path_box, rows )
self._path_box.Add( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
#
text = '''regular - try to export the files to the directory, overwriting if the filesize if different
synchronise - try to export the files to the directory, overwriting if the filesize if different, and delete anything else in the directory
If you select synchronise, be careful!'''
st = ClientGUICommon.BetterStaticText( self._type_box, label = text )
st.setWordWrap( True )
self._type_box.Add( st, CC.FLAGS_EXPAND_PERPENDICULAR )
self._type_box.Add( self._type, CC.FLAGS_EXPAND_PERPENDICULAR )
rows = []
rows.append( ( 'delete files from client after export: ', self._delete_from_client_after_export ) )
gridbox = ClientGUICommon.WrapInGrid( self._type_box, rows )
self._type_box.Add( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
self._query_box.Add( self._tag_autocomplete )
self._period_box.Add( self._period, CC.FLAGS_EXPAND_PERPENDICULAR )
rows = []
rows.append( ( 'run regularly?: ', self._run_regularly ) )
rows.append( ( 'paused: ', self._paused ) )
rows.append( ( 'run on dialog ok: ', self._run_now ) )
gridbox = ClientGUICommon.WrapInGrid( self._period_box, rows )
self._period_box.Add( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
phrase_hbox = QP.HBoxLayout()
QP.AddToLayout( phrase_hbox, self._pattern, CC.FLAGS_EXPAND_BOTH_WAYS )
QP.AddToLayout( phrase_hbox, self._examples, CC.FLAGS_VCENTER )
self._phrase_box.Add( phrase_hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
vbox = QP.VBoxLayout()
QP.AddToLayout( vbox, self._path_box, CC.FLAGS_EXPAND_PERPENDICULAR )
QP.AddToLayout( vbox, self._type_box, CC.FLAGS_EXPAND_PERPENDICULAR )
QP.AddToLayout( vbox, self._query_box, CC.FLAGS_EXPAND_BOTH_WAYS )
QP.AddToLayout( vbox, self._period_box, CC.FLAGS_EXPAND_PERPENDICULAR )
QP.AddToLayout( vbox, self._phrase_box, CC.FLAGS_EXPAND_PERPENDICULAR )
self.widget().setLayout( vbox )
self._UpdateTypeDeleteUI()
self._type.currentIndexChanged.connect( self._UpdateTypeDeleteUI )
self._delete_from_client_after_export.clicked.connect( self.EventDeleteFilesAfterExport )
def _UpdateTypeDeleteUI( self ):
if self._type.GetValue() == HC.EXPORT_FOLDER_TYPE_SYNCHRONISE:
self._delete_from_client_after_export.setEnabled( False )
if self._delete_from_client_after_export.isChecked():
self._delete_from_client_after_export.setChecked( False )
else:
self._delete_from_client_after_export.setEnabled( True )
def CanOK( self ):
if self._delete_from_client_after_export.isChecked():
message = 'You have set this export folder to delete the files from the client after export! Are you absolutely sure this is what you want?'
result = ClientGUIDialogsQuick.GetYesNo( self, message )
if result != QW.QDialog.Accepted:
return False
return True
def EventDeleteFilesAfterExport( self ):
if self._delete_from_client_after_export.isChecked():
QW.QMessageBox.warning( self, 'Warning', 'This will delete the exported files from your client after the export! If you do not know what this means, uncheck it!' )
def GetValue( self ):
name = self._name.text()
path = self._path.GetPath()
export_type = self._type.GetValue()
delete_from_client_after_export = self._delete_from_client_after_export.isChecked()
file_search_context = self._tag_autocomplete.GetFileSearchContext()
run_regularly = self._run_regularly.isChecked()
period = self._period.GetValue()
if self._path.GetPath() in ( '', None ):
raise HydrusExceptions.VetoException( 'You must enter a folder path to export to!' )
phrase = self._pattern.text()
try:
ClientExporting.ParseExportPhrase( phrase )
except Exception as e:
raise HydrusExceptions.VetoException( 'Could not parse that export phrase! ' + str( e ) )
run_now = self._run_now.isChecked()
paused = self._paused.isChecked()
export_folder = ClientExporting.ExportFolder( name, path = path, export_type = export_type, delete_from_client_after_export = delete_from_client_after_export, file_search_context = file_search_context, run_regularly = run_regularly, period = period, phrase = phrase, last_checked = self._last_checked, paused = paused, run_now = run_now )
return export_folder
class ReviewExportFilesPanel( ClientGUIScrolledPanels.ReviewPanel ):
def __init__( self, parent, flat_media, do_export_and_then_quit = False ):
ClientGUIScrolledPanels.ReviewPanel.__init__( self, parent )
new_options = HG.client_controller.new_options
self._media_to_paths = {}
self._existing_filenames = set()
self._last_phrase_used = ''
self._last_dir_used = ''
self._tags_box = ClientGUICommon.StaticBoxSorterForListBoxTags( self, 'files\' tags' )
services_manager = HG.client_controller.services_manager
self._neighbouring_txt_tag_service_keys = services_manager.FilterValidServiceKeys( new_options.GetKeyList( 'default_neighbouring_txt_tag_service_keys' ) )
t = ClientGUIListBoxes.ListBoxTagsSelection( self._tags_box, ClientTags.TAG_DISPLAY_SIBLINGS_AND_PARENTS, include_counts = True )
self._tags_box.SetTagsBox( t )
self._tags_box.setMinimumSize( QC.QSize( 220, 300 ) )
columns = [ ( 'number', 8 ), ( 'filetype', 20 ), ( 'expected path', -1 ) ]
self._paths = ClientGUIListCtrl.BetterListCtrl( self, 'export_files', 24, 64, columns, self._ConvertDataToListCtrlTuples, use_simple_delete = True )
self._paths.Sort( 0 )
self._export_path_box = ClientGUICommon.StaticBox( self, 'export path' )
self._directory_picker = QP.DirPickerCtrl( self._export_path_box )
self._directory_picker.dirPickerChanged.connect( self._RefreshPaths )
self._open_location = QW.QPushButton( 'open this location', self._export_path_box )
self._open_location.clicked.connect( self.EventOpenLocation )
self._filenames_box = ClientGUICommon.StaticBox( self, 'filenames' )
self._pattern = QW.QLineEdit( self._filenames_box )
self._update = QW.QPushButton( 'update', self._filenames_box )
self._update.clicked.connect( self._RefreshPaths )
self._examples = ClientGUICommon.ExportPatternButton( self._filenames_box )
self._delete_files_after_export = QW.QCheckBox( 'delete files from client after export?', self )
self._delete_files_after_export.setObjectName( 'HydrusWarning' )
self._export_symlinks = QW.QCheckBox( 'EXPERIMENTAL: export symlinks', self )
self._export_symlinks.setObjectName( 'HydrusWarning' )
text = 'This will export all the files\' tags, newline separated, into .txts beside the files themselves.'
self._export_tag_txts_services_button = ClientGUICommon.BetterButton( self, 'set .txt services', self._SetTxtServices )
self._export_tag_txts = QW.QCheckBox( 'export tags to .txt files?', self )
self._export_tag_txts.setToolTip( text )
self._export_tag_txts.clicked.connect( self.EventExportTagTxtsChanged )
self._export = QW.QPushButton( 'export', self )
self._export.clicked.connect( self._DoExport )
#
export_path = ClientExporting.GetExportPath()
self._directory_picker.SetPath( export_path )
phrase = new_options.GetString( 'export_phrase' )
self._pattern.setText( phrase )
if len( self._neighbouring_txt_tag_service_keys ) > 0:
self._export_tag_txts.setChecked( True )
self._paths.SetData( list( enumerate( flat_media ) ) )
self._delete_files_after_export.setChecked( HG.client_controller.new_options.GetBoolean( 'delete_files_after_export' ) )
self._delete_files_after_export.clicked.connect( self.EventDeleteFilesChanged )
if not HG.client_controller.new_options.GetBoolean( 'advanced_mode' ):
self._export_symlinks.setVisible( False )
#
top_hbox = QP.HBoxLayout()
QP.AddToLayout( top_hbox, self._tags_box, CC.FLAGS_EXPAND_PERPENDICULAR )
QP.AddToLayout( top_hbox, self._paths, CC.FLAGS_EXPAND_BOTH_WAYS )
hbox = QP.HBoxLayout()
QP.AddToLayout( hbox, self._directory_picker, CC.FLAGS_EXPAND_BOTH_WAYS )
QP.AddToLayout( hbox, self._open_location, CC.FLAGS_VCENTER )
self._export_path_box.Add( hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
hbox = QP.HBoxLayout()
QP.AddToLayout( hbox, self._pattern, CC.FLAGS_EXPAND_BOTH_WAYS )
QP.AddToLayout( hbox, self._update, CC.FLAGS_VCENTER )
QP.AddToLayout( hbox, self._examples, CC.FLAGS_VCENTER )
self._filenames_box.Add( hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
txt_hbox = QP.HBoxLayout()
QP.AddToLayout( txt_hbox, self._export_tag_txts_services_button, CC.FLAGS_VCENTER )
QP.AddToLayout( txt_hbox, self._export_tag_txts, CC.FLAGS_VCENTER )
vbox = QP.VBoxLayout()
QP.AddToLayout( vbox, top_hbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
QP.AddToLayout( vbox, self._export_path_box, CC.FLAGS_EXPAND_PERPENDICULAR )
QP.AddToLayout( vbox, self._filenames_box, CC.FLAGS_EXPAND_PERPENDICULAR )
QP.AddToLayout( vbox, self._delete_files_after_export, CC.FLAGS_LONE_BUTTON )
QP.AddToLayout( vbox, self._export_symlinks, CC.FLAGS_LONE_BUTTON )
QP.AddToLayout( vbox, txt_hbox, CC.FLAGS_LONE_BUTTON )
QP.AddToLayout( vbox, self._export, CC.FLAGS_LONE_BUTTON )
self.widget().setLayout( vbox )
self._RefreshTags()
self._UpdateTxtButton()
HG.client_controller.CallAfterQtSafe( self._export, self._export.setFocus, QC.Qt.OtherFocusReason)
self._paths.itemSelectionChanged.connect( self._RefreshTags )
if do_export_and_then_quit:
QP.CallAfter( self._DoExport, True )
def _ConvertDataToListCtrlTuples( self, data ):
directory = self._directory_picker.GetPath()
( ordering_index, media ) = data
number = ordering_index
mime = media.GetMime()
try:
path = self._GetPath( media )
except Exception as e:
path = str( e )
pretty_number = HydrusData.ToHumanInt( ordering_index + 1 )
pretty_mime = HC.mime_string_lookup[ mime ]
pretty_path = path
if not path.startswith( directory ):
pretty_path = 'INVALID, above destination directory: ' + path
display_tuple = ( pretty_number, pretty_mime, pretty_path )
sort_tuple = ( number, pretty_mime, path )
return ( display_tuple, sort_tuple )
def _DoExport( self, quit_afterwards = False ):
delete_afterwards = self._delete_files_after_export.isChecked()
export_symlinks = self._export_symlinks.isChecked() and not delete_afterwards
if quit_afterwards:
message = 'Export as shown?'
if delete_afterwards:
message += os.linesep * 2
message += 'THE FILES WILL BE DELETED FROM THE CLIENT AFTERWARDS'
result = ClientGUIDialogsQuick.GetYesNo( self, message )
if result != QW.QDialog.Accepted:
self.parentWidget().close()
return
elif delete_afterwards:
message = 'THE FILES WILL BE DELETED FROM THE CLIENT AFTERWARDS'
result = ClientGUIDialogsQuick.GetYesNo( self, message )
if result != QW.QDialog.Accepted:
return
self._RefreshPaths()
export_tag_txts = self._export_tag_txts.isChecked()
if self._export_tag_txts.isChecked():
neighbouring_txt_tag_service_keys = self._neighbouring_txt_tag_service_keys
else:
neighbouring_txt_tag_service_keys = []
directory = self._directory_picker.GetPath()
HydrusPaths.MakeSureDirectoryExists( directory )
pattern = self._pattern.text()
HG.client_controller.new_options.SetString( 'export_phrase', pattern )
try:
terms = ClientExporting.ParseExportPhrase( pattern )
except Exception as e:
QW.QMessageBox.critical( self, 'Error', str(e) )
return
client_files_manager = HG.client_controller.client_files_manager
self._export.setEnabled( False )
to_do = self._paths.GetData()
num_to_do = len( to_do )
def qt_update_label( text ):
if not QP.isValid( self ) or not QP.isValid( self._export ) or not self._export:
return
self._export.setText( text )
def qt_done( quit_afterwards ):
if not QP.isValid( self ) or not QP.isValid( self._export ) or not self._export:
return
self._export.setEnabled( True )
if quit_afterwards:
QP.CallAfter( self.parentWidget().close() )
def do_it( directory, neighbouring_txt_tag_service_keys, delete_afterwards, export_symlinks, quit_afterwards ):
pauser = HydrusData.BigJobPauser()
for ( index, ( ordering_index, media ) ) in enumerate( to_do ):
try:
QP.CallAfter( qt_update_label, HydrusData.ConvertValueRangeToPrettyString(index+1,num_to_do) )
hash = media.GetHash()
mime = media.GetMime()
path = self._GetPath( media )
path = os.path.normpath( path )
if not path.startswith( directory ):
raise Exception( 'It seems a destination path was above the main export directory! The file was "{}" and its destination path was "{}".'.format( hash.hex(), path ) )
path_dir = os.path.dirname( path )
HydrusPaths.MakeSureDirectoryExists( path_dir )
if export_tag_txts:
tags_manager = media.GetTagsManager()
tags = set()
for service_key in neighbouring_txt_tag_service_keys:
current_tags = tags_manager.GetCurrent( service_key, ClientTags.TAG_DISPLAY_SIBLINGS_AND_PARENTS )
tags.update( current_tags )
tags = list( tags )
tags.sort()
txt_path = path + '.txt'
with open( txt_path, 'w', encoding = 'utf-8' ) as f:
f.write( os.linesep.join( tags ) )
source_path = client_files_manager.GetFilePath( hash, mime, check_file_exists = False )
if export_symlinks:
os.symlink( source_path, path )
else:
HydrusPaths.MirrorFile( source_path, path )
HydrusPaths.MakeFileWritable( path )
except:
QP.CallAfter( QW.QMessageBox.information, self, 'Information', 'Encountered a problem while attempting to export file with index '+str(ordering_index+1)+':'+os.linesep*2+traceback.format_exc() )
break
pauser.Pause()
if delete_afterwards:
QP.CallAfter( qt_update_label, 'deleting' )
deletee_hashes = { media.GetHash() for ( ordering_index, media ) in to_do }
chunks_of_hashes = HydrusData.SplitListIntoChunks( deletee_hashes, 64 )
reason = 'Deleted after manual export to "{}".'.format( directory )
content_updates = [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_DELETE, chunk_of_hashes, reason = reason ) for chunk_of_hashes in chunks_of_hashes ]
for content_update in content_updates:
HG.client_controller.WriteSynchronous( 'content_updates', { CC.LOCAL_FILE_SERVICE_KEY : [ content_update ] } )
QP.CallAfter( qt_update_label, 'done!' )
time.sleep( 1 )
QP.CallAfter( qt_update_label, 'export' )
QP.CallAfter( qt_done, quit_afterwards )
HG.client_controller.CallToThread( do_it, directory, neighbouring_txt_tag_service_keys, delete_afterwards, export_symlinks, quit_afterwards )
def _GetPath( self, media ):
if media in self._media_to_paths:
return self._media_to_paths[ media ]
directory = self._directory_picker.GetPath()
pattern = self._pattern.text()
terms = ClientExporting.ParseExportPhrase( pattern )
filename = ClientExporting.GenerateExportFilename( directory, media, terms )
i = 1
while filename in self._existing_filenames:
filename = ClientExporting.GenerateExportFilename( directory, media, terms, append_number = i )
i += 1
path = os.path.join( directory, filename )
path = os.path.normpath( path )
self._existing_filenames.add( filename )
self._media_to_paths[ media ] = path
return path
def _RefreshPaths( self ):
pattern = self._pattern.text()
dir_path = self._directory_picker.GetPath()
if pattern == self._last_phrase_used and dir_path == self._last_dir_used:
return
self._last_phrase_used = pattern
self._last_dir_used = dir_path
HG.client_controller.new_options.SetString( 'export_phrase', pattern )
self._existing_filenames = set()
self._media_to_paths = {}
self._paths.UpdateDatas()
def _RefreshTags( self ):
data = self._paths.GetData( only_selected = True )
if len( data ) == 0:
data = self._paths.GetData()
all_media = [ media for ( ordering_index, media ) in data ]
self._tags_box.SetTagsByMedia( all_media )
def _SetTxtServices( self ):
services_manager = HG.client_controller.services_manager
tag_services = services_manager.GetServices( HC.REAL_TAG_SERVICES )
choice_tuples = [ ( service.GetName(), service.GetServiceKey(), service.GetServiceKey() in self._neighbouring_txt_tag_service_keys ) for service in tag_services ]
with ClientGUITopLevelWindows.DialogEdit( self, 'select tag services' ) as dlg:
panel = ClientGUIScrolledPanelsEdit.EditChooseMultiple( dlg, choice_tuples )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
self._neighbouring_txt_tag_service_keys = panel.GetValue()
HG.client_controller.new_options.SetKeyList( 'default_neighbouring_txt_tag_service_keys', self._neighbouring_txt_tag_service_keys )
if len( self._neighbouring_txt_tag_service_keys ) == 0:
self._export_tag_txts.setChecked( False )
self._UpdateTxtButton()
def _UpdateTxtButton( self ):
if self._export_tag_txts.isChecked():
self._export_tag_txts_services_button.setEnabled( True )
else:
self._export_tag_txts_services_button.setEnabled( False )
if len( self._neighbouring_txt_tag_service_keys ) == 0:
tt = 'No services set.'
else:
names = [ HG.client_controller.services_manager.GetName( service_key ) for service_key in self._neighbouring_txt_tag_service_keys ]
tt = ', '.join( names )
self._export_tag_txts_services_button.setToolTip( tt )
def EventExport( self, event ):
self._DoExport()
def EventDeleteFilesChanged( self ):
value = self._delete_files_after_export.isChecked()
HG.client_controller.new_options.SetBoolean( 'delete_files_after_export', value )
if value:
self._export_symlinks.setChecked( False )
def EventExportTagTxtsChanged( self ):
turning_on = self._export_tag_txts.isChecked()
self._UpdateTxtButton()
if turning_on:
self._SetTxtServices()
else:
HG.client_controller.new_options.SetKeyList( 'default_neighbouring_txt_tag_service_keys', [] )
def EventOpenLocation( self ):
directory = self._directory_picker.GetPath()
if directory is not None and directory != '':
HydrusPaths.LaunchDirectory( directory )