summaryrefslogtreecommitdiff
path: root/indra/newview/llinventorymodel.cpp
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2009-11-24 23:21:57 -0600
committerDave Parks <davep@lindenlab.com>2009-11-24 23:21:57 -0600
commite264f00c833805e1f813bc1d0b2cfd7a1bf7b272 (patch)
tree1a64a520502d2ed2c7dadc2316e543ae9e9a91d2 /indra/newview/llinventorymodel.cpp
parentc9e153c182dae9472a2b87cddfec8c47b30b06b9 (diff)
parent5b5354c933aa7b1ceeb307853c24fba28d4e31bf (diff)
Merge
Diffstat (limited to 'indra/newview/llinventorymodel.cpp')
-rw-r--r--indra/newview/llinventorymodel.cpp639
1 files changed, 84 insertions, 555 deletions
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 4b7e364cf9..fbaab385fe 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -31,40 +31,25 @@
*/
#include "llviewerprecompiledheaders.h"
-
#include "llinventorymodel.h"
-#include "llassetstorage.h"
-#include "llcrc.h"
-#include "lldir.h"
-#include "llsys.h"
-#include "llxfermanager.h"
-#include "message.h"
-
#include "llagent.h"
#include "llagentwearables.h"
-#include "llfloater.h"
-#include "llfocusmgr.h"
-#include "llinventorybridge.h"
-#include "llinventoryfunctions.h"
#include "llinventorypanel.h"
#include "llfloaterinventory.h"
-#include "llviewerfoldertype.h"
-#include "llviewerinventory.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llinventoryobserver.h"
+#include "llwindow.h"
+#include "llviewercontrol.h"
+#include "llpreview.h"
#include "llviewermessage.h"
+#include "llviewerfoldertype.h"
#include "llviewerwindow.h"
-#include "llviewerregion.h"
#include "llappviewer.h"
-#include "lldbstrings.h"
-#include "llviewerstats.h"
-#include "llmutelist.h"
-#include "llnotifications.h"
+#include "llviewerregion.h"
#include "llcallbacklist.h"
-#include "llpreview.h"
-#include "llviewercontrol.h"
#include "llvoavatarself.h"
-#include "llsdutil.h"
-#include <deque>
//#define DIFF_INVENTORY_FILES
#ifdef DIFF_INVENTORY_FILES
@@ -176,6 +161,7 @@ LLInventoryModel::LLInventoryModel()
mRootFolderID(),
mLibraryRootFolderID(),
mLibraryOwnerID(),
+ mIsNotifyObservers(FALSE),
mIsAgentInvUsable(false)
{
}
@@ -321,10 +307,10 @@ void LLInventoryModel::unlockDirectDescendentArrays(const LLUUID& cat_id)
// specifies 'type' as what it defaults to containing. The category is
// not necessarily only for that type. *NOTE: This will create a new
// inventory category on the fly if one does not exist.
-const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType t, bool create_folder)
+const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType t, bool create_folder, bool find_in_library)
{
- const LLUUID &rv = findCatUUID(t);
- if(rv.isNull() && isInventoryUsable() && create_folder)
+ const LLUUID &rv = findCatUUID(t, find_in_library);
+ if(rv.isNull() && isInventoryUsable() && (create_folder && !find_in_library))
{
const LLUUID &root_id = gInventory.getRootFolderID();
if(root_id.notNull())
@@ -337,10 +323,10 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType t, bo
// Internal method which looks for a category with the specified
// preferred type. Returns LLUUID::null if not found.
-const LLUUID &LLInventoryModel::findCatUUID(LLFolderType::EType preferred_type) const
+const LLUUID &LLInventoryModel::findCatUUID(LLFolderType::EType preferred_type, bool find_in_library) const
{
- const LLUUID &root_id = gInventory.getRootFolderID();
- if(LLFolderType::FT_CATEGORY == preferred_type)
+ const LLUUID &root_id = (find_in_library) ? gInventory.getLibraryRootFolderID() : gInventory.getRootFolderID();
+ if(LLFolderType::FT_ROOT_INVENTORY == preferred_type)
{
return root_id;
}
@@ -523,7 +509,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
}
}
-void LLInventoryModel::updateLinkedItems(const LLUUID& object_id)
+void LLInventoryModel::addChangedMaskForLinks(const LLUUID& object_id, U32 mask)
{
const LLInventoryObject *obj = getObject(object_id);
if (!obj || obj->getIsLinkType())
@@ -537,13 +523,16 @@ void LLInventoryModel::updateLinkedItems(const LLUUID& object_id)
item_array,
LLInventoryModel::INCLUDE_TRASH,
is_linked_item_match);
-
+ if (cat_array.empty() && item_array.empty())
+ {
+ return;
+ }
for (LLInventoryModel::cat_array_t::iterator cat_iter = cat_array.begin();
cat_iter != cat_array.end();
cat_iter++)
{
LLViewerInventoryCategory *linked_cat = (*cat_iter);
- addChangedMask(LLInventoryObserver::LABEL, linked_cat->getUUID());
+ addChangedMask(mask, linked_cat->getUUID());
};
for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
@@ -551,9 +540,8 @@ void LLInventoryModel::updateLinkedItems(const LLUUID& object_id)
iter++)
{
LLViewerInventoryItem *linked_item = (*iter);
- addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID());
+ addChangedMask(mask, linked_item->getUUID());
};
- notifyObservers();
}
const LLUUID& LLInventoryModel::getLinkedItemID(const LLUUID& object_id) const
@@ -639,6 +627,7 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
new_item = old_item;
LLUUID old_parent_id = old_item->getParentUUID();
LLUUID new_parent_id = item->getParentUUID();
+
if(old_parent_id != new_parent_id)
{
// need to update the parent-child tree
@@ -881,7 +870,8 @@ void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id)
// Delete a particular inventory object by ID.
void LLInventoryModel::deleteObject(const LLUUID& id)
{
- purgeLinkedObjects(id);
+ // Disabling this; let users manually purge linked objects.
+ // purgeLinkedObjects(id);
lldebugs << "LLInventoryModel::deleteObject()" << llendl;
LLPointer<LLInventoryObject> obj = getObject(id);
if(obj)
@@ -918,13 +908,14 @@ void LLInventoryModel::deleteObject(const LLUUID& id)
}
addChangedMask(LLInventoryObserver::REMOVE, id);
obj = NULL; // delete obj
+ gInventory.notifyObservers();
}
}
// Delete a particular inventory item by ID, and remove it from the server.
void LLInventoryModel::purgeObject(const LLUUID &id)
{
- lldebugs << "LLInventoryModel::purgeObject()" << llendl;
+ lldebugs << "LLInventoryModel::purgeObject() [ id: " << id << " ] " << llendl;
LLPointer<LLInventoryObject> obj = getObject(id);
if(obj)
{
@@ -1133,6 +1124,23 @@ BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer) const
// The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328]
void LLInventoryModel::notifyObservers(const std::string service_name)
{
+ if (mIsNotifyObservers)
+ {
+ // Within notifyObservers, something called notifyObservers
+ // again. This type of recursion is unsafe because it causes items to be
+ // processed twice, and this can easily lead to infinite loops.
+ llwarns << "Call was made to notifyObservers within notifyObservers!" << llendl;
+ return;
+ }
+
+ if ((mModifyMask == LLInventoryObserver::NONE) && (service_name == ""))
+ {
+ mModifyMask = LLInventoryObserver::NONE;
+ mChangedItemIDs.clear();
+ return;
+ }
+
+ mIsNotifyObservers = TRUE;
for (observer_list_t::iterator iter = mObservers.begin();
iter != mObservers.end(); )
{
@@ -1154,12 +1162,21 @@ void LLInventoryModel::notifyObservers(const std::string service_name)
mModifyMask = LLInventoryObserver::NONE;
mChangedItemIDs.clear();
+ mIsNotifyObservers = FALSE;
}
// store flag for change
// and id of object change applies to
void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
{
+ if (mIsNotifyObservers)
+ {
+ // Something marked an item for change within a call to notifyObservers
+ // (which is in the process of processing the list of items marked for change).
+ // This means the change may fail to be processed.
+ llwarns << "Adding changed mask within notify observers! Change will likely be lost." << llendl;
+ }
+
mModifyMask |= mask;
if (referent.notNull())
{
@@ -1170,7 +1187,7 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
// not sure what else might need to be accounted for this.
if (mModifyMask & LLInventoryObserver::LABEL)
{
- updateLinkedItems(referent);
+ addChangedMaskForLinks(referent, LLInventoryObserver::LABEL);
}
}
@@ -1189,7 +1206,7 @@ void LLInventoryModel::mock(const LLUUID& root_id)
root_id,
LLUUID::null,
LLAssetType::AT_CATEGORY,
- LLFolderType::lookupNewCategoryName(LLFolderType::FT_ROOT_CATEGORY),
+ LLFolderType::lookupNewCategoryName(LLFolderType::FT_ROOT_INVENTORY),
gAgent.getID());
addCategory(cat);
gInventory.buildParentChildMap();
@@ -1271,8 +1288,11 @@ void LLInventoryModel::fetchInventoryResponder::error(U32 status, const std::str
bool LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id)
{
- if(folder_id.isNull()) return false;
-
+ if(folder_id.isNull())
+ {
+ llwarns << "Calling fetch descendents on NULL folder id!" << llendl;
+ return false;
+ }
LLViewerInventoryCategory* cat = getCategory(folder_id);
if(!cat)
{
@@ -1830,13 +1850,13 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
{
//llinfos << "LLInventoryModel::addItem()" << llendl;
-
- // This can happen if assettype enums change. This can be a backwards compatibility issue
- // in some viewer prototypes prior to when the AT_LINK enum changed from 23 to 24.
+ // This can happen if assettype enums from llassettype.h ever change.
+ // For example, there is a known backwards compatibility issue in some viewer prototypes prior to when
+ // the AT_LINK enum changed from 23 to 24.
if ((item->getType() == LLAssetType::AT_NONE)
|| LLAssetType::lookup(item->getType()) == LLAssetType::badLookup())
{
- llwarns << "Got bad asset type for item ( name: " << item->getName() << " type: " << item->getType() << " inv-type: " << item->getInventoryType() << " ), ignoring." << llendl;
+ llwarns << "Got bad asset type for item [ name: " << item->getName() << " type: " << item->getType() << " inv-type: " << item->getInventoryType() << " ], ignoring." << llendl;
return;
}
if(item)
@@ -1845,7 +1865,7 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
// The item will show up as a broken link.
if (item->getIsBrokenLink())
{
- llinfos << "Adding broken link ( name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << llendl;
+ llinfos << "Adding broken link [ name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << llendl;
}
mItemMap[item->getUUID()] = item;
}
@@ -2173,7 +2193,7 @@ bool LLInventoryModel::loadSkeleton(
// Add all the items loaded which are parented to a
// category with a correctly cached parent
- count = items.count();
+ S32 bad_link_count = 0;
cat_map_t::iterator unparented = mCategoryMap.end();
for(item_array_t::const_iterator item_iter = items.begin();
item_iter != items.end();
@@ -2190,7 +2210,11 @@ bool LLInventoryModel::loadSkeleton(
// This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache.
if (item->getIsBrokenLink())
{
- llinfos << "Attempted to add cached link item without baseobj present ( name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ). Ignoring and invalidating " << cat->getName() << " . " << llendl;
+ bad_link_count++;
+ lldebugs << "Attempted to add cached link item without baseobj present ( name: "
+ << item->getName() << " itemID: " << item->getUUID()
+ << " assetID: " << item->getAssetUUID()
+ << " ). Ignoring and invalidating " << cat->getName() << " . " << llendl;
invalid_categories.insert(cit->second);
continue;
}
@@ -2200,6 +2224,12 @@ bool LLInventoryModel::loadSkeleton(
}
}
}
+ if (bad_link_count > 0)
+ {
+ llinfos << "Attempted to add " << bad_link_count
+ << " cached link items without baseobj present. "
+ << "The corresponding categories were invalidated." << llendl;
+ }
}
else
{
@@ -2427,7 +2457,7 @@ void LLInventoryModel::buildParentChildMap()
{
cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
}
- else if(LLFolderType::FT_CATEGORY == pref)
+ else if(LLFolderType::FT_ROOT_INVENTORY == pref)
{
// it's the root
cat->setParent(LLUUID::null);
@@ -3304,6 +3334,12 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**)
for(i = 0; i < count; ++i)
{
titem->unpackMessage(msg, _PREHASH_ItemData, i);
+ // If the item has already been added (e.g. from link prefetch), then it doesn't need to be re-added.
+ if (gInventory.getItem(titem->getUUID()))
+ {
+ lldebugs << "Skipping prefetched item [ Name: " << titem->getName() << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << llendl;
+ continue;
+ }
gInventory.updateItem(titem);
}
@@ -3679,513 +3715,6 @@ bool LLNameCategoryCollector::operator()(
return false;
}
-
-
-///----------------------------------------------------------------------------
-/// Observers
-///----------------------------------------------------------------------------
-
-void LLInventoryCompletionObserver::changed(U32 mask)
-{
- // scan through the incomplete items and move or erase them as
- // appropriate.
- if(!mIncomplete.empty())
- {
- for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); )
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(!item)
- {
- it = mIncomplete.erase(it);
- continue;
- }
- if(item->isComplete())
- {
- mComplete.push_back(*it);
- it = mIncomplete.erase(it);
- continue;
- }
- ++it;
- }
- if(mIncomplete.empty())
- {
- done();
- }
- }
-}
-
-void LLInventoryCompletionObserver::watchItem(const LLUUID& id)
-{
- if(id.notNull())
- {
- mIncomplete.push_back(id);
- }
-}
-
-
-void LLInventoryFetchObserver::changed(U32 mask)
-{
- // scan through the incomplete items and move or erase them as
- // appropriate.
- if(!mIncomplete.empty())
- {
- for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); )
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(!item)
- {
- // BUG: This can cause done() to get called prematurely below.
- // This happens with the LLGestureInventoryFetchObserver that
- // loads gestures at startup. JC
- it = mIncomplete.erase(it);
- continue;
- }
- if(item->isComplete())
- {
- mComplete.push_back(*it);
- it = mIncomplete.erase(it);
- continue;
- }
- ++it;
- }
- if(mIncomplete.empty())
- {
- done();
- }
- }
- //llinfos << "LLInventoryFetchObserver::changed() mComplete size " << mComplete.size() << llendl;
- //llinfos << "LLInventoryFetchObserver::changed() mIncomplete size " << mIncomplete.size() << llendl;
-}
-
-bool LLInventoryFetchObserver::isEverythingComplete() const
-{
- return mIncomplete.empty();
-}
-
-void fetch_items_from_llsd(const LLSD& items_llsd)
-{
- if (!items_llsd.size()) return;
- LLSD body;
- body[0]["cap_name"] = "FetchInventory";
- body[1]["cap_name"] = "FetchLib";
- for (S32 i=0; i<items_llsd.size();i++)
- {
- if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString())
- {
- body[0]["items"].append(items_llsd[i]);
- continue;
- }
- if (items_llsd[i]["owner_id"].asString() == ALEXANDRIA_LINDEN_ID.asString())
- {
- body[1]["items"].append(items_llsd[i]);
- continue;
- }
- }
-
- for (S32 i=0; i<body.size(); i++)
- {
- if (0 >= body[i].size()) continue;
- std::string url = gAgent.getRegion()->getCapability(body[i]["cap_name"].asString());
-
- if (!url.empty())
- {
- body[i]["agent_id"] = gAgent.getID();
- LLHTTPClient::post(url, body[i], new LLInventoryModel::fetchInventoryResponder(body[i]));
- break;
- }
-
- LLMessageSystem* msg = gMessageSystem;
- BOOL start_new_message = TRUE;
- for (S32 j=0; j<body[i]["items"].size(); j++)
- {
- LLSD item_entry = body[i]["items"][j];
- if(start_new_message)
- {
- start_new_message = FALSE;
- msg->newMessageFast(_PREHASH_FetchInventory);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- }
- msg->nextBlockFast(_PREHASH_InventoryData);
- msg->addUUIDFast(_PREHASH_OwnerID, item_entry["owner_id"].asUUID());
- msg->addUUIDFast(_PREHASH_ItemID, item_entry["item_id"].asUUID());
- if(msg->isSendFull(NULL))
- {
- start_new_message = TRUE;
- gAgent.sendReliableMessage();
- }
- }
- if(!start_new_message)
- {
- gAgent.sendReliableMessage();
- }
- }
-}
-
-void LLInventoryFetchObserver::fetchItems(
- const LLInventoryFetchObserver::item_ref_t& ids)
-{
- LLUUID owner_id;
- LLSD items_llsd;
- for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it)
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(item)
- {
- if(item->isComplete())
- {
- // It's complete, so put it on the complete container.
- mComplete.push_back(*it);
- continue;
- }
- else
- {
- owner_id = item->getPermissions().getOwner();
- }
- }
- else
- {
- // assume it's agent inventory.
- owner_id = gAgent.getID();
- }
-
- // It's incomplete, so put it on the incomplete container, and
- // pack this on the message.
- mIncomplete.push_back(*it);
-
- // Prepare the data to fetch
- LLSD item_entry;
- item_entry["owner_id"] = owner_id;
- item_entry["item_id"] = (*it);
- items_llsd.append(item_entry);
- }
- fetch_items_from_llsd(items_llsd);
-}
-
-// virtual
-void LLInventoryFetchDescendentsObserver::changed(U32 mask)
-{
- for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();)
- {
- LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
- if(!cat)
- {
- it = mIncompleteFolders.erase(it);
- continue;
- }
- if(isComplete(cat))
- {
- mCompleteFolders.push_back(*it);
- it = mIncompleteFolders.erase(it);
- continue;
- }
- ++it;
- }
- if(mIncompleteFolders.empty())
- {
- done();
- }
-}
-
-void LLInventoryFetchDescendentsObserver::fetchDescendents(
- const folder_ref_t& ids)
-{
- for(folder_ref_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
- {
- LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
- if(!cat) continue;
- if(!isComplete(cat))
- {
- cat->fetchDescendents(); //blindly fetch it without seeing if anything else is fetching it.
- mIncompleteFolders.push_back(*it); //Add to list of things being downloaded for this observer.
- }
- else
- {
- mCompleteFolders.push_back(*it);
- }
- }
-}
-
-bool LLInventoryFetchDescendentsObserver::isEverythingComplete() const
-{
- return mIncompleteFolders.empty();
-}
-
-bool LLInventoryFetchDescendentsObserver::isComplete(LLViewerInventoryCategory* cat)
-{
- S32 version = cat->getVersion();
- S32 descendents = cat->getDescendentCount();
- if((LLViewerInventoryCategory::VERSION_UNKNOWN == version)
- || (LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN == descendents))
- {
- return false;
- }
- // it might be complete - check known descendents against
- // currently available.
- LLInventoryModel::cat_array_t* cats;
- LLInventoryModel::item_array_t* items;
- gInventory.getDirectDescendentsOf(cat->getUUID(), cats, items);
- if(!cats || !items)
- {
- // bit of a hack - pretend we're done if they are gone or
- // incomplete. should never know, but it would suck if this
- // kept tight looping because of a corrupt memory state.
- return true;
- }
- S32 known = cats->count() + items->count();
- if(descendents == known)
- {
- // hey - we're done.
- return true;
- }
- return false;
-}
-
-void LLInventoryFetchComboObserver::changed(U32 mask)
-{
- if(!mIncompleteItems.empty())
- {
- for(item_ref_t::iterator it = mIncompleteItems.begin(); it < mIncompleteItems.end(); )
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(!item)
- {
- it = mIncompleteItems.erase(it);
- continue;
- }
- if(item->isComplete())
- {
- mCompleteItems.push_back(*it);
- it = mIncompleteItems.erase(it);
- continue;
- }
- ++it;
- }
- }
- if(!mIncompleteFolders.empty())
- {
- for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();)
- {
- LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
- if(!cat)
- {
- it = mIncompleteFolders.erase(it);
- continue;
- }
- if(gInventory.isCategoryComplete(*it))
- {
- mCompleteFolders.push_back(*it);
- it = mIncompleteFolders.erase(it);
- continue;
- }
- ++it;
- }
- }
- if(!mDone && mIncompleteItems.empty() && mIncompleteFolders.empty())
- {
- mDone = true;
- done();
- }
-}
-
-void LLInventoryFetchComboObserver::fetch(
- const folder_ref_t& folder_ids,
- const item_ref_t& item_ids)
-{
- lldebugs << "LLInventoryFetchComboObserver::fetch()" << llendl;
- for(folder_ref_t::const_iterator fit = folder_ids.begin(); fit != folder_ids.end(); ++fit)
- {
- LLViewerInventoryCategory* cat = gInventory.getCategory(*fit);
- if(!cat) continue;
- if(!gInventory.isCategoryComplete(*fit))
- {
- cat->fetchDescendents();
- lldebugs << "fetching folder " << *fit <<llendl;
- mIncompleteFolders.push_back(*fit);
- }
- else
- {
- mCompleteFolders.push_back(*fit);
- lldebugs << "completing folder " << *fit <<llendl;
- }
- }
-
- // Now for the items - we fetch everything which is not a direct
- // descendent of an incomplete folder because the item will show
- // up in an inventory descendents message soon enough so we do not
- // have to fetch it individually.
- LLSD items_llsd;
- LLUUID owner_id;
- for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit)
- {
- LLViewerInventoryItem* item = gInventory.getItem(*iit);
- if(!item)
- {
- lldebugs << "uanble to find item " << *iit << llendl;
- continue;
- }
- if(item->isComplete())
- {
- // It's complete, so put it on the complete container.
- mCompleteItems.push_back(*iit);
- lldebugs << "completing item " << *iit << llendl;
- continue;
- }
- else
- {
- mIncompleteItems.push_back(*iit);
- owner_id = item->getPermissions().getOwner();
- }
- if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end())
- {
- LLSD item_entry;
- item_entry["owner_id"] = owner_id;
- item_entry["item_id"] = (*iit);
- items_llsd.append(item_entry);
- }
- else
- {
- lldebugs << "not worrying about " << *iit << llendl;
- }
- }
- fetch_items_from_llsd(items_llsd);
-}
-
-void LLInventoryExistenceObserver::watchItem(const LLUUID& id)
-{
- if(id.notNull())
- {
- mMIA.push_back(id);
- }
-}
-
-void LLInventoryExistenceObserver::changed(U32 mask)
-{
- // scan through the incomplete items and move or erase them as
- // appropriate.
- if(!mMIA.empty())
- {
- for(item_ref_t::iterator it = mMIA.begin(); it < mMIA.end(); )
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(!item)
- {
- ++it;
- continue;
- }
- mExist.push_back(*it);
- it = mMIA.erase(it);
- }
- if(mMIA.empty())
- {
- done();
- }
- }
-}
-
-void LLInventoryAddedObserver::changed(U32 mask)
-{
- if(!(mask & LLInventoryObserver::ADD))
- {
- return;
- }
-
- // *HACK: If this was in response to a packet off
- // the network, figure out which item was updated.
- LLMessageSystem* msg = gMessageSystem;
-
- std::string msg_name;
- if (mMessageName.empty())
- {
- msg_name = msg->getMessageName();
- }
- else
- {
- msg_name = mMessageName;
- }
-
- if (msg_name.empty())
- {
- return;
- }
-
- // We only want newly created inventory items. JC
- if ( msg_name != "UpdateCreateInventoryItem")
- {
- return;
- }
-
- LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
- S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
- for(S32 i = 0; i < num_blocks; ++i)
- {
- titem->unpackMessage(msg, _PREHASH_InventoryData, i);
- if (!(titem->getUUID().isNull()))
- {
- //we don't do anything with null keys
- mAdded.push_back(titem->getUUID());
- }
- }
- if (!mAdded.empty())
- {
- done();
- }
-}
-
-LLInventoryTransactionObserver::LLInventoryTransactionObserver(
- const LLTransactionID& transaction_id) :
- mTransactionID(transaction_id)
-{
-}
-
-void LLInventoryTransactionObserver::changed(U32 mask)
-{
- if(mask & LLInventoryObserver::ADD)
- {
- // This could be it - see if we are processing a bulk update
- LLMessageSystem* msg = gMessageSystem;
- if(msg->getMessageName()
- && (0 == strcmp(msg->getMessageName(), "BulkUpdateInventory")))
- {
- // we have a match for the message - now check the
- // transaction id.
- LLUUID id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, id);
- if(id == mTransactionID)
- {
- // woo hoo, we found it
- folder_ref_t folders;
- item_ref_t items;
- S32 count;
- count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
- S32 i;
- for(i = 0; i < count; ++i)
- {
- msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, id, i);
- if(id.notNull())
- {
- folders.push_back(id);
- }
- }
- count = msg->getNumberOfBlocksFast(_PREHASH_ItemData);
- for(i = 0; i < count; ++i)
- {
- msg->getUUIDFast(_PREHASH_ItemData, _PREHASH_ItemID, id, i);
- if(id.notNull())
- {
- items.push_back(id);
- }
- }
-
- // call the derived class the implements this method.
- done(folders, items);
- }
- }
- }
-}
-
-
///----------------------------------------------------------------------------
/// LLAssetIDMatches
///----------------------------------------------------------------------------