SL-17665 Add operation to create a subfolder from selected items in Inventory

meow-7.2.2
Mnikolenko Productengine 2022-07-04 20:25:18 +03:00
parent 0fbfa6e884
commit ed9dbabb5e
6 changed files with 235 additions and 1 deletions

View File

@ -792,6 +792,19 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
disabled_items.push_back(std::string("Copy"));
}
if (isAgentInventory())
{
items.push_back(std::string("New folder from selected"));
items.push_back(std::string("Subfolder Separator"));
std::set<LLUUID> selected_uuid_set = LLAvatarActions::getInventorySelectedUUIDs();
uuid_vec_t ids;
std::copy(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids));
if (!is_only_items_selected(ids) && !is_only_cats_selected(ids))
{
disabled_items.push_back(std::string("New folder from selected"));
}
}
if (obj->getIsLinkType())
{
items.push_back(std::string("Find Original"));
@ -4266,7 +4279,16 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t&
items.push_back(std::string("Conference Chat Folder"));
items.push_back(std::string("IM All Contacts In Folder"));
}
if (((flags & ITEM_IN_MULTI_SELECTION) == 0) && hasChildren())
{
items.push_back(std::string("Ungroup folder items"));
}
}
else
{
disabled_items.push_back(std::string("New folder from selected"));
}
#ifndef LL_RELEASE_FOR_DOWNLOAD
if (LLFolderType::lookupIsProtectedType(type) && is_agent_inventory)

View File

@ -1868,6 +1868,86 @@ void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id)
}
}
void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids)
{
for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it)
{
LLInventoryItem* inv_item = gInventory.getItem(*it);
if (inv_item)
{
change_item_parent(*it, new_cat_uuid);
}
else
{
LLInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (inv_cat)
{
gInventory.changeCategoryParent((LLViewerInventoryCategory*)inv_cat, new_cat_uuid, false);
}
}
}
LLFloater* floater_inventory = LLFloaterReg::getInstance("inventory");
if (!floater_inventory)
{
LL_WARNS() << "Could not find My Inventory floater" << LL_ENDL;
return;
}
LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
if (sidepanel_inventory)
{
if (sidepanel_inventory->getActivePanel())
{
sidepanel_inventory->getActivePanel()->setSelection(new_cat_uuid, TAKE_FOCUS_YES);
LLFolderViewItem* fv_folder = sidepanel_inventory->getActivePanel()->getItemByID(new_cat_uuid);
if (fv_folder)
{
fv_folder->setOpen(TRUE);
}
}
}
}
bool is_only_cats_selected(const uuid_vec_t& selected_uuids)
{
for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it)
{
LLInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (!inv_cat)
{
return false;
}
}
return true;
}
bool is_only_items_selected(const uuid_vec_t& selected_uuids)
{
for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it)
{
LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
if (!inv_item)
{
return false;
}
}
return true;
}
void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::string& folder_name)
{
LLInventoryObject* first_item = gInventory.getObject(*selected_uuids.begin());
if (!first_item)
{
return;
}
inventory_func_type func = boost::bind(&move_items_to_folder, _1, selected_uuids);
gInventory.createNewCategory(first_item->getParentUUID(), LLFolderType::FT_NONE, folder_name, func);
}
///----------------------------------------------------------------------------
/// LLInventoryCollectFunctor implementations
///----------------------------------------------------------------------------
@ -2522,6 +2602,81 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
{
(new LLDirPickerThread(boost::bind(&LLInventoryAction::saveMultipleTextures, _1, selected_items, model), std::string()))->getFile();
}
else if ("new_folder_from_selected" == action)
{
LLInventoryObject* first_item = gInventory.getObject(*ids.begin());
if (!first_item)
{
return;
}
const LLUUID& parent_uuid = first_item->getParentUUID();
for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
{
LLInventoryObject *item = gInventory.getObject(*it);
if (!item || item->getParentUUID() != parent_uuid)
{
LLNotificationsUtil::add("SameFolderRequired");
return;
}
}
LLSD args;
args["DESC"] = LLTrans::getString("New Folder");
LLNotificationsUtil::add("CreateSubfolder", args, LLSD(),
[ids](const LLSD& notification, const LLSD& response)
{
S32 opt = LLNotificationsUtil::getSelectedOption(notification, response);
if (opt == 0)
{
std::string settings_name = response["message"].asString();
LLInventoryObject::correctInventoryName(settings_name);
if (settings_name.empty())
{
settings_name = LLTrans::getString("New Folder");
}
move_items_to_new_subfolder(ids, settings_name);
}
});
}
else if ("ungroup_folder_items" == action)
{
if (selected_uuid_set.size() == 1)
{
LLInventoryCategory* inv_cat = gInventory.getCategory(*ids.begin());
if (!inv_cat)
{
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();
}
}
else
{
std::set<LLFolderViewItem*>::iterator set_iter;

View File

@ -93,6 +93,10 @@ LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth);
S32 compute_stock_count(LLUUID cat_uuid, bool force_count = false);
void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id);
void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::string& folder_name);
void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids);
bool is_only_cats_selected(const uuid_vec_t& selected_uuids);
bool is_only_items_selected(const uuid_vec_t& selected_uuids);
/** Miscellaneous global functions
** **

View File

@ -291,7 +291,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
mLineEditor->setText(edit_text_contents);
std::string notif_name = mNotification->getName();
if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name) || ("CreateLandmarkFolder" == notif_name))
if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name) || ("CreateLandmarkFolder" == notif_name) || ("CreateSubfolder" == notif_name))
{
mLineEditor->setPrevalidate(&LLTextValidate::validateASCII);
}

View File

@ -912,6 +912,25 @@
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_item_separator
layout="topleft"
name="Marketplace Separator" />

View File

@ -11842,4 +11842,38 @@ Unpacking: [UNPACK_TIME]s [USIZE]KB
</form>
</notification>
<notification
icon="alertmodal.tga"
label="Save Outfit"
name="CreateSubfolder"
type="alertmodal">
<unique/>
Name the new folder:
<tag>confirm</tag>
<form name="form">
<input name="message" type="text">
[DESC]
</input>
<button
default="true"
index="0"
name="OK"
text="OK"/>
<button
index="1"
name="Cancel"
text="Cancel"/>
</form>
</notification>
<notification
icon="alertmodal.tga"
name="SameFolderRequired"
type="alert">
Selected items must be in the same folder.
<tag>fail</tag>
<usetemplate
name="okbutton"
yestext="OK"/>
</notification>
</notifications>