diff options
Diffstat (limited to 'indra/newview/llinventorymodel.cpp')
-rw-r--r-- | indra/newview/llinventorymodel.cpp | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index ef18386e57..bdf1ebddac 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -142,6 +142,105 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item) return rv; } +/* +This namespace contains a functionality to remove LM prefixes were used to store sort order of +Favorite Landmarks in landmarks' names. +Once being in Favorites folder LM inventory Item has such prefix. +Due to another solution is implemented in EXT-3985 these prefixes should be removed. + +*NOTE: It will be unnecessary after the first successful session in viewer 2.0. +Can be removed before public release. + +Implementation details: +At the first run with this patch it patches all cached landmarks: removes LM sort prefixes and +updates them on the viewer and server sides. +Also it calls fetching agent's inventory to process not yet loaded landmarks too. +If fetching is successfully done it will store special per-agent empty file-marker +in the user temporary folder (where cached inventory is loaded) while caching agent's inventory. +After that in will not affect the viewer until cached marker is removed. +*/ +namespace LMSortPrefix +{ + bool cleanup_done = false; + const std::string getMarkerPath() + { + std::string path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, gAgentID.asString())); + std::string marker_filename = llformat("%s-lm_prefix_marker", path.c_str()); + + return marker_filename; + } + bool wasClean() + { + static bool was_clean = false; + static bool already_init = false; + if (already_init) return was_clean; + + already_init = true; + std::string path_to_marker = getMarkerPath(); + was_clean = LLFile::isfile(path_to_marker); + + return was_clean; + } + + void setLandmarksWereCleaned() + { + if (cleanup_done) + { + std::string path_to_marker = getMarkerPath(); + LLFILE* file = LLFile::fopen(path_to_marker, "w"); + if(!file) + { + llwarns << "unable to save marker that LM prefixes were removed: " << path_to_marker << llendl; + return; + } + + fclose(file); + } + } + + void removePrefix(LLPointer<LLViewerInventoryItem> inv_item) + { + if (wasClean()) + { + LL_INFOS_ONCE("") << "Inventory was cleaned for this avatar. Patch can be removed." << LL_ENDL; + return; + } + + if (LLInventoryType::IT_LANDMARK != inv_item->getInventoryType()) return; + + std::string old_name = inv_item->getName(); + + S32 sort_field = -1; + std::string display_name; + BOOL exists = LLViewerInventoryItem::extractSortFieldAndDisplayName(old_name, &sort_field, &display_name); + if (exists && sort_field != -1) + { + llinfos << "Removing Landmark sort field and separator for: " << old_name << " | " << inv_item->getUUID() << llendl; + LLUUID parent_uuid = inv_item->getParentUUID(); + if (gInventory.getCategory(parent_uuid)) + { + llinfos << "parent folder is: " << gInventory.getCategory(parent_uuid)->getName() << llendl; + } + + + // mark item completed to avoid error while copying and updating server + inv_item->setComplete(TRUE); + LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item.get()); + new_item->rename(display_name); + gInventory.updateItem(new_item); + new_item->updateServer(FALSE); + + gInventory.notifyObservers(); + } + } + + void completeCleanup() + { + // background fetch is completed. can save marker + cleanup_done = true; + } +} + ///---------------------------------------------------------------------------- /// Class LLInventoryModel ///---------------------------------------------------------------------------- @@ -755,6 +854,10 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item) gCacheName->get(id, FALSE, boost::bind(&LLViewerInventoryItem::onCallingCardNameLookup, new_item.get(), _1, _2, _3)); } } + else if (new_item->getType() == LLAssetType::AT_GESTURE) + { + mask |= LLInventoryObserver::GESTURE; + } addChangedMask(mask, new_item->getUUID()); return mask; } @@ -1732,6 +1835,8 @@ void LLInventoryModel::stopBackgroundFetch() gIdleCallbacks.deleteFunction(&LLInventoryModel::backgroundFetch, NULL); sBulkFetchCount=0; sMinTimeBetweenFetches=0.0f; + + LMSortPrefix::completeCleanup(); } } @@ -1878,6 +1983,13 @@ void LLInventoryModel::cache( const LLUUID& parent_folder_id, const LLUUID& agent_id) { + if (getRootFolderID() == parent_folder_id) + { + // *TODO: mantipov: can be removed before public release, EXT-3985 + //save marker to avoid fetching inventory on future sessions + LMSortPrefix::setLandmarksWereCleaned(); + } + lldebugs << "Caching " << parent_folder_id << " for " << agent_id << llendl; LLViewerInventoryCategory* root_cat = getCategory(parent_folder_id); @@ -2688,6 +2800,28 @@ void LLInventoryModel::buildParentChildMap() // The inv tree is built. mIsAgentInvUsable = true; + {// *TODO: mantipov: can be removed before public release, EXT-3985 + /* + *HACK: mantipov: to cleanup landmarks were marked with sort index prefix in name. + Is necessary to be called once per account after EXT-3985 is implemented. + So, let fetch agent's inventory, processing will be done in processInventoryDescendents() + Should be removed before public release. + */ + if (!LMSortPrefix::wasClean()) + { + cat_array_t cats; + item_array_t items; + collectDescendents(agent_inv_root_id, cats, items, INCLUDE_TRASH); + + for (item_array_t::const_iterator it= items.begin(); it != items.end(); ++it) + { + LMSortPrefix::removePrefix(*it); + } + + gInventory.startBackgroundFetch(agent_inv_root_id); + } + } + llinfos << "Inventory initialized, notifying observers" << llendl; addChangedMask(LLInventoryObserver::ALL, LLUUID::null); notifyObservers(); @@ -3453,6 +3587,10 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**) continue; } gInventory.updateItem(titem); + + {// *TODO: mantipov: can be removed before public release, EXT-3985 + LMSortPrefix::removePrefix(titem); + } } // set version and descendentcount according to message. @@ -3648,6 +3786,9 @@ void LLInventoryModel::updateItemsOrder(LLInventoryModel::item_array_t& items, c LLViewerInventoryItem* src_item = *it_src; items.erase(it_src); + + // target iterator can not be valid because the container was changed, so update it. + it_dest = find_item_iter_by_uuid(items, dest_item_id); items.insert(it_dest, src_item); } @@ -3673,6 +3814,44 @@ void LLInventoryModel::saveItemsOrder(const LLInventoryModel::item_array_t& item notifyObservers(); } +// See also LLInventorySort where landmarks in the Favorites folder are sorted. +class LLViewerInventoryItemSort +{ +public: + bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) + { + return a->getSortField() < b->getSortField(); + } +}; + +/** + * Sorts passed items by LLViewerInventoryItem sort field. + * + * @param[in, out] items - array of items, not sorted. + */ +static void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items) +{ + static LLViewerInventoryItemSort sort_functor; + std::sort(items.begin(), items.end(), sort_functor); +} + +void LLInventoryModel::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLIsType is_type(LLAssetType::AT_LANDMARK); + LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + + // ensure items are sorted properly before changing order. EXT-3498 + rearrange_item_order_by_sort_field(items); + + // update order + updateItemsOrder(items, source_item_id, target_item_id); + + saveItemsOrder(items); +} + //---------------------------------------------------------------------------- // *NOTE: DEBUG functionality |