diff options
| author | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 |
|---|---|---|
| committer | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 |
| commit | 1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch) | |
| tree | ab243607f74f78200787bba5b9b88f07ef1b966f /indra/newview/llinventoryfilter.cpp | |
| parent | 6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff) | |
| parent | e1623bb276f83a43ce7a197e388720c05bdefe61 (diff) | |
Merge remote-tracking branch 'origin/main' into DRTVWR-600-maint-A
# Conflicts:
# autobuild.xml
# indra/cmake/CMakeLists.txt
# indra/cmake/GoogleMock.cmake
# indra/llaudio/llaudioengine_fmodstudio.cpp
# indra/llaudio/llaudioengine_fmodstudio.h
# indra/llaudio/lllistener_fmodstudio.cpp
# indra/llaudio/lllistener_fmodstudio.h
# indra/llaudio/llstreamingaudio_fmodstudio.cpp
# indra/llaudio/llstreamingaudio_fmodstudio.h
# indra/llcharacter/llmultigesture.cpp
# indra/llcharacter/llmultigesture.h
# indra/llimage/llimage.cpp
# indra/llimage/llimagepng.cpp
# indra/llimage/llimageworker.cpp
# indra/llimage/tests/llimageworker_test.cpp
# indra/llmessage/tests/llmockhttpclient.h
# indra/llprimitive/llgltfmaterial.h
# indra/llrender/llfontfreetype.cpp
# indra/llui/llcombobox.cpp
# indra/llui/llfolderview.cpp
# indra/llui/llfolderviewmodel.h
# indra/llui/lllineeditor.cpp
# indra/llui/lllineeditor.h
# indra/llui/lltextbase.cpp
# indra/llui/lltextbase.h
# indra/llui/lltexteditor.cpp
# indra/llui/lltextvalidate.cpp
# indra/llui/lltextvalidate.h
# indra/llui/lluictrl.h
# indra/llui/llview.cpp
# indra/llwindow/llwindowmacosx.cpp
# indra/newview/app_settings/settings.xml
# indra/newview/llappearancemgr.cpp
# indra/newview/llappearancemgr.h
# indra/newview/llavatarpropertiesprocessor.cpp
# indra/newview/llavatarpropertiesprocessor.h
# indra/newview/llbreadcrumbview.cpp
# indra/newview/llbreadcrumbview.h
# indra/newview/llbreastmotion.cpp
# indra/newview/llbreastmotion.h
# indra/newview/llconversationmodel.h
# indra/newview/lldensityctrl.cpp
# indra/newview/lldensityctrl.h
# indra/newview/llface.inl
# indra/newview/llfloatereditsky.cpp
# indra/newview/llfloatereditwater.cpp
# indra/newview/llfloateremojipicker.h
# indra/newview/llfloaterimsessiontab.cpp
# indra/newview/llfloaterprofiletexture.cpp
# indra/newview/llfloaterprofiletexture.h
# indra/newview/llgesturemgr.cpp
# indra/newview/llgesturemgr.h
# indra/newview/llimpanel.cpp
# indra/newview/llimpanel.h
# indra/newview/llinventorybridge.cpp
# indra/newview/llinventorybridge.h
# indra/newview/llinventoryclipboard.cpp
# indra/newview/llinventoryclipboard.h
# indra/newview/llinventoryfunctions.cpp
# indra/newview/llinventoryfunctions.h
# indra/newview/llinventorygallery.cpp
# indra/newview/lllistbrowser.cpp
# indra/newview/lllistbrowser.h
# indra/newview/llpanelobjectinventory.cpp
# indra/newview/llpanelprofile.cpp
# indra/newview/llpanelprofile.h
# indra/newview/llpreviewgesture.cpp
# indra/newview/llsavedsettingsglue.cpp
# indra/newview/llsavedsettingsglue.h
# indra/newview/lltooldraganddrop.cpp
# indra/newview/llurllineeditorctrl.cpp
# indra/newview/llvectorperfoptions.cpp
# indra/newview/llvectorperfoptions.h
# indra/newview/llviewerparceloverlay.cpp
# indra/newview/llviewertexlayer.cpp
# indra/newview/llviewertexturelist.cpp
# indra/newview/macmain.h
# indra/test/test.cpp
Diffstat (limited to 'indra/newview/llinventoryfilter.cpp')
| -rw-r--r-- | indra/newview/llinventoryfilter.cpp | 3442 |
1 files changed, 1721 insertions, 1721 deletions
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 83770e28b6..8312cfae03 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -1,1721 +1,1721 @@ -/** -* @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 "llagent.h" -#include "llfolderviewmodel.h" -#include "llfolderviewitem.h" -#include "llinventorymodel.h" -#include "llinventorymodelbackgroundfetch.h" -#include "llinventoryfunctions.h" -#include "llmarketplacefunctions.h" -#include "llregex.h" -#include "llviewercontrol.h" -#include "llfolderview.h" -#include "llinventorybridge.h" -#include "llviewerfoldertype.h" -#include "llradiogroup.h" -#include "llstartup.h" - -// linden library includes -#include "llclipboard.h" -#include "lltrans.h" - -LLInventoryFilter::FilterOps::FilterOps(const Params& p) -: mFilterObjectTypes(p.object_types), - mFilterCategoryTypes(p.category_types), - mFilterWearableTypes(p.wearable_types), - mFilterSettingsTypes(p.settings_types), - mMinDate(p.date_range.min_date), - mMaxDate(p.date_range.max_date), - mHoursAgo(p.hours_ago), - mDateSearchDirection(p.date_search_direction), - mShowFolderState(p.show_folder_state), - mFilterCreatorType(p.creator_type), - mPermissions(p.permissions), - mFilterTypes(p.types), - mFilterUUID(p.uuid), - mFilterLinks(p.links), - mFilterThumbnails(p.thumbnails), - mSearchVisibility(p.search_visibility) -{ -} - -///---------------------------------------------------------------------------- -/// Class LLInventoryFilter -///---------------------------------------------------------------------------- -LLInventoryFilter::LLInventoryFilter(const Params& p) -: mName(p.name), - mFilterModified(FILTER_NONE), - mEmptyLookupMessage("InventoryNoMatchingItems"), - mDefaultEmptyLookupMessage(""), - mFilterOps(p.filter_ops), - mBackupFilterOps(mFilterOps), - mFilterSubString(p.substring), - mCurrentGeneration(0), - mFirstRequiredGeneration(0), - mFirstSuccessGeneration(0), - mSearchType(SEARCHTYPE_NAME), - mSingleFolderMode(false) -{ - // copy mFilterOps into mDefaultFilterOps - markDefault(); - mUsername = gAgentUsername; - LLStringUtil::toUpper(mUsername); -} - -bool LLInventoryFilter::check(const LLFolderViewModelItem* item) -{ - const LLFolderViewModelItemInventory* listener = dynamic_cast<const LLFolderViewModelItemInventory*>(item); - - // If it's a folder and we're showing all folders, return automatically. - const bool is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY; - if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)) - { - return true; - } - - std::string desc = listener->getSearchableCreatorName(); - switch(mSearchType) - { - case SEARCHTYPE_CREATOR: - desc = listener->getSearchableCreatorName(); - break; - case SEARCHTYPE_DESCRIPTION: - desc = listener->getSearchableDescription(); - break; - case SEARCHTYPE_UUID: - desc = listener->getSearchableUUIDString(); - break; - case SEARCHTYPE_NAME: - default: - desc = listener->getSearchableName(); - break; - } - - - bool passed = true; - if (!mExactToken.empty() && (mSearchType == SEARCHTYPE_NAME)) - { - passed = false; - typedef boost::tokenizer<boost::char_separator<char> > tokenizer; - boost::char_separator<char> sep(" "); - tokenizer tokens(desc, sep); - - for (auto token_iter : tokens) - { - if (token_iter == mExactToken) - { - passed = true; - break; - } - } - } - else if ((mFilterTokens.size() > 0) && (mSearchType == SEARCHTYPE_NAME)) - { - for (auto token_iter : mFilterTokens) - { - if (desc.find(token_iter) == std::string::npos) - { - return false; - } - } - } - else - { - passed = (mFilterSubString.size() ? desc.find(mFilterSubString) != std::string::npos : true); - } - - passed = passed && checkAgainstFilterType(listener); - passed = passed && checkAgainstPermissions(listener); - passed = passed && checkAgainstFilterLinks(listener); - passed = passed && checkAgainstCreator(listener); - passed = passed && checkAgainstSearchVisibility(listener); - - passed = passed && checkAgainstFilterThumbnails(listener->getUUID()); - - return passed; -} - -bool LLInventoryFilter::check(const LLInventoryItem* item) -{ - const bool passed_string = (mFilterSubString.size() ? item->getName().find(mFilterSubString) != std::string::npos : true); - const bool passed_filtertype = checkAgainstFilterType(item); - const bool passed_permissions = checkAgainstPermissions(item); - - return passed_filtertype && passed_permissions && passed_string; -} - -bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const -{ - const LLFolderViewModelItemInventory* listener = dynamic_cast<const LLFolderViewModelItemInventory*>(item); - if (!listener) - { - LL_ERRS() << "Folder view event listener not found." << LL_ENDL; - return false; - } - - const LLUUID folder_id = listener->getUUID(); - - return checkFolder(folder_id); -} - -bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const -{ - // we're showing all folders, overriding filter - if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS) - { - return true; - } - - // when applying a filter, matching folders get their contents downloaded first - // but make sure we are not interfering with pre-download - if (isNotDefault() - && LLStartUp::getStartupState() > STATE_WEARABLES_WAIT - && !LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress()) - { - LLViewerInventoryCategory* cat = gInventory.getCategory(folder_id); - if ((!cat && folder_id.notNull())) - { - // Shouldn't happen? Server provides full list of folders on startup - LLInventoryModelBackgroundFetch::instance().start(folder_id, false); - } - else if (cat && cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) - { - // At the moment background fetch only cares about VERSION_UNKNOWN, - // so do not check isCategoryComplete that compares descendant count, - // but if that is nesesary, do a forced scheduleFolderFetch. - cat->fetch(); - } - } - - if (!checkAgainstFilterThumbnails(folder_id)) - { - return false; - } - - // Marketplace folder filtering - const U32 filterTypes = mFilterOps.mFilterTypes; - const U32 marketplace_filter = FILTERTYPE_MARKETPLACE_ACTIVE | FILTERTYPE_MARKETPLACE_INACTIVE | - FILTERTYPE_MARKETPLACE_UNASSOCIATED | FILTERTYPE_MARKETPLACE_LISTING_FOLDER | - FILTERTYPE_NO_MARKETPLACE_ITEMS; - if (filterTypes & marketplace_filter) - { - S32 depth = depth_nesting_in_marketplace(folder_id); - - if (filterTypes & FILTERTYPE_NO_MARKETPLACE_ITEMS) - { - if (depth >= 0) - { - return false; - } - } - - if (filterTypes & FILTERTYPE_MARKETPLACE_LISTING_FOLDER) - { - if (depth > 1) - { - return false; - } - } - - if (depth > 0) - { - LLUUID listing_uuid = nested_parent_id(folder_id, depth); - if (filterTypes & FILTERTYPE_MARKETPLACE_ACTIVE) - { - if (!LLMarketplaceData::instance().getActivationState(listing_uuid)) - { - return false; - } - } - else if (filterTypes & FILTERTYPE_MARKETPLACE_INACTIVE) - { - if (!LLMarketplaceData::instance().isListed(listing_uuid) || LLMarketplaceData::instance().getActivationState(listing_uuid)) - { - return false; - } - } - else if (filterTypes & FILTERTYPE_MARKETPLACE_UNASSOCIATED) - { - if (LLMarketplaceData::instance().isListed(listing_uuid)) - { - return false; - } - } - } - } - - // show folder links - LLViewerInventoryItem* item = gInventory.getItem(folder_id); - if (item && item->getActualType() == LLAssetType::AT_LINK_FOLDER) - { - return true; - } - - if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY) - { - // Can only filter categories for items in your inventory - // (e.g. versus in-world object contents). - const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id); - if (!cat) - return folder_id.isNull(); - LLFolderType::EType cat_type = cat->getPreferredType(); - if (cat_type != LLFolderType::FT_NONE && (1LL << cat_type & mFilterOps.mFilterCategoryTypes) == U64(0)) - return false; - } - - return true; -} - -bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInventory* listener) const -{ - if (!listener) return false; - - LLInventoryType::EType object_type = listener->getInventoryType(); - const LLUUID object_id = listener->getUUID(); - const LLInventoryObject *object = gInventory.getObject(object_id); - - const U32 filterTypes = mFilterOps.mFilterTypes; - - //////////////////////////////////////////////////////////////////////////////// - // FILTERTYPE_OBJECT - // Pass if this item's type is of the correct filter type - if (filterTypes & FILTERTYPE_OBJECT) - { - switch (object_type) - { - case LLInventoryType::IT_NONE: - // If it has no type, pass it, unless it's a link. - if (object && object->getIsLinkType()) - { - return false; - } - break; - case LLInventoryType::IT_UNKNOWN: - { - // Unknows are only shown when we show every type. - // Unknows are 255 and won't fit in 64 bits. - if (mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL) - { - return false; - } - break; - } - default: - if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0)) - { - return false; - } - break; - } - } - - if(filterTypes & FILTERTYPE_WORN) - { - if (!get_is_item_worn(object_id)) - { - return false; - } - } - - //////////////////////////////////////////////////////////////////////////////// - // FILTERTYPE_UUID - // Pass if this item is the target UUID or if it links to the target UUID - if (filterTypes & FILTERTYPE_UUID) - { - if (!object) return false; - - if (object->getLinkedUUID() != mFilterOps.mFilterUUID) - return false; - } - - //////////////////////////////////////////////////////////////////////////////// - // FILTERTYPE_DATE - // Pass if this item is within the date range. - if (filterTypes & FILTERTYPE_DATE) - { - const U16 HOURS_TO_SECONDS = 3600; - time_t earliest = time_corrected() - mFilterOps.mHoursAgo * HOURS_TO_SECONDS; - - if (mFilterOps.mMinDate > time_min() && mFilterOps.mMinDate < earliest) - { - earliest = mFilterOps.mMinDate; - } - else if (!mFilterOps.mHoursAgo) - { - earliest = 0; - } - - if (FILTERDATEDIRECTION_NEWER == mFilterOps.mDateSearchDirection || isSinceLogoff()) - { - if (listener->getCreationDate() < earliest || - listener->getCreationDate() > mFilterOps.mMaxDate) - return false; - } - else - { - if (listener->getCreationDate() > earliest || - listener->getCreationDate() > mFilterOps.mMaxDate) - return false; - } - } - - //////////////////////////////////////////////////////////////////////////////// - // FILTERTYPE_WEARABLE - // Pass if this item is a wearable of the appropriate type - if (filterTypes & FILTERTYPE_WEARABLE) - { - LLWearableType::EType type = listener->getWearableType(); - if ((object_type == LLInventoryType::IT_WEARABLE) && - (((0x1LL << type) & mFilterOps.mFilterWearableTypes) == 0)) - { - return false; - } - } - - //////////////////////////////////////////////////////////////////////////////// - // FILTERTYPE_SETTINGS - // Pass if this item is a setting of the appropriate type - if (filterTypes & FILTERTYPE_SETTINGS) - { - LLSettingsType::type_e type = listener->getSettingsType(); - if ((object_type == LLInventoryType::IT_SETTINGS) && - (((0x1LL << type) & mFilterOps.mFilterSettingsTypes) == 0)) - { - return false; - } - } - - //////////////////////////////////////////////////////////////////////////////// - // FILTERTYPE_EMPTYFOLDERS - // Pass if this item is a folder and is not a system folder that should be hidden - if (filterTypes & FILTERTYPE_EMPTYFOLDERS) - { - if (object_type == LLInventoryType::IT_CATEGORY) - { - bool is_hidden_if_empty = LLViewerFolderType::lookupIsHiddenIfEmpty(listener->getPreferredType()); - if (is_hidden_if_empty) - { - // Force the fetching of those folders so they are hidden if they really are empty... - // But don't interfere with startup download - if (LLStartUp::getStartupState() > STATE_WEARABLES_WAIT) - { - gInventory.fetchDescendentsOf(object_id); - } - - LLInventoryModel::cat_array_t* cat_array = NULL; - LLInventoryModel::item_array_t* item_array = NULL; - gInventory.getDirectDescendentsOf(object_id,cat_array,item_array); - S32 descendents_actual = 0; - if(cat_array && item_array) - { - descendents_actual = cat_array->size() + item_array->size(); - } - if (descendents_actual == 0) - { - return false; - } - } - } - } - - return true; -} - -bool LLInventoryFilter::checkAgainstFilterType(const LLInventoryItem* item) const -{ - LLInventoryType::EType object_type = item->getInventoryType(); - - const U32 filterTypes = mFilterOps.mFilterTypes; - - //////////////////////////////////////////////////////////////////////////////// - // FILTERTYPE_OBJECT - // Pass if this item's type is of the correct filter type - if (filterTypes & FILTERTYPE_OBJECT) - { - switch (object_type) - { - case LLInventoryType::IT_NONE: - // If it has no type, pass it, unless it's a link. - if (item && item->getIsLinkType()) - { - return false; - } - break; - case LLInventoryType::IT_UNKNOWN: - { - // Unknows are only shown when we show every type. - // Unknows are 255 and won't fit in 64 bits. - if (mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL) - { - return false; - } - break; - } - default: - if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0)) - { - return false; - } - break; - } - } - - //////////////////////////////////////////////////////////////////////////////// - // FILTERTYPE_UUID - // Pass if this item is the target UUID or if it links to the target UUID - if (filterTypes & FILTERTYPE_UUID) - { - if (!item) return false; - - if (item->getLinkedUUID() != mFilterOps.mFilterUUID) - return false; - } - - //////////////////////////////////////////////////////////////////////////////// - // FILTERTYPE_DATE - // Pass if this item is within the date range. - if (filterTypes & FILTERTYPE_DATE) - { - // We don't get the updated item creation date for the task inventory or - // a notecard embedded item. See LLTaskInvFVBridge::getCreationDate(). - return false; - } - - return true; -} - -// Items and folders that are on the clipboard or, recursively, in a folder which -// is on the clipboard must be filtered out if the clipboard is in the "cut" mode. -bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const -{ - if (LLClipboard::instance().isCutMode()) - { - LL_PROFILE_ZONE_SCOPED; - LLUUID current_id = object_id; - LLInventoryObject *current_object = gInventory.getObject(object_id); - while (current_id.notNull() && current_object) - { - if (LLClipboard::instance().isOnClipboard(current_id)) - { - return false; - } - current_id = current_object->getParentUUID(); - if (current_id.notNull()) - { - current_object = gInventory.getObject(current_id); - } - } - } - return true; -} - -bool LLInventoryFilter::checkAgainstPermissions(const LLFolderViewModelItemInventory* listener) const -{ - if (!listener) return false; - - PermissionMask perm = listener->getPermissionMask(); - const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(listener); - if (bridge && bridge->isLink()) - { - const LLUUID& linked_uuid = gInventory.getLinkedItemID(bridge->getUUID()); - const LLViewerInventoryItem *linked_item = gInventory.getItem(linked_uuid); - if (linked_item) - perm = linked_item->getPermissionMask(); - } - return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions; -} - -bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) const -{ - if (!item) return false; - - LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); - PermissionMask perm = new_item->getPermissionMask(); - new_item = NULL; - - return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions; -} - -bool LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewModelItemInventory* listener) const -{ - if (!listener) return true; - - const LLUUID object_id = listener->getUUID(); - const LLInventoryObject *object = gInventory.getObject(object_id); - if (!object) return true; - - const bool is_link = object->getIsLinkType(); - if (is_link && (mFilterOps.mFilterLinks == FILTERLINK_EXCLUDE_LINKS)) - return false; - if (!is_link && (mFilterOps.mFilterLinks == FILTERLINK_ONLY_LINKS)) - return false; - return true; -} - -bool LLInventoryFilter::checkAgainstFilterThumbnails(const LLUUID& object_id) const -{ - const LLInventoryObject *object = gInventory.getObject(object_id); - if (!object) return true; - - const bool is_thumbnail = object->getThumbnailUUID().notNull(); - if (is_thumbnail && (mFilterOps.mFilterThumbnails == FILTER_EXCLUDE_THUMBNAILS)) - return false; - if (!is_thumbnail && (mFilterOps.mFilterThumbnails == FILTER_ONLY_THUMBNAILS)) - return false; - return true; -} - -bool LLInventoryFilter::checkAgainstCreator(const LLFolderViewModelItemInventory* listener) const -{ - if (!listener) return true; - const bool is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY; - switch (mFilterOps.mFilterCreatorType) - { - case FILTERCREATOR_SELF: - if(is_folder) return false; - return (listener->getSearchableCreatorName() == mUsername); - case FILTERCREATOR_OTHERS: - if(is_folder) return false; - return (listener->getSearchableCreatorName() != mUsername); - case FILTERCREATOR_ALL: - default: - return true; - } -} - -bool LLInventoryFilter::checkAgainstSearchVisibility(const LLFolderViewModelItemInventory* listener) const -{ - if (!listener || !hasFilterString()) return true; - - const LLUUID object_id = listener->getUUID(); - const LLInventoryObject *object = gInventory.getObject(object_id); - if (!object) return true; - - const bool is_link = object->getIsLinkType(); - if (is_link && ((mFilterOps.mSearchVisibility & VISIBILITY_LINKS) == 0)) - return false; - - if (listener->isItemInOutfits() && ((mFilterOps.mSearchVisibility & VISIBILITY_OUTFITS) == 0)) - return false; - - if (listener->isItemInTrash() && ((mFilterOps.mSearchVisibility & VISIBILITY_TRASH) == 0)) - return false; - - if (!listener->isAgentInventory() && ((mFilterOps.mSearchVisibility & VISIBILITY_LIBRARY) == 0)) - return false; - - return true; -} - -const std::string& LLInventoryFilter::getFilterSubString(bool trim) const -{ - return mFilterSubString; -} - -std::string::size_type LLInventoryFilter::getStringMatchOffset(LLFolderViewModelItem* item) const -{ - if (mSearchType == SEARCHTYPE_NAME) - { - return mFilterSubString.size() ? item->getSearchableName().find(mFilterSubString) : std::string::npos; - } - else - { - return std::string::npos; - } -} - -bool LLInventoryFilter::isDefault() const -{ - return !isNotDefault(); -} - -// has user modified default filter params? -bool LLInventoryFilter::isNotDefault() const -{ - S32 not_default = 0; - - not_default |= (mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes); - not_default |= (mFilterOps.mFilterCategoryTypes != mDefaultFilterOps.mFilterCategoryTypes); - not_default |= (mFilterOps.mFilterWearableTypes != mDefaultFilterOps.mFilterWearableTypes); - not_default |= (mFilterOps.mFilterTypes != mDefaultFilterOps.mFilterTypes); - not_default |= (mFilterOps.mFilterLinks != mDefaultFilterOps.mFilterLinks); - not_default |= (mFilterSubString.size()); - not_default |= (mFilterOps.mPermissions != mDefaultFilterOps.mPermissions); - not_default |= (mFilterOps.mMinDate != mDefaultFilterOps.mMinDate); - not_default |= (mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate); - not_default |= (mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo); - - return not_default != 0; -} - -bool LLInventoryFilter::isActive() const -{ - return mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL - || mFilterOps.mFilterCategoryTypes != 0xffffffffffffffffULL - || mFilterOps.mFilterWearableTypes != 0xffffffffffffffffULL - || mFilterOps.mFilterTypes != FILTERTYPE_OBJECT - || mFilterOps.mFilterLinks != FILTERLINK_INCLUDE_LINKS - || mFilterSubString.size() - || mFilterOps.mPermissions != PERM_NONE - || mFilterOps.mMinDate != time_min() - || mFilterOps.mMaxDate != time_max() - || mFilterOps.mHoursAgo != 0; -} - -bool LLInventoryFilter::isModified() const -{ - return mFilterModified != FILTER_NONE; -} - -void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types) -{ - if (current_types != types) - { - // keep current items only if no type bits getting turned off - bool fewer_bits_set = (current_types & ~types) != 0; - bool more_bits_set = (~current_types & types) != 0; - - current_types = types; - if (more_bits_set && fewer_bits_set) - { - // neither less or more restrictive, 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::setSearchType(ESearchType type) -{ - if(mSearchType != type) - { - mSearchType = type; - setModified(); - } -} - -void LLInventoryFilter::setFilterCreator(EFilterCreatorType type) -{ - if (mFilterOps.mFilterCreatorType != type) - { - mFilterOps.mFilterCreatorType = type; - setModified(); - } -} - -void LLInventoryFilter::setFilterObjectTypes(U64 types) -{ - updateFilterTypes(types, mFilterOps.mFilterObjectTypes); - mFilterOps.mFilterTypes |= FILTERTYPE_OBJECT; -} - -void LLInventoryFilter::setFilterCategoryTypes(U64 types) -{ - updateFilterTypes(types, mFilterOps.mFilterCategoryTypes); - mFilterOps.mFilterTypes |= FILTERTYPE_CATEGORY; -} - -void LLInventoryFilter::setFilterWearableTypes(U64 types) -{ - updateFilterTypes(types, mFilterOps.mFilterWearableTypes); - mFilterOps.mFilterTypes |= FILTERTYPE_WEARABLE; -} - -void LLInventoryFilter::setFilterSettingsTypes(U64 types) -{ - updateFilterTypes(types, mFilterOps.mFilterSettingsTypes); - mFilterOps.mFilterTypes |= FILTERTYPE_SETTINGS; -} - -void LLInventoryFilter::setFilterThumbnails(U64 filter_thumbnails) -{ - if (mFilterOps.mFilterThumbnails != filter_thumbnails) - { - if (mFilterOps.mFilterThumbnails == FILTER_EXCLUDE_THUMBNAILS - && filter_thumbnails == FILTER_ONLY_THUMBNAILS) - { - setModified(FILTER_RESTART); - } - else if (mFilterOps.mFilterThumbnails == FILTER_ONLY_THUMBNAILS - && filter_thumbnails == FILTER_EXCLUDE_THUMBNAILS) - { - setModified(FILTER_RESTART); - } - else if (mFilterOps.mFilterThumbnails == FILTER_INCLUDE_THUMBNAILS) - { - setModified(FILTER_MORE_RESTRICTIVE); - } - else - { - setModified(FILTER_LESS_RESTRICTIVE); - } - } - mFilterOps.mFilterThumbnails = filter_thumbnails; -} - -void LLInventoryFilter::setFilterEmptySystemFolders() -{ - mFilterOps.mFilterTypes |= FILTERTYPE_EMPTYFOLDERS; -} - -void LLInventoryFilter::setFilterWorn() -{ - mFilterOps.mFilterTypes |= FILTERTYPE_WORN; -} - -void LLInventoryFilter::setFilterMarketplaceActiveFolders() -{ - mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_ACTIVE; -} - -void LLInventoryFilter::setFilterMarketplaceInactiveFolders() -{ - mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_INACTIVE; -} - -void LLInventoryFilter::setFilterMarketplaceUnassociatedFolders() -{ - mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_UNASSOCIATED; -} - -void LLInventoryFilter::setFilterMarketplaceListingFolders(bool select_only_listing_folders) -{ - if (select_only_listing_folders) - { - mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_LISTING_FOLDER; - setModified(FILTER_MORE_RESTRICTIVE); - } - else - { - mFilterOps.mFilterTypes &= ~FILTERTYPE_MARKETPLACE_LISTING_FOLDER; - setModified(FILTER_LESS_RESTRICTIVE); - } -} - - -void LLInventoryFilter::toggleSearchVisibilityLinks() -{ - bool hide_links = mFilterOps.mSearchVisibility & VISIBILITY_LINKS; - if (hide_links) - { - mFilterOps.mSearchVisibility &= ~VISIBILITY_LINKS; - } - else - { - mFilterOps.mSearchVisibility |= VISIBILITY_LINKS; - } - - if (hasFilterString()) - { - setModified(hide_links ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE); - } -} - -void LLInventoryFilter::toggleSearchVisibilityOutfits() -{ - bool hide_outfits = mFilterOps.mSearchVisibility & VISIBILITY_OUTFITS; - if (hide_outfits) - { - mFilterOps.mSearchVisibility &= ~VISIBILITY_OUTFITS; - } - else - { - mFilterOps.mSearchVisibility |= VISIBILITY_OUTFITS; - } - - if (hasFilterString()) - { - setModified(hide_outfits ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE); - } -} - -void LLInventoryFilter::toggleSearchVisibilityTrash() -{ - bool hide_trash = mFilterOps.mSearchVisibility & VISIBILITY_TRASH; - if (hide_trash) - { - mFilterOps.mSearchVisibility &= ~VISIBILITY_TRASH; - } - else - { - mFilterOps.mSearchVisibility |= VISIBILITY_TRASH; - } - - if (hasFilterString()) - { - setModified(hide_trash ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE); - } -} - -void LLInventoryFilter::toggleSearchVisibilityLibrary() -{ - bool hide_library = mFilterOps.mSearchVisibility & VISIBILITY_LIBRARY; - if (hide_library) - { - mFilterOps.mSearchVisibility &= ~VISIBILITY_LIBRARY; - } - else - { - mFilterOps.mSearchVisibility |= VISIBILITY_LIBRARY; - } - - if (hasFilterString()) - { - setModified(hide_library ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE); - } -} - -void LLInventoryFilter::setFilterNoMarketplaceFolder() -{ - mFilterOps.mFilterTypes |= FILTERTYPE_NO_MARKETPLACE_ITEMS; -} - -void LLInventoryFilter::setFilterUUID(const LLUUID& object_id) -{ - if (mFilterOps.mFilterUUID == LLUUID::null) - { - setModified(FILTER_MORE_RESTRICTIVE); - } - else - { - setModified(FILTER_RESTART); - } - mFilterOps.mFilterUUID = object_id; - mFilterOps.mFilterTypes = FILTERTYPE_UUID; -} - -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) - { - - mFilterTokens.clear(); - if (filter_sub_string_new.find_first_of("+") != std::string::npos) - { - typedef boost::tokenizer<boost::char_separator<char> > tokenizer; - boost::char_separator<char> sep("+"); - tokenizer tokens(filter_sub_string_new, sep); - - for (auto token_iter : tokens) - { - mFilterTokens.push_back(token_iter); - } - } - - std::string old_token = mExactToken; - mExactToken.clear(); - bool exact_token_changed = false; - if (mFilterTokens.empty() && filter_sub_string_new.size() > 2) - { - boost::regex mPattern = boost::regex("\"\\s*([^<]*)?\\s*\"", - boost::regex::perl | boost::regex::icase); - boost::match_results<std::string::const_iterator> matches; - mExactToken = (ll_regex_match(filter_sub_string_new, matches, mPattern) && matches[1].matched) - ? matches[1] - : LLStringUtil::null; - if ((old_token.empty() && !mExactToken.empty()) - || (!old_token.empty() && mExactToken.empty())) - { - exact_token_changed = true; - } - } - - // 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 (exact_token_changed) - { - setModified(FILTER_RESTART); - } - else if (less_restrictive) - { - setModified(FILTER_LESS_RESTRICTIVE); - } - else if (more_restrictive) - { - setModified(FILTER_MORE_RESTRICTIVE); - } - else - { - setModified(FILTER_RESTART); - } - - // Cancel out filter links once the search string is modified - if (mFilterOps.mFilterLinks == FILTERLINK_ONLY_LINKS) - { - if (mBackupFilterOps.mFilterLinks == FILTERLINK_ONLY_LINKS) - { - // we started viewer/floater in 'only links' mode - mFilterOps.mFilterLinks = FILTERLINK_INCLUDE_LINKS; - } - else - { - mFilterOps = mBackupFilterOps; - setModified(FILTER_RESTART); - } - } - - // Cancel out UUID once the search string is modified - if (mFilterOps.mFilterTypes == FILTERTYPE_UUID) - { - mFilterOps.mFilterTypes &= ~FILTERTYPE_UUID; - mFilterOps.mFilterUUID = LLUUID::null; - setModified(FILTER_RESTART); - } - } -} - -void LLInventoryFilter::setSearchVisibilityTypes(U32 types) -{ - if (mFilterOps.mSearchVisibility != types) - { - // keep current items only if no perm bits getting turned off - bool fewer_bits_set = (mFilterOps.mSearchVisibility & ~types); - bool more_bits_set = (~mFilterOps.mSearchVisibility & types); - mFilterOps.mSearchVisibility = types; - - 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::setSearchVisibilityTypes(const Params& params) -{ - if (!params.validateBlock()) - { - return; - } - - if (params.filter_ops.search_visibility.isProvided()) - { - setSearchVisibilityTypes(params.filter_ops.search_visibility); - } -} - -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(); - } - - if (areDateLimitsSet()) - { - mFilterOps.mFilterTypes |= FILTERTYPE_DATE; - } - else - { - mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE; - } -} - -void LLInventoryFilter::setDateRangeLastLogoff(bool sl) -{ - static LLCachedControl<U32> s_last_logoff(gSavedPerAccountSettings, "LastLogoff", 0); - if (sl && !isSinceLogoff()) - { - setDateRange(s_last_logoff(), time_max()); - setModified(); - } - if (!sl && isSinceLogoff()) - { - setDateRange(time_min(), time_max()); - setModified(); - } - - if (areDateLimitsSet()) - { - mFilterOps.mFilterTypes |= FILTERTYPE_DATE; - } - else - { - mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE; - } -} - -bool LLInventoryFilter::isSinceLogoff() const -{ - static LLCachedControl<U32> s_last_logoff(gSavedSettings, "LastLogoff", 0); - - return (mFilterOps.mMinDate == (time_t)s_last_logoff()) && - (mFilterOps.mMaxDate == time_max()) && - (mFilterOps.mFilterTypes & FILTERTYPE_DATE); -} - -void LLInventoryFilter::clearModified() -{ - mFilterModified = 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_decreasing = hours < mFilterOps.mHoursAgo; - bool is_increasing_from_zero = is_increasing && !mFilterOps.mHoursAgo && !isSinceLogoff(); - - // *NOTE: need to cache last filter time, in case filter goes stale - bool less_restrictive; - bool more_restrictive; - if (FILTERDATEDIRECTION_NEWER == mFilterOps.mDateSearchDirection) - { - less_restrictive = ((are_date_limits_valid && ((is_increasing && mFilterOps.mHoursAgo))) || !hours); - more_restrictive = ((are_date_limits_valid && (!is_increasing && hours)) || is_increasing_from_zero); - } - else - { - less_restrictive = ((are_date_limits_valid && ((is_decreasing && mFilterOps.mHoursAgo))) || !hours); - more_restrictive = ((are_date_limits_valid && (!is_decreasing && 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); - } - } - - if (areDateLimitsSet()) - { - mFilterOps.mFilterTypes |= FILTERTYPE_DATE; - } - else - { - mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE; - } -} - -void LLInventoryFilter::setDateSearchDirection(U32 direction) -{ - if (direction != mFilterOps.mDateSearchDirection) - { - mFilterOps.mDateSearchDirection = direction; - setModified(FILTER_RESTART); - } -} - -U32 LLInventoryFilter::getDateSearchDirection() const -{ - return mFilterOps.mDateSearchDirection; -} - -void LLInventoryFilter::setFilterLinks(U64 filter_links) -{ - if (mFilterOps.mFilterLinks != filter_links) - { - if (mFilterOps.mFilterLinks == FILTERLINK_EXCLUDE_LINKS || - mFilterOps.mFilterLinks == FILTERLINK_ONLY_LINKS) - setModified(FILTER_MORE_RESTRICTIVE); - else - setModified(FILTER_LESS_RESTRICTIVE); - } - mFilterOps.mFilterLinks = filter_links; -} - -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::setFindAllLinksMode(const std::string &search_name, const LLUUID& search_id) -{ - // Save a copy of settings so that we will be able to restore it later - // but make sure we are not searching for links already - if(mFilterOps.mFilterLinks != FILTERLINK_ONLY_LINKS) - { - mBackupFilterOps = mFilterOps; - } - - // set search options - setFilterSubString(search_name); - setFilterUUID(search_id); - setShowFolderState(SHOW_NON_EMPTY_FOLDERS); - setFilterLinks(FILTERLINK_ONLY_LINKS); -} - -void LLInventoryFilter::markDefault() -{ - mDefaultFilterOps = mFilterOps; -} - -void LLInventoryFilter::resetDefault() -{ - mFilterOps = mDefaultFilterOps; - setModified(); -} - -void LLInventoryFilter::setModified(EFilterModified behavior) -{ - mFilterText.clear(); - mCurrentGeneration++; - - if (mFilterModified == FILTER_NONE) - { - mFilterModified = behavior; - } - else if (mFilterModified != behavior) - { - // trying to do both less restrictive and more restrictive filter - // basically means restart from scratch - mFilterModified = FILTER_RESTART; - } - - // if not keeping current filter results, update last valid as well - switch(mFilterModified) - { - case FILTER_RESTART: - mFirstRequiredGeneration = mCurrentGeneration; - mFirstSuccessGeneration = mCurrentGeneration; - break; - case FILTER_LESS_RESTRICTIVE: - mFirstRequiredGeneration = mCurrentGeneration; - break; - case FILTER_MORE_RESTRICTIVE: - mFirstSuccessGeneration = mCurrentGeneration; - break; - default: - LL_ERRS() << "Bad filter behavior specified" << LL_ENDL; - } -} - -bool LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const -{ - return mFilterOps.mFilterObjectTypes & (1LL << t); -} - -const std::string& LLInventoryFilter::getFilterText() -{ - if (!mFilterText.empty()) - { - return mFilterText; - } - - 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 (isFilterObjectTypesWith(LLInventoryType::IT_ANIMATION)) - { - filtered_types += LLTrans::getString("Animations"); - filtered_by_type = true; - num_filter_types++; - } - else - { - not_filtered_types += LLTrans::getString("Animations"); - - filtered_by_all_types = false; - } - - if (isFilterObjectTypesWith(LLInventoryType::IT_CALLINGCARD)) - { - filtered_types += LLTrans::getString("Calling Cards"); - filtered_by_type = true; - num_filter_types++; - } - else - { - not_filtered_types += LLTrans::getString("Calling Cards"); - filtered_by_all_types = false; - } - - if (isFilterObjectTypesWith(LLInventoryType::IT_WEARABLE)) - { - filtered_types += LLTrans::getString("Clothing"); - filtered_by_type = true; - num_filter_types++; - } - else - { - not_filtered_types += LLTrans::getString("Clothing"); - filtered_by_all_types = false; - } - - if (isFilterObjectTypesWith(LLInventoryType::IT_GESTURE)) - { - filtered_types += LLTrans::getString("Gestures"); - filtered_by_type = true; - num_filter_types++; - } - else - { - not_filtered_types += LLTrans::getString("Gestures"); - filtered_by_all_types = false; - } - - if (isFilterObjectTypesWith(LLInventoryType::IT_LANDMARK)) - { - filtered_types += LLTrans::getString("Landmarks"); - filtered_by_type = true; - num_filter_types++; - } - else - { - not_filtered_types += LLTrans::getString("Landmarks"); - filtered_by_all_types = false; - } - - if (isFilterObjectTypesWith(LLInventoryType::IT_MATERIAL)) - { - filtered_types += LLTrans::getString("Materials"); - filtered_by_type = true; - num_filter_types++; - } - else - { - not_filtered_types += LLTrans::getString("Materials"); - filtered_by_all_types = false; - } - - if (isFilterObjectTypesWith(LLInventoryType::IT_NOTECARD)) - { - filtered_types += LLTrans::getString("Notecards"); - filtered_by_type = true; - num_filter_types++; - } - else - { - not_filtered_types += LLTrans::getString("Notecards"); - filtered_by_all_types = false; - } - - if (isFilterObjectTypesWith(LLInventoryType::IT_OBJECT) && isFilterObjectTypesWith(LLInventoryType::IT_ATTACHMENT)) - { - filtered_types += LLTrans::getString("Objects"); - filtered_by_type = true; - num_filter_types++; - } - else - { - not_filtered_types += LLTrans::getString("Objects"); - filtered_by_all_types = false; - } - - if (isFilterObjectTypesWith(LLInventoryType::IT_LSL)) - { - filtered_types += LLTrans::getString("Scripts"); - filtered_by_type = true; - num_filter_types++; - } - else - { - not_filtered_types += LLTrans::getString("Scripts"); - filtered_by_all_types = false; - } - - if (isFilterObjectTypesWith(LLInventoryType::IT_SOUND)) - { - filtered_types += LLTrans::getString("Sounds"); - filtered_by_type = true; - num_filter_types++; - } - else - { - not_filtered_types += LLTrans::getString("Sounds"); - filtered_by_all_types = false; - } - - if (isFilterObjectTypesWith(LLInventoryType::IT_TEXTURE)) - { - filtered_types += LLTrans::getString("Textures"); - filtered_by_type = true; - num_filter_types++; - } - else - { - not_filtered_types += LLTrans::getString("Textures"); - filtered_by_all_types = false; - } - - if (isFilterObjectTypesWith(LLInventoryType::IT_SNAPSHOT)) - { - filtered_types += LLTrans::getString("Snapshots"); - filtered_by_type = true; - num_filter_types++; - } - else - { - not_filtered_types += LLTrans::getString("Snapshots"); - filtered_by_all_types = false; - } - - if (isFilterObjectTypesWith(LLInventoryType::IT_SETTINGS)) - { - filtered_types += LLTrans::getString("Settings"); - filtered_by_type = true; - num_filter_types++; - } - else - { - not_filtered_types += LLTrans::getString("Settings"); - filtered_by_all_types = false; - } - - if (!LLInventoryModelBackgroundFetch::instance().folderFetchActive() - && filtered_by_type - && !filtered_by_all_types) - { - mFilterText += " - "; - if (num_filter_types < 5) - { - mFilterText += filtered_types; - } - else - { - mFilterText += LLTrans::getString("No Filters"); - mFilterText += not_filtered_types; - } - // remove the ',' at the end - mFilterText.erase(mFilterText.size() - 1, 1); - } - - if (isSinceLogoff()) - { - mFilterText += LLTrans::getString("Since Logoff"); - } - return mFilterText; -} - - -LLInventoryFilter& LLInventoryFilter::operator=( const LLInventoryFilter& other ) -{ - setFilterObjectTypes(other.getFilterObjectTypes()); - setDateRange(other.getMinDate(), other.getMaxDate()); - setHoursAgo(other.getHoursAgo()); - setDateSearchDirection(other.getDateSearchDirection()); - setShowFolderState(other.getShowFolderState()); - setFilterPermissions(other.getFilterPermissions()); - setFilterSubString(other.getFilterSubString()); - setDateRangeLastLogoff(other.isSinceLogoff()); - return *this; -} - - -void LLInventoryFilter::toParams(Params& params) const -{ - params.filter_ops.types = getFilterObjectTypes(); - params.filter_ops.category_types = getFilterCategoryTypes(); - if (getFilterObjectTypes() & FILTERTYPE_WEARABLE) - { - params.filter_ops.wearable_types = getFilterWearableTypes(); - } - params.filter_ops.date_range.min_date = getMinDate(); - params.filter_ops.date_range.max_date = getMaxDate(); - params.filter_ops.hours_ago = getHoursAgo(); - params.filter_ops.date_search_direction = getDateSearchDirection(); - params.filter_ops.show_folder_state = getShowFolderState(); - params.filter_ops.creator_type = getFilterCreatorType(); - params.filter_ops.permissions = getFilterPermissions(); - params.filter_ops.search_visibility = getSearchVisibilityTypes(); - params.substring = getFilterSubString(); - params.since_logoff = isSinceLogoff(); -} - -void LLInventoryFilter::fromParams(const Params& params) -{ - if (!params.validateBlock()) - { - return; - } - - setFilterObjectTypes(params.filter_ops.types); - setFilterCategoryTypes(params.filter_ops.category_types); - if (params.filter_ops.wearable_types.isProvided()) - { - setFilterWearableTypes(params.filter_ops.wearable_types); - } - setDateRange(params.filter_ops.date_range.min_date, params.filter_ops.date_range.max_date); - setHoursAgo(params.filter_ops.hours_ago); - setDateSearchDirection(params.filter_ops.date_search_direction); - setShowFolderState(params.filter_ops.show_folder_state); - setFilterCreator(params.filter_ops.creator_type); - setFilterPermissions(params.filter_ops.permissions); - setSearchVisibilityTypes(params.filter_ops.search_visibility); - setFilterSubString(params.substring); - setDateRangeLastLogoff(params.since_logoff); -} - -U64 LLInventoryFilter::getFilterTypes() const -{ - return mFilterOps.mFilterTypes; -} - -U64 LLInventoryFilter::getFilterObjectTypes() const -{ - return mFilterOps.mFilterObjectTypes; -} - -U64 LLInventoryFilter::getFilterCategoryTypes() const -{ - return mFilterOps.mFilterCategoryTypes; -} - -U64 LLInventoryFilter::getFilterWearableTypes() const -{ - return mFilterOps.mFilterWearableTypes; -} - -U64 LLInventoryFilter::getFilterSettingsTypes() const -{ - return mFilterOps.mFilterSettingsTypes; -} - -U64 LLInventoryFilter::getSearchVisibilityTypes() const -{ - return mFilterOps.mSearchVisibility; -} - -U64 LLInventoryFilter::getFilterThumbnails() const -{ - return mFilterOps.mFilterThumbnails; -} - -bool LLInventoryFilter::hasFilterString() const -{ - return mFilterSubString.size() > 0; -} - -std::string::size_type LLInventoryFilter::getFilterStringSize() const -{ - return mFilterSubString.size(); -} - -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; -} -U64 LLInventoryFilter::getFilterLinks() const -{ - return mFilterOps.mFilterLinks; -} -LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const -{ - return mFilterOps.mShowFolderState; -} - -LLInventoryFilter::EFilterCreatorType LLInventoryFilter::getFilterCreatorType() const -{ - return mFilterOps.mFilterCreatorType; -} - -bool LLInventoryFilter::isTimedOut() -{ - return mFilterTime.hasExpired(); -} - -void LLInventoryFilter::resetTime(S32 timeout) -{ - mFilterTime.reset(); - F32 time_in_sec = (F32)(timeout)/1000.0; - mFilterTime.setTimerExpirySec(time_in_sec); -} - -S32 LLInventoryFilter::getCurrentGeneration() const -{ - return mCurrentGeneration; -} -S32 LLInventoryFilter::getFirstSuccessGeneration() const -{ - return mFirstSuccessGeneration; -} -S32 LLInventoryFilter::getFirstRequiredGeneration() const -{ - return mFirstRequiredGeneration; -} - -void LLInventoryFilter::setEmptyLookupMessage(const std::string& message) -{ - mEmptyLookupMessage = message; -} - -void LLInventoryFilter::setDefaultEmptyLookupMessage(const std::string& message) -{ - mDefaultEmptyLookupMessage = message; -} - -std::string LLInventoryFilter::getEmptyLookupMessage(bool is_empty_folder) const -{ - if ((isDefault() || is_empty_folder) && !mDefaultEmptyLookupMessage.empty()) - { - return LLTrans::getString(mDefaultEmptyLookupMessage); - } - else - { - LLStringUtil::format_map_t args; - args["[SEARCH_TERM]"] = LLURI::escape(getFilterSubStringOrig()); - - return LLTrans::getString(mEmptyLookupMessage, args); - } - -} - -bool LLInventoryFilter::areDateLimitsSet() -{ - return mFilterOps.mMinDate != time_min() - || mFilterOps.mMaxDate != time_max() - || mFilterOps.mHoursAgo != 0; -} - -bool LLInventoryFilter::showAllResults() const -{ - return hasFilterString() && !mSingleFolderMode; -} - - - -bool LLInventoryFilter::FilterOps::DateRange::validateBlock( bool emit_errors /*= true*/ ) const -{ - bool valid = LLInitParam::Block<DateRange>::validateBlock(emit_errors); - if (valid) - { - if (max_date() < min_date()) - { - if (emit_errors) - { - LL_WARNS() << "max_date should be greater or equal to min_date" << LL_ENDL; - } - valid = false; - } - } - return valid; -} +/**
+* @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 "llagent.h"
+#include "llfolderviewmodel.h"
+#include "llfolderviewitem.h"
+#include "llinventorymodel.h"
+#include "llinventorymodelbackgroundfetch.h"
+#include "llinventoryfunctions.h"
+#include "llmarketplacefunctions.h"
+#include "llregex.h"
+#include "llviewercontrol.h"
+#include "llfolderview.h"
+#include "llinventorybridge.h"
+#include "llviewerfoldertype.h"
+#include "llradiogroup.h"
+#include "llstartup.h"
+
+// linden library includes
+#include "llclipboard.h"
+#include "lltrans.h"
+
+LLInventoryFilter::FilterOps::FilterOps(const Params& p)
+: mFilterObjectTypes(p.object_types),
+ mFilterCategoryTypes(p.category_types),
+ mFilterWearableTypes(p.wearable_types),
+ mFilterSettingsTypes(p.settings_types),
+ mMinDate(p.date_range.min_date),
+ mMaxDate(p.date_range.max_date),
+ mHoursAgo(p.hours_ago),
+ mDateSearchDirection(p.date_search_direction),
+ mShowFolderState(p.show_folder_state),
+ mFilterCreatorType(p.creator_type),
+ mPermissions(p.permissions),
+ mFilterTypes(p.types),
+ mFilterUUID(p.uuid),
+ mFilterLinks(p.links),
+ mFilterThumbnails(p.thumbnails),
+ mSearchVisibility(p.search_visibility)
+{
+}
+
+///----------------------------------------------------------------------------
+/// Class LLInventoryFilter
+///----------------------------------------------------------------------------
+LLInventoryFilter::LLInventoryFilter(const Params& p)
+: mName(p.name),
+ mFilterModified(FILTER_NONE),
+ mEmptyLookupMessage("InventoryNoMatchingItems"),
+ mDefaultEmptyLookupMessage(""),
+ mFilterOps(p.filter_ops),
+ mBackupFilterOps(mFilterOps),
+ mFilterSubString(p.substring),
+ mCurrentGeneration(0),
+ mFirstRequiredGeneration(0),
+ mFirstSuccessGeneration(0),
+ mSearchType(SEARCHTYPE_NAME),
+ mSingleFolderMode(false)
+{
+ // copy mFilterOps into mDefaultFilterOps
+ markDefault();
+ mUsername = gAgentUsername;
+ LLStringUtil::toUpper(mUsername);
+}
+
+bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
+{
+ const LLFolderViewModelItemInventory* listener = dynamic_cast<const LLFolderViewModelItemInventory*>(item);
+
+ // If it's a folder and we're showing all folders, return automatically.
+ const bool is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY;
+ if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS))
+ {
+ return true;
+ }
+
+ std::string desc = listener->getSearchableCreatorName();
+ switch(mSearchType)
+ {
+ case SEARCHTYPE_CREATOR:
+ desc = listener->getSearchableCreatorName();
+ break;
+ case SEARCHTYPE_DESCRIPTION:
+ desc = listener->getSearchableDescription();
+ break;
+ case SEARCHTYPE_UUID:
+ desc = listener->getSearchableUUIDString();
+ break;
+ case SEARCHTYPE_NAME:
+ default:
+ desc = listener->getSearchableName();
+ break;
+ }
+
+
+ bool passed = true;
+ if (!mExactToken.empty() && (mSearchType == SEARCHTYPE_NAME))
+ {
+ passed = false;
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep(" ");
+ tokenizer tokens(desc, sep);
+
+ for (auto token_iter : tokens)
+ {
+ if (token_iter == mExactToken)
+ {
+ passed = true;
+ break;
+ }
+ }
+ }
+ else if ((mFilterTokens.size() > 0) && (mSearchType == SEARCHTYPE_NAME))
+ {
+ for (auto token_iter : mFilterTokens)
+ {
+ if (desc.find(token_iter) == std::string::npos)
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ passed = (mFilterSubString.size() ? desc.find(mFilterSubString) != std::string::npos : true);
+ }
+
+ passed = passed && checkAgainstFilterType(listener);
+ passed = passed && checkAgainstPermissions(listener);
+ passed = passed && checkAgainstFilterLinks(listener);
+ passed = passed && checkAgainstCreator(listener);
+ passed = passed && checkAgainstSearchVisibility(listener);
+
+ passed = passed && checkAgainstFilterThumbnails(listener->getUUID());
+
+ return passed;
+}
+
+bool LLInventoryFilter::check(const LLInventoryItem* item)
+{
+ const bool passed_string = (mFilterSubString.size() ? item->getName().find(mFilterSubString) != std::string::npos : true);
+ const bool passed_filtertype = checkAgainstFilterType(item);
+ const bool passed_permissions = checkAgainstPermissions(item);
+
+ return passed_filtertype && passed_permissions && passed_string;
+}
+
+bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const
+{
+ const LLFolderViewModelItemInventory* listener = dynamic_cast<const LLFolderViewModelItemInventory*>(item);
+ if (!listener)
+ {
+ LL_ERRS() << "Folder view event listener not found." << LL_ENDL;
+ return false;
+ }
+
+ const LLUUID folder_id = listener->getUUID();
+
+ return checkFolder(folder_id);
+}
+
+bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const
+{
+ // we're showing all folders, overriding filter
+ if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)
+ {
+ return true;
+ }
+
+ // when applying a filter, matching folders get their contents downloaded first
+ // but make sure we are not interfering with pre-download
+ if (isNotDefault()
+ && LLStartUp::getStartupState() > STATE_WEARABLES_WAIT
+ && !LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress())
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(folder_id);
+ if ((!cat && folder_id.notNull()))
+ {
+ // Shouldn't happen? Server provides full list of folders on startup
+ LLInventoryModelBackgroundFetch::instance().start(folder_id, false);
+ }
+ else if (cat && cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
+ {
+ // At the moment background fetch only cares about VERSION_UNKNOWN,
+ // so do not check isCategoryComplete that compares descendant count,
+ // but if that is nesesary, do a forced scheduleFolderFetch.
+ cat->fetch();
+ }
+ }
+
+ if (!checkAgainstFilterThumbnails(folder_id))
+ {
+ return false;
+ }
+
+ // Marketplace folder filtering
+ const U32 filterTypes = mFilterOps.mFilterTypes;
+ const U32 marketplace_filter = FILTERTYPE_MARKETPLACE_ACTIVE | FILTERTYPE_MARKETPLACE_INACTIVE |
+ FILTERTYPE_MARKETPLACE_UNASSOCIATED | FILTERTYPE_MARKETPLACE_LISTING_FOLDER |
+ FILTERTYPE_NO_MARKETPLACE_ITEMS;
+ if (filterTypes & marketplace_filter)
+ {
+ S32 depth = depth_nesting_in_marketplace(folder_id);
+
+ if (filterTypes & FILTERTYPE_NO_MARKETPLACE_ITEMS)
+ {
+ if (depth >= 0)
+ {
+ return false;
+ }
+ }
+
+ if (filterTypes & FILTERTYPE_MARKETPLACE_LISTING_FOLDER)
+ {
+ if (depth > 1)
+ {
+ return false;
+ }
+ }
+
+ if (depth > 0)
+ {
+ LLUUID listing_uuid = nested_parent_id(folder_id, depth);
+ if (filterTypes & FILTERTYPE_MARKETPLACE_ACTIVE)
+ {
+ if (!LLMarketplaceData::instance().getActivationState(listing_uuid))
+ {
+ return false;
+ }
+ }
+ else if (filterTypes & FILTERTYPE_MARKETPLACE_INACTIVE)
+ {
+ if (!LLMarketplaceData::instance().isListed(listing_uuid) || LLMarketplaceData::instance().getActivationState(listing_uuid))
+ {
+ return false;
+ }
+ }
+ else if (filterTypes & FILTERTYPE_MARKETPLACE_UNASSOCIATED)
+ {
+ if (LLMarketplaceData::instance().isListed(listing_uuid))
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ // show folder links
+ LLViewerInventoryItem* item = gInventory.getItem(folder_id);
+ if (item && item->getActualType() == LLAssetType::AT_LINK_FOLDER)
+ {
+ return true;
+ }
+
+ if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY)
+ {
+ // Can only filter categories for items in your inventory
+ // (e.g. versus in-world object contents).
+ const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id);
+ if (!cat)
+ return folder_id.isNull();
+ LLFolderType::EType cat_type = cat->getPreferredType();
+ if (cat_type != LLFolderType::FT_NONE && (1LL << cat_type & mFilterOps.mFilterCategoryTypes) == U64(0))
+ return false;
+ }
+
+ return true;
+}
+
+bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInventory* listener) const
+{
+ if (!listener) return false;
+
+ LLInventoryType::EType object_type = listener->getInventoryType();
+ const LLUUID object_id = listener->getUUID();
+ const LLInventoryObject *object = gInventory.getObject(object_id);
+
+ const U32 filterTypes = mFilterOps.mFilterTypes;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_OBJECT
+ // Pass if this item's type is of the correct filter type
+ if (filterTypes & FILTERTYPE_OBJECT)
+ {
+ switch (object_type)
+ {
+ case LLInventoryType::IT_NONE:
+ // If it has no type, pass it, unless it's a link.
+ if (object && object->getIsLinkType())
+ {
+ return false;
+ }
+ break;
+ case LLInventoryType::IT_UNKNOWN:
+ {
+ // Unknows are only shown when we show every type.
+ // Unknows are 255 and won't fit in 64 bits.
+ if (mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL)
+ {
+ return false;
+ }
+ break;
+ }
+ default:
+ if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0))
+ {
+ return false;
+ }
+ break;
+ }
+ }
+
+ if(filterTypes & FILTERTYPE_WORN)
+ {
+ if (!get_is_item_worn(object_id))
+ {
+ return false;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_UUID
+ // Pass if this item is the target UUID or if it links to the target UUID
+ if (filterTypes & FILTERTYPE_UUID)
+ {
+ if (!object) return false;
+
+ if (object->getLinkedUUID() != mFilterOps.mFilterUUID)
+ return false;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_DATE
+ // Pass if this item is within the date range.
+ if (filterTypes & FILTERTYPE_DATE)
+ {
+ const U16 HOURS_TO_SECONDS = 3600;
+ time_t earliest = time_corrected() - mFilterOps.mHoursAgo * HOURS_TO_SECONDS;
+
+ if (mFilterOps.mMinDate > time_min() && mFilterOps.mMinDate < earliest)
+ {
+ earliest = mFilterOps.mMinDate;
+ }
+ else if (!mFilterOps.mHoursAgo)
+ {
+ earliest = 0;
+ }
+
+ if (FILTERDATEDIRECTION_NEWER == mFilterOps.mDateSearchDirection || isSinceLogoff())
+ {
+ if (listener->getCreationDate() < earliest ||
+ listener->getCreationDate() > mFilterOps.mMaxDate)
+ return false;
+ }
+ else
+ {
+ if (listener->getCreationDate() > earliest ||
+ listener->getCreationDate() > mFilterOps.mMaxDate)
+ return false;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_WEARABLE
+ // Pass if this item is a wearable of the appropriate type
+ if (filterTypes & FILTERTYPE_WEARABLE)
+ {
+ LLWearableType::EType type = listener->getWearableType();
+ if ((object_type == LLInventoryType::IT_WEARABLE) &&
+ (((0x1LL << type) & mFilterOps.mFilterWearableTypes) == 0))
+ {
+ return false;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_SETTINGS
+ // Pass if this item is a setting of the appropriate type
+ if (filterTypes & FILTERTYPE_SETTINGS)
+ {
+ LLSettingsType::type_e type = listener->getSettingsType();
+ if ((object_type == LLInventoryType::IT_SETTINGS) &&
+ (((0x1LL << type) & mFilterOps.mFilterSettingsTypes) == 0))
+ {
+ return false;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_EMPTYFOLDERS
+ // Pass if this item is a folder and is not a system folder that should be hidden
+ if (filterTypes & FILTERTYPE_EMPTYFOLDERS)
+ {
+ if (object_type == LLInventoryType::IT_CATEGORY)
+ {
+ bool is_hidden_if_empty = LLViewerFolderType::lookupIsHiddenIfEmpty(listener->getPreferredType());
+ if (is_hidden_if_empty)
+ {
+ // Force the fetching of those folders so they are hidden if they really are empty...
+ // But don't interfere with startup download
+ if (LLStartUp::getStartupState() > STATE_WEARABLES_WAIT)
+ {
+ gInventory.fetchDescendentsOf(object_id);
+ }
+
+ LLInventoryModel::cat_array_t* cat_array = NULL;
+ LLInventoryModel::item_array_t* item_array = NULL;
+ gInventory.getDirectDescendentsOf(object_id,cat_array,item_array);
+ S32 descendents_actual = 0;
+ if(cat_array && item_array)
+ {
+ descendents_actual = cat_array->size() + item_array->size();
+ }
+ if (descendents_actual == 0)
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool LLInventoryFilter::checkAgainstFilterType(const LLInventoryItem* item) const
+{
+ LLInventoryType::EType object_type = item->getInventoryType();
+
+ const U32 filterTypes = mFilterOps.mFilterTypes;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_OBJECT
+ // Pass if this item's type is of the correct filter type
+ if (filterTypes & FILTERTYPE_OBJECT)
+ {
+ switch (object_type)
+ {
+ case LLInventoryType::IT_NONE:
+ // If it has no type, pass it, unless it's a link.
+ if (item && item->getIsLinkType())
+ {
+ return false;
+ }
+ break;
+ case LLInventoryType::IT_UNKNOWN:
+ {
+ // Unknows are only shown when we show every type.
+ // Unknows are 255 and won't fit in 64 bits.
+ if (mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL)
+ {
+ return false;
+ }
+ break;
+ }
+ default:
+ if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0))
+ {
+ return false;
+ }
+ break;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_UUID
+ // Pass if this item is the target UUID or if it links to the target UUID
+ if (filterTypes & FILTERTYPE_UUID)
+ {
+ if (!item) return false;
+
+ if (item->getLinkedUUID() != mFilterOps.mFilterUUID)
+ return false;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_DATE
+ // Pass if this item is within the date range.
+ if (filterTypes & FILTERTYPE_DATE)
+ {
+ // We don't get the updated item creation date for the task inventory or
+ // a notecard embedded item. See LLTaskInvFVBridge::getCreationDate().
+ return false;
+ }
+
+ return true;
+}
+
+// Items and folders that are on the clipboard or, recursively, in a folder which
+// is on the clipboard must be filtered out if the clipboard is in the "cut" mode.
+bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const
+{
+ if (LLClipboard::instance().isCutMode())
+ {
+ LL_PROFILE_ZONE_SCOPED;
+ LLUUID current_id = object_id;
+ LLInventoryObject *current_object = gInventory.getObject(object_id);
+ while (current_id.notNull() && current_object)
+ {
+ if (LLClipboard::instance().isOnClipboard(current_id))
+ {
+ return false;
+ }
+ current_id = current_object->getParentUUID();
+ if (current_id.notNull())
+ {
+ current_object = gInventory.getObject(current_id);
+ }
+ }
+ }
+ return true;
+}
+
+bool LLInventoryFilter::checkAgainstPermissions(const LLFolderViewModelItemInventory* listener) const
+{
+ if (!listener) return false;
+
+ PermissionMask perm = listener->getPermissionMask();
+ const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(listener);
+ if (bridge && bridge->isLink())
+ {
+ const LLUUID& linked_uuid = gInventory.getLinkedItemID(bridge->getUUID());
+ const LLViewerInventoryItem *linked_item = gInventory.getItem(linked_uuid);
+ if (linked_item)
+ perm = linked_item->getPermissionMask();
+ }
+ return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions;
+}
+
+bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) const
+{
+ if (!item) return false;
+
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ PermissionMask perm = new_item->getPermissionMask();
+ new_item = NULL;
+
+ return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions;
+}
+
+bool LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewModelItemInventory* listener) const
+{
+ if (!listener) return true;
+
+ const LLUUID object_id = listener->getUUID();
+ const LLInventoryObject *object = gInventory.getObject(object_id);
+ if (!object) return true;
+
+ const bool is_link = object->getIsLinkType();
+ if (is_link && (mFilterOps.mFilterLinks == FILTERLINK_EXCLUDE_LINKS))
+ return false;
+ if (!is_link && (mFilterOps.mFilterLinks == FILTERLINK_ONLY_LINKS))
+ return false;
+ return true;
+}
+
+bool LLInventoryFilter::checkAgainstFilterThumbnails(const LLUUID& object_id) const
+{
+ const LLInventoryObject *object = gInventory.getObject(object_id);
+ if (!object) return true;
+
+ const bool is_thumbnail = object->getThumbnailUUID().notNull();
+ if (is_thumbnail && (mFilterOps.mFilterThumbnails == FILTER_EXCLUDE_THUMBNAILS))
+ return false;
+ if (!is_thumbnail && (mFilterOps.mFilterThumbnails == FILTER_ONLY_THUMBNAILS))
+ return false;
+ return true;
+}
+
+bool LLInventoryFilter::checkAgainstCreator(const LLFolderViewModelItemInventory* listener) const
+{
+ if (!listener) return true;
+ const bool is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY;
+ switch (mFilterOps.mFilterCreatorType)
+ {
+ case FILTERCREATOR_SELF:
+ if(is_folder) return false;
+ return (listener->getSearchableCreatorName() == mUsername);
+ case FILTERCREATOR_OTHERS:
+ if(is_folder) return false;
+ return (listener->getSearchableCreatorName() != mUsername);
+ case FILTERCREATOR_ALL:
+ default:
+ return true;
+ }
+}
+
+bool LLInventoryFilter::checkAgainstSearchVisibility(const LLFolderViewModelItemInventory* listener) const
+{
+ if (!listener || !hasFilterString()) return true;
+
+ const LLUUID object_id = listener->getUUID();
+ const LLInventoryObject *object = gInventory.getObject(object_id);
+ if (!object) return true;
+
+ const bool is_link = object->getIsLinkType();
+ if (is_link && ((mFilterOps.mSearchVisibility & VISIBILITY_LINKS) == 0))
+ return false;
+
+ if (listener->isItemInOutfits() && ((mFilterOps.mSearchVisibility & VISIBILITY_OUTFITS) == 0))
+ return false;
+
+ if (listener->isItemInTrash() && ((mFilterOps.mSearchVisibility & VISIBILITY_TRASH) == 0))
+ return false;
+
+ if (!listener->isAgentInventory() && ((mFilterOps.mSearchVisibility & VISIBILITY_LIBRARY) == 0))
+ return false;
+
+ return true;
+}
+
+const std::string& LLInventoryFilter::getFilterSubString(bool trim) const
+{
+ return mFilterSubString;
+}
+
+std::string::size_type LLInventoryFilter::getStringMatchOffset(LLFolderViewModelItem* item) const
+{
+ if (mSearchType == SEARCHTYPE_NAME)
+ {
+ return mFilterSubString.size() ? item->getSearchableName().find(mFilterSubString) : std::string::npos;
+ }
+ else
+ {
+ return std::string::npos;
+ }
+}
+
+bool LLInventoryFilter::isDefault() const
+{
+ return !isNotDefault();
+}
+
+// has user modified default filter params?
+bool LLInventoryFilter::isNotDefault() const
+{
+ S32 not_default = 0;
+
+ not_default |= (mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes);
+ not_default |= (mFilterOps.mFilterCategoryTypes != mDefaultFilterOps.mFilterCategoryTypes);
+ not_default |= (mFilterOps.mFilterWearableTypes != mDefaultFilterOps.mFilterWearableTypes);
+ not_default |= (mFilterOps.mFilterTypes != mDefaultFilterOps.mFilterTypes);
+ not_default |= (mFilterOps.mFilterLinks != mDefaultFilterOps.mFilterLinks);
+ not_default |= (mFilterSubString.size());
+ not_default |= (mFilterOps.mPermissions != mDefaultFilterOps.mPermissions);
+ not_default |= (mFilterOps.mMinDate != mDefaultFilterOps.mMinDate);
+ not_default |= (mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate);
+ not_default |= (mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo);
+
+ return not_default != 0;
+}
+
+bool LLInventoryFilter::isActive() const
+{
+ return mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL
+ || mFilterOps.mFilterCategoryTypes != 0xffffffffffffffffULL
+ || mFilterOps.mFilterWearableTypes != 0xffffffffffffffffULL
+ || mFilterOps.mFilterTypes != FILTERTYPE_OBJECT
+ || mFilterOps.mFilterLinks != FILTERLINK_INCLUDE_LINKS
+ || mFilterSubString.size()
+ || mFilterOps.mPermissions != PERM_NONE
+ || mFilterOps.mMinDate != time_min()
+ || mFilterOps.mMaxDate != time_max()
+ || mFilterOps.mHoursAgo != 0;
+}
+
+bool LLInventoryFilter::isModified() const
+{
+ return mFilterModified != FILTER_NONE;
+}
+
+void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types)
+{
+ if (current_types != types)
+ {
+ // keep current items only if no type bits getting turned off
+ bool fewer_bits_set = (current_types & ~types) != 0;
+ bool more_bits_set = (~current_types & types) != 0;
+
+ current_types = types;
+ if (more_bits_set && fewer_bits_set)
+ {
+ // neither less or more restrictive, 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::setSearchType(ESearchType type)
+{
+ if(mSearchType != type)
+ {
+ mSearchType = type;
+ setModified();
+ }
+}
+
+void LLInventoryFilter::setFilterCreator(EFilterCreatorType type)
+{
+ if (mFilterOps.mFilterCreatorType != type)
+ {
+ mFilterOps.mFilterCreatorType = type;
+ setModified();
+ }
+}
+
+void LLInventoryFilter::setFilterObjectTypes(U64 types)
+{
+ updateFilterTypes(types, mFilterOps.mFilterObjectTypes);
+ mFilterOps.mFilterTypes |= FILTERTYPE_OBJECT;
+}
+
+void LLInventoryFilter::setFilterCategoryTypes(U64 types)
+{
+ updateFilterTypes(types, mFilterOps.mFilterCategoryTypes);
+ mFilterOps.mFilterTypes |= FILTERTYPE_CATEGORY;
+}
+
+void LLInventoryFilter::setFilterWearableTypes(U64 types)
+{
+ updateFilterTypes(types, mFilterOps.mFilterWearableTypes);
+ mFilterOps.mFilterTypes |= FILTERTYPE_WEARABLE;
+}
+
+void LLInventoryFilter::setFilterSettingsTypes(U64 types)
+{
+ updateFilterTypes(types, mFilterOps.mFilterSettingsTypes);
+ mFilterOps.mFilterTypes |= FILTERTYPE_SETTINGS;
+}
+
+void LLInventoryFilter::setFilterThumbnails(U64 filter_thumbnails)
+{
+ if (mFilterOps.mFilterThumbnails != filter_thumbnails)
+ {
+ if (mFilterOps.mFilterThumbnails == FILTER_EXCLUDE_THUMBNAILS
+ && filter_thumbnails == FILTER_ONLY_THUMBNAILS)
+ {
+ setModified(FILTER_RESTART);
+ }
+ else if (mFilterOps.mFilterThumbnails == FILTER_ONLY_THUMBNAILS
+ && filter_thumbnails == FILTER_EXCLUDE_THUMBNAILS)
+ {
+ setModified(FILTER_RESTART);
+ }
+ else if (mFilterOps.mFilterThumbnails == FILTER_INCLUDE_THUMBNAILS)
+ {
+ setModified(FILTER_MORE_RESTRICTIVE);
+ }
+ else
+ {
+ setModified(FILTER_LESS_RESTRICTIVE);
+ }
+ }
+ mFilterOps.mFilterThumbnails = filter_thumbnails;
+}
+
+void LLInventoryFilter::setFilterEmptySystemFolders()
+{
+ mFilterOps.mFilterTypes |= FILTERTYPE_EMPTYFOLDERS;
+}
+
+void LLInventoryFilter::setFilterWorn()
+{
+ mFilterOps.mFilterTypes |= FILTERTYPE_WORN;
+}
+
+void LLInventoryFilter::setFilterMarketplaceActiveFolders()
+{
+ mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_ACTIVE;
+}
+
+void LLInventoryFilter::setFilterMarketplaceInactiveFolders()
+{
+ mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_INACTIVE;
+}
+
+void LLInventoryFilter::setFilterMarketplaceUnassociatedFolders()
+{
+ mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_UNASSOCIATED;
+}
+
+void LLInventoryFilter::setFilterMarketplaceListingFolders(bool select_only_listing_folders)
+{
+ if (select_only_listing_folders)
+ {
+ mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_LISTING_FOLDER;
+ setModified(FILTER_MORE_RESTRICTIVE);
+ }
+ else
+ {
+ mFilterOps.mFilterTypes &= ~FILTERTYPE_MARKETPLACE_LISTING_FOLDER;
+ setModified(FILTER_LESS_RESTRICTIVE);
+ }
+}
+
+
+void LLInventoryFilter::toggleSearchVisibilityLinks()
+{
+ bool hide_links = mFilterOps.mSearchVisibility & VISIBILITY_LINKS;
+ if (hide_links)
+ {
+ mFilterOps.mSearchVisibility &= ~VISIBILITY_LINKS;
+ }
+ else
+ {
+ mFilterOps.mSearchVisibility |= VISIBILITY_LINKS;
+ }
+
+ if (hasFilterString())
+ {
+ setModified(hide_links ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE);
+ }
+}
+
+void LLInventoryFilter::toggleSearchVisibilityOutfits()
+{
+ bool hide_outfits = mFilterOps.mSearchVisibility & VISIBILITY_OUTFITS;
+ if (hide_outfits)
+ {
+ mFilterOps.mSearchVisibility &= ~VISIBILITY_OUTFITS;
+ }
+ else
+ {
+ mFilterOps.mSearchVisibility |= VISIBILITY_OUTFITS;
+ }
+
+ if (hasFilterString())
+ {
+ setModified(hide_outfits ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE);
+ }
+}
+
+void LLInventoryFilter::toggleSearchVisibilityTrash()
+{
+ bool hide_trash = mFilterOps.mSearchVisibility & VISIBILITY_TRASH;
+ if (hide_trash)
+ {
+ mFilterOps.mSearchVisibility &= ~VISIBILITY_TRASH;
+ }
+ else
+ {
+ mFilterOps.mSearchVisibility |= VISIBILITY_TRASH;
+ }
+
+ if (hasFilterString())
+ {
+ setModified(hide_trash ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE);
+ }
+}
+
+void LLInventoryFilter::toggleSearchVisibilityLibrary()
+{
+ bool hide_library = mFilterOps.mSearchVisibility & VISIBILITY_LIBRARY;
+ if (hide_library)
+ {
+ mFilterOps.mSearchVisibility &= ~VISIBILITY_LIBRARY;
+ }
+ else
+ {
+ mFilterOps.mSearchVisibility |= VISIBILITY_LIBRARY;
+ }
+
+ if (hasFilterString())
+ {
+ setModified(hide_library ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE);
+ }
+}
+
+void LLInventoryFilter::setFilterNoMarketplaceFolder()
+{
+ mFilterOps.mFilterTypes |= FILTERTYPE_NO_MARKETPLACE_ITEMS;
+}
+
+void LLInventoryFilter::setFilterUUID(const LLUUID& object_id)
+{
+ if (mFilterOps.mFilterUUID == LLUUID::null)
+ {
+ setModified(FILTER_MORE_RESTRICTIVE);
+ }
+ else
+ {
+ setModified(FILTER_RESTART);
+ }
+ mFilterOps.mFilterUUID = object_id;
+ mFilterOps.mFilterTypes = FILTERTYPE_UUID;
+}
+
+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)
+ {
+
+ mFilterTokens.clear();
+ if (filter_sub_string_new.find_first_of("+") != std::string::npos)
+ {
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep("+");
+ tokenizer tokens(filter_sub_string_new, sep);
+
+ for (auto token_iter : tokens)
+ {
+ mFilterTokens.push_back(token_iter);
+ }
+ }
+
+ std::string old_token = mExactToken;
+ mExactToken.clear();
+ bool exact_token_changed = false;
+ if (mFilterTokens.empty() && filter_sub_string_new.size() > 2)
+ {
+ boost::regex mPattern = boost::regex("\"\\s*([^<]*)?\\s*\"",
+ boost::regex::perl | boost::regex::icase);
+ boost::match_results<std::string::const_iterator> matches;
+ mExactToken = (ll_regex_match(filter_sub_string_new, matches, mPattern) && matches[1].matched)
+ ? matches[1]
+ : LLStringUtil::null;
+ if ((old_token.empty() && !mExactToken.empty())
+ || (!old_token.empty() && mExactToken.empty()))
+ {
+ exact_token_changed = true;
+ }
+ }
+
+ // 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 (exact_token_changed)
+ {
+ setModified(FILTER_RESTART);
+ }
+ else if (less_restrictive)
+ {
+ setModified(FILTER_LESS_RESTRICTIVE);
+ }
+ else if (more_restrictive)
+ {
+ setModified(FILTER_MORE_RESTRICTIVE);
+ }
+ else
+ {
+ setModified(FILTER_RESTART);
+ }
+
+ // Cancel out filter links once the search string is modified
+ if (mFilterOps.mFilterLinks == FILTERLINK_ONLY_LINKS)
+ {
+ if (mBackupFilterOps.mFilterLinks == FILTERLINK_ONLY_LINKS)
+ {
+ // we started viewer/floater in 'only links' mode
+ mFilterOps.mFilterLinks = FILTERLINK_INCLUDE_LINKS;
+ }
+ else
+ {
+ mFilterOps = mBackupFilterOps;
+ setModified(FILTER_RESTART);
+ }
+ }
+
+ // Cancel out UUID once the search string is modified
+ if (mFilterOps.mFilterTypes == FILTERTYPE_UUID)
+ {
+ mFilterOps.mFilterTypes &= ~FILTERTYPE_UUID;
+ mFilterOps.mFilterUUID = LLUUID::null;
+ setModified(FILTER_RESTART);
+ }
+ }
+}
+
+void LLInventoryFilter::setSearchVisibilityTypes(U32 types)
+{
+ if (mFilterOps.mSearchVisibility != types)
+ {
+ // keep current items only if no perm bits getting turned off
+ bool fewer_bits_set = (mFilterOps.mSearchVisibility & ~types);
+ bool more_bits_set = (~mFilterOps.mSearchVisibility & types);
+ mFilterOps.mSearchVisibility = types;
+
+ 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::setSearchVisibilityTypes(const Params& params)
+{
+ if (!params.validateBlock())
+ {
+ return;
+ }
+
+ if (params.filter_ops.search_visibility.isProvided())
+ {
+ setSearchVisibilityTypes(params.filter_ops.search_visibility);
+ }
+}
+
+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();
+ }
+
+ if (areDateLimitsSet())
+ {
+ mFilterOps.mFilterTypes |= FILTERTYPE_DATE;
+ }
+ else
+ {
+ mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE;
+ }
+}
+
+void LLInventoryFilter::setDateRangeLastLogoff(bool sl)
+{
+ static LLCachedControl<U32> s_last_logoff(gSavedPerAccountSettings, "LastLogoff", 0);
+ if (sl && !isSinceLogoff())
+ {
+ setDateRange(s_last_logoff(), time_max());
+ setModified();
+ }
+ if (!sl && isSinceLogoff())
+ {
+ setDateRange(time_min(), time_max());
+ setModified();
+ }
+
+ if (areDateLimitsSet())
+ {
+ mFilterOps.mFilterTypes |= FILTERTYPE_DATE;
+ }
+ else
+ {
+ mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE;
+ }
+}
+
+bool LLInventoryFilter::isSinceLogoff() const
+{
+ static LLCachedControl<U32> s_last_logoff(gSavedSettings, "LastLogoff", 0);
+
+ return (mFilterOps.mMinDate == (time_t)s_last_logoff()) &&
+ (mFilterOps.mMaxDate == time_max()) &&
+ (mFilterOps.mFilterTypes & FILTERTYPE_DATE);
+}
+
+void LLInventoryFilter::clearModified()
+{
+ mFilterModified = 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_decreasing = hours < mFilterOps.mHoursAgo;
+ bool is_increasing_from_zero = is_increasing && !mFilterOps.mHoursAgo && !isSinceLogoff();
+
+ // *NOTE: need to cache last filter time, in case filter goes stale
+ bool less_restrictive;
+ bool more_restrictive;
+ if (FILTERDATEDIRECTION_NEWER == mFilterOps.mDateSearchDirection)
+ {
+ less_restrictive = ((are_date_limits_valid && ((is_increasing && mFilterOps.mHoursAgo))) || !hours);
+ more_restrictive = ((are_date_limits_valid && (!is_increasing && hours)) || is_increasing_from_zero);
+ }
+ else
+ {
+ less_restrictive = ((are_date_limits_valid && ((is_decreasing && mFilterOps.mHoursAgo))) || !hours);
+ more_restrictive = ((are_date_limits_valid && (!is_decreasing && 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);
+ }
+ }
+
+ if (areDateLimitsSet())
+ {
+ mFilterOps.mFilterTypes |= FILTERTYPE_DATE;
+ }
+ else
+ {
+ mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE;
+ }
+}
+
+void LLInventoryFilter::setDateSearchDirection(U32 direction)
+{
+ if (direction != mFilterOps.mDateSearchDirection)
+ {
+ mFilterOps.mDateSearchDirection = direction;
+ setModified(FILTER_RESTART);
+ }
+}
+
+U32 LLInventoryFilter::getDateSearchDirection() const
+{
+ return mFilterOps.mDateSearchDirection;
+}
+
+void LLInventoryFilter::setFilterLinks(U64 filter_links)
+{
+ if (mFilterOps.mFilterLinks != filter_links)
+ {
+ if (mFilterOps.mFilterLinks == FILTERLINK_EXCLUDE_LINKS ||
+ mFilterOps.mFilterLinks == FILTERLINK_ONLY_LINKS)
+ setModified(FILTER_MORE_RESTRICTIVE);
+ else
+ setModified(FILTER_LESS_RESTRICTIVE);
+ }
+ mFilterOps.mFilterLinks = filter_links;
+}
+
+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::setFindAllLinksMode(const std::string &search_name, const LLUUID& search_id)
+{
+ // Save a copy of settings so that we will be able to restore it later
+ // but make sure we are not searching for links already
+ if(mFilterOps.mFilterLinks != FILTERLINK_ONLY_LINKS)
+ {
+ mBackupFilterOps = mFilterOps;
+ }
+
+ // set search options
+ setFilterSubString(search_name);
+ setFilterUUID(search_id);
+ setShowFolderState(SHOW_NON_EMPTY_FOLDERS);
+ setFilterLinks(FILTERLINK_ONLY_LINKS);
+}
+
+void LLInventoryFilter::markDefault()
+{
+ mDefaultFilterOps = mFilterOps;
+}
+
+void LLInventoryFilter::resetDefault()
+{
+ mFilterOps = mDefaultFilterOps;
+ setModified();
+}
+
+void LLInventoryFilter::setModified(EFilterModified behavior)
+{
+ mFilterText.clear();
+ mCurrentGeneration++;
+
+ if (mFilterModified == FILTER_NONE)
+ {
+ mFilterModified = behavior;
+ }
+ else if (mFilterModified != behavior)
+ {
+ // trying to do both less restrictive and more restrictive filter
+ // basically means restart from scratch
+ mFilterModified = FILTER_RESTART;
+ }
+
+ // if not keeping current filter results, update last valid as well
+ switch(mFilterModified)
+ {
+ case FILTER_RESTART:
+ mFirstRequiredGeneration = mCurrentGeneration;
+ mFirstSuccessGeneration = mCurrentGeneration;
+ break;
+ case FILTER_LESS_RESTRICTIVE:
+ mFirstRequiredGeneration = mCurrentGeneration;
+ break;
+ case FILTER_MORE_RESTRICTIVE:
+ mFirstSuccessGeneration = mCurrentGeneration;
+ break;
+ default:
+ LL_ERRS() << "Bad filter behavior specified" << LL_ENDL;
+ }
+}
+
+bool LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const
+{
+ return mFilterOps.mFilterObjectTypes & (1LL << t);
+}
+
+const std::string& LLInventoryFilter::getFilterText()
+{
+ if (!mFilterText.empty())
+ {
+ return mFilterText;
+ }
+
+ 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 (isFilterObjectTypesWith(LLInventoryType::IT_ANIMATION))
+ {
+ filtered_types += LLTrans::getString("Animations");
+ filtered_by_type = true;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Animations");
+
+ filtered_by_all_types = false;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_CALLINGCARD))
+ {
+ filtered_types += LLTrans::getString("Calling Cards");
+ filtered_by_type = true;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Calling Cards");
+ filtered_by_all_types = false;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_WEARABLE))
+ {
+ filtered_types += LLTrans::getString("Clothing");
+ filtered_by_type = true;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Clothing");
+ filtered_by_all_types = false;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_GESTURE))
+ {
+ filtered_types += LLTrans::getString("Gestures");
+ filtered_by_type = true;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Gestures");
+ filtered_by_all_types = false;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_LANDMARK))
+ {
+ filtered_types += LLTrans::getString("Landmarks");
+ filtered_by_type = true;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Landmarks");
+ filtered_by_all_types = false;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_MATERIAL))
+ {
+ filtered_types += LLTrans::getString("Materials");
+ filtered_by_type = true;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Materials");
+ filtered_by_all_types = false;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_NOTECARD))
+ {
+ filtered_types += LLTrans::getString("Notecards");
+ filtered_by_type = true;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Notecards");
+ filtered_by_all_types = false;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_OBJECT) && isFilterObjectTypesWith(LLInventoryType::IT_ATTACHMENT))
+ {
+ filtered_types += LLTrans::getString("Objects");
+ filtered_by_type = true;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Objects");
+ filtered_by_all_types = false;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_LSL))
+ {
+ filtered_types += LLTrans::getString("Scripts");
+ filtered_by_type = true;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Scripts");
+ filtered_by_all_types = false;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_SOUND))
+ {
+ filtered_types += LLTrans::getString("Sounds");
+ filtered_by_type = true;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Sounds");
+ filtered_by_all_types = false;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_TEXTURE))
+ {
+ filtered_types += LLTrans::getString("Textures");
+ filtered_by_type = true;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Textures");
+ filtered_by_all_types = false;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_SNAPSHOT))
+ {
+ filtered_types += LLTrans::getString("Snapshots");
+ filtered_by_type = true;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Snapshots");
+ filtered_by_all_types = false;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_SETTINGS))
+ {
+ filtered_types += LLTrans::getString("Settings");
+ filtered_by_type = true;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Settings");
+ filtered_by_all_types = false;
+ }
+
+ if (!LLInventoryModelBackgroundFetch::instance().folderFetchActive()
+ && filtered_by_type
+ && !filtered_by_all_types)
+ {
+ mFilterText += " - ";
+ if (num_filter_types < 5)
+ {
+ mFilterText += filtered_types;
+ }
+ else
+ {
+ mFilterText += LLTrans::getString("No Filters");
+ mFilterText += not_filtered_types;
+ }
+ // remove the ',' at the end
+ mFilterText.erase(mFilterText.size() - 1, 1);
+ }
+
+ if (isSinceLogoff())
+ {
+ mFilterText += LLTrans::getString("Since Logoff");
+ }
+ return mFilterText;
+}
+
+
+LLInventoryFilter& LLInventoryFilter::operator=( const LLInventoryFilter& other )
+{
+ setFilterObjectTypes(other.getFilterObjectTypes());
+ setDateRange(other.getMinDate(), other.getMaxDate());
+ setHoursAgo(other.getHoursAgo());
+ setDateSearchDirection(other.getDateSearchDirection());
+ setShowFolderState(other.getShowFolderState());
+ setFilterPermissions(other.getFilterPermissions());
+ setFilterSubString(other.getFilterSubString());
+ setDateRangeLastLogoff(other.isSinceLogoff());
+ return *this;
+}
+
+
+void LLInventoryFilter::toParams(Params& params) const
+{
+ params.filter_ops.types = getFilterObjectTypes();
+ params.filter_ops.category_types = getFilterCategoryTypes();
+ if (getFilterObjectTypes() & FILTERTYPE_WEARABLE)
+ {
+ params.filter_ops.wearable_types = getFilterWearableTypes();
+ }
+ params.filter_ops.date_range.min_date = getMinDate();
+ params.filter_ops.date_range.max_date = getMaxDate();
+ params.filter_ops.hours_ago = getHoursAgo();
+ params.filter_ops.date_search_direction = getDateSearchDirection();
+ params.filter_ops.show_folder_state = getShowFolderState();
+ params.filter_ops.creator_type = getFilterCreatorType();
+ params.filter_ops.permissions = getFilterPermissions();
+ params.filter_ops.search_visibility = getSearchVisibilityTypes();
+ params.substring = getFilterSubString();
+ params.since_logoff = isSinceLogoff();
+}
+
+void LLInventoryFilter::fromParams(const Params& params)
+{
+ if (!params.validateBlock())
+ {
+ return;
+ }
+
+ setFilterObjectTypes(params.filter_ops.types);
+ setFilterCategoryTypes(params.filter_ops.category_types);
+ if (params.filter_ops.wearable_types.isProvided())
+ {
+ setFilterWearableTypes(params.filter_ops.wearable_types);
+ }
+ setDateRange(params.filter_ops.date_range.min_date, params.filter_ops.date_range.max_date);
+ setHoursAgo(params.filter_ops.hours_ago);
+ setDateSearchDirection(params.filter_ops.date_search_direction);
+ setShowFolderState(params.filter_ops.show_folder_state);
+ setFilterCreator(params.filter_ops.creator_type);
+ setFilterPermissions(params.filter_ops.permissions);
+ setSearchVisibilityTypes(params.filter_ops.search_visibility);
+ setFilterSubString(params.substring);
+ setDateRangeLastLogoff(params.since_logoff);
+}
+
+U64 LLInventoryFilter::getFilterTypes() const
+{
+ return mFilterOps.mFilterTypes;
+}
+
+U64 LLInventoryFilter::getFilterObjectTypes() const
+{
+ return mFilterOps.mFilterObjectTypes;
+}
+
+U64 LLInventoryFilter::getFilterCategoryTypes() const
+{
+ return mFilterOps.mFilterCategoryTypes;
+}
+
+U64 LLInventoryFilter::getFilterWearableTypes() const
+{
+ return mFilterOps.mFilterWearableTypes;
+}
+
+U64 LLInventoryFilter::getFilterSettingsTypes() const
+{
+ return mFilterOps.mFilterSettingsTypes;
+}
+
+U64 LLInventoryFilter::getSearchVisibilityTypes() const
+{
+ return mFilterOps.mSearchVisibility;
+}
+
+U64 LLInventoryFilter::getFilterThumbnails() const
+{
+ return mFilterOps.mFilterThumbnails;
+}
+
+bool LLInventoryFilter::hasFilterString() const
+{
+ return mFilterSubString.size() > 0;
+}
+
+std::string::size_type LLInventoryFilter::getFilterStringSize() const
+{
+ return mFilterSubString.size();
+}
+
+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;
+}
+U64 LLInventoryFilter::getFilterLinks() const
+{
+ return mFilterOps.mFilterLinks;
+}
+LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const
+{
+ return mFilterOps.mShowFolderState;
+}
+
+LLInventoryFilter::EFilterCreatorType LLInventoryFilter::getFilterCreatorType() const
+{
+ return mFilterOps.mFilterCreatorType;
+}
+
+bool LLInventoryFilter::isTimedOut()
+{
+ return mFilterTime.hasExpired();
+}
+
+void LLInventoryFilter::resetTime(S32 timeout)
+{
+ mFilterTime.reset();
+ F32 time_in_sec = (F32)(timeout)/1000.0;
+ mFilterTime.setTimerExpirySec(time_in_sec);
+}
+
+S32 LLInventoryFilter::getCurrentGeneration() const
+{
+ return mCurrentGeneration;
+}
+S32 LLInventoryFilter::getFirstSuccessGeneration() const
+{
+ return mFirstSuccessGeneration;
+}
+S32 LLInventoryFilter::getFirstRequiredGeneration() const
+{
+ return mFirstRequiredGeneration;
+}
+
+void LLInventoryFilter::setEmptyLookupMessage(const std::string& message)
+{
+ mEmptyLookupMessage = message;
+}
+
+void LLInventoryFilter::setDefaultEmptyLookupMessage(const std::string& message)
+{
+ mDefaultEmptyLookupMessage = message;
+}
+
+std::string LLInventoryFilter::getEmptyLookupMessage(bool is_empty_folder) const
+{
+ if ((isDefault() || is_empty_folder) && !mDefaultEmptyLookupMessage.empty())
+ {
+ return LLTrans::getString(mDefaultEmptyLookupMessage);
+ }
+ else
+ {
+ LLStringUtil::format_map_t args;
+ args["[SEARCH_TERM]"] = LLURI::escape(getFilterSubStringOrig());
+
+ return LLTrans::getString(mEmptyLookupMessage, args);
+ }
+
+}
+
+bool LLInventoryFilter::areDateLimitsSet()
+{
+ return mFilterOps.mMinDate != time_min()
+ || mFilterOps.mMaxDate != time_max()
+ || mFilterOps.mHoursAgo != 0;
+}
+
+bool LLInventoryFilter::showAllResults() const
+{
+ return hasFilterString() && !mSingleFolderMode;
+}
+
+
+
+bool LLInventoryFilter::FilterOps::DateRange::validateBlock( bool emit_errors /*= true*/ ) const
+{
+ bool valid = LLInitParam::Block<DateRange>::validateBlock(emit_errors);
+ if (valid)
+ {
+ if (max_date() < min_date())
+ {
+ if (emit_errors)
+ {
+ LL_WARNS() << "max_date should be greater or equal to min_date" << LL_ENDL;
+ }
+ valid = false;
+ }
+ }
+ return valid;
+}
|
