00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llinventorymodel.h"
00035
00036 #include "llassetstorage.h"
00037 #include "llcrc.h"
00038 #include "lldir.h"
00039 #include "llsys.h"
00040 #include "llxfermanager.h"
00041 #include "message.h"
00042
00043 #include "llagent.h"
00044 #include "llfloater.h"
00045 #include "llfocusmgr.h"
00046 #include "llinventoryview.h"
00047 #include "llviewerinventory.h"
00048 #include "llviewermessage.h"
00049 #include "llviewerwindow.h"
00050 #include "viewer.h"
00051 #include "lldbstrings.h"
00052 #include "llviewerstats.h"
00053 #include "llmutelist.h"
00054 #include "llnotify.h"
00055 #include "llcallbacklist.h"
00056 #include "llpreview.h"
00057 #include <deque>
00058
00059
00060 #ifdef DIFF_INVENTORY_FILES
00061 #include "process.h"
00062 #endif
00063
00064 BOOL LLInventoryModel::sBackgroundFetchActive = FALSE;
00065 BOOL LLInventoryModel::sAllFoldersFetched = FALSE;
00066 BOOL LLInventoryModel::sFullFetchStarted = FALSE;
00067 S32 LLInventoryModel::sNumFetchRetries = 0;
00068 F32 LLInventoryModel::sMinTimeBetweenFetches = 0.3f;
00069 F32 LLInventoryModel::sMaxTimeBetweenFetches = 10.f;
00070 BOOL LLInventoryModel::sTimelyFetchPending = FALSE;
00071 LLFrameTimer LLInventoryModel::sFetchTimer;
00072
00073
00074 static std::deque<LLUUID> sFetchQueue;
00075
00079
00080
00081 const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f;
00082 const S32 MAX_FETCH_RETRIES = 5;
00083 const char CACHE_FORMAT_STRING[] = "%s.inv";
00084 const char* NEW_CATEGORY_NAME = "New Folder";
00085 const char* NEW_CATEGORY_NAMES[LLAssetType::AT_COUNT] =
00086 {
00087 "Textures",
00088 "Sounds",
00089 "Calling Cards",
00090 "Landmarks",
00091 "Scripts",
00092 "Clothing",
00093 "Objects",
00094 "Notecards",
00095 "New Folder",
00096 "Inventory",
00097 "Scripts",
00098 "Scripts",
00099 "Uncompressed Images",
00100 "Body Parts",
00101 "Trash",
00102 "Photo Album",
00103 "Lost And Found",
00104 "Uncompressed Sounds",
00105 "Uncompressed Images",
00106 "Uncompressed Images",
00107 "Animations",
00108 "Gestures",
00109 };
00110
00111 struct InventoryIDPtrLess
00112 {
00113 bool operator()(const LLViewerInventoryCategory* i1, const LLViewerInventoryCategory* i2) const
00114 {
00115 return (i1->getUUID() < i2->getUUID());
00116 }
00117 };
00118
00119 class LLCanCache : public LLInventoryCollectFunctor
00120 {
00121 public:
00122 LLCanCache(LLInventoryModel* model) : mModel(model) {}
00123 virtual ~LLCanCache() {}
00124 virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
00125 protected:
00126 LLInventoryModel* mModel;
00127 std::set<LLUUID> mCachedCatIDs;
00128 };
00129
00130 bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
00131 {
00132 bool rv = false;
00133 if(item)
00134 {
00135 if(mCachedCatIDs.find(item->getParentUUID()) != mCachedCatIDs.end())
00136 {
00137 rv = true;
00138 }
00139 }
00140 else if(cat)
00141 {
00142
00143 LLViewerInventoryCategory* c = (LLViewerInventoryCategory*)cat;
00144 if(c->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
00145 {
00146 S32 descendents_server = c->getDescendentCount();
00147 LLInventoryModel::cat_array_t* cats;
00148 LLInventoryModel::item_array_t* items;
00149 mModel->getDirectDescendentsOf(
00150 c->getUUID(),
00151 cats,
00152 items);
00153 S32 descendents_actual = 0;
00154 if(cats && items)
00155 {
00156 descendents_actual = cats->count() + items->count();
00157 }
00158 if(descendents_server == descendents_actual)
00159 {
00160 mCachedCatIDs.insert(c->getUUID());
00161 rv = true;
00162 }
00163 }
00164 }
00165 return rv;
00166 }
00167
00171
00172
00173 LLInventoryModel gInventory;
00174
00175
00176 LLInventoryModel::LLInventoryModel() :
00177 mModifyMask(LLInventoryObserver::ALL),
00178 mLastItem(NULL),
00179 mIsAgentInvUsable(false)
00180 {
00181 }
00182
00183
00184 LLInventoryModel::~LLInventoryModel()
00185 {
00186 empty();
00187 for (observer_list_t::iterator iter = mObservers.begin();
00188 iter != mObservers.end(); ++iter)
00189 {
00190 delete *iter;
00191 }
00192 }
00193
00194
00195
00196 BOOL LLInventoryModel::isObjectDescendentOf(const LLUUID& obj_id,
00197 const LLUUID& cat_id)
00198 {
00199 LLInventoryObject* obj = getObject(obj_id);
00200 while(obj)
00201 {
00202 const LLUUID& parent_id = obj->getParentUUID();
00203 if( parent_id.isNull() )
00204 {
00205 return FALSE;
00206 }
00207 if(parent_id == cat_id)
00208 {
00209 return TRUE;
00210 }
00211
00212
00213 obj = getCategory(parent_id);
00214 }
00215 return FALSE;
00216 }
00217
00218
00219 LLInventoryObject* LLInventoryModel::getObject(const LLUUID& id) const
00220 {
00221 LLViewerInventoryCategory* cat = getCategory(id);
00222 if (cat)
00223 {
00224 return cat;
00225 }
00226 LLViewerInventoryItem* item = getItem(id);
00227 if (item)
00228 {
00229 return item;
00230 }
00231 return NULL;
00232 }
00233
00234
00235 LLViewerInventoryItem* LLInventoryModel::getItem(const LLUUID& id) const
00236 {
00237 LLViewerInventoryItem* item = NULL;
00238 if(mLastItem.notNull() && mLastItem->getUUID() == id)
00239 {
00240 item = mLastItem;
00241 }
00242 else
00243 {
00244 item_map_t::const_iterator iter = mItemMap.find(id);
00245 if (iter != mItemMap.end())
00246 {
00247 item = iter->second;
00248 mLastItem = item;
00249 }
00250 }
00251 return item;
00252 }
00253
00254
00255 LLViewerInventoryCategory* LLInventoryModel::getCategory(const LLUUID& id) const
00256 {
00257 LLViewerInventoryCategory* category = NULL;
00258 cat_map_t::const_iterator iter = mCategoryMap.find(id);
00259 if (iter != mCategoryMap.end())
00260 {
00261 category = iter->second;
00262 }
00263 return category;
00264 }
00265
00266 S32 LLInventoryModel::getItemCount() const
00267 {
00268 return mItemMap.size();
00269 }
00270
00271 S32 LLInventoryModel::getCategoryCount() const
00272 {
00273 return mCategoryMap.size();
00274 }
00275
00276
00277
00278
00279
00280
00281 void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id,
00282 cat_array_t*& categories,
00283 item_array_t*& items) const
00284 {
00285 categories = get_ptr_in_map(mParentChildCategoryTree, cat_id);
00286 items = get_ptr_in_map(mParentChildItemTree, cat_id);
00287 }
00288
00289
00290
00291
00292
00293 LLUUID LLInventoryModel::findCategoryUUIDForType(LLAssetType::EType t, bool create_folder)
00294 {
00295 LLUUID rv = findCatUUID(t);
00296 if(rv.isNull() && isInventoryUsable() && create_folder)
00297 {
00298 LLUUID root_id = gAgent.getInventoryRootID();
00299 if(root_id.notNull())
00300 {
00301 rv = createNewCategory(root_id, t, NULL);
00302 }
00303 }
00304 return rv;
00305 }
00306
00307
00308
00309 LLUUID LLInventoryModel::findCatUUID(LLAssetType::EType preferred_type)
00310 {
00311 LLUUID root_id = gAgent.getInventoryRootID();
00312 if(LLAssetType::AT_CATEGORY == preferred_type)
00313 {
00314 return root_id;
00315 }
00316 if(root_id.notNull())
00317 {
00318 cat_array_t* cats = NULL;
00319 cats = get_ptr_in_map(mParentChildCategoryTree, root_id);
00320 if(cats)
00321 {
00322 S32 count = cats->count();
00323 for(S32 i = 0; i < count; ++i)
00324 {
00325 if(cats->get(i)->getPreferredType() == preferred_type)
00326 {
00327 return cats->get(i)->getUUID();
00328 }
00329 }
00330 }
00331 }
00332 return LLUUID::null;
00333 }
00334
00335
00336
00337
00338
00339 LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
00340 LLAssetType::EType preferred_type,
00341 const LLString& pname)
00342 {
00343 LLUUID id;
00344 if(!isInventoryUsable())
00345 {
00346 llwarns << "Inventory is broken." << llendl;
00347 return id;
00348 }
00349
00350 id.generate();
00351 LLString name = pname;
00352 if(!pname.empty())
00353 {
00354 name.assign(pname);
00355 }
00356 else if((preferred_type >= LLAssetType::AT_TEXTURE) &&
00357 (preferred_type < LLAssetType::AT_COUNT))
00358 {
00359 name.assign(NEW_CATEGORY_NAMES[preferred_type]);
00360 }
00361 else
00362 {
00363 name.assign(NEW_CATEGORY_NAME);
00364 }
00365
00366
00367 LLPointer<LLViewerInventoryCategory> cat =
00368 new LLViewerInventoryCategory(id, parent_id, preferred_type, name, gAgent.getID());
00369 cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL);
00370 cat->setDescendentCount(0);
00371 LLCategoryUpdate update(cat->getParentUUID(), 1);
00372 accountForUpdate(update);
00373 updateCategory(cat);
00374
00375
00376
00377 LLMessageSystem* msg = gMessageSystem;
00378 msg->newMessage("CreateInventoryFolder");
00379 msg->nextBlock("AgentData");
00380 msg->addUUID("AgentID", gAgent.getID());
00381 msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
00382 msg->nextBlock("FolderData");
00383 cat->packMessage(msg);
00384 gAgent.sendReliableMessage();
00385
00386
00387 return id;
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397 class LLAlwaysCollect : public LLInventoryCollectFunctor
00398 {
00399 public:
00400 virtual ~LLAlwaysCollect() {}
00401 virtual bool operator()(LLInventoryCategory* cat,
00402 LLInventoryItem* item)
00403 {
00404 return TRUE;
00405 }
00406 };
00407
00408 void LLInventoryModel::collectDescendents(const LLUUID& id,
00409 cat_array_t& cats,
00410 item_array_t& items,
00411 BOOL include_trash)
00412 {
00413 LLAlwaysCollect always;
00414 collectDescendentsIf(id, cats, items, include_trash, always);
00415 }
00416
00417 void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
00418 cat_array_t& cats,
00419 item_array_t& items,
00420 BOOL include_trash,
00421 LLInventoryCollectFunctor& add)
00422 {
00423
00424 if(!include_trash)
00425 {
00426 LLUUID trash_id(findCatUUID(LLAssetType::AT_TRASH));
00427 if(trash_id.notNull() && (trash_id == id))
00428 return;
00429 }
00430 cat_array_t* cat_array = get_ptr_in_map(mParentChildCategoryTree, id);
00431 if(cat_array)
00432 {
00433 S32 count = cat_array->count();
00434 for(S32 i = 0; i < count; ++i)
00435 {
00436 LLViewerInventoryCategory* cat = cat_array->get(i);
00437 if(add(cat,NULL))
00438 {
00439 cats.put(cat);
00440 }
00441 collectDescendentsIf(cat->getUUID(), cats, items, include_trash, add);
00442 }
00443 }
00444
00445
00446 LLViewerInventoryItem* item = NULL;
00447 item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, id);
00448 if(item_array)
00449 {
00450 S32 count = item_array->count();
00451 for(S32 i = 0; i < count; ++i)
00452 {
00453 item = item_array->get(i);
00454 if(add(NULL, item))
00455 {
00456 items.put(item);
00457 }
00458 }
00459 }
00460 }
00461
00462
00463
00464 void LLInventoryModel::appendPath(const LLUUID& id, LLString& path)
00465 {
00466 LLString temp;
00467 LLInventoryObject* obj = getObject(id);
00468 LLUUID parent_id;
00469 if(obj) parent_id = obj->getParentUUID();
00470 LLString forward_slash("/");
00471 while(obj)
00472 {
00473 obj = getCategory(parent_id);
00474 if(obj)
00475 {
00476 temp.assign(forward_slash + obj->getName() + temp);
00477 parent_id = obj->getParentUUID();
00478 }
00479 }
00480 path.append(temp);
00481 }
00482
00483 bool LLInventoryModel::isInventoryUsable()
00484 {
00485 bool result = false;
00486 if(gAgent.getInventoryRootID().notNull() && mIsAgentInvUsable)
00487 {
00488 result = true;
00489 }
00490 return result;
00491 }
00492
00493
00494
00495
00496 U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
00497 {
00498 U32 mask = LLInventoryObserver::NONE;
00499 if(item->getUUID().isNull())
00500 {
00501 return mask;
00502 }
00503
00504 if(!isInventoryUsable())
00505 {
00506 llwarns << "Inventory is broken." << llendl;
00507 return mask;
00508 }
00509
00510 LLViewerInventoryItem* old_item = getItem(item->getUUID());
00511 if(old_item)
00512 {
00513
00514 LLUUID old_parent_id = old_item->getParentUUID();
00515 LLUUID new_parent_id = item->getParentUUID();
00516 if(old_parent_id != new_parent_id)
00517 {
00518
00519 item_array_t* item_array;
00520 item_array = get_ptr_in_map(mParentChildItemTree, old_parent_id);
00521 if(item_array)
00522 {
00523 item_array->removeObj(old_item);
00524 }
00525 item_array = get_ptr_in_map(mParentChildItemTree, new_parent_id);
00526 if(item_array)
00527 {
00528 item_array->put(old_item);
00529 }
00530 mask |= LLInventoryObserver::STRUCTURE;
00531 }
00532 if(old_item->getName() != item->getName())
00533 {
00534 mask |= LLInventoryObserver::LABEL;
00535 }
00536 old_item->copy(item);
00537 mask |= LLInventoryObserver::INTERNAL;
00538 }
00539 else
00540 {
00541
00542 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
00543 addItem(new_item);
00544
00545 if(item->getParentUUID().isNull())
00546 {
00547 LLUUID category_id = findCategoryUUIDForType(new_item->getType());
00548 new_item->setParent(category_id);
00549 item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, category_id);
00550 if( item_array )
00551 {
00552
00553 new_item->updateServer(TRUE);
00554 item_array->put(new_item);
00555 }
00556 else
00557 {
00558 llwarns << "Couldn't find parent-child item tree for " << new_item->getName() << llendl;
00559 }
00560 }
00561 else
00562 {
00563
00564
00565
00566
00567
00568 LLUUID parent_id = item->getParentUUID();
00569 if(parent_id == CATEGORIZE_LOST_AND_FOUND_ID)
00570 {
00571 parent_id = findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
00572 new_item->setParent(parent_id);
00573 }
00574 item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, parent_id);
00575 if(item_array)
00576 {
00577 item_array->put(new_item);
00578 }
00579 else
00580 {
00581
00582 llinfos << "Lost item: " << new_item->getUUID() << " - "
00583 << new_item->getName() << llendl;
00584 parent_id = findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
00585 new_item->setParent(parent_id);
00586 item_array = get_ptr_in_map(mParentChildItemTree, parent_id);
00587 if(item_array)
00588 {
00589
00590
00591 new_item->updateServer(TRUE);
00592 item_array->put(new_item);
00593 }
00594 else
00595 {
00596 llwarns << "Lost and found Not there!!" << llendl;
00597 }
00598 }
00599 }
00600 mask |= LLInventoryObserver::ADD;
00601 }
00602 if(item->getType() == LLAssetType::AT_CALLINGCARD)
00603 {
00604 mask |= LLInventoryObserver::CALLING_CARD;
00605 }
00606 addChangedMask(mask, item->getUUID());
00607 return mask;
00608 }
00609
00610
00611
00612 void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat)
00613 {
00614 if(cat->getUUID().isNull())
00615 {
00616 return;
00617 }
00618
00619 if(!isInventoryUsable())
00620 {
00621 llwarns << "Inventory is broken." << llendl;
00622 return;
00623 }
00624
00625 LLViewerInventoryCategory* old_cat = getCategory(cat->getUUID());
00626 if(old_cat)
00627 {
00628
00629 U32 mask = LLInventoryObserver::NONE;
00630 LLUUID old_parent_id = old_cat->getParentUUID();
00631 LLUUID new_parent_id = cat->getParentUUID();
00632 if(old_parent_id != new_parent_id)
00633 {
00634
00635 cat_array_t* cat_array;
00636 cat_array = get_ptr_in_map(mParentChildCategoryTree, old_parent_id);
00637 if(cat_array)
00638 {
00639 cat_array->removeObj(old_cat);
00640 }
00641 cat_array = get_ptr_in_map(mParentChildCategoryTree, new_parent_id);
00642 if(cat_array)
00643 {
00644 cat_array->put(old_cat);
00645 }
00646 mask |= LLInventoryObserver::STRUCTURE;
00647 }
00648 if(old_cat->getName() != cat->getName())
00649 {
00650 mask |= LLInventoryObserver::LABEL;
00651 }
00652 old_cat->copy(cat);
00653 addChangedMask(mask, cat->getUUID());
00654 }
00655 else
00656 {
00657
00658 LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat->getParentUUID());
00659 new_cat->copy(cat);
00660 addCategory(new_cat);
00661
00662
00663 cat_array_t* cat_array;
00664 cat_array = get_ptr_in_map(mParentChildCategoryTree, cat->getParentUUID());
00665 if(cat_array)
00666 {
00667 cat_array->put(new_cat);
00668 }
00669
00670
00671 cat_array_t* catsp = new cat_array_t;
00672 item_array_t* itemsp = new item_array_t;
00673 mParentChildCategoryTree[new_cat->getUUID()] = catsp;
00674 mParentChildItemTree[new_cat->getUUID()] = itemsp;
00675 addChangedMask(LLInventoryObserver::ADD, cat->getUUID());
00676 }
00677 }
00678
00679 void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id)
00680 {
00681 lldebugs << "LLInventoryModel::moveObject()" << llendl;
00682 if(!isInventoryUsable())
00683 {
00684 llwarns << "Inventory is broken." << llendl;
00685 return;
00686 }
00687
00688 if((object_id == cat_id) || !is_in_map(mCategoryMap, cat_id))
00689 {
00690 llwarns << "Could not move inventory object " << object_id << " to "
00691 << cat_id << llendl;
00692 return;
00693 }
00694 LLViewerInventoryCategory* cat = getCategory(object_id);
00695 if(cat && (cat->getParentUUID() != cat_id))
00696 {
00697 cat_array_t* cat_array;
00698 cat_array = get_ptr_in_map(mParentChildCategoryTree, cat->getParentUUID());
00699 if(cat_array) cat_array->removeObj(cat);
00700 cat_array = get_ptr_in_map(mParentChildCategoryTree, cat_id);
00701 cat->setParent(cat_id);
00702 if(cat_array) cat_array->put(cat);
00703 addChangedMask(LLInventoryObserver::STRUCTURE, object_id);
00704 return;
00705 }
00706 LLViewerInventoryItem* item = getItem(object_id);
00707 if(item && (item->getParentUUID() != cat_id))
00708 {
00709 item_array_t* item_array;
00710 item_array = get_ptr_in_map(mParentChildItemTree, item->getParentUUID());
00711 if(item_array) item_array->removeObj(item);
00712 item_array = get_ptr_in_map(mParentChildItemTree, cat_id);
00713 item->setParent(cat_id);
00714 if(item_array) item_array->put(item);
00715 addChangedMask(LLInventoryObserver::STRUCTURE, object_id);
00716 return;
00717 }
00718 }
00719
00720
00721 void LLInventoryModel::deleteObject(const LLUUID& id)
00722 {
00723 lldebugs << "LLInventoryModel::deleteObject()" << llendl;
00724 LLPointer<LLInventoryObject> obj = getObject(id);
00725 if(obj)
00726 {
00727 lldebugs << "Deleting inventory object " << id << llendl;
00728 mLastItem = NULL;
00729 LLUUID parent_id = obj->getParentUUID();
00730 mCategoryMap.erase(id);
00731 mItemMap.erase(id);
00732
00733 item_array_t* item_list = get_ptr_in_map(mParentChildItemTree, parent_id);
00734 if(item_list)
00735 {
00736 LLViewerInventoryItem* item = (LLViewerInventoryItem*)((LLInventoryObject*)obj);
00737 item_list->removeObj(item);
00738 }
00739 cat_array_t* cat_list = get_ptr_in_map(mParentChildCategoryTree, parent_id);
00740 if(cat_list)
00741 {
00742 LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)((LLInventoryObject*)obj);
00743 cat_list->removeObj(cat);
00744 }
00745 item_list = get_ptr_in_map(mParentChildItemTree, id);
00746 if(item_list)
00747 {
00748 delete item_list;
00749 mParentChildItemTree.erase(id);
00750 }
00751 cat_list = get_ptr_in_map(mParentChildCategoryTree, id);
00752 if(cat_list)
00753 {
00754 delete cat_list;
00755 mParentChildCategoryTree.erase(id);
00756 }
00757 addChangedMask(LLInventoryObserver::REMOVE, id);
00758 obj = NULL;
00759 }
00760 }
00761
00762
00763
00764
00765
00766
00767 void LLInventoryModel::purgeDescendentsOf(const LLUUID& id)
00768 {
00769 EHasChildren children = categoryHasChildren(id);
00770 if(children == CHILDREN_NO)
00771 {
00772 llinfos << "Not purging descendents of " << id << llendl;
00773 return;
00774 }
00775 LLPointer<LLViewerInventoryCategory> cat = getCategory(id);
00776 if(cat.notNull())
00777 {
00778
00779 llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName()
00780 << llendl;
00781 S32 descendents = cat->getDescendentCount();
00782 if(descendents > 0)
00783 {
00784 LLCategoryUpdate up(id, -descendents);
00785 accountForUpdate(up);
00786 }
00787
00788
00789
00790
00791 cat->setDescendentCount(0);
00792
00793
00794 LLMessageSystem* msg = gMessageSystem;
00795 msg->newMessage("PurgeInventoryDescendents");
00796 msg->nextBlock("AgentData");
00797 msg->addUUID("AgentID", gAgent.getID());
00798 msg->addUUID("SessionID", gAgent.getSessionID());
00799 msg->nextBlock("InventoryData");
00800 msg->addUUID("FolderID", id);
00801 gAgent.sendReliableMessage();
00802
00803
00804 cat_array_t categories;
00805 item_array_t items;
00806 collectDescendents(id,
00807 categories,
00808 items,
00809 INCLUDE_TRASH);
00810 S32 count = items.count();
00811 S32 i;
00812 for(i = 0; i < count; ++i)
00813 {
00814 deleteObject(items.get(i)->getUUID());
00815 }
00816 count = categories.count();
00817 for(i = 0; i < count; ++i)
00818 {
00819 deleteObject(categories.get(i)->getUUID());
00820 }
00821 }
00822 }
00823
00824 void LLInventoryModel::deleteFromServer(LLDynamicArray<LLUUID>& category_ids,
00825 LLDynamicArray<LLUUID>& item_ids)
00826 {
00827
00828
00829
00830
00831
00832 std::set<LLUUID> ignore_parents;
00833 update_map_t inc_parents;
00834
00835 S32 i;
00836 S32 count = category_ids.count();
00837 BOOL start_new_message = TRUE;
00838 LLMessageSystem* msg = gMessageSystem;
00839 LLPointer<LLViewerInventoryCategory> cat;
00840 for(i = 0; i < count; i++)
00841 {
00842 if(start_new_message)
00843 {
00844 start_new_message = FALSE;
00845 msg->newMessageFast(_PREHASH_RemoveInventoryObjects);
00846 msg->nextBlockFast(_PREHASH_AgentData);
00847 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00848 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00849 }
00850 LLUUID cat_id = category_ids.get(i);
00851
00852 msg->nextBlockFast(_PREHASH_FolderData);
00853 msg->addUUIDFast(_PREHASH_FolderID, cat_id);
00854 cat = getCategory(cat_id);
00855 ignore_parents.insert(cat_id);
00856 addChangedMask(LLInventoryObserver::REMOVE | LLInventoryObserver::STRUCTURE, cat_id);
00857 if(cat.notNull() && (ignore_parents.find(cat->getParentUUID())==ignore_parents.end()))
00858 {
00859 --inc_parents[cat->getParentUUID()];
00860 }
00861 if(msg->isSendFullFast(_PREHASH_FolderData))
00862 {
00863 start_new_message = TRUE;
00864 msg->nextBlockFast(_PREHASH_ItemData);
00865 msg->addUUIDFast(_PREHASH_ItemID, LLUUID::null);
00866 gAgent.sendReliableMessage();
00867 accountForUpdate(inc_parents);
00868 inc_parents.clear();
00869 }
00870 }
00871
00872 count = item_ids.count();
00873 std::set<LLUUID>::iterator not_ignored = ignore_parents.end();
00874 LLPointer<LLViewerInventoryItem> item;
00875 if((0 == count) && (!start_new_message))
00876 {
00877 msg->nextBlockFast(_PREHASH_ItemData);
00878 msg->addUUIDFast(_PREHASH_ItemID, LLUUID::null);
00879 }
00880 for(i = 0; i < count; i++)
00881 {
00882 if(start_new_message)
00883 {
00884 start_new_message = FALSE;
00885 msg->newMessageFast(_PREHASH_RemoveInventoryObjects);
00886 msg->nextBlockFast(_PREHASH_AgentData);
00887 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00888 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00889 msg->nextBlockFast(_PREHASH_FolderData);
00890 msg->addUUIDFast(_PREHASH_FolderID, LLUUID::null);
00891 }
00892 LLUUID item_id = item_ids.get(i);
00893 msg->nextBlockFast(_PREHASH_ItemData);
00894 msg->addUUIDFast(_PREHASH_ItemID, item_id);
00895 item = getItem(item_id);
00896 addChangedMask(LLInventoryObserver::REMOVE | LLInventoryObserver::STRUCTURE, item_id);
00897 if(item.notNull() && (ignore_parents.find(item->getParentUUID()) == not_ignored))
00898 {
00899 --inc_parents[item->getParentUUID()];
00900 }
00901 if(msg->isSendFullFast(_PREHASH_ItemData))
00902 {
00903 start_new_message = TRUE;
00904 gAgent.sendReliableMessage();
00905 accountForUpdate(inc_parents);
00906 inc_parents.clear();
00907 }
00908 }
00909 if(!start_new_message)
00910 {
00911 gAgent.sendReliableMessage();
00912 accountForUpdate(inc_parents);
00913 }
00914 }
00915
00916
00917
00918 void LLInventoryModel::addObserver(LLInventoryObserver* observer)
00919 {
00920 mObservers.insert(observer);
00921 }
00922
00923 void LLInventoryModel::removeObserver(LLInventoryObserver* observer)
00924 {
00925 mObservers.erase(observer);
00926 }
00927
00928
00929
00930
00931 void LLInventoryModel::notifyObservers()
00932 {
00933 for (observer_list_t::iterator iter = mObservers.begin();
00934 iter != mObservers.end(); )
00935 {
00936 LLInventoryObserver* observer = *iter;
00937 observer->changed(mModifyMask);
00938
00939 iter = mObservers.upper_bound(observer);
00940 }
00941
00942 mModifyMask = LLInventoryObserver::NONE;
00943 mChangedItemIDs.clear();
00944 }
00945
00946
00947
00948 void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
00949 {
00950 mModifyMask |= mask;
00951 if (referent.notNull())
00952 {
00953 mChangedItemIDs.insert(referent);
00954 }
00955 }
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 void LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id)
00980 {
00981 LLViewerInventoryCategory* cat = getCategory(folder_id);
00982 if(!cat)
00983 {
00984 llwarns << "Asked to fetch descendents of non-existent folder: "
00985 << folder_id << llendl;
00986 return;
00987 }
00988
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999 if(!cat->fetchDescendents())
01000 {
01001
01002 }
01003 }
01004
01005
01006 bool LLInventoryModel::isEverythingFetched()
01007 {
01008 return (sAllFoldersFetched ? true : false);
01009 }
01010
01011
01012 BOOL LLInventoryModel::backgroundFetchActive()
01013 {
01014 return sBackgroundFetchActive;
01015 }
01016
01017
01018 void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)
01019 {
01020 if (!sAllFoldersFetched)
01021 {
01022 sBackgroundFetchActive = TRUE;
01023 if (cat_id.isNull())
01024 {
01025 if (!sFullFetchStarted)
01026 {
01027 sFullFetchStarted = TRUE;
01028 sFetchQueue.push_back(gInventoryLibraryRoot);
01029 sFetchQueue.push_back(gAgent.getInventoryRootID());
01030 gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
01031 }
01032 }
01033 else
01034 {
01035
01036 if (sFetchQueue.empty() || sFetchQueue.front() != cat_id)
01037 {
01038 sFetchQueue.push_front(cat_id);
01039 gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
01040 }
01041 }
01042 }
01043 }
01044
01045
01046 void LLInventoryModel::stopBackgroundFetch()
01047 {
01048 if (sBackgroundFetchActive)
01049 {
01050 sBackgroundFetchActive = FALSE;
01051 gIdleCallbacks.deleteFunction(&LLInventoryModel::backgroundFetch, NULL);
01052 }
01053 }
01054
01055
01056 void LLInventoryModel::backgroundFetch(void*)
01057 {
01058 if (sBackgroundFetchActive)
01059 {
01060
01061 if (sFetchQueue.empty())
01062 {
01063 llinfos << "Inventory fetch completed" << llendl;
01064 if (sFullFetchStarted)
01065 {
01066 sAllFoldersFetched = TRUE;
01067 }
01068 stopBackgroundFetch();
01069 return;
01070 }
01071
01072 F32 fast_fetch_time = lerp(sMinTimeBetweenFetches, sMaxTimeBetweenFetches, 0.1f);
01073 F32 slow_fetch_time = lerp(sMinTimeBetweenFetches, sMaxTimeBetweenFetches, 0.5f);
01074 if (sTimelyFetchPending && sFetchTimer.getElapsedTimeF32() > slow_fetch_time)
01075 {
01076
01077 sMinTimeBetweenFetches = llmin(sMinTimeBetweenFetches * 2.f, 10.f);
01078 sMaxTimeBetweenFetches = llmin(sMaxTimeBetweenFetches * 2.f, 120.f);
01079 llinfos << "Inventory fetch times grown to (" << sMinTimeBetweenFetches << ", " << sMaxTimeBetweenFetches << ")" << llendl;
01080
01081 sTimelyFetchPending = FALSE;
01082 }
01083
01084 while(1)
01085 {
01086 if (sFetchQueue.empty())
01087 {
01088 break;
01089 }
01090
01091 if(gDisconnected)
01092 {
01093
01094 break;
01095 }
01096
01097 LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front());
01098
01099
01100 if (!cat)
01101 {
01102 sFetchQueue.pop_front();
01103 continue;
01104 }
01105
01106 if (sFetchTimer.getElapsedTimeF32() > sMinTimeBetweenFetches &&
01107 LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
01108 {
01109
01110
01111 if (cat->fetchDescendents())
01112 {
01113 sFetchTimer.reset();
01114 sTimelyFetchPending = TRUE;
01115 }
01116 else
01117 {
01118
01119
01120
01121 break;
01122 }
01123 }
01124
01125 else if (gInventory.isCategoryComplete(sFetchQueue.front()))
01126 {
01127
01128 sFetchQueue.pop_front();
01129
01130
01131 parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID());
01132 if (cat_it != gInventory.mParentChildCategoryTree.end())
01133 {
01134 cat_array_t* child_categories = cat_it->second;
01135
01136 for (S32 child_num = 0; child_num < child_categories->count(); child_num++)
01137 {
01138 sFetchQueue.push_back(child_categories->get(child_num)->getUUID());
01139 }
01140 }
01141
01142
01143 if (sTimelyFetchPending && sFetchTimer.getElapsedTimeF32() < fast_fetch_time)
01144 {
01145
01146 sMinTimeBetweenFetches = llmax(sMinTimeBetweenFetches * 0.8f, 0.3f);
01147 sMaxTimeBetweenFetches = llmax(sMaxTimeBetweenFetches * 0.8f, 10.f);
01148
01149 }
01150
01151 sTimelyFetchPending = FALSE;
01152 continue;
01153 }
01154 else if (sFetchTimer.getElapsedTimeF32() > sMaxTimeBetweenFetches)
01155 {
01156
01157
01158 LLUUID fetch_id = sFetchQueue.front();
01159 sFetchQueue.pop_front();
01160
01161 if (sNumFetchRetries++ < MAX_FETCH_RETRIES)
01162 {
01163
01164 sFetchQueue.push_back(fetch_id);
01165 }
01166 sTimelyFetchPending = FALSE;
01167 sFetchTimer.reset();
01168 break;
01169 }
01170
01171
01172 break;
01173 }
01174 }
01175 }
01176
01177 void LLInventoryModel::cache(
01178 const LLUUID& parent_folder_id,
01179 const LLUUID& agent_id)
01180 {
01181 lldebugs << "Caching " << parent_folder_id << " for " << agent_id
01182 << llendl;
01183 LLViewerInventoryCategory* root_cat = getCategory(parent_folder_id);
01184 if(!root_cat) return;
01185 cat_array_t categories;
01186 categories.put(root_cat);
01187 item_array_t items;
01188
01189 LLCanCache can_cache(this);
01190 can_cache(root_cat, NULL);
01191 collectDescendentsIf(
01192 parent_folder_id,
01193 categories,
01194 items,
01195 INCLUDE_TRASH,
01196 can_cache);
01197 char agent_id_str[UUID_STR_LENGTH];
01198 char inventory_filename[LL_MAX_PATH];
01199 agent_id.toString(agent_id_str);
01200 std::string path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, agent_id_str));
01201 snprintf(
01202 inventory_filename,
01203 LL_MAX_PATH,
01204 CACHE_FORMAT_STRING,
01205 path.c_str());
01206 saveToFile(inventory_filename, categories, items);
01207 std::string gzip_filename(inventory_filename);
01208 gzip_filename.append(".gz");
01209 if(gzip_file(inventory_filename, gzip_filename.c_str()))
01210 {
01211 lldebugs << "Successfully compressed " << inventory_filename << llendl;
01212 LLFile::remove(inventory_filename);
01213 }
01214 else
01215 {
01216 llwarns << "Unable to compress " << inventory_filename << llendl;
01217 }
01218 }
01219
01220
01221 void LLInventoryModel::addCategory(LLViewerInventoryCategory* category)
01222 {
01223
01224 if(category)
01225 {
01226
01227 mCategoryMap[category->getUUID()] = category;
01228
01229 }
01230 }
01231
01232 void LLInventoryModel::addItem(LLViewerInventoryItem* item)
01233 {
01234
01235 if(item)
01236 {
01237 mItemMap[item->getUUID()] = item;
01238
01239 }
01240 }
01241
01242
01243 void LLInventoryModel::empty()
01244 {
01245
01246 std::for_each(
01247 mParentChildCategoryTree.begin(),
01248 mParentChildCategoryTree.end(),
01249 DeletePairedPointer());
01250 mParentChildCategoryTree.clear();
01251 std::for_each(
01252 mParentChildItemTree.begin(),
01253 mParentChildItemTree.end(),
01254 DeletePairedPointer());
01255 mParentChildItemTree.clear();
01256 mCategoryMap.clear();
01257 mItemMap.clear();
01258 mLastItem = NULL;
01259
01260 }
01261
01262 void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update)
01263 {
01264 LLViewerInventoryCategory* cat = getCategory(update.mCategoryID);
01265 if(cat)
01266 {
01267 bool accounted = false;
01268 S32 version = cat->getVersion();
01269 if(version != LLViewerInventoryCategory::VERSION_UNKNOWN)
01270 {
01271 S32 descendents_server = cat->getDescendentCount();
01272 LLInventoryModel::cat_array_t* cats;
01273 LLInventoryModel::item_array_t* items;
01274 getDirectDescendentsOf(update.mCategoryID, cats, items);
01275 S32 descendents_actual = 0;
01276 if(cats && items)
01277 {
01278 descendents_actual = cats->count() + items->count();
01279 }
01280 if(descendents_server == descendents_actual)
01281 {
01282 accounted = true;
01283 descendents_actual += update.mDescendentDelta;
01284 cat->setDescendentCount(descendents_actual);
01285 cat->setVersion(++version);
01286 llinfos << "accounted: '" << cat->getName() << "' "
01287 << version << " with " << descendents_actual
01288 << " descendents." << llendl;
01289 }
01290 }
01291 if(!accounted)
01292 {
01293 lldebugs << "No accounting for: '" << cat->getName() << "' "
01294 << version << llendl;
01295 }
01296 }
01297 else
01298 {
01299 llwarns << "No category found for update " << update.mCategoryID
01300 << llendl;
01301 }
01302 }
01303
01304 void LLInventoryModel::accountForUpdate(
01305 const LLInventoryModel::update_list_t& update)
01306 {
01307 update_list_t::const_iterator it = update.begin();
01308 update_list_t::const_iterator end = update.end();
01309 for(; it != end; ++it)
01310 {
01311 accountForUpdate(*it);
01312 }
01313 }
01314
01315 void LLInventoryModel::accountForUpdate(
01316 const LLInventoryModel::update_map_t& update)
01317 {
01318 LLCategoryUpdate up;
01319 update_map_t::const_iterator it = update.begin();
01320 update_map_t::const_iterator end = update.end();
01321 for(; it != end; ++it)
01322 {
01323 up.mCategoryID = (*it).first;
01324 up.mDescendentDelta = (*it).second.mValue;
01325 accountForUpdate(up);
01326 }
01327 }
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370 LLInventoryModel::EHasChildren LLInventoryModel::categoryHasChildren(
01371 const LLUUID& cat_id) const
01372 {
01373 LLViewerInventoryCategory* cat = getCategory(cat_id);
01374 if(!cat) return CHILDREN_NO;
01375 if(cat->getDescendentCount() > 0)
01376 {
01377 return CHILDREN_YES;
01378 }
01379 if(cat->getDescendentCount() == 0)
01380 {
01381 return CHILDREN_NO;
01382 }
01383 if((cat->getDescendentCount() == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)
01384 || (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN))
01385 {
01386 return CHILDREN_MAYBE;
01387 }
01388
01389
01390 parent_cat_map_t::const_iterator cat_it = mParentChildCategoryTree.find(cat->getUUID());
01391 if (cat_it != mParentChildCategoryTree.end() && cat_it->second->count() > 0)
01392 {
01393 return CHILDREN_YES;
01394 }
01395 parent_item_map_t::const_iterator item_it = mParentChildItemTree.find(cat->getUUID());
01396 if (item_it != mParentChildItemTree.end() && item_it->second->count() > 0)
01397 {
01398 return CHILDREN_YES;
01399 }
01400
01401 return CHILDREN_NO;
01402 }
01403
01404 bool LLInventoryModel::isCategoryComplete(const LLUUID& cat_id) const
01405 {
01406 LLViewerInventoryCategory* cat = getCategory(cat_id);
01407 if(cat && (cat->getVersion()!=LLViewerInventoryCategory::VERSION_UNKNOWN))
01408 {
01409 S32 descendents_server = cat->getDescendentCount();
01410 LLInventoryModel::cat_array_t* cats;
01411 LLInventoryModel::item_array_t* items;
01412 getDirectDescendentsOf(cat_id, cats, items);
01413 S32 descendents_actual = 0;
01414 if(cats && items)
01415 {
01416 descendents_actual = cats->count() + items->count();
01417 }
01418 if(descendents_server == descendents_actual)
01419 {
01420 return true;
01421 }
01422 }
01423 return false;
01424 }
01425
01426 bool LLInventoryModel::loadSkeleton(
01427 const LLInventoryModel::options_t& options,
01428 const LLUUID& owner_id)
01429 {
01430 lldebugs << "importing inventory skeleton for " << owner_id << llendl;
01431
01432 typedef std::set<LLPointer<LLViewerInventoryCategory>, InventoryIDPtrLess> cat_set_t;
01433 cat_set_t temp_cats;
01434
01435 update_map_t child_counts;
01436
01437 LLUUID id;
01438 LLAssetType::EType preferred_type;
01439 bool rv = true;
01440 for(options_t::const_iterator it = options.begin(); it < options.end(); ++it)
01441 {
01442 LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(owner_id);
01443 response_t::const_iterator no_response = (*it).end();
01444 response_t::const_iterator skel;
01445 skel = (*it).find("name");
01446 if(skel == no_response) goto clean_cat;
01447 cat->rename(LLString((*skel).second.c_str()));
01448 skel = (*it).find("folder_id");
01449 if(skel == no_response) goto clean_cat;
01450 id.set((*skel).second.c_str());
01451
01452 if(id.isNull()) goto clean_cat;
01453 cat->setUUID(id);
01454 skel = (*it).find("parent_id");
01455 if(skel == no_response) goto clean_cat;
01456 id.set((*skel).second.c_str());
01457 cat->setParent(id);
01458 skel = (*it).find("type_default");
01459 if(skel == no_response)
01460 {
01461 preferred_type = LLAssetType::AT_NONE;
01462 }
01463 else
01464 {
01465 S32 t = atoi((*skel).second.c_str());
01466 preferred_type = (LLAssetType::EType)t;
01467 }
01468 cat->setPreferredType(preferred_type);
01469 skel = (*it).find("version");
01470 if(skel == no_response) goto clean_cat;
01471 cat->setVersion(atoi((*skel).second.c_str()));
01472 temp_cats.insert(cat);
01473 continue;
01474 clean_cat:
01475 llwarns << "Unable to import near " << cat->getName() << llendl;
01476 rv = false;
01477
01478 }
01479
01480 S32 cached_category_count = 0;
01481 S32 cached_item_count = 0;
01482 if(!temp_cats.empty())
01483 {
01484 cat_array_t categories;
01485 item_array_t items;
01486 char owner_id_str[UUID_STR_LENGTH];
01487 owner_id.toString(owner_id_str);
01488 std::string path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, owner_id_str));
01489 char inventory_filename[LL_MAX_PATH];
01490 snprintf(
01491 inventory_filename,
01492 LL_MAX_PATH,
01493 CACHE_FORMAT_STRING,
01494 path.c_str());
01495 const S32 NO_VERSION = LLViewerInventoryCategory::VERSION_UNKNOWN;
01496 std::string gzip_filename(inventory_filename);
01497 gzip_filename.append(".gz");
01498 FILE* fp = LLFile::fopen(gzip_filename.c_str(), "rb");
01499 bool remove_inventory_file = false;
01500 if(fp)
01501 {
01502 fclose(fp);
01503 fp = NULL;
01504 if(gunzip_file(gzip_filename.c_str(), inventory_filename))
01505 {
01506
01507
01508
01509 remove_inventory_file = true;
01510 }
01511 else
01512 {
01513 llinfos << "Unable to gunzip " << gzip_filename << llendl;
01514 }
01515 }
01516 if(loadFromFile(inventory_filename, categories, items))
01517 {
01518
01519
01520
01521
01522 S32 count = categories.count();
01523 cat_set_t::iterator not_cached = temp_cats.end();
01524 std::set<LLUUID> cached_ids;
01525 for(S32 i = 0; i < count; ++i)
01526 {
01527 LLViewerInventoryCategory* cat = categories[i];
01528 cat_set_t::iterator cit = temp_cats.find(cat);
01529 if (cit == temp_cats.end())
01530 {
01531 continue;
01532 }
01533 LLViewerInventoryCategory* tcat = *cit;
01534
01535
01536
01537 if(cit == not_cached)
01538 {
01539 continue;
01540 }
01541 if(cat->getVersion() != tcat->getVersion())
01542 {
01543
01544
01545
01546 tcat->setVersion(NO_VERSION);
01547 }
01548 else
01549 {
01550 cached_ids.insert(tcat->getUUID());
01551 }
01552 }
01553
01554
01555 std::set<LLUUID>::iterator not_cached_id = cached_ids.end();
01556 cached_category_count = cached_ids.size();
01557 for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
01558 {
01559 if(cached_ids.find((*it)->getUUID()) == not_cached_id)
01560 {
01561
01562
01563
01564 LLViewerInventoryCategory *llvic = (*it);
01565 llvic->setVersion(NO_VERSION);
01566 }
01567 addCategory(*it);
01568 ++child_counts[(*it)->getParentUUID()];
01569 }
01570
01571
01572
01573 count = items.count();
01574 cat_map_t::iterator unparented = mCategoryMap.end();
01575 for(int i = 0; i < count; ++i)
01576 {
01577 cat_map_t::iterator cit = mCategoryMap.find(items[i]->getParentUUID());
01578
01579 if(cit != unparented)
01580 {
01581 LLViewerInventoryCategory* cat = cit->second;
01582 if(cat->getVersion() != NO_VERSION)
01583 {
01584 addItem(items[i]);
01585 cached_item_count += 1;
01586 ++child_counts[cat->getUUID()];
01587 }
01588 }
01589 }
01590 }
01591 else
01592 {
01593
01594
01595 for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
01596 {
01597 LLViewerInventoryCategory *llvic = (*it);
01598 llvic->setVersion(NO_VERSION);
01599 addCategory(*it);
01600 }
01601 }
01602
01603
01604
01605
01606 update_map_t::iterator no_child_counts = child_counts.end();
01607 update_map_t::iterator the_count;
01608 for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
01609 {
01610 LLViewerInventoryCategory* cat = (*it);
01611 if(cat->getVersion() != NO_VERSION)
01612 {
01613 the_count = child_counts.find(cat->getUUID());
01614 if(the_count != no_child_counts)
01615 {
01616 cat->setDescendentCount((*the_count).second.mValue);
01617 }
01618 else
01619 {
01620 cat->setDescendentCount(0);
01621 }
01622 }
01623 }
01624
01625 if(remove_inventory_file)
01626 {
01627
01628 LLFile::remove(inventory_filename);
01629 }
01630 categories.clear();
01631 }
01632
01633 llinfos << "Successfully loaded " << cached_category_count
01634 << " categories and " << cached_item_count << " items from cache."
01635 << llendl;
01636
01637 return rv;
01638 }
01639
01640 bool LLInventoryModel::loadMeat(
01641 const LLInventoryModel::options_t& options, const LLUUID& owner_id)
01642 {
01643 llinfos << "importing inventory for " << owner_id << llendl;
01644 LLPermissions default_perm;
01645 default_perm.init(LLUUID::null, owner_id, LLUUID::null, LLUUID::null);
01646 LLPointer<LLViewerInventoryItem> item;
01647 LLUUID id;
01648 LLAssetType::EType type;
01649 LLInventoryType::EType inv_type;
01650 bool rv = true;
01651 for(options_t::const_iterator it = options.begin(); it < options.end(); ++it)
01652 {
01653 item = new LLViewerInventoryItem;
01654 response_t::const_iterator no_response = (*it).end();
01655 response_t::const_iterator meat;
01656 meat = (*it).find("name");
01657 if(meat == no_response) goto clean_item;
01658 item->rename(LLString((*meat).second.c_str()));
01659 meat = (*it).find("item_id");
01660 if(meat == no_response) goto clean_item;
01661 id.set((*meat).second.c_str());
01662 item->setUUID(id);
01663 meat = (*it).find("parent_id");
01664 if(meat == no_response) goto clean_item;
01665 id.set((*meat).second.c_str());
01666 item->setParent(id);
01667 meat = (*it).find("type");
01668 if(meat == no_response) goto clean_item;
01669 type = (LLAssetType::EType)atoi((*meat).second.c_str());
01670 item->setType(type);
01671 meat = (*it).find("inv_type");
01672 if(meat != no_response)
01673 {
01674 inv_type = (LLInventoryType::EType)atoi((*meat).second.c_str());
01675 item->setInventoryType(inv_type);
01676 }
01677 meat = (*it).find("data_id");
01678 if(meat == no_response) goto clean_item;
01679 id.set((*meat).second.c_str());
01680 if(LLAssetType::AT_CALLINGCARD == type)
01681 {
01682 LLPermissions perm;
01683 perm.init(id, owner_id, LLUUID::null, LLUUID::null);
01684 item->setPermissions(perm);
01685 }
01686 else
01687 {
01688 meat = (*it).find("perm_mask");
01689 if(meat != no_response)
01690 {
01691 PermissionMask perm_mask = atoi((*meat).second.c_str());
01692 default_perm.initMasks(
01693 perm_mask, perm_mask, perm_mask, perm_mask, perm_mask);
01694 }
01695 else
01696 {
01697 default_perm.initMasks(
01698 PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE);
01699 }
01700 item->setPermissions(default_perm);
01701 item->setAssetUUID(id);
01702 }
01703 meat = (*it).find("flags");
01704 if(meat != no_response)
01705 {
01706 item->setFlags(strtoul((*meat).second.c_str(), NULL, 0));
01707 }
01708 meat = (*it).find("time");
01709 if(meat != no_response)
01710 {
01711 item->setCreationDate(atoi((*meat).second.c_str()));
01712 }
01713 addItem(item);
01714 continue;
01715 clean_item:
01716 llwarns << "Unable to import near " << item->getName() << llendl;
01717 rv = false;
01718
01719 }
01720 return rv;
01721 }
01722
01723
01724
01725
01726 void LLInventoryModel::buildParentChildMap()
01727 {
01728 llinfos << "LLInventoryModel::buildParentChildMap()" << llendl;
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738 cat_array_t cats;
01739 cat_array_t* catsp;
01740 item_array_t* itemsp;
01741
01742 for(cat_map_t::iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
01743 {
01744 LLViewerInventoryCategory* cat = cit->second;
01745 cats.put(cat);
01746 if (mParentChildCategoryTree.count(cat->getUUID()) == 0)
01747 {
01748 catsp = new cat_array_t;
01749 mParentChildCategoryTree[cat->getUUID()] = catsp;
01750 }
01751 if (mParentChildItemTree.count(cat->getUUID()) == 0)
01752 {
01753 itemsp = new item_array_t;
01754 mParentChildItemTree[cat->getUUID()] = itemsp;
01755 }
01756 }
01757
01758
01759
01760
01761
01762 if (mParentChildCategoryTree.count(LLUUID::null) == 0)
01763 {
01764 catsp = new cat_array_t;
01765 mParentChildCategoryTree[LLUUID::null] = catsp;
01766 }
01767
01768
01769
01770
01771 S32 count = cats.count();
01772 S32 i;
01773 S32 lost = 0;
01774 for(i = 0; i < count; ++i)
01775 {
01776 LLViewerInventoryCategory* cat = cats.get(i);
01777 catsp = get_ptr_in_map(mParentChildCategoryTree, cat->getParentUUID());
01778 if(catsp)
01779 {
01780 catsp->put(cat);
01781 }
01782 else
01783 {
01784
01785
01786
01787
01788
01789
01790 llinfos << "Lost categroy: " << cat->getUUID() << " - "
01791 << cat->getName() << llendl;
01792 ++lost;
01793
01794 LLAssetType::EType pref = cat->getPreferredType();
01795 if(LLAssetType::AT_NONE == pref)
01796 {
01797 cat->setParent(findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND));
01798 }
01799 else if(LLAssetType::AT_CATEGORY == pref)
01800 {
01801
01802 cat->setParent(LLUUID::null);
01803 }
01804 else
01805 {
01806
01807 cat->setParent(gAgent.getInventoryRootID());
01808 }
01809 cat->updateServer(TRUE);
01810 catsp = get_ptr_in_map(mParentChildCategoryTree, cat->getParentUUID());
01811 if(catsp)
01812 {
01813 catsp->put(cat);
01814 }
01815 else
01816 {
01817 llwarns << "Lost and found Not there!!" << llendl;
01818 }
01819 }
01820 }
01821 if(lost)
01822 {
01823 llwarns << "Found " << lost << " lost categories." << llendl;
01824 }
01825
01826
01827
01828
01829 item_array_t items;
01830 if(!mItemMap.empty())
01831 {
01832 LLPointer<LLViewerInventoryItem> item;
01833 for(item_map_t::iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
01834 {
01835 item = (*iit).second;
01836 items.put(item);
01837 }
01838 }
01839 count = items.count();
01840 lost = 0;
01841 std::vector<LLUUID> lost_item_ids;
01842 for(i = 0; i < count; ++i)
01843 {
01844 LLPointer<LLViewerInventoryItem> item;
01845 item = items.get(i);
01846 itemsp = get_ptr_in_map(mParentChildItemTree, item->getParentUUID());
01847 if(itemsp)
01848 {
01849 itemsp->put(item);
01850 }
01851 else
01852 {
01853 llinfos << "Lost item: " << item->getUUID() << " - "
01854 << item->getName() << llendl;
01855 ++lost;
01856
01857
01858 item->setParent(findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND));
01859
01860
01861
01862 lost_item_ids.push_back(item->getUUID());
01863 itemsp = get_ptr_in_map(mParentChildItemTree, item->getParentUUID());
01864 if(itemsp)
01865 {
01866 itemsp->put(item);
01867 }
01868 else
01869 {
01870 llwarns << "Lost and found Not there!!" << llendl;
01871 }
01872 }
01873 }
01874 if(lost)
01875 {
01876 llwarns << "Found " << lost << " lost items." << llendl;
01877 LLMessageSystem* msg = gMessageSystem;
01878 BOOL start_new_message = TRUE;
01879 LLUUID lnf = findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
01880 for(std::vector<LLUUID>::iterator it = lost_item_ids.begin() ; it < lost_item_ids.end(); ++it)
01881 {
01882 if(start_new_message)
01883 {
01884 start_new_message = FALSE;
01885 msg->newMessageFast(_PREHASH_MoveInventoryItem);
01886 msg->nextBlockFast(_PREHASH_AgentData);
01887 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
01888 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01889 msg->addBOOLFast(_PREHASH_Stamp, FALSE);
01890 }
01891 msg->nextBlockFast(_PREHASH_InventoryData);
01892 msg->addUUIDFast(_PREHASH_ItemID, (*it));
01893 msg->addUUIDFast(_PREHASH_FolderID, lnf);
01894 msg->addString("NewName", NULL);
01895 if(msg->isSendFull(NULL))
01896 {
01897 start_new_message = TRUE;
01898 gAgent.sendReliableMessage();
01899 }
01900 }
01901 if(!start_new_message)
01902 {
01903 gAgent.sendReliableMessage();
01904 }
01905 }
01906
01907 const LLUUID& agent_inv_root_id = gAgent.getInventoryRootID();
01908 if (agent_inv_root_id.notNull())
01909 {
01910 cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id);
01911 if(catsp)
01912 {
01913
01914
01915
01916 mIsAgentInvUsable = true;
01917 }
01918 }
01919 }
01920
01921 struct LLUUIDAndName
01922 {
01923 LLUUIDAndName() {}
01924 LLUUIDAndName(const LLUUID& id, const LLString& name);
01925 bool operator==(const LLUUIDAndName& rhs) const;
01926 bool operator<(const LLUUIDAndName& rhs) const;
01927 bool operator>(const LLUUIDAndName& rhs) const;
01928
01929 LLUUID mID;
01930 LLString mName;
01931 };
01932
01933 LLUUIDAndName::LLUUIDAndName(const LLUUID& id, const LLString& name) :
01934 mID(id), mName(name)
01935 {
01936 }
01937
01938 bool LLUUIDAndName::operator==(const LLUUIDAndName& rhs) const
01939 {
01940 return ((mID == rhs.mID) && (mName == rhs.mName));
01941 }
01942
01943 bool LLUUIDAndName::operator<(const LLUUIDAndName& rhs) const
01944 {
01945 return (mID < rhs.mID);
01946 }
01947
01948 bool LLUUIDAndName::operator>(const LLUUIDAndName& rhs) const
01949 {
01950 return (mID > rhs.mID);
01951 }
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021 bool LLInventoryModel::loadFromFile(
02022 const char* filename,
02023 LLInventoryModel::cat_array_t& categories,
02024 LLInventoryModel::item_array_t& items)
02025 {
02026 if(!filename)
02027 {
02028 llerrs << "Filename is Null!" << llendl;
02029 return false;
02030 }
02031 llinfos << "LLInventoryModel::loadFromFile(" << filename << ")" << llendl;
02032 FILE* file = LLFile::fopen(filename, "rb");
02033 if(!file)
02034 {
02035 llinfos << "unable to load inventory from: " << filename << llendl;
02036 return false;
02037 }
02038
02039 char buffer[MAX_STRING];
02040 char keyword[MAX_STRING];
02041 while(!feof(file) && fgets(buffer, MAX_STRING, file))
02042 {
02043 sscanf(buffer, " %254s", keyword);
02044 if(0 == strcmp("inv_category", keyword))
02045 {
02046 LLPointer<LLViewerInventoryCategory> inv_cat = new LLViewerInventoryCategory(LLUUID::null);
02047 if(inv_cat->importFileLocal(file))
02048 {
02049 categories.put(inv_cat);
02050 }
02051 else
02052 {
02053 llwarns << "loadInventoryFromFile(). Ignoring invalid inventory category: " << inv_cat->getName() << llendl;
02054
02055 }
02056 }
02057 else if(0 == strcmp("inv_item", keyword))
02058 {
02059 LLPointer<LLViewerInventoryItem> inv_item = new LLViewerInventoryItem;
02060 if( inv_item->importFileLocal(file) )
02061 {
02062
02063
02064
02065 if(inv_item->getUUID().isNull())
02066 {
02067
02068 llwarns << "Ignoring inventory with null item id: "
02069 << inv_item->getName() << llendl;
02070
02071 }
02072 else
02073 {
02074 items.put(inv_item);
02075 }
02076 }
02077 else
02078 {
02079 llwarns << "loadInventoryFromFile(). Ignoring invalid inventory item: " << inv_item->getName() << llendl;
02080
02081 }
02082 }
02083 else
02084 {
02085 llwarns << "Unknown token in inventory file '" << keyword << "'"
02086 << llendl;
02087 }
02088 }
02089 fclose(file);
02090 return true;
02091 }
02092
02093
02094 bool LLInventoryModel::saveToFile(
02095 const char* filename,
02096 const cat_array_t& categories,
02097 const item_array_t& items)
02098 {
02099 if(!filename)
02100 {
02101 llerrs << "Filename is Null!" << llendl;
02102 return false;
02103 }
02104 llinfos << "LLInventoryModel::saveToFile(" << filename << ")" << llendl;
02105 FILE* file = LLFile::fopen(filename, "wb");
02106 if(!file)
02107 {
02108 llwarns << "unable to save inventory to: " << filename << llendl;
02109 return false;
02110 }
02111
02112 S32 count = categories.count();
02113 S32 i;
02114 for(i = 0; i < count; ++i)
02115 {
02116 LLViewerInventoryCategory* cat = categories[i];
02117 if(cat->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
02118 {
02119 cat->exportFileLocal(file);
02120 }
02121 }
02122
02123 count = items.count();
02124 for(i = 0; i < count; ++i)
02125 {
02126 items[i]->exportFile(file);
02127 }
02128
02129 fclose(file);
02130 return true;
02131 }
02132
02133
02134
02135 void LLInventoryModel::registerCallbacks(LLMessageSystem* msg)
02136 {
02137
02138
02139
02140
02141
02142
02143 msg->setHandlerFuncFast(_PREHASH_UpdateCreateInventoryItem,
02144 processUpdateCreateInventoryItem,
02145 NULL);
02146 msg->setHandlerFuncFast(_PREHASH_RemoveInventoryItem,
02147 processRemoveInventoryItem,
02148 NULL);
02149 msg->setHandlerFuncFast(_PREHASH_UpdateInventoryFolder,
02150 processUpdateInventoryFolder,
02151 NULL);
02152 msg->setHandlerFuncFast(_PREHASH_RemoveInventoryFolder,
02153 processRemoveInventoryFolder,
02154 NULL);
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164 msg->setHandlerFuncFast(_PREHASH_SaveAssetIntoInventory,
02165 processSaveAssetIntoInventory,
02166 NULL);
02167 msg->setHandlerFuncFast(_PREHASH_BulkUpdateInventory,
02168 processBulkUpdateInventory,
02169 NULL);
02170 msg->setHandlerFunc("InventoryDescendents", processInventoryDescendents);
02171 msg->setHandlerFunc("MoveInventoryItem", processMoveInventoryItem);
02172 msg->setHandlerFunc("FetchInventoryReply", processFetchInventoryReply);
02173 }
02174
02175
02176
02177 void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, void**)
02178 {
02179
02180 if (gInventory.messageUpdateCore(msg, true))
02181 {
02182 U32 callback_id;
02183 LLUUID item_id;
02184 msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_ItemID, item_id);
02185 msg->getU32Fast(_PREHASH_InventoryData, _PREHASH_CallbackID, callback_id);
02186
02187 gInventoryCallbacks.fire(callback_id, item_id);
02188 }
02189
02190 }
02191
02192
02193 void LLInventoryModel::processFetchInventoryReply(LLMessageSystem* msg, void**)
02194 {
02195
02196 gInventory.messageUpdateCore(msg, false);
02197 }
02198
02199
02200 bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account)
02201 {
02202
02203 start_new_inventory_observer();
02204
02205 LLUUID agent_id;
02206 msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
02207 if(agent_id != gAgent.getID())
02208 {
02209 llwarns << "Got a inventory update for the wrong agent: " << agent_id
02210 << llendl;
02211 return false;
02212 }
02213 item_array_t items;
02214 update_map_t update;
02215 S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
02216 bool all_one_folder = true;
02217 LLUUID folder_id;
02218
02219 for(S32 i = 0; i < count; ++i)
02220 {
02221 LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
02222 titem->unpackMessage(msg, _PREHASH_InventoryData, i);
02223 lldebugs << "LLInventoryModel::messageUpdateCore() item id:"
02224 << titem->getUUID() << llendl;
02225 items.push_back(titem);
02226
02227 LLViewerInventoryItem* itemp = gInventory.getItem(titem->getUUID());
02228 if(itemp)
02229 {
02230 if(titem->getParentUUID() == itemp->getParentUUID())
02231 {
02232 update[titem->getParentUUID()];
02233 }
02234 else
02235 {
02236 ++update[titem->getParentUUID()];
02237 --update[itemp->getParentUUID()];
02238 }
02239 }
02240 else
02241 {
02242 ++update[titem->getParentUUID()];
02243 }
02244 if (folder_id.isNull())
02245 {
02246 folder_id = titem->getParentUUID();
02247 }
02248 else
02249 {
02250 all_one_folder = false;
02251 }
02252 }
02253 if(account)
02254 {
02255 gInventory.accountForUpdate(update);
02256 }
02257
02258 U32 changes = 0x0;
02259
02260 for (item_array_t::iterator it = items.begin(); it != items.end(); ++it)
02261 {
02262 changes |= gInventory.updateItem(*it);
02263 }
02264 gInventory.notifyObservers();
02265 gViewerWindow->getWindow()->decBusyCount();
02266
02267 return true;
02268 }
02269
02270
02271 void LLInventoryModel::processRemoveInventoryItem(LLMessageSystem* msg, void**)
02272 {
02273 lldebugs << "LLInventoryModel::processRemoveInventoryItem()" << llendl;
02274 LLUUID agent_id, item_id;
02275 msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
02276 if(agent_id != gAgent.getID())
02277 {
02278 llwarns << "Got a RemoveInventoryItem for the wrong agent."
02279 << llendl;
02280 return;
02281 }
02282 S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
02283 std::vector<LLUUID> item_ids;
02284 update_map_t update;
02285 for(S32 i = 0; i < count; ++i)
02286 {
02287 msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_ItemID, item_id, i);
02288 LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
02289 if(itemp)
02290 {
02291
02292
02293
02294 --update[itemp->getParentUUID()];
02295 item_ids.push_back(item_id);
02296 }
02297 }
02298 gInventory.accountForUpdate(update);
02299 for(std::vector<LLUUID>::iterator it = item_ids.begin(); it != item_ids.end(); ++it)
02300 {
02301 gInventory.deleteObject(*it);
02302 }
02303 gInventory.notifyObservers();
02304 }
02305
02306
02307 void LLInventoryModel::processUpdateInventoryFolder(LLMessageSystem* msg,
02308 void**)
02309 {
02310 lldebugs << "LLInventoryModel::processUpdateInventoryFolder()" << llendl;
02311 LLUUID agent_id, folder_id, parent_id;
02312
02313 msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_AgentID, agent_id);
02314 if(agent_id != gAgent.getID())
02315 {
02316 llwarns << "Got an UpdateInventoryFolder for the wrong agent."
02317 << llendl;
02318 return;
02319 }
02320 LLPointer<LLViewerInventoryCategory> lastfolder;
02321 cat_array_t folders;
02322 update_map_t update;
02323 S32 count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
02324 for(S32 i = 0; i < count; ++i)
02325 {
02326 LLPointer<LLViewerInventoryCategory> tfolder = new LLViewerInventoryCategory(gAgent.getID());
02327 lastfolder = tfolder;
02328 tfolder->unpackMessage(msg, _PREHASH_FolderData, i);
02329
02330 tfolder->setPreferredType(LLAssetType::AT_NONE);
02331 folders.push_back(tfolder);
02332
02333 LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID());
02334 if(folderp)
02335 {
02336 if(tfolder->getParentUUID() == folderp->getParentUUID())
02337 {
02338 update[tfolder->getParentUUID()];
02339 }
02340 else
02341 {
02342 ++update[tfolder->getParentUUID()];
02343 --update[folderp->getParentUUID()];
02344 }
02345 }
02346 else
02347 {
02348 ++update[tfolder->getParentUUID()];
02349 }
02350 }
02351 gInventory.accountForUpdate(update);
02352 for (cat_array_t::iterator it = folders.begin(); it != folders.end(); ++it)
02353 {
02354 gInventory.updateCategory(*it);
02355 }
02356 gInventory.notifyObservers();
02357
02358
02359 LLInventoryView* view = LLInventoryView::getActiveInventory();
02360 if(view)
02361 {
02362 view->getPanel()->setSelection(lastfolder->getUUID(), TAKE_FOCUS_NO);
02363 }
02364 }
02365
02366
02367 void LLInventoryModel::processRemoveInventoryFolder(LLMessageSystem* msg,
02368 void**)
02369 {
02370 lldebugs << "LLInventoryModel::processRemoveInventoryFolder()" << llendl;
02371 LLUUID agent_id, folder_id;
02372 msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_AgentID, agent_id);
02373 if(agent_id != gAgent.getID())
02374 {
02375 llwarns << "Got a RemoveInventoryFolder for the wrong agent."
02376 << llendl;
02377 return;
02378 }
02379 std::vector<LLUUID> folder_ids;
02380 update_map_t update;
02381 S32 count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
02382 for(S32 i = 0; i < count; ++i)
02383 {
02384 msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, folder_id, i);
02385 LLViewerInventoryCategory* folderp = gInventory.getCategory(folder_id);
02386 if(folderp)
02387 {
02388 --update[folderp->getParentUUID()];
02389 folder_ids.push_back(folder_id);
02390 }
02391 }
02392 gInventory.accountForUpdate(update);
02393 for(std::vector<LLUUID>::iterator it = folder_ids.begin(); it != folder_ids.end(); ++it)
02394 {
02395 gInventory.deleteObject(*it);
02396 }
02397 gInventory.notifyObservers();
02398 }
02399
02400
02401 void LLInventoryModel::processSaveAssetIntoInventory(LLMessageSystem* msg,
02402 void**)
02403 {
02404 LLUUID agent_id;
02405 msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
02406 if(agent_id != gAgent.getID())
02407 {
02408 llwarns << "Got a SaveAssetIntoInventory message for the wrong agent."
02409 << llendl;
02410 return;
02411 }
02412
02413 LLUUID item_id;
02414 msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_ItemID, item_id);
02415
02416
02417
02418
02419 lldebugs << "LLInventoryModel::processSaveAssetIntoInventory itemID="
02420 << item_id << llendl;
02421 LLViewerInventoryItem* item = gInventory.getItem( item_id );
02422 if( item )
02423 {
02424 LLCategoryUpdate up(item->getParentUUID(), 0);
02425 gInventory.accountForUpdate(up);
02426 gInventory.addChangedMask( LLInventoryObserver::INTERNAL, item_id);
02427 gInventory.notifyObservers();
02428 }
02429 else
02430 {
02431 llinfos << "LLInventoryModel::processSaveAssetIntoInventory item"
02432 " not found: " << item_id << llendl;
02433 }
02434 if(gViewerWindow)
02435 {
02436 gViewerWindow->getWindow()->decBusyCount();
02437 }
02438 }
02439
02440 struct InventoryCallbackInfo
02441 {
02442 InventoryCallbackInfo(U32 callback, const LLUUID& inv_id) :
02443 mCallback(callback), mInvID(inv_id) {}
02444 U32 mCallback;
02445 LLUUID mInvID;
02446 };
02447
02448
02449 void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
02450 {
02451 LLUUID agent_id;
02452 msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
02453 if(agent_id != gAgent.getID())
02454 {
02455 llwarns << "Got a BulkUpdateInventory for the wrong agent." << llendl;
02456 return;
02457 }
02458 LLUUID tid;
02459 msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, tid);
02460 llinfos << "Bulk inventory: " << tid << llendl;
02461
02462 update_map_t update;
02463 cat_array_t folders;
02464 S32 count;
02465 S32 i;
02466 count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
02467 for(i = 0; i < count; ++i)
02468 {
02469 LLPointer<LLViewerInventoryCategory> tfolder = new LLViewerInventoryCategory(gAgent.getID());
02470 tfolder->unpackMessage(msg, _PREHASH_FolderData, i);
02471
02472
02473
02474 if(tfolder->getUUID().notNull())
02475 {
02476 folders.push_back(tfolder);
02477 LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID());
02478 if(folderp)
02479 {
02480 if(tfolder->getParentUUID() == folderp->getParentUUID())
02481 {
02482 update[tfolder->getParentUUID()];
02483 }
02484 else
02485 {
02486 ++update[tfolder->getParentUUID()];
02487 --update[folderp->getParentUUID()];
02488 }
02489 }
02490 else
02491 {
02492
02493
02494
02495 folderp = gInventory.getCategory(tfolder->getParentUUID());
02496 if(folderp)
02497 {
02498 ++update[tfolder->getParentUUID()];
02499 }
02500 }
02501 }
02502 }
02503
02504
02505 count = msg->getNumberOfBlocksFast(_PREHASH_ItemData);
02506 std::vector<LLUUID> wearable_ids;
02507 item_array_t items;
02508 std::list<InventoryCallbackInfo> cblist;
02509 for(i = 0; i < count; ++i)
02510 {
02511 LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
02512 titem->unpackMessage(msg, _PREHASH_ItemData, i);
02513
02514
02515 U32 callback_id;
02516 msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id);
02517 if(titem->getUUID().notNull())
02518 {
02519 items.push_back(titem);
02520 cblist.push_back(InventoryCallbackInfo(callback_id, titem->getUUID()));
02521 if (titem->getInventoryType() == LLInventoryType::IT_WEARABLE)
02522 {
02523 wearable_ids.push_back(titem->getUUID());
02524 }
02525
02526 LLViewerInventoryItem* itemp = gInventory.getItem(titem->getUUID());
02527 if(itemp)
02528 {
02529 if(titem->getParentUUID() == itemp->getParentUUID())
02530 {
02531 update[titem->getParentUUID()];
02532 }
02533 else
02534 {
02535 ++update[titem->getParentUUID()];
02536 --update[itemp->getParentUUID()];
02537 }
02538 }
02539 else
02540 {
02541 LLViewerInventoryCategory* folderp = gInventory.getCategory(titem->getParentUUID());
02542 if(folderp)
02543 {
02544 ++update[titem->getParentUUID()];
02545 }
02546 }
02547 }
02548 else
02549 {
02550 cblist.push_back(InventoryCallbackInfo(callback_id, LLUUID::null));
02551 }
02552 }
02553 gInventory.accountForUpdate(update);
02554
02555 for (cat_array_t::iterator cit = folders.begin(); cit != folders.end(); ++cit)
02556 {
02557 gInventory.updateCategory(*cit);
02558 }
02559 for (item_array_t::iterator iit = items.begin(); iit != items.end(); ++iit)
02560 {
02561 gInventory.updateItem(*iit);
02562 }
02563 gInventory.notifyObservers();
02564
02565
02566
02567
02568 if (LLInventoryView::sWearNewClothing)
02569 {
02570 LLInventoryView::sWearNewClothingTransactionID = tid;
02571 LLInventoryView::sWearNewClothing = FALSE;
02572 }
02573
02574 if (tid == LLInventoryView::sWearNewClothingTransactionID)
02575 {
02576 count = wearable_ids.size();
02577 for (i = 0; i < count; ++i)
02578 {
02579 LLViewerInventoryItem* wearable_item;
02580 wearable_item = gInventory.getItem(wearable_ids[i]);
02581 wear_inventory_item_on_avatar(wearable_item);
02582 }
02583 }
02584
02585 std::list<InventoryCallbackInfo>::iterator inv_it;
02586 for (inv_it = cblist.begin(); inv_it != cblist.end(); ++inv_it)
02587 {
02588 InventoryCallbackInfo cbinfo = (*inv_it);
02589 gInventoryCallbacks.fire(cbinfo.mCallback, cbinfo.mInvID);
02590 }
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611 }
02612
02613
02614 void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**)
02615 {
02616 LLUUID agent_id;
02617 msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
02618 if(agent_id != gAgent.getID())
02619 {
02620 llwarns << "Got a UpdateInventoryItem for the wrong agent."
02621 << llendl;
02622 return;
02623 }
02624 LLUUID parent_id;
02625 msg->getUUID("AgentData", "FolderID", parent_id);
02626 LLUUID owner_id;
02627 msg->getUUID("AgentData", "OwnerID", owner_id);
02628 S32 version;
02629 msg->getS32("AgentData", "Version", version);
02630 S32 descendents;
02631 msg->getS32("AgentData", "Descendents", descendents);
02632 S32 i;
02633 S32 count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
02634 LLPointer<LLViewerInventoryCategory> tcategory = new LLViewerInventoryCategory(owner_id);
02635 for(i = 0; i < count; ++i)
02636 {
02637 tcategory->unpackMessage(msg, _PREHASH_FolderData, i);
02638 gInventory.updateCategory(tcategory);
02639 }
02640
02641 count = msg->getNumberOfBlocksFast(_PREHASH_ItemData);
02642 LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
02643 for(i = 0; i < count; ++i)
02644 {
02645 titem->unpackMessage(msg, _PREHASH_ItemData, i);
02646 gInventory.updateItem(titem);
02647 }
02648
02649
02650 LLViewerInventoryCategory* cat = gInventory.getCategory(parent_id);
02651 if(cat)
02652 {
02653 cat->setVersion(version);
02654 cat->setDescendentCount(descendents);
02655 }
02656 gInventory.notifyObservers();
02657 }
02658
02659
02660 void LLInventoryModel::processMoveInventoryItem(LLMessageSystem* msg, void**)
02661 {
02662 lldebugs << "LLInventoryModel::processMoveInventoryItem()" << llendl;
02663 LLUUID agent_id;
02664 msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
02665 if(agent_id != gAgent.getID())
02666 {
02667 llwarns << "Got a MoveInventoryItem message for the wrong agent."
02668 << llendl;
02669 return;
02670 }
02671
02672 LLUUID item_id;
02673 LLUUID folder_id;
02674 char new_name[MAX_STRING];
02675 bool anything_changed = false;
02676 S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
02677 for(S32 i = 0; i < count; ++i)
02678 {
02679 msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_ItemID, item_id, i);
02680 LLViewerInventoryItem* item = gInventory.getItem(item_id);
02681 if(item)
02682 {
02683 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
02684 msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_FolderID, folder_id, i);
02685 msg->getString("InventoryData", "NewName", MAX_STRING, new_name, i);
02686
02687 lldebugs << "moving item " << item_id << " to folder "
02688 << folder_id << llendl;
02689 update_list_t update;
02690 LLCategoryUpdate old_folder(item->getParentUUID(), -1);
02691 update.push_back(old_folder);
02692 LLCategoryUpdate new_folder(folder_id, 1);
02693 update.push_back(new_folder);
02694 gInventory.accountForUpdate(update);
02695
02696 new_item->setParent(folder_id);
02697 if(strlen(new_name) > 0)
02698 {
02699 new_item->rename(new_name);
02700 }
02701 gInventory.updateItem(new_item);
02702 anything_changed = true;
02703 }
02704 else
02705 {
02706 llinfos << "LLInventoryModel::processMoveInventoryItem item not found: " << item_id << llendl;
02707 }
02708 }
02709 if(anything_changed)
02710 {
02711 gInventory.notifyObservers();
02712 }
02713 }
02714
02715
02716 void LLInventoryModel::dumpInventory()
02717 {
02718 llinfos << "\nBegin Inventory Dump\n**********************:" << llendl;
02719 llinfos << "mCategroy[] contains " << mCategoryMap.size() << " items." << llendl;
02720 for(cat_map_t::iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
02721 {
02722 LLViewerInventoryCategory* cat = cit->second;
02723 if(cat)
02724 {
02725 llinfos << " " << cat->getUUID() << " '" << cat->getName() << "' "
02726 << cat->getVersion() << " " << cat->getDescendentCount()
02727 << llendl;
02728 }
02729 else
02730 {
02731 llinfos << " NULL!" << llendl;
02732 }
02733 }
02734 llinfos << "mItemMap[] contains " << mItemMap.size() << " items." << llendl;
02735 for(item_map_t::iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
02736 {
02737 LLViewerInventoryItem* item = iit->second;
02738 if(item)
02739 {
02740 llinfos << " " << item->getUUID() << " "
02741 << item->getName() << llendl;
02742 }
02743 else
02744 {
02745 llinfos << " NULL!" << llendl;
02746 }
02747 }
02748 llinfos << "\n**********************\nEnd Inventory Dump" << llendl;
02749 }
02750
02754
02755 bool LLIsType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
02756 {
02757 if(mType == LLAssetType::AT_CATEGORY)
02758 {
02759 if(cat) return TRUE;
02760 }
02761 if(item)
02762 {
02763 if(item->getType() == mType) return TRUE;
02764 }
02765 return FALSE;
02766 }
02767
02768 bool LLIsNotType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
02769 {
02770 if(mType == LLAssetType::AT_CATEGORY)
02771 {
02772 if(cat) return FALSE;
02773 }
02774 if(item)
02775 {
02776 if(item->getType() == mType) return FALSE;
02777 else return TRUE;
02778 }
02779 return TRUE;
02780 }
02781
02782 bool LLIsTypeWithPermissions::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
02783 {
02784 if(mType == LLAssetType::AT_CATEGORY)
02785 {
02786 if(cat)
02787 {
02788 return TRUE;
02789 }
02790 }
02791 if(item)
02792 {
02793 if(item->getType() == mType)
02794 {
02795 LLPermissions perm = item->getPermissions();
02796 if ((perm.getMaskBase() & mPerm) == mPerm)
02797 {
02798 return TRUE;
02799 }
02800 }
02801 }
02802 return FALSE;
02803 }
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832
02833
02834 bool LLBuddyCollector::operator()(LLInventoryCategory* cat,
02835 LLInventoryItem* item)
02836 {
02837 if(item)
02838 {
02839 if((LLAssetType::AT_CALLINGCARD == item->getType())
02840 && (!item->getCreatorUUID().isNull())
02841 && (item->getCreatorUUID() != gAgent.getID()))
02842 {
02843 return true;
02844 }
02845 }
02846 return false;
02847 }
02848
02849
02850 bool LLUniqueBuddyCollector::operator()(LLInventoryCategory* cat,
02851 LLInventoryItem* item)
02852 {
02853 if(item)
02854 {
02855 if((LLAssetType::AT_CALLINGCARD == item->getType())
02856 && (item->getCreatorUUID().notNull())
02857 && (item->getCreatorUUID() != gAgent.getID()))
02858 {
02859 mSeen.insert(item->getCreatorUUID());
02860 return true;
02861 }
02862 }
02863 return false;
02864 }
02865
02866
02867 bool LLParticularBuddyCollector::operator()(LLInventoryCategory* cat,
02868 LLInventoryItem* item)
02869 {
02870 if(item)
02871 {
02872 if((LLAssetType::AT_CALLINGCARD == item->getType())
02873 && (item->getCreatorUUID() == mBuddyID))
02874 {
02875 return TRUE;
02876 }
02877 }
02878 return FALSE;
02879 }
02880
02881
02882 bool LLNameCategoryCollector::operator()(
02883 LLInventoryCategory* cat, LLInventoryItem* item)
02884 {
02885 if(cat)
02886 {
02887 if (!LLString::compareInsensitive(mName.c_str(), cat->getName().c_str()))
02888 {
02889 return true;
02890 }
02891 }
02892 return false;
02893 }
02894
02895
02896
02900
02901 void LLInventoryCompletionObserver::changed(U32 mask)
02902 {
02903
02904
02905 if(!mIncomplete.empty())
02906 {
02907 for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); )
02908 {
02909 LLViewerInventoryItem* item = gInventory.getItem(*it);
02910 if(!item)
02911 {
02912 it = mIncomplete.erase(it);
02913 continue;
02914 }
02915 if(item->isComplete())
02916 {
02917 mComplete.push_back(*it);
02918 it = mIncomplete.erase(it);
02919 continue;
02920 }
02921 ++it;
02922 }
02923 if(mIncomplete.empty())
02924 {
02925 done();
02926 }
02927 }
02928 }
02929
02930 void LLInventoryCompletionObserver::watchItem(const LLUUID& id)
02931 {
02932 if(id.notNull())
02933 {
02934 mIncomplete.push_back(id);
02935 }
02936 }
02937
02938
02939 void LLInventoryFetchObserver::changed(U32 mask)
02940 {
02941
02942
02943 if(!mIncomplete.empty())
02944 {
02945 for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); )
02946 {
02947 LLViewerInventoryItem* item = gInventory.getItem(*it);
02948 if(!item)
02949 {
02950
02951
02952
02953 it = mIncomplete.erase(it);
02954 continue;
02955 }
02956 if(item->isComplete())
02957 {
02958 mComplete.push_back(*it);
02959 it = mIncomplete.erase(it);
02960 continue;
02961 }
02962 ++it;
02963 }
02964 if(mIncomplete.empty())
02965 {
02966 done();
02967 }
02968 }
02969
02970
02971 }
02972
02973 bool LLInventoryFetchObserver::isEverythingComplete() const
02974 {
02975 return mIncomplete.empty();
02976 }
02977
02978 void LLInventoryFetchObserver::fetchItems(
02979 const LLInventoryFetchObserver::item_ref_t& ids)
02980 {
02981 LLMessageSystem* msg = gMessageSystem;
02982 BOOL start_new_message = TRUE;
02983 LLUUID owner_id;
02984 for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it)
02985 {
02986 LLViewerInventoryItem* item = gInventory.getItem(*it);
02987 if(item)
02988 {
02989 if(item->isComplete())
02990 {
02991
02992 mComplete.push_back(*it);
02993 continue;
02994 }
02995 else
02996 {
02997 owner_id = item->getPermissions().getOwner();
02998 }
02999 }
03000 else
03001 {
03002
03003 owner_id = gAgent.getID();
03004 }
03005
03006
03007
03008 mIncomplete.push_back(*it);
03009 if(start_new_message)
03010 {
03011 start_new_message = FALSE;
03012 msg->newMessageFast(_PREHASH_FetchInventory);
03013 msg->nextBlockFast(_PREHASH_AgentData);
03014 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
03015 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03016 }
03017 msg->nextBlockFast(_PREHASH_InventoryData);
03018 msg->addUUIDFast(_PREHASH_OwnerID, owner_id);
03019 msg->addUUIDFast(_PREHASH_ItemID, (*it));
03020 if(msg->isSendFull(NULL))
03021 {
03022 start_new_message = TRUE;
03023 gAgent.sendReliableMessage();
03024 }
03025 }
03026 if(!start_new_message)
03027 {
03028 gAgent.sendReliableMessage();
03029 }
03030 }
03031
03032
03033 void LLInventoryFetchDescendentsObserver::changed(U32 mask)
03034 {
03035 for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();)
03036 {
03037 LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
03038 if(!cat)
03039 {
03040 it = mIncompleteFolders.erase(it);
03041 continue;
03042 }
03043 if(isComplete(cat))
03044 {
03045 mCompleteFolders.push_back(*it);
03046 it = mIncompleteFolders.erase(it);
03047 continue;
03048 }
03049 ++it;
03050 }
03051 if(mIncompleteFolders.empty())
03052 {
03053 done();
03054 }
03055 }
03056
03057 void LLInventoryFetchDescendentsObserver::fetchDescendents(
03058 const folder_ref_t& ids)
03059 {
03060 for(folder_ref_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
03061 {
03062 LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
03063 if(!cat) continue;
03064 if(!isComplete(cat))
03065 {
03066 cat->fetchDescendents();
03067 mIncompleteFolders.push_back(*it);
03068 }
03069 else
03070 {
03071 mCompleteFolders.push_back(*it);
03072 }
03073 }
03074 }
03075
03076 bool LLInventoryFetchDescendentsObserver::isEverythingComplete() const
03077 {
03078 return mIncompleteFolders.empty();
03079 }
03080
03081 bool LLInventoryFetchDescendentsObserver::isComplete(LLViewerInventoryCategory* cat)
03082 {
03083 S32 version = cat->getVersion();
03084 S32 descendents = cat->getDescendentCount();
03085 if((LLViewerInventoryCategory::VERSION_UNKNOWN == version)
03086 || (LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN == descendents))
03087 {
03088 return false;
03089 }
03090
03091
03092 LLInventoryModel::cat_array_t* cats;
03093 LLInventoryModel::item_array_t* items;
03094 gInventory.getDirectDescendentsOf(cat->getUUID(), cats, items);
03095 if(!cats || !items)
03096 {
03097
03098
03099
03100 return true;
03101 }
03102 S32 known = cats->count() + items->count();
03103 if(descendents == known)
03104 {
03105
03106 return true;
03107 }
03108 return false;
03109 }
03110
03111 void LLInventoryFetchComboObserver::changed(U32 mask)
03112 {
03113 if(!mIncompleteItems.empty())
03114 {
03115 for(item_ref_t::iterator it = mIncompleteItems.begin(); it < mIncompleteItems.end(); )
03116 {
03117 LLViewerInventoryItem* item = gInventory.getItem(*it);
03118 if(!item)
03119 {
03120 it = mIncompleteItems.erase(it);
03121 continue;
03122 }
03123 if(item->isComplete())
03124 {
03125 mCompleteItems.push_back(*it);
03126 it = mIncompleteItems.erase(it);
03127 continue;
03128 }
03129 ++it;
03130 }
03131 }
03132 if(!mIncompleteFolders.empty())
03133 {
03134 for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();)
03135 {
03136 LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
03137 if(!cat)
03138 {
03139 it = mIncompleteFolders.erase(it);
03140 continue;
03141 }
03142 if(gInventory.isCategoryComplete(*it))
03143 {
03144 mCompleteFolders.push_back(*it);
03145 it = mIncompleteFolders.erase(it);
03146 continue;
03147 }
03148 ++it;
03149 }
03150 }
03151 if(!mDone && mIncompleteItems.empty() && mIncompleteFolders.empty())
03152 {
03153 mDone = true;
03154 done();
03155 }
03156 }
03157
03158 void LLInventoryFetchComboObserver::fetch(
03159 const folder_ref_t& folder_ids,
03160 const item_ref_t& item_ids)
03161 {
03162 lldebugs << "LLInventoryFetchComboObserver::fetch()" << llendl;
03163 for(folder_ref_t::const_iterator fit = folder_ids.begin(); fit != folder_ids.end(); ++fit)
03164 {
03165 LLViewerInventoryCategory* cat = gInventory.getCategory(*fit);
03166 if(!cat) continue;
03167 if(!gInventory.isCategoryComplete(*fit))
03168 {
03169 cat->fetchDescendents();
03170 lldebugs << "fetching folder " << *fit <<llendl;
03171 mIncompleteFolders.push_back(*fit);
03172 }
03173 else
03174 {
03175 mCompleteFolders.push_back(*fit);
03176 lldebugs << "completing folder " << *fit <<llendl;
03177 }
03178 }
03179
03180
03181
03182
03183
03184 LLUUID owner_id;
03185 LLMessageSystem* msg = gMessageSystem;
03186 bool start_new_message = true;
03187 for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit)
03188 {
03189 LLViewerInventoryItem* item = gInventory.getItem(*iit);
03190 if(!item)
03191 {
03192 lldebugs << "uanble to find item " << *iit << llendl;
03193 continue;
03194 }
03195 if(item->isComplete())
03196 {
03197
03198 mCompleteItems.push_back(*iit);
03199 lldebugs << "completing item " << *iit << llendl;
03200 continue;
03201 }
03202 else
03203 {
03204 mIncompleteItems.push_back(*iit);
03205 owner_id = item->getPermissions().getOwner();
03206 }
03207 if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end())
03208 {
03209 lldebugs << "fetching item " << *iit << llendl;
03210 if(start_new_message)
03211 {
03212 start_new_message = false;
03213 msg->newMessageFast(_PREHASH_FetchInventory);
03214 msg->nextBlockFast(_PREHASH_AgentData);
03215 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
03216 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03217 }
03218 msg->nextBlockFast(_PREHASH_InventoryData);
03219 msg->addUUIDFast(_PREHASH_OwnerID, owner_id);
03220 msg->addUUIDFast(_PREHASH_ItemID, (*iit));
03221 if(msg->isSendFullFast(_PREHASH_InventoryData))
03222 {
03223 start_new_message = true;
03224 gAgent.sendReliableMessage();
03225 }
03226 }
03227 else
03228 {
03229 lldebugs << "not worrying about " << *iit << llendl;
03230 }
03231 }
03232 if(!start_new_message)
03233 {
03234 gAgent.sendReliableMessage();
03235 }
03236 }
03237
03238 void LLInventoryExistenceObserver::watchItem(const LLUUID& id)
03239 {
03240 if(id.notNull())
03241 {
03242 mMIA.push_back(id);
03243 }
03244 }
03245
03246 void LLInventoryExistenceObserver::changed(U32 mask)
03247 {
03248
03249
03250 if(!mMIA.empty())
03251 {
03252 for(item_ref_t::iterator it = mMIA.begin(); it < mMIA.end(); )
03253 {
03254 LLViewerInventoryItem* item = gInventory.getItem(*it);
03255 if(!item)
03256 {
03257 ++it;
03258 continue;
03259 }
03260 mExist.push_back(*it);
03261 it = mMIA.erase(it);
03262 }
03263 if(mMIA.empty())
03264 {
03265 done();
03266 }
03267 }
03268 }
03269
03270 void LLInventoryAddedObserver::changed(U32 mask)
03271 {
03272 if(!(mask & LLInventoryObserver::ADD))
03273 {
03274 return;
03275 }
03276
03277
03278
03279
03280 LLMessageSystem* msg = gMessageSystem;
03281 const char* msg_name = msg->getMessageName();
03282 if (!msg_name) return;
03283
03284
03285 if ( strcmp(msg_name, "UpdateCreateInventoryItem") )
03286 {
03287 return;
03288 }
03289
03290 LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
03291 S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
03292 for(S32 i = 0; i < num_blocks; ++i)
03293 {
03294 titem->unpackMessage(msg, _PREHASH_InventoryData, i);
03295 if (!(titem->getUUID().isNull()))
03296 {
03297
03298 mAdded.push_back(titem->getUUID());
03299 }
03300 }
03301 if (!mAdded.empty())
03302 {
03303 done();
03304 }
03305 }
03306
03307 LLInventoryTransactionObserver::LLInventoryTransactionObserver(
03308 const LLTransactionID& transaction_id) :
03309 mTransactionID(transaction_id)
03310 {
03311 }
03312
03313 void LLInventoryTransactionObserver::changed(U32 mask)
03314 {
03315 if(mask & LLInventoryObserver::ADD)
03316 {
03317
03318 LLMessageSystem* msg = gMessageSystem;
03319 if(msg->getMessageName()
03320 && (0 == strcmp(msg->getMessageName(), "BulkUpdateInventory")))
03321 {
03322
03323
03324 LLUUID id;
03325 msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, id);
03326 if(id == mTransactionID)
03327 {
03328
03329 folder_ref_t folders;
03330 item_ref_t items;
03331 S32 count;
03332 count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
03333 S32 i;
03334 for(i = 0; i < count; ++i)
03335 {
03336 msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, id, i);
03337 if(id.notNull())
03338 {
03339 folders.push_back(id);
03340 }
03341 }
03342 count = msg->getNumberOfBlocksFast(_PREHASH_ItemData);
03343 for(i = 0; i < count; ++i)
03344 {
03345 msg->getUUIDFast(_PREHASH_ItemData, _PREHASH_ItemID, id, i);
03346 if(id.notNull())
03347 {
03348 items.push_back(id);
03349 }
03350 }
03351
03352
03353 done(folders, items);
03354 }
03355 }
03356 }
03357 }
03358
03359
03363 bool LLAssetIDMatches ::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
03364 {
03365 return (item && item->getAssetUUID() == mAssetID);
03366 }
03367
03368
03372
03373
03374
03375
03376
03377
03378
03379
03380
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413