EXP-1799 FIX -- Replace and Add to Outfit options and Copy to Merchant Outbox options can appear in invalid state when a valid folder is last selection
EXP-1834 FIX -- Right click context menus on Folders in Merchant Outbox and Library folders can show all inventory options including admin options EXP-1835 FIX -- Right clicking on a folder and selecting New Folder creates folder under My Inventory not within selected folder * Updated folder context menu building to build full options in one step or trigger a load which will rebuild top-level context menu for all selected items when complete. Previous code had an implicit assumption that the selected folder was the only selection after background fetch.master
parent
039cd701c4
commit
e2d4309ba5
|
|
@ -2923,129 +2923,13 @@ void LLFolderBridge::pasteLinkFromClipboard()
|
|||
void LLFolderBridge::staticFolderOptionsMenu()
|
||||
{
|
||||
LLFolderBridge* selfp = sSelf.get();
|
||||
if (selfp)
|
||||
|
||||
if (selfp && selfp->mRoot)
|
||||
{
|
||||
selfp->folderOptionsMenuAfterFetch();
|
||||
selfp->mRoot->updateMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void LLFolderBridge::folderOptionsMenuAfterFetch()
|
||||
{
|
||||
const U32 flags = mContextMenuFlags;
|
||||
|
||||
mItems.clear();
|
||||
mDisabledItems.clear();
|
||||
mContextMenuFlags = 0x0;
|
||||
|
||||
LLMenuGL* menup = dynamic_cast<LLMenuGL*>(mMenu.get());
|
||||
if (!menup) return;
|
||||
|
||||
// Reset the menu
|
||||
{
|
||||
const LLView::child_list_t *list = menup->getChildList();
|
||||
|
||||
LLView::child_list_t::const_iterator menu_itor;
|
||||
for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor)
|
||||
{
|
||||
(*menu_itor)->setVisible(FALSE);
|
||||
(*menu_itor)->pushVisible(TRUE);
|
||||
(*menu_itor)->setEnabled(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
// Build basic menu back up
|
||||
buildContextMenuBaseOptions(*menup, flags);
|
||||
|
||||
// Build folder specific options back up
|
||||
LLInventoryModel* model = getInventoryModel();
|
||||
if(!model) return;
|
||||
|
||||
const LLInventoryCategory* category = model->getCategory(mUUID);
|
||||
if(!category) return;
|
||||
|
||||
const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
if (trash_id == mUUID) return;
|
||||
if (isItemInTrash()) return;
|
||||
if (!isAgentInventory()) return;
|
||||
if (isOutboxFolder()) return;
|
||||
|
||||
LLFolderType::EType type = category->getPreferredType();
|
||||
const bool is_system_folder = LLFolderType::lookupIsProtectedType(type);
|
||||
// BAP change once we're no longer treating regular categories as ensembles.
|
||||
const bool is_ensemble = (type == LLFolderType::FT_NONE ||
|
||||
LLFolderType::lookupIsEnsembleType(type));
|
||||
|
||||
// Only enable calling-card related options for non-system folders.
|
||||
if (!is_system_folder)
|
||||
{
|
||||
LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
|
||||
if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))
|
||||
{
|
||||
mItems.push_back(std::string("Calling Card Separator"));
|
||||
mItems.push_back(std::string("Conference Chat Folder"));
|
||||
mItems.push_back(std::string("IM All Contacts In Folder"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!isItemRemovable())
|
||||
{
|
||||
mDisabledItems.push_back(std::string("Delete"));
|
||||
}
|
||||
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
if (LLFolderType::lookupIsProtectedType(type))
|
||||
{
|
||||
mItems.push_back(std::string("Delete System Folder"));
|
||||
}
|
||||
#endif
|
||||
|
||||
// wearables related functionality for folders.
|
||||
//is_wearable
|
||||
LLFindWearables is_wearable;
|
||||
LLIsType is_object( LLAssetType::AT_OBJECT );
|
||||
LLIsType is_gesture( LLAssetType::AT_GESTURE );
|
||||
|
||||
if (mWearables ||
|
||||
checkFolderForContentsOfType(model, is_wearable) ||
|
||||
checkFolderForContentsOfType(model, is_object) ||
|
||||
checkFolderForContentsOfType(model, is_gesture) )
|
||||
{
|
||||
mItems.push_back(std::string("Folder Wearables Separator"));
|
||||
|
||||
// Only enable add/replace outfit for non-system folders.
|
||||
if (!is_system_folder)
|
||||
{
|
||||
// Adding an outfit onto another (versus replacing) doesn't make sense.
|
||||
if (type != LLFolderType::FT_OUTFIT)
|
||||
{
|
||||
mItems.push_back(std::string("Add To Outfit"));
|
||||
}
|
||||
|
||||
mItems.push_back(std::string("Replace Outfit"));
|
||||
}
|
||||
if (is_ensemble)
|
||||
{
|
||||
mItems.push_back(std::string("Wear As Ensemble"));
|
||||
}
|
||||
mItems.push_back(std::string("Remove From Outfit"));
|
||||
if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID))
|
||||
{
|
||||
mDisabledItems.push_back(std::string("Remove From Outfit"));
|
||||
}
|
||||
if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))
|
||||
{
|
||||
mDisabledItems.push_back(std::string("Replace Outfit"));
|
||||
}
|
||||
mItems.push_back(std::string("Outfit Separator"));
|
||||
}
|
||||
|
||||
hide_context_entries(*menup, mItems, mDisabledItems);
|
||||
|
||||
// Reposition the menu, in case we're adding items to an existing menu.
|
||||
menup->needsArrange();
|
||||
menup->arrangeAndClear();
|
||||
}
|
||||
|
||||
BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
|
||||
{
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
|
|
@ -3058,7 +2942,7 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv
|
|||
return ((item_array.count() > 0) ? TRUE : FALSE );
|
||||
}
|
||||
|
||||
void LLFolderBridge::buildContextMenuBaseOptions(LLMenuGL& menu, U32 flags)
|
||||
void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)
|
||||
{
|
||||
LLInventoryModel* model = getInventoryModel();
|
||||
llassert(model != NULL);
|
||||
|
|
@ -3079,10 +2963,6 @@ void LLFolderBridge::buildContextMenuBaseOptions(LLMenuGL& menu, U32 flags)
|
|||
mDisabledItems.push_back(std::string("New Body Parts"));
|
||||
}
|
||||
|
||||
// clear out old menu and folder pointers
|
||||
mMenu.markDead();
|
||||
sSelf.markDead();
|
||||
|
||||
if(trash_id == mUUID)
|
||||
{
|
||||
// This is the trash.
|
||||
|
|
@ -3185,45 +3065,134 @@ void LLFolderBridge::buildContextMenuBaseOptions(LLMenuGL& menu, U32 flags)
|
|||
}
|
||||
}
|
||||
|
||||
void LLFolderBridge::buildContextMenuFolderOptions(U32 flags)
|
||||
{
|
||||
// Build folder specific options back up
|
||||
LLInventoryModel* model = getInventoryModel();
|
||||
if(!model) return;
|
||||
|
||||
const LLInventoryCategory* category = model->getCategory(mUUID);
|
||||
if(!category) return;
|
||||
|
||||
const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
if (trash_id == mUUID) return;
|
||||
if (isItemInTrash()) return;
|
||||
if (!isAgentInventory()) return;
|
||||
if (isOutboxFolder()) return;
|
||||
|
||||
LLFolderType::EType type = category->getPreferredType();
|
||||
const bool is_system_folder = LLFolderType::lookupIsProtectedType(type);
|
||||
// BAP change once we're no longer treating regular categories as ensembles.
|
||||
const bool is_ensemble = (type == LLFolderType::FT_NONE ||
|
||||
LLFolderType::lookupIsEnsembleType(type));
|
||||
|
||||
// Only enable calling-card related options for non-system folders.
|
||||
if (!is_system_folder)
|
||||
{
|
||||
LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
|
||||
if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))
|
||||
{
|
||||
mItems.push_back(std::string("Calling Card Separator"));
|
||||
mItems.push_back(std::string("Conference Chat Folder"));
|
||||
mItems.push_back(std::string("IM All Contacts In Folder"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!isItemRemovable())
|
||||
{
|
||||
mDisabledItems.push_back(std::string("Delete"));
|
||||
}
|
||||
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
if (LLFolderType::lookupIsProtectedType(type))
|
||||
{
|
||||
mItems.push_back(std::string("Delete System Folder"));
|
||||
}
|
||||
#endif
|
||||
|
||||
// wearables related functionality for folders.
|
||||
//is_wearable
|
||||
LLFindWearables is_wearable;
|
||||
LLIsType is_object( LLAssetType::AT_OBJECT );
|
||||
LLIsType is_gesture( LLAssetType::AT_GESTURE );
|
||||
|
||||
if (mWearables ||
|
||||
checkFolderForContentsOfType(model, is_wearable) ||
|
||||
checkFolderForContentsOfType(model, is_object) ||
|
||||
checkFolderForContentsOfType(model, is_gesture) )
|
||||
{
|
||||
mItems.push_back(std::string("Folder Wearables Separator"));
|
||||
|
||||
// Only enable add/replace outfit for non-system folders.
|
||||
if (!is_system_folder)
|
||||
{
|
||||
// Adding an outfit onto another (versus replacing) doesn't make sense.
|
||||
if (type != LLFolderType::FT_OUTFIT)
|
||||
{
|
||||
mItems.push_back(std::string("Add To Outfit"));
|
||||
}
|
||||
|
||||
mItems.push_back(std::string("Replace Outfit"));
|
||||
}
|
||||
if (is_ensemble)
|
||||
{
|
||||
mItems.push_back(std::string("Wear As Ensemble"));
|
||||
}
|
||||
mItems.push_back(std::string("Remove From Outfit"));
|
||||
if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID))
|
||||
{
|
||||
mDisabledItems.push_back(std::string("Remove From Outfit"));
|
||||
}
|
||||
if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))
|
||||
{
|
||||
mDisabledItems.push_back(std::string("Replace Outfit"));
|
||||
}
|
||||
mItems.push_back(std::string("Outfit Separator"));
|
||||
}
|
||||
}
|
||||
|
||||
// Flags unused
|
||||
void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
||||
{
|
||||
sSelf.markDead();
|
||||
|
||||
mItems.clear();
|
||||
mDisabledItems.clear();
|
||||
mContextMenuFlags = flags;
|
||||
|
||||
lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;
|
||||
|
||||
LLInventoryModel* model = getInventoryModel();
|
||||
if(!model) return;
|
||||
|
||||
buildContextMenuBaseOptions(menu, flags);
|
||||
buildContextMenuBaseOptions(flags);
|
||||
|
||||
// Add menu items that are dependent on the contents of the folder.
|
||||
LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID);
|
||||
if (category)
|
||||
{
|
||||
uuid_vec_t folders;
|
||||
folders.push_back(category->getUUID());
|
||||
|
||||
sSelf = getHandle();
|
||||
LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE);
|
||||
fetch->startFetch();
|
||||
inc_busy_count();
|
||||
if (fetch->isFinished())
|
||||
{
|
||||
buildContextMenuFolderOptions(flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's all on its way - add an observer, and the inventory will call done for us when everything is here.
|
||||
gInventory.addObserver(fetch);
|
||||
}
|
||||
}
|
||||
|
||||
hide_context_entries(menu, mItems, mDisabledItems);
|
||||
|
||||
// Add menu items that are dependent on the contents of the folder.
|
||||
uuid_vec_t folders;
|
||||
LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
|
||||
if (category)
|
||||
{
|
||||
folders.push_back(category->getUUID());
|
||||
}
|
||||
|
||||
mMenu = menu.getHandle();
|
||||
sSelf = getHandle();
|
||||
LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE);
|
||||
fetch->startFetch();
|
||||
inc_busy_count();
|
||||
if(fetch->isFinished())
|
||||
{
|
||||
// everything is already here - call done.
|
||||
fetch->done();
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's all on its way - add an observer, and the inventory will call done for us when everything is here.
|
||||
gInventory.addObserver(fetch);
|
||||
}
|
||||
// Reposition the menu, in case we're adding items to an existing menu.
|
||||
menu.needsArrange();
|
||||
menu.arrangeAndClear();
|
||||
}
|
||||
|
||||
BOOL LLFolderBridge::hasChildren() const
|
||||
|
|
|
|||
|
|
@ -235,8 +235,7 @@ public:
|
|||
const LLUUID& uuid) :
|
||||
LLInvFVBridge(inventory, root, uuid),
|
||||
mCallingCards(FALSE),
|
||||
mWearables(FALSE),
|
||||
mContextMenuFlags(0x0)
|
||||
mWearables(FALSE)
|
||||
{}
|
||||
|
||||
BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg);
|
||||
|
|
@ -283,7 +282,8 @@ public:
|
|||
LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; }
|
||||
|
||||
protected:
|
||||
void buildContextMenuBaseOptions(LLMenuGL& menu, U32 flags);
|
||||
void buildContextMenuBaseOptions(U32 flags);
|
||||
void buildContextMenuFolderOptions(U32 flags);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Menu callbacks
|
||||
|
|
@ -320,15 +320,12 @@ protected:
|
|||
public:
|
||||
static LLHandle<LLFolderBridge> sSelf;
|
||||
static void staticFolderOptionsMenu();
|
||||
void folderOptionsMenuAfterFetch();
|
||||
|
||||
private:
|
||||
BOOL mCallingCards;
|
||||
BOOL mWearables;
|
||||
LLHandle<LLView> mMenu;
|
||||
menuentry_vec_t mItems;
|
||||
menuentry_vec_t mDisabledItems;
|
||||
U32 mContextMenuFlags;
|
||||
LLRootHandle<LLFolderBridge> mHandle;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue