diff options
| -rw-r--r-- | indra/newview/llinventorybridge.cpp | 97 | ||||
| -rw-r--r-- | indra/newview/llinventorybridge.h | 11 | ||||
| -rw-r--r-- | indra/newview/llinventorypanel.cpp | 15 | ||||
| -rw-r--r-- | indra/newview/llviewerinventory.cpp | 49 | ||||
| -rw-r--r-- | indra/newview/llviewerinventory.h | 22 |
5 files changed, 134 insertions, 60 deletions
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index c8ea14a11e..8e4e70474f 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2026, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -249,11 +249,27 @@ const std::string& LLInvFVBridge::getName() const const std::string& LLInvFVBridge::getDisplayName() const { - if(mDisplayName.empty()) + if(mSearchableName.empty()) { - buildDisplayName(); + // first request of display name, build search string and cache it for later use + buildSearchableName(); } - return mDisplayName; + + LLInventoryModel* model = getInventoryModel(); + if (model) + { + LLViewerInventoryCategory* cat = model->getCategory(mUUID); + if (cat) + { + return cat->getDisplayName(); + } + LLViewerInventoryItem* item = model->getItem(mUUID); + if (item) + { + return item->getName(); + } + } + return LLStringUtil::null; } std::string LLInvFVBridge::getSearchableDescription() const @@ -2035,22 +2051,22 @@ PermissionMask LLItemBridge::getPermissionMask() const } // virtual -void LLItemBridge::buildDisplayName() const +void LLItemBridge::buildSearchableName() const { - if (getItem()) + LLViewerInventoryItem* item = getItem(); + if (item) { - mDisplayName.assign(getItem()->getName()); + // for items, display name matches item name + mSearchableName.assign(item->getName()); } else { - mDisplayName.assign(LLStringUtil::null); + mSearchableName.assign(LLStringUtil::null); } - - mSearchableName.assign(mDisplayName); mSearchableName.append(getLabelSuffix()); LLStringUtil::toUpper(mSearchableName); - // Name set, so trigger a sort + // Searchable and name set, so trigger a sort LLInventorySort sorter = static_cast<LLFolderViewModelInventory&>(mRootViewModel).getSorter(); if (mParent && !sorter.isByDate()) { @@ -2371,39 +2387,17 @@ void LLFolderBridge::selectItem() } } -void LLFolderBridge::buildDisplayName() const +void LLFolderBridge::buildSearchableName() const { - LLFolderType::EType preferred_type = getPreferredType(); - - // *TODO: to be removed when database supports multi language. This is a - // temporary attempt to display the inventory folder in the user locale. - // mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID - // it uses the same way to find localized string - - // HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder) - // Translation of Accessories folder in Library inventory folder - bool accessories = false; - if(getName() == "Accessories") + LLViewerInventoryCategory* cat = gInventory.getCategory(getUUID()); + if (cat) { - //To ensure that Accessories folder is in Library we have to check its parent folder. - //Due to parent LLFolderViewFloder is not set to this item yet we have to check its parent via Inventory Model - LLInventoryCategory* cat = gInventory.getCategory(getUUID()); - if(cat) - { - const LLUUID& parent_folder_id = cat->getParentUUID(); - accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); - } + mSearchableName.assign(cat->getDisplayName()); } - - //"Accessories" inventory category has folder type FT_NONE. So, this folder - //can not be detected as protected with LLFolderType::lookupIsProtectedType - mDisplayName.assign(getName()); - if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) + else { - LLTrans::findString(mDisplayName, std::string("InvFolder ") + getName(), LLSD()); + mSearchableName.assign(LLStringUtil::null); } - - mSearchableName.assign(mDisplayName); mSearchableName.append(getLabelSuffix()); LLStringUtil::toUpper(mSearchableName); @@ -2417,6 +2411,8 @@ void LLFolderBridge::buildDisplayName() const std::string LLFolderBridge::getLabelSuffix() const { + // Folders, unlike items, have context dependent suffixes + // that may change as the folder is loaded static LLCachedControl<bool> xui_debug(gSavedSettings, "DebugShowXUINames", 0); if (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= FOLDER_LOADING_MESSAGE_DELAY) @@ -6576,18 +6572,29 @@ void LLCallingCardBridge::refreshFolderViewItem() void LLCallingCardBridge::checkSearchBySuffixChanges() { - if (!mDisplayName.empty()) + if (!mSearchableName.empty()) { - // changes in mDisplayName are processed by rename function and here it will be always same + LLViewerInventoryItem* item = getItem(); + if (!item) + { + // checkSearchBySuffixChanges is only used by friend list + // so if item is not found, we removed the calling card or + // are no longer friends. + mSearchableName.clear(); + return; + } + + // changes in display name are processed by rename function and here it will be always same // suffixes are also of fixed length, and we are processing change of one at a time, // so it should be safe to use length (note: mSearchableName is capitalized) - auto old_length = mSearchableName.length(); - auto new_length = mDisplayName.length() + getLabelSuffix().length(); + size_t old_length = mSearchableName.length(); + const std::string& display_name = item->getName(); + size_t new_length = display_name.length() + getLabelSuffix().length(); if (old_length == new_length) { return; } - mSearchableName.assign(mDisplayName); + mSearchableName.assign(display_name); mSearchableName.append(getLabelSuffix()); LLStringUtil::toUpper(mSearchableName); if (new_length<old_length) @@ -7465,7 +7472,7 @@ bool LLObjectBridge::renameItem(const std::string& new_name) new_item->updateServer(false); model->updateItem(new_item); model->notifyObservers(); - buildDisplayName(); + buildSearchableName(); if (isAgentAvatarValid()) { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index decb2c0528..68e7a7f80e 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2026, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -87,7 +87,7 @@ public: virtual const LLUUID& getUUID() const { return mUUID; } virtual const LLUUID& getThumbnailUUID() const { return LLUUID::null; } virtual bool isFavorite() const { return false; } - virtual void clearDisplayName() { mDisplayName.clear(); } + virtual void clearSearchableName() { mSearchableName.clear(); } virtual void restoreItem() {} virtual void restoreToWorld() {} @@ -202,12 +202,11 @@ protected: LLInventoryType::EType mInvType; bool mIsLink; LLTimer mTimeSinceRequestStart; - mutable std::string mDisplayName; mutable std::string mSearchableName; void purgeItem(LLInventoryModel *model, const LLUUID &uuid); void removeObject(LLInventoryModel *model, const LLUUID &uuid); - virtual void buildDisplayName() const {} + virtual void buildSearchableName() const {} }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -266,7 +265,7 @@ public: protected: bool confirmRemoveItem(const LLSD& notification, const LLSD& response); virtual bool isItemPermissive() const; - virtual void buildDisplayName() const; + virtual void buildSearchableName() const; void doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb); private: @@ -287,7 +286,7 @@ public: void callback_dropItemIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryItem* inv_item); void callback_dropCategoryIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryCategory* inv_category); - virtual void buildDisplayName() const; + virtual void buildSearchableName() const; virtual void performAction(LLInventoryModel* model, std::string action); virtual void openItem(); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 06dd830416..e87ef025c6 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2026, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -581,8 +581,9 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getViewModelItem(); if(bridge) { - // Clear the display name first, so it gets properly re-built during refresh() - bridge->clearDisplayName(); + // Clear the searchable name first, so it gets + // properly re-built during refresh() + bridge->clearSearchableName(); view_item->refresh(); } @@ -1676,7 +1677,7 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it LLFolderBridge* prev_bridge = (LLFolderBridge*)prev_folder_item->getViewModelItem(); if(prev_bridge) { - prev_bridge->clearDisplayName(); + prev_bridge->clearSearchableName(); prev_bridge->setShowDescendantsCount(false); prev_folder_item->refresh(); } @@ -1685,7 +1686,7 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getViewModelItem(); if(bridge) { - bridge->clearDisplayName(); + bridge->clearSearchableName(); bridge->setShowDescendantsCount(true); folder_item->refresh(); mPreviousSelectedFolder = bridge->getUUID(); @@ -1700,7 +1701,7 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it LLFolderBridge* prev_bridge = (LLFolderBridge*)prev_folder_item->getViewModelItem(); if(prev_bridge) { - prev_bridge->clearDisplayName(); + prev_bridge->clearSearchableName(); prev_bridge->setShowDescendantsCount(false); prev_folder_item->refresh(); } @@ -1720,7 +1721,7 @@ void LLInventoryPanel::updateFolderLabel(const LLUUID& folder_id) LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getViewModelItem(); if(bridge) { - bridge->clearDisplayName(); + bridge->clearSearchableName(); bridge->setShowDescendantsCount(true); folder_item->refresh(); } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index efa3f5cd1e..707b2f1993 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2014, Linden Research, Inc. + * Copyright (C) 2026, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -673,6 +673,25 @@ void LLViewerInventoryCategory::setVersion(S32 version) mVersion = version; } +const std::string& LLViewerInventoryCategory::getDisplayName() const +{ + if (mNeedsDisplayNameUpdate) + { + buildDisplayName(); + } + if (!mDisplayName.empty()) + { + return mDisplayName; + } + return getName(); +} + +void LLViewerInventoryCategory::invalidateDisplayName() +{ + mNeedsDisplayNameUpdate = true; + mDisplayName.clear(); +} + bool LLViewerInventoryCategory::fetch(S32 expiry_seconds) { if((VERSION_UNKNOWN == getVersion()) @@ -889,6 +908,34 @@ void LLViewerInventoryCategory::localizeName() LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName); } +void LLViewerInventoryCategory::buildDisplayName() const +{ + // Secure and library folders can't be renamed, + // so we only need to do this once. + mNeedsDisplayNameUpdate = false; + + //"Accessories" inventory category has folder type FT_NONE. So, this folder + //can not be detected as protected with LLFolderType::lookupIsProtectedType + // + // HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder) + // Translation of Accessories folder in Library inventory folder + LLFolderType::EType preferred_type = getPreferredType(); + + bool is_accessories = false; + if (getName() == "Accessories") + { + // To ensure that Accessories folder is in Library we have to check its parent folder. + const LLUUID& parent_folder_id = getParentUUID(); + is_accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); + } + + if (is_accessories || LLFolderType::lookupIsProtectedType(preferred_type)) + { + // All predefined folders have translations in strings.xml. + LLTrans::findString(mDisplayName, std::string("InvFolder ") + getName(), LLSD()); + } +} + // virtual bool LLViewerInventoryCategory::unpackMessage(const LLSD& category) { diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index a42bdaa2b0..f14850da5a 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2026, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -209,6 +209,13 @@ public: S32 getVersion() const; void setVersion(S32 version); + const std::string& getDisplayName() const; + // The display name gets cached on demand, so needs a cleanup method. + // But in practice only secure folders' display name mismatches + // actual name, and those folders can't be renamed, so in practice + // this is useless unless we want to free memory. + void invalidateDisplayName(); + // Returns true if a fetch was issued (not nessesary in progress). // no requests will happen during expiry_seconds even if fetch completed bool fetch(S32 expiry_seconds = 10); @@ -253,6 +260,19 @@ protected: S32 mDescendentCount; EFetchType mFetching; LLFrameTimer mDescendentsRequested; + + // Display names are generated on demand and cached. + // buildDisplayName is essentially a way to localize + // system and library folders. + // + // TODO: This is on demand and mutable because that's how it + // worked in inventory bridge, before it was moved. + // But system folders always get loaded, it's likely better + // to just generate from the get go. + // Consider merging with localizeName. + void buildDisplayName() const; + mutable std::string mDisplayName; + mutable bool mNeedsDisplayNameUpdate = true; }; class LLInventoryCallback : public LLRefCount |
