LLInventoryFilter migrated into llinventoryfilter.cpp/h

This commit is contained in:
Shyotl
2012-01-22 21:46:10 -06:00
parent c5024ff04d
commit 7d4c2aa54f
5 changed files with 892 additions and 689 deletions

View File

@@ -291,6 +291,7 @@ set(viewer_SOURCE_FILES
llinventorybackup.cpp
llinventorybridge.cpp
llinventoryclipboard.cpp
llinventoryfilter.cpp
llinventoryfunctions.cpp
llinventoryicon.cpp
llinventorymodel.cpp
@@ -766,6 +767,7 @@ set(viewer_HEADER_FILES
llinventorybackup.h
llinventorybridge.h
llinventoryclipboard.h
llinventoryfilter.h
llinventoryfunctions.h
llinventoryicon.h
llinventorymodel.h

View File

@@ -4630,581 +4630,3 @@ void LLFolderViewEventListener::arrangeAndSet(LLFolderViewItem* focus,
}
///----------------------------------------------------------------------------
/// Class LLInventoryFilter
///----------------------------------------------------------------------------
LLInventoryFilter::LLInventoryFilter(const std::string& name) :
mName(name),
mModified(FALSE),
mNeedTextRebuild(TRUE)
{
mFilterOps.mFilterTypes = 0xffffffff;
mFilterOps.mMinDate = time_min();
mFilterOps.mMaxDate = time_max();
mFilterOps.mHoursAgo = 0;
mFilterOps.mShowFolderState = SHOW_NON_EMPTY_FOLDERS;
mFilterOps.mPermissions = PERM_NONE;
mOrder = SO_FOLDERS_BY_NAME; // This gets overridden by a pref immediately
mSubStringMatchOffset = 0;
mFilterSubString.clear();
mFilterWorn = false;
mFilterGeneration = 0;
mMustPassGeneration = S32_MAX;
mMinRequiredGeneration = 0;
mFilterCount = 0;
mNextFilterGeneration = mFilterGeneration + 1;
mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff");
mFilterBehavior = FILTER_NONE;
// copy mFilterOps into mDefaultFilterOps
markDefault();
}
LLInventoryFilter::~LLInventoryFilter()
{
}
BOOL LLInventoryFilter::check(LLFolderViewItem* item)
{
LLFolderViewEventListener* listener = item->getListener();
const LLUUID& item_id = listener->getUUID();
const LLInventoryObject *obj = gInventory.getObject(item_id);
if (isActive() && obj && obj->getIsLinkType())
{
// When filtering is active, omit links.
return FALSE;
}
time_t earliest;
earliest = time_corrected() - mFilterOps.mHoursAgo * 3600;
if (mFilterOps.mMinDate > time_min() && mFilterOps.mMinDate < earliest)
{
earliest = mFilterOps.mMinDate;
}
else if (!mFilterOps.mHoursAgo)
{
earliest = 0;
}
mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos;
BOOL passed = (0x1 << listener->getInventoryType() & mFilterOps.mFilterTypes || listener->getInventoryType() == LLInventoryType::IT_NONE)
&& (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)
&& (mFilterWorn == false || gAgentWearables.isWearingItem(item_id) ||
(gAgentAvatarp && gAgentAvatarp->isWearingAttachment(item_id)))
&& ((listener->getPermissionMask() & mFilterOps.mPermissions) == mFilterOps.mPermissions)
&& (listener->getCreationDate() >= earliest && listener->getCreationDate() <= mFilterOps.mMaxDate);
return passed;
}
const std::string LLInventoryFilter::getFilterSubString(BOOL trim)
{
return mFilterSubString;
}
std::string::size_type LLInventoryFilter::getStringMatchOffset() const
{
return mSubStringMatchOffset;
}
// has user modified default filter params?
BOOL LLInventoryFilter::isNotDefault()
{
return mFilterOps.mFilterTypes != mDefaultFilterOps.mFilterTypes
|| mFilterSubString.size()
|| mFilterWorn
|| mFilterOps.mPermissions != mDefaultFilterOps.mPermissions
|| mFilterOps.mMinDate != mDefaultFilterOps.mMinDate
|| mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate
|| mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo;
}
BOOL LLInventoryFilter::isActive()
{
return mFilterOps.mFilterTypes != 0xffffffff
|| mFilterSubString.size()
|| mFilterWorn
|| mFilterOps.mPermissions != PERM_NONE
|| mFilterOps.mMinDate != time_min()
|| mFilterOps.mMaxDate != time_max()
|| mFilterOps.mHoursAgo != 0;
}
BOOL LLInventoryFilter::isModified()
{
return mModified;
}
BOOL LLInventoryFilter::isModifiedAndClear()
{
BOOL ret = mModified;
mModified = FALSE;
return ret;
}
void LLInventoryFilter::setFilterTypes(U32 types)
{
if (mFilterOps.mFilterTypes != types)
{
// keep current items only if no type bits getting turned off
BOOL fewer_bits_set = (mFilterOps.mFilterTypes & ~types);
BOOL more_bits_set = (~mFilterOps.mFilterTypes & types);
mFilterOps.mFilterTypes = types;
if (more_bits_set && fewer_bits_set)
{
// neither less or more restrive, both simultaneously
// so we need to filter from scratch
setModified(FILTER_RESTART);
}
else if (more_bits_set)
{
// target is only one of all requested types so more type bits == less restrictive
setModified(FILTER_LESS_RESTRICTIVE);
}
else if (fewer_bits_set)
{
setModified(FILTER_MORE_RESTRICTIVE);
}
}
}
void LLInventoryFilter::setFilterSubString(const std::string& string)
{
if (mFilterSubString != string)
{
// hitting BACKSPACE, for example
BOOL less_restrictive = mFilterSubString.size() >= string.size() && !mFilterSubString.substr(0, string.size()).compare(string);
// appending new characters
BOOL more_restrictive = mFilterSubString.size() < string.size() && !string.substr(0, mFilterSubString.size()).compare(mFilterSubString);
mFilterSubString = string;
LLStringUtil::toUpper(mFilterSubString);
LLStringUtil::trimHead(mFilterSubString);
if (less_restrictive)
{
setModified(FILTER_LESS_RESTRICTIVE);
}
else if (more_restrictive)
{
setModified(FILTER_MORE_RESTRICTIVE);
}
else
{
setModified(FILTER_RESTART);
}
}
}
void LLInventoryFilter::setFilterPermissions(PermissionMask perms)
{
if (mFilterOps.mPermissions != perms)
{
// keep current items only if no perm bits getting turned off
BOOL fewer_bits_set = (mFilterOps.mPermissions & ~perms);
BOOL more_bits_set = (~mFilterOps.mPermissions & perms);
mFilterOps.mPermissions = perms;
if (more_bits_set && fewer_bits_set)
{
setModified(FILTER_RESTART);
}
else if (more_bits_set)
{
// target must have all requested permission bits, so more bits == more restrictive
setModified(FILTER_MORE_RESTRICTIVE);
}
else if (fewer_bits_set)
{
setModified(FILTER_LESS_RESTRICTIVE);
}
}
}
void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date)
{
mFilterOps.mHoursAgo = 0;
if (mFilterOps.mMinDate != min_date)
{
mFilterOps.mMinDate = min_date;
setModified();
}
if (mFilterOps.mMaxDate != llmax(mFilterOps.mMinDate, max_date))
{
mFilterOps.mMaxDate = llmax(mFilterOps.mMinDate, max_date);
setModified();
}
}
void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)
{
if (sl && !isSinceLogoff())
{
setDateRange(mLastLogoff, time_max());
setModified();
}
if (!sl && isSinceLogoff())
{
setDateRange(0, time_max());
setModified();
}
}
BOOL LLInventoryFilter::isSinceLogoff()
{
return (mFilterOps.mMinDate == mLastLogoff) &&
(mFilterOps.mMaxDate == time_max());
}
void LLInventoryFilter::setHoursAgo(U32 hours)
{
if (mFilterOps.mHoursAgo != hours)
{
// *NOTE: need to cache last filter time, in case filter goes stale
BOOL less_restrictive = (mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max() && hours > mFilterOps.mHoursAgo);
BOOL more_restrictive = (mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max() && hours <= mFilterOps.mHoursAgo);
mFilterOps.mHoursAgo = hours;
mFilterOps.mMinDate = time_min();
mFilterOps.mMaxDate = time_max();
if (less_restrictive)
{
setModified(FILTER_LESS_RESTRICTIVE);
}
else if (more_restrictive)
{
setModified(FILTER_MORE_RESTRICTIVE);
}
else
{
setModified(FILTER_RESTART);
}
}
}
void LLInventoryFilter::setShowFolderState(EFolderShow state)
{
if (mFilterOps.mShowFolderState != state)
{
mFilterOps.mShowFolderState = state;
if (state == SHOW_NON_EMPTY_FOLDERS)
{
// showing fewer folders than before
setModified(FILTER_MORE_RESTRICTIVE);
}
else if (state == SHOW_ALL_FOLDERS)
{
// showing same folders as before and then some
setModified(FILTER_LESS_RESTRICTIVE);
}
else
{
setModified();
}
}
}
void LLInventoryFilter::setSortOrder(U32 order)
{
if (mOrder != order)
{
mOrder = order;
setModified();
}
}
void LLInventoryFilter::markDefault()
{
mDefaultFilterOps = mFilterOps;
}
void LLInventoryFilter::resetDefault()
{
mFilterOps = mDefaultFilterOps;
setModified();
}
void LLInventoryFilter::setModified(EFilterBehavior behavior)
{
mModified = TRUE;
mNeedTextRebuild = TRUE;
mFilterGeneration = mNextFilterGeneration++;
if (mFilterBehavior == FILTER_NONE)
{
mFilterBehavior = behavior;
}
else if (mFilterBehavior != behavior)
{
// trying to do both less restrictive and more restrictive filter
// basically means restart from scratch
mFilterBehavior = FILTER_RESTART;
}
if (isNotDefault())
{
// if not keeping current filter results, update last valid as well
switch(mFilterBehavior)
{
case FILTER_RESTART:
mMustPassGeneration = mFilterGeneration;
mMinRequiredGeneration = mFilterGeneration;
break;
case FILTER_LESS_RESTRICTIVE:
mMustPassGeneration = mFilterGeneration;
break;
case FILTER_MORE_RESTRICTIVE:
mMinRequiredGeneration = mFilterGeneration;
// must have passed either current filter generation (meaningless, as it hasn't been run yet)
// or some older generation, so keep the value
mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration);
break;
default:
llerrs << "Bad filter behavior specified" << llendl;
}
}
else
{
// shortcut disabled filters to show everything immediately
mMinRequiredGeneration = 0;
mMustPassGeneration = S32_MAX;
}
}
BOOL LLInventoryFilter::isFilterWith(LLInventoryType::EType t)
{
return mFilterOps.mFilterTypes & (0x01 << t);
}
std::string LLInventoryFilter::getFilterText()
{
if (!mNeedTextRebuild)
{
return mFilterText;
}
mNeedTextRebuild = FALSE;
std::string filtered_types;
std::string not_filtered_types;
BOOL filtered_by_type = FALSE;
BOOL filtered_by_all_types = TRUE;
S32 num_filter_types = 0;
mFilterText.clear();
if (isFilterWith(LLInventoryType::IT_ANIMATION))
{
filtered_types += " Animations,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Animations,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_CALLINGCARD))
{
filtered_types += " Calling Cards,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Calling Cards,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_WEARABLE))
{
filtered_types += " Clothing,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Clothing,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_GESTURE))
{
filtered_types += " Gestures,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Gestures,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_LANDMARK))
{
filtered_types += " Landmarks,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Landmarks,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_NOTECARD))
{
filtered_types += " Notecards,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Notecards,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_OBJECT) && isFilterWith(LLInventoryType::IT_ATTACHMENT))
{
filtered_types += " Objects,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Objects,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_LSL))
{
filtered_types += " Scripts,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Scripts,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_SOUND))
{
filtered_types += " Sounds,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Sounds,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_TEXTURE))
{
filtered_types += " Textures,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Textures,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_SNAPSHOT))
{
filtered_types += " Snapshots,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Snapshots,";
filtered_by_all_types = FALSE;
}
if (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() && filtered_by_type && !filtered_by_all_types)
{
mFilterText += " - ";
if (num_filter_types < 5)
{
mFilterText += filtered_types;
}
else
{
mFilterText += "No ";
mFilterText += not_filtered_types;
}
// remove the ',' at the end
mFilterText.erase(mFilterText.size() - 1, 1);
}
if (isSinceLogoff())
{
mFilterText += " - Since Logoff";
}
if (getFilterWorn())
{
mFilterText += " - Worn";
}
return mFilterText;
}
void LLInventoryFilter::toLLSD(LLSD& data)
{
data["filter_types"] = (LLSD::Integer)getFilterTypes();
data["min_date"] = (LLSD::Integer)getMinDate();
data["max_date"] = (LLSD::Integer)getMaxDate();
data["hours_ago"] = (LLSD::Integer)getHoursAgo();
data["show_folder_state"] = (LLSD::Integer)getShowFolderState();
data["permissions"] = (LLSD::Integer)getFilterPermissions();
data["substring"] = (LLSD::String)getFilterSubString();
data["sort_order"] = (LLSD::Integer)getSortOrder();
data["since_logoff"] = (LLSD::Boolean)isSinceLogoff();
}
void LLInventoryFilter::fromLLSD(LLSD& data)
{
if(data.has("filter_types"))
{
setFilterTypes((U32)data["filter_types"].asInteger());
}
if(data.has("min_date") && data.has("max_date"))
{
setDateRange(data["min_date"].asInteger(), data["max_date"].asInteger());
}
if(data.has("hours_ago"))
{
setHoursAgo((U32)data["hours_ago"].asInteger());
}
if(data.has("show_folder_state"))
{
setShowFolderState((EFolderShow)data["show_folder_state"].asInteger());
}
if(data.has("permissions"))
{
setFilterPermissions((PermissionMask)data["permissions"].asInteger());
}
if(data.has("substring"))
{
setFilterSubString(std::string(data["substring"].asString()));
}
if(data.has("sort_order"))
{
setSortOrder((U32)data["sort_order"].asInteger());
}
if(data.has("since_logoff"))
{
setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean());
}
}

View File

@@ -55,6 +55,7 @@
#include "llviewertexture.h"
#include "lldepthstack.h"
#include "lltooldraganddrop.h"
#include "llinventoryfilter.h"
class LLMenuGL;
@@ -74,7 +75,6 @@ class LLFolderViewFunctor;
class LLScrollableContainerView;
class LLFolderViewEventListener;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFolderViewListenerFunctor
//
@@ -102,117 +102,7 @@ class LLFolderViewItem;
class LLFolderViewFolder;
class LLInventoryFilter
{
public:
typedef enum e_folder_show
{
SHOW_ALL_FOLDERS,
SHOW_NON_EMPTY_FOLDERS,
SHOW_NO_FOLDERS
} EFolderShow;
typedef enum e_filter_behavior
{
FILTER_NONE, // nothing to do, already filtered
FILTER_RESTART, // restart filtering from scratch
FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter
FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one
} EFilterBehavior;
static const U32 SO_DATE = 1;
static const U32 SO_FOLDERS_BY_NAME = 2;
static const U32 SO_SYSTEM_FOLDERS_TO_TOP = 4;
LLInventoryFilter(const std::string& name);
virtual ~LLInventoryFilter();
void setFilterTypes(U32 types);
U32 getFilterTypes() const { return mFilterOps.mFilterTypes; }
void setFilterSubString(const std::string& string);
const std::string getFilterSubString(BOOL trim = FALSE);
void setFilterWorn(bool worn) { mFilterWorn = worn; }
bool getFilterWorn() const { return mFilterWorn; }
void setFilterPermissions(PermissionMask perms);
PermissionMask getFilterPermissions() const { return mFilterOps.mPermissions; }
void setDateRange(time_t min_date, time_t max_date);
void setDateRangeLastLogoff(BOOL sl);
time_t getMinDate() const { return mFilterOps.mMinDate; }
time_t getMaxDate() const { return mFilterOps.mMaxDate; }
void setHoursAgo(U32 hours);
U32 getHoursAgo() const { return mFilterOps.mHoursAgo; }
void setShowFolderState( EFolderShow state);
EFolderShow getShowFolderState() { return mFilterOps.mShowFolderState; }
void setSortOrder(U32 order);
U32 getSortOrder() { return mOrder; }
BOOL check(LLFolderViewItem* item);
std::string::size_type getStringMatchOffset() const;
BOOL isActive();
BOOL isNotDefault();
BOOL isModified();
BOOL isModifiedAndClear();
BOOL isSinceLogoff();
void clearModified() { mModified = FALSE; mFilterBehavior = FILTER_NONE; }
const std::string getName() const { return mName; }
std::string getFilterText();
void setFilterCount(S32 count) { mFilterCount = count; }
S32 getFilterCount() { return mFilterCount; }
void decrementFilterCount() { mFilterCount--; }
void markDefault();
void resetDefault();
BOOL isFilterWith(LLInventoryType::EType t);
S32 getCurrentGeneration() const { return mFilterGeneration; }
S32 getMinRequiredGeneration() const { return mMinRequiredGeneration; }
S32 getMustPassGeneration() const { return mMustPassGeneration; }
//RN: this is public to allow system to externally force a global refilter
void setModified(EFilterBehavior behavior = FILTER_RESTART);
void toLLSD(LLSD& data);
void fromLLSD(LLSD& data);
protected:
struct filter_ops
{
U32 mFilterTypes;
time_t mMinDate;
time_t mMaxDate;
U32 mHoursAgo;
EFolderShow mShowFolderState;
PermissionMask mPermissions;
};
filter_ops mFilterOps;
filter_ops mDefaultFilterOps;
std::string::size_type mSubStringMatchOffset;
std::string mFilterSubString;
bool mFilterWorn;
U32 mOrder;
const std::string mName;
S32 mFilterGeneration;
S32 mMustPassGeneration;
S32 mMinRequiredGeneration;
S32 mFilterCount;
S32 mNextFilterGeneration;
EFilterBehavior mFilterBehavior;
private:
U32 mLastLogoff;
BOOL mModified;
BOOL mNeedTextRebuild;
std::string mFilterText;
};
// These are grouping of inventory types.
// Order matters when sorting system folders to the top.

View File

@@ -0,0 +1,706 @@
/**
* @file llinventoryfilter.cpp
* @brief Support for filtering your inventory to only display a subset of the
* available items.
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llinventoryfilter.h"
// viewer includes
#include "llfoldervieweventlistener.h"
#include "llfolderview.h"
#include "llinventorymodel.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llviewercontrol.h"
#include "llfolderview.h"
#include "llinventorybridge.h"
#include "llviewerfoldertype.h"
#include "llagentwearables.h"
#include "llvoavatarself.h"
// linden library includes
#include "lltrans.h"
LLInventoryFilter::FilterOps::FilterOps() :
mFilterTypes(0xffffffff),
mMinDate(time_min()),
mMaxDate(time_max()),
mHoursAgo(0),
mShowFolderState(SHOW_NON_EMPTY_FOLDERS),
mPermissions(PERM_NONE) {}
///----------------------------------------------------------------------------
/// Class LLInventoryFilter
///----------------------------------------------------------------------------
LLInventoryFilter::LLInventoryFilter(const std::string& name)
: mName(name),
mModified(FALSE),
mNeedTextRebuild(TRUE)
{
mOrder = SO_FOLDERS_BY_NAME; // This gets overridden by a pref immediately
mSubStringMatchOffset = 0;
mFilterSubString.clear();
mFilterWorn = false;
mFilterGeneration = 0;
mMustPassGeneration = S32_MAX;
mMinRequiredGeneration = 0;
mFilterCount = 0;
mNextFilterGeneration = mFilterGeneration + 1;
mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff");
mFilterBehavior = FILTER_NONE;
// copy mFilterOps into mDefaultFilterOps
markDefault();
}
LLInventoryFilter::~LLInventoryFilter()
{
}
BOOL LLInventoryFilter::check(LLFolderViewItem* item)
{
LLFolderViewEventListener* listener = item->getListener();
const LLUUID& item_id = listener->getUUID();
const LLInventoryObject *obj = gInventory.getObject(item_id);
if (isActive() && obj && obj->getIsLinkType())
{
// When filtering is active, omit links.
return FALSE;
}
time_t earliest;
earliest = time_corrected() - mFilterOps.mHoursAgo * 3600;
if (mFilterOps.mMinDate > time_min() && mFilterOps.mMinDate < earliest)
{
earliest = mFilterOps.mMinDate;
}
else if (!mFilterOps.mHoursAgo)
{
earliest = 0;
}
mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos;
BOOL passed = (0x1 << listener->getInventoryType() & mFilterOps.mFilterTypes || listener->getInventoryType() == LLInventoryType::IT_NONE)
&& (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)
&& (mFilterWorn == false || gAgentWearables.isWearingItem(item_id) ||
(gAgentAvatarp && gAgentAvatarp->isWearingAttachment(item_id)))
&& ((listener->getPermissionMask() & mFilterOps.mPermissions) == mFilterOps.mPermissions)
&& (listener->getCreationDate() >= earliest && listener->getCreationDate() <= mFilterOps.mMaxDate);
return passed;
}
const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const
{
return mFilterSubString;
}
std::string::size_type LLInventoryFilter::getStringMatchOffset() const
{
return mSubStringMatchOffset;
}
// has user modified default filter params?
BOOL LLInventoryFilter::isNotDefault() const
{
return mFilterOps.mFilterTypes != mDefaultFilterOps.mFilterTypes
|| mFilterSubString.size()
|| mFilterWorn
|| mFilterOps.mPermissions != mDefaultFilterOps.mPermissions
|| mFilterOps.mMinDate != mDefaultFilterOps.mMinDate
|| mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate
|| mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo;
}
BOOL LLInventoryFilter::isActive() const
{
return mFilterOps.mFilterTypes != 0xffffffff
|| mFilterSubString.size()
|| mFilterWorn
|| mFilterOps.mPermissions != PERM_NONE
|| mFilterOps.mMinDate != time_min()
|| mFilterOps.mMaxDate != time_max()
|| mFilterOps.mHoursAgo != 0;
}
BOOL LLInventoryFilter::isModified() const
{
return mModified;
}
BOOL LLInventoryFilter::isModifiedAndClear()
{
BOOL ret = mModified;
mModified = FALSE;
return ret;
}
void LLInventoryFilter::setFilterTypes(U32 types)
{
if (mFilterOps.mFilterTypes != types)
{
// keep current items only if no type bits getting turned off
BOOL fewer_bits_set = (mFilterOps.mFilterTypes & ~types);
BOOL more_bits_set = (~mFilterOps.mFilterTypes & types);
mFilterOps.mFilterTypes = types;
if (more_bits_set && fewer_bits_set)
{
// neither less or more restrive, both simultaneously
// so we need to filter from scratch
setModified(FILTER_RESTART);
}
else if (more_bits_set)
{
// target is only one of all requested types so more type bits == less restrictive
setModified(FILTER_LESS_RESTRICTIVE);
}
else if (fewer_bits_set)
{
setModified(FILTER_MORE_RESTRICTIVE);
}
}
}
void LLInventoryFilter::setFilterSubString(const std::string& string)
{
std::string filter_sub_string_new = string;
mFilterSubStringOrig = string;
LLStringUtil::trimHead(filter_sub_string_new);
LLStringUtil::toUpper(filter_sub_string_new);
if (mFilterSubString != filter_sub_string_new)
{
// hitting BACKSPACE, for example
const BOOL less_restrictive = mFilterSubString.size() >= filter_sub_string_new.size()
&& !mFilterSubString.substr(0, filter_sub_string_new.size()).compare(filter_sub_string_new);
// appending new characters
const BOOL more_restrictive = mFilterSubString.size() < filter_sub_string_new.size()
&& !filter_sub_string_new.substr(0, mFilterSubString.size()).compare(mFilterSubString);
mFilterSubString = filter_sub_string_new;
if (less_restrictive)
{
setModified(FILTER_LESS_RESTRICTIVE);
}
else if (more_restrictive)
{
setModified(FILTER_MORE_RESTRICTIVE);
}
else
{
setModified(FILTER_RESTART);
}
}
}
void LLInventoryFilter::setFilterPermissions(PermissionMask perms)
{
if (mFilterOps.mPermissions != perms)
{
// keep current items only if no perm bits getting turned off
BOOL fewer_bits_set = (mFilterOps.mPermissions & ~perms);
BOOL more_bits_set = (~mFilterOps.mPermissions & perms);
mFilterOps.mPermissions = perms;
if (more_bits_set && fewer_bits_set)
{
setModified(FILTER_RESTART);
}
else if (more_bits_set)
{
// target must have all requested permission bits, so more bits == more restrictive
setModified(FILTER_MORE_RESTRICTIVE);
}
else if (fewer_bits_set)
{
setModified(FILTER_LESS_RESTRICTIVE);
}
}
}
void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date)
{
mFilterOps.mHoursAgo = 0;
if (mFilterOps.mMinDate != min_date)
{
mFilterOps.mMinDate = min_date;
setModified();
}
if (mFilterOps.mMaxDate != llmax(mFilterOps.mMinDate, max_date))
{
mFilterOps.mMaxDate = llmax(mFilterOps.mMinDate, max_date);
setModified();
}
}
void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)
{
if (sl && !isSinceLogoff())
{
setDateRange(mLastLogoff, time_max());
setModified();
}
if (!sl && isSinceLogoff())
{
setDateRange(0, time_max());
setModified();
}
}
BOOL LLInventoryFilter::isSinceLogoff() const
{
return (mFilterOps.mMinDate == (time_t)mLastLogoff) &&
(mFilterOps.mMaxDate == time_max());
}
void LLInventoryFilter::clearModified()
{
mModified = FALSE;
mFilterBehavior = FILTER_NONE;
}
void LLInventoryFilter::setHoursAgo(U32 hours)
{
if (mFilterOps.mHoursAgo != hours)
{
bool are_date_limits_valid = mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max();
bool is_increasing = hours > mFilterOps.mHoursAgo;
bool is_increasing_from_zero = is_increasing && !mFilterOps.mHoursAgo;
// *NOTE: need to cache last filter time, in case filter goes stale
BOOL less_restrictive = (are_date_limits_valid && ((is_increasing && mFilterOps.mHoursAgo)) || !hours);
BOOL more_restrictive = (are_date_limits_valid && (!is_increasing && hours) || is_increasing_from_zero);
mFilterOps.mHoursAgo = hours;
mFilterOps.mMinDate = time_min();
mFilterOps.mMaxDate = time_max();
if (less_restrictive)
{
setModified(FILTER_LESS_RESTRICTIVE);
}
else if (more_restrictive)
{
setModified(FILTER_MORE_RESTRICTIVE);
}
else
{
setModified(FILTER_RESTART);
}
}
}
void LLInventoryFilter::setShowFolderState(EFolderShow state)
{
if (mFilterOps.mShowFolderState != state)
{
mFilterOps.mShowFolderState = state;
if (state == SHOW_NON_EMPTY_FOLDERS)
{
// showing fewer folders than before
setModified(FILTER_MORE_RESTRICTIVE);
}
else if (state == SHOW_ALL_FOLDERS)
{
// showing same folders as before and then some
setModified(FILTER_LESS_RESTRICTIVE);
}
else
{
setModified();
}
}
}
void LLInventoryFilter::setSortOrder(U32 order)
{
if (mOrder != order)
{
mOrder = order;
setModified();
}
}
void LLInventoryFilter::markDefault()
{
mDefaultFilterOps = mFilterOps;
}
void LLInventoryFilter::resetDefault()
{
mFilterOps = mDefaultFilterOps;
setModified();
}
void LLInventoryFilter::setModified(EFilterBehavior behavior)
{
mModified = TRUE;
mNeedTextRebuild = TRUE;
mFilterGeneration = mNextFilterGeneration++;
if (mFilterBehavior == FILTER_NONE)
{
mFilterBehavior = behavior;
}
else if (mFilterBehavior != behavior)
{
// trying to do both less restrictive and more restrictive filter
// basically means restart from scratch
mFilterBehavior = FILTER_RESTART;
}
if (isNotDefault())
{
// if not keeping current filter results, update last valid as well
switch(mFilterBehavior)
{
case FILTER_RESTART:
mMustPassGeneration = mFilterGeneration;
mMinRequiredGeneration = mFilterGeneration;
break;
case FILTER_LESS_RESTRICTIVE:
mMustPassGeneration = mFilterGeneration;
break;
case FILTER_MORE_RESTRICTIVE:
mMinRequiredGeneration = mFilterGeneration;
// must have passed either current filter generation (meaningless, as it hasn't been run yet)
// or some older generation, so keep the value
mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration);
break;
default:
llerrs << "Bad filter behavior specified" << llendl;
}
}
else
{
// shortcut disabled filters to show everything immediately
mMinRequiredGeneration = 0;
mMustPassGeneration = S32_MAX;
}
}
BOOL LLInventoryFilter::isFilterWith(LLInventoryType::EType t) const
{
return mFilterOps.mFilterTypes & (0x01 << t);
}
const std::string& LLInventoryFilter::getFilterText()
{
if (!mNeedTextRebuild)
{
return mFilterText;
}
mNeedTextRebuild = FALSE;
std::string filtered_types;
std::string not_filtered_types;
BOOL filtered_by_type = FALSE;
BOOL filtered_by_all_types = TRUE;
S32 num_filter_types = 0;
mFilterText.clear();
if (isFilterWith(LLInventoryType::IT_ANIMATION))
{
filtered_types += " Animations,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Animations,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_CALLINGCARD))
{
filtered_types += " Calling Cards,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Calling Cards,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_WEARABLE))
{
filtered_types += " Clothing,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Clothing,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_GESTURE))
{
filtered_types += " Gestures,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Gestures,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_LANDMARK))
{
filtered_types += " Landmarks,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Landmarks,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_NOTECARD))
{
filtered_types += " Notecards,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Notecards,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_OBJECT) && isFilterWith(LLInventoryType::IT_ATTACHMENT))
{
filtered_types += " Objects,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Objects,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_LSL))
{
filtered_types += " Scripts,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Scripts,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_SOUND))
{
filtered_types += " Sounds,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Sounds,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_TEXTURE))
{
filtered_types += " Textures,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Textures,";
filtered_by_all_types = FALSE;
}
if (isFilterWith(LLInventoryType::IT_SNAPSHOT))
{
filtered_types += " Snapshots,";
filtered_by_type = TRUE;
num_filter_types++;
}
else
{
not_filtered_types += " Snapshots,";
filtered_by_all_types = FALSE;
}
if (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive()
&& filtered_by_type
&& !filtered_by_all_types)
{
mFilterText += " - ";
if (num_filter_types < 5)
{
mFilterText += filtered_types;
}
else
{
mFilterText += "No ";
mFilterText += not_filtered_types;
}
// remove the ',' at the end
mFilterText.erase(mFilterText.size() - 1, 1);
}
if (isSinceLogoff())
{
mFilterText += " - Since Logoff";
}
if (getFilterWorn())
{
mFilterText += " - Worn";
}
return mFilterText;
}
void LLInventoryFilter::toLLSD(LLSD& data) const
{
data["filter_types"] = (LLSD::Integer)getFilterTypes();
data["min_date"] = (LLSD::Integer)getMinDate();
data["max_date"] = (LLSD::Integer)getMaxDate();
data["hours_ago"] = (LLSD::Integer)getHoursAgo();
data["show_folder_state"] = (LLSD::Integer)getShowFolderState();
data["permissions"] = (LLSD::Integer)getFilterPermissions();
data["substring"] = (LLSD::String)getFilterSubString();
data["sort_order"] = (LLSD::Integer)getSortOrder();
data["since_logoff"] = (LLSD::Boolean)isSinceLogoff();
}
void LLInventoryFilter::fromLLSD(LLSD& data)
{
if(data.has("filter_types"))
{
setFilterTypes((U32)data["filter_types"].asInteger());
}
if(data.has("min_date") && data.has("max_date"))
{
setDateRange(data["min_date"].asInteger(), data["max_date"].asInteger());
}
if(data.has("hours_ago"))
{
setHoursAgo((U32)data["hours_ago"].asInteger());
}
if(data.has("show_folder_state"))
{
setShowFolderState((EFolderShow)data["show_folder_state"].asInteger());
}
if(data.has("permissions"))
{
setFilterPermissions((PermissionMask)data["permissions"].asInteger());
}
if(data.has("substring"))
{
setFilterSubString(std::string(data["substring"].asString()));
}
if(data.has("sort_order"))
{
setSortOrder((U32)data["sort_order"].asInteger());
}
if(data.has("since_logoff"))
{
setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean());
}
}
BOOL LLInventoryFilter::hasFilterString() const
{
return mFilterSubString.size() > 0;
}
PermissionMask LLInventoryFilter::getFilterPermissions() const
{
return mFilterOps.mPermissions;
}
time_t LLInventoryFilter::getMinDate() const
{
return mFilterOps.mMinDate;
}
time_t LLInventoryFilter::getMaxDate() const
{
return mFilterOps.mMaxDate;
}
U32 LLInventoryFilter::getHoursAgo() const
{
return mFilterOps.mHoursAgo;
}
LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const
{
return mFilterOps.mShowFolderState;
}
U32 LLInventoryFilter::getSortOrder() const
{
return mOrder;
}
const std::string& LLInventoryFilter::getName() const
{
return mName;
}
void LLInventoryFilter::setFilterCount(S32 count)
{
mFilterCount = count;
}
S32 LLInventoryFilter::getFilterCount() const
{
return mFilterCount;
}
void LLInventoryFilter::decrementFilterCount()
{
mFilterCount--;
}
S32 LLInventoryFilter::getCurrentGeneration() const
{
return mFilterGeneration;
}
S32 LLInventoryFilter::getMinRequiredGeneration() const
{
return mMinRequiredGeneration;
}
S32 LLInventoryFilter::getMustPassGeneration() const
{
return mMustPassGeneration;
}

View File

@@ -0,0 +1,183 @@
/**
* @file llinventoryfilter.h
* @brief Support for filtering your inventory to only display a subset of the
* available items.
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LLINVENTORYFILTER_H
#define LLINVENTORYFILTER_H
#include "llinventorytype.h"
#include "llpermissionsflags.h"
class LLFolderViewItem;
class LLFolderViewFolder;
class LLInventoryFilter
{
public:
enum EFolderShow
{
SHOW_ALL_FOLDERS,
SHOW_NON_EMPTY_FOLDERS,
SHOW_NO_FOLDERS
};
enum EFilterBehavior
{
FILTER_NONE, // nothing to do, already filtered
FILTER_RESTART, // restart filtering from scratch
FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter
FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one
};
enum ESortOrderType
{
SO_DATE = 0x1, // Sort inventory by date
SO_FOLDERS_BY_NAME = 0x1 << 1, // Force folder sort by name
SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2 // Force system folders to be on top
};
LLInventoryFilter(const std::string& name);
virtual ~LLInventoryFilter();
void setFilterTypes(U32 types);
BOOL isFilterWith(LLInventoryType::EType t) const;
U32 getFilterTypes() const { return mFilterOps.mFilterTypes; }
void setFilterSubString(const std::string& string);
const std::string& getFilterSubString(BOOL trim = FALSE) const;
const std::string& getFilterSubStringOrig() const { return mFilterSubStringOrig; }
BOOL hasFilterString() const;
void setFilterWorn(bool worn) { mFilterWorn = worn; }
bool getFilterWorn() const { return mFilterWorn; }
void setFilterPermissions(PermissionMask perms);
PermissionMask getFilterPermissions() const;
void setDateRange(time_t min_date, time_t max_date);
void setDateRangeLastLogoff(BOOL sl);
time_t getMinDate() const;
time_t getMaxDate() const;
void setHoursAgo(U32 hours);
U32 getHoursAgo() const;
// +-------------------------------------------------------------------+
// + Execution And Results
// +-------------------------------------------------------------------+
BOOL check(LLFolderViewItem* item);
std::string::size_type getStringMatchOffset() const;
// +-------------------------------------------------------------------+
// + Presentation
// +-------------------------------------------------------------------+
void setShowFolderState( EFolderShow state);
EFolderShow getShowFolderState() const;
void setSortOrder(U32 order);
U32 getSortOrder() const;
// +-------------------------------------------------------------------+
// + Status
// +-------------------------------------------------------------------+
BOOL isActive() const;
BOOL isModified() const;
BOOL isModifiedAndClear();
BOOL isSinceLogoff() const;
void clearModified();
const std::string& getName() const;
const std::string& getFilterText();
//RN: this is public to allow system to externally force a global refilter
void setModified(EFilterBehavior behavior = FILTER_RESTART);
// +-------------------------------------------------------------------+
// + Count
// +-------------------------------------------------------------------+
void setFilterCount(S32 count);
S32 getFilterCount() const;
void decrementFilterCount();
// +-------------------------------------------------------------------+
// + Default
// +-------------------------------------------------------------------+
BOOL isNotDefault() const;
void markDefault();
void resetDefault();
// +-------------------------------------------------------------------+
// + Generation
// +-------------------------------------------------------------------+
S32 getCurrentGeneration() const;
S32 getMinRequiredGeneration() const;
S32 getMustPassGeneration() const;
void toLLSD(LLSD& data) const;
void fromLLSD(LLSD& data);
private:
struct FilterOps
{
FilterOps();
U32 mFilterTypes;
time_t mMinDate;
time_t mMaxDate;
U32 mHoursAgo;
EFolderShow mShowFolderState;
PermissionMask mPermissions;
};
U32 mOrder;
U32 mLastLogoff;
FilterOps mFilterOps;
FilterOps mDefaultFilterOps;
std::string::size_type mSubStringMatchOffset;
std::string mFilterSubString;
std::string mFilterSubStringOrig;
bool mFilterWorn;
const std::string mName;
S32 mFilterGeneration;
S32 mMustPassGeneration;
S32 mMinRequiredGeneration;
S32 mNextFilterGeneration;
S32 mFilterCount;
EFilterBehavior mFilterBehavior;
BOOL mModified;
BOOL mNeedTextRebuild;
std::string mFilterText;
};
#endif