Files
SingularityViewer/indra/newview/llinventoryfunctions.cpp
Aleric Inglewood 325ef60a8c Wearable export improvements.
Add grid nick to default filename.
Add grid nick and date to exported XML.
Add inventory path, name and description of item to exported XML.
2013-07-19 21:22:59 +02:00

1061 lines
26 KiB
C++

/**
* @file llinventoryfunctions.cpp
* @brief Implementation of the inventory view and associated stuff.
*
* $LicenseInfo:firstyear=2001&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 <utility> // for std::pair<>
#include "llinventoryfunctions.h"
// library includes
#include "llagent.h"
#include "llagentwearables.h"
#include "llcallingcard.h"
#include "llinventorydefines.h"
#include "llsdserialize.h"
#include "llspinctrl.h"
#include "llui.h"
#include "message.h"
// newview includes
#include "llappearancemgr.h"
#include "llappviewer.h"
//#include "llfirstuse.h"
#include "llfloaterinventory.h"
#include "llfloateroutbox.h"
#include "llfocusmgr.h"
#include "llfolderview.h"
#include "llgesturemgr.h"
#include "lliconctrl.h"
#include "llimview.h"
#include "llinventorybridge.h"
#include "llinventoryclipboard.h"
#include "llinventorymodel.h"
#include "llinventorypanel.h"
#include "lllineeditor.h"
#include "llmarketplacenotifications.h"
#include "llmenugl.h"
#include "llnotificationsutil.h"
#include "llpanelmaininventory.h"
#include "llpreviewanim.h"
#include "llpreviewgesture.h"
#include "llpreviewnotecard.h"
#include "llpreviewscript.h"
#include "llpreviewsound.h"
#include "llpreviewtexture.h"
#include "llresmgr.h"
#include "llscrollbar.h"
#include "llscrollcontainer.h"
#include "llselectmgr.h"
#include "lltabcontainer.h"
#include "lltooldraganddrop.h"
#include "lluictrlfactory.h"
#include "llviewermessage.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
#include "llvoavatarself.h"
#include "llwearablelist.h"
#include <boost/foreach.hpp>
// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a)
#include "rlvhandler.h"
#include "rlvlocks.h"
// [/RLVa:KB]
BOOL LLInventoryState::sWearNewClothing = FALSE;
LLUUID LLInventoryState::sWearNewClothingTransactionID;
// Generates a string containing the path to the item specified by
// item_id.
void append_path(const LLUUID& id, std::string& path)
{
std::string temp;
const LLInventoryObject* obj = gInventory.getObject(id);
LLUUID parent_id;
if(obj) parent_id = obj->getParentUUID();
std::string forward_slash("/");
while(obj)
{
obj = gInventory.getCategory(parent_id);
if(obj)
{
temp.assign(forward_slash + obj->getName() + temp);
parent_id = obj->getParentUUID();
}
}
path.append(temp);
}
// Path should already end on '/' if it is not empty.
void append_path_short(LLUUID const& id, std::string& path)
{
LLInventoryObject const* obj = gInventory.getObject(id);
if (!obj) return;
LLUUID const root_id = gInventory.getRootFolderID();
std::string const forward_slash("/");
std::string result;
while(1)
{
LLUUID parent_id = obj->getParentUUID();
if (parent_id == root_id ||
!(obj = gInventory.getCategory(parent_id)))
{
break;
}
std::string temp;
temp.swap(result);
result = obj->getName();
if (!temp.empty())
{
result.append(forward_slash);
result.append(temp);
}
}
path.append(result);
}
void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name)
{
LLViewerInventoryCategory* cat;
if (!model ||
!get_is_category_renameable(model, cat_id) ||
(cat = model->getCategory(cat_id)) == NULL ||
cat->getName() == new_name)
{
return;
}
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
new_cat->rename(new_name);
new_cat->updateServer(FALSE);
model->updateCategory(new_cat);
model->notifyObservers();
}
void copy_inventory_category(LLInventoryModel* model,
LLViewerInventoryCategory* cat,
const LLUUID& parent_id,
const LLUUID& root_copy_id)
{
// Create the initial folder
LLUUID new_cat_uuid = gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName());
model->notifyObservers();
// We need to exclude the initial root of the copy to avoid recursively copying the copy, etc...
LLUUID root_id = (root_copy_id.isNull() ? new_cat_uuid : root_copy_id);
// Get the content of the folder
LLInventoryModel::cat_array_t* cat_array;
LLInventoryModel::item_array_t* item_array;
gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array);
// Copy all the items
LLInventoryModel::item_array_t item_array_copy = *item_array;
for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
{
LLInventoryItem* item = *iter;
copy_inventory_item(
gAgent.getID(),
item->getPermissions().getOwner(),
item->getUUID(),
new_cat_uuid,
std::string(),
LLPointer<LLInventoryCallback>(NULL));
}
// Copy all the folders
LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
{
LLViewerInventoryCategory* category = *iter;
if (category->getUUID() != root_id)
{
copy_inventory_category(model, category, new_cat_uuid, root_id);
}
}
}
class LLInventoryCollectAllItems : public LLInventoryCollectFunctor
{
public:
virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
return true;
}
};
BOOL get_is_parent_to_worn_item(const LLUUID& id)
{
const LLViewerInventoryCategory* cat = gInventory.getCategory(id);
if (!cat)
{
return FALSE;
}
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
LLInventoryCollectAllItems collect_all;
gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), cats, items, LLInventoryModel::EXCLUDE_TRASH, collect_all);
for (LLInventoryModel::item_array_t::const_iterator it = items.begin(); it != items.end(); ++it)
{
const LLViewerInventoryItem * const item = *it;
llassert(item->getIsLinkType());
LLUUID linked_id = item->getLinkedUUID();
const LLViewerInventoryItem * const linked_item = gInventory.getItem(linked_id);
if (linked_item)
{
LLUUID parent_id = linked_item->getParentUUID();
while (!parent_id.isNull())
{
LLInventoryCategory * parent_cat = gInventory.getCategory(parent_id);
if (cat == parent_cat)
{
return TRUE;
}
parent_id = parent_cat->getParentUUID();
}
}
}
return FALSE;
}
BOOL get_is_item_worn(const LLInventoryItem *item)
{
if (!item)
return FALSE;
// Consider the item as worn if it has links in COF.
/* if (LLCOFMgr::instance().isLinkInCOF(item->getUUID()))
{ REMOVED due to advice from Kitty Barnett, looks like it WILL cause trouble on some grids -SG
return TRUE;
} */
switch(item->getType())
{
case LLAssetType::AT_OBJECT:
{
if (isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item->getLinkedUUID()))
return TRUE;
break;
}
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
if(gAgentWearables.isWearingItem(item->getLinkedUUID()))
return TRUE;
break;
case LLAssetType::AT_GESTURE:
if (LLGestureMgr::instance().isGestureActive(item->getLinkedUUID()))
return TRUE;
break;
default:
break;
}
return FALSE;
}
BOOL get_is_item_worn(const LLUUID& id)
{
return get_is_item_worn(gInventory.getItem(id));
}
BOOL get_can_item_be_worn(const LLUUID& id)
{
const LLViewerInventoryItem* item = gInventory.getItem(id);
if (!item)
return FALSE;
if (LLAppearanceMgr::isLinkInCOF(item->getLinkedUUID()))
{
// an item having links in COF (i.e. a worn item)
return FALSE;
}
if (gInventory.isObjectDescendentOf(id, LLAppearanceMgr::instance().getCOF()))
{
// a non-link object in COF (should not normally happen)
return FALSE;
}
const LLUUID trash_id = gInventory.findCategoryUUIDForType(
LLFolderType::FT_TRASH);
// item can't be worn if base obj in trash, see EXT-7015
if (gInventory.isObjectDescendentOf(item->getLinkedUUID(),
trash_id))
{
return false;
}
switch(item->getType())
{
case LLAssetType::AT_OBJECT:
{
if (isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item->getLinkedUUID()))
{
// Already being worn
return FALSE;
}
else
{
// Not being worn yet.
return TRUE;
}
break;
}
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
if(gAgentWearables.isWearingItem(item->getLinkedUUID()))
{
// Already being worn
return FALSE;
}
else
{
// Not being worn yet.
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id)
{
if (!model)
{
return FALSE;
}
if(id == gInventory.getRootFolderID())
{
return FALSE;
}
// Can't delete an item that's in the library.
if(!model->isObjectDescendentOf(id, gInventory.getRootFolderID()))
{
return FALSE;
}
// Disable delete from COF folder; have users explicitly choose "detach/take off",
// unless the item is not worn but in the COF (i.e. is bugged).
if (LLAppearanceMgr::instance().getIsProtectedCOFItem(id))
{
if (get_is_item_worn(id))
{
return FALSE;
}
}
// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
if ( (rlv_handler_t::isEnabled()) &&
(RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) && (!RlvFolderLocks::instance().canRemoveItem(id)) )
{
return FALSE;
}
// [/RLVa:KB]
const LLInventoryObject *obj = model->getItem(id);
if (obj && obj->getIsLinkType())
{
return TRUE;
}
if (get_is_item_worn(id))
{
return FALSE;
}
return TRUE;
}
BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id)
{
// NOTE: This function doesn't check the folder's children.
// See LLFolderBridge::isItemRemovable for a function that does
// consider the children.
if (!model)
{
return FALSE;
}
if (!model->isObjectDescendentOf(id, gInventory.getRootFolderID()))
{
return FALSE;
}
// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
if ( ((rlv_handler_t::isEnabled()) &&
(RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) && (!RlvFolderLocks::instance().canRemoveFolder(id))) )
{
return FALSE;
}
// [/RLVa:KB]
if (!isAgentAvatarValid()) return FALSE;
const LLInventoryCategory* category = model->getCategory(id);
if (!category)
{
return FALSE;
}
const LLFolderType::EType folder_type = category->getPreferredType();
#ifndef DELETE_SYSTEM_FOLDERS
if (LLFolderType::lookupIsProtectedType(folder_type))
{
return FALSE;
}
#endif
// Can't delete the outfit that is currently being worn.
if (folder_type == LLFolderType::FT_OUTFIT)
{
const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();
if (base_outfit_link && (category == base_outfit_link->getLinkedCategory()))
{
return FALSE;
}
}
return TRUE;
}
BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id)
{
if (!model)
{
return FALSE;
}
// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
if ( (rlv_handler_t::isEnabled()) && (model == &gInventory) && (!RlvFolderLocks::instance().canRenameFolder(id)) )
{
return FALSE;
}
// [/RLVa:KB]
LLViewerInventoryCategory* cat = model->getCategory(id);
if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) &&
cat->getOwnerID() == gAgent.getID())
{
return TRUE;
}
return FALSE;
}
void show_item_profile(const LLUUID& item_uuid)
{
LLUUID linked_uuid = gInventory.getLinkedItemID(item_uuid);
if(!LLFloaterProperties::show(linked_uuid, LLUUID::null))
{
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
LLRect rect = gSavedSettings.getRect("PropertiesRect");
rect.translate( left - rect.mLeft, top - rect.mTop );
LLFloaterProperties* floater;
floater = new LLFloaterProperties("item properties",
rect,
"Inventory Item Properties",
linked_uuid,
LLUUID::null);
// keep onscreen
gFloaterView->adjustToFitScreen(floater, FALSE);
}
}
void open_outbox()
{
LLFloaterOutbox::showInstance();
}
LLUUID create_folder_in_outbox_for_item(LLInventoryItem* item, const LLUUID& destFolderId, S32 operation_id)
{
llassert(item);
llassert(destFolderId.notNull());
LLUUID created_folder_id = gInventory.createNewCategory(destFolderId, LLFolderType::FT_NONE, item->getName());
gInventory.notifyObservers();
LLNotificationsUtil::add("OutboxFolderCreated");
return created_folder_id;
}
void move_to_outbox_cb_action(const LLSD& payload)
{
LLViewerInventoryItem * viitem = gInventory.getItem(payload["item_id"].asUUID());
LLUUID dest_folder_id = payload["dest_folder_id"].asUUID();
if (viitem)
{
// when moving item directly into outbox create folder with that name
if (dest_folder_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
{
S32 operation_id = payload["operation_id"].asInteger();
dest_folder_id = create_folder_in_outbox_for_item(viitem, dest_folder_id, operation_id);
}
LLUUID parent = viitem->getParentUUID();
gInventory.changeItemParent(
viitem,
dest_folder_id,
false);
LLUUID top_level_folder = payload["top_level_folder"].asUUID();
if (top_level_folder != LLUUID::null)
{
LLViewerInventoryCategory* category;
while (parent.notNull())
{
LLInventoryModel::cat_array_t* cat_array;
LLInventoryModel::item_array_t* item_array;
gInventory.getDirectDescendentsOf(parent,cat_array,item_array);
LLUUID next_parent;
category = gInventory.getCategory(parent);
if (!category) break;
next_parent = category->getParentUUID();
if (cat_array->empty() && item_array->empty())
{
gInventory.removeCategory(parent);
}
if (parent == top_level_folder)
{
break;
}
parent = next_parent;
}
}
open_outbox();
}
}
void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id)
{
// Collapse links directly to items/folders
LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory();
if (linked_category != NULL)
{
copy_folder_to_outbox(linked_category, dest_folder, top_level_folder, operation_id);
}
else
{
LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
if (linked_item != NULL)
{
inv_item = (LLInventoryItem *) linked_item;
}
// Check for copy permissions
if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
{
// when moving item directly into outbox create folder with that name
if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
{
dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, operation_id);
}
copy_inventory_item(gAgent.getID(),
inv_item->getPermissions().getOwner(),
inv_item->getUUID(),
dest_folder,
inv_item->getName(),
LLPointer<LLInventoryCallback>(NULL));
open_outbox();
}
else
{
LLSD payload;
payload["item_id"] = inv_item->getUUID();
payload["dest_folder_id"] = dest_folder;
payload["top_level_folder"] = top_level_folder;
payload["operation_id"] = operation_id;
LLMarketplaceInventoryNotifications::addNoCopyNotification(payload, move_to_outbox_cb_action);
}
}
}
void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id)
{
// when moving item directly into outbox create folder with that name
if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
{
dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, operation_id);
}
LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
gInventory.changeItemParent(
viewer_inv_item,
dest_folder,
false);
}
void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id)
{
LLUUID new_folder_id = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_cat->getName());
gInventory.notifyObservers();
LLInventoryModel::cat_array_t* cat_array;
LLInventoryModel::item_array_t* item_array;
gInventory.getDirectDescendentsOf(inv_cat->getUUID(),cat_array,item_array);
// copy the vector because otherwise the iterator won't be happy if we delete from it
LLInventoryModel::item_array_t item_array_copy = *item_array;
for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
{
LLInventoryItem* item = *iter;
copy_item_to_outbox(item, new_folder_id, top_level_folder, operation_id);
}
LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
{
LLViewerInventoryCategory* category = *iter;
copy_folder_to_outbox(category, new_folder_id, top_level_folder, operation_id);
}
open_outbox();
}
///----------------------------------------------------------------------------
/// LLInventoryCollectFunctor implementations
///----------------------------------------------------------------------------
// static
bool LLInventoryCollectFunctor::itemTransferCommonlyAllowed(const LLInventoryItem* item)
{
if (!item)
return false;
switch(item->getType())
{
case LLAssetType::AT_OBJECT:
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
if (!get_is_item_worn(item->getUUID()))
return true;
break;
default:
return true;
break;
}
return false;
}
bool LLIsType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
if(mType == LLAssetType::AT_CATEGORY)
{
if(cat) return TRUE;
}
if(item)
{
if(item->getType() == mType) return TRUE;
}
return FALSE;
}
bool LLIsNotType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
if(mType == LLAssetType::AT_CATEGORY)
{
if(cat) return FALSE;
}
if(item)
{
if(item->getType() == mType) return FALSE;
else return TRUE;
}
return TRUE;
}
bool LLIsOfAssetType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
if(mType == LLAssetType::AT_CATEGORY)
{
if(cat) return TRUE;
}
if(item)
{
if(item->getActualType() == mType) return TRUE;
}
return FALSE;
}
bool LLIsTypeWithPermissions::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
if(mType == LLAssetType::AT_CATEGORY)
{
if(cat)
{
return TRUE;
}
}
if(item)
{
if(item->getType() == mType)
{
LLPermissions perm = item->getPermissions();
if ((perm.getMaskBase() & mPerm) == mPerm)
{
return TRUE;
}
}
}
return FALSE;
}
bool LLBuddyCollector::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
if(item)
{
if((LLAssetType::AT_CALLINGCARD == item->getType())
&& (!item->getCreatorUUID().isNull())
&& (item->getCreatorUUID() != gAgent.getID()))
{
return true;
}
}
return false;
}
bool LLUniqueBuddyCollector::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
if(item)
{
if((LLAssetType::AT_CALLINGCARD == item->getType())
&& (item->getCreatorUUID().notNull())
&& (item->getCreatorUUID() != gAgent.getID()))
{
mSeen.insert(item->getCreatorUUID());
return true;
}
}
return false;
}
bool LLParticularBuddyCollector::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
if(item)
{
if((LLAssetType::AT_CALLINGCARD == item->getType())
&& (item->getCreatorUUID() == mBuddyID))
{
return TRUE;
}
}
return FALSE;
}
bool LLNameCategoryCollector::operator()(
LLInventoryCategory* cat, LLInventoryItem* item)
{
if(cat)
{
if (!LLStringUtil::compareInsensitive(mName, cat->getName()))
{
return true;
}
}
return false;
}
bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
// Valid COF items are:
// - links to wearables (body parts or clothing)
// - links to attachments
// - links to gestures
// - links to ensemble folders
LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem();
if (linked_item)
{
LLAssetType::EType type = linked_item->getType();
return (type == LLAssetType::AT_CLOTHING ||
type == LLAssetType::AT_BODYPART ||
type == LLAssetType::AT_GESTURE ||
type == LLAssetType::AT_OBJECT);
}
else
{
LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory();
// BAP remove AT_NONE support after ensembles are fully working?
return (linked_category &&
((linked_category->getPreferredType() == LLFolderType::FT_NONE) ||
(LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType()))));
}
}
bool LLFindWearables::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
if(item)
{
if((item->getType() == LLAssetType::AT_CLOTHING)
|| (item->getType() == LLAssetType::AT_BODYPART))
{
return TRUE;
}
}
return FALSE;
}
LLFindWearablesEx::LLFindWearablesEx(bool is_worn, bool include_body_parts)
: mIsWorn(is_worn)
, mIncludeBodyParts(include_body_parts)
{}
bool LLFindWearablesEx::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
if (!vitem) return false;
// Skip non-wearables.
if (!vitem->isWearableType() && vitem->getType() != LLAssetType::AT_OBJECT)
{
return false;
}
// Skip body parts if requested.
if (!mIncludeBodyParts && vitem->getType() == LLAssetType::AT_BODYPART)
{
return false;
}
// Skip broken links.
if (vitem->getIsBrokenLink())
{
return false;
}
return (bool) get_is_item_worn(item->getUUID()) == mIsWorn;
}
bool LLFindWearablesOfType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
if (!item) return false;
if (item->getType() != LLAssetType::AT_CLOTHING &&
item->getType() != LLAssetType::AT_BODYPART)
{
return false;
}
LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
if (!vitem || vitem->getWearableType() != mWearableType) return false;
return true;
}
void LLFindWearablesOfType::setType(LLWearableType::EType type)
{
mWearableType = type;
}
bool LLFindNonRemovableObjects::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
if (item)
{
return !get_is_item_removable(&gInventory, item->getUUID());
}
if (cat)
{
return !get_is_category_removable(&gInventory, cat->getUUID());
}
llwarns << "Not a category and not an item?" << llendl;
return false;
}
///----------------------------------------------------------------------------
/// LLAssetIDMatches
///----------------------------------------------------------------------------
bool LLAssetIDMatches ::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
return (item && item->getAssetUUID() == mAssetID);
}
///----------------------------------------------------------------------------
/// LLLinkedItemIDMatches
///----------------------------------------------------------------------------
bool LLLinkedItemIDMatches::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
return (item &&
(item->getIsLinkType()) &&
(item->getLinkedUUID() == mBaseItemID)); // A linked item's assetID will be the compared-to item's itemID.
}
void LLSaveFolderState::setApply(BOOL apply)
{
mApply = apply;
// before generating new list of open folders, clear the old one
if(!apply)
{
clearOpenFolders();
}
}
void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)
{
LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
if(!bridge) return;
if(mApply)
{
// we're applying the open state
LLUUID id(bridge->getUUID());
if(mOpenFolders.find(id) != mOpenFolders.end())
{
if (!folder->isOpen())
{
folder->setOpen(TRUE);
}
}
else
{
// keep selected filter in its current state, this is less jarring to user
if (!folder->isSelected() && folder->isOpen())
{
folder->setOpen(FALSE);
}
}
}
else
{
// we're recording state at this point
if(folder->isOpen())
{
mOpenFolders.insert(bridge->getUUID());
}
}
}
void LLOpenFilteredFolders::doItem(LLFolderViewItem *item)
{
if (item->getFiltered())
{
item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
}
void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder)
{
if (folder->getFiltered() && folder->getParentFolder())
{
folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
// if this folder didn't pass the filter, and none of its descendants did
else if (!folder->getFiltered() && !folder->hasFilteredDescendants())
{
folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO);
}
}
void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item)
{
if (item->getFiltered() && !mItemSelected)
{
item->getRoot()->setSelection(item, FALSE, FALSE);
if (item->getParentFolder())
{
item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
item->getRoot()->scrollToShowSelection();
mItemSelected = TRUE;
}
}
void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder)
{
if (folder->getFiltered() && !mItemSelected)
{
folder->getRoot()->setSelection(folder, FALSE, FALSE);
if (folder->getParentFolder())
{
folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
folder->getRoot()->scrollToShowSelection();
mItemSelected = TRUE;
}
}
void LLOpenFoldersWithSelection::doItem(LLFolderViewItem *item)
{
if (item->getParentFolder() && item->isSelected())
{
item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
}
void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder)
{
if (folder->getParentFolder() && folder->isSelected())
{
folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
}
}