summaryrefslogtreecommitdiff
path: root/indra/newview/llviewerinventory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewerinventory.cpp')
-rw-r--r--indra/newview/llviewerinventory.cpp595
1 files changed, 577 insertions, 18 deletions
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index bad2e174c9..176e1b5499 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -37,6 +37,7 @@
#include "indra_constants.h"
#include "llagent.h"
+#include "llfoldertype.h"
#include "llviewercontrol.h"
#include "llconsole.h"
#include "llinventorymodel.h"
@@ -44,12 +45,15 @@
#include "llimview.h"
#include "llgesturemgr.h"
-#include "llinventoryview.h"
+#include "llinventorybridge.h"
+#include "llfloaterinventory.h"
#include "llviewerregion.h"
#include "llviewerobjectlist.h"
#include "llpreviewgesture.h"
#include "llviewerwindow.h"
+#include "lltrans.h"
+#include "llappearancemgr.h"
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
@@ -117,6 +121,41 @@ LLViewerInventoryItem::~LLViewerInventoryItem()
{
}
+BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(S32* sortField, std::string* displayName) const
+{
+ using std::string;
+ using std::stringstream;
+
+ const char separator = getSeparator();
+ const string::size_type separatorPos = mName.find(separator, 0);
+
+ BOOL result = FALSE;
+
+ if (separatorPos < string::npos)
+ {
+ if (sortField)
+ {
+ /*
+ * The conversion from string to S32 is made this way instead of old plain
+ * atoi() to ensure portability. If on some other platform S32 will not be
+ * defined to be signed int, this conversion will still work because of
+ * operators overloading, but atoi() may fail.
+ */
+ stringstream ss(mName.substr(0, separatorPos));
+ ss >> *sortField;
+ }
+
+ if (displayName)
+ {
+ *displayName = mName.substr(separatorPos + 1, string::npos);
+ }
+
+ result = TRUE;
+ }
+
+ return result;
+}
+
void LLViewerInventoryItem::copyViewerItem(const LLViewerInventoryItem* other)
{
LLInventoryItem::copyItem(other);
@@ -199,10 +238,19 @@ void LLViewerInventoryItem::fetchFromServer(void) const
{
std::string url;
- if( ALEXANDRIA_LINDEN_ID.getString() == mPermissions.getOwner().getString())
- url = gAgent.getRegion()->getCapability("FetchLib");
- else
- url = gAgent.getRegion()->getCapability("FetchInventory");
+ LLViewerRegion* region = gAgent.getRegion();
+ // we have to check region. It can be null after region was destroyed. See EXT-245
+ if (region)
+ {
+ if( ALEXANDRIA_LINDEN_ID.getString() == mPermissions.getOwner().getString())
+ url = region->getCapability("FetchLib");
+ else
+ url = region->getCapability("FetchInventory");
+ }
+ else
+ {
+ llwarns << "Agent Region is absent" << llendl;
+ }
if (!url.empty())
{
@@ -242,8 +290,7 @@ BOOL LLViewerInventoryItem::unpackMessage(LLSD item)
}
// virtual
-BOOL LLViewerInventoryItem::unpackMessage(
- LLMessageSystem* msg, const char* block, S32 block_num)
+BOOL LLViewerInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num)
{
BOOL rv = LLInventoryItem::unpackMessage(msg, block, block_num);
mIsComplete = TRUE;
@@ -402,7 +449,8 @@ void LLViewerInventoryCategory::updateParentOnServer(BOOL restamp) const
void LLViewerInventoryCategory::updateServer(BOOL is_new) const
{
// communicate that change with the server.
- if(LLAssetType::AT_NONE != mPreferredType)
+
+ if (LLAssetType::lookupIsProtectedCategoryType(mPreferredType))
{
LLNotifications::instance().add("CannotModifyProtectedCategories");
return;
@@ -426,7 +474,7 @@ void LLViewerInventoryCategory::removeFromServer( void )
llinfos << "Removing inventory category " << mUUID << " from server."
<< llendl;
// communicate that change with the server.
- if(LLAssetType::AT_NONE != mPreferredType)
+ if(LLAssetType::lookupIsProtectedCategoryType(mPreferredType))
{
LLNotifications::instance().add("CannotRemoveProtectedCategories");
return;
@@ -576,6 +624,76 @@ bool LLViewerInventoryCategory::exportFileLocal(LLFILE* fp) const
return true;
}
+void LLViewerInventoryCategory::determineFolderType()
+{
+ LLAssetType::EType original_type = getPreferredType();
+ if (LLAssetType::lookupIsProtectedCategoryType(original_type))
+ return;
+
+ U64 folder_valid = 0;
+ U64 folder_invalid = 0;
+ LLInventoryModel::cat_array_t category_array;
+ LLInventoryModel::item_array_t item_array;
+ gInventory.collectDescendents(getUUID(),category_array,item_array,FALSE);
+
+ // For ensembles
+ if (category_array.empty())
+ {
+ for (LLInventoryModel::item_array_t::iterator item_iter = item_array.begin();
+ item_iter != item_array.end();
+ item_iter++)
+ {
+ const LLViewerInventoryItem *item = (*item_iter);
+ if (item->getIsLinkType())
+ return;
+ if (item->getInventoryType() == LLInventoryType::IT_WEARABLE)
+ {
+ const EWearableType wearable_type = EWearableType(item->getFlags() & LLInventoryItem::II_FLAGS_WEARABLES_MASK);
+ const std::string& wearable_name = LLWearableDictionary::getTypeName(wearable_type);
+ U64 valid_folder_types = LLFolderType::lookupValidFolderTypes(wearable_name);
+ folder_valid |= valid_folder_types;
+ folder_invalid |= ~valid_folder_types;
+ }
+ }
+ for (U8 i = LLAssetType::AT_FOLDER_ENSEMBLE_START; i <= LLAssetType::AT_FOLDER_ENSEMBLE_END; i++)
+ {
+ if ((folder_valid & (1LL << i)) &&
+ !(folder_invalid & (1LL << i)))
+ {
+ changeType((LLAssetType::EType)i);
+ return;
+ }
+ }
+ }
+ if (LLAssetType::lookupIsEnsembleCategoryType(original_type))
+ {
+ changeType(LLAssetType::AT_NONE);
+ }
+}
+
+void LLViewerInventoryCategory::changeType(LLAssetType::EType new_folder_type)
+{
+ const LLUUID &folder_id = getUUID();
+ const LLUUID &parent_id = getParentUUID();
+ const std::string &name = getName();
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_FolderData);
+ msg->addUUIDFast(_PREHASH_FolderID, folder_id);
+ msg->addUUIDFast(_PREHASH_ParentID, parent_id);
+ msg->addS8Fast(_PREHASH_Type, new_folder_type);
+ msg->addStringFast(_PREHASH_Name, name);
+ gAgent.sendReliableMessage();
+
+ setPreferredType(new_folder_type);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id);
+ gInventory.updateLinkedObjects(folder_id);
+}
+
///----------------------------------------------------------------------------
/// Local function definitions
///----------------------------------------------------------------------------
@@ -643,6 +761,11 @@ void WearOnAvatarCallback::fire(const LLUUID& inv_item)
}
}
+void ModifiedCOFCallback::fire(const LLUUID& inv_item)
+{
+ LLAppearanceManager::instance().updateAppearanceFromCOF();
+}
+
RezAttachmentCallback::RezAttachmentCallback(LLViewerJointAttachment *attachmentp)
{
mAttach = attachmentp;
@@ -663,13 +786,12 @@ void RezAttachmentCallback::fire(const LLUUID& inv_item)
}
}
-extern LLGestureManager gGestureManager;
void ActivateGestureCallback::fire(const LLUUID& inv_item)
{
if (inv_item.isNull())
return;
- gGestureManager.activateGesture(inv_item);
+ LLGestureManager::instance().activateGesture(inv_item);
}
void CreateGestureCallback::fire(const LLUUID& inv_item)
@@ -677,19 +799,16 @@ void CreateGestureCallback::fire(const LLUUID& inv_item)
if (inv_item.isNull())
return;
- gGestureManager.activateGesture(inv_item);
+ LLGestureManager::instance().activateGesture(inv_item);
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (!item) return;
gInventory.updateItem(item);
gInventory.notifyObservers();
- if(!LLPreview::show(inv_item,FALSE))
- {
- LLPreviewGesture* preview = LLPreviewGesture::show(std::string("Gesture: ") + item->getName(), inv_item, LLUUID::null);
- // Force to be entirely onscreen.
- gFloaterView->adjustToFitScreen(preview, FALSE);
- }
+ LLPreviewGesture* preview = LLPreviewGesture::show(inv_item, LLUUID::null);
+ // Force to be entirely onscreen.
+ gFloaterView->adjustToFitScreen(preview, FALSE);
}
LLInventoryCallbackManager gInventoryCallbacks;
@@ -721,6 +840,16 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
gAgent.sendReliableMessage();
}
+void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent /*= LLUUID::null*/, LLPointer<LLInventoryCallback> cb/*=NULL*/)
+{
+ std::string item_desc = avatar_id.asString();
+ std::string item_name;
+ gCacheName->getFullName(avatar_id, item_name);
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
+ parent, LLTransactionID::tnull, item_name, item_desc, LLAssetType::AT_CALLINGCARD,
+ LLInventoryType::IT_CALLINGCARD, NOT_WEARABLE, PERM_MOVE | PERM_TRANSFER, cb);
+}
+
void copy_inventory_item(
const LLUUID& agent_id,
const LLUUID& current_owner,
@@ -743,6 +872,60 @@ void copy_inventory_item(
gAgent.sendReliableMessage();
}
+void link_inventory_item(
+ const LLUUID& agent_id,
+ const LLUUID& item_id,
+ const LLUUID& parent_id,
+ const std::string& new_name,
+ const LLAssetType::EType asset_type,
+ LLPointer<LLInventoryCallback> cb)
+{
+ const LLInventoryObject *baseobj = gInventory.getObject(item_id);
+ if (!baseobj)
+ {
+ llwarns << "attempt to link to unknown item, linked-to-item's itemID " << item_id << llendl;
+ return;
+ }
+ if (baseobj && baseobj->getIsLinkType())
+ {
+ llwarns << "attempt to create a link to a link, linked-to-item's itemID " << item_id << llendl;
+ return;
+ }
+
+ if (baseobj && !LLAssetType::lookupCanLink(baseobj->getType()))
+ {
+ // Fail if item can be found but is of a type that can't be linked.
+ // Arguably should fail if the item can't be found too, but that could
+ // be a larger behavioral change.
+ llwarns << "attempt to link an unlinkable item, type = " << baseobj->getActualType() << llendl;
+ return;
+ }
+
+ LLUUID transaction_id;
+ std::string desc = "Link";
+ LLInventoryType::EType inv_type = LLInventoryType::IT_NONE;
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_LinkInventoryItem);
+ msg->nextBlock(_PREHASH_AgentData);
+ {
+ msg->addUUIDFast(_PREHASH_AgentID, agent_id);
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ }
+ msg->nextBlock(_PREHASH_InventoryBlock);
+ {
+ msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb));
+ msg->addUUIDFast(_PREHASH_FolderID, parent_id);
+ msg->addUUIDFast(_PREHASH_TransactionID, transaction_id);
+ msg->addUUIDFast(_PREHASH_OldItemID, item_id);
+ msg->addS8Fast(_PREHASH_Type, (S8)asset_type);
+ msg->addS8Fast(_PREHASH_InvType, (S8)inv_type);
+ msg->addStringFast(_PREHASH_Name, new_name);
+ msg->addStringFast(_PREHASH_Description, desc);
+ }
+ gAgent.sendReliableMessage();
+}
+
void move_inventory_item(
const LLUUID& agent_id,
const LLUUID& session_id,
@@ -800,3 +983,379 @@ void copy_inventory_from_notecard(const LLUUID& object_id, const LLUUID& notecar
viewer_region->getCapAPI().post(request);
}
+
+void create_new_item(const std::string& name,
+ const LLUUID& parent_id,
+ LLAssetType::EType asset_type,
+ LLInventoryType::EType inv_type,
+ U32 next_owner_perm)
+{
+ std::string desc;
+ LLAssetType::generateDescriptionFor(asset_type, desc);
+ next_owner_perm = (next_owner_perm) ? next_owner_perm : PERM_MOVE | PERM_TRANSFER;
+
+
+ if (inv_type == LLInventoryType::IT_GESTURE)
+ {
+ LLPointer<LLInventoryCallback> cb = new CreateGestureCallback();
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
+ parent_id, LLTransactionID::tnull, name, desc, asset_type, inv_type,
+ NOT_WEARABLE, next_owner_perm, cb);
+ }
+ else
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
+ parent_id, LLTransactionID::tnull, name, desc, asset_type, inv_type,
+ NOT_WEARABLE, next_owner_perm, cb);
+ }
+
+}
+
+const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not)
+const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not)
+const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not)
+
+void menu_create_inventory_item(LLFolderView* folder, LLFolderBridge *bridge, const LLSD& userdata)
+{
+ std::string type = userdata.asString();
+
+ if (("category" == type) || ("current" == type) || ("outfit" == type) || ("my_otfts" == type) )
+ {
+ LLAssetType::EType a_type = LLAssetType::AT_NONE;
+ if ("current" == type)
+ a_type = LLAssetType::AT_CURRENT_OUTFIT;
+ if ("outfit" == type)
+ a_type = LLAssetType::AT_OUTFIT;
+ if ("my_otfts" == type)
+ a_type = LLAssetType::AT_MY_OUTFITS;
+ LLUUID category;
+ if (bridge)
+ {
+ category = gInventory.createNewCategory(bridge->getUUID(), a_type, LLStringUtil::null);
+ }
+ else
+ {
+ category = gInventory.createNewCategory(gInventory.getRootFolderID(), a_type, LLStringUtil::null);
+ }
+ gInventory.notifyObservers();
+ folder->setSelectionByID(category, TRUE);
+ }
+ else if ("lsl" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_LSL_TEXT);
+ create_new_item(NEW_LSL_NAME,
+ parent_id,
+ LLAssetType::AT_LSL_TEXT,
+ LLInventoryType::IT_LSL,
+ PERM_MOVE | PERM_TRANSFER);
+ }
+ else if ("notecard" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_NOTECARD);
+ create_new_item(NEW_NOTECARD_NAME,
+ parent_id,
+ LLAssetType::AT_NOTECARD,
+ LLInventoryType::IT_NOTECARD,
+ PERM_ALL);
+ }
+ else if ("gesture" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_GESTURE);
+ create_new_item(NEW_GESTURE_NAME,
+ parent_id,
+ LLAssetType::AT_GESTURE,
+ LLInventoryType::IT_GESTURE,
+ PERM_ALL);
+ }
+ else if ("shirt" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ LLFolderBridge::createWearable(parent_id, WT_SHIRT);
+ }
+ else if ("pants" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ LLFolderBridge::createWearable(parent_id, WT_PANTS);
+ }
+ else if ("shoes" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ LLFolderBridge::createWearable(parent_id, WT_SHOES);
+ }
+ else if ("socks" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ LLFolderBridge::createWearable(parent_id, WT_SOCKS);
+ }
+ else if ("jacket" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ LLFolderBridge::createWearable(parent_id, WT_JACKET);
+ }
+ else if ("skirt" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ LLFolderBridge::createWearable(parent_id, WT_SKIRT);
+ }
+ else if ("gloves" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ LLFolderBridge::createWearable(parent_id, WT_GLOVES);
+ }
+ else if ("undershirt" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ LLFolderBridge::createWearable(parent_id, WT_UNDERSHIRT);
+ }
+ else if ("underpants" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ LLFolderBridge::createWearable(parent_id, WT_UNDERPANTS);
+ }
+ else if ("shape" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART);
+ LLFolderBridge::createWearable(parent_id, WT_SHAPE);
+ }
+ else if ("skin" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART);
+ LLFolderBridge::createWearable(parent_id, WT_SKIN);
+ }
+ else if ("hair" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART);
+ LLFolderBridge::createWearable(parent_id, WT_HAIR);
+ }
+ else if ("eyes" == type)
+ {
+ LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART);
+ LLFolderBridge::createWearable(parent_id, WT_EYES);
+ }
+
+ folder->setNeedsAutoRename(TRUE);
+}
+
+LLAssetType::EType LLViewerInventoryItem::getType() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getType();
+ }
+ if (const LLViewerInventoryCategory *linked_category = getLinkedCategory())
+ {
+ return linked_category->getType();
+ }
+ return LLInventoryItem::getType();
+}
+
+const LLUUID& LLViewerInventoryItem::getAssetUUID() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getAssetUUID();
+ }
+
+ return LLInventoryItem::getAssetUUID();
+}
+
+const std::string& LLViewerInventoryItem::getName() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getName();
+ }
+ if (const LLViewerInventoryCategory *linked_category = getLinkedCategory())
+ {
+ return linked_category->getName();
+ }
+
+ return getDisplayName();
+}
+
+const std::string& LLViewerInventoryItem::getDisplayName() const
+{
+ std::string result;
+ BOOL hasSortField = extractSortFieldAndDisplayName(0, &result);
+
+ return mDisplayName = hasSortField ? result : LLInventoryItem::getName();
+}
+
+S32 LLViewerInventoryItem::getSortField() const
+{
+ S32 result;
+ BOOL hasSortField = extractSortFieldAndDisplayName(&result, 0);
+
+ return hasSortField ? result : -1;
+}
+
+void LLViewerInventoryItem::setSortField(S32 sortField)
+{
+ using std::string;
+
+ std::stringstream ss;
+ ss << sortField;
+
+ string newSortField = ss.str();
+
+ const char separator = getSeparator();
+ const string::size_type separatorPos = mName.find(separator, 0);
+
+ if (separatorPos < string::npos)
+ {
+ // the name of the LLViewerInventoryItem already consists of sort field and display name.
+ mName = newSortField + separator + mName.substr(separatorPos + 1, string::npos);
+ }
+ else
+ {
+ // there is no sort field in the name of LLViewerInventoryItem, we should add it
+ mName = newSortField + separator + mName;
+ }
+}
+
+void LLViewerInventoryItem::rename(const std::string& n)
+{
+ using std::string;
+
+ string new_name(n);
+ LLStringUtil::replaceNonstandardASCII(new_name, ' ');
+ LLStringUtil::replaceChar(new_name, '|', ' ');
+ LLStringUtil::trim(new_name);
+ LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN);
+
+ const char separator = getSeparator();
+ const string::size_type separatorPos = mName.find(separator, 0);
+
+ if (separatorPos < string::npos)
+ {
+ mName.replace(separatorPos + 1, string::npos, new_name);
+ }
+ else
+ {
+ mName = new_name;
+ }
+}
+
+const LLPermissions& LLViewerInventoryItem::getPermissions() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getPermissions();
+ }
+
+ // Use the actual permissions of the symlink, not its parent.
+ return LLInventoryItem::getPermissions();
+}
+
+const LLUUID& LLViewerInventoryItem::getCreatorUUID() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getCreatorUUID();
+ }
+
+ return LLInventoryItem::getCreatorUUID();
+}
+
+const std::string& LLViewerInventoryItem::getDescription() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getDescription();
+ }
+
+ return LLInventoryItem::getDescription();
+}
+
+const LLSaleInfo& LLViewerInventoryItem::getSaleInfo() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getSaleInfo();
+ }
+
+ return LLInventoryItem::getSaleInfo();
+}
+
+LLInventoryType::EType LLViewerInventoryItem::getInventoryType() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getInventoryType();
+ }
+
+ // Categories don't have types. If this item is an AT_FOLDER_LINK,
+ // treat it as a category.
+ if (getLinkedCategory())
+ {
+ return LLInventoryType::IT_CATEGORY;
+ }
+
+ return LLInventoryItem::getInventoryType();
+}
+
+U32 LLViewerInventoryItem::getFlags() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getFlags();
+ }
+ return LLInventoryItem::getFlags();
+}
+
+time_t LLViewerInventoryItem::getCreationDate() const
+{
+ return LLInventoryItem::getCreationDate();
+}
+
+U32 LLViewerInventoryItem::getCRC32() const
+{
+ return LLInventoryItem::getCRC32();
+}
+
+// This returns true if the item that this item points to
+// doesn't exist in memory (i.e. LLInventoryModel). The baseitem
+// might still be in the database but just not loaded yet.
+bool LLViewerInventoryItem::getIsBrokenLink() const
+{
+ // If the item's type resolves to be a link, that means either:
+ // A. It wasn't able to perform indirection, i.e. the baseobj doesn't exist in memory.
+ // B. It's pointing to another link, which is illegal.
+ return LLAssetType::lookupIsLinkType(getType());
+}
+
+LLViewerInventoryItem *LLViewerInventoryItem::getLinkedItem() const
+{
+ if (mType == LLAssetType::AT_LINK)
+ {
+ LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID);
+ if (linked_item && linked_item->getIsLinkType())
+ {
+ llwarns << "Warning: Accessing link to link" << llendl;
+ return NULL;
+ }
+ return linked_item;
+ }
+ return NULL;
+}
+
+LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const
+{
+ if (mType == LLAssetType::AT_LINK_FOLDER)
+ {
+ LLViewerInventoryCategory *linked_category = gInventory.getCategory(mAssetUUID);
+ return linked_category;
+ }
+ return NULL;
+}
+
+//----------
+
+void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name)
+{
+ rename(first_name + " " + last_name);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, getUUID());
+ gInventory.notifyObservers();
+}
+