hydrus/hydrus/client/gui/search/ClientGUISearchPanels.py

358 lines
12 KiB
Python

import collections
import itertools
import typing
from qtpy import QtWidgets as QW
from hydrus.core import HydrusData
from hydrus.core import HydrusGlobals as HG
from hydrus.client import ClientConstants as CC
from hydrus.client import ClientSearch
from hydrus.client.gui import ClientGUIFunctions
from hydrus.client.gui import ClientGUIDialogsQuick
from hydrus.client.gui import ClientGUIResultsSortCollect
from hydrus.client.gui import ClientGUIScrolledPanels
from hydrus.client.gui import ClientGUITopLevelWindowsPanels
from hydrus.client.gui import QtPorting as QP
from hydrus.client.gui.lists import ClientGUIListConstants as CGLC
from hydrus.client.gui.lists import ClientGUIListCtrl
from hydrus.client.gui.widgets import ClientGUICommon
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 = ClientGUIResultsSortCollect.MediaSortControl( self )
self._media_collect = ClientGUIResultsSortCollect.MediaCollectControl( self, silent = True )
page_key = HydrusData.GenerateKey()
from hydrus.client.gui.search import ClientGUIACDropdown
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_BOTH_WAYS )
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 UserIsOKToOK( 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 )
self._favourite_searches = ClientGUIListCtrl.BetterListCtrl( self._favourite_searches_panel, CGLC.COLUMN_LIST_FAVOURITE_SEARCHES.ID, 20, 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()
#
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 ClientGUITopLevelWindowsPanels.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 ClientGUITopLevelWindowsPanels.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