diff options
author | Maxim Nikolenko <maximnproductengine@lindenlab.com> | 2023-03-29 13:51:40 +0300 |
---|---|---|
committer | Maxim Nikolenko <maximnproductengine@lindenlab.com> | 2023-03-29 13:51:40 +0300 |
commit | e5b8b799cc75f3b9cd259403c323cd47b59453d8 (patch) | |
tree | efd077f3b8677f806a7c9a715b2a4cb6d4c3f8b3 /indra | |
parent | 11b2f138cecc123c3e6876b56ea63c5fbd734d56 (diff) |
SL-19379 WIP add basic context menu
Diffstat (limited to 'indra')
-rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/newview/llavataractions.cpp | 160 | ||||
-rw-r--r-- | indra/newview/llavataractions.h | 1 | ||||
-rw-r--r-- | indra/newview/llinventoryfunctions.cpp | 70 | ||||
-rw-r--r-- | indra/newview/llinventoryfunctions.h | 2 | ||||
-rw-r--r-- | indra/newview/llinventorygallery.cpp | 18 | ||||
-rw-r--r-- | indra/newview/llinventorygallery.h | 5 | ||||
-rw-r--r-- | indra/newview/llinventorygallerymenu.cpp | 616 | ||||
-rw-r--r-- | indra/newview/llinventorygallerymenu.h | 55 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/menu_gallery_inventory.xml | 531 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 23 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/panel_inventory_gallery.xml | 2 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/panel_inventory_gallery_item.xml | 4 |
13 files changed, 1393 insertions, 96 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index d587f8bfc4..1d7c238629 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -381,6 +381,7 @@ set(viewer_SOURCE_FILES llinventoryfilter.cpp llinventoryfunctions.cpp llinventorygallery.cpp + llinventorygallerymenu.cpp llinventoryicon.cpp llinventoryitemslist.cpp llinventorylistitem.cpp @@ -1025,6 +1026,7 @@ set(viewer_HEADER_FILES llinventoryfilter.h llinventoryfunctions.h llinventorygallery.h + llinventorygallerymenu.h llinventoryicon.h llinventoryitemslist.h llinventorylistitem.h diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 3e450e6dec..6bd2b8bbee 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -730,6 +730,37 @@ namespace action_give_inventory /** * Checks My Inventory visibility. */ + static bool is_give_inventory_acceptable_ids(const std::set<LLUUID> inventory_selected_uuids) + { + if (inventory_selected_uuids.empty()) return false; // nothing selected + + bool acceptable = false; + std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); + const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end(); + for (; it != it_end; ++it) + { + LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); + // any category can be offered. + if (inv_cat) + { + acceptable = true; + continue; + } + + LLViewerInventoryItem* inv_item = gInventory.getItem(*it); + // check if inventory item can be given + if (LLGiveInventory::isInventoryGiveAcceptable(inv_item)) + { + acceptable = true; + continue; + } + + // there are neither item nor category in inventory + acceptable = false; + break; + } + return acceptable; + } static bool is_give_inventory_acceptable(LLInventoryPanel* panel = NULL) { @@ -737,32 +768,7 @@ namespace action_give_inventory const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(panel); if (inventory_selected_uuids.empty()) return false; // nothing selected - bool acceptable = false; - std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); - const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end(); - for (; it != it_end; ++it) - { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); - // any category can be offered. - if (inv_cat) - { - acceptable = true; - continue; - } - - LLViewerInventoryItem* inv_item = gInventory.getItem(*it); - // check if inventory item can be given - if (LLGiveInventory::isInventoryGiveAcceptable(inv_item)) - { - acceptable = true; - continue; - } - - // there are neither item nor category in inventory - acceptable = false; - break; - } - return acceptable; + return is_give_inventory_acceptable_ids(inventory_selected_uuids); } static void build_items_string(const std::set<LLUUID>& inventory_selected_uuids , std::string& items_string) @@ -890,46 +896,58 @@ namespace action_give_inventory * @param avatar_names - avatar names request to be sent. * @param avatar_uuids - avatar names request to be sent. */ - static void give_inventory(const uuid_vec_t& avatar_uuids, const std::vector<LLAvatarName> avatar_names, LLInventoryPanel* panel = NULL) - { - llassert(avatar_names.size() == avatar_uuids.size()); - const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(panel); - if (inventory_selected_uuids.empty()) - { - return; - } + static void give_inventory_ids(const uuid_vec_t& avatar_uuids, const std::vector<LLAvatarName> avatar_names, const uuid_set_t inventory_selected_uuids) + { + llassert(avatar_names.size() == avatar_uuids.size()); - std::string residents; - LLAvatarActions::buildResidentsString(avatar_names, residents, true); + if (inventory_selected_uuids.empty()) + { + return; + } - std::string items; - build_items_string(inventory_selected_uuids, items); + std::string residents; + LLAvatarActions::buildResidentsString(avatar_names, residents, true); - int folders_count = 0; - std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); + std::string items; + build_items_string(inventory_selected_uuids, items); - //traverse through selected inventory items and count folders among them - for ( ; it != inventory_selected_uuids.end() && folders_count <=1 ; ++it) - { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); - if (NULL != inv_cat) - { - folders_count++; - } - } + int folders_count = 0; + std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); - // EXP-1599 - // In case of sharing multiple folders, make the confirmation - // dialog contain a warning that only one folder can be shared at a time. - std::string notification = (folders_count > 1) ? "ShareFolderConfirmation" : "ShareItemsConfirmation"; - LLSD substitutions; - substitutions["RESIDENTS"] = residents; - substitutions["ITEMS"] = items; - LLShareInfo::instance().mAvatarNames = avatar_names; - LLShareInfo::instance().mAvatarUuids = avatar_uuids; - LLNotificationsUtil::add(notification, substitutions, LLSD(), boost::bind(&give_inventory_cb, _1, _2, inventory_selected_uuids)); - } + //traverse through selected inventory items and count folders among them + for ( ; it != inventory_selected_uuids.end() && folders_count <=1 ; ++it) + { + LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); + if (NULL != inv_cat) + { + folders_count++; + } + } + + // EXP-1599 + // In case of sharing multiple folders, make the confirmation + // dialog contain a warning that only one folder can be shared at a time. + std::string notification = (folders_count > 1) ? "ShareFolderConfirmation" : "ShareItemsConfirmation"; + LLSD substitutions; + substitutions["RESIDENTS"] = residents; + substitutions["ITEMS"] = items; + LLShareInfo::instance().mAvatarNames = avatar_names; + LLShareInfo::instance().mAvatarUuids = avatar_uuids; + LLNotificationsUtil::add(notification, substitutions, LLSD(), boost::bind(&give_inventory_cb, _1, _2, inventory_selected_uuids)); + } + + static void give_inventory(const uuid_vec_t& avatar_uuids, const std::vector<LLAvatarName> avatar_names, LLInventoryPanel* panel = NULL) + { + llassert(avatar_names.size() == avatar_uuids.size()); + + const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(panel); + if (inventory_selected_uuids.empty()) + { + return; + } + give_inventory_ids(avatar_uuids, avatar_names, inventory_selected_uuids); + } } // static @@ -1037,6 +1055,28 @@ void LLAvatarActions::shareWithAvatars(LLView * panel) LLNotificationsUtil::add("ShareNotification"); } +//static +void LLAvatarActions::shareWithAvatars(const uuid_set_t inventory_selected_uuids, LLFloater* root_floater) +{ + using namespace action_give_inventory; + + LLFloaterAvatarPicker* picker = + LLFloaterAvatarPicker::show(boost::bind(give_inventory_ids, _1, _2, inventory_selected_uuids), TRUE, FALSE, FALSE, root_floater->getName()); + if (!picker) + { + return; + } + + picker->setOkBtnEnableCb(boost::bind(is_give_inventory_acceptable_ids, inventory_selected_uuids)); + picker->openFriendsTab(); + + if (root_floater) + { + root_floater->addDependentFloater(picker); + } + LLNotificationsUtil::add("ShareNotification"); +} + // static bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NULL*/) { diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 86183cc119..8a0f40dd52 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -133,6 +133,7 @@ public: * Share items with the picked avatars. */ static void shareWithAvatars(LLView * panel); + static void shareWithAvatars(const uuid_set_t inventory_selected_uuids, LLFloater* root_floater); /** * Block/unblock the avatar by id. diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index fbcce5f078..d38208da71 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -2125,6 +2125,45 @@ std::string get_localized_folder_name(LLUUID cat_uuid) return localized_root_name; } + +void new_folder_window(const LLUUID& folder_id) +{ + LLPanelMainInventory::newFolderWindow(folder_id); +} + +void ungroup_folder_items(const LLUUID& folder_id) +{ + LLInventoryCategory* inv_cat = gInventory.getCategory(folder_id); + if (!inv_cat || LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())) + { + return; + } + const LLUUID &new_cat_uuid = inv_cat->getParentUUID(); + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cat_array, item_array); + LLInventoryModel::cat_array_t cats = *cat_array; + LLInventoryModel::item_array_t items = *item_array; + + for (LLInventoryModel::cat_array_t::const_iterator cat_iter = cats.begin(); cat_iter != cats.end(); ++cat_iter) + { + LLViewerInventoryCategory* cat = *cat_iter; + if (cat) + { + gInventory.changeCategoryParent(cat, new_cat_uuid, false); + } + } + for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin(); item_iter != items.end(); ++item_iter) + { + LLViewerInventoryItem* item = *item_iter; + if(item) + { + gInventory.changeItemParent(item, new_cat_uuid, false); + } + } + gInventory.removeCategory(inv_cat->getUUID()); + gInventory.notifyObservers(); +} ///---------------------------------------------------------------------------- /// LLMarketplaceValidator implementations ///---------------------------------------------------------------------------- @@ -2977,36 +3016,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root { if (selected_uuid_set.size() == 1) { - LLInventoryCategory* inv_cat = gInventory.getCategory(*ids.begin()); - if (!inv_cat || LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())) - { - return; - } - const LLUUID &new_cat_uuid = inv_cat->getParentUUID(); - LLInventoryModel::cat_array_t* cat_array; - LLInventoryModel::item_array_t* item_array; - gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cat_array, item_array); - LLInventoryModel::cat_array_t cats = *cat_array; - LLInventoryModel::item_array_t items = *item_array; - - for (LLInventoryModel::cat_array_t::const_iterator cat_iter = cats.begin(); cat_iter != cats.end(); ++cat_iter) - { - LLViewerInventoryCategory* cat = *cat_iter; - if (cat) - { - gInventory.changeCategoryParent(cat, new_cat_uuid, false); - } - } - for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin(); item_iter != items.end(); ++item_iter) - { - LLViewerInventoryItem* item = *item_iter; - if(item) - { - gInventory.changeItemParent(item, new_cat_uuid, false); - } - } - gInventory.removeCategory(inv_cat->getUUID()); - gInventory.notifyObservers(); + ungroup_folder_items(*ids.begin()); } } else diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index f7755be1dd..5f1c5067d5 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -101,6 +101,8 @@ bool can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_out bool can_move_to_landmarks(LLInventoryItem* inv_item); bool can_move_to_my_outfits(LLInventoryModel* model, LLInventoryCategory* inv_cat, U32 wear_limit); std::string get_localized_folder_name(LLUUID cat_uuid); +void new_folder_window(const LLUUID& folder_id); +void ungroup_folder_items(const LLUUID& folder_id); /** Miscellaneous global functions ** ** diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 08836555d4..bfca22ba8a 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -27,8 +27,8 @@ #include "llviewerprecompiledheaders.h" #include "llinventorygallery.h" +#include "llinventorygallerymenu.h" -#include "llaccordionctrltab.h" #include "llcommonutils.h" #include "lliconctrl.h" #include "llinventorybridge.h" @@ -115,12 +115,14 @@ BOOL LLInventoryGallery::postBuild() LLPanel::Params params = LLPanel::getDefaultParams(); mGalleryPanel = LLUICtrlFactory::create<LLPanel>(params); mMessageTextBox = getChild<LLTextBox>("empty_txt"); - + mInventoryGalleryMenu = new LLInventoryGalleryContextMenu(this); return TRUE; } LLInventoryGallery::~LLInventoryGallery() { + delete mInventoryGalleryMenu; + while (!mUnusedRowPanels.empty()) { LLPanel* panelp = mUnusedRowPanels.back(); @@ -600,7 +602,7 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, obj->getIsLinkType()); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); - + item->setRightMouseDownCallback(boost::bind(&LLInventoryGallery::showContextMenu, this, _1, _2, _3, item_id)); item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::onChangeItemSelection, this, item_id)); if (mGalleryCreated) { @@ -671,6 +673,16 @@ void LLInventoryGallery::updateItemThumbnail(LLUUID item_id) } } +void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id) +{ + if (mInventoryGalleryMenu && item_id.notNull()) + { + uuid_vec_t selected_uuids; + selected_uuids.push_back(item_id); + mInventoryGalleryMenu->show(ctrl, selected_uuids, x, y); + } +} + void LLInventoryGallery::onChangeItemSelection(const LLUUID& category_id) { if (mSelectedItemID == category_id) diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index 1c45a8345f..5c529e7589 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -27,6 +27,7 @@ #ifndef LL_LLINVENTORYGALLERY_H #define LL_LLINVENTORYGALLERY_H +#include "lllistcontextmenu.h" #include "llpanel.h" #include "llinventorymodel.h" @@ -35,6 +36,8 @@ class LLInventoryGalleryItem; class LLScrollContainer; class LLTextBox; +class LLInventoryGalleryContextMenu; + class LLInventoryGallery : public LLPanel { public: @@ -108,6 +111,7 @@ public: protected: void onChangeItemSelection(const LLUUID& category_id); + void showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id); void applyFilter(LLInventoryGalleryItem* item, const std::string& filter_substring); @@ -171,6 +175,7 @@ private: int mRowPanWidthFactor; int mGalleryWidthFactor; + LLInventoryGalleryContextMenu* mInventoryGalleryMenu; std::string mFilterSubString; typedef std::map<LLUUID, LLInventoryGalleryItem*> gallery_item_map_t; 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<LLUUID> 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<LLUUID> objects; + LLClipboard::instance().pasteFromClipboard(objects); + for (std::vector<LLUUID>::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<LLInventoryCallback>(NULL)); + } + else + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + selected_id, + std::string(), + LLPointer<LLInventoryCallback>(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<LLInventoryCallback>(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<std::string> items; + std::vector<std::string> 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<bool> 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); +} + diff --git a/indra/newview/llinventorygallerymenu.h b/indra/newview/llinventorygallerymenu.h new file mode 100644 index 0000000000..1768c07e6e --- /dev/null +++ b/indra/newview/llinventorygallerymenu.h @@ -0,0 +1,55 @@ +/** + * @file llinventorygallerymenu.h + * + * $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$ + */ + +#ifndef LL_LLINVENTORYGALLERYMENU_H +#define LL_LLINVENTORYGALLERYMENU_H + +#include "lllistcontextmenu.h" + +class LLInventoryGalleryContextMenu : public LLListContextMenu +{ +public: + LLInventoryGalleryContextMenu(LLInventoryGallery* gallery) + : LLListContextMenu(), + mGallery(gallery){} + /*virtual*/ LLContextMenu* createMenu(); + +protected: + //virtual void buildContextMenu(class LLMenuGL& menu, U32 flags); + void updateMenuItemsVisibility(LLContextMenu* menu); + + void doToSelected(const LLSD& userdata, const LLUUID& selected_id); + void fileUploadLocation(const LLSD& userdata, const LLUUID& selected_id); + + static void onRename(const LLSD& notification, const LLSD& response); + +private: + bool enableContextMenuItem(const LLSD& userdata); + bool checkContextMenuItem(const LLSD& userdata); + + LLInventoryGallery* mGallery; +}; + +#endif diff --git a/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml b/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml new file mode 100644 index 0000000000..15466e8f32 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml @@ -0,0 +1,531 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<context_menu + layout="topleft" + name="Gallery"> + <menu_item_call + label="Share" + layout="topleft" + name="Share"> + <menu_item_call.on_click + function="Inventory.Share" /> + </menu_item_call> + <menu_item_call + label="Empty Trash" + layout="topleft" + name="Empty Trash"> + <menu_item_call.on_click + function="Inventory.EmptyTrash"/> + </menu_item_call> + <menu_item_call + label="Empty Lost And Found" + layout="topleft" + name="Empty Lost And Found"> + <menu_item_call.on_click + function="Inventory.EmptyLostAndFound"/> + </menu_item_call> + <menu_item_call + label="New Folder" + layout="topleft" + name="New Folder"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="category" /> + </menu_item_call> + <menu_item_call + label="New Outfit" + layout="topleft" + name="New Outfit"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="outfit" /> + </menu_item_call> + <menu_item_call + label="Teleport" + layout="topleft" + name="Landmark Open"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="open" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Folder Wearables Separator" /> + <menu_item_call + label="Replace Current Outfit" + layout="topleft" + name="Replace Outfit"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="replaceoutfit" /> + </menu_item_call> + <menu_item_call + label="Add To Current Outfit" + layout="topleft" + name="Add To Outfit"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="addtooutfit" /> + </menu_item_call> + <menu_item_call + label="Remove From Current Outfit" + layout="topleft" + name="Remove From Outfit"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="removefromoutfit" /> + </menu_item_call> + <menu_item_call + label="Copy outfit list to clipboard" + layout="topleft" + name="Copy outfit list to clipboard"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="copyoutfittoclipboard" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Outfit Separator" /> + <menu_item_call + label="Find Original" + layout="topleft" + name="Find Original"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="goto" /> + </menu_item_call> + <menu_item_call + label="Purge Item" + layout="topleft" + name="Purge Item"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="purge"/> + </menu_item_call> + <menu_item_call + label="Restore Item" + layout="topleft" + name="Restore Item"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="restore" /> + </menu_item_call> + <menu_item_call + label="Open" + layout="topleft" + name="Open"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="open" /> + </menu_item_call> + <menu_item_call + label="Open Original" + layout="topleft" + name="Open Original"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="open_original" /> + </menu_item_call> + <menu_item_call + label="Properties" + layout="topleft" + name="Properties"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="properties" /> + </menu_item_call> + <menu_item_call + label="Image..." + layout="topleft" + name="thumbnail"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="thumbnail" /> + </menu_item_call> + <menu_item_call + label="Copy Asset UUID" + layout="topleft" + name="Copy Asset UUID"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="copy_uuid" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Copy Separator" /> + <menu_item_call + label="Open" + layout="topleft" + name="open_in_current_window"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="open_selected_folder" /> + </menu_item_call> + <menu_item_call + label="Open in new window" + layout="topleft" + name="open_in_new_window"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="open_in_new_window" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Open Folder Separator" /> + <menu_item_call + label="Rename" + layout="topleft" + name="Rename"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="rename" /> + </menu_item_call> + <menu_item_call + label="Cut" + layout="topleft" + name="Cut"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="cut" /> + </menu_item_call> + <menu_item_call + label="Copy" + layout="topleft" + name="Copy"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="copy" /> + </menu_item_call> + <menu_item_call + label="Paste" + layout="topleft" + name="Paste"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="paste" /> + </menu_item_call> + <menu_item_call + label="Paste As Link" + layout="topleft" + name="Paste As Link"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="paste_link" /> + </menu_item_call> + <menu_item_call + label="Replace Links" + layout="topleft" + name="Replace Links"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="replace_links" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Paste Separator" /> + <menu_item_call + label="Delete" + layout="topleft" + name="Delete"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="delete" /> + </menu_item_call> + <menu_item_call + label="Delete System Folder" + layout="topleft" + name="Delete System Folder"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="delete_system_folder" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_separator + layout="topleft" /> + <menu_item_call + label="Play" + layout="topleft" + name="Sound Play"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="sound_play" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Landmark Separator" /> + <menu_item_call + label="Copy SLurl" + layout="topleft" + name="url_copy"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="copy_slurl" /> + </menu_item_call> + <menu_item_call + label="About Landmark" + layout="topleft" + name="About Landmark"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="about" /> + </menu_item_call> + <menu_item_call + label="Show on Map" + layout="topleft" + name="show_on_map"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="show_on_map" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Animation Separator" /> + <menu_item_call + label="Play Inworld" + layout="topleft" + name="Animation Play"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="playworld" /> + </menu_item_call> + <menu_item_call + label="Play Locally" + layout="topleft" + name="Animation Audition"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="playlocal" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Send Instant Message Separator" /> + <menu_item_call + label="Send Instant Message" + layout="topleft" + name="Send Instant Message"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="begin_im" /> + </menu_item_call> + <menu_item_call + label="Offer Teleport..." + layout="topleft" + name="Offer Teleport..."> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="lure" /> + </menu_item_call> + <menu_item_call + label="Request Teleport..." + layout="topleft" + name="Request Teleport..."> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="request_lure" /> + </menu_item_call> + <menu_item_call + label="Start Conference Chat" + layout="topleft" + name="Conference Chat"> + <menu_item_call.on_click + function="Inventory.BeginIMSession" + parameter="selected" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Gesture Separator" /> + <menu_item_call + label="Activate" + layout="topleft" + name="Activate"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="activate" /> + </menu_item_call> + <menu_item_call + label="Deactivate" + layout="topleft" + name="Deactivate"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="deactivate" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Texture Separator" /> + <menu_item_call + label="Save As" + layout="topleft" + name="Save As"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="save_as" /> + </menu_item_call> + <menu_item_call + label="Save Selected As" + layout="topleft" + name="Save Selected As"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="save_selected_as" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Wearable And Object Separator"/> + <menu_item_call + label="Wear" + layout="topleft" + name="Wearable And Object Wear"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="wear" /> + </menu_item_call> + <menu + label="Attach To" + layout="topleft" + name="Attach To" /> + <menu + label="Attach To HUD" + layout="topleft" + name="Attach To HUD" /> + <menu_item_call + label="Touch" + layout="topleft" + name="Attachment Touch"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="touch" /> + </menu_item_call> + <menu_item_call + label="Edit" + layout="topleft" + name="Wearable Edit"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="edit" /> + </menu_item_call> + <menu_item_call + label="Add" + layout="topleft" + name="Wearable Add"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="wear_add" /> + </menu_item_call> + <menu_item_call + label="Detach From Yourself" + layout="topleft" + name="Detach From Yourself"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="detach" /> + </menu_item_call> + <menu_item_call + label="Take Off" + layout="topleft" + name="Take Off"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="take_off" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Settings Separator" /> + <menu_item_call + name="Settings Apply Local" + layout="topleft" + label="Apply Only To Myself"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="apply_settings_local" /> + </menu_item_call> + <menu_item_call + name="Settings Apply Parcel" + layout="topleft" + label="Apply To Parcel"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="apply_settings_parcel" /> + </menu_item_call> + <menu_item_separator + layout="topleft" + name="Subfolder Separator" /> + <menu_item_call + label="Create folder from selected" + layout="topleft" + name="New folder from selected"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="new_folder_from_selected" /> + </menu_item_call> + <menu_item_call + label="Ungroup folder items" + layout="topleft" + name="Ungroup folder items"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="ungroup_folder_items" /> + </menu_item_call> + <menu + label="Use as default for" + layout="topleft" + name="upload_def"> + <menu_item_call + label="Image uploads" + layout="topleft" + name="Image uploads"> + <menu_item_call.on_click + function="Inventory.FileUploadLocation" + parameter="texture" /> + </menu_item_call> + <menu_item_call + label="Sound uploads" + layout="topleft" + name="Sound uploads"> + <menu_item_call.on_click + function="Inventory.FileUploadLocation" + parameter="sound" /> + </menu_item_call> + <menu_item_call + label="Animation uploads" + layout="topleft" + name="Animation uploads"> + <menu_item_call.on_click + function="Inventory.FileUploadLocation" + parameter="animation" /> + </menu_item_call> + <menu_item_call + label="Model uploads" + layout="topleft" + name="Model uploads"> + <menu_item_call.on_click + function="Inventory.FileUploadLocation" + parameter="model" /> + </menu_item_call> + </menu> + <menu_item_separator + layout="topleft" + name="Marketplace Separator" /> + <menu_item_call + label="Copy to Marketplace Listings" + layout="topleft" + name="Marketplace Copy"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="copy_to_marketplace_listings" /> + </menu_item_call> + <menu_item_call + label="Move to Marketplace Listings" + layout="topleft" + name="Marketplace Move"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="move_to_marketplace_listings" /> + </menu_item_call> + <menu_item_call + label="--no options--" + layout="topleft" + name="--no options--" /> + <menu_item_separator + layout="topleft" /> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index d2d3cb4523..70edd567a1 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3249,6 +3249,29 @@ See https://wiki.secondlife.com/wiki/Adding_Spelling_Dictionaries <notification icon="alertmodal.tga" + label="Rename Selected Item" + name="RenameItem" + type="alertmodal"> + Choose a new name for [NAME] + <tag>confirm</tag> + <form name="form"> + <input name="new_name" type="text" width="300"> + [NAME] + </input> + <button + default="true" + index="0" + name="OK" + text="OK"/> + <button + index="1" + name="Cancel" + text="Cancel"/> + </form> + </notification> + + <notification + icon="alertmodal.tga" name="RemoveFromFriends" type="alertmodal"> <tag>friendship</tag> diff --git a/indra/newview/skins/default/xui/en/panel_inventory_gallery.xml b/indra/newview/skins/default/xui/en/panel_inventory_gallery.xml index 68f78a77c8..b32d592bf6 100644 --- a/indra/newview/skins/default/xui/en/panel_inventory_gallery.xml +++ b/indra/newview/skins/default/xui/en/panel_inventory_gallery.xml @@ -26,7 +26,7 @@ </text> <scroll_container follows="all" - height="400" + height="390" layout="topleft" left="4" top="0" 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 73889af71a..1d216df094 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 @@ -53,7 +53,7 @@ left="0" top="129" height="25" - width="148" + width="130" name="text_bg_panel"> <text read_only="true" @@ -65,7 +65,7 @@ name="item_name" parse_urls="false" top="2" - width="150" + width="130" use_ellipses="true"> Item name, folder name. </text> |