From e5b8b799cc75f3b9cd259403c323cd47b59453d8 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 29 Mar 2023 13:51:40 +0300 Subject: SL-19379 WIP add basic context menu --- indra/newview/llinventorygallerymenu.cpp | 616 +++++++++++++++++++++++++++++++ 1 file changed, 616 insertions(+) create mode 100644 indra/newview/llinventorygallerymenu.cpp (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp new file mode 100644 index 0000000000..11dd5e6690 --- /dev/null +++ b/indra/newview/llinventorygallerymenu.cpp @@ -0,0 +1,616 @@ +/** + * @file llinventorygallerymenu.cpp + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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 "llinventorygallery.h" +#include "llinventorygallerymenu.h" + +#include "llagent.h" +#include "llappearancemgr.h" +#include "llavataractions.h" +#include "llclipboard.h" +#include "llfloaterreg.h" +#include "llgiveinventory.h" +#include "llinventorybridge.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "llmarketplacefunctions.h" +#include "llmenugl.h" +#include "llnotificationsutil.h" +#include "llviewerfoldertype.h" +#include "llviewerwindow.h" + +LLContextMenu* LLInventoryGalleryContextMenu::createMenu() +{ + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + //LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + LLUUID selected_id = mUUIDs.front(); + + registrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryGalleryContextMenu::doToSelected, this, _2, selected_id)); + registrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::fileUploadLocation, this, _2, selected_id)); + registrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH)); + registrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)); + + std::set uuids{selected_id}; + registrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, uuids, gFloaterView->getParentFloater(mGallery))); + + LLContextMenu* menu = createFromFile("menu_gallery_inventory.xml"); + + updateMenuItemsVisibility(menu); + + return menu; +} + +void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLUUID& selected_id) +{ + std::string action = userdata.asString(); + LLInventoryObject* obj = gInventory.getObject(selected_id); + if(!obj) return; + + bool is_folder = (obj->getType() == LLAssetType::AT_CATEGORY); + + if ("open_selected_folder" == action) + { + mGallery->setRootFolder(selected_id); + } + else if ("open_in_new_window" == action) + { + new_folder_window(selected_id); + } + else if ("properties" == action) + { + show_item_profile(selected_id); + } + else if ("restore" == action) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(selected_id); + if(cat) + { + const LLUUID new_parent = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType())); + // do not restamp children on restore + gInventory.changeCategoryParent(cat, new_parent, false); + } + else + { + LLViewerInventoryItem* item = gInventory.getItem(selected_id); + if(item) + { + bool is_snapshot = (item->getInventoryType() == LLInventoryType::IT_SNAPSHOT); + + const LLUUID new_parent = gInventory.findCategoryUUIDForType(is_snapshot? LLFolderType::FT_SNAPSHOT_CATEGORY : LLFolderType::assetTypeToFolderType(item->getType())); + // do not restamp children on restore + gInventory.changeItemParent(item, new_parent, false); + } + } + } + else if ("copy_uuid" == action) + { + LLViewerInventoryItem* item = gInventory.getItem(selected_id); + if(item) + { + LLUUID asset_id = item->getProtectedAssetUUID(); + std::string buffer; + asset_id.toString(buffer); + + gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(buffer)); + } + } + else if ("purge" == action) + { + remove_inventory_object(selected_id, NULL); + } + else if ("goto" == action) + { + show_item_original(selected_id); + } + else if ("thumbnail" == action) + { + LLSD data(selected_id); + LLFloaterReg::showInstance("change_item_thumbnail", data); + } + else if ("cut" == action) + { + bool allow = false; + if(is_folder) + { + allow = get_is_category_removable(&gInventory, selected_id); + } + else + { + allow = get_is_item_removable(&gInventory, selected_id); + } + if(allow) + { + LLClipboard::instance().setCutMode(true); + LLClipboard::instance().addToClipboard(selected_id); + } + } + else if ("paste" == action) + { + { + const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + if(gInventory.isObjectDescendentOf(selected_id, marketplacelistings_id)) + { + return; + } + + bool is_cut_mode = (LLClipboard::instance().isCutMode()); + { + std::vector objects; + LLClipboard::instance().pasteFromClipboard(objects); + for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) + { + const LLUUID& item_id = (*iter); + if(gInventory.isObjectDescendentOf(item_id, marketplacelistings_id) && (LLMarketplaceData::instance().isInActiveFolder(item_id) || + LLMarketplaceData::instance().isListedAndActive(item_id))) + { + return; + } + LLViewerInventoryCategory* cat = gInventory.getCategory(item_id); + if (cat) + { + if(is_cut_mode) + { + gInventory.changeCategoryParent(cat, selected_id, false); + } + else + { + copy_inventory_category(&gInventory, cat, selected_id); + } + } + else + { + LLViewerInventoryItem* item = gInventory.getItem(item_id); + if (item) + { + if(is_cut_mode) + { + gInventory.changeItemParent(item, selected_id, false); + } + else + { + if (item->getIsLinkType()) + { + link_inventory_object(selected_id, item_id, + LLPointer(NULL)); + } + else + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + selected_id, + std::string(), + LLPointer(NULL)); + } + } + } + } + } + LLClipboard::instance().setCutMode(false); + } + + } + } + else if ("delete" == action) + { + if (is_folder) + { + if(get_is_category_removable(&gInventory, selected_id)) + { + gInventory.removeCategory(selected_id); + } + } + else + { + if(get_is_item_removable(&gInventory, selected_id)) + { + gInventory.removeItem(selected_id); + } + } + } + else if ("copy" == action) + { + if(is_folder) + { + LLClipboard::instance().reset(); + LLClipboard::instance().addToClipboard(selected_id); + } + else + { + LLViewerInventoryItem* inv_item = gInventory.getItem(selected_id); + if (inv_item && inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()) && !get_is_item_worn(selected_id)) + { + LLClipboard::instance().reset(); + LLClipboard::instance().addToClipboard(selected_id); + } + } + } + else if ("paste_as_link" == action) + { + link_inventory_object(selected_id, obj, LLPointer(NULL)); + } + else if ("rename" == action) + { + LLSD args; + args["NAME"] = obj->getName(); + + LLSD payload; + payload["id"] = selected_id; + + LLNotificationsUtil::add("RenameItem", args, payload, boost::bind(onRename, _1, _2)); + } + else if ("open" == action || "open_original" == action) + { + LLViewerInventoryItem* item = gInventory.getItem(selected_id); + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(), selected_id , &gInventory); + } + } + else if ("ungroup_folder_items" == action) + { + ungroup_folder_items(selected_id); + } +} + +void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return; // canceled + + std::string new_name = response["new_name"].asString(); + LLStringUtil::trim(new_name); + if (!new_name.empty()) + { + LLUUID id = notification["payload"]["id"].asUUID(); + + LLViewerInventoryCategory* cat = gInventory.getCategory(id); + if(cat && (cat->getName() != new_name)) + { + LLSD updates; + updates["name"] = new_name; + update_inventory_category(cat->getUUID(),updates, NULL); + return; + } + + LLViewerInventoryItem* item = gInventory.getItem(id); + if(item && (item->getName() != new_name)) + { + LLSD updates; + updates["name"] = new_name; + update_inventory_item(item->getUUID(),updates, NULL); + } + } +} + +void LLInventoryGalleryContextMenu::fileUploadLocation(const LLSD& userdata, const LLUUID& selected_id) +{ + const std::string param = userdata.asString(); + if (param == "model") + { + gSavedPerAccountSettings.setString("ModelUploadFolder", selected_id.asString()); + } + else if (param == "texture") + { + gSavedPerAccountSettings.setString("TextureUploadFolder", selected_id.asString()); + } + else if (param == "sound") + { + gSavedPerAccountSettings.setString("SoundUploadFolder", selected_id.asString()); + } + else if (param == "animation") + { + gSavedPerAccountSettings.setString("AnimationUploadFolder", selected_id.asString()); + } +} + +bool can_share_item(LLUUID item_id) +{ + bool can_share = false; + + if (gInventory.isObjectDescendentOf(item_id, gInventory.getRootFolderID())) + { + const LLViewerInventoryItem *item = gInventory.getItem(item_id); + if (item) + { + if (LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item)) + { + can_share = LLGiveInventory::isInventoryGiveAcceptable(item); + } + } + else + { + can_share = (gInventory.getCategory(item_id) != NULL); + } + + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if ((item_id == trash_id) || gInventory.isObjectDescendentOf(item_id, trash_id)) + { + can_share = false; + } + } + + return can_share; +} + +bool is_inbox_folder(LLUUID item_id) +{ + const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX); + + if (inbox_id.isNull()) + { + return false; + } + + return gInventory.isObjectDescendentOf(item_id, inbox_id); +} + +void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* menu) +{ + LLUUID selected_id = mUUIDs.front(); + LLInventoryObject* obj = gInventory.getObject(selected_id); + if (!obj) + { + return; + } + + std::vector items; + std::vector disabled_items; + + bool is_agent_inventory = gInventory.isObjectDescendentOf(selected_id, gInventory.getRootFolderID()); + bool is_link = obj->getIsLinkType(); + bool is_folder = (obj->getType() == LLAssetType::AT_CATEGORY); + bool is_cof = LLAppearanceMgr::instance().getIsInCOF(selected_id); + bool is_inbox = is_inbox_folder(selected_id); + bool is_trash = (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)); + bool is_in_trash = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)); + bool is_lost_and_found = (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); + bool is_outfits= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS)); + //bool is_favorites= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)); + + bool is_system_folder = false; + LLFolderType::EType folder_type(LLFolderType::FT_NONE); + bool has_children = false; + bool is_full_perm_item = false; + bool is_copyable = false; + LLViewerInventoryItem* selected_item = gInventory.getItem(selected_id); + + if(is_folder) + { + LLInventoryCategory* category = gInventory.getCategory(selected_id); + if (category) + { + folder_type = category->getPreferredType(); + is_system_folder = LLFolderType::lookupIsProtectedType(folder_type); + has_children = (gInventory.categoryHasChildren(selected_id) != LLInventoryModel::CHILDREN_NO); + } + } + else + { + if (selected_item) + { + is_full_perm_item = selected_item->getIsFullPerm(); + is_copyable = selected_item->getPermissions().allowCopyBy(gAgent.getID()); + } + } + + if(!is_link) + { + items.push_back(std::string("thumbnail")); + LLViewerInventoryItem* inv_item = gInventory.getItem(selected_id); + if (inv_item && !inv_item->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID())) + { + disabled_items.push_back(std::string("thumbnail")); + } + } + + if (is_folder) + { + items.push_back(std::string("Copy Separator")); + + items.push_back(std::string("open_in_current_window")); + items.push_back(std::string("open_in_new_window")); + items.push_back(std::string("Open Folder Separator")); + } + + if(is_trash) + { + items.push_back(std::string("Empty Trash")); + + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(selected_id, cat_array, item_array); + if (0 == cat_array->size() && 0 == item_array->size()) + { + disabled_items.push_back(std::string("Empty Trash")); + } + } + else if(is_in_trash) + { + if (is_link) + { + items.push_back(std::string("Find Original")); + if (LLAssetType::lookupIsLinkType(obj->getType())) + { + disabled_items.push_back(std::string("Find Original")); + } + } + items.push_back(std::string("Purge Item")); + if (!get_is_category_removable(&gInventory, selected_id)) + { + disabled_items.push_back(std::string("Purge Item")); + } + items.push_back(std::string("Restore Item")); + } + else + { + if(can_share_item(selected_id)) + { + items.push_back(std::string("Share")); + } + if (is_folder && is_agent_inventory) + { + if (!is_cof && (folder_type != LLFolderType::FT_OUTFIT) && !is_outfits && !is_inbox_folder(selected_id)) + { + if (!gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD))) + { + items.push_back(std::string("New Folder")); + } + items.push_back(std::string("upload_def")); + } + + if(is_outfits) + { + items.push_back(std::string("New Outfit")); + } + + items.push_back(std::string("Subfolder Separator")); + if (!is_system_folder) + { + if(has_children && (folder_type != LLFolderType::FT_OUTFIT)) + { + items.push_back(std::string("Ungroup folder items")); + } + items.push_back(std::string("Cut")); + items.push_back(std::string("Delete")); + if(!get_is_category_removable(&gInventory, selected_id)) + { + disabled_items.push_back(std::string("Delete")); + disabled_items.push_back(std::string("Cut")); + } + if(!is_inbox) + { + items.push_back(std::string("Rename")); + } + } + if (LLClipboard::instance().hasContents() && is_agent_inventory && !is_cof && !is_inbox_folder(selected_id)) + { + items.push_back(std::string("Paste")); + + static LLCachedControl inventory_linking(gSavedSettings, "InventoryLinking", true); + if (inventory_linking) + { + items.push_back(std::string("Paste As Link")); + } + } + if(!is_system_folder) + { + items.push_back(std::string("Copy")); + } + } + else if(!is_folder) + { + items.push_back(std::string("Properties")); + items.push_back(std::string("Copy Asset UUID")); + items.push_back(std::string("Copy Separator")); + + bool is_asset_knowable = is_asset_knowable = LLAssetType::lookupIsAssetIDKnowable(obj->getType()); + if ( !is_asset_knowable // disable menu item for Inventory items with unknown asset. EXT-5308 + || (! ( is_full_perm_item || gAgent.isGodlike()))) + { + disabled_items.push_back(std::string("Copy Asset UUID")); + } + if(is_agent_inventory) + { + items.push_back(std::string("Cut")); + if (!is_link || !is_cof || !get_is_item_worn(selected_id)) + { + items.push_back(std::string("Delete")); + } + if(!get_is_item_removable(&gInventory, selected_id)) + { + disabled_items.push_back(std::string("Delete")); + disabled_items.push_back(std::string("Cut")); + } + + if (selected_item && (selected_item->getInventoryType() != LLInventoryType::IT_CALLINGCARD) && !is_inbox && selected_item->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID())) + { + items.push_back(std::string("Rename")); + } + } + items.push_back(std::string("Copy")); + if (!is_copyable) + { + disabled_items.push_back(std::string("Copy")); + } + } + if((obj->getType() == LLAssetType::AT_SETTINGS) + || ((obj->getType() <= LLAssetType::AT_GESTURE) + && obj->getType() != LLAssetType::AT_OBJECT + && obj->getType() != LLAssetType::AT_CLOTHING + && obj->getType() != LLAssetType::AT_CATEGORY + && obj->getType() != LLAssetType::AT_BODYPART)) + { + bool can_open = !LLAssetType::lookupIsLinkType(obj->getType()); + + if (can_open) + { + if (is_link) + items.push_back(std::string("Open Original")); + else + items.push_back(std::string("Open")); + } + else + { + disabled_items.push_back(std::string("Open")); + disabled_items.push_back(std::string("Open Original")); + } + } + else if(LLAssetType::AT_LANDMARK == obj->getType()) + { + items.push_back(std::string("Landmark Open")); + } + if (is_link) + { + items.push_back(std::string("Find Original")); + if (LLAssetType::lookupIsLinkType(obj->getType())) + { + disabled_items.push_back(std::string("Find Original")); + } + } + if (is_lost_and_found) + { + items.push_back(std::string("Empty Lost And Found")); + + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(selected_id, cat_array, item_array); + // Enable Empty menu item only when there is something to act upon. + if (0 == cat_array->size() && 0 == item_array->size()) + { + disabled_items.push_back(std::string("Empty Lost And Found")); + } + + disabled_items.push_back(std::string("New Folder")); + disabled_items.push_back(std::string("upload_def")); + } + } + + hide_context_entries(*menu, items, disabled_items); +} + -- cgit v1.3 From e161b128c7eac6df63b6d9210f3bca6c3cbc77ea Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 30 Mar 2023 02:36:14 +0300 Subject: SL-19379 WIP one more batch of context menu items --- indra/newview/llinventorygallerymenu.cpp | 54 ++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 11dd5e6690..a501f02e00 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -42,6 +42,7 @@ #include "llnotificationsutil.h" #include "llviewerfoldertype.h" #include "llviewerwindow.h" +#include "llvoavatarself.h" LLContextMenu* LLInventoryGalleryContextMenu::createMenu() { @@ -276,6 +277,18 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU { ungroup_folder_items(selected_id); } + else if ("take_off" == action || "detach" == action) + { + LLAppearanceMgr::instance().removeItemFromAvatar(selected_id); + } + else if ("wear_add" == action) + { + LLAppearanceMgr::instance().wearItemOnAvatar(selected_id, true, false); // Don't replace if adding. + } + else if ("wear" == action) + { + LLAppearanceMgr::instance().wearItemOnAvatar(selected_id, true, true); + } } void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLSD& response) @@ -564,6 +577,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men && obj->getType() != LLAssetType::AT_OBJECT && obj->getType() != LLAssetType::AT_CLOTHING && obj->getType() != LLAssetType::AT_CATEGORY + && obj->getType() != LLAssetType::AT_LANDMARK && obj->getType() != LLAssetType::AT_BODYPART)) { bool can_open = !LLAssetType::lookupIsLinkType(obj->getType()); @@ -585,6 +599,46 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men { items.push_back(std::string("Landmark Open")); } + else if (obj->getType() == LLAssetType::AT_OBJECT || obj->getType() == LLAssetType::AT_CLOTHING || obj->getType() == LLAssetType::AT_BODYPART) + { + items.push_back(std::string("Wearable And Object Separator")); + if(obj->getType() == LLAssetType::AT_CLOTHING) + { + items.push_back(std::string("Take Off")); + } + if(get_is_item_worn(selected_id)) + { + if(obj->getType() == LLAssetType::AT_OBJECT) + { + items.push_back(std::string("Detach From Yourself")); + } + disabled_items.push_back(std::string("Wearable And Object Wear")); + disabled_items.push_back(std::string("Wearable Add")); + } + else + { + if(obj->getType() == LLAssetType::AT_OBJECT) + { + items.push_back(std::string("Wearable Add")); + } + items.push_back(std::string("Wearable And Object Wear")); + disabled_items.push_back(std::string("Take Off")); + } + + if (!gAgentAvatarp->canAttachMoreObjects() && (obj->getType() == LLAssetType::AT_OBJECT)) + { + disabled_items.push_back(std::string("Wearable And Object Wear")); + disabled_items.push_back(std::string("Wearable Add")); + } + if (selected_item && (obj->getType() != LLAssetType::AT_OBJECT) && LLWearableType::getInstance()->getAllowMultiwear(selected_item->getWearableType())) + { + items.push_back(std::string("Wearable Add")); + if (!gAgentWearables.canAddWearable(selected_item->getWearableType())) + { + disabled_items.push_back(std::string("Wearable Add")); + } + } + } if (is_link) { items.push_back(std::string("Find Original")); -- cgit v1.3 From ae3e3662159ca26db5b2efe36d91a9ccdfcec256 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 30 Mar 2023 21:39:43 +0300 Subject: SL-19379 WIP update gear menu with Gallery items --- indra/newview/llinventoryfunctions.cpp | 30 ++++ indra/newview/llinventoryfunctions.h | 1 + indra/newview/llinventorygallery.h | 1 + indra/newview/llinventorygallerymenu.cpp | 30 ---- indra/newview/llpanelmaininventory.cpp | 163 ++++++++++++++++----- indra/newview/llpanelmaininventory.h | 5 +- .../default/xui/en/menu_inventory_gear_default.xml | 3 +- 7 files changed, 168 insertions(+), 65 deletions(-) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index f24c2de714..7979ef209a 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -55,6 +55,7 @@ #include "llfocusmgr.h" #include "llfolderview.h" #include "llgesturemgr.h" +#include "llgiveinventory.h" #include "lliconctrl.h" #include "llimview.h" #include "llinventorybridge.h" @@ -2219,6 +2220,35 @@ std::string get_searchable_UUID(LLInventoryModel* model, const LLUUID& item_id) } return LLStringUtil::null; } + +bool can_share_item(const LLUUID& item_id) +{ + bool can_share = false; + + if (gInventory.isObjectDescendentOf(item_id, gInventory.getRootFolderID())) + { + const LLViewerInventoryItem *item = gInventory.getItem(item_id); + if (item) + { + if (LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item)) + { + can_share = LLGiveInventory::isInventoryGiveAcceptable(item); + } + } + else + { + can_share = (gInventory.getCategory(item_id) != NULL); + } + + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if ((item_id == trash_id) || gInventory.isObjectDescendentOf(item_id, trash_id)) + { + can_share = false; + } + } + + return can_share; +} ///---------------------------------------------------------------------------- /// LLMarketplaceValidator implementations ///---------------------------------------------------------------------------- diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 5c4a325eca..1b0f598bf5 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -106,6 +106,7 @@ void ungroup_folder_items(const LLUUID& folder_id); std::string get_searchable_description(LLInventoryModel* model, const LLUUID& item_id); std::string get_searchable_creator_name(LLInventoryModel* model, const LLUUID& item_id); std::string get_searchable_UUID(LLInventoryModel* model, const LLUUID& item_id); +bool can_share_item(const LLUUID& item_id); /** Miscellaneous global functions ** ** diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index 02e706eecd..c53640d0ff 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -108,6 +108,7 @@ public: void deselectItem(const LLUUID& category_id); void signalSelectionItemID(const LLUUID& category_id); boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb); + LLUUID getSelectedItemID() { return mSelectedItemID; } void setSearchType(LLInventoryFilter::ESearchType type); LLInventoryFilter::ESearchType getSearchType() { return mSearchType; } diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index a501f02e00..21f7b06534 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -33,7 +33,6 @@ #include "llavataractions.h" #include "llclipboard.h" #include "llfloaterreg.h" -#include "llgiveinventory.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventorymodel.h" @@ -342,35 +341,6 @@ void LLInventoryGalleryContextMenu::fileUploadLocation(const LLSD& userdata, con } } -bool can_share_item(LLUUID item_id) -{ - bool can_share = false; - - if (gInventory.isObjectDescendentOf(item_id, gInventory.getRootFolderID())) - { - const LLViewerInventoryItem *item = gInventory.getItem(item_id); - if (item) - { - if (LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item)) - { - can_share = LLGiveInventory::isInventoryGiveAcceptable(item); - } - } - else - { - can_share = (gInventory.getCategory(item_id) != NULL); - } - - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if ((item_id == trash_id) || gInventory.isObjectDescendentOf(item_id, trash_id)) - { - can_share = false; - } - } - - return can_share; -} - bool is_inbox_folder(LLUUID item_id) { const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX); diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index cc2c17d17d..e55d1f19f4 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -130,7 +130,6 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p) mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLPanelMainInventory::toggleFindOptions, this)); mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLPanelMainInventory::resetFilters, this)); mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLPanelMainInventory::setSortBy, this, _2)); - mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, this)); mEnableCallbackRegistrar.add("Inventory.EnvironmentEnabled", [](LLUICtrl *, const LLSD &) { return LLPanelMainInventory::hasSettingsInventory(); }); @@ -416,14 +415,15 @@ S32 get_instance_num() return instance_num; } -void LLPanelMainInventory::newWindow() +LLFloaterSidePanelContainer* LLPanelMainInventory::newWindow() { S32 instance_num = get_instance_num(); if (!gAgentCamera.cameraMouselook()) { - LLFloaterReg::showTypedInstance("inventory", LLSD(instance_num)); + return LLFloaterReg::showTypedInstance("inventory", LLSD(instance_num)); } + return NULL; } //static @@ -527,6 +527,17 @@ void LLPanelMainInventory::resetAllItemsFilters() setFilterTextFromFilter(); } +void LLPanelMainInventory::findLinks(const LLUUID& item_id, const std::string& item_name) +{ + mFilterSubString = item_name; + + LLInventoryFilter &filter = mActivePanel->getFilter(); + filter.setFindAllLinksMode(item_name, item_id); + + mFilterEditor->setText(item_name); + mFilterEditor->setFocus(TRUE); +} + void LLPanelMainInventory::setSortBy(const LLSD& userdata) { U32 sort_order_mask = getActivePanel()->getSortOrder(); @@ -1556,13 +1567,22 @@ void LLPanelMainInventory::onClipboardAction(const LLSD& userdata) void LLPanelMainInventory::saveTexture(const LLSD& userdata) { - LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); - if (!current_item) - { - return; - } - - const LLUUID& item_id = static_cast(current_item->getViewModelItem())->getUUID(); + LLUUID item_id; + if(mSingleFolderMode && isGalleryViewMode()) + { + item_id = mInventoryGalleryPanel->getSelectedItemID(); + if (item_id.isNull()) return; + } + else + { + LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); + if (!current_item) + { + return; + } + item_id = static_cast(current_item->getViewModelItem())->getUUID(); + } + LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance("preview_texture", LLSD(item_id), TAKE_FOCUS_YES); if (preview_texture) { @@ -1646,35 +1666,69 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) } if (command_name == "find_original") { + if(mSingleFolderMode && isGalleryViewMode()) + { + LLInventoryObject *obj = gInventory.getObject(mInventoryGalleryPanel->getSelectedItemID()); + if (obj && obj->getIsLinkType()) + { + show_item_original(obj->getUUID()); + } + } + else + { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) { return; } static_cast(current_item->getViewModelItem())->performAction(getActivePanel()->getModel(), "goto"); + } } if (command_name == "find_links") { - LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); - if (!current_item) - { - return; - } - const LLUUID& item_id = static_cast(current_item->getViewModelItem())->getUUID(); - const std::string &item_name = current_item->getViewModelItem()->getName(); - mFilterSubString = item_name; - - LLInventoryFilter &filter = mActivePanel->getFilter(); - filter.setFindAllLinksMode(item_name, item_id); - - mFilterEditor->setText(item_name); - mFilterEditor->setFocus(TRUE); + if(mSingleFolderMode && isGalleryViewMode()) + { + LLFloaterSidePanelContainer* inventory_container = newWindow(); + if (inventory_container) + { + LLSidepanelInventory* sidepanel_inventory = dynamic_cast(inventory_container->findChild("main_panel", true)); + if (sidepanel_inventory) + { + LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); + if (main_inventory) + { + LLInventoryObject *obj = gInventory.getObject(mInventoryGalleryPanel->getSelectedItemID()); + if (obj) + { + main_inventory->findLinks(obj->getUUID(), obj->getName()); + } + } + } + } + } + else + { + LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); + if (!current_item) + { + return; + } + const LLUUID& item_id = static_cast(current_item->getViewModelItem())->getUUID(); + const std::string &item_name = current_item->getViewModelItem()->getName(); + findLinks(item_id, item_name); + } } if (command_name == "replace_links") { - LLSD params; + LLSD params; + if(mSingleFolderMode && isGalleryViewMode()) + { + params = LLSD(mInventoryGalleryPanel->getSelectedItemID()); + } + else + { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (current_item) { @@ -1689,6 +1743,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) } } } + } LLFloaterReg::showInstance("linkreplace", params); } @@ -1733,6 +1788,19 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) } } + if (command_name == "share") + { + if(mSingleFolderMode && isGalleryViewMode()) + { + std::set uuids{mInventoryGalleryPanel->getSelectedItemID()}; + LLAvatarActions::shareWithAvatars(uuids, gFloaterView->getParentFloater(this)); + } + else + { + LLAvatarActions::shareWithAvatars(this); + } + } + if (command_name == "list_view") { setViewMode(MODE_LIST); @@ -1758,17 +1826,26 @@ void LLPanelMainInventory::onVisibilityChange( BOOL new_visibility ) bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata) { - LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); - if (current_item) - { - LLViewerInventoryItem *inv_item = dynamic_cast(static_cast(current_item->getViewModelItem())->getInventoryObject()); + LLViewerInventoryItem *inv_item = NULL; + if(mSingleFolderMode && isGalleryViewMode()) + { + inv_item = gInventory.getItem(mInventoryGalleryPanel->getSelectedItemID()); + } + else + { + LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); + if (current_item) + { + inv_item = dynamic_cast(static_cast(current_item->getViewModelItem())->getInventoryObject()); + } + } if(inv_item) { bool can_save = inv_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); - LLInventoryType::EType curr_type = static_cast(current_item->getViewModelItem())->getInventoryType(); + LLInventoryType::EType curr_type = inv_item->getInventoryType(); return can_save && (curr_type == LLInventoryType::IT_TEXTURE || curr_type == LLInventoryType::IT_SNAPSHOT); } - } + return false; } @@ -1799,9 +1876,16 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) } if (command_name == "find_original") { + LLUUID item_id; + if(mSingleFolderMode && isGalleryViewMode()) + { + item_id = mInventoryGalleryPanel->getSelectedItemID(); + } + else{ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) return FALSE; - const LLUUID& item_id = static_cast(current_item->getViewModelItem())->getUUID(); + item_id = static_cast(current_item->getViewModelItem())->getUUID(); + } const LLViewerInventoryItem *item = gInventory.getItem(item_id); if (item && item->getIsLinkType() && !item->getIsBrokenLink()) { @@ -1812,12 +1896,19 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) if (command_name == "find_links") { + LLUUID item_id; + if(mSingleFolderMode && isGalleryViewMode()) + { + item_id = mInventoryGalleryPanel->getSelectedItemID(); + } + else{ LLFolderView* root = getActivePanel()->getRootFolder(); std::set selection_set = root->getSelectionList(); if (selection_set.size() != 1) return FALSE; LLFolderViewItem* current_item = root->getCurSelectedItem(); if (!current_item) return FALSE; - const LLUUID& item_id = static_cast(current_item->getViewModelItem())->getUUID(); + item_id = static_cast(current_item->getViewModelItem())->getUUID(); + } const LLInventoryObject *obj = gInventory.getObject(item_id); if (obj && !obj->getIsLinkType() && LLAssetType::lookupCanLink(obj->getType())) { @@ -1841,10 +1932,16 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) if (command_name == "share") { + if(mSingleFolderMode && isGalleryViewMode()) + { + return can_share_item(mInventoryGalleryPanel->getSelectedItemID()); + } + else{ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) return FALSE; LLSidepanelInventory* parent = LLFloaterSidePanelContainer::getPanel("inventory"); return parent ? parent->canShare() : FALSE; + } } if (command_name == "empty_trash") { diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index d41b0a094a..bd51830ebb 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -48,6 +48,7 @@ class LLMenuGL; class LLSidepanelInventory; class LLToggleableMenu; class LLFloater; +class LLFloaterSidePanelContainer; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLPanelMainInventory @@ -101,7 +102,7 @@ public: void setFocusFilterEditor(); - static void newWindow(); + static LLFloaterSidePanelContainer* newWindow(); static void newFolderWindow(LLUUID folder_id = LLUUID(), LLUUID item_to_select = LLUUID()); void toggleFindOptions(); @@ -109,6 +110,8 @@ public: void resetFilters(); void resetAllItemsFilters(); + void findLinks(const LLUUID& item_id, const std::string& item_name); + void onViewModeClick(); void toggleViewMode(); void onUpFolderClicked(); diff --git a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml index 5032505487..2c630880c2 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml @@ -69,7 +69,8 @@ name="Share" visible="true"> + function="Inventory.GearDefault.Custom.Action" + parameter="share" /> -- cgit v1.3 From 126bfa4877303b47abbc99f09c09a931c20cbd3b Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 31 Mar 2023 15:23:11 +0300 Subject: SL-19379 WIP fix for displaying folder link items, added correct action for 'paste as link' --- indra/newview/llinventorygallery.cpp | 36 +++++++++++++++++++------------- indra/newview/llinventorygallerymenu.cpp | 30 ++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 17 deletions(-) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 8c49cd5a4b..499d51c431 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -222,6 +222,9 @@ void LLInventoryGallery::updateRootFolder() } } + const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + mCategoriesObserver->addCategory(cof, boost::bind(&LLInventoryGallery::onCOFChanged, this)); + if (!mGalleryCreated) { initGallery(); @@ -243,9 +246,6 @@ void LLInventoryGallery::initGallery() } reArrangeRows(); mGalleryCreated = true; - - const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - mCategoriesObserver->addCategory(cof, boost::bind(&LLInventoryGallery::onCOFChanged, this)); } } @@ -646,7 +646,14 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) LLInventoryType::EType inventory_type(LLInventoryType::IT_CATEGORY); U32 misc_flags = 0; bool is_worn = false; - if (LLAssetType::AT_CATEGORY == obj->getType()) + LLInventoryItem* inv_item = gInventory.getItem(item_id); + if (inv_item) + { + inventory_type = inv_item->getInventoryType(); + misc_flags = inv_item->getFlags(); + is_worn = LLAppearanceMgr::instance().isLinkedInCOF(item_id); + } + else if (LLAssetType::AT_CATEGORY == obj->getType()) { name = get_localized_folder_name(item_id); if(thumbnail_id.isNull()) @@ -654,16 +661,6 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) thumbnail_id = getOutfitImageID(item_id); } } - else - { - LLInventoryItem* inv_item = gInventory.getItem(item_id); - if (inv_item) - { - inventory_type = inv_item->getInventoryType(); - misc_flags = inv_item->getFlags(); - is_worn = LLAppearanceMgr::instance().isLinkedInCOF(item_id); - } - } LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getIsLinkType(), is_worn); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); @@ -1049,7 +1046,16 @@ void LLInventoryGalleryItem::setType(LLAssetType::EType type, LLInventoryType::E if(mIsFolder) { mSortGroup = SG_NORMAL_FOLDER; - LLViewerInventoryCategory * cat = gInventory.getCategory(mUUID); + LLUUID folder_id = mUUID; + if(mIsLink) + { + LLInventoryObject* obj = gInventory.getObject(mUUID); + if (obj) + { + folder_id = obj->getLinkedUUID(); + } + } + LLViewerInventoryCategory* cat = gInventory.getCategory(folder_id); if (cat) { LLFolderType::EType preferred_type = cat->getPreferredType(); diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 21f7b06534..e91ec78730 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -250,9 +250,35 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } } } - else if ("paste_as_link" == action) + else if ("paste_link" == action) { - link_inventory_object(selected_id, obj, LLPointer(NULL)); + const LLUUID ¤t_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID &my_outifts_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + + const BOOL move_is_into_current_outfit = (selected_id == current_outfit_id); + const BOOL move_is_into_my_outfits = (selected_id == my_outifts_id) || gInventory.isObjectDescendentOf(selected_id, my_outifts_id); + const BOOL move_is_into_marketplacelistings = gInventory.isObjectDescendentOf(selected_id, marketplacelistings_id); + + if (move_is_into_marketplacelistings || move_is_into_current_outfit || move_is_into_my_outfits) + { + return; + } + + std::vector objects; + LLClipboard::instance().pasteFromClipboard(objects); + for (std::vector::const_iterator iter = objects.begin(); + iter != objects.end(); + ++iter) + { + const LLUUID &object_id = (*iter); + if (LLConstPointer link_obj = gInventory.getObject(object_id)) + { + link_inventory_object(selected_id, link_obj, LLPointer(NULL)); + } + } + + LLClipboard::instance().setCutMode(false); } else if ("rename" == action) { -- cgit v1.3 From 107a7eb919bb0afadf6ad3f92482cf7e6d67c56e Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 13 Apr 2023 17:49:26 +0300 Subject: SL-19544 WIP add active suffix for gestures and add appropriate context menu handling --- indra/newview/llinventorygallery.cpp | 54 +++++++++++++++++++++- indra/newview/llinventorygallery.h | 17 +++++++ indra/newview/llinventorygallerymenu.cpp | 33 +++++++++++++ .../xui/en/panel_inventory_gallery_item.xml | 1 + 4 files changed, 103 insertions(+), 2 deletions(-) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 9766a39e3c..9344668f52 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -92,6 +92,9 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mThumbnailsObserver = new LLThumbnailsObserver(); gInventory.addObserver(mThumbnailsObserver); + mGestureObserver = new LLGalleryGestureObserver(this); + LLGestureMgr::instance().addObserver(mGestureObserver); + mUsername = gAgentUsername; LLStringUtil::toUpper(mUsername); } @@ -154,6 +157,9 @@ LLInventoryGallery::~LLInventoryGallery() gInventory.removeObserver(mThumbnailsObserver); } delete mThumbnailsObserver; + + LLGestureMgr::instance().removeObserver(mGestureObserver); + delete mGestureObserver; } void LLInventoryGallery::setRootFolder(const LLUUID cat_id) @@ -701,7 +707,14 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) { inventory_type = inv_item->getInventoryType(); misc_flags = inv_item->getFlags(); - is_worn = LLAppearanceMgr::instance().isLinkedInCOF(item_id); + if (LLAssetType::AT_GESTURE == obj->getType()) + { + is_worn = LLGestureMgr::instance().isGestureActive(item_id); + } + else + { + is_worn = LLAppearanceMgr::instance().isLinkedInCOF(item_id); + } } else if (LLAssetType::AT_CATEGORY == obj->getType()) { @@ -943,6 +956,37 @@ void LLInventoryGallery::onCOFChanged() } } +void LLInventoryGallery::onGesturesChanged() +{ + uuid_vec_t vnew; + uuid_vec_t vadded; + uuid_vec_t vremoved; + + const LLGestureMgr::item_map_t& active_gestures = LLGestureMgr::instance().getActiveGestures(); + for (LLGestureMgr::item_map_t::const_iterator iter = active_gestures.begin(); + iter != active_gestures.end(); + ++iter) + { + vnew.push_back(iter->first); + } + + LLCommonUtils::computeDifference(vnew, mActiveGestures, vadded, vremoved); + + mActiveGestures = vnew; + + for (uuid_vec_t::const_iterator iter = vadded.begin(); + iter != vadded.end(); + ++iter) + { + updateWornItem(*iter, true); + } + + for (uuid_vec_t::const_iterator iter = vremoved.begin(); iter != vremoved.end(); ++iter) + { + updateWornItem(*iter, false); + } +} + void LLInventoryGallery::deselectItem(const LLUUID& category_id) { // Reset selection if the item is selected. @@ -1353,7 +1397,13 @@ BOOL LLInventoryGalleryItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL dro void LLInventoryGalleryItem::setWorn(bool value) { mWorn = value; - mSuffixText->setValue(mWorn ? getString("worn_string") : ""); + std::string suffix(""); + + if(mWorn) + { + suffix = (mType == LLAssetType::AT_GESTURE) ? getString("active_string") : getString("worn_string"); + } + mSuffixText->setValue(suffix); mNameText->setFont(getTextFont()); mNameText->setText(mName); // refresh to pick up font changes diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index 6bca8a0dc5..f0f4c45e04 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -27,6 +27,7 @@ #ifndef LL_LLINVENTORYGALLERY_H #define LL_LLINVENTORYGALLERY_H +#include "llgesturemgr.h" #include "lllistcontextmenu.h" #include "llpanel.h" #include "llinventoryfilter.h" @@ -38,6 +39,7 @@ class LLInventoryGalleryItem; class LLScrollContainer; class LLTextBox; class LLThumbnailsObserver; +class LLGalleryGestureObserver; class LLInventoryGalleryContextMenu; @@ -110,6 +112,7 @@ public: void refreshList(const LLUUID& category_id); void onCOFChanged(); + void onGesturesChanged(); void computeDifference(const LLInventoryModel::cat_array_t vcats, const LLInventoryModel::item_array_t vitems, uuid_vec_t& vadded, uuid_vec_t& vremoved); void deselectItem(const LLUUID& category_id); @@ -133,6 +136,7 @@ protected: LLInventoryCategoriesObserver* mCategoriesObserver; LLThumbnailsObserver* mThumbnailsObserver; + LLGalleryGestureObserver* mGestureObserver; LLUUID mSelectedItemID; bool mIsInitialized; @@ -199,6 +203,7 @@ private: typedef std::map gallery_item_map_t; gallery_item_map_t mItemMap; uuid_vec_t mCOFLinkedItems; + uuid_vec_t mActiveGestures; std::map mItemIndexMap; LLInventoryFilter::ESearchType mSearchType; @@ -257,6 +262,7 @@ public: void setHidden(bool hidden) {mHidden = hidden;} void setType(LLAssetType::EType type, LLInventoryType::EType inventory_type, U32 flags, bool is_link); + LLAssetType::EType getAssetType() { return mType; } void setThumbnail(LLUUID id); void setGallery(LLInventoryGallery* gallery) { mGallery = gallery; } bool isFolder() { return mIsFolder; } @@ -314,4 +320,15 @@ protected: item_map_t mItemMap; }; +class LLGalleryGestureObserver : public LLGestureManagerObserver +{ +public: + LLGalleryGestureObserver(LLInventoryGallery* gallery) : mGallery(gallery) {} + virtual ~LLGalleryGestureObserver() {} + virtual void changed() { mGallery->onGesturesChanged(); } + +private: + LLInventoryGallery* mGallery; +}; + #endif diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index e91ec78730..84b18c1517 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -314,6 +314,26 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU { LLAppearanceMgr::instance().wearItemOnAvatar(selected_id, true, true); } + else if ("activate" == action) + { + LLGestureMgr::instance().activateGesture(selected_id); + + LLViewerInventoryItem* item = gInventory.getItem(selected_id); + if (!item) return; + + gInventory.updateItem(item); + gInventory.notifyObservers(); + } + else if ("deactivate" == action) + { + LLGestureMgr::instance().deactivateGesture(selected_id); + + LLViewerInventoryItem* item = gInventory.getItem(selected_id); + if (!item) return; + + gInventory.updateItem(item); + gInventory.notifyObservers(); + } } void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLSD& response) @@ -590,6 +610,19 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men disabled_items.push_back(std::string("Open")); disabled_items.push_back(std::string("Open Original")); } + + if(LLAssetType::AT_GESTURE == obj->getType()) + { + items.push_back(std::string("Gesture Separator")); + if(!LLGestureMgr::instance().isGestureActive(selected_id)) + { + items.push_back(std::string("Activate")); + } + else + { + items.push_back(std::string("Deactivate")); + } + } } else if(LLAssetType::AT_LANDMARK == obj->getType()) { diff --git a/indra/newview/skins/default/xui/en/panel_inventory_gallery_item.xml b/indra/newview/skins/default/xui/en/panel_inventory_gallery_item.xml index b343aafca5..e7589f889f 100644 --- a/indra/newview/skins/default/xui/en/panel_inventory_gallery_item.xml +++ b/indra/newview/skins/default/xui/en/panel_inventory_gallery_item.xml @@ -14,6 +14,7 @@ left="0" top="0"> (worn) + (active) Date: Fri, 21 Apr 2023 18:31:56 +0300 Subject: SL-19379 update for gallery context menu --- indra/newview/llinventorygallerymenu.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 84b18c1517..43ddf4da63 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -334,6 +334,10 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU gInventory.updateItem(item); gInventory.notifyObservers(); } + else if ("replace_links" == action) + { + LLFloaterReg::showInstance("linkreplace", LLSD(selected_id)); + } } void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLSD& response) @@ -451,8 +455,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men if(!is_link) { items.push_back(std::string("thumbnail")); - LLViewerInventoryItem* inv_item = gInventory.getItem(selected_id); - if (inv_item && !inv_item->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID())) + if (!is_agent_inventory) { disabled_items.push_back(std::string("thumbnail")); } @@ -466,6 +469,13 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men items.push_back(std::string("open_in_new_window")); items.push_back(std::string("Open Folder Separator")); } + else + { + if (is_agent_inventory && (obj->getType() != LLAssetType::AT_LINK_FOLDER)) + { + items.push_back(std::string("Replace Links")); + } + } if(is_trash) { @@ -490,7 +500,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men } } items.push_back(std::string("Purge Item")); - if (!get_is_category_removable(&gInventory, selected_id)) + if (is_folder && !get_is_category_removable(&gInventory, selected_id)) { disabled_items.push_back(std::string("Purge Item")); } -- cgit v1.3 From 67e17bd822f146f333b91d353df6f55174ce4db6 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 26 May 2023 19:45:46 +0300 Subject: SL-19774 add context menu for root folder (without any selection); show paste menu when right clicking any item --- indra/newview/llinventorygallery.cpp | 24 ++++++++++++++ indra/newview/llinventorygallery.h | 2 ++ indra/newview/llinventorygallerymenu.cpp | 54 ++++++++++++++++++-------------- indra/newview/llinventorygallerymenu.h | 7 ++++- 4 files changed, 63 insertions(+), 24 deletions(-) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 18a7068b66..c6fee42297 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -126,12 +126,15 @@ BOOL LLInventoryGallery::postBuild() mGalleryPanel = LLUICtrlFactory::create(params); mMessageTextBox = getChild("empty_txt"); mInventoryGalleryMenu = new LLInventoryGalleryContextMenu(this); + mRootGalleryMenu = new LLInventoryGalleryContextMenu(this); + mRootGalleryMenu->setRootFolder(true); return TRUE; } LLInventoryGallery::~LLInventoryGallery() { delete mInventoryGalleryMenu; + delete mRootGalleryMenu; delete mFilter; while (!mUnusedRowPanels.empty()) @@ -837,6 +840,27 @@ void LLInventoryGallery::onThumbnailAdded(LLUUID item_id) } } +BOOL LLInventoryGallery::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + if(mItemMap[mSelectedItemID]) + { + mItemMap[mSelectedItemID]->setFocus(false); + } + clearSelection(); + BOOL res = LLPanel::handleRightMouseDown(x, y, mask); + if (mSelectedItemID.isNull()) + { + if (mInventoryGalleryMenu && mFolderID.notNull()) + { + uuid_vec_t selected_uuids; + selected_uuids.push_back(mFolderID); + mRootGalleryMenu->show(this, selected_uuids, x, y); + return TRUE; + } + } + return res; +} + void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id) { if (mInventoryGalleryMenu && item_id.notNull()) diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index 473d1a1db4..7e4ed9725b 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -78,6 +78,7 @@ public: void draw(); BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); + BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); void setFilterSubString(const std::string& string); std::string getFilterSubString() { return mFilterSubString; } @@ -204,6 +205,7 @@ private: int mGalleryWidthFactor; LLInventoryGalleryContextMenu* mInventoryGalleryMenu; + LLInventoryGalleryContextMenu* mRootGalleryMenu; std::string mFilterSubString; LLInventoryFilter* mFilter; diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 43ddf4da63..8a99b79e2b 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -159,6 +159,8 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU bool is_cut_mode = (LLClipboard::instance().isCutMode()); { + LLUUID dest = is_folder ? selected_id : obj->getParentUUID(); + std::vector objects; LLClipboard::instance().pasteFromClipboard(objects); for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) @@ -174,11 +176,11 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU { if(is_cut_mode) { - gInventory.changeCategoryParent(cat, selected_id, false); + gInventory.changeCategoryParent(cat, dest, false); } else { - copy_inventory_category(&gInventory, cat, selected_id); + copy_inventory_category(&gInventory, cat, dest); } } else @@ -188,13 +190,13 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU { if(is_cut_mode) { - gInventory.changeItemParent(item, selected_id, false); + gInventory.changeItemParent(item, dest, false); } else { if (item->getIsLinkType()) { - link_inventory_object(selected_id, item_id, + link_inventory_object(dest, item_id, LLPointer(NULL)); } else @@ -203,7 +205,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU gAgent.getID(), item->getPermissions().getOwner(), item->getUUID(), - selected_id, + dest, std::string(), LLPointer(NULL)); } @@ -264,7 +266,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU { return; } - + LLUUID dest = is_folder ? selected_id : obj->getParentUUID(); std::vector objects; LLClipboard::instance().pasteFromClipboard(objects); for (std::vector::const_iterator iter = objects.begin(); @@ -274,7 +276,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU const LLUUID &object_id = (*iter); if (LLConstPointer link_obj = gInventory.getObject(object_id)) { - link_inventory_object(selected_id, link_obj, LLPointer(NULL)); + link_inventory_object(dest, link_obj, LLPointer(NULL)); } } @@ -463,11 +465,14 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men if (is_folder) { - items.push_back(std::string("Copy Separator")); + if(!isRootFolder()) + { + items.push_back(std::string("Copy Separator")); - items.push_back(std::string("open_in_current_window")); - items.push_back(std::string("open_in_new_window")); - items.push_back(std::string("Open Folder Separator")); + items.push_back(std::string("open_in_current_window")); + items.push_back(std::string("open_in_new_window")); + items.push_back(std::string("Open Folder Separator")); + } } else { @@ -512,18 +517,28 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men { items.push_back(std::string("Share")); } + if (LLClipboard::instance().hasContents() && is_agent_inventory && !is_cof && !is_inbox_folder(selected_id)) + { + items.push_back(std::string("Paste")); + + static LLCachedControl inventory_linking(gSavedSettings, "InventoryLinking", true); + if (inventory_linking) + { + items.push_back(std::string("Paste As Link")); + } + } if (is_folder && is_agent_inventory) { if (!is_cof && (folder_type != LLFolderType::FT_OUTFIT) && !is_outfits && !is_inbox_folder(selected_id)) { - if (!gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD))) + if (!gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD)) && !isRootFolder()) { items.push_back(std::string("New Folder")); } items.push_back(std::string("upload_def")); } - if(is_outfits) + if(is_outfits && !isRootFolder()) { items.push_back(std::string("New Outfit")); } @@ -531,6 +546,8 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men items.push_back(std::string("Subfolder Separator")); if (!is_system_folder) { + if(!isRootFolder()) + { if(has_children && (folder_type != LLFolderType::FT_OUTFIT)) { items.push_back(std::string("Ungroup folder items")); @@ -542,21 +559,12 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men disabled_items.push_back(std::string("Delete")); disabled_items.push_back(std::string("Cut")); } + } if(!is_inbox) { items.push_back(std::string("Rename")); } } - if (LLClipboard::instance().hasContents() && is_agent_inventory && !is_cof && !is_inbox_folder(selected_id)) - { - items.push_back(std::string("Paste")); - - static LLCachedControl inventory_linking(gSavedSettings, "InventoryLinking", true); - if (inventory_linking) - { - items.push_back(std::string("Paste As Link")); - } - } if(!is_system_folder) { items.push_back(std::string("Copy")); diff --git a/indra/newview/llinventorygallerymenu.h b/indra/newview/llinventorygallerymenu.h index 1768c07e6e..fd542e7d79 100644 --- a/indra/newview/llinventorygallerymenu.h +++ b/indra/newview/llinventorygallerymenu.h @@ -33,9 +33,13 @@ class LLInventoryGalleryContextMenu : public LLListContextMenu public: LLInventoryGalleryContextMenu(LLInventoryGallery* gallery) : LLListContextMenu(), - mGallery(gallery){} + mGallery(gallery), + mRootFolder(false){} /*virtual*/ LLContextMenu* createMenu(); + bool isRootFolder() { return mRootFolder; } + void setRootFolder(bool is_root) { mRootFolder = is_root; } + protected: //virtual void buildContextMenu(class LLMenuGL& menu, U32 flags); void updateMenuItemsVisibility(LLContextMenu* menu); @@ -50,6 +54,7 @@ private: bool checkContextMenuItem(const LLSD& userdata); LLInventoryGallery* mGallery; + bool mRootFolder; }; #endif -- cgit v1.3 From 5c55adae47cab93a12793528373f639ea9e8efcf Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Tue, 30 May 2023 13:10:36 +0300 Subject: SL-19773 add context menu for root folder in single folder mode --- indra/llui/llfolderview.cpp | 12 +++++++++--- indra/llui/llfolderview.h | 6 +++++- indra/newview/llinventorybridge.cpp | 20 ++++++++++++++++---- indra/newview/llinventoryfunctions.cpp | 8 ++++++++ indra/newview/llinventorygallerymenu.cpp | 6 ++---- indra/newview/llinventorypanel.cpp | 17 ++++++++++++++++- indra/newview/llinventorypanel.h | 1 + 7 files changed, 57 insertions(+), 13 deletions(-) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 798c00d0ca..f0106e345c 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -190,7 +190,8 @@ LLFolderView::LLFolderView(const Params& p) mShowItemLinkOverlays(p.show_item_link_overlays), mViewModel(p.view_model), mGroupedItemModel(p.grouped_item_model), - mForceArrange(false) + mForceArrange(false), + mSingleFolderMode(false) { LLPanel* panel = p.parent_panel; mParentPanel = panel->getHandle(); @@ -1475,8 +1476,8 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) } } bool hide_folder_menu = mSuppressFolderMenu && isFolderSelected(); - if (menu && (handled - && ( count > 0 && (hasVisibleChildren()) )) && // show menu only if selected items are visible + if (menu && (mSingleFolderMode || (handled + && ( count > 0 && (hasVisibleChildren()) ))) && // show menu only if selected items are visible !hide_folder_menu) { if (mCallbackRegistrar) @@ -1918,6 +1919,11 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) flags = multi_select_flag; } + if(mSingleFolderMode && (mSelectedItems.size() == 0)) + { + buildContextMenu(*menu, flags); + } + // This adds a check for restrictions based on the entire // selection set - for example, any one wearable may not push you // over the limit, but all wearables together still might. diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 73028f31b1..ed84b29fd9 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -127,6 +127,9 @@ public: bool getAllowMultiSelect() { return mAllowMultiSelect; } bool getAllowDrag() { return mAllowDrag; } + void setSingleFolderMode(bool is_single_mode) { mSingleFolderMode = is_single_mode; } + bool isSingleFolderMode() { return mSingleFolderMode; } + // Close all folders in the view void closeAllFolders(); void openTopLevelFolders(); @@ -300,7 +303,8 @@ protected: mShowItemLinkOverlays, mShowSelectionContext, mShowSingleSelection, - mSuppressFolderMenu; + mSuppressFolderMenu, + mSingleFolderMode; // Renaming variables and methods LLFolderViewItem* mRenameItem; // The item currently being renamed diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 1c8342cdda..3c1e58205a 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -791,6 +791,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, menuentry_vec_t &disabled_items, U32 flags) { const LLInventoryObject *obj = getInventoryObject(); + bool single_folder_root = (mRoot == NULL); if (obj) { @@ -802,7 +803,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, disabled_items.push_back(std::string("Copy")); } - if (isAgentInventory()) + if (isAgentInventory() && !single_folder_root) { items.push_back(std::string("New folder from selected")); items.push_back(std::string("Subfolder Separator")); @@ -836,7 +837,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, items.push_back(std::string("Find Links")); } - if (!isInboxFolder()) + if (!isInboxFolder() && !single_folder_root) { items.push_back(std::string("Rename")); if (!isItemRenameable() || ((flags & FIRST_SELECTED_ITEM) == 0)) @@ -870,6 +871,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } } + if(!single_folder_root) + { items.push_back(std::string("Cut")); if (!isItemMovable() || !isItemRemovable()) { @@ -891,6 +894,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } } } + } } } @@ -916,7 +920,10 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, items.push_back(std::string("Paste Separator")); - addDeleteContextMenuOptions(items, disabled_items); + if(!single_folder_root) + { + addDeleteContextMenuOptions(items, disabled_items); + } if (!isPanelActive("All Items") && !isPanelActive("single_folder_inv") && !isPanelActive("comb_single_folder_inv")) { @@ -4382,7 +4389,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& const bool is_agent_inventory = isAgentInventory(); // Only enable calling-card related options for non-system folders. - if (!is_system_folder && is_agent_inventory) + if (!is_system_folder && is_agent_inventory && (mRoot != NULL)) { LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) @@ -4402,6 +4409,11 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& disabled_items.push_back(std::string("New folder from selected")); } + //skip the rest options in single-folder mode + if (mRoot == NULL) + { + return; + } if ((flags & ITEM_IN_MULTI_SELECTION) == 0) { diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index b934ccd22b..a259dad08a 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -3194,6 +3194,14 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root if(!bridge) continue; bridge->performAction(model, action); } + if(root->isSingleFolderMode() && selected_items.empty()) + { + LLInvFVBridge* bridge = (LLInvFVBridge*)root->getViewModelItem(); + if(bridge) + { + bridge->performAction(model, action); + } + } } // Update the marketplace listings that have been affected by the operation diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 8a99b79e2b..6dc749fab6 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -544,10 +544,8 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men } items.push_back(std::string("Subfolder Separator")); - if (!is_system_folder) + if (!is_system_folder && !isRootFolder()) { - if(!isRootFolder()) - { if(has_children && (folder_type != LLFolderType::FT_OUTFIT)) { items.push_back(std::string("Ungroup folder items")); @@ -559,7 +557,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men disabled_items.push_back(std::string("Delete")); disabled_items.push_back(std::string("Cut")); } - } + if(!is_inbox) { items.push_back(std::string("Rename")); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 2226384ba2..bd15e55b9a 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -2116,6 +2116,7 @@ LLInventorySingleFolderPanel::LLInventorySingleFolderPanel(const Params& params) mCommitCallbackRegistrar.add("Inventory.OpenSelectedFolder", boost::bind(&LLInventorySingleFolderPanel::openInCurrentWindow, this, _2)); mCommitCallbackRegistrar.replace("Inventory.DoCreate", boost::bind(&LLInventorySingleFolderPanel::doCreate, this, _2)); + mCommitCallbackRegistrar.replace("Inventory.Share", boost::bind(&LLInventorySingleFolderPanel::doShare, this)); } LLInventorySingleFolderPanel::~LLInventorySingleFolderPanel() @@ -2138,6 +2139,7 @@ void LLInventorySingleFolderPanel::initFromParams(const Params& p) pane_params.open_first_folder = false; pane_params.start_folder.id = mFolderID; LLInventoryPanel::initFromParams(pane_params); + mFolderRoot.get()->setSingleFolderMode(true); } void LLInventorySingleFolderPanel::openInCurrentWindow(const LLSD& userdata) @@ -2219,7 +2221,7 @@ void LLInventorySingleFolderPanel::updateSingleFolderRoot() LLFolderView* folder_view = createFolderRoot(root_id); folder_view->setChildrenInited(false); mFolderRoot = folder_view->getHandle(); - + mFolderRoot.get()->setSingleFolderMode(true); addItemID(root_id, mFolderRoot.get()); LLRect scroller_view_rect = getRect(); @@ -2285,6 +2287,19 @@ void LLInventorySingleFolderPanel::doCreate(const LLSD& userdata) reset_inventory_filter(); menu_create_inventory_item(this, dest_id, userdata); } + +void LLInventorySingleFolderPanel::doShare() +{ + if(mFolderRoot.get()->getCurSelectedItem() == NULL) + { + std::set uuids{mFolderID}; + LLAvatarActions::shareWithAvatars(uuids, gFloaterView->getParentFloater(this)); + } + else + { + LLAvatarActions::shareWithAvatars(this); + } +} /************************************************************************/ /* Asset Pre-Filtered Inventory Panel related class */ /************************************************************************/ diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 7b54a5bbf2..2754d79fbe 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -409,6 +409,7 @@ public: LLUUID getSingleFolderRoot() { return mFolderID; } void doCreate(const LLSD& userdata); + void doShare(); bool isBackwardAvailable(); bool isForwardAvailable(); -- cgit v1.3 From 29f52ad1a7c4f0d023c4b6a7dd0d43ea105e8fdb Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 8 Jun 2023 12:44:35 +0300 Subject: SL-19845 Show confirmation before deleting an item in Gallery view --- indra/newview/llinventorygallerymenu.cpp | 45 ++++++++++++++++++++++---------- indra/newview/llinventorygallerymenu.h | 1 + 2 files changed, 32 insertions(+), 14 deletions(-) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 6dc749fab6..e7f8b10cca 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -39,6 +39,7 @@ #include "llmarketplacefunctions.h" #include "llmenugl.h" #include "llnotificationsutil.h" +#include "lltrans.h" #include "llviewerfoldertype.h" #include "llviewerwindow.h" #include "llvoavatarself.h" @@ -220,20 +221,9 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } else if ("delete" == action) { - if (is_folder) - { - if(get_is_category_removable(&gInventory, selected_id)) - { - gInventory.removeCategory(selected_id); - } - } - else - { - if(get_is_item_removable(&gInventory, selected_id)) - { - gInventory.removeItem(selected_id); - } - } + LLSD args; + args["QUESTION"] = LLTrans::getString("DeleteItem"); + LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGalleryContextMenu::onDelete, _1, _2, selected_id)); } else if ("copy" == action) { @@ -342,6 +332,33 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } } +void LLInventoryGalleryContextMenu::onDelete(const LLSD& notification, const LLSD& response, const LLUUID& selected_id) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + LLInventoryObject* obj = gInventory.getObject(selected_id); + if (!obj) + { + return; + } + if (obj->getType() == LLAssetType::AT_CATEGORY) + { + if(get_is_category_removable(&gInventory, selected_id)) + { + gInventory.removeCategory(selected_id); + } + } + else + { + if(get_is_item_removable(&gInventory, selected_id)) + { + gInventory.removeItem(selected_id); + } + } + } +} + void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); diff --git a/indra/newview/llinventorygallerymenu.h b/indra/newview/llinventorygallerymenu.h index 67cf9a569a..1c56266310 100644 --- a/indra/newview/llinventorygallerymenu.h +++ b/indra/newview/llinventorygallerymenu.h @@ -47,6 +47,7 @@ protected: void fileUploadLocation(const LLSD& userdata, const LLUUID& selected_id); + static void onDelete(const LLSD& notification, const LLSD& response, const LLUUID& selected_id); static void onRename(const LLSD& notification, const LLSD& response); private: -- cgit v1.3 From 53fc42fe032c2aef453f420645b0e46dea4c23db Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 8 Jun 2023 22:50:12 +0300 Subject: SL-19832 Inventory gallery should support CTRL+X, C and V --- indra/newview/llinventorygallery.cpp | 235 ++++++++++++++++++++++++++++++- indra/newview/llinventorygallery.h | 15 +- indra/newview/llinventorygallerymenu.cpp | 32 +---- 3 files changed, 254 insertions(+), 28 deletions(-) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 63a706a9d6..eff43e33ca 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -29,6 +29,7 @@ #include "llinventorygallery.h" #include "llinventorygallerymenu.h" +#include "llclipboard.h" #include "llcommonutils.h" #include "lliconctrl.h" #include "llinventorybridge.h" @@ -133,6 +134,11 @@ BOOL LLInventoryGallery::postBuild() LLInventoryGallery::~LLInventoryGallery() { + if (gEditMenuHandler == this) + { + gEditMenuHandler = NULL; + } + delete mInventoryGalleryMenu; delete mRootGalleryMenu; delete mFilter; @@ -1009,6 +1015,7 @@ void LLInventoryGallery::moveUp() LLUUID item_id = item->getUUID(); changeItemSelection(item_id, true); item->setFocus(TRUE); + claimEditHandler(); } } } @@ -1031,6 +1038,7 @@ void LLInventoryGallery::moveDown() LLUUID item_id = item->getUUID(); changeItemSelection(item_id, true); item->setFocus(TRUE); + claimEditHandler(); } } } @@ -1056,6 +1064,7 @@ void LLInventoryGallery::moveLeft() LLUUID item_id = item->getUUID(); changeItemSelection(item_id, true); item->setFocus(TRUE); + claimEditHandler(); } } } @@ -1079,6 +1088,7 @@ void LLInventoryGallery::moveRight() LLUUID item_id = item->getUUID(); changeItemSelection(item_id, true); item->setFocus(TRUE); + claimEditHandler(); } } } @@ -1154,6 +1164,227 @@ LLInventoryGalleryItem* LLInventoryGallery::getSelectedItem() return mItemMap[mSelectedItemID]; } +void LLInventoryGallery::copy() +{ + LLClipboard::instance().reset(); + if (getVisible() && getEnabled() && mSelectedItemID.notNull()) + { + LLClipboard::instance().addToClipboard(mSelectedItemID); + } + mFilterSubString.clear(); +} + +BOOL LLInventoryGallery::canCopy() const +{ + if (!getVisible() || !getEnabled() || mSelectedItemID.isNull()) + { + return FALSE; + } + + if (!isItemCopyable(mSelectedItemID)) + { + return FALSE; + } + + return TRUE; +} + +void LLInventoryGallery::cut() +{ + // clear the inventory clipboard + LLClipboard::instance().reset(); + if (getVisible() && getEnabled() && mSelectedItemID.notNull()) + { + // todo: fade out selected item + LLClipboard::instance().setCutMode(true); + LLClipboard::instance().addToClipboard(mSelectedItemID); + } + mFilterSubString.clear(); +} + +BOOL LLInventoryGallery::canCut() const +{ + if (!getVisible() || !getEnabled() || mSelectedItemID.isNull()) + { + return FALSE; + } + + LLViewerInventoryCategory* cat = gInventory.getCategory(mSelectedItemID); + if (cat) + { + if (!get_is_category_removable(&gInventory, mSelectedItemID)) + { + return FALSE; + } + } + else if (!get_is_item_removable(&gInventory, mSelectedItemID)) + { + return FALSE; + } + + return TRUE; +} + +void LLInventoryGallery::paste() +{ + const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + if (gInventory.isObjectDescendentOf(mSelectedItemID, marketplacelistings_id)) + { + return; + } + + LLInventoryObject* obj = gInventory.getObject(mSelectedItemID); + bool is_folder = obj && (obj->getType() == LLAssetType::AT_CATEGORY); + LLUUID dest = is_folder ? mSelectedItemID : mFolderID; + bool is_cut_mode = LLClipboard::instance().isCutMode(); + + std::vector objects; + LLClipboard::instance().pasteFromClipboard(objects); + for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) + { + const LLUUID& item_id = (*iter); + if (gInventory.isObjectDescendentOf(item_id, marketplacelistings_id) && (LLMarketplaceData::instance().isInActiveFolder(item_id) || + LLMarketplaceData::instance().isListedAndActive(item_id))) + { + return; + } + LLViewerInventoryCategory* cat = gInventory.getCategory(item_id); + if (cat) + { + if (is_cut_mode) + { + gInventory.changeCategoryParent(cat, dest, false); + } + else + { + copy_inventory_category(&gInventory, cat, dest); + } + } + else + { + LLViewerInventoryItem* item = gInventory.getItem(item_id); + if (item) + { + if (is_cut_mode) + { + gInventory.changeItemParent(item, dest, false); + } + else + { + if (item->getIsLinkType()) + { + link_inventory_object(dest, item_id, + LLPointer(NULL)); + } + else + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + dest, + std::string(), + LLPointer(NULL)); + } + } + } + } + } + // todo: scroll to item on arrival + LLClipboard::instance().setCutMode(false); +} + +BOOL LLInventoryGallery::canPaste() const +{ + // Return FALSE on degenerated cases: empty clipboard, no inventory, no agent + if (!LLClipboard::instance().hasContents()) + { + return FALSE; + } + + // In cut mode, whatever is on the clipboard is always pastable + if (LLClipboard::instance().isCutMode()) + { + return TRUE; + } + + // In normal mode, we need to check each element of the clipboard to know if we can paste or not + std::vector objects; + LLClipboard::instance().pasteFromClipboard(objects); + S32 count = objects.size(); + for (S32 i = 0; i < count; i++) + { + const LLUUID& item_id = objects.at(i); + + // Each item must be copyable to be pastable + if (!isItemCopyable(item_id)) + { + return FALSE; + } + } + return TRUE; +} + +void LLInventoryGallery::claimEditHandler() +{ + gEditMenuHandler = this; +} + +bool LLInventoryGallery::isItemCopyable(const LLUUID & item_id) +{ + const LLInventoryCategory* cat = gInventory.getCategory(item_id); + if (cat) + { + // Folders are copyable if items in them are, recursively, copyable. + // Get the content of the folder + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(item_id, cat_array, item_array); + + // Check the items + LLInventoryModel::item_array_t item_array_copy = *item_array; + for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) + { + LLInventoryItem* item = *iter; + if (!isItemCopyable(item->getUUID())) + { + return false; + } + } + + // Check the folders + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLViewerInventoryCategory* category = *iter; + if (!isItemCopyable(category->getUUID())) + { + return false; + } + } + + return true; + } + + LLViewerInventoryItem* item = gInventory.getItem(item_id); + if (item) + { + // Can't copy worn objects. + // Worn objects are tied to their inworld conterparts + // Copy of modified worn object will return object with obsolete asset and inventory + if (get_is_item_worn(item_id)) + { + return false; + } + + static LLCachedControl inventory_linking(gSavedSettings, "InventoryLinking", true); + return (item->getIsLinkType() && inventory_linking) + || item->getPermissions().allowCopyBy(gAgent.getID()); + } + + return false; +} + void LLInventoryGallery::updateMessageVisibility() { @@ -1666,6 +1897,7 @@ void LLInventoryGalleryItem::setSelected(bool value) BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) { setFocus(TRUE); + mGallery->claimEditHandler(); gFocusMgr.setMouseCapture(this); S32 screen_x; @@ -1678,6 +1910,8 @@ BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLInventoryGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) { setFocus(TRUE); + mGallery->claimEditHandler(); + return LLUICtrl::handleRightMouseDown(x, y, mask); } @@ -1763,7 +1997,6 @@ BOOL LLInventoryGalleryItem::handleKeyHere(KEY key, MASK mask) BOOL handled = FALSE; switch (key) { - case KEY_LEFT: mGallery->moveLeft(); handled = true; diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index e2d9786296..ac4811adec 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -45,7 +45,7 @@ class LLInventoryGalleryContextMenu; typedef boost::function callback_t; -class LLInventoryGallery : public LLPanel +class LLInventoryGallery : public LLPanel, public LLEditMenuHandler { public: @@ -139,6 +139,19 @@ public: LLScrollContainer* getScrollableContainer() { return mScrollPanel; } LLInventoryGalleryItem* getSelectedItem(); + // Copy & paste (LLEditMenuHandler) + void copy() override; + BOOL canCopy() const override; + + void cut() override; + BOOL canCut() const override; + + void paste() override; + BOOL canPaste() const override; + + void claimEditHandler(); + static bool isItemCopyable(const LLUUID & item_id); + protected: void showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id); diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index e7f8b10cca..bc4b28b584 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -134,20 +134,10 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } else if ("cut" == action) { - bool allow = false; - if(is_folder) - { - allow = get_is_category_removable(&gInventory, selected_id); - } - else - { - allow = get_is_item_removable(&gInventory, selected_id); - } - if(allow) - { - LLClipboard::instance().setCutMode(true); - LLClipboard::instance().addToClipboard(selected_id); - } + if (mGallery->canCut()) + { + mGallery->cut(); + } } else if ("paste" == action) { @@ -227,19 +217,9 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } else if ("copy" == action) { - if(is_folder) + if (mGallery->canCopy()) { - LLClipboard::instance().reset(); - LLClipboard::instance().addToClipboard(selected_id); - } - else - { - LLViewerInventoryItem* inv_item = gInventory.getItem(selected_id); - if (inv_item && inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()) && !get_is_item_worn(selected_id)) - { - LLClipboard::instance().reset(); - LLClipboard::instance().addToClipboard(selected_id); - } + mGallery->copy(); } } else if ("paste_link" == action) -- cgit v1.3 From f8823a426383949fb1609fa82b5ebb98ef2c295b Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 8 Jun 2023 23:25:12 +0300 Subject: SL-19845 show delete confirmation at least once per session --- indra/newview/llinventoryfunctions.cpp | 6 +++--- indra/newview/llinventoryfunctions.h | 2 +- indra/newview/llinventorygallerymenu.cpp | 6 ++++++ 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index a259dad08a..0b024536ae 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -96,6 +96,7 @@ BOOL LLInventoryState::sWearNewClothing = FALSE; LLUUID LLInventoryState::sWearNewClothingTransactionID; std::list LLInventoryAction::sMarketplaceFolders; +bool LLInventoryAction::sDeleteConfirmationDisplayed = false; // Helper function : callback to update a folder after inventory action happened in the background void update_folder_cb(const LLUUID& dest_folder) @@ -2940,7 +2941,6 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root if ("delete" == action) { - static bool sDisplayedAtSession = false; const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); bool marketplacelistings_item = false; LLAllDescendentsPassedFilter f; @@ -2964,10 +2964,10 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root } else { - if (!sDisplayedAtSession) // ask for the confirmation at least once per session + if (!sDeleteConfirmationDisplayed) // ask for the confirmation at least once per session { LLNotifications::instance().setIgnored("DeleteItems", false); - sDisplayedAtSession = true; + sDeleteConfirmationDisplayed = true; } LLSD args; diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 1b0f598bf5..914d9da620 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -551,7 +551,7 @@ struct LLInventoryAction static void saveMultipleTextures(const std::vector& filenames, std::set selected_items, LLInventoryModel* model); - static const int sConfirmOnDeleteItemsNumber; + static bool sDeleteConfirmationDisplayed; private: static void buildMarketplaceFolders(LLFolderView* root); diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index bc4b28b584..b090434528 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -211,6 +211,12 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } else if ("delete" == action) { + if (!LLInventoryAction::sDeleteConfirmationDisplayed) // ask for the confirmation at least once per session + { + LLNotifications::instance().setIgnored("DeleteItems", false); + LLInventoryAction::sDeleteConfirmationDisplayed = true; + } + LLSD args; args["QUESTION"] = LLTrans::getString("DeleteItem"); LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGalleryContextMenu::onDelete, _1, _2, selected_id)); -- cgit v1.3 From a358acf86ddf19aab96ad26a8f4db9cf609bdce7 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 9 Jun 2023 00:34:03 +0300 Subject: SL-19845 Show delete confirmation for 'delete' key --- indra/newview/llinventorygallery.cpp | 59 +++++++++++++++++++++++--------- indra/newview/llinventorygallery.h | 3 ++ indra/newview/llinventorygallerymenu.cpp | 37 +------------------- indra/newview/llinventorygallerymenu.h | 1 - 4 files changed, 46 insertions(+), 54 deletions(-) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index eff43e33ca..189fb33334 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -46,6 +46,7 @@ #include "llfriendcard.h" #include "llgesturemgr.h" #include "llmarketplacefunctions.h" +#include "llnotificationsutil.h" #include "lloutfitobserver.h" #include "lltrans.h" #include "llviewerassettype.h" @@ -901,23 +902,7 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) // Note: on Mac laptop keyboards, backspace and delete are one and the same if (mSelectedItemID.notNull()) { - LLViewerInventoryCategory* category = gInventory.getCategory(mSelectedItemID); - if (category) - { - if (get_is_category_removable(&gInventory, mSelectedItemID)) - { - gInventory.removeCategory(mSelectedItemID); - handled = TRUE; - } - } - else - { - if (get_is_item_removable(&gInventory, mSelectedItemID)) - { - gInventory.removeItem(mSelectedItemID); - handled = TRUE; - } - } + deleteSelection(); } break; @@ -1325,6 +1310,46 @@ BOOL LLInventoryGallery::canPaste() const return TRUE; } +void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response, const LLUUID& selected_id) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + LLInventoryObject* obj = gInventory.getObject(selected_id); + if (!obj) + { + return; + } + if (obj->getType() == LLAssetType::AT_CATEGORY) + { + if (get_is_category_removable(&gInventory, selected_id)) + { + gInventory.removeCategory(selected_id); + } + } + else + { + if (get_is_item_removable(&gInventory, selected_id)) + { + gInventory.removeItem(selected_id); + } + } + } +} + +void LLInventoryGallery::deleteSelection() +{ + if (!LLInventoryAction::sDeleteConfirmationDisplayed) // ask for the confirmation at least once per session + { + LLNotifications::instance().setIgnored("DeleteItems", false); + LLInventoryAction::sDeleteConfirmationDisplayed = true; + } + + LLSD args; + args["QUESTION"] = LLTrans::getString("DeleteItem"); + LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemID)); +} + void LLInventoryGallery::claimEditHandler() { gEditMenuHandler = this; diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index ac4811adec..54588a3907 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -149,6 +149,9 @@ public: void paste() override; BOOL canPaste() const override; + static void onDelete(const LLSD& notification, const LLSD& response, const LLUUID& selected_id); + void deleteSelection(); + void claimEditHandler(); static bool isItemCopyable(const LLUUID & item_id); diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index b090434528..54b9294ce1 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -211,15 +211,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } else if ("delete" == action) { - if (!LLInventoryAction::sDeleteConfirmationDisplayed) // ask for the confirmation at least once per session - { - LLNotifications::instance().setIgnored("DeleteItems", false); - LLInventoryAction::sDeleteConfirmationDisplayed = true; - } - - LLSD args; - args["QUESTION"] = LLTrans::getString("DeleteItem"); - LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGalleryContextMenu::onDelete, _1, _2, selected_id)); + mGallery->deleteSelection(); } else if ("copy" == action) { @@ -318,33 +310,6 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } } -void LLInventoryGalleryContextMenu::onDelete(const LLSD& notification, const LLSD& response, const LLUUID& selected_id) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0) - { - LLInventoryObject* obj = gInventory.getObject(selected_id); - if (!obj) - { - return; - } - if (obj->getType() == LLAssetType::AT_CATEGORY) - { - if(get_is_category_removable(&gInventory, selected_id)) - { - gInventory.removeCategory(selected_id); - } - } - else - { - if(get_is_item_removable(&gInventory, selected_id)) - { - gInventory.removeItem(selected_id); - } - } - } -} - void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); diff --git a/indra/newview/llinventorygallerymenu.h b/indra/newview/llinventorygallerymenu.h index 1c56266310..67cf9a569a 100644 --- a/indra/newview/llinventorygallerymenu.h +++ b/indra/newview/llinventorygallerymenu.h @@ -47,7 +47,6 @@ protected: void fileUploadLocation(const LLSD& userdata, const LLUUID& selected_id); - static void onDelete(const LLSD& notification, const LLSD& response, const LLUUID& selected_id); static void onRename(const LLSD& notification, const LLSD& response); private: -- cgit v1.3 From 5c6a2779c498e69e36276700283ccfb4bdbfd438 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 9 Jun 2023 22:04:52 +0300 Subject: SL-19826 Pasting folders in Single folder should highlight pasted folder --- indra/newview/llinventoryfunctions.cpp | 30 +++++-- indra/newview/llinventoryfunctions.h | 1 + indra/newview/llinventorygallery.cpp | 150 +++++++++++++++++++++++++------ indra/newview/llinventorygallery.h | 2 + indra/newview/llinventorygallerymenu.cpp | 97 +------------------- 5 files changed, 152 insertions(+), 128 deletions(-) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 0b024536ae..034488c011 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -401,14 +401,32 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s } void copy_inventory_category(LLInventoryModel* model, - LLViewerInventoryCategory* cat, - const LLUUID& parent_id, - const LLUUID& root_copy_id, - bool move_no_copy_items ) + LLViewerInventoryCategory* cat, + const LLUUID& parent_id, + const LLUUID& root_copy_id, + bool move_no_copy_items) +{ + // Create the initial folder + inventory_func_type func = [model, cat, root_copy_id, move_no_copy_items](const LLUUID& new_id) + { + copy_inventory_category_content(new_id, model, cat, root_copy_id, move_no_copy_items); + }; + gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName(), func, cat->getThumbnailUUID()); +} + +void copy_inventory_category(LLInventoryModel* model, + LLViewerInventoryCategory* cat, + const LLUUID& parent_id, + const LLUUID& root_copy_id, + bool move_no_copy_items, + inventory_func_type callback) { // Create the initial folder - // D567 needs to handle new fields - inventory_func_type func = boost::bind(©_inventory_category_content, _1, model, cat, root_copy_id, move_no_copy_items); + inventory_func_type func = [model, cat, root_copy_id, move_no_copy_items, callback](const LLUUID &new_id) + { + copy_inventory_category_content(new_id, model, cat, root_copy_id, move_no_copy_items); + callback(new_id); + }; gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName(), func, cat->getThumbnailUUID()); } diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 914d9da620..f19cadaded 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -75,6 +75,7 @@ void update_all_marketplace_count(); void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name); void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id = LLUUID::null, bool move_no_copy_items = false); +void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id, bool move_no_copy_items, inventory_func_type callback); void copy_inventory_category_content(const LLUUID& new_cat_uuid, LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& root_copy_id, bool move_no_copy_items); diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 358b4e457a..412e9e9c0b 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -709,7 +709,9 @@ void LLInventoryGallery::onIdle(void* userdata) if (self->mItemToSelect.notNull()) { - self->changeItemSelection(self->mItemToSelect, true); + LLUUID item_to_select = self->mItemToSelect; + self->mItemToSelect = LLUUID::null; + self->changeItemSelection(item_to_select, true); } if (self->mItemToSelect.isNull()) @@ -879,12 +881,14 @@ void LLInventoryGallery::onThumbnailAdded(LLUUID item_id) BOOL LLInventoryGallery::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if(mItemMap[mSelectedItemID]) + LLUUID old_selection = mSelectedItemID; + BOOL res = LLPanel::handleRightMouseDown(x, y, mask); + if (!res) { - mItemMap[mSelectedItemID]->setFocus(false); + clearSelection(); + mItemMap[old_selection]->setFocus(false); } - clearSelection(); - BOOL res = LLPanel::handleRightMouseDown(x, y, mask); + if (mSelectedItemID.isNull()) { if (mInventoryGalleryMenu && mFolderID.notNull()) @@ -1125,24 +1129,30 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ mItemToSelect = item_id; return; } - if (mSelectedItemID != item_id) + if (mSelectedItemID == item_id) { - if (mItemMap[mSelectedItemID]) - { - mItemMap[mSelectedItemID]->setSelected(FALSE); - } - if (mItemMap[item_id]) - { - mItemMap[item_id]->setSelected(TRUE); - } - mSelectedItemID = item_id; - signalSelectionItemID(item_id); + return; + } + if (mNeedsArrange && item_id.notNull() && scroll_to_selection) + { + mItemToSelect = item_id; + return; + } - mItemToSelect = LLUUID::null; - if(scroll_to_selection) - { - scrollToShowItem(mSelectedItemID); - } + if (mItemMap[mSelectedItemID]) + { + mItemMap[mSelectedItemID]->setSelected(FALSE); + } + if (mItemMap[item_id]) + { + mItemMap[item_id]->setSelected(TRUE); + } + mSelectedItemID = item_id; + signalSelectionItemID(item_id); + + if (scroll_to_selection) + { + scrollToShowItem(mSelectedItemID); } } @@ -1241,6 +1251,11 @@ BOOL LLInventoryGallery::canCut() const void LLInventoryGallery::paste() { + if (!LLClipboard::instance().hasContents()) + { + return; + } + const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); if (gInventory.isObjectDescendentOf(mSelectedItemID, marketplacelistings_id)) { @@ -1254,6 +1269,20 @@ void LLInventoryGallery::paste() std::vector objects; LLClipboard::instance().pasteFromClipboard(objects); + + LLHandle handle = getHandle(); + std::function on_copy_callback = [handle](const LLUUID& inv_item) + { + LLInventoryGallery* panel = (LLInventoryGallery*)handle.get(); + if (panel) + { + // Scroll to pasted item and highlight it + // Should it only highlight the last one? + panel->changeItemSelection(inv_item, true); + } + }; + LLPointer cb = new LLBoostFuncInventoryCallback(on_copy_callback); + for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) { const LLUUID& item_id = (*iter); @@ -1268,10 +1297,12 @@ void LLInventoryGallery::paste() if (is_cut_mode) { gInventory.changeCategoryParent(cat, dest, false); + // Don't select immediately, wait for item to arrive + mItemToSelect = item_id; } else { - copy_inventory_category(&gInventory, cat, dest); + copy_inventory_category(&gInventory, cat, dest, LLUUID::null, false, on_copy_callback); } } else @@ -1282,13 +1313,14 @@ void LLInventoryGallery::paste() if (is_cut_mode) { gInventory.changeItemParent(item, dest, false); + // Don't select immediately, wait for item to arrive + mItemToSelect = item_id; } else { if (item->getIsLinkType()) { - link_inventory_object(dest, item_id, - LLPointer(NULL)); + link_inventory_object(dest, item_id, cb); } else { @@ -1298,13 +1330,13 @@ void LLInventoryGallery::paste() item->getUUID(), dest, std::string(), - LLPointer(NULL)); + cb); } } } } } - // todo: scroll to item on arrival + LLClipboard::instance().setCutMode(false); } @@ -1379,6 +1411,66 @@ void LLInventoryGallery::deleteSelection() LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemID)); } +void LLInventoryGallery::pasteAsLink() +{ + if (!LLClipboard::instance().hasContents()) + { + return; + } + + const LLUUID& current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& my_outifts_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + + LLUUID dest; + LLInventoryObject* obj = gInventory.getObject(mSelectedItemID); + if (obj && obj->getType() == LLAssetType::AT_CATEGORY) + { + dest = mSelectedItemID; + } + else + { + dest = mFolderID; + } + + const BOOL move_is_into_current_outfit = (dest == current_outfit_id); + const BOOL move_is_into_my_outfits = (dest == my_outifts_id) || gInventory.isObjectDescendentOf(dest, my_outifts_id); + const BOOL move_is_into_marketplacelistings = gInventory.isObjectDescendentOf(dest, marketplacelistings_id); + + if (move_is_into_marketplacelistings || move_is_into_current_outfit || move_is_into_my_outfits) + { + return; + } + std::vector objects; + LLClipboard::instance().pasteFromClipboard(objects); + + LLHandle handle = getHandle(); + std::function on_link_callback = [handle](const LLUUID& inv_item) + { + LLInventoryGallery *panel = (LLInventoryGallery*)handle.get(); + if (panel) + { + // Scroll to pasted item and highlight it + // Should it only highlight the last one? + panel->changeItemSelection(inv_item, true); + } + }; + LLPointer cb = new LLBoostFuncInventoryCallback(on_link_callback); + + for (std::vector::const_iterator iter = objects.begin(); + iter != objects.end(); + ++iter) + { + const LLUUID& object_id = (*iter); + if (LLConstPointer link_obj = gInventory.getObject(object_id)) + { + link_inventory_object(dest, link_obj, cb); + } + } + + LLClipboard::instance().setCutMode(false); +} + void LLInventoryGallery::claimEditHandler() { gEditMenuHandler = this; @@ -1970,7 +2062,8 @@ BOOL LLInventoryGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) setFocus(TRUE); mGallery->claimEditHandler(); - return LLUICtrl::handleRightMouseDown(x, y, mask); + LLUICtrl::handleRightMouseDown(x, y, mask); + return TRUE; } BOOL LLInventoryGalleryItem::handleMouseUp(S32 x, S32 y, MASK mask) @@ -2238,6 +2331,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, accepted = dragItemIntoFolder(dest_id, inv_item, drop, tooltip_msg, true); if (accepted && drop) { + // Don't select immediately, wait for item to arrive mItemToSelect = inv_item->getUUID(); } break; @@ -2257,7 +2351,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, { accepted = dragItemIntoFolder(dest_id, inv_item, drop, tooltip_msg, TRUE); } - if (accepted && drop) + if (accepted && drop && inv_item) { mItemToSelect = inv_item->getUUID(); } diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index 3797b9bc61..e71e2eddcd 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -149,8 +149,10 @@ public: void paste() override; BOOL canPaste() const override; + // Copy & paste & delete static void onDelete(const LLSD& notification, const LLSD& response, const LLUUID& selected_id); void deleteSelection(); + void pasteAsLink(); void claimEditHandler(); static bool isItemCopyable(const LLUUID & item_id); diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 54b9294ce1..68ead64839 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -71,8 +71,6 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU LLInventoryObject* obj = gInventory.getObject(selected_id); if(!obj) return; - bool is_folder = (obj->getType() == LLAssetType::AT_CATEGORY); - if ("open_selected_folder" == action) { mGallery->setRootFolder(selected_id); @@ -141,72 +139,9 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } else if ("paste" == action) { + if (mGallery->canPaste()) { - const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); - if(gInventory.isObjectDescendentOf(selected_id, marketplacelistings_id)) - { - return; - } - - bool is_cut_mode = (LLClipboard::instance().isCutMode()); - { - LLUUID dest = is_folder ? selected_id : obj->getParentUUID(); - - std::vector objects; - LLClipboard::instance().pasteFromClipboard(objects); - for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) - { - const LLUUID& item_id = (*iter); - if(gInventory.isObjectDescendentOf(item_id, marketplacelistings_id) && (LLMarketplaceData::instance().isInActiveFolder(item_id) || - LLMarketplaceData::instance().isListedAndActive(item_id))) - { - return; - } - LLViewerInventoryCategory* cat = gInventory.getCategory(item_id); - if (cat) - { - if(is_cut_mode) - { - gInventory.changeCategoryParent(cat, dest, false); - } - else - { - copy_inventory_category(&gInventory, cat, dest); - } - } - else - { - LLViewerInventoryItem* item = gInventory.getItem(item_id); - if (item) - { - if(is_cut_mode) - { - gInventory.changeItemParent(item, dest, false); - } - else - { - if (item->getIsLinkType()) - { - link_inventory_object(dest, item_id, - LLPointer(NULL)); - } - else - { - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - dest, - std::string(), - LLPointer(NULL)); - } - } - } - } - } - LLClipboard::instance().setCutMode(false); - } - + mGallery->paste(); } } else if ("delete" == action) @@ -222,33 +157,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } else if ("paste_link" == action) { - const LLUUID ¤t_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); - const LLUUID &my_outifts_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - - const BOOL move_is_into_current_outfit = (selected_id == current_outfit_id); - const BOOL move_is_into_my_outfits = (selected_id == my_outifts_id) || gInventory.isObjectDescendentOf(selected_id, my_outifts_id); - const BOOL move_is_into_marketplacelistings = gInventory.isObjectDescendentOf(selected_id, marketplacelistings_id); - - if (move_is_into_marketplacelistings || move_is_into_current_outfit || move_is_into_my_outfits) - { - return; - } - LLUUID dest = is_folder ? selected_id : obj->getParentUUID(); - std::vector objects; - LLClipboard::instance().pasteFromClipboard(objects); - for (std::vector::const_iterator iter = objects.begin(); - iter != objects.end(); - ++iter) - { - const LLUUID &object_id = (*iter); - if (LLConstPointer link_obj = gInventory.getObject(object_id)) - { - link_inventory_object(dest, link_obj, LLPointer(NULL)); - } - } - - LLClipboard::instance().setCutMode(false); + mGallery->pasteAsLink(); } else if ("rename" == action) { -- cgit v1.3 From f608eafc3724899a16d01d4b9464a21f8fbc08d3 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 16 Jun 2023 22:22:59 +0300 Subject: SL-19496 Fix attempts to open trash for thumnail assigment do not work. --- indra/newview/llfloaterchangeitemthumbnail.cpp | 4 ++-- indra/newview/llinventorybridge.cpp | 2 ++ indra/newview/llinventorygallerymenu.cpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llfloaterchangeitemthumbnail.cpp b/indra/newview/llfloaterchangeitemthumbnail.cpp index c3392889fb..48378cb724 100644 --- a/indra/newview/llfloaterchangeitemthumbnail.cpp +++ b/indra/newview/llfloaterchangeitemthumbnail.cpp @@ -295,8 +295,8 @@ void LLFloaterChangeItemThumbnail::refreshFromInventory() if (obj) { const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - bool in_trash = (obj->getUUID() == trash_id) || gInventory.isObjectDescendentOf(obj->getUUID(), trash_id); - if (in_trash) + bool in_trash = gInventory.isObjectDescendentOf(obj->getUUID(), trash_id); + if (in_trash && obj->getUUID() != trash_id) { // Close properties when moving to trash // Aren't supposed to view properties from trash diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 02a29f2ac9..a2bf9e7cd2 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4218,6 +4218,8 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items { disabled_items.push_back(std::string("Empty Trash")); } + + items.push_back(std::string("thumbnail")); } else if(isItemInTrash()) { diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 68ead64839..e30883d564 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -334,7 +334,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men if(!is_link) { items.push_back(std::string("thumbnail")); - if (!is_agent_inventory) + if (!is_agent_inventory || (is_in_trash && !is_trash)) { disabled_items.push_back(std::string("thumbnail")); } -- cgit v1.3 From 6c0891473ff1d5f740e3d3624cec2f5c17da0ad6 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Tue, 20 Jun 2023 17:38:23 +0300 Subject: SL-19892 add missing menu items for Landmarks in Gallery view --- indra/newview/llinventorygallerymenu.cpp | 59 ++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index e30883d564..541fed8172 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -33,9 +33,12 @@ #include "llavataractions.h" #include "llclipboard.h" #include "llfloaterreg.h" +#include "llfloatersidepanelcontainer.h" +#include "llfloaterworldmap.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventorymodel.h" +#include "lllandmarkactions.h" #include "llmarketplacefunctions.h" #include "llmenugl.h" #include "llnotificationsutil.h" @@ -217,6 +220,55 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU { LLFloaterReg::showInstance("linkreplace", LLSD(selected_id)); } + else if ("copy_slurl" == action) + { + boost::function copy_slurl_cb = [](LLLandmark* landmark) + { + LLVector3d global_pos; + landmark->getGlobalPos(global_pos); + boost::function copy_slurl_to_clipboard_cb = [](const std::string& slurl) + { + gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl)); + LLSD args; + args["SLURL"] = slurl; + LLNotificationsUtil::add("CopySLURL", args); + }; + LLLandmarkActions::getSLURLfromPosGlobal(global_pos, copy_slurl_to_clipboard_cb, true); + }; + LLLandmark* landmark = LLLandmarkActions::getLandmark(selected_id, copy_slurl_cb); + if (landmark) + { + copy_slurl_cb(landmark); + } + } + else if ("about" == action) + { + LLSD key; + key["type"] = "landmark"; + key["id"] = selected_id; + LLFloaterSidePanelContainer::showPanel("places", key); + } + else if ("show_on_map" == action) + { + boost::function show_on_map_cb = [](LLLandmark* landmark) + { + LLVector3d landmark_global_pos; + if (landmark->getGlobalPos(landmark_global_pos)) + { + LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance(); + if (!landmark_global_pos.isExactlyZero() && worldmap_instance) + { + worldmap_instance->trackLocation(landmark_global_pos); + LLFloaterReg::showInstance("world_map", "center"); + } + } + }; + LLLandmark* landmark = LLLandmarkActions::getLandmark(selected_id, show_on_map_cb); + if(landmark) + { + show_on_map_cb(landmark); + } + } } void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLSD& response) @@ -357,6 +409,13 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men { items.push_back(std::string("Replace Links")); } + if (obj->getType() == LLAssetType::AT_LANDMARK) + { + items.push_back(std::string("Landmark Separator")); + items.push_back(std::string("url_copy")); + items.push_back(std::string("About Landmark")); + items.push_back(std::string("show_on_map")); + } } if(is_trash) -- cgit v1.3 From 434f2ee512dc6edf4a6dfbafd7265d121038bf0b Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Mon, 26 Jun 2023 18:39:51 +0300 Subject: SL-19918 "Save as" menu item is missing for textures in Gallery view --- indra/newview/llinventorygallerymenu.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 541fed8172..bca10b9c0e 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -42,6 +42,7 @@ #include "llmarketplacefunctions.h" #include "llmenugl.h" #include "llnotificationsutil.h" +#include "llpreviewtexture.h" #include "lltrans.h" #include "llviewerfoldertype.h" #include "llviewerwindow.h" @@ -269,6 +270,15 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU show_on_map_cb(landmark); } } + else if ("save_as" == action) + { + LLPreviewTexture* preview_texture = LLFloaterReg::getTypedInstance("preview_texture", selected_id); + if (preview_texture) + { + preview_texture->openToSave(); + preview_texture->saveAs(); + } + } } void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLSD& response) @@ -620,6 +630,15 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men } } } + if(obj->getType() == LLAssetType::AT_TEXTURE) + { + items.push_back(std::string("Save As")); + bool can_copy = selected_item && selected_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); + if (!can_copy) + { + disabled_items.push_back(std::string("Save As")); + } + } if (is_link) { items.push_back(std::string("Find Original")); -- cgit v1.3 From f24f72d2f9db7490b169daea16f8ab8400ca12b4 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 6 Sep 2023 02:56:11 +0300 Subject: SL-19826 Gallery multiselect support Part#3 wip --- indra/newview/llinventoryfunctions.cpp | 5 +- indra/newview/llinventorygallery.cpp | 480 ++++++++++++++++----- indra/newview/llinventorygallery.h | 25 +- indra/newview/llinventorygallerymenu.cpp | 162 ++++--- indra/newview/llinventorygallerymenu.h | 6 +- .../default/xui/en/menu_gallery_inventory.xml | 26 +- 6 files changed, 509 insertions(+), 195 deletions(-) (limited to 'indra/newview/llinventorygallerymenu.cpp') diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index f5f0d74f0f..4aeacae6ed 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -454,7 +454,10 @@ void copy_inventory_category(LLInventoryModel* model, inventory_func_type func = [model, cat, root_copy_id, move_no_copy_items, callback](const LLUUID &new_id) { copy_inventory_category_content(new_id, model, cat, root_copy_id, move_no_copy_items); - callback(new_id); + if (callback) + { + callback(new_id); + } }; gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName(), func, cat->getThumbnailUUID()); } diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 8170c0c63b..eab15b79ad 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -107,7 +107,6 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mIsInitialized(false), mRootDirty(false), mNeedsArrange(false), - mNeedsSelection(false), mSearchType(LLInventoryFilter::SEARCHTYPE_NAME), mSortOrder(LLInventoryFilter::SO_DATE) { @@ -219,10 +218,10 @@ void LLInventoryGallery::setRootFolder(const LLUUID cat_id) gIdleCallbacks.deleteFunction(onIdle, (void*)this); mFolderID = cat_id; - mItemToSelect.setNull(); + mItemsToSelect.clear(); + mSelectedItemIDs.clear(); mItemBuildQuery.clear(); mNeedsArrange = false; - mNeedsSelection = false; dirtyRootFolder(); } @@ -831,15 +830,17 @@ void LLInventoryGallery::onIdle(void* userdata) self->updateMessageVisibility(); } - if (self->mNeedsSelection) + if (!self->mItemsToSelect.empty() && !self->mNeedsArrange) { - LLUUID item_to_select = self->mItemToSelect; - self->mItemToSelect = LLUUID::null; - self->mNeedsSelection = false; - self->changeItemSelection(item_to_select, true); + selection_deque selection_list(self->mItemsToSelect); + self->mItemsToSelect.clear(); + for (LLUUID & item_to_select : selection_list) + { + self->addItemSelection(item_to_select, true); + } } - if (!self->mNeedsSelection && self->mItemBuildQuery.empty()) + if (self->mItemsToSelect.empty() && self->mItemBuildQuery.empty()) { gIdleCallbacks.deleteFunction(onIdle, (void*)self); } @@ -911,7 +912,6 @@ bool LLInventoryGallery::updateAddedItem(LLUUID item_id) LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getCreationDate(), obj->getIsLinkType(), is_worn); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); - item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::changeItemSelection, this, item_id, false)); if (mGalleryCreated) { res = applyFilter(item, mFilterSubString); @@ -1074,8 +1074,7 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) mFilterSubString.clear(); if (mInventoryGalleryMenu && mSelectedItemIDs.size() == 1) { - selection_deque::iterator iter = mSelectedItemIDs.begin(); - mInventoryGalleryMenu->doToSelected("rename", *iter); + mInventoryGalleryMenu->rename(mSelectedItemIDs.front()); } handled = TRUE; break; @@ -1117,22 +1116,22 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) break; case KEY_LEFT: - moveLeft(); + moveLeft(mask); handled = TRUE; break; case KEY_RIGHT: - moveRight(); + moveRight(mask); handled = TRUE; break; case KEY_UP: - moveUp(); + moveUp(mask); handled = TRUE; break; case KEY_DOWN: - moveDown(); + moveDown(mask); handled = TRUE; break; @@ -1148,59 +1147,107 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) return handled; } -void LLInventoryGallery::moveUp() +void LLInventoryGallery::moveUp(MASK mask) { mFilterSubString.clear(); if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getFirstSelectedItem(); + LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID]; if (item) { - S32 n = mItemIndexMap[item]; - n -= mItemsInRow; - if (n >= 0) + if (mask == MASK_NONE || mask == MASK_CONTROL) { - item = mIndexToItemMap[n]; - LLUUID item_id = item->getUUID(); - changeItemSelection(item_id, true); - item->setFocus(TRUE); - claimEditHandler(); + S32 n = mItemIndexMap[item]; + n -= mItemsInRow; + if (n >= 0) + { + item = mIndexToItemMap[n]; + LLUUID item_id = item->getUUID(); + if (mask == MASK_CONTROL) + { + addItemSelection(item_id, true); + } + else + { + changeItemSelection(item_id, true); + } + item->setFocus(TRUE); + claimEditHandler(); + } + } + else if (mask == MASK_SHIFT) + { + S32 n = mItemIndexMap[item]; + S32 target = llmax(0, n - mItemsInRow); + toggleSelectionRange(target, n - 1); + if (target != n) + { + item = mIndexToItemMap[target]; + item->setFocus(TRUE); + claimEditHandler(); + } } } } } -void LLInventoryGallery::moveDown() +void LLInventoryGallery::moveDown(MASK mask) { mFilterSubString.clear(); if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getFirstSelectedItem(); + LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID]; if (item) { - S32 n = mItemIndexMap[item]; - n += mItemsInRow; - if (n < mItemsAddedCount) + if (mask == MASK_NONE || mask == MASK_CONTROL) { - item = mIndexToItemMap[n]; - LLUUID item_id = item->getUUID(); - changeItemSelection(item_id, true); - item->setFocus(TRUE); - claimEditHandler(); + S32 n = mItemIndexMap[item]; + n += mItemsInRow; + if (n < mItemsAddedCount) + { + item = mIndexToItemMap[n]; + LLUUID item_id = item->getUUID(); + if (mask == MASK_CONTROL) + { + addItemSelection(item_id, true); + } + else + { + changeItemSelection(item_id, true); + } + item->setFocus(TRUE); + claimEditHandler(); + } + } + else if (mask == MASK_SHIFT) + { + S32 n = mItemIndexMap[item]; + S32 target = llmin(mItemsAddedCount - 1, n + mItemsInRow); + toggleSelectionRange(n + 1, target); + if (target != n) + { + item = mIndexToItemMap[target]; + item->setFocus(TRUE); + claimEditHandler(); + } } } } } -void LLInventoryGallery::moveLeft() +void LLInventoryGallery::moveLeft(MASK mask) { mFilterSubString.clear(); if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getFirstSelectedItem(); + LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID]; + if (mask == MASK_SHIFT) + { + item = mItemMap[mLastSelectedUUID]; + } if (item) { // Might be better to get item from panel @@ -1212,20 +1259,31 @@ void LLInventoryGallery::moveLeft() } item = mIndexToItemMap[n]; LLUUID item_id = item->getUUID(); - changeItemSelection(item_id, true); + if (mask == MASK_CONTROL) + { + addItemSelection(item_id, true); + } + else if (mask == MASK_SHIFT) + { + toggleItemSelection(item_id, true); + } + else + { + changeItemSelection(item_id, true); + } item->setFocus(TRUE); claimEditHandler(); } } } -void LLInventoryGallery::moveRight() +void LLInventoryGallery::moveRight(MASK mask) { mFilterSubString.clear(); if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getFirstSelectedItem(); + LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID]; if (item) { S32 n = mItemIndexMap[item]; @@ -1236,13 +1294,58 @@ void LLInventoryGallery::moveRight() } item = mIndexToItemMap[n]; LLUUID item_id = item->getUUID(); - changeItemSelection(item_id, true); + if (mask == MASK_CONTROL) + { + addItemSelection(item_id, true); + } + else if (mask == MASK_SHIFT) + { + toggleItemSelection(item_id, true); + } + else + { + changeItemSelection(item_id, true); + } item->setFocus(TRUE); claimEditHandler(); } } } +void LLInventoryGallery::toggleSelectionRange(S32 start_idx, S32 end_idx) +{ + LLInventoryGalleryItem* item = NULL; + for (S32 i = start_idx; i <= end_idx; i++) + { + item = mIndexToItemMap[i]; + LLUUID item_id = item->getUUID(); + toggleItemSelection(item_id, true); + } +} + +void LLInventoryGallery::toggleSelectionRangeFromLast(const LLUUID target) +{ + if (mLastSelectedUUID == target) + { + return; + } + LLInventoryGalleryItem* last_item = mItemMap[mLastSelectedUUID]; + LLInventoryGalleryItem* next_item = mItemMap[target]; + if (last_item && next_item) + { + S32 last_idx = mItemIndexMap[last_item]; + S32 next_idx = mItemIndexMap[next_item]; + if (last_idx < next_idx) + { + toggleSelectionRange(last_idx + 1, next_idx); + } + else + { + toggleSelectionRange(next_idx, last_idx - 1); + } + } +} + void LLInventoryGallery::onFocusLost() { // inventory no longer handles cut/copy/paste/delete @@ -1270,17 +1373,21 @@ void LLInventoryGallery::onFocusReceived() // Tab support, when tabbing into this view, select first item if (mSelectedItemIDs.size() > 0) { + LLInventoryGalleryItem* focus_item = NULL; for (const LLUUID& id : mSelectedItemIDs) { if (mItemMap[id]) { - LLInventoryGalleryItem* focus_item = mItemMap[id]; + focus_item = mItemMap[id]; focus_item->setSelected(true); - focus_item->setFocus(TRUE); } } + if (focus_item) + { + focus_item->setFocus(TRUE); + } } - else if (mIndexToItemMap.size() > 0 && !mNeedsSelection) + else if (mIndexToItemMap.size() > 0 && mItemsToSelect.empty()) { // choose any items from visible rect S32 vert_offset = mScrollPanel->getDocPosVertical(); @@ -1304,18 +1411,26 @@ void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLU mSelectedItemIDs.clear(); changeItemSelection(item_id, false); } - uuid_vec_t selected_uuids; - selected_uuids.push_back(item_id); + uuid_vec_t selected_uuids(mSelectedItemIDs.begin(), mSelectedItemIDs.end()); mInventoryGalleryMenu->show(ctrl, selected_uuids, x, y); } } void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_to_selection) { + for (const LLUUID& id : mSelectedItemIDs) + { + if (mItemMap[id]) + { + mItemMap[id]->setSelected(FALSE); + } + } + mSelectedItemIDs.clear(); + if ((mItemMap.count(item_id) == 0) || mNeedsArrange) { - mItemToSelect = item_id; - mNeedsSelection = true; + mItemsToSelect.clear(); + mItemsToSelect.push_back(item_id); return; } if (mSelectedItemIDs.size() == 1 @@ -1325,14 +1440,32 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ return; } - for (const LLUUID& id : mSelectedItemIDs) + if (mItemMap[item_id]) { - if (mItemMap[id]) - { - mItemMap[id]->setSelected(FALSE); - } + mItemMap[item_id]->setSelected(TRUE); + } + mSelectedItemIDs.push_back(item_id); + signalSelectionItemID(item_id); + mLastSelectedUUID = item_id; + + if (scroll_to_selection) + { + scrollToShowItem(item_id); + } +} + +void LLInventoryGallery::addItemSelection(const LLUUID& item_id, bool scroll_to_selection) +{ + if ((mItemMap.count(item_id) == 0) || mNeedsArrange) + { + mItemsToSelect.push_back(item_id); + return; + } + if (std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id) != mSelectedItemIDs.end()) + { + // Already selected + return; } - mSelectedItemIDs.clear(); if (mItemMap[item_id]) { @@ -1340,6 +1473,7 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ } mSelectedItemIDs.push_back(item_id); signalSelectionItemID(item_id); + mLastSelectedUUID = item_id; if (scroll_to_selection) { @@ -1347,6 +1481,43 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ } } +bool LLInventoryGallery::toggleItemSelection(const LLUUID& item_id, bool scroll_to_selection) +{ + bool result = false; + if ((mItemMap.count(item_id) == 0) || mNeedsArrange) + { + mItemsToSelect.push_back(item_id); + return result; + } + selection_deque::iterator found = std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id); + if (found != mSelectedItemIDs.end()) + { + if (mItemMap[item_id]) + { + mItemMap[item_id]->setSelected(FALSE); + } + mSelectedItemIDs.erase(found); + result = false; + } + else + { + if (mItemMap[item_id]) + { + mItemMap[item_id]->setSelected(TRUE); + } + mSelectedItemIDs.push_back(item_id); + signalSelectionItemID(item_id); + mLastSelectedUUID = item_id; + result = true; + } + + if (scroll_to_selection) + { + scrollToShowItem(item_id); + } + return result; +} + void LLInventoryGallery::scrollToShowItem(const LLUUID& item_id) { LLInventoryGalleryItem* item = mItemMap[item_id]; @@ -1476,32 +1647,63 @@ void LLInventoryGallery::paste() return; } - LLUUID first_selected_id; - if (mSelectedItemIDs.size() > 0) - { - first_selected_id = *mSelectedItemIDs.begin(); - } - - LLInventoryObject* obj = gInventory.getObject(first_selected_id); - bool is_folder = obj && (obj->getType() == LLAssetType::AT_CATEGORY); - LLUUID dest = is_folder ? first_selected_id : mFolderID; bool is_cut_mode = LLClipboard::instance().isCutMode(); - std::vector objects; LLClipboard::instance().pasteFromClipboard(objects); - LLHandle handle = getHandle(); - std::function on_copy_callback = [handle](const LLUUID& inv_item) + bool paste_into_root = mSelectedItemIDs.empty(); + for (LLUUID& dest : mSelectedItemIDs) { - LLInventoryGallery* panel = (LLInventoryGallery*)handle.get(); - if (panel) + LLInventoryObject* obj = gInventory.getObject(dest); + if (!obj || (obj->getType() != LLAssetType::AT_CATEGORY)) { - // Scroll to pasted item and highlight it - // Should it only highlight the last one? - panel->changeItemSelection(inv_item, true); + paste_into_root = true; + continue; } - }; - LLPointer cb = new LLBoostFuncInventoryCallback(on_copy_callback); + + paste(dest, objects, is_cut_mode, marketplacelistings_id); + is_cut_mode = false; + } + + if (paste_into_root) + { + for (const LLUUID& id : mSelectedItemIDs) + { + if (mItemMap[id]) + { + mItemMap[id]->setSelected(FALSE); + } + } + mSelectedItemIDs.clear(); + + paste(mFolderID, objects, is_cut_mode, marketplacelistings_id); + } + + LLClipboard::instance().setCutMode(false); +} + +void LLInventoryGallery::paste(const LLUUID& dest, + std::vector& objects, + bool is_cut_mode, + const LLUUID& marketplacelistings_id) +{ + LLHandle handle = getHandle(); + std::function on_copy_callback = NULL; + LLPointer cb = NULL; + if (dest == mFolderID) + { + on_copy_callback = [handle](const LLUUID& inv_item) + { + LLInventoryGallery* panel = (LLInventoryGallery*)handle.get(); + if (panel) + { + // Scroll to pasted item and highlight it + // Should it only highlight the last one? + panel->addItemSelection(inv_item, true); + } + }; + cb = new LLBoostFuncInventoryCallback(on_copy_callback); + } for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) { @@ -1517,9 +1719,11 @@ void LLInventoryGallery::paste() if (is_cut_mode) { gInventory.changeCategoryParent(cat, dest, false); - // Don't select immediately, wait for item to arrive - mItemToSelect = item_id; - mNeedsSelection = true; + if (dest == mFolderID) + { + // Don't select immediately, wait for item to arrive + mItemsToSelect.push_back(item_id); + } } else { @@ -1534,9 +1738,11 @@ void LLInventoryGallery::paste() if (is_cut_mode) { gInventory.changeItemParent(item, dest, false); - // Don't select immediately, wait for item to arrive - mItemToSelect = item_id; - mNeedsSelection = true; + if (dest == mFolderID) + { + // Don't select immediately, wait for item to arrive + mItemsToSelect.push_back(item_id); + } } else { @@ -1679,17 +1885,45 @@ void LLInventoryGallery::pasteAsLink() const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); const LLUUID& my_outifts_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - LLUUID dest; - if (mSelectedItemIDs.size() > 0) + std::vector objects; + LLClipboard::instance().pasteFromClipboard(objects); + + bool paste_into_root = mSelectedItemIDs.empty(); + for (LLUUID& dest : mSelectedItemIDs) { - dest = *mSelectedItemIDs.begin(); + LLInventoryObject* obj = gInventory.getObject(dest); + if (!obj || obj->getType() != LLAssetType::AT_CATEGORY) + { + paste_into_root = true; + continue; + } + + pasteAsLink(dest, objects, current_outfit_id, marketplacelistings_id, my_outifts_id); } - LLInventoryObject* obj = gInventory.getObject(dest); - if (!obj || obj->getType() != LLAssetType::AT_CATEGORY) + + if (paste_into_root) { - dest = mFolderID; + for (const LLUUID& id : mSelectedItemIDs) + { + if (mItemMap[id]) + { + mItemMap[id]->setSelected(FALSE); + } + } + mSelectedItemIDs.clear(); + + pasteAsLink(mFolderID, objects, current_outfit_id, marketplacelistings_id, my_outifts_id); } + LLClipboard::instance().setCutMode(false); +} + +void LLInventoryGallery::pasteAsLink(const LLUUID& dest, + std::vector& objects, + const LLUUID& current_outfit_id, + const LLUUID& marketplacelistings_id, + const LLUUID& my_outifts_id) +{ const BOOL move_is_into_current_outfit = (dest == current_outfit_id); const BOOL move_is_into_my_outfits = (dest == my_outifts_id) || gInventory.isObjectDescendentOf(dest, my_outifts_id); const BOOL move_is_into_marketplacelistings = gInventory.isObjectDescendentOf(dest, marketplacelistings_id); @@ -1698,21 +1932,23 @@ void LLInventoryGallery::pasteAsLink() { return; } - std::vector objects; - LLClipboard::instance().pasteFromClipboard(objects); - LLHandle handle = getHandle(); - std::function on_link_callback = [handle](const LLUUID& inv_item) + LLPointer cb = NULL; + if (dest == mFolderID) { - LLInventoryGallery *panel = (LLInventoryGallery*)handle.get(); - if (panel) - { - // Scroll to pasted item and highlight it - // Should it only highlight the last one? - panel->changeItemSelection(inv_item, true); - } - }; - LLPointer cb = new LLBoostFuncInventoryCallback(on_link_callback); + LLHandle handle = getHandle(); + std::function on_link_callback = [handle](const LLUUID& inv_item) + { + LLInventoryGallery* panel = (LLInventoryGallery*)handle.get(); + if (panel) + { + // Scroll to pasted item and highlight it + // Should it only highlight the last one? + panel->addItemSelection(inv_item, true); + } + }; + cb = new LLBoostFuncInventoryCallback(on_link_callback); + } for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); @@ -1724,8 +1960,6 @@ void LLInventoryGallery::pasteAsLink() link_inventory_object(dest, link_obj, cb); } } - - LLClipboard::instance().setCutMode(false); } void LLInventoryGallery::claimEditHandler() @@ -1852,7 +2086,7 @@ void LLInventoryGallery::refreshList(const LLUUID& category_id) mNeedsArrange = true; } - if(mNeedsArrange || mItemToSelect.notNull()) + if(mNeedsArrange || !mItemsToSelect.empty()) { // Don't scroll to target/arrange immediately // since more updates might be pending @@ -1969,7 +2203,7 @@ void LLInventoryGallery::deselectItem(const LLUUID& category_id) mItemMap[category_id]->setSelected(FALSE); setFocus(true); // Todo: support multiselect - signalSelectionItemID(LLUUID::null); + // signalSelectionItemID(LLUUID::null); } selection_deque::iterator found = std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), category_id); @@ -1991,6 +2225,7 @@ void LLInventoryGallery::clearSelection() if (!mSelectedItemIDs.empty()) { mSelectedItemIDs.clear(); + // BUG: wrong, item can be null signalSelectionItemID(LLUUID::null); } } @@ -2350,8 +2585,6 @@ void LLInventoryGalleryItem::draw() border.mTop = border.mTop + 1; gl_rect_2d(border, border_color.get(), FALSE); } - - } void LLInventoryGalleryItem::setItemName(std::string name) @@ -2379,7 +2612,18 @@ BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) { // call changeItemSelection directly, before setFocus // to avoid autoscroll from LLInventoryGallery::onFocusReceived() - mGallery->changeItemSelection(mUUID, false); + if (mask == MASK_CONTROL) + { + mGallery->addItemSelection(mUUID, false); + } + else if (mask == MASK_SHIFT) + { + mGallery->toggleSelectionRangeFromLast(mUUID); + } + else + { + mGallery->changeItemSelection(mUUID, false); + } setFocus(TRUE); mGallery->claimEditHandler(); @@ -2496,22 +2740,22 @@ BOOL LLInventoryGalleryItem::handleKeyHere(KEY key, MASK mask) switch (key) { case KEY_LEFT: - mGallery->moveLeft(); + mGallery->moveLeft(mask); handled = true; break; case KEY_RIGHT: - mGallery->moveRight(); + mGallery->moveRight(mask); handled = true; break; case KEY_UP: - mGallery->moveUp(); + mGallery->moveUp(mask); handled = true; break; case KEY_DOWN: - mGallery->moveDown(); + mGallery->moveDown(mask); handled = true; break; @@ -2525,7 +2769,6 @@ void LLInventoryGalleryItem::onFocusLost() { // inventory no longer handles cut/copy/paste/delete mGallery->resetEditHandler(); - setSelected(false); LLPanel::onFocusLost(); } @@ -2534,7 +2777,6 @@ void LLInventoryGalleryItem::onFocusReceived() { // inventory now handles cut/copy/paste/delete mGallery->claimEditHandler(); - setSelected(true); LLPanel::onFocusReceived(); } @@ -2649,6 +2891,11 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, { LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; + if (drop && LLToolDragAndDrop::getInstance()->getCargoIndex() == 0) + { + clearSelection(); + } + BOOL accepted = FALSE; switch(cargo_type) { @@ -2669,8 +2916,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, if (accepted && drop) { // Don't select immediately, wait for item to arrive - mItemToSelect = inv_item->getUUID(); - mNeedsSelection = true; + mItemsToSelect.push_back(inv_item->getUUID()); } break; case DAD_LINK: @@ -2691,8 +2937,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, } if (accepted && drop && inv_item) { - mItemToSelect = inv_item->getUUID(); - mNeedsSelection = true; + mItemsToSelect.push_back(inv_item->getUUID()); } break; case DAD_CATEGORY: @@ -2706,8 +2951,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, accepted = dragCategoryIntoFolder(dest_id, cat_ptr, drop, tooltip_msg, FALSE); if (accepted && drop) { - mItemToSelect = cat_ptr->getUUID(); - mNeedsSelection = true; + mItemsToSelect.push_back(cat_ptr->getUUID()); } } break; diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index f2e5e38940..44e0dcf960 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -82,10 +82,12 @@ public: void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) override; BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; BOOL handleKeyHere(KEY key, MASK mask) override; - void moveUp(); - void moveDown(); - void moveLeft(); - void moveRight(); + void moveUp(MASK mask); + void moveDown(MASK mask); + void moveLeft(MASK mask); + void moveRight(MASK mask); + void toggleSelectionRange(S32 start_idx, S32 end_idx); + void toggleSelectionRangeFromLast(const LLUUID target); void onFocusLost() override; void onFocusReceived() override; @@ -130,6 +132,8 @@ public: void deselectItem(const LLUUID& category_id); void clearSelection(); void changeItemSelection(const LLUUID& item_id, bool scroll_to_selection = false); + void addItemSelection(const LLUUID& item_id, bool scroll_to_selection = false); + bool toggleItemSelection(const LLUUID& item_id, bool scroll_to_selection = false); void scrollToShowItem(const LLUUID& item_id); void signalSelectionItemID(const LLUUID& category_id); boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb); @@ -174,6 +178,15 @@ public: void showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id); protected: + void paste(const LLUUID& dest, + std::vector& objects, + bool is_cut_mode, + const LLUUID& marketplacelistings_id); + void pasteAsLink(const LLUUID& dest, + std::vector& objects, + const LLUUID& current_outfit_id, + const LLUUID& marketplacelistings_id, + const LLUUID& my_outifts_id); bool applyFilter(LLInventoryGalleryItem* item, const std::string& filter_substring); bool checkAgainstFilters(LLInventoryGalleryItem* item, const std::string& filter_substring); @@ -185,8 +198,8 @@ protected: LLGalleryGestureObserver* mGestureObserver; LLInventoryObserver* mInventoryObserver; selection_deque mSelectedItemIDs; - LLUUID mItemToSelect; - bool mNeedsSelection; + selection_deque mItemsToSelect; + LLUUID mLastSelectedUUID; bool mIsInitialized; bool mRootDirty; diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index bca10b9c0e..5f4b816b99 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -51,16 +51,17 @@ LLContextMenu* LLInventoryGalleryContextMenu::createMenu() { LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - //LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - LLUUID selected_id = mUUIDs.front(); + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - registrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryGalleryContextMenu::doToSelected, this, _2, selected_id)); - registrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::fileUploadLocation, this, _2, selected_id)); + registrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryGalleryContextMenu::doToSelected, this, _2)); + registrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::fileUploadLocation, this, _2)); registrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH)); registrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)); - std::set uuids{selected_id}; + std::set uuids(mUUIDs.begin(), mUUIDs.end()); registrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, uuids, gFloaterView->getParentFloater(mGallery))); + + enable_registrar.add("Inventory.CanSetUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::canSetUploadLocation, this, _2)); LLContextMenu* menu = createFromFile("menu_gallery_inventory.xml"); @@ -69,49 +70,52 @@ LLContextMenu* LLInventoryGalleryContextMenu::createMenu() return menu; } -void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLUUID& selected_id) +void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata) { std::string action = userdata.asString(); - LLInventoryObject* obj = gInventory.getObject(selected_id); + LLInventoryObject* obj = gInventory.getObject(mUUIDs.front()); if(!obj) return; if ("open_selected_folder" == action) { - mGallery->setRootFolder(selected_id); + mGallery->setRootFolder(mUUIDs.front()); } else if ("open_in_new_window" == action) { - new_folder_window(selected_id); + new_folder_window(mUUIDs.front()); } else if ("properties" == action) { - show_item_profile(selected_id); + show_item_profile(mUUIDs.front()); } else if ("restore" == action) { - LLViewerInventoryCategory* cat = gInventory.getCategory(selected_id); - if(cat) + for (LLUUID& selected_id : mUUIDs) { - const LLUUID new_parent = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType())); - // do not restamp children on restore - gInventory.changeCategoryParent(cat, new_parent, false); - } - else - { - LLViewerInventoryItem* item = gInventory.getItem(selected_id); - if(item) + LLViewerInventoryCategory* cat = gInventory.getCategory(selected_id); + if (cat) { - bool is_snapshot = (item->getInventoryType() == LLInventoryType::IT_SNAPSHOT); - - const LLUUID new_parent = gInventory.findCategoryUUIDForType(is_snapshot? LLFolderType::FT_SNAPSHOT_CATEGORY : LLFolderType::assetTypeToFolderType(item->getType())); + const LLUUID new_parent = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType())); // do not restamp children on restore - gInventory.changeItemParent(item, new_parent, false); + gInventory.changeCategoryParent(cat, new_parent, false); + } + else + { + LLViewerInventoryItem* item = gInventory.getItem(selected_id); + if (item) + { + bool is_snapshot = (item->getInventoryType() == LLInventoryType::IT_SNAPSHOT); + + const LLUUID new_parent = gInventory.findCategoryUUIDForType(is_snapshot ? LLFolderType::FT_SNAPSHOT_CATEGORY : LLFolderType::assetTypeToFolderType(item->getType())); + // do not restamp children on restore + gInventory.changeItemParent(item, new_parent, false); + } } } } else if ("copy_uuid" == action) { - LLViewerInventoryItem* item = gInventory.getItem(selected_id); + LLViewerInventoryItem* item = gInventory.getItem(mUUIDs.front()); if(item) { LLUUID asset_id = item->getProtectedAssetUUID(); @@ -123,15 +127,18 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } else if ("purge" == action) { - remove_inventory_object(selected_id, NULL); + for (LLUUID& selected_id : mUUIDs) + { + remove_inventory_object(selected_id, NULL); + } } else if ("goto" == action) { - show_item_original(selected_id); + show_item_original(mUUIDs.front()); } else if ("thumbnail" == action) { - LLSD data(selected_id); + LLSD data(mUUIDs.front()); LLFloaterReg::showInstance("change_item_thumbnail", data); } else if ("cut" == action) @@ -165,61 +172,70 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } else if ("rename" == action) { - LLSD args; - args["NAME"] = obj->getName(); - - LLSD payload; - payload["id"] = selected_id; - - LLNotificationsUtil::add("RenameItem", args, payload, boost::bind(onRename, _1, _2)); + rename(mUUIDs.front()); } else if ("open" == action || "open_original" == action) { - LLViewerInventoryItem* item = gInventory.getItem(selected_id); + LLViewerInventoryItem* item = gInventory.getItem(mUUIDs.front()); if (item) { - LLInvFVBridgeAction::doAction(item->getType(), selected_id , &gInventory); + LLInvFVBridgeAction::doAction(item->getType(), mUUIDs.front(), &gInventory); } } else if ("ungroup_folder_items" == action) { - ungroup_folder_items(selected_id); + ungroup_folder_items(mUUIDs.front()); } else if ("take_off" == action || "detach" == action) { - LLAppearanceMgr::instance().removeItemFromAvatar(selected_id); + for (LLUUID& selected_id : mUUIDs) + { + LLAppearanceMgr::instance().removeItemFromAvatar(selected_id); + } } else if ("wear_add" == action) { - LLAppearanceMgr::instance().wearItemOnAvatar(selected_id, true, false); // Don't replace if adding. + for (LLUUID& selected_id : mUUIDs) + { + LLAppearanceMgr::instance().wearItemOnAvatar(selected_id, true, false); // Don't replace if adding. + } } else if ("wear" == action) { - LLAppearanceMgr::instance().wearItemOnAvatar(selected_id, true, true); + for (LLUUID& selected_id : mUUIDs) + { + LLAppearanceMgr::instance().wearItemOnAvatar(selected_id, true, true); + } } else if ("activate" == action) { - LLGestureMgr::instance().activateGesture(selected_id); + for (LLUUID& selected_id : mUUIDs) + { + LLGestureMgr::instance().activateGesture(selected_id); - LLViewerInventoryItem* item = gInventory.getItem(selected_id); - if (!item) return; + LLViewerInventoryItem* item = gInventory.getItem(selected_id); + if (!item) return; - gInventory.updateItem(item); + gInventory.updateItem(item); + } gInventory.notifyObservers(); } else if ("deactivate" == action) { - LLGestureMgr::instance().deactivateGesture(selected_id); + for (LLUUID& selected_id : mUUIDs) + { + LLGestureMgr::instance().deactivateGesture(selected_id); - LLViewerInventoryItem* item = gInventory.getItem(selected_id); - if (!item) return; + LLViewerInventoryItem* item = gInventory.getItem(selected_id); + if (!item) return; - gInventory.updateItem(item); + gInventory.updateItem(item); + } gInventory.notifyObservers(); } else if ("replace_links" == action) { - LLFloaterReg::showInstance("linkreplace", LLSD(selected_id)); + LLFloaterReg::showInstance("linkreplace", LLSD(mUUIDs.front())); } else if ("copy_slurl" == action) { @@ -236,7 +252,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU }; LLLandmarkActions::getSLURLfromPosGlobal(global_pos, copy_slurl_to_clipboard_cb, true); }; - LLLandmark* landmark = LLLandmarkActions::getLandmark(selected_id, copy_slurl_cb); + LLLandmark* landmark = LLLandmarkActions::getLandmark(mUUIDs.front(), copy_slurl_cb); if (landmark) { copy_slurl_cb(landmark); @@ -246,7 +262,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU { LLSD key; key["type"] = "landmark"; - key["id"] = selected_id; + key["id"] = mUUIDs.front(); LLFloaterSidePanelContainer::showPanel("places", key); } else if ("show_on_map" == action) @@ -264,7 +280,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } } }; - LLLandmark* landmark = LLLandmarkActions::getLandmark(selected_id, show_on_map_cb); + LLLandmark* landmark = LLLandmarkActions::getLandmark(mUUIDs.front(), show_on_map_cb); if(landmark) { show_on_map_cb(landmark); @@ -272,7 +288,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } else if ("save_as" == action) { - LLPreviewTexture* preview_texture = LLFloaterReg::getTypedInstance("preview_texture", selected_id); + LLPreviewTexture* preview_texture = LLFloaterReg::getTypedInstance("preview_texture", mUUIDs.front()); if (preview_texture) { preview_texture->openToSave(); @@ -281,6 +297,20 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata, const LLU } } +void LLInventoryGalleryContextMenu::rename(const LLUUID& item_id) +{ + LLInventoryObject* obj = gInventory.getObject(item_id); + if (!obj) return; + + LLSD args; + args["NAME"] = obj->getName(); + + LLSD payload; + payload["id"] = mUUIDs.front(); + + LLNotificationsUtil::add("RenameItem", args, payload, boost::bind(onRename, _1, _2)); +} + void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); @@ -311,25 +341,39 @@ void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLS } } -void LLInventoryGalleryContextMenu::fileUploadLocation(const LLSD& userdata, const LLUUID& selected_id) +void LLInventoryGalleryContextMenu::fileUploadLocation(const LLSD& userdata) { const std::string param = userdata.asString(); if (param == "model") { - gSavedPerAccountSettings.setString("ModelUploadFolder", selected_id.asString()); + gSavedPerAccountSettings.setString("ModelUploadFolder", mUUIDs.front().asString()); } else if (param == "texture") { - gSavedPerAccountSettings.setString("TextureUploadFolder", selected_id.asString()); + gSavedPerAccountSettings.setString("TextureUploadFolder", mUUIDs.front().asString()); } else if (param == "sound") { - gSavedPerAccountSettings.setString("SoundUploadFolder", selected_id.asString()); + gSavedPerAccountSettings.setString("SoundUploadFolder", mUUIDs.front().asString()); } else if (param == "animation") { - gSavedPerAccountSettings.setString("AnimationUploadFolder", selected_id.asString()); + gSavedPerAccountSettings.setString("AnimationUploadFolder", mUUIDs.front().asString()); + } +} + +bool LLInventoryGalleryContextMenu::canSetUploadLocation(const LLSD& userdata) +{ + if (mUUIDs.size() != 1) + { + return false; + } + LLInventoryCategory* cat = gInventory.getCategory(mUUIDs.front()); + if (!cat) + { + return false; } + return true; } bool is_inbox_folder(LLUUID item_id) diff --git a/indra/newview/llinventorygallerymenu.h b/indra/newview/llinventorygallerymenu.h index 67cf9a569a..7c3545432b 100644 --- a/indra/newview/llinventorygallerymenu.h +++ b/indra/newview/llinventorygallerymenu.h @@ -39,13 +39,15 @@ public: bool isRootFolder() { return mRootFolder; } void setRootFolder(bool is_root) { mRootFolder = is_root; } - void doToSelected(const LLSD& userdata, const LLUUID& selected_id); + void doToSelected(const LLSD& userdata); + void rename(const LLUUID& item_id); protected: //virtual void buildContextMenu(class LLMenuGL& menu, U32 flags); void updateMenuItemsVisibility(LLContextMenu* menu); - void fileUploadLocation(const LLSD& userdata, const LLUUID& selected_id); + void fileUploadLocation(const LLSD& userdata); + bool canSetUploadLocation(const LLSD& userdata); static void onRename(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml b/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml index 46afa3821b..d82c453e5f 100644 --- a/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml @@ -453,30 +453,38 @@ + - + + - + + - + +