def __init__( self, name, path = '', export_type = HC.EXPORT_FOLDER_TYPE_REGULAR, delete_from_client_after_export = False, file_search_context = None, run_regularly = True, period = 3600, phrase = None, last_checked = 0, paused = False, run_now = False, last_error = '' ): HydrusSerialisable.SerialisableBaseNamed.__init__( self, name ) if export_type == HC.EXPORT_FOLDER_TYPE_SYNCHRONISE: delete_from_client_after_export = False if file_search_context is None: default_local_file_service_key = HG.client_controller.services_manager.GetDefaultLocalFileServiceKey() location_search_context = ClientSearch.LocationSearchContext( current_service_keys = [ default_local_file_service_key ] ) file_search_context = ClientSearch.FileSearchContext( location_search_context = location_search_context ) if phrase is None: phrase = HG.client_controller.new_options.GetString( 'export_phrase' ) self._path = path self._export_type = export_type self._delete_from_client_after_export = delete_from_client_after_export self._file_search_context = file_search_context self._run_regularly = run_regularly self._period = period self._phrase = phrase self._last_checked = last_checked self._paused = paused and not run_now self._run_now = run_now self._last_error = last_error
def __init__(self, parent: QW.QWidget, predicate: ClientSearch.Predicate): QW.QWidget.__init__(self, parent) from hydrus.client.gui.search import ClientGUIACDropdown if predicate.GetType() != ClientSearch.PREDICATE_TYPE_OR_CONTAINER: raise Exception( 'Launched an ORPredicateControl without an OR Pred!') predicates = predicate.GetValue() page_key = HydrusData.GenerateKey() location_search_context = ClientSearch.LocationSearchContext( current_service_keys=[CC.LOCAL_FILE_SERVICE_KEY]) file_search_context = ClientSearch.FileSearchContext( location_search_context=location_search_context, predicates=predicates) self._search_control = ClientGUIACDropdown.AutoCompleteDropdownTagsRead( self, page_key, file_search_context, hide_favourites_edit_actions=True) vbox = QP.VBoxLayout() QP.AddToLayout(vbox, self._search_control, CC.FLAGS_EXPAND_BOTH_WAYS) self.setLayout(vbox)
def ExpandPredicate( self, service_key: bytes, predicate: ClientSearch.Predicate, service_strict: bool = False ): if not service_strict and self._controller.new_options.GetBoolean( 'apply_all_siblings_to_all_services' ): service_key = CC.COMBINED_TAG_SERVICE_KEY ideal_sibling_predicate = predicate other_sibling_predicates = [] if predicate.GetType() == ClientSearch.PREDICATE_TYPE_TAG: tag = predicate.GetValue() ideal_sibling = self.CollapseTag( service_key, tag, service_strict = service_strict ) ideal_sibling_predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_TAG, ideal_sibling, predicate.IsInclusive() ) other_siblings = set( self.GetAllSiblings( service_key, tag, service_strict = service_strict ) ) other_siblings.discard( tag ) other_siblings.discard( ideal_sibling ) other_sibling_predicates = [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_TAG, sibling, predicate.IsInclusive() ) for sibling in other_siblings ] return ( ideal_sibling_predicate, other_sibling_predicates )
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 default_local_file_service_key = HG.client_controller.services_manager.GetDefaultLocalFileServiceKey() location_search_context = ClientSearch.LocationSearchContext( current_service_keys = [ default_local_file_service_key ] ) file_search_context = ClientSearch.FileSearchContext( location_search_context = location_search_context ) 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 ClientGUITopLevelWindowsPanels.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 test_basics(self): def test(obj, dupe_obj): self.assertEqual(len(list(obj.items())), len(list(dupe_obj.items()))) for (key, value) in list(obj.items()): self.assertEqual(value, dupe_obj[key]) # d = HydrusSerialisable.SerialisableDictionary() d[1] = 2 d[3] = 'test1' d['test2'] = 4 d['test3'] = 5 d[6] = HydrusSerialisable.SerialisableDictionary( {i: 'test' + str(i) for i in range(20)}) d[ClientSearch.Predicate(ClientSearch.PREDICATE_TYPE_TAG, 'test pred 1')] = 56 d[ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_TAG, 'test pred 2')] = HydrusSerialisable.SerialisableList([ ClientSearch.Predicate(ClientSearch.PREDICATE_TYPE_TAG, 'test' + str(i)) for i in range(10) ]) self.assertEqual(len(list(d.keys())), 7) for (key, value) in list(d.items()): self.assertEqual(d[key], value) self._dump_and_load_and_test(d, test) # db = HydrusSerialisable.SerialisableBytesDictionary() db[HydrusData.GenerateKey()] = HydrusData.GenerateKey() db[HydrusData.GenerateKey()] = [ HydrusData.GenerateKey() for i in range(10) ] db[1] = HydrusData.GenerateKey() db[2] = [HydrusData.GenerateKey() for i in range(10)] self.assertEqual(len(list(db.keys())), 4) for (key, value) in list(db.items()): self.assertEqual(db[key], value) self._dump_and_load_and_test(db, test)
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' default_local_file_service_key = HG.client_controller.services_manager.GetDefaultLocalFileServiceKey( ) location_search_context = ClientSearch.LocationSearchContext( current_service_keys=[default_local_file_service_key]) file_search_context = ClientSearch.FileSearchContext( location_search_context=location_search_context) 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 ExpandPredicates(self, service_key, predicates, service_strict=False): if not service_strict and self._controller.new_options.GetBoolean( 'apply_all_parents_to_all_services'): service_key = CC.COMBINED_TAG_SERVICE_KEY results = [] with self._lock: for predicate in predicates: results.append(predicate) if predicate.GetType() == ClientSearch.PREDICATE_TYPE_TAG: tag = predicate.GetValue() parents = self._service_keys_to_children_to_parents[ service_key][tag] for parent in parents: parent_predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_PARENT, parent) results.append(parent_predicate) return results
def __init__( self, name, path = '', export_type = HC.EXPORT_FOLDER_TYPE_REGULAR, delete_from_client_after_export = False, file_search_context = None, run_regularly = True, period = 3600, phrase = None, last_checked = 0, paused = False, run_now = False ): HydrusSerialisable.SerialisableBaseNamed.__init__( self, name ) if export_type == HC.EXPORT_FOLDER_TYPE_SYNCHRONISE: delete_from_client_after_export = False if file_search_context is None: file_search_context = ClientSearch.FileSearchContext( file_service_key = CC.LOCAL_FILE_SERVICE_KEY ) if phrase is None: phrase = HG.client_controller.new_options.GetString( 'export_phrase' ) self._path = path self._export_type = export_type self._delete_from_client_after_export = delete_from_client_after_export self._file_search_context = file_search_context self._run_regularly = run_regularly self._period = period self._phrase = phrase self._last_checked = last_checked self._paused = paused and not run_now self._run_now = run_now
def GetSearchPredicates(self) -> typing.List[ClientSearch.Predicate]: # with counts? or just merge this into texttag??? return [ ClientSearch.Predicate(ClientSearch.PREDICATE_TYPE_TAG, self._tag) ]
def filetype_pred_generator( v ): # v is a list of non-hydrus-standard filetype strings mimes = ( 1, ) return ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_MIME, mimes )
def GetPredicates( self ): rating = None if self._rated_checkbox.isChecked(): operator = '=' rating = 'rated' elif self._not_rated_checkbox.isChecked(): operator = '=' rating = 'not rated' elif self._rating_control.GetRatingState() != ClientRatings.NULL: operator = self._operator.GetStringSelection() rating = self._rating_control.GetRating() if rating is None: return [] else: predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_RATING, ( operator, rating, self._service_key ) ) return [ predicate ]
def FilterAndConvertLabelPredicates( predicates: typing.Collection[ClientSearch.Predicate] ) -> typing.List[ClientSearch.Predicate]: good_predicates = [] for predicate in predicates: predicate = predicate.GetCountlessCopy() predicate_type = predicate.GetType() if predicate_type in (ClientSearch.PREDICATE_TYPE_LABEL, ClientSearch.PREDICATE_TYPE_PARENT): continue elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_UNTAGGED: predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_TAGS, (None, '=', 0)) good_predicates.append(predicate) return good_predicates
def GetPredicates( self ): rating = None if self._rated_checkbox.isChecked(): rating = 'rated' elif self._not_rated_checkbox.isChecked(): rating = 'not rated' else: rating_state = self._rating_control.GetRatingState() if rating_state == ClientRatings.LIKE: rating = 1 elif rating_state == ClientRatings.DISLIKE: rating = 0 if rating is None: return [] else: predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_RATING, ( '=', rating, self._service_key ) ) return [ predicate ]
def ExpandPredicates(self, service_key, predicates, service_strict=False): results = [] with self._lock: for predicate in predicates: results.append(predicate) if predicate.GetType() == ClientSearch.PREDICATE_TYPE_TAG: tag = predicate.GetValue() parents = self._service_keys_to_children_to_parents[ service_key][tag] for parent in parents: parent_predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_PARENT, parent) results.append(parent_predicate) return results
def file_service_pred_generator(o, v, u): o_dict = { 'is not currently in': (False, HC.CONTENT_STATUS_CURRENT), 'is currently in': (True, HC.CONTENT_STATUS_CURRENT), 'is not pending to': (False, HC.CONTENT_STATUS_PENDING), 'is pending to': (True, HC.CONTENT_STATUS_PENDING) } (is_in, status) = o_dict[o] try: service_name = v service_key = HG.client_controller.services_manager.GetServiceKeyFromName( HC.FILE_SERVICES, service_name) except: raise HydrusExceptions.BadRequestException( 'Could not find the service "{}"!'.format(service_name)) return ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_SERVICE, (is_in, status, service_key))
def RegenerateSearchableSubtagMap(self, file_service_id, tag_service_id, status_hook=None): subtags_fts4_table_name = self.GetSubtagsFTS4TableName( file_service_id, tag_service_id) subtags_searchable_map_table_name = self.GetSubtagsSearchableMapTableName( file_service_id, tag_service_id) self._Execute( 'DELETE FROM {};'.format(subtags_searchable_map_table_name)) query = 'SELECT docid FROM {};'.format(subtags_fts4_table_name) BLOCK_SIZE = 10000 for (group_of_subtag_ids, num_done, num_to_do) in HydrusDB.ReadLargeIdQueryInSeparateChunks( self._c, query, BLOCK_SIZE): for subtag_id in group_of_subtag_ids: result = self._Execute( 'SELECT subtag FROM subtags WHERE subtag_id = ?;', (subtag_id, )).fetchone() if result is None: continue (subtag, ) = result searchable_subtag = ClientSearch.ConvertSubtagToSearchable( subtag) if searchable_subtag != subtag: searchable_subtag_id = self.modules_tags.GetSubtagId( searchable_subtag) self._Execute( 'INSERT OR IGNORE INTO {} ( subtag_id, searchable_subtag_id ) VALUES ( ?, ? );' .format(subtags_searchable_map_table_name), (subtag_id, searchable_subtag_id)) message = HydrusData.ConvertValueRangeToPrettyString( num_done, num_to_do) HG.client_controller.frame_splash_status.SetSubtext(message) if status_hook is not None: status_hook(message)
def CollapsePredicates( self, service_key, predicates, service_strict = False ): if not service_strict and self._controller.new_options.GetBoolean( 'apply_all_siblings_to_all_services' ): service_key = CC.COMBINED_TAG_SERVICE_KEY with self._lock: siblings = self._service_keys_to_siblings[ service_key ] results = [ predicate for predicate in predicates if predicate.GetType() != ClientSearch.PREDICATE_TYPE_TAG ] tag_predicates = [ predicate for predicate in predicates if predicate.GetType() == ClientSearch.PREDICATE_TYPE_TAG ] tags_to_predicates = {predicate.GetValue() : predicate for predicate in predicates if predicate.GetType() == ClientSearch.PREDICATE_TYPE_TAG} tags = list( tags_to_predicates.keys() ) tags_to_include_in_results = set() for tag in tags: if tag in siblings: old_tag = tag old_predicate = tags_to_predicates[ old_tag ] new_tag = siblings[ old_tag ] if new_tag not in tags_to_predicates: ( old_pred_type, old_value, old_inclusive ) = old_predicate.GetInfo() new_predicate = ClientSearch.Predicate( old_pred_type, new_tag, old_inclusive ) tags_to_predicates[ new_tag ] = new_predicate tags_to_include_in_results.add( new_tag ) new_predicate = tags_to_predicates[ new_tag ] new_predicate.AddCounts( old_predicate ) else: tags_to_include_in_results.add( tag ) results.extend( [ tags_to_predicates[ tag ] for tag in tags_to_include_in_results ] ) return results
def num_file_relationships_pred_generator( o, v, u ): u_dict = { 'not related/false positive' : HC.DUPLICATE_FALSE_POSITIVE, 'duplicates' : HC.DUPLICATE_MEMBER, 'alternates' : HC.DUPLICATE_ALTERNATE, 'potential duplicates' : HC.DUPLICATE_POTENTIAL } dupe_type = u_dict[ u ] return ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_RELATIONSHIPS_COUNT, ( o, v, dupe_type ) )
def date_pred_generator(pred_type, o, v): #Either a tuple of 4 non-negative integers: (years, months, days, hours) where the latter is < 24 OR #a datetime.date object. For the latter, only the YYYY-MM-DD format is accepted. date_type = 'delta' if isinstance(v, datetime.date): date_type = 'date' v = (v.year, v.month, v.day) return ClientSearch.Predicate(pred_type, (o, date_type, tuple(v)))
def ExpandPredicate( self, service_key: bytes, predicate: ClientSearch.Predicate ): ideal_sibling_predicate = predicate other_sibling_predicates = [] if predicate.GetType() == ClientSearch.PREDICATE_TYPE_TAG: tag = predicate.GetValue() ideal_sibling = self.GetSibling( service_key, tag ) ideal_sibling_predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_TAG, ideal_sibling, predicate.IsInclusive() ) other_siblings = set( self.GetAllSiblings( service_key, tag ) ) other_siblings.discard( tag ) other_siblings.discard( ideal_sibling ) other_sibling_predicates = [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_TAG, sibling, predicate.IsInclusive() ) for sibling in other_siblings ] return ( ideal_sibling_predicate, other_sibling_predicates )
def url_class_pred_generator( include, url_class_name ): description = ( 'has {} url' if include else 'does not have {} url' ).format( url_class_name ) try: url_class = HG.client_controller.network_engine.domain_manager.GetURLClassFromName( url_class_name ) except HydrusExceptions.DataMissing as e: raise ValueError( str( e ) ) return ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_KNOWN_URLS, ( include, 'url_class', url_class, description ) )
def GetPredicates(self): or_sub_predicates = self._search_control.GetPredicates() if len(or_sub_predicates) == 0: return [] elif len(or_sub_predicates) == 1: return or_sub_predicates or_predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_OR_CONTAINER, or_sub_predicates) return [or_predicate]
def file_service_pred_generator( o, v, u ): if o.startswith( 'is not' ): is_in = False else: is_in = True o_dict = { 'currently in' : HC.CONTENT_STATUS_CURRENT, 'deleted from' : HC.CONTENT_STATUS_DELETED, 'pending to' : HC.CONTENT_STATUS_PENDING, 'petitioned from' : HC.CONTENT_STATUS_PETITIONED } status = None for ( phrase, possible_status ) in o_dict.items(): if phrase in o: status = possible_status break if status is None: raise HydrusExceptions.BadRequestException( 'Did not understand the file service status!' ) try: service_name = v service_key = HG.client_controller.services_manager.GetServiceKeyFromName( HC.FILE_SERVICES, service_name ) except: raise HydrusExceptions.BadRequestException( 'Could not find the service "{}"!'.format( service_name ) ) return ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_SERVICE, ( is_in, status, service_key ) )
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 do_it( service_key, hash, search_tags, max_results, max_time_to_take ): def qt_code( predicates ): if not self or not QP.isValid( self ): return self._last_fetched_predicates = predicates self._UpdateTagDisplay() self._have_fetched = True predicates = HG.client_controller.Read( 'related_tags', service_key, hash, search_tags, max_results, max_time_to_take ) predicates = ClientSearch.SortPredicates( predicates ) QP.CallAfter( qt_code, predicates )
def __init__(self, parent: QW.QWidget, predicate: ClientSearch.Predicate): QW.QWidget.__init__(self, parent) from hydrus.client.gui.search import ClientGUIACDropdown if predicate.GetType() != ClientSearch.PREDICATE_TYPE_OR_CONTAINER: raise Exception( 'Launched an ORPredicateControl without an OR Pred!') predicates = predicate.GetValue() page_key = HydrusData.GenerateKey() location_context = HG.client_controller.new_options.GetDefaultLocalLocationContext( ) file_search_context = ClientSearch.FileSearchContext( location_context=location_context, predicates=predicates) self._search_control = ClientGUIACDropdown.AutoCompleteDropdownTagsRead( self, page_key, file_search_context, hide_favourites_edit_actions=True) self._search_control.setMinimumWidth( ClientGUIFunctions.ConvertTextToPixelWidth(self._search_control, 64)) vbox = QP.VBoxLayout() QP.AddToLayout(vbox, self._search_control, CC.FLAGS_EXPAND_BOTH_WAYS) self.setLayout(vbox) ClientGUIFunctions.SetFocusLater(self._search_control)
def GetSubtagIdsFromWildcardIntoTable(self, file_service_id: int, tag_service_id: int, subtag_wildcard, subtag_id_table_name, job_key=None): if tag_service_id == self.modules_services.combined_tag_service_id: search_tag_service_ids = self.modules_services.GetServiceIds( HC.REAL_TAG_SERVICES) else: search_tag_service_ids = (tag_service_id, ) for search_tag_service_id in search_tag_service_ids: if '*' in subtag_wildcard: subtags_fts4_table_name = self.GetSubtagsFTS4TableName( file_service_id, search_tag_service_id) wildcard_has_fts4_searchable_characters = WildcardHasFTS4SearchableCharacters( subtag_wildcard) if subtag_wildcard == '*': # hellmode, but shouldn't be called normally cursor = self._Execute('SELECT docid FROM {};'.format( subtags_fts4_table_name)) elif ClientSearch.IsComplexWildcard( subtag_wildcard ) or not wildcard_has_fts4_searchable_characters: # FTS4 does not support complex wildcards, so instead we'll search our raw subtags # however, since we want to search 'searchable' text, we use the 'searchable subtags map' to cross between real and searchable like_param = ConvertWildcardToSQLiteLikeParameter( subtag_wildcard) if subtag_wildcard.startswith( '*' ) or not wildcard_has_fts4_searchable_characters: # this is a SCAN, but there we go # a potential optimisation here, in future, is to store fts4 of subtags reversed, then for '*amus', we can just search that reverse cache for 'suma*' # and this would only double the size of the fts4 cache, the largest cache in the whole db! a steal! # it also would not fix '*amu*', but with some cleverness could speed up '*amus ar*' query = 'SELECT docid FROM {} WHERE subtag LIKE ?;'.format( subtags_fts4_table_name) cursor = self._Execute(query, (like_param, )) else: # we have an optimisation here--rather than searching all subtags for bl*ah, let's search all the bl* subtags for bl*ah! prefix_fts4_wildcard = subtag_wildcard.split('*')[0] prefix_fts4_wildcard_param = '"{}*"'.format( prefix_fts4_wildcard) query = 'SELECT docid FROM {} WHERE subtag MATCH ? AND subtag LIKE ?;'.format( subtags_fts4_table_name) cursor = self._Execute( query, (prefix_fts4_wildcard_param, like_param)) else: # we want the " " wrapping our search text to keep whitespace words connected and in order # "samus ar*" should not match "around samus" # simple 'sam*' style subtag, so we can search fts4 no prob subtags_fts4_param = '"{}"'.format(subtag_wildcard) cursor = self._Execute( 'SELECT docid FROM {} WHERE subtag MATCH ?;'.format( subtags_fts4_table_name), (subtags_fts4_param, )) cancelled_hook = None if job_key is not None: cancelled_hook = job_key.IsCancelled loop_of_subtag_id_tuples = HydrusDB.ReadFromCancellableCursor( cursor, 1024, cancelled_hook=cancelled_hook) self._ExecuteMany( 'INSERT OR IGNORE INTO {} ( subtag_id ) VALUES ( ? );'. format(subtag_id_table_name), loop_of_subtag_id_tuples) else: # old notes from before we had searchable subtag map. I deleted that map once, albeit in an older and less efficient form. *don't delete it again, it has use* # # NOTE: doing a subtag = 'blah' lookup on subtags_fts4 tables is ultra slow, lmao! # attempts to match '/a/' to 'a' with clever FTS4 MATCHing (i.e. a MATCH on a*\b, then an '= a') proved not super successful # in testing, it was still a bit slow. my guess is it is still iterating through all the nodes for ^a*, the \b just makes it a bit more efficient sometimes # in tests '^a\b' was about twice as fast as 'a*', so the \b might not even be helping at all # so, I decided to move back to a lean and upgraded searchable subtag map, and here we are searchable_subtag = subtag_wildcard if self.modules_tags.SubtagExists(searchable_subtag): searchable_subtag_id = self.modules_tags.GetSubtagId( searchable_subtag) self._Execute( 'INSERT OR IGNORE INTO {} ( subtag_id ) VALUES ( ? );'. format(subtag_id_table_name), (searchable_subtag_id, )) subtags_searchable_map_table_name = self.GetSubtagsSearchableMapTableName( file_service_id, search_tag_service_id) self._Execute( 'INSERT OR IGNORE INTO {} ( subtag_id ) SELECT subtag_id FROM {} WHERE searchable_subtag_id = ?;' .format(subtag_id_table_name, subtags_searchable_map_table_name), (searchable_subtag_id, )) if job_key is not None and job_key.IsCancelled(): self._Execute('DELETE FROM {};'.format(subtag_id_table_name)) return
def GetSearchPredicates(self) -> typing.List[ClientSearch.Predicate]: return [ ClientSearch.Predicate(ClientSearch.PREDICATE_TYPE_TAG, self._tag) ]
def __init__(self, parent, predicate: ClientSearch.Predicate): ClientGUIScrolledPanels.EditPanel.__init__(self, parent) predicate_type = predicate.GetType() self._predicates = [] label = None editable_pred_panels = [] static_pred_buttons = [] recent_predicate_types = [predicate_type] if predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_AGE: static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_AGE, ('<', 'delta', (0, 0, 1, 0))), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_AGE, ('<', 'delta', (0, 0, 7, 0))), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_AGE, ('<', 'delta', (0, 1, 0, 0))), ))) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemAgeDelta, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemAgeDate, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_MODIFIED_TIME: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemModifiedDelta, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemModifiedDate, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_DIMENSIONS: recent_predicate_types = [ ClientSearch.PREDICATE_TYPE_SYSTEM_HEIGHT, ClientSearch.PREDICATE_TYPE_SYSTEM_WIDTH, ClientSearch.PREDICATE_TYPE_SYSTEM_RATIO, ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_PIXELS ] static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_RATIO, ('=', 16, 9)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_RATIO, ('=', 9, 16)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_RATIO, ('=', 4, 3)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_RATIO, ('=', 1, 1)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_WIDTH, ('=', 1920)), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_HEIGHT, ('=', 1080))), forced_label='1080p')) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_WIDTH, ('=', 1280)), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_HEIGHT, ('=', 720))), forced_label='720p')) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_WIDTH, ('=', 3840)), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_HEIGHT, ('=', 2160))), forced_label='4k')) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemHeight, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemWidth, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemRatio, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemNumPixels, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_DURATION: recent_predicate_types = [ ClientSearch.PREDICATE_TYPE_SYSTEM_DURATION, ClientSearch.PREDICATE_TYPE_SYSTEM_FRAMERATE, ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_FRAMES ] static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_DURATION, ('>', 0)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_DURATION, ('=', 0)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_FRAMERATE, ('=', 30)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_FRAMERATE, ('=', 60)), ))) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemDuration, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemFramerate, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemNumFrames, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_SERVICE: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemFileService, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_KNOWN_URLS: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsExactURL, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsDomain, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsRegex, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsURLClass, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_HAS_AUDIO: recent_predicate_types = [] static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_HAS_AUDIO, True), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_HAS_AUDIO, False), ))) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_HASH: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemHash, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_LIMIT: label = 'system:limit clips a large search result down to the given number of files. It is very useful for processing in smaller batches.' label += os.linesep * 2 label += 'For all the simpler sorts (filesize, duration, etc...), it will select the n largest/smallest in the result set appropriate for that sort. For complicated sorts like tags, it will sample randomly.' static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_LIMIT, 64), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_LIMIT, 256), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_LIMIT, 1024), ))) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemLimit, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_MIME: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemMime, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_TAGS: static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_TAGS, (None, '>', 0)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_TAGS, (None, '=', 0)), ))) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemNumTags, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NOTES: recent_predicate_types = [ ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_NOTES, ClientSearch.PREDICATE_TYPE_SYSTEM_HAS_NOTE_NAME ] static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_NOTES, ('>', 0)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_NOTES, ('=', 0)), ))) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemNumNotes, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemHasNoteName, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_WORDS: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemNumWords, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_RATING: services_manager = HG.client_controller.services_manager ratings_services = services_manager.GetServices( (HC.LOCAL_RATING_LIKE, HC.LOCAL_RATING_NUMERICAL)) if len(ratings_services) > 0: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesMultiple.PanelPredicateSystemRating, (predicate, ))) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_SIMILAR_TO: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemSimilarTo, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_SIZE: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemSize, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_TAG_AS_NUMBER: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemTagAsNumber, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_RELATIONSHIPS: static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch. PREDICATE_TYPE_SYSTEM_FILE_RELATIONSHIPS_KING, False), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch. PREDICATE_TYPE_SYSTEM_FILE_RELATIONSHIPS_KING, True), ))) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemDuplicateRelationships, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_VIEWING_STATS: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemFileViewingStatsViews, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemFileViewingStatsViewtime, predicate)) vbox = QP.VBoxLayout() if label is not None: st = ClientGUICommon.BetterStaticText(self, label=label) st.setWordWrap(True) QP.AddToLayout(vbox, st, CC.FLAGS_EXPAND_PERPENDICULAR) recent_predicates = [] if len(recent_predicate_types) > 0: recent_predicates = HG.client_controller.new_options.GetRecentPredicates( recent_predicate_types) if len(recent_predicates) > 0: recent_predicates_box = ClientGUICommon.StaticBox( self, 'recent') for recent_predicate in recent_predicates: button = ClientGUIPredicatesSingle.StaticSystemPredicateButton( recent_predicates_box, self, (recent_predicate, )) recent_predicates_box.Add(button, CC.FLAGS_EXPAND_PERPENDICULAR) QP.AddToLayout(vbox, recent_predicates_box, CC.FLAGS_EXPAND_PERPENDICULAR) for button in static_pred_buttons: QP.AddToLayout(vbox, button, CC.FLAGS_EXPAND_PERPENDICULAR) for panel in editable_pred_panels: QP.AddToLayout(vbox, panel, CC.FLAGS_EXPAND_PERPENDICULAR) if len(static_pred_buttons) > 0 and len(editable_pred_panels) == 0: HG.client_controller.CallAfterQtSafe( static_pred_buttons[0], static_pred_buttons[0].setFocus, QC.Qt.OtherFocusReason) self.widget().setLayout(vbox)
def __init__(self, parent, predicates: typing.Collection[ClientSearch.Predicate]): ClientGUIScrolledPanels.EditPanel.__init__(self, parent) predicates = list(predicates) predicates.sort(key=lambda p: p.ToString(with_count=False)) self._uneditable_predicates = [] self._invertible_pred_buttons = [] self._editable_pred_panels = [] rating_preds = [] # I hate this pred comparison stuff, but let's hang in there until we split this stuff up by type mate # then we can just have a dict type->panel_class lookup or whatever # also it would be nice to have proper rating editing here, think about it AGE_DELTA_PRED = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_AGE, ('>', 'delta', (2000, 1, 1, 1))) MODIFIED_DELTA_PRED = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_MODIFIED_TIME, ('>', 'delta', (2000, 1, 1, 1))) KNOWN_URL_EXACT = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_KNOWN_URLS, (True, 'exact_match', '', '')) KNOWN_URL_DOMAIN = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_KNOWN_URLS, (True, 'domain', '', '')) KNOWN_URL_REGEX = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_KNOWN_URLS, (True, 'regex', '', '')) FILE_VIEWS_PRED = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_VIEWING_STATS, ('views', ('media', ), '>', 0)) for predicate in predicates: predicate_type = predicate.GetType() if predicate_type == ClientSearch.PREDICATE_TYPE_OR_CONTAINER: self._editable_pred_panels.append( ClientGUIPredicatesOR.ORPredicateControl(self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_AGE: if predicate.IsUIEditable(AGE_DELTA_PRED): self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemAgeDelta( self, predicate)) else: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemAgeDate( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_MODIFIED_TIME: if predicate.IsUIEditable(MODIFIED_DELTA_PRED): self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemModifiedDelta(self, predicate)) else: self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemModifiedDate(self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_HEIGHT: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemHeight( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_WIDTH: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemWidth( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_RATIO: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemRatio( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_PIXELS: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemNumPixels( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_DURATION: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemDuration( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_FRAMERATE: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemFramerate( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_FRAMES: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemNumFrames( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_SERVICE: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemFileService( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_KNOWN_URLS: if predicate.IsUIEditable(KNOWN_URL_EXACT): self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsExactURL(self, predicate)) elif predicate.IsUIEditable(KNOWN_URL_DOMAIN): self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsDomain(self, predicate)) elif predicate.IsUIEditable(KNOWN_URL_REGEX): self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsRegex(self, predicate)) else: self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsURLClass(self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_HASH: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemHash( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_LIMIT: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemLimit( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_MIME: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemMime( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_TAGS: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemNumTags( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_NOTES: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemNumNotes( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_HAS_NOTE_NAME: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemHasNoteName( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_WORDS: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemNumWords( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_SIMILAR_TO: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemSimilarTo( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_SIZE: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemSize( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_TAG_AS_NUMBER: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemTagAsNumber( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_RELATIONSHIPS_COUNT: self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemDuplicateRelationships( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_VIEWING_STATS: if predicate.IsUIEditable(FILE_VIEWS_PRED): self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemFileViewingStatsViews( self, predicate)) else: self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemFileViewingStatsViewtime( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_RATING: rating_preds.append(predicate) elif predicate.IsInvertible(): self._invertible_pred_buttons.append( ClientGUIPredicatesSingle.InvertiblePredicateButton( self, predicate)) else: self._uneditable_predicates.append(predicate) if len(rating_preds) > 0: self._editable_pred_panels.append( ClientGUIPredicatesMultiple.PanelPredicateSystemRating( self, rating_preds)) vbox = QP.VBoxLayout() for button in self._invertible_pred_buttons: QP.AddToLayout(vbox, button, CC.FLAGS_EXPAND_PERPENDICULAR) for panel in self._editable_pred_panels: if isinstance(panel, ClientGUIPredicatesOR.ORPredicateControl): flags = CC.FLAGS_EXPAND_BOTH_WAYS else: flags = CC.FLAGS_EXPAND_PERPENDICULAR QP.AddToLayout(vbox, panel, flags) self.widget().setLayout(vbox)