PageRenderTime 103ms CodeModel.GetById 14ms app.highlight 83ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llinventoryfilter.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 976 lines | 769 code | 109 blank | 98 comment | 183 complexity | e4d064c44270c62835703de75364bbf2 MD5 | raw file
  1/** 
  2* @file llinventoryfilter.cpp
  3* @brief Support for filtering your inventory to only display a subset of the
  4* available items.
  5*
  6* $LicenseInfo:firstyear=2005&license=viewerlgpl$
  7* Second Life Viewer Source Code
  8* Copyright (C) 2010, Linden Research, Inc.
  9* 
 10* This library is free software; you can redistribute it and/or
 11* modify it under the terms of the GNU Lesser General Public
 12* License as published by the Free Software Foundation;
 13* version 2.1 of the License only.
 14* 
 15* This library is distributed in the hope that it will be useful,
 16* but WITHOUT ANY WARRANTY; without even the implied warranty of
 17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 18* Lesser General Public License for more details.
 19* 
 20* You should have received a copy of the GNU Lesser General Public
 21* License along with this library; if not, write to the Free Software
 22* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 23* 
 24* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 25* $/LicenseInfo$
 26*/
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "llinventoryfilter.h"
 30
 31// viewer includes
 32#include "llfoldervieweventlistener.h"
 33#include "llfolderviewitem.h"
 34#include "llinventorymodel.h"
 35#include "llinventorymodelbackgroundfetch.h"
 36#include "llviewercontrol.h"
 37#include "llfolderview.h"
 38#include "llinventorybridge.h"
 39#include "llviewerfoldertype.h"
 40
 41// linden library includes
 42#include "lltrans.h"
 43
 44LLInventoryFilter::FilterOps::FilterOps() :
 45	mFilterObjectTypes(0xffffffffffffffffULL),
 46	mFilterCategoryTypes(0xffffffffffffffffULL),
 47	mFilterWearableTypes(0xffffffffffffffffULL),
 48	mMinDate(time_min()),
 49	mMaxDate(time_max()),
 50	mHoursAgo(0),
 51	mShowFolderState(SHOW_NON_EMPTY_FOLDERS),
 52	mPermissions(PERM_NONE),
 53	mFilterTypes(FILTERTYPE_OBJECT),
 54	mFilterUUID(LLUUID::null),
 55	mFilterLinks(FILTERLINK_INCLUDE_LINKS)
 56{
 57}
 58
 59///----------------------------------------------------------------------------
 60/// Class LLInventoryFilter
 61///----------------------------------------------------------------------------
 62LLInventoryFilter::LLInventoryFilter(const std::string& name)
 63:	mName(name),
 64	mModified(FALSE),
 65	mNeedTextRebuild(TRUE),
 66	mEmptyLookupMessage("InventoryNoMatchingItems")
 67{
 68	mOrder = SO_FOLDERS_BY_NAME; // This gets overridden by a pref immediately
 69
 70	mSubStringMatchOffset = 0;
 71	mFilterSubString.clear();
 72	mFilterGeneration = 0;
 73	mMustPassGeneration = S32_MAX;
 74	mMinRequiredGeneration = 0;
 75	mFilterCount = 0;
 76	mNextFilterGeneration = mFilterGeneration + 1;
 77
 78	mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff");
 79	mFilterBehavior = FILTER_NONE;
 80
 81	// copy mFilterOps into mDefaultFilterOps
 82	markDefault();
 83}
 84
 85LLInventoryFilter::~LLInventoryFilter()
 86{
 87}
 88
 89BOOL LLInventoryFilter::check(const LLFolderViewItem* item) 
 90{
 91	// If it's a folder and we're showing all folders, return TRUE automatically.
 92	const BOOL is_folder = (dynamic_cast<const LLFolderViewFolder*>(item) != NULL);
 93	if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS))
 94	{
 95		return TRUE;
 96	}
 97
 98	mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos;
 99
100	const BOOL passed_filtertype = checkAgainstFilterType(item);
101	const BOOL passed_permissions = checkAgainstPermissions(item);
102	const BOOL passed_filterlink = checkAgainstFilterLinks(item);
103	const BOOL passed = (passed_filtertype &&
104						 passed_permissions &&
105						 passed_filterlink &&
106						 (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos));
107
108	return passed;
109}
110
111bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder)
112{
113	// we're showing all folders, overriding filter
114	if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)
115	{
116		return true;
117	}
118
119	const LLFolderViewEventListener* listener = folder->getListener();
120	const LLUUID folder_id = listener->getUUID();
121	
122	if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY)
123	{
124		// Can only filter categories for items in your inventory
125		// (e.g. versus in-world object contents).
126		const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id);
127		if (!cat)
128			return false;
129		LLFolderType::EType cat_type = cat->getPreferredType();
130		if (cat_type != LLFolderType::FT_NONE && (1LL << cat_type & mFilterOps.mFilterCategoryTypes) == U64(0))
131			return false;
132	}
133
134	return true;
135}
136
137BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const
138{
139	const LLFolderViewEventListener* listener = item->getListener();
140	if (!listener) return FALSE;
141
142	LLInventoryType::EType object_type = listener->getInventoryType();
143	const LLUUID object_id = listener->getUUID();
144	const LLInventoryObject *object = gInventory.getObject(object_id);
145
146	const U32 filterTypes = mFilterOps.mFilterTypes;
147
148	////////////////////////////////////////////////////////////////////////////////
149	// FILTERTYPE_OBJECT
150	// Pass if this item's type is of the correct filter type
151	if (filterTypes & FILTERTYPE_OBJECT)
152	{
153		// If it has no type, pass it, unless it's a link.
154		if (object_type == LLInventoryType::IT_NONE)
155		{
156			if (object && object->getIsLinkType())
157			{
158				return FALSE;
159			}
160		}
161		else if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0))
162		{
163			return FALSE;
164		}
165	}
166	
167	////////////////////////////////////////////////////////////////////////////////
168	// FILTERTYPE_UUID
169	// Pass if this item is the target UUID or if it links to the target UUID
170	if (filterTypes & FILTERTYPE_UUID)
171	{
172		if (!object) return FALSE;
173
174		if (object->getLinkedUUID() != mFilterOps.mFilterUUID)
175			return FALSE;
176	}
177
178	////////////////////////////////////////////////////////////////////////////////
179	// FILTERTYPE_DATE
180	// Pass if this item is within the date range.
181	if (filterTypes & FILTERTYPE_DATE)
182	{
183		const U16 HOURS_TO_SECONDS = 3600;
184		time_t earliest = time_corrected() - mFilterOps.mHoursAgo * HOURS_TO_SECONDS;
185		if (mFilterOps.mMinDate > time_min() && mFilterOps.mMinDate < earliest)
186		{
187			earliest = mFilterOps.mMinDate;
188		}
189		else if (!mFilterOps.mHoursAgo)
190		{
191			earliest = 0;
192		}
193		if (listener->getCreationDate() < earliest ||
194			listener->getCreationDate() > mFilterOps.mMaxDate)
195			return FALSE;
196	}
197
198	////////////////////////////////////////////////////////////////////////////////
199	// FILTERTYPE_WEARABLE
200	// Pass if this item is a wearable of the appropriate type
201	if (filterTypes & FILTERTYPE_WEARABLE)
202	{
203		LLWearableType::EType type = listener->getWearableType();
204		if ((0x1LL << type & mFilterOps.mFilterWearableTypes) == 0)
205		{
206			return FALSE;
207		}
208	}
209
210	////////////////////////////////////////////////////////////////////////////////
211	// FILTERTYPE_EMPTYFOLDERS
212	// Pass if this item is a folder and is not a system folder that should be hidden
213	if (filterTypes & FILTERTYPE_EMPTYFOLDERS)
214	{
215		if (object_type == LLInventoryType::IT_CATEGORY)
216		{
217			bool is_hidden_if_empty = LLViewerFolderType::lookupIsHiddenIfEmpty(listener->getPreferredType());
218			if (is_hidden_if_empty)
219			{
220				// Force the fetching of those folders so they are hidden iff they really are empty...
221				gInventory.fetchDescendentsOf(object_id);
222				return FALSE;
223			}
224		}
225	}
226	
227	return TRUE;
228}
229
230BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const
231{
232	const LLFolderViewEventListener* listener = item->getListener();
233	if (!listener) return FALSE;
234
235	PermissionMask perm = listener->getPermissionMask();
236	const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(item->getListener());
237	if (bridge && bridge->isLink())
238	{
239		const LLUUID& linked_uuid = gInventory.getLinkedItemID(bridge->getUUID());
240		const LLViewerInventoryItem *linked_item = gInventory.getItem(linked_uuid);
241		if (linked_item)
242			perm = linked_item->getPermissionMask();
243	}
244	return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions;
245}
246
247BOOL LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const
248{
249	const LLFolderViewEventListener* listener = item->getListener();
250	if (!listener) return TRUE;
251
252	const LLUUID object_id = listener->getUUID();
253	const LLInventoryObject *object = gInventory.getObject(object_id);
254	if (!object) return TRUE;
255
256	const BOOL is_link = object->getIsLinkType();
257	if (is_link && (mFilterOps.mFilterLinks == FILTERLINK_EXCLUDE_LINKS))
258		return FALSE;
259	if (!is_link && (mFilterOps.mFilterLinks == FILTERLINK_ONLY_LINKS))
260		return FALSE;
261	return TRUE;
262}
263
264const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const
265{
266	return mFilterSubString;
267}
268
269std::string::size_type LLInventoryFilter::getStringMatchOffset() const
270{
271	return mSubStringMatchOffset;
272}
273
274// has user modified default filter params?
275BOOL LLInventoryFilter::isNotDefault() const
276{
277	BOOL not_default = FALSE;
278
279	not_default |= (mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes);
280	not_default |= (mFilterOps.mFilterCategoryTypes != mDefaultFilterOps.mFilterCategoryTypes);
281	not_default |= (mFilterOps.mFilterWearableTypes != mDefaultFilterOps.mFilterWearableTypes);
282	not_default |= (mFilterOps.mFilterTypes != mDefaultFilterOps.mFilterTypes);
283	not_default |= (mFilterOps.mFilterLinks != mDefaultFilterOps.mFilterLinks);
284	not_default |= (mFilterSubString.size());
285	not_default |= (mFilterOps.mPermissions != mDefaultFilterOps.mPermissions);
286	not_default |= (mFilterOps.mMinDate != mDefaultFilterOps.mMinDate);
287	not_default |= (mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate);
288	not_default |= (mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo);
289
290	return not_default;
291}
292
293BOOL LLInventoryFilter::isActive() const
294{
295	return mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL
296		|| mFilterOps.mFilterCategoryTypes != 0xffffffffffffffffULL
297		|| mFilterOps.mFilterWearableTypes != 0xffffffffffffffffULL
298		|| mFilterOps.mFilterTypes != FILTERTYPE_OBJECT
299		|| mFilterOps.mFilterLinks != FILTERLINK_INCLUDE_LINKS
300		|| mFilterSubString.size() 
301		|| mFilterOps.mPermissions != PERM_NONE 
302		|| mFilterOps.mMinDate != time_min()
303		|| mFilterOps.mMaxDate != time_max()
304		|| mFilterOps.mHoursAgo != 0;
305}
306
307BOOL LLInventoryFilter::isModified() const
308{
309	return mModified;
310}
311
312BOOL LLInventoryFilter::isModifiedAndClear()
313{
314	BOOL ret = mModified;
315	mModified = FALSE;
316	return ret;
317}
318
319void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types)
320{
321	if (current_types != types)
322	{
323		// keep current items only if no type bits getting turned off
324		bool fewer_bits_set = (current_types & ~types) != 0;
325		bool more_bits_set = (~current_types & types) != 0;
326
327		current_types = types;
328		if (more_bits_set && fewer_bits_set)
329		{
330			// neither less or more restrive, both simultaneously
331			// so we need to filter from scratch
332			setModified(FILTER_RESTART);
333		}
334		else if (more_bits_set)
335		{
336			// target is only one of all requested types so more type bits == less restrictive
337			setModified(FILTER_LESS_RESTRICTIVE);
338		}
339		else if (fewer_bits_set)
340		{
341			setModified(FILTER_MORE_RESTRICTIVE);
342		}
343	}
344}
345
346void LLInventoryFilter::setFilterObjectTypes(U64 types)
347{
348	updateFilterTypes(types, mFilterOps.mFilterObjectTypes);
349	mFilterOps.mFilterTypes |= FILTERTYPE_OBJECT;
350}
351
352void LLInventoryFilter::setFilterCategoryTypes(U64 types)
353{
354	updateFilterTypes(types, mFilterOps.mFilterCategoryTypes);
355	mFilterOps.mFilterTypes |= FILTERTYPE_CATEGORY;
356}
357
358void LLInventoryFilter::setFilterWearableTypes(U64 types)
359{
360	updateFilterTypes(types, mFilterOps.mFilterWearableTypes);
361	mFilterOps.mFilterTypes |= FILTERTYPE_WEARABLE;
362}
363
364void LLInventoryFilter::setFilterEmptySystemFolders()
365{
366	mFilterOps.mFilterTypes |= FILTERTYPE_EMPTYFOLDERS;
367}
368
369void LLInventoryFilter::setFilterUUID(const LLUUID& object_id)
370{
371	if (mFilterOps.mFilterUUID == LLUUID::null)
372	{
373		setModified(FILTER_MORE_RESTRICTIVE);
374	}
375	else
376	{
377		setModified(FILTER_RESTART);
378	}
379	mFilterOps.mFilterUUID = object_id;
380	mFilterOps.mFilterTypes = FILTERTYPE_UUID;
381}
382
383void LLInventoryFilter::setFilterSubString(const std::string& string)
384{
385	std::string filter_sub_string_new = string;
386	mFilterSubStringOrig = string;
387	LLStringUtil::trimHead(filter_sub_string_new);
388	LLStringUtil::toUpper(filter_sub_string_new);
389
390	if (mFilterSubString != filter_sub_string_new)
391	{
392		// hitting BACKSPACE, for example
393		const BOOL less_restrictive = mFilterSubString.size() >= filter_sub_string_new.size()
394			&& !mFilterSubString.substr(0, filter_sub_string_new.size()).compare(filter_sub_string_new);
395
396		// appending new characters
397		const BOOL more_restrictive = mFilterSubString.size() < filter_sub_string_new.size()
398			&& !filter_sub_string_new.substr(0, mFilterSubString.size()).compare(mFilterSubString);
399
400		mFilterSubString = filter_sub_string_new;
401		if (less_restrictive)
402		{
403			setModified(FILTER_LESS_RESTRICTIVE);
404		}
405		else if (more_restrictive)
406		{
407			setModified(FILTER_MORE_RESTRICTIVE);
408		}
409		else
410		{
411			setModified(FILTER_RESTART);
412		}
413
414		// Cancel out UUID once the search string is modified
415		if (mFilterOps.mFilterTypes == FILTERTYPE_UUID)
416		{
417			mFilterOps.mFilterTypes &= ~FILTERTYPE_UUID;
418			mFilterOps.mFilterUUID == LLUUID::null;
419			setModified(FILTER_RESTART);
420		}
421
422		// Cancel out filter links once the search string is modified
423		{
424			mFilterOps.mFilterLinks = FILTERLINK_INCLUDE_LINKS;
425		}
426	}
427}
428
429void LLInventoryFilter::setFilterPermissions(PermissionMask perms)
430{
431	if (mFilterOps.mPermissions != perms)
432	{
433		// keep current items only if no perm bits getting turned off
434		BOOL fewer_bits_set = (mFilterOps.mPermissions & ~perms);
435		BOOL more_bits_set = (~mFilterOps.mPermissions & perms);
436		mFilterOps.mPermissions = perms;
437
438		if (more_bits_set && fewer_bits_set)
439		{
440			setModified(FILTER_RESTART);
441		}
442		else if (more_bits_set)
443		{
444			// target must have all requested permission bits, so more bits == more restrictive
445			setModified(FILTER_MORE_RESTRICTIVE);
446		}
447		else if (fewer_bits_set)
448		{
449			setModified(FILTER_LESS_RESTRICTIVE);
450		}
451	}
452}
453
454void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date)
455{
456	mFilterOps.mHoursAgo = 0;
457	if (mFilterOps.mMinDate != min_date)
458	{
459		mFilterOps.mMinDate = min_date;
460		setModified();
461	}
462	if (mFilterOps.mMaxDate != llmax(mFilterOps.mMinDate, max_date))
463	{
464		mFilterOps.mMaxDate = llmax(mFilterOps.mMinDate, max_date);
465		setModified();
466	}
467	mFilterOps.mFilterTypes |= FILTERTYPE_DATE;
468}
469
470void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)
471{
472	if (sl && !isSinceLogoff())
473	{
474		setDateRange(mLastLogoff, time_max());
475		setModified();
476	}
477	if (!sl && isSinceLogoff())
478	{
479		setDateRange(0, time_max());
480		setModified();
481	}
482	mFilterOps.mFilterTypes |= FILTERTYPE_DATE;
483}
484
485BOOL LLInventoryFilter::isSinceLogoff() const
486{
487	return (mFilterOps.mMinDate == (time_t)mLastLogoff) &&
488		(mFilterOps.mMaxDate == time_max()) &&
489		(mFilterOps.mFilterTypes & FILTERTYPE_DATE);
490}
491
492void LLInventoryFilter::clearModified()
493{
494	mModified = FALSE; 
495	mFilterBehavior = FILTER_NONE;
496}
497
498void LLInventoryFilter::setHoursAgo(U32 hours)
499{
500	if (mFilterOps.mHoursAgo != hours)
501	{
502		bool are_date_limits_valid = mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max();
503
504		bool is_increasing = hours > mFilterOps.mHoursAgo;
505		bool is_increasing_from_zero = is_increasing && !mFilterOps.mHoursAgo;
506
507		// *NOTE: need to cache last filter time, in case filter goes stale
508		BOOL less_restrictive = (are_date_limits_valid && ((is_increasing && mFilterOps.mHoursAgo)) || !hours);
509		BOOL more_restrictive = (are_date_limits_valid && (!is_increasing && hours) || is_increasing_from_zero);
510
511		mFilterOps.mHoursAgo = hours;
512		mFilterOps.mMinDate = time_min();
513		mFilterOps.mMaxDate = time_max();
514		if (less_restrictive)
515		{
516			setModified(FILTER_LESS_RESTRICTIVE);
517		}
518		else if (more_restrictive)
519		{
520			setModified(FILTER_MORE_RESTRICTIVE);
521		}
522		else
523		{
524			setModified(FILTER_RESTART);
525		}
526	}
527	mFilterOps.mFilterTypes |= FILTERTYPE_DATE;
528}
529
530void LLInventoryFilter::setFilterLinks(U64 filter_links)
531{
532	if (mFilterOps.mFilterLinks != filter_links)
533	{
534		if (mFilterOps.mFilterLinks == FILTERLINK_EXCLUDE_LINKS ||
535			mFilterOps.mFilterLinks == FILTERLINK_ONLY_LINKS)
536			setModified(FILTER_MORE_RESTRICTIVE);
537		else
538			setModified(FILTER_LESS_RESTRICTIVE);
539	}
540	mFilterOps.mFilterLinks = filter_links;
541}
542
543void LLInventoryFilter::setShowFolderState(EFolderShow state)
544{
545	if (mFilterOps.mShowFolderState != state)
546	{
547		mFilterOps.mShowFolderState = state;
548		if (state == SHOW_NON_EMPTY_FOLDERS)
549		{
550			// showing fewer folders than before
551			setModified(FILTER_MORE_RESTRICTIVE);
552		}
553		else if (state == SHOW_ALL_FOLDERS)
554		{
555			// showing same folders as before and then some
556			setModified(FILTER_LESS_RESTRICTIVE);
557		}
558		else
559		{
560			setModified();
561		}
562	}
563}
564
565void LLInventoryFilter::setSortOrder(U32 order)
566{
567	if (mOrder != order)
568	{
569		mOrder = order;
570		setModified();
571	}
572}
573
574void LLInventoryFilter::markDefault()
575{
576	mDefaultFilterOps = mFilterOps;
577}
578
579void LLInventoryFilter::resetDefault()
580{
581	mFilterOps = mDefaultFilterOps;
582	setModified();
583}
584
585void LLInventoryFilter::setModified(EFilterBehavior behavior)
586{
587	mModified = TRUE;
588	mNeedTextRebuild = TRUE;
589	mFilterGeneration = mNextFilterGeneration++;
590
591	if (mFilterBehavior == FILTER_NONE)
592	{
593		mFilterBehavior = behavior;
594	}
595	else if (mFilterBehavior != behavior)
596	{
597		// trying to do both less restrictive and more restrictive filter
598		// basically means restart from scratch
599		mFilterBehavior = FILTER_RESTART;
600	}
601
602	if (isNotDefault())
603	{
604		// if not keeping current filter results, update last valid as well
605		switch(mFilterBehavior)
606		{
607			case FILTER_RESTART:
608				mMustPassGeneration = mFilterGeneration;
609				mMinRequiredGeneration = mFilterGeneration;
610				break;
611			case FILTER_LESS_RESTRICTIVE:
612				mMustPassGeneration = mFilterGeneration;
613				break;
614			case FILTER_MORE_RESTRICTIVE:
615				mMinRequiredGeneration = mFilterGeneration;
616				// must have passed either current filter generation (meaningless, as it hasn't been run yet)
617				// or some older generation, so keep the value
618				mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration);
619				break;
620			default:
621				llerrs << "Bad filter behavior specified" << llendl;
622		}
623	}
624	else
625	{
626		// shortcut disabled filters to show everything immediately
627		mMinRequiredGeneration = 0;
628		mMustPassGeneration = S32_MAX;
629	}
630}
631
632BOOL LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const
633{
634	return mFilterOps.mFilterObjectTypes & (1LL << t);
635}
636
637const std::string& LLInventoryFilter::getFilterText()
638{
639	if (!mNeedTextRebuild)
640	{
641		return mFilterText;
642	}
643
644	mNeedTextRebuild = FALSE;
645	std::string filtered_types;
646	std::string not_filtered_types;
647	BOOL filtered_by_type = FALSE;
648	BOOL filtered_by_all_types = TRUE;
649	S32 num_filter_types = 0;
650	mFilterText.clear();
651
652	if (isFilterObjectTypesWith(LLInventoryType::IT_ANIMATION))
653	{
654		//filtered_types += " Animations,";
655		filtered_types += LLTrans::getString("Animations");
656		filtered_by_type = TRUE;
657		num_filter_types++;
658	}
659	else
660	{
661		//not_filtered_types += " Animations,";
662		not_filtered_types += LLTrans::getString("Animations");
663
664		filtered_by_all_types = FALSE;
665	}
666
667	if (isFilterObjectTypesWith(LLInventoryType::IT_CALLINGCARD))
668	{
669		//filtered_types += " Calling Cards,";
670		filtered_types += LLTrans::getString("Calling Cards");
671		filtered_by_type = TRUE;
672		num_filter_types++;
673	}
674	else
675	{
676		//not_filtered_types += " Calling Cards,";
677		not_filtered_types += LLTrans::getString("Calling Cards");
678		filtered_by_all_types = FALSE;
679	}
680
681	if (isFilterObjectTypesWith(LLInventoryType::IT_WEARABLE))
682	{
683		//filtered_types += " Clothing,";
684		filtered_types +=  LLTrans::getString("Clothing");
685		filtered_by_type = TRUE;
686		num_filter_types++;
687	}
688	else
689	{
690		//not_filtered_types += " Clothing,";
691		not_filtered_types +=  LLTrans::getString("Clothing");
692		filtered_by_all_types = FALSE;
693	}
694
695	if (isFilterObjectTypesWith(LLInventoryType::IT_GESTURE))
696	{
697		//filtered_types += " Gestures,";
698		filtered_types +=  LLTrans::getString("Gestures");
699		filtered_by_type = TRUE;
700		num_filter_types++;
701	}
702	else
703	{
704		//not_filtered_types += " Gestures,";
705		not_filtered_types +=  LLTrans::getString("Gestures");
706		filtered_by_all_types = FALSE;
707	}
708
709	if (isFilterObjectTypesWith(LLInventoryType::IT_LANDMARK))
710	{
711		//filtered_types += " Landmarks,";
712		filtered_types +=  LLTrans::getString("Landmarks");
713		filtered_by_type = TRUE;
714		num_filter_types++;
715	}
716	else
717	{
718		//not_filtered_types += " Landmarks,";
719		not_filtered_types +=  LLTrans::getString("Landmarks");
720		filtered_by_all_types = FALSE;
721	}
722
723	if (isFilterObjectTypesWith(LLInventoryType::IT_NOTECARD))
724	{
725		//filtered_types += " Notecards,";
726		filtered_types +=  LLTrans::getString("Notecards");
727		filtered_by_type = TRUE;
728		num_filter_types++;
729	}
730	else
731	{
732		//not_filtered_types += " Notecards,";
733		not_filtered_types +=  LLTrans::getString("Notecards");
734		filtered_by_all_types = FALSE;
735	}
736
737	if (isFilterObjectTypesWith(LLInventoryType::IT_OBJECT) && isFilterObjectTypesWith(LLInventoryType::IT_ATTACHMENT))
738	{
739		//filtered_types += " Objects,";
740		filtered_types +=  LLTrans::getString("Objects");
741		filtered_by_type = TRUE;
742		num_filter_types++;
743	}
744	else
745	{
746		//not_filtered_types += " Objects,";
747		not_filtered_types +=  LLTrans::getString("Objects");
748		filtered_by_all_types = FALSE;
749	}
750
751	if (isFilterObjectTypesWith(LLInventoryType::IT_LSL))
752	{
753		//filtered_types += " Scripts,";
754		filtered_types +=  LLTrans::getString("Scripts");
755		filtered_by_type = TRUE;
756		num_filter_types++;
757	}
758	else
759	{
760		//not_filtered_types += " Scripts,";
761		not_filtered_types +=  LLTrans::getString("Scripts");
762		filtered_by_all_types = FALSE;
763	}
764
765	if (isFilterObjectTypesWith(LLInventoryType::IT_SOUND))
766	{
767		//filtered_types += " Sounds,";
768		filtered_types +=  LLTrans::getString("Sounds");
769		filtered_by_type = TRUE;
770		num_filter_types++;
771	}
772	else
773	{
774		//not_filtered_types += " Sounds,";
775		not_filtered_types +=  LLTrans::getString("Sounds");
776		filtered_by_all_types = FALSE;
777	}
778
779	if (isFilterObjectTypesWith(LLInventoryType::IT_TEXTURE))
780	{
781		//filtered_types += " Textures,";
782		filtered_types +=  LLTrans::getString("Textures");
783		filtered_by_type = TRUE;
784		num_filter_types++;
785	}
786	else
787	{
788		//not_filtered_types += " Textures,";
789		not_filtered_types +=  LLTrans::getString("Textures");
790		filtered_by_all_types = FALSE;
791	}
792
793	if (isFilterObjectTypesWith(LLInventoryType::IT_SNAPSHOT))
794	{
795		//filtered_types += " Snapshots,";
796		filtered_types +=  LLTrans::getString("Snapshots");
797		filtered_by_type = TRUE;
798		num_filter_types++;
799	}
800	else
801	{
802		//not_filtered_types += " Snapshots,";
803		not_filtered_types +=  LLTrans::getString("Snapshots");
804		filtered_by_all_types = FALSE;
805	}
806
807	if (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive()
808		&& filtered_by_type
809		&& !filtered_by_all_types)
810	{
811		mFilterText += " - ";
812		if (num_filter_types < 5)
813		{
814			mFilterText += filtered_types;
815		}
816		else
817		{
818			//mFilterText += "No ";
819			mFilterText += LLTrans::getString("No Filters");
820			mFilterText += not_filtered_types;
821		}
822		// remove the ',' at the end
823		mFilterText.erase(mFilterText.size() - 1, 1);
824	}
825
826	if (isSinceLogoff())
827	{
828		//mFilterText += " - Since Logoff";
829		mFilterText += LLTrans::getString("Since Logoff");
830	}
831	return mFilterText;
832}
833
834void LLInventoryFilter::toLLSD(LLSD& data) const
835{
836	data["filter_types"] = (LLSD::Integer)getFilterObjectTypes();
837	data["min_date"] = (LLSD::Integer)getMinDate();
838	data["max_date"] = (LLSD::Integer)getMaxDate();
839	data["hours_ago"] = (LLSD::Integer)getHoursAgo();
840	data["show_folder_state"] = (LLSD::Integer)getShowFolderState();
841	data["permissions"] = (LLSD::Integer)getFilterPermissions();
842	data["substring"] = (LLSD::String)getFilterSubString();
843	data["sort_order"] = (LLSD::Integer)getSortOrder();
844	data["since_logoff"] = (LLSD::Boolean)isSinceLogoff();
845}
846
847void LLInventoryFilter::fromLLSD(LLSD& data)
848{
849	if(data.has("filter_types"))
850	{
851		setFilterObjectTypes((U32)data["filter_types"].asInteger());
852	}
853
854	if(data.has("min_date") && data.has("max_date"))
855	{
856		setDateRange(data["min_date"].asInteger(), data["max_date"].asInteger());
857	}
858
859	if(data.has("hours_ago"))
860	{
861		setHoursAgo((U32)data["hours_ago"].asInteger());
862	}
863
864	if(data.has("show_folder_state"))
865	{
866		setShowFolderState((EFolderShow)data["show_folder_state"].asInteger());
867	}
868
869	if(data.has("permissions"))
870	{
871		setFilterPermissions((PermissionMask)data["permissions"].asInteger());
872	}
873
874	if(data.has("substring"))
875	{
876		setFilterSubString(std::string(data["substring"].asString()));
877	}
878
879	if(data.has("sort_order"))
880	{
881		setSortOrder((U32)data["sort_order"].asInteger());
882	}
883
884	if(data.has("since_logoff"))
885	{
886		setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean());
887	}
888}
889
890U64 LLInventoryFilter::getFilterObjectTypes() const
891{
892	return mFilterOps.mFilterObjectTypes;
893}
894
895U64 LLInventoryFilter::getFilterCategoryTypes() const
896{
897	return mFilterOps.mFilterCategoryTypes;
898}
899
900BOOL LLInventoryFilter::hasFilterString() const
901{
902	return mFilterSubString.size() > 0;
903}
904
905PermissionMask LLInventoryFilter::getFilterPermissions() const
906{
907	return mFilterOps.mPermissions;
908}
909
910time_t LLInventoryFilter::getMinDate() const
911{
912	return mFilterOps.mMinDate;
913}
914
915time_t LLInventoryFilter::getMaxDate() const 
916{ 
917	return mFilterOps.mMaxDate; 
918}
919U32 LLInventoryFilter::getHoursAgo() const 
920{ 
921	return mFilterOps.mHoursAgo; 
922}
923U64 LLInventoryFilter::getFilterLinks() const
924{
925	return mFilterOps.mFilterLinks;
926}
927LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const
928{ 
929	return mFilterOps.mShowFolderState; 
930}
931U32 LLInventoryFilter::getSortOrder() const 
932{ 
933	return mOrder; 
934}
935const std::string& LLInventoryFilter::getName() const 
936{ 
937	return mName; 
938}
939
940void LLInventoryFilter::setFilterCount(S32 count) 
941{ 
942	mFilterCount = count; 
943}
944S32 LLInventoryFilter::getFilterCount() const
945{
946	return mFilterCount;
947}
948
949void LLInventoryFilter::decrementFilterCount() 
950{ 
951	mFilterCount--; 
952}
953
954S32 LLInventoryFilter::getCurrentGeneration() const 
955{ 
956	return mFilterGeneration; 
957}
958S32 LLInventoryFilter::getMinRequiredGeneration() const 
959{ 
960	return mMinRequiredGeneration; 
961}
962S32 LLInventoryFilter::getMustPassGeneration() const 
963{ 
964	return mMustPassGeneration; 
965}
966
967void LLInventoryFilter::setEmptyLookupMessage(const std::string& message)
968{
969	mEmptyLookupMessage = message;
970}
971
972const std::string& LLInventoryFilter::getEmptyLookupMessage() const
973{
974	return mEmptyLookupMessage;
975
976}