hydrus/include/ClientGUISearchPanels.py

359 lines
12 KiB
Python

from . import ClientConstants as CC
from . import ClientGUIFunctions
from . import ClientGUICommon
from . import ClientGUIDialogsQuick
from . import ClientGUIListCtrl
from . import ClientGUIScrolledPanels
from . import ClientGUISearch
from . import ClientGUITopLevelWindows
from . import ClientSearch
import collections
from . import HydrusConstants as HC
from . import HydrusData
from . import HydrusExceptions
from . import HydrusGlobals as HG
import itertools
import typing
from qtpy import QtWidgets as QW
from . import QtPorting as QP
class EditFavouriteSearchPanel( ClientGUIScrolledPanels.EditPanel ):
def __init__( self, parent, existing_folders_to_names, foldername, name, file_search_context, synchronised, media_sort, media_collect ):
ClientGUIScrolledPanels.EditPanel.__init__( self, parent )
self._existing_folders_to_names = existing_folders_to_names
self._original_folder_and_name = ( foldername, name )
self._foldername = QW.QLineEdit( self )
self._name = QW.QLineEdit( self )
self._media_sort = ClientGUISearch.MediaSortControl( self )
self._media_collect = ClientGUISearch.MediaCollectControl( self, silent = True )
page_key = HydrusData.GenerateKey()
from . import ClientGUIACDropdown
from . import ClientGUIListBoxes
self._tag_autocomplete = ClientGUIACDropdown.AutoCompleteDropdownTagsRead( self, page_key, file_search_context, media_sort_widget = self._media_sort, media_collect_widget = self._media_collect, synchronised = synchronised, hide_favourites_edit_actions = True )
self._include_media_sort = QW.QCheckBox( self )
self._include_media_collect = QW.QCheckBox( self )
width = ClientGUIFunctions.ConvertTextToPixelWidth( self._include_media_collect, 48 )
self._include_media_collect.setMinimumWidth( width )
self._include_media_sort.stateChanged.connect( self._UpdateWidgets )
self._include_media_collect.stateChanged.connect( self._UpdateWidgets )
#
if foldername is not None:
self._foldername.setText( foldername )
self._name.setText( name )
if media_sort is not None:
self._include_media_sort.setChecked( True )
self._media_sort.SetSort( media_sort )
if media_collect is not None:
self._include_media_collect.setChecked( True )
self._media_collect.SetCollect( media_collect )
#
rows = []
rows.append( ( 'folder (blank for none): ', self._foldername ) )
rows.append( ( 'name: ', self._name ) )
top_gridbox = ClientGUICommon.WrapInGrid( self, rows )
rows = []
rows.append( ( 'save sort: ', self._include_media_sort ) )
rows.append( ( 'sort: ', self._media_sort ) )
rows.append( ( 'save collect: ', self._include_media_collect ) )
rows.append( ( 'collect: ', self._media_collect ) )
bottom_gridbox = ClientGUICommon.WrapInGrid( self, rows )
vbox = QP.VBoxLayout()
QP.AddToLayout( vbox, top_gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
QP.AddToLayout( vbox, self._tag_autocomplete, CC.FLAGS_EXPAND_PERPENDICULAR )
QP.AddToLayout( vbox, bottom_gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
self.widget().setLayout( vbox )
def _UpdateWidgets( self ):
self._media_sort.setEnabled( self._include_media_sort.isChecked() )
self._media_collect.setEnabled( self._include_media_collect.isChecked() )
def CanOK( self ):
( foldername, name, file_search_context, synchronised, media_sort, media_collect ) = self.GetValue()
if ( foldername, name ) != self._original_folder_and_name:
if foldername in self._existing_folders_to_names and name in self._existing_folders_to_names[ foldername ]:
if foldername is None:
folder_str = ''
else:
folder_str = ' under folder "{}"'.format( foldername )
message = 'The search "{}"{} already exists! Do you want to overwrite it?'.format( name, folder_str )
result = ClientGUIDialogsQuick.GetYesNo( self, message )
if result != QW.QDialog.Accepted:
return False
return True
def GetValue( self ):
foldername = self._foldername.text()
if foldername == '':
foldername = None
name = self._name.text()
file_search_context = self._tag_autocomplete.GetFileSearchContext()
synchronised = self._tag_autocomplete.IsSynchronised()
if self._include_media_sort.isChecked():
media_sort = self._media_sort.GetSort()
else:
media_sort = None
if self._include_media_collect.isChecked():
media_collect = self._media_collect.GetValue()
else:
media_collect = None
return ( foldername, name, file_search_context, synchronised, media_sort, media_collect )
class EditFavouriteSearchesPanel( ClientGUIScrolledPanels.EditPanel ):
def __init__( self, parent, favourite_searches_rows, initial_search_row_to_edit = None ):
ClientGUIScrolledPanels.EditPanel.__init__( self, parent )
self._favourite_searches_panel = ClientGUIListCtrl.BetterListCtrlPanel( self )
columns = [ ( 'folder', 24 ), ( 'name', 24 ), ( 'search', -1 ), ( 'sort', 24 ), ( 'collect', 24 ) ]
self._favourite_searches = ClientGUIListCtrl.BetterListCtrl( self._favourite_searches_panel, 'favourite_searches', 20, 72, columns, self._ConvertRowToListCtrlTuples, use_simple_delete = True, activation_callback = self._EditFavouriteSearch )
self._favourite_searches_panel.SetListCtrl( self._favourite_searches )
self._favourite_searches_panel.AddButton( 'add', self._AddNewFavouriteSearch )
self._favourite_searches_panel.AddButton( 'edit', self._EditFavouriteSearch, enabled_only_on_selection = True )
self._favourite_searches_panel.AddDeleteButton()
#
self._favourite_searches.AddDatas( favourite_searches_rows )
self._favourite_searches.Sort( 0 )
#
vbox = QP.VBoxLayout()
QP.AddToLayout( vbox, self._favourite_searches_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
self.widget().setLayout( vbox )
if initial_search_row_to_edit is not None:
HG.client_controller.CallLaterQtSafe( self, 0.5, self._AddNewFavouriteSearch, initial_search_row_to_edit )
def _AddNewFavouriteSearch( self, search_row = None ):
existing_folders_to_names = self._GetExistingFoldersToNames()
existing_names = { name for name in itertools.chain.from_iterable( existing_folders_to_names.values() ) }
if search_row is None:
foldername = None
name = 'new favourite search'
file_search_context = ClientSearch.FileSearchContext( file_service_key = CC.LOCAL_FILE_SERVICE_KEY )
synchronised = True
media_sort = None
media_collect = None
else:
( foldername, name, file_search_context, synchronised, media_sort, media_collect ) = search_row
name = HydrusData.GetNonDupeName( name, existing_names )
with ClientGUITopLevelWindows.DialogEdit( self, 'edit favourite search' ) as dlg:
panel = EditFavouriteSearchPanel( dlg, existing_folders_to_names, foldername, name, file_search_context, synchronised, media_sort, media_collect )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
row = panel.GetValue()
self._DeleteRow( row[0], row[1] )
self._favourite_searches.AddDatas( ( row, ) )
self._favourite_searches.Sort()
def _ConvertRowToListCtrlTuples( self, row ):
( foldername, name, file_search_context, synchronised, media_sort, media_collect ) = row
if foldername is None:
pretty_foldername = ''
else:
pretty_foldername = foldername
pretty_name = name
pretty_file_search_context = ', '.join( predicate.ToString() for predicate in file_search_context.GetPredicates() )
if media_sort is None:
pretty_media_sort = ''
else:
pretty_media_sort = media_sort.ToString()
if media_collect is None:
pretty_media_collect = ''
else:
pretty_media_collect = media_collect.ToString()
display_tuple = ( pretty_foldername, pretty_name, pretty_file_search_context, pretty_media_sort, pretty_media_collect )
sort_tuple = ( pretty_foldername, pretty_name, pretty_file_search_context, pretty_media_sort, pretty_media_collect )
return ( display_tuple, sort_tuple )
def _DeleteRow( self, foldername, name ):
for row in self._favourite_searches.GetData():
if foldername == row[0] and name == row[1]:
self._favourite_searches.DeleteDatas( ( row, ) )
return
def _EditFavouriteSearch( self ):
for row in self._favourite_searches.GetData( only_selected = True ):
( foldername, name, file_search_context, synchronised, media_sort, media_collect ) = row
existing_folders_to_names = self._GetExistingFoldersToNames()
with ClientGUITopLevelWindows.DialogEdit( self, 'edit favourite search' ) as dlg:
panel = EditFavouriteSearchPanel( dlg, existing_folders_to_names, foldername, name, file_search_context, synchronised, media_sort, media_collect )
dlg.SetPanel( panel )
if dlg.exec() == QW.QDialog.Accepted:
self._DeleteRow( foldername, name )
edited_row = panel.GetValue()
self._DeleteRow( edited_row[0], edited_row[1] )
self._favourite_searches.AddDatas( ( edited_row, ) )
else:
break
self._favourite_searches.Sort()
def _GetExistingFoldersToNames( self ):
existing_folders_to_names = collections.defaultdict( list )
for ( foldername, name, file_search_context, synchronised, media_sort, media_collect ) in self._favourite_searches.GetData():
existing_folders_to_names[ foldername ].append( name )
return existing_folders_to_names
def GetValue( self ):
favourite_searches_rows = self._favourite_searches.GetData()
return favourite_searches_rows