diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llcommon/llassettype.cpp | 17 | ||||
| -rw-r--r-- | indra/llcommon/llassettype.h | 2 | ||||
| -rw-r--r-- | indra/llcommon/llsdutil.h | 38 | ||||
| -rw-r--r-- | indra/llinventory/llfoldertype.cpp | 19 | ||||
| -rw-r--r-- | indra/llinventory/llfoldertype.h | 2 | ||||
| -rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/newview/llinventoryfunctions.h | 4 | ||||
| -rw-r--r-- | indra/newview/llinventorylistener.cpp | 309 | ||||
| -rw-r--r-- | indra/newview/llinventorylistener.h | 48 | ||||
| -rw-r--r-- | indra/newview/llinventorymodel.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/llviewerinventory.cpp | 3 | 
11 files changed, 451 insertions, 1 deletions
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index c09cf7abd2..9672a3262b 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -29,6 +29,7 @@  #include "llassettype.h"  #include "lldictionary.h"  #include "llmemory.h" +#include "llsd.h"  #include "llsingleton.h"  ///---------------------------------------------------------------------------- @@ -246,3 +247,19 @@ bool LLAssetType::lookupIsAssetIDKnowable(EType asset_type)      }      return false;  } + +LLSD LLAssetType::getTypeNames() +{ +    LLSD type_names; +    const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); +    for (S32 type = AT_TEXTURE; type < AT_COUNT; ++type) +    { +        const AssetEntry *entry = dict->lookup((LLAssetType::EType) type); +        // skip llassettype_bad_lookup +        if (entry) +        { +            type_names.append(entry->mTypeName); +        } +    } +    return type_names; +} diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index 547c3f4329..17177d81c3 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -165,6 +165,8 @@ public:      static bool                 lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download      static bool                 lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer +    static LLSD getTypeNames(); +      static const std::string    BADLOOKUP;  protected: diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index 38bbe19ddd..4d65059fe6 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -553,6 +553,44 @@ LLSD shallow(LLSD value, LLSD filter=LLSD()) { return llsd_shallow(value, filter  } // namespace llsd +/***************************************************************************** +*   LLSDParam<std::vector<T>> +*****************************************************************************/ +// Given an LLSD array, return a const std::vector<T>&, where T is a type +// supported by LLSDParam. Bonus: if the LLSD value is actually a scalar, +// return a single-element vector containing the converted value. +template <typename T> +class LLSDParam<std::vector<T>>: public LLSDParamBase +{ +public: +    LLSDParam(const LLSD& array) +    { +        // treat undefined "array" as empty vector +        if (array.isDefined()) +        { +            // what if it's a scalar? +            if (! array.isArray()) +            { +                v.push_back(LLSDParam<T>(array)); +            } +            else                        // really is an array +            { +                // reserve space for the array entries +                v.reserve(array.size()); +                for (const auto& item : llsd::inArray(array)) +                { +                    v.push_back(LLSDParam<T>(item)); +                } +            } +        } +    } + +    operator const std::vector<T>&() const { return v; } + +private: +    std::vector<T> v; +}; +  // Specialization for generating a hash value from an LLSD block.  namespace boost  { diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp index 7e1be17ecc..670405e9b5 100644 --- a/indra/llinventory/llfoldertype.cpp +++ b/indra/llinventory/llfoldertype.cpp @@ -29,6 +29,7 @@  #include "llfoldertype.h"  #include "lldictionary.h"  #include "llmemory.h" +#include "llsd.h"  #include "llsingleton.h"  ///---------------------------------------------------------------------------- @@ -220,3 +221,21 @@ const std::string &LLFolderType::badLookup()      static const std::string sBadLookup = "llfoldertype_bad_lookup";      return sBadLookup;  } + +LLSD LLFolderType::getTypeNames() +{ +    LLSD type_names; +    for (S32 type = FT_TEXTURE; type < FT_COUNT; ++type) +    { +        if (lookupIsEnsembleType((LLFolderType::EType)type)) +            continue; + +        const FolderEntry* entry = LLFolderDictionary::getInstance()->lookup((LLFolderType::EType)type); +        // skip llfoldertype_bad_lookup +        if (entry) +        { +            type_names.append(entry->mName); +        } +    } +    return type_names; +} diff --git a/indra/llinventory/llfoldertype.h b/indra/llinventory/llfoldertype.h index 46a1b92a96..dd12693f66 100644 --- a/indra/llinventory/llfoldertype.h +++ b/indra/llinventory/llfoldertype.h @@ -115,6 +115,8 @@ public:      static const std::string&   badLookup(); // error string when a lookup fails +    static LLSD getTypeNames(); +  protected:      LLFolderType() {}      ~LLFolderType() {} diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 98a1d7f0fd..9290bc0ffa 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -362,6 +362,7 @@ set(viewer_SOURCE_FILES      llinventorygallerymenu.cpp      llinventoryicon.cpp      llinventoryitemslist.cpp +    llinventorylistener.cpp      llinventorylistitem.cpp      llinventorymodel.cpp      llinventorymodelbackgroundfetch.cpp @@ -1033,6 +1034,7 @@ set(viewer_HEADER_FILES      llinventorygallerymenu.h      llinventoryicon.h      llinventoryitemslist.h +    llinventorylistener.h      llinventorylistitem.h      llinventorymodel.h      llinventorymodelbackgroundfetch.h diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index a668cc31d8..b40fc051a0 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -192,7 +192,9 @@ class LLInventoryCollectFunctor  {  public:      virtual ~LLInventoryCollectFunctor(){}; -    virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) = 0; +        virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) = 0; + +        virtual bool exceedsLimit() { return false; }      static bool itemTransferCommonlyAllowed(const LLInventoryItem* item);  }; diff --git a/indra/newview/llinventorylistener.cpp b/indra/newview/llinventorylistener.cpp new file mode 100644 index 0000000000..028483e134 --- /dev/null +++ b/indra/newview/llinventorylistener.cpp @@ -0,0 +1,309 @@ +/** + * @file llinventorylistener.cpp + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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 + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llinventorylistener.h" + +#include "llappearancemgr.h" +#include "llinventoryfunctions.h" +#include "lltransutil.h" +#include "llwearableitemslist.h" +#include "stringize.h" + +LLInventoryListener::LLInventoryListener() +  : LLEventAPI("LLInventory", +               "API for interactions with viewer Inventory items") +{ +    add("getItemsInfo", +        "Return information about items or folders defined in [\"item_ids\"]:\n" +        "reply will contain [\"items\"] and [\"categories\"] result set keys", +        &LLInventoryListener::getItemsInfo, +        llsd::map("item_ids", LLSD(), "reply", LLSD())); + +    add("getFolderTypeNames", +        "Return the table of folder type names, contained in [\"names\"]\n", +        &LLInventoryListener::getFolderTypeNames, +        llsd::map("reply", LLSD())); + +    add("getAssetTypeNames", +        "Return the table of asset type names, contained in [\"names\"]\n", +        &LLInventoryListener::getAssetTypeNames, +        llsd::map("reply", LLSD())); + +    add("getBasicFolderID", +        "Return the UUID of the folder by specified folder type name, for example:\n" +        "\"Textures\", \"My outfits\", \"Sounds\" and other basic folders which have associated type", +        &LLInventoryListener::getBasicFolderID, +        llsd::map("ft_name", LLSD(), "reply", LLSD())); + +    add("getDirectDescendants", +        "Return result set keys [\"categories\"] and [\"items\"] for the direct\n" +        "descendants of the [\"folder_id\"]", +        &LLInventoryListener::getDirectDescendants, +        llsd::map("folder_id", LLSD(), "reply", LLSD())); + +    add("collectDescendantsIf", +        "Return result set keys [\"categories\"] and [\"items\"] for the descendants\n" +        "of the [\"folder_id\"], if it passes specified filters:\n" +        "[\"name\"] is a substring of object's name,\n" +        "[\"desc\"] is a substring of object's description,\n" +        "asset [\"type\"] corresponds to the string name of the object's asset type\n" +        "[\"limit\"] sets item count limit in result set (default unlimited)\n" +        "[\"filter_links\"]: EXCLUDE_LINKS - don't show links, ONLY_LINKS - only show links, INCLUDE_LINKS - show links too (default)", +        &LLInventoryListener::collectDescendantsIf, +        llsd::map("folder_id", LLSD(), "reply", LLSD())); +} + +void add_cat_info(LLEventAPI::Response& response, LLViewerInventoryCategory* cat) +{ +    response["categories"].insert(cat->getUUID().asString(), +                                  llsd::map("id", cat->getUUID(), +                                            "name", cat->getName(), +                                            "parent_id", cat->getParentUUID(), +                                            "type", LLFolderType::lookup(cat->getPreferredType()))); + +}; + +void add_item_info(LLEventAPI::Response& response, LLViewerInventoryItem* item) +{ +    response["items"].insert(item->getUUID().asString(), +                             llsd::map("id", item->getUUID(), +                                       "name", item->getName(), +                                       "parent_id", item->getParentUUID(), +                                       "desc", item->getDescription(), +                                       "inv_type", LLInventoryType::lookup(item->getInventoryType()), +                                       "asset_type", LLAssetType::lookup(item->getType()), +                                       "creation_date", LLSD::Integer(item->getCreationDate()), +                                       "asset_id", item->getAssetUUID(), +                                       "is_link", item->getIsLinkType(), +                                       "linked_id", item->getLinkedUUID())); +} + +void add_objects_info(LLEventAPI::Response& response, LLInventoryModel::cat_array_t cat_array, LLInventoryModel::item_array_t item_array) +{ +    for (auto& p : item_array) +    { +        add_item_info(response, p); +    } +    for (auto& p : cat_array) +    { +        add_cat_info(response, p); +    } +} + +void LLInventoryListener::getItemsInfo(LLSD const &data) +{ +    Response response(LLSD(), data); +    uuid_vec_t ids = LLSDParam<uuid_vec_t>(data["item_ids"]); +    for (auto &it : ids) +    { +        LLViewerInventoryItem* item = gInventory.getItem(it); +        if (item) +        { +            add_item_info(response, item); +        } +        else +        { +            LLViewerInventoryCategory *cat = gInventory.getCategory(it); +            if (cat) +            { +                add_cat_info(response, cat); +            } +        } +    } +} + +void LLInventoryListener::getFolderTypeNames(LLSD const &data) +{ +    Response response(llsd::map("names", LLFolderType::getTypeNames()), data); +} + +void LLInventoryListener::getAssetTypeNames(LLSD const &data) +{ +    Response response(llsd::map("names", LLAssetType::getTypeNames()), data); +} + +void LLInventoryListener::getBasicFolderID(LLSD const &data) +{ +    Response response(llsd::map("id", gInventory.findCategoryUUIDForType(LLFolderType::lookup(data["ft_name"].asString()))), data); +} + + +void LLInventoryListener::getDirectDescendants(LLSD const &data) +{ +    Response response(LLSD(), data); +    LLUUID folder_id(data["folder_id"].asUUID()); +    LLViewerInventoryCategory* cat = gInventory.getCategory(folder_id); +    if (!cat) +    { +        return response.error(stringize("Folder ", std::quoted(data["folder_id"].asString()), " was not found")); +    } +    LLInventoryModel::cat_array_t* cats; +    LLInventoryModel::item_array_t* items; +    gInventory.getDirectDescendentsOf(folder_id, cats, items); + +    add_objects_info(response, *cats, *items); +} + +struct LLFilteredCollector : public LLInventoryCollectFunctor +{ +    enum EFilterLink +    { +        INCLUDE_LINKS,  // show links too +        EXCLUDE_LINKS,  // don't show links +        ONLY_LINKS      // only show links +    }; + +    LLFilteredCollector(LLSD const &data); +    virtual ~LLFilteredCollector() {} +    virtual bool operator()(LLInventoryCategory *cat, LLInventoryItem *item) override; +    virtual bool exceedsLimit() override +    { +        // mItemLimit == 0 means unlimited +        return (mItemLimit && mItemLimit <= mItemCount); +    } + +  protected: +    bool checkagainstType(LLInventoryCategory *cat, LLInventoryItem *item); +    bool checkagainstNameDesc(LLInventoryCategory *cat, LLInventoryItem *item); +    bool checkagainstLinks(LLInventoryCategory *cat, LLInventoryItem *item); + +    LLAssetType::EType mType; +    std::string mName; +    std::string mDesc; +    EFilterLink mLinkFilter; + +    S32 mItemLimit; +    S32 mItemCount; +}; + +void LLInventoryListener::collectDescendantsIf(LLSD const &data) +{ +    Response response(LLSD(), data); +    LLUUID folder_id(data["folder_id"].asUUID()); +    LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id); +    if (!cat) +    { +        return response.error(stringize("Folder ", std::quoted(data["folder_id"].asString()), " was not found")); +    } +    LLInventoryModel::cat_array_t  cat_array; +    LLInventoryModel::item_array_t item_array; + +    LLFilteredCollector collector = LLFilteredCollector(data); + +    gInventory.collectDescendentsIf(folder_id, cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, collector); + +    add_objects_info(response, cat_array, item_array); +} + +LLFilteredCollector::LLFilteredCollector(LLSD const &data) : +    mType(LLAssetType::EType::AT_UNKNOWN), +    mLinkFilter(INCLUDE_LINKS), +    mItemLimit(0), +    mItemCount(0) +{ + +    mName = data["name"].asString(); +    mDesc = data["desc"].asString(); + +    if (data.has("type")) +    { +        mType = LLAssetType::lookup(data["type"]); +    } +    if (data.has("filter_links")) +    { +        if (data["filter_links"] == "EXCLUDE_LINKS") +        { +            mLinkFilter = EXCLUDE_LINKS; +        } +        else if (data["filter_links"] == "ONLY_LINKS") +        { +            mLinkFilter = ONLY_LINKS; +        } +    } +    if (data["limit"].isInteger()) +    { +        mItemLimit = std::max(data["limit"].asInteger(), 1); +    } +} + +bool LLFilteredCollector::operator()(LLInventoryCategory *cat, LLInventoryItem *item) +{ +    bool passed = checkagainstType(cat, item); +    passed = passed && checkagainstNameDesc(cat, item); +    passed = passed && checkagainstLinks(cat, item); + +    if (passed) +    { +        ++mItemCount; +    } +    return passed; +} + +bool LLFilteredCollector::checkagainstNameDesc(LLInventoryCategory *cat, LLInventoryItem *item) +{ +    std::string name, desc; +    bool passed(true); +    if (cat) +    { +        if (!mDesc.empty()) return false; +        name = cat->getName(); +    } +    if (item) +    { +        name = item->getName(); +        passed = (mDesc.empty() || (item->getDescription().find(mDesc) != std::string::npos)); +    } + +    return passed && (mName.empty() || name.find(mName) != std::string::npos); +} + +bool LLFilteredCollector::checkagainstType(LLInventoryCategory *cat, LLInventoryItem *item) +{ +    if (mType == LLAssetType::AT_UNKNOWN) +    { +        return true; +    } +    if (cat && (mType == LLAssetType::AT_CATEGORY)) +    { +        return true; +    } +    if (item && item->getType() == mType) +    { +        return true; +    } +    return false; +} + +bool LLFilteredCollector::checkagainstLinks(LLInventoryCategory *cat, LLInventoryItem *item) +{ +    bool is_link = cat ? cat->getIsLinkType() : item->getIsLinkType(); +    if (is_link && (mLinkFilter == EXCLUDE_LINKS)) +        return false; +    if (!is_link && (mLinkFilter == ONLY_LINKS)) +        return false; +    return true; +} diff --git a/indra/newview/llinventorylistener.h b/indra/newview/llinventorylistener.h new file mode 100644 index 0000000000..d50397730c --- /dev/null +++ b/indra/newview/llinventorylistener.h @@ -0,0 +1,48 @@ +/** + * @file llinventorylistener.h + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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 + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + + +#ifndef LL_LLINVENTORYLISTENER_H +#define LL_LLINVENTORYLISTENER_H + +#include "lleventapi.h" +#include "llinventoryfunctions.h" + +class LLInventoryListener : public LLEventAPI +{ +public: +    LLInventoryListener(); + +private: +    void getItemsInfo(LLSD const &data); +    void getFolderTypeNames(LLSD const &data); +    void getAssetTypeNames(LLSD const &data); +    void getBasicFolderID(LLSD const &data); +    void getDirectDescendants(LLSD const &data); +    void collectDescendantsIf(LLSD const &data); +}; + +#endif // LL_LLINVENTORYLISTENER_H + diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index c7cc8f3032..110957dfa7 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1282,6 +1282,10 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,      {          for (auto& cat : *cat_array)          { +            if (add.exceedsLimit()) +            { +                break; +            }              if(add(cat,NULL))              {                  cats.push_back(cat); @@ -1297,6 +1301,10 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,      {          for (auto& item : *item_array)          { +            if (add.exceedsLimit()) +            { +                break; +            }              if(add(NULL, item))              {                  items.push_back(item); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 8caa0144c3..5f61aeaf13 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -71,6 +71,9 @@  #include "llclipboard.h"  #include "llhttpretrypolicy.h"  #include "llsettingsvo.h" +#include "llinventorylistener.h" + +LLInventoryListener sInventoryListener;  // do-nothing ops for use in callbacks.  void no_op_inventory_func(const LLUUID&) {}  | 
