diff options
Diffstat (limited to 'indra/newview/llviewerinventory.cpp')
-rw-r--r-- | indra/newview/llviewerinventory.cpp | 580 |
1 files changed, 427 insertions, 153 deletions
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 57a4117d5d..b42d25c1d8 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -33,21 +33,28 @@ #include "llviewerprecompiledheaders.h" #include "llviewerinventory.h" +#include "llnotificationsutil.h" +#include "llsdserialize.h" #include "message.h" #include "indra_constants.h" #include "llagent.h" -#include "llfoldertype.h" +#include "llagentcamera.h" +#include "llviewerfoldertype.h" +#include "llfolderview.h" #include "llviewercontrol.h" #include "llconsole.h" +#include "llinventoryfunctions.h" #include "llinventorymodel.h" -#include "llnotify.h" -#include "llimview.h" +#include "llinventorymodelbackgroundfetch.h" #include "llgesturemgr.h" +#include "llsidetray.h" #include "llinventorybridge.h" +#include "llinventorypanel.h" #include "llfloaterinventory.h" +#include "llviewerassettype.h" #include "llviewerregion.h" #include "llviewerobjectlist.h" #include "llpreviewgesture.h" @@ -55,11 +62,60 @@ #include "lltrans.h" #include "llappearancemgr.h" #include "llfloatercustomize.h" +#include "llcommandhandler.h" +#include "llviewermessage.h" ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- +class LLInventoryHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& params, const LLSD& query_map, + LLMediaCtrl* web) + { + if (params.size() < 1) + { + return false; + } + + // support secondlife:///app/inventory/show + if (params[0].asString() == "show") + { + LLSideTray::getInstance()->showPanel("sidepanel_inventory", LLSD()); + return true; + } + + // otherwise, we need a UUID and a verb... + if (params.size() < 2) + { + return false; + } + LLUUID inventory_id; + if (!inventory_id.set(params[0], FALSE)) + { + return false; + } + + const std::string verb = params[1].asString(); + if (verb == "select") + { + uuid_vec_t items_to_open; + items_to_open.push_back(inventory_id); + //inventory_handler is just a stub, because we don't know from who this offer + open_inventory_offer(items_to_open, "inventory_handler"); + return true; + } + + return false; + } +}; +LLInventoryHandler gInventoryHandler; + ///---------------------------------------------------------------------------- /// Class LLViewerInventoryItem ///---------------------------------------------------------------------------- @@ -359,7 +415,7 @@ void LLViewerInventoryItem::updateParentOnServer(BOOL restamp) const LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& uuid, const LLUUID& parent_uuid, - LLAssetType::EType pref, + LLFolderType::EType pref, const std::string& name, const LLUUID& owner_id) : LLInventoryCategory(uuid, parent_uuid, pref, name), @@ -416,9 +472,9 @@ void LLViewerInventoryCategory::updateServer(BOOL is_new) const { // communicate that change with the server. - if (LLAssetType::lookupIsProtectedCategoryType(mPreferredType)) + if (LLFolderType::lookupIsProtectedType(mPreferredType)) { - LLNotifications::instance().add("CannotModifyProtectedCategories"); + LLNotificationsUtil::add("CannotModifyProtectedCategories"); return; } @@ -440,9 +496,9 @@ void LLViewerInventoryCategory::removeFromServer( void ) llinfos << "Removing inventory category " << mUUID << " from server." << llendl; // communicate that change with the server. - if(LLAssetType::lookupIsProtectedCategoryType(mPreferredType)) + if(LLFolderType::lookupIsProtectedType(mPreferredType)) { - LLNotifications::instance().add("CannotRemoveProtectedCategories"); + LLNotificationsUtil::add("CannotRemoveProtectedCategories"); return; } @@ -473,13 +529,18 @@ bool LLViewerInventoryCategory::fetchDescendents() // 2 = folders by date // Need to mask off anything but the first bit. // This comes from LLInventoryFilter from llfolderview.h - U32 sort_order = gSavedSettings.getU32("InventorySortOrder") & 0x1; + U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER) & 0x1; + + // *NOTE: For bug EXT-2879, originally commented out + // gAgent.getRegion()->getCapability in order to use the old + // message-based system. This has been uncommented now that + // AIS folks are aware of the issue and have a fix in process. + // see ticket for details. std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents"); - if (!url.empty()) //Capability found. Build up LLSD and use it. { - LLInventoryModel::startBackgroundFetch(mUUID); + LLInventoryModelBackgroundFetch::instance().start(mUUID); } else { //Deprecated, but if we don't have a capability, use the old system. @@ -543,7 +604,7 @@ bool LLViewerInventoryCategory::importFileLocal(LLFILE* fp) } else if(0 == strcmp("pref_type", keyword)) { - mPreferredType = LLAssetType::lookup(valuestr); + mPreferredType = LLFolderType::lookup(valuestr); } else if(0 == strcmp("name", keyword)) { @@ -581,7 +642,7 @@ bool LLViewerInventoryCategory::exportFileLocal(LLFILE* fp) const mParentUUID.toString(uuid_str); fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str()); fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); - fprintf(fp, "\t\tpref_type\t%s\n", LLAssetType::lookup(mPreferredType)); + fprintf(fp, "\t\tpref_type\t%s\n", LLFolderType::lookup(mPreferredType).c_str()); fprintf(fp, "\t\tname\t%s|\n", mName.c_str()); mOwnerID.toString(uuid_str); fprintf(fp, "\t\towner_id\t%s\n", uuid_str.c_str()); @@ -592,8 +653,10 @@ bool LLViewerInventoryCategory::exportFileLocal(LLFILE* fp) const void LLViewerInventoryCategory::determineFolderType() { - LLAssetType::EType original_type = getPreferredType(); - if (LLAssetType::lookupIsProtectedCategoryType(original_type)) + /* Do NOT uncomment this code. This is for future 2.1 support of ensembles. + llassert(FALSE); + LLFolderType::EType original_type = getPreferredType(); + if (LLFolderType::lookupIsProtectedType(original_type)) return; U64 folder_valid = 0; @@ -616,28 +679,30 @@ void LLViewerInventoryCategory::determineFolderType() { const EWearableType wearable_type = item->getWearableType(); const std::string& wearable_name = LLWearableDictionary::getTypeName(wearable_type); - U64 valid_folder_types = LLFolderType::lookupValidFolderTypes(wearable_name); + U64 valid_folder_types = LLViewerFolderType::lookupValidFolderTypes(wearable_name); folder_valid |= valid_folder_types; folder_invalid |= ~valid_folder_types; } } - for (U8 i = LLAssetType::AT_FOLDER_ENSEMBLE_START; i <= LLAssetType::AT_FOLDER_ENSEMBLE_END; i++) + for (U8 i = LLFolderType::FT_ENSEMBLE_START; i <= LLFolderType::FT_ENSEMBLE_END; i++) { if ((folder_valid & (1LL << i)) && !(folder_invalid & (1LL << i))) { - changeType((LLAssetType::EType)i); + changeType((LLFolderType::EType)i); return; } } } - if (LLAssetType::lookupIsEnsembleCategoryType(original_type)) + if (LLFolderType::lookupIsEnsembleType(original_type)) { - changeType(LLAssetType::AT_NONE); + changeType(LLFolderType::FT_NONE); } + llassert(FALSE); + */ } -void LLViewerInventoryCategory::changeType(LLAssetType::EType new_folder_type) +void LLViewerInventoryCategory::changeType(LLFolderType::EType new_folder_type) { const LLUUID &folder_id = getUUID(); const LLUUID &parent_id = getParentUUID(); @@ -728,8 +793,8 @@ void WearOnAvatarCallback::fire(const LLUUID& inv_item) void ModifiedCOFCallback::fire(const LLUUID& inv_item) { - LLAppearanceManager::instance().updateAppearanceFromCOF(); - if( CAMERA_MODE_CUSTOMIZE_AVATAR == gAgent.getCameraMode() ) + LLAppearanceMgr::instance().updateAppearanceFromCOF(); + if( CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode() ) { // If we're in appearance editing mode, the current tab may need to be refreshed if (gFloaterCustomize) @@ -764,7 +829,7 @@ void ActivateGestureCallback::fire(const LLUUID& inv_item) if (inv_item.isNull()) return; - LLGestureManager::instance().activateGesture(inv_item); + LLGestureMgr::instance().activateGesture(inv_item); } void CreateGestureCallback::fire(const LLUUID& inv_item) @@ -772,7 +837,7 @@ void CreateGestureCallback::fire(const LLUUID& inv_item) if (inv_item.isNull()) return; - LLGestureManager::instance().activateGesture(inv_item); + LLGestureMgr::instance().activateGesture(inv_item); LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (!item) return; @@ -784,6 +849,13 @@ void CreateGestureCallback::fire(const LLUUID& inv_item) gFloaterView->adjustToFitScreen(preview, FALSE); } +void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id) +{ + if (mTargetLandmarkId.isNull()) return; + + gInventory.rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId); +} + LLInventoryCallbackManager gInventoryCallbacks; void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id, @@ -875,8 +947,20 @@ void link_inventory_item( } LLUUID transaction_id; - std::string desc = "Link"; + std::string desc = "Broken link"; // This should only show if the object can't find its baseobj. LLInventoryType::EType inv_type = LLInventoryType::IT_NONE; + if (dynamic_cast<const LLInventoryCategory *>(baseobj)) + { + inv_type = LLInventoryType::IT_CATEGORY; + } + else + { + const LLViewerInventoryItem *baseitem = dynamic_cast<const LLViewerInventoryItem *>(baseobj); + if (baseitem) + { + inv_type = baseitem->getInventoryType(); + } + } LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_LinkInventoryItem); @@ -948,7 +1032,7 @@ void copy_inventory_from_notecard(const LLUUID& object_id, const LLUUID& notecar body["notecard-id"] = notecard_inv_id; body["object-id"] = object_id; body["item-id"] = src->getUUID(); - body["folder-id"] = gInventory.findCategoryUUIDForType(src->getType()); + body["folder-id"] = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(src->getType())); body["callback-id"] = (LLSD::Integer)callback_id; request["message"] = "CopyInventoryFromNotecard"; @@ -964,7 +1048,7 @@ void create_new_item(const std::string& name, U32 next_owner_perm) { std::string desc; - LLAssetType::generateDescriptionFor(asset_type, desc); + LLViewerAssetType::generateDescriptionFor(asset_type, desc); next_owner_perm = (next_owner_perm) ? next_owner_perm : PERM_MOVE | PERM_TRANSFER; @@ -989,19 +1073,14 @@ const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not) const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not) +// ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements... void menu_create_inventory_item(LLFolderView* folder, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid) { - std::string type = userdata.asString(); + std::string type_name = userdata.asString(); - if (("category" == type) || ("current" == type) || ("outfit" == type) || ("my_otfts" == type) ) + if (("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name)) { - LLAssetType::EType a_type = LLAssetType::AT_NONE; - if ("current" == type) - a_type = LLAssetType::AT_CURRENT_OUTFIT; - if ("outfit" == type) - a_type = LLAssetType::AT_OUTFIT; - if ("my_otfts" == type) - a_type = LLAssetType::AT_MY_OUTFITS; + LLFolderType::EType preferred_type = LLFolderType::lookup(type_name); LLUUID parent_id; if (bridge) @@ -1017,103 +1096,53 @@ void menu_create_inventory_item(LLFolderView* folder, LLFolderBridge *bridge, co parent_id = gInventory.getRootFolderID(); } - LLUUID category = gInventory.createNewCategory(parent_id, a_type, LLStringUtil::null); + LLUUID category = gInventory.createNewCategory(parent_id, preferred_type, LLStringUtil::null); gInventory.notifyObservers(); folder->setSelectionByID(category, TRUE); } - else if ("lsl" == type) + else if ("lsl" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_LSL_TEXT); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_LSL_TEXT); create_new_item(NEW_LSL_NAME, parent_id, LLAssetType::AT_LSL_TEXT, LLInventoryType::IT_LSL, PERM_MOVE | PERM_TRANSFER); } - else if ("notecard" == type) + else if ("notecard" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_NOTECARD); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_NOTECARD); create_new_item(NEW_NOTECARD_NAME, parent_id, LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, PERM_ALL); } - else if ("gesture" == type) + else if ("gesture" == type_name) { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_GESTURE); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE); create_new_item(NEW_GESTURE_NAME, parent_id, LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, PERM_ALL); } - else if ("shirt" == type) - { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); - LLFolderBridge::createWearable(parent_id, WT_SHIRT); - } - else if ("pants" == type) - { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); - LLFolderBridge::createWearable(parent_id, WT_PANTS); - } - else if ("shoes" == type) - { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); - LLFolderBridge::createWearable(parent_id, WT_SHOES); - } - else if ("socks" == type) - { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); - LLFolderBridge::createWearable(parent_id, WT_SOCKS); - } - else if ("jacket" == type) - { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); - LLFolderBridge::createWearable(parent_id, WT_JACKET); - } - else if ("skirt" == type) - { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); - LLFolderBridge::createWearable(parent_id, WT_SKIRT); - } - else if ("gloves" == type) - { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); - LLFolderBridge::createWearable(parent_id, WT_GLOVES); - } - else if ("undershirt" == type) - { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); - LLFolderBridge::createWearable(parent_id, WT_UNDERSHIRT); - } - else if ("underpants" == type) - { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING); - LLFolderBridge::createWearable(parent_id, WT_UNDERPANTS); - } - else if ("shape" == type) - { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART); - LLFolderBridge::createWearable(parent_id, WT_SHAPE); - } - else if ("skin" == type) - { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART); - LLFolderBridge::createWearable(parent_id, WT_SKIN); - } - else if ("hair" == type) - { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART); - LLFolderBridge::createWearable(parent_id, WT_HAIR); - } - else if ("eyes" == type) + else { - LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART); - LLFolderBridge::createWearable(parent_id, WT_EYES); + // Use for all clothing and body parts. Adding new wearable types requires updating LLWearableDictionary. + EWearableType wearable_type = LLWearableDictionary::typeNameToType(type_name); + if (wearable_type >= WT_SHAPE && wearable_type < WT_COUNT) + { + LLAssetType::EType asset_type = LLWearableDictionary::getAssetType(wearable_type); + LLFolderType::EType folder_type = LLFolderType::assetTypeToFolderType(asset_type); + const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(folder_type); + LLFolderBridge::createWearable(parent_id, wearable_type); + } + else + { + llwarns << "Can't create unrecognized type " << type_name << llendl; + } } - folder->setNeedsAutoRename(TRUE); } @@ -1140,90 +1169,243 @@ const LLUUID& LLViewerInventoryItem::getAssetUUID() const return LLInventoryItem::getAssetUUID(); } -const std::string& LLViewerInventoryItem::getName() const +const LLUUID& LLViewerInventoryItem::getProtectedAssetUUID() const { if (const LLViewerInventoryItem *linked_item = getLinkedItem()) { - return linked_item->getName(); + return linked_item->getProtectedAssetUUID(); } - if (const LLViewerInventoryCategory *linked_category = getLinkedCategory()) + + // check for conditions under which we may return a visible UUID to the user + bool item_is_fullperm = getIsFullPerm(); + bool agent_is_godlike = gAgent.isGodlikeWithoutAdminMenuFakery(); + if (item_is_fullperm || agent_is_godlike) { - return linked_category->getName(); + return LLInventoryItem::getAssetUUID(); } - return getDisplayName(); + return LLUUID::null; } -const std::string& LLViewerInventoryItem::getDisplayName() const +const bool LLViewerInventoryItem::getIsFullPerm() const { - std::string result; - BOOL hasSortField = extractSortFieldAndDisplayName(0, &result); + LLPermissions item_permissions = getPermissions(); - return mDisplayName = hasSortField ? result : LLInventoryItem::getName(); + // modify-ok & copy-ok & transfer-ok + return ( item_permissions.allowOperationBy(PERM_MODIFY, + gAgent.getID(), + gAgent.getGroupID()) && + item_permissions.allowOperationBy(PERM_COPY, + gAgent.getID(), + gAgent.getGroupID()) && + item_permissions.allowOperationBy(PERM_TRANSFER, + gAgent.getID(), + gAgent.getGroupID()) ); } -S32 LLViewerInventoryItem::getSortField() const +const std::string& LLViewerInventoryItem::getName() const { - S32 result; - BOOL hasSortField = extractSortFieldAndDisplayName(&result, 0); + if (const LLViewerInventoryItem *linked_item = getLinkedItem()) + { + return linked_item->getName(); + } + if (const LLViewerInventoryCategory *linked_category = getLinkedCategory()) + { + return linked_category->getName(); + } - return hasSortField ? result : -1; + return LLInventoryItem::getName(); } -void LLViewerInventoryItem::setSortField(S32 sortField) -{ - using std::string; +/** + * Class to store sorting order of favorites landmarks in a local file. EXT-3985. + * It replaced previously implemented solution to store sort index in landmark's name as a "<N>@" prefix. + * Data are stored in user home directory. + */ +class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage> + , public LLDestroyClass<LLFavoritesOrderStorage> +{ +public: + /** + * Sets sort index for specified with LLUUID favorite landmark + */ + void setSortIndex(const LLUUID& inv_item_id, S32 sort_index); + + /** + * Gets sort index for specified with LLUUID favorite landmark + */ + S32 getSortIndex(const LLUUID& inv_item_id); + void removeSortIndex(const LLUUID& inv_item_id); + + /** + * Implementation of LLDestroyClass. Calls cleanup() instance method. + * + * It is important this callback is called before gInventory is cleaned. + * For now it is called from LLAppViewer::cleanup() -> LLAppViewer::disconnectViewer(), + * Inventory is cleaned later from LLAppViewer::cleanup() after LLAppViewer::disconnectViewer() is called. + * @see cleanup() + */ + static void destroyClass(); + + const static S32 NO_INDEX; +private: + friend class LLSingleton<LLFavoritesOrderStorage>; + LLFavoritesOrderStorage() : mIsDirty(false) { load(); } + ~LLFavoritesOrderStorage() { save(); } + + /** + * Removes sort indexes for items which are not in Favorites bar for now. + */ + void cleanup(); + + const static std::string SORTING_DATA_FILE_NAME; + + void load(); + void save(); + + typedef std::map<LLUUID, S32> sort_index_map_t; + sort_index_map_t mSortIndexes; + + bool mIsDirty; + + struct IsNotInFavorites + { + IsNotInFavorites(const LLInventoryModel::item_array_t& items) + : mFavoriteItems(items) + { - std::stringstream ss; - ss << sortField; + } - string newSortField = ss.str(); + /** + * Returns true if specified item is not found among inventory items + */ + bool operator()(const sort_index_map_t::value_type& id_index_pair) const + { + LLPointer<LLViewerInventoryItem> item = gInventory.getItem(id_index_pair.first); + if (item.isNull()) return true; - const char separator = getSeparator(); - const string::size_type separatorPos = mName.find(separator, 0); + LLInventoryModel::item_array_t::const_iterator found_it = + std::find(mFavoriteItems.begin(), mFavoriteItems.end(), item); - if (separatorPos < string::npos) - { - // the name of the LLViewerInventoryItem already consists of sort field and display name. - mName = newSortField + separator + mName.substr(separatorPos + 1, string::npos); - } - else + return found_it == mFavoriteItems.end(); + } + private: + LLInventoryModel::item_array_t mFavoriteItems; + }; + +}; + +const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml"; +const S32 LLFavoritesOrderStorage::NO_INDEX = -1; + +void LLFavoritesOrderStorage::setSortIndex(const LLUUID& inv_item_id, S32 sort_index) +{ + mSortIndexes[inv_item_id] = sort_index; + mIsDirty = true; +} + +S32 LLFavoritesOrderStorage::getSortIndex(const LLUUID& inv_item_id) +{ + sort_index_map_t::const_iterator it = mSortIndexes.find(inv_item_id); + if (it != mSortIndexes.end()) { - // there is no sort field in the name of LLViewerInventoryItem, we should add it - mName = newSortField + separator + mName; + return it->second; } + return NO_INDEX; } -void LLViewerInventoryItem::rename(const std::string& n) +void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id) { - using std::string; + mSortIndexes.erase(inv_item_id); + mIsDirty = true; +} - string new_name(n); - LLStringUtil::replaceNonstandardASCII(new_name, ' '); - LLStringUtil::replaceChar(new_name, '|', ' '); - LLStringUtil::trim(new_name); - LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN); +// static +void LLFavoritesOrderStorage::destroyClass() +{ + LLFavoritesOrderStorage::instance().cleanup(); +} - const char separator = getSeparator(); - const string::size_type separatorPos = mName.find(separator, 0); +void LLFavoritesOrderStorage::load() +{ + // load per-resident sorting information + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); - if (separatorPos < string::npos) + LLSD settings_llsd; + llifstream file; + file.open(filename); + if (file.is_open()) { - mName.replace(separatorPos + 1, string::npos, new_name); + LLSDSerialize::fromXML(settings_llsd, file); } - else + + for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); + iter != settings_llsd.endMap(); ++iter) { - mName = new_name; + mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); } } -const LLPermissions& LLViewerInventoryItem::getPermissions() const +void LLFavoritesOrderStorage::save() { - if (const LLViewerInventoryItem *linked_item = getLinkedItem()) + // nothing to save if clean + if (!mIsDirty) return; + + // If we quit from the login screen we will not have an SL account + // name. Don't try to save, otherwise we'll dump a file in + // C:\Program Files\SecondLife\ or similar. JC + std::string user_dir = gDirUtilp->getLindenUserDir(); + if (!user_dir.empty()) { - return linked_item->getPermissions(); + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME); + LLSD settings_llsd; + + for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter) + { + settings_llsd[iter->first.asString()] = iter->second; + } + + llofstream file; + file.open(filename); + LLSDSerialize::toPrettyXML(settings_llsd, file); } +} + +void LLFavoritesOrderStorage::cleanup() +{ + // nothing to clean + if (!mIsDirty) return; + + const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); + + IsNotInFavorites is_not_in_fav(items); + + sort_index_map_t aTempMap; + //copy unremoved values from mSortIndexes to aTempMap + std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(), + inserter(aTempMap, aTempMap.begin()), + is_not_in_fav); + + //Swap the contents of mSortIndexes and aTempMap + mSortIndexes.swap(aTempMap); +} + +S32 LLViewerInventoryItem::getSortField() const +{ + return LLFavoritesOrderStorage::instance().getSortIndex(mUUID); +} + +void LLViewerInventoryItem::setSortField(S32 sortField) +{ + LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField); +} + +const LLPermissions& LLViewerInventoryItem::getPermissions() const +{ // Use the actual permissions of the symlink, not its parent. return LLInventoryItem::getPermissions(); } @@ -1310,6 +1492,8 @@ U32 LLViewerInventoryItem::getCRC32() const return LLInventoryItem::getCRC32(); } +// *TODO: mantipov: should be removed with LMSortPrefix patch in llinventorymodel.cpp, EXT-3985 +static char getSeparator() { return '@'; } BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName) { using std::string; @@ -1381,6 +1565,25 @@ LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const return NULL; } +bool LLViewerInventoryItem::checkPermissionsSet(PermissionMask mask) const +{ + const LLPermissions& perm = getPermissions(); + PermissionMask curr_mask = PERM_NONE; + if(perm.getOwner() == gAgent.getID()) + { + curr_mask = perm.getMaskBase(); + } + else if(gAgent.isInGroup(perm.getGroup())) + { + curr_mask = perm.getMaskGroup(); + } + else + { + curr_mask = perm.getMaskEveryone(); + } + return ((curr_mask & mask) == mask); +} + //---------- void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name) @@ -1390,3 +1593,74 @@ void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const std: gInventory.notifyObservers(); } +class LLRegenerateLinkCollector : public LLInventoryCollectFunctor +{ +public: + LLRegenerateLinkCollector(const LLViewerInventoryItem *target_item) : mTargetItem(target_item) {} + virtual ~LLRegenerateLinkCollector() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item) + { + if (item) + { + if ((item->getName() == mTargetItem->getName()) && + (item->getInventoryType() == mTargetItem->getInventoryType()) && + (!item->getIsLinkType())) + { + return true; + } + } + return false; + } +protected: + const LLViewerInventoryItem* mTargetItem; +}; + +LLUUID find_possible_item_for_regeneration(const LLViewerInventoryItem *target_item) +{ + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + + LLRegenerateLinkCollector candidate_matches(target_item); + gInventory.collectDescendentsIf(gInventory.getRootFolderID(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + candidate_matches); + for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items.begin(); + item_iter != items.end(); + ++item_iter) + { + const LLViewerInventoryItem *item = (*item_iter); + if (true) return item->getUUID(); + } + return LLUUID::null; +} + +// This currently dosen't work, because the sim does not allow us +// to change an item's assetID. +BOOL LLViewerInventoryItem::regenerateLink() +{ + const LLUUID target_item_id = find_possible_item_for_regeneration(this); + if (target_item_id.isNull()) + return FALSE; + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLAssetIDMatches asset_id_matches(getAssetUUID()); + gInventory.collectDescendentsIf(gInventory.getRootFolderID(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + asset_id_matches); + for (LLViewerInventoryItem::item_array_t::iterator item_iter = items.begin(); + item_iter != items.end(); + item_iter++) + { + LLViewerInventoryItem *item = (*item_iter); + item->setAssetUUID(target_item_id); + item->updateServer(FALSE); + gInventory.addChangedMask(LLInventoryObserver::REBUILD, item->getUUID()); + } + gInventory.notifyObservers(); + return TRUE; +} |