Issue 1151: Add share to LLAvatarActions

Syncs LLGiveInventory and LLFloaterAvatarPicker with upstream.
Syncsyncsync~

Translators:
menu_inventory.xml menu_radar.xml and menu_avs_list.xml: Share
notifications.xml: ShareNotification, ShareItemsConfirmation, ShareFolderConfirmation, ItemsShared
strings.xml: share_alert
This commit is contained in:
Inusaito Sayori
2014-10-17 00:33:33 -04:00
parent 2d53641cd0
commit e98792209e
21 changed files with 937 additions and 136 deletions

View File

@@ -906,7 +906,6 @@ AIHTTPTimeoutPolicy const* AIHTTPTimeoutPolicy::getTimeoutPolicyByName(std::stri
// Policy name Policy
P(assetReportHandler);
P(avatarPickerResponder);
P(authHandler);
P(avatarNameResponder);
P2(baseCapabilitiesComplete, transfer_18s_connect_5s);

View File

@@ -444,6 +444,7 @@ set(viewer_SOURCE_FILES
llscrollingpanelparam.cpp
llscrollingpanelparambase.cpp
llselectmgr.cpp
llshareavatarhandler.cpp
llsky.cpp
llslurl.cpp
llspatialpartition.cpp

View File

@@ -5084,6 +5084,39 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ContextConeInAlpha</key>
<map>
<key>Comment</key>
<string>Cone In Alpha</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.0</real>
</map>
<key>ContextConeOutAlpha</key>
<map>
<key>Comment</key>
<string>Cone Out Alpha</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>1.0</real>
</map>
<key>ContextConeFadeTime</key>
<map>
<key>Comment</key>
<string>Cone Fade Time</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>.08</real>
</map>
<key>CookiesEnabled</key>
<map>
<key>Comment</key>

View File

@@ -37,20 +37,26 @@
#include "llagent.h"
#include "llcallingcard.h" // for LLAvatarTracker
#include "llfloateravatarinfo.h"
#include "llfloateravatarpicker.h" // for LLFloaterAvatarPicker
#include "llfloaterchatterbox.h"
#include "llfloatergroupbulkban.h"
#include "llfloatergroupinvite.h"
#include "llfloatergroups.h"
#include "llfloaterwebprofile.h"
#include "llfloaterworldmap.h"
#include "llgiveinventory.h"
#include "llgivemoney.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventorypanel.h"
#include "llimview.h" // for gIMMgr
#include "llinventoryobserver.h"
#include "llmutelist.h"
#include "llpanelprofile.h"
#include "lltrans.h"
#include "llvoiceclient.h"
#include "llweb.h"
#include "llslurl.h" // IDEVO
#include "llpanelmaininventory.h"
#include "llavatarname.h"
#include "llagentui.h"
// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0)
@@ -569,7 +575,262 @@ void LLAvatarActions::csr(const LLUUID& id)
LLWeb::loadURL(url);
}
// Singu TODO: Share inventory code block should live here
//static
void LLAvatarActions::share(const LLUUID& id)
{
/*
LLSD key;
LLFloaterSidePanelContainer::showPanel("inventory", key);
LLFloaterReg::showInstance("im_container");
*/
LLInventoryView::getActiveInventory()->setVisible(true);
LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, id);
if (!gIMMgr->hasSession(session_id))
{
startIM(id);
}
if (gIMMgr->hasSession(session_id))
{
// we should always get here, but check to verify anyways
LLIMMgr::getInstance()->addMessage(session_id, LLUUID::null, SYSTEM_FROM, LLTrans::getString("share_alert"));
LLFloaterChatterBox::showInstance(session_id);
}
}
namespace action_give_inventory
{
/**
* Returns a pointer to 'Add More' inventory panel of Edit Outfit SP.
*
static LLInventoryPanel* get_outfit_editor_inventory_panel()
{
LLPanelOutfitEdit* panel_outfit_edit = dynamic_cast<LLPanelOutfitEdit*>(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit"));
if (NULL == panel_outfit_edit) return NULL;
LLInventoryPanel* inventory_panel = panel_outfit_edit->findChild<LLInventoryPanel>("folder_view");
return inventory_panel;
}*/
/**
* @return active inventory panel, or NULL if there's no such panel
*/
static LLInventoryPanel* get_active_inventory_panel()
{
LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
/*if (!active_panel)
{
active_panel = get_outfit_editor_inventory_panel();
}*/
return active_panel;
}
/**
* Checks My Inventory visibility.
*/
static bool is_give_inventory_acceptable()
{
// check selection in the panel
const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
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 void build_items_string(const std::set<LLUUID>& inventory_selected_uuids , std::string& items_string)
{
llassert(inventory_selected_uuids.size() > 0);
const std::string& separator = LLTrans::getString("words_separator");
for (std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); ; )
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (NULL != inv_cat)
{
items_string = inv_cat->getName();
break;
}
LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
if (NULL != inv_item)
{
items_string.append(inv_item->getName());
}
if(++it == inventory_selected_uuids.end())
{
break;
}
items_string.append(separator);
}
}
struct LLShareInfo : public LLSingleton<LLShareInfo>
{
std::vector<LLAvatarName> mAvatarNames;
uuid_vec_t mAvatarUuids;
};
static void give_inventory_cb(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// if Cancel pressed
if (option == 1)
{
return;
}
const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
if (inventory_selected_uuids.empty())
{
return;
}
S32 count = LLShareInfo::instance().mAvatarNames.size();
bool shared = count && !inventory_selected_uuids.empty();
// iterate through avatars
for(S32 i = 0; i < count; ++i)
{
const LLUUID& avatar_uuid = LLShareInfo::instance().mAvatarUuids[i];
// We souldn't open IM session, just calculate session ID for logging purpose. See EXT-6710
const LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, avatar_uuid);
std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
const std::string& separator = LLTrans::getString("words_separator");
std::string noncopy_item_names;
LLSD noncopy_items = LLSD::emptyArray();
// iterate through selected inventory objects
for (; it != it_end; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (inv_cat)
{
if (!LLGiveInventory::doGiveInventoryCategory(avatar_uuid, inv_cat, session_id, "ItemsShared"))
{
shared = false;
}
break;
}
LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
if (!inv_item->getPermissions().allowCopyBy(gAgentID))
{
if (!noncopy_item_names.empty())
{
noncopy_item_names.append(separator);
}
noncopy_item_names.append(inv_item->getName());
noncopy_items.append(*it);
}
else
{
if (!LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id))
{
shared = false;
}
}
}
if (noncopy_items.beginArray() != noncopy_items.endArray())
{
LLSD substitutions;
substitutions["ITEMS"] = noncopy_item_names;
LLSD payload;
payload["agent_id"] = avatar_uuid;
payload["items"] = noncopy_items;
payload["success_notification"] = "ItemsShared";
LLNotificationsUtil::add("CannotCopyWarning", substitutions, payload,
&LLGiveInventory::handleCopyProtectedItem);
shared = false;
break;
}
}
if (shared)
{
if (LLFloaterAvatarPicker::instanceExists()) LLFloaterAvatarPicker::instance().close();
LLNotificationsUtil::add("ItemsShared");
}
}
/**
* Performs "give inventory" operations for provided avatars.
*
* Sends one requests to give all selected inventory items for each passed avatar.
* Avatars are represent by two vectors: names and UUIDs which must be sychronized with each other.
*
* @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)
{
llassert(avatar_names.size() == avatar_uuids.size());
const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
if (inventory_selected_uuids.empty())
{
return;
}
std::string residents;
LLAvatarActions::buildResidentsString(avatar_names, residents);
std::string items;
build_items_string(inventory_selected_uuids, items);
int folders_count = 0;
std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
//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(), &give_inventory_cb);
}
}
// static
void LLAvatarActions::buildResidentsString(std::vector<LLAvatarName> avatar_names, std::string& residents_string)
@@ -611,7 +872,118 @@ void LLAvatarActions::buildResidentsString(const uuid_vec_t& avatar_uuids, std::
}
}
// Singu TODO: Share inventory code block should live here, too
//static
std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs()
{
LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel();
return active_panel ? active_panel->getRootFolder()->getSelectionList() : std::set<LLUUID>();
/*std::set<LLFolderViewItem*> inventory_selected;
LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel();
if (active_panel)
{
inventory_selected= active_panel->getRootFolder()->getSelectionList();
}
if (inventory_selected.empty())
{
LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
if (sidepanel_inventory)
{
inventory_selected= sidepanel_inventory->getInboxSelectionList();
}
}
std::set<LLUUID> inventory_selected_uuids;
for (std::set<LLFolderViewItem*>::iterator it = inventory_selected.begin(), end_it = inventory_selected.end();
it != end_it;
++it)
{
inventory_selected_uuids.insert(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID());
}
return inventory_selected_uuids;*/
}
//static
void LLAvatarActions::shareWithAvatars(LLView * panel)
{
using namespace action_give_inventory;
LLFloater* root_floater = gFloaterView->getParentFloater(panel);
LLFloaterAvatarPicker* picker =
LLFloaterAvatarPicker::show(boost::bind(give_inventory, _1, _2), TRUE, FALSE, FALSE, root_floater->getName());
if (!picker)
{
return;
}
picker->setOkBtnEnableCb(boost::bind(is_give_inventory_acceptable));
picker->openFriendsTab();
if (root_floater)
{
root_floater->addDependentFloater(picker);
}
LLNotificationsUtil::add("ShareNotification");
}
// static
bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NULL*/)
{
using namespace action_give_inventory;
if (!inv_panel)
{
LLInventoryPanel* active_panel = get_active_inventory_panel();
if (!active_panel) return false;
inv_panel = active_panel;
}
// check selection in the panel
LLFolderView* root_folder = inv_panel->getRootFolder();
if (!root_folder)
{
return false;
}
const std::set<LLUUID> inventory_selected = root_folder->getSelectionList();
if (inventory_selected.empty()) return false; // nothing selected
bool can_share = true;
const LLUUID& trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); // <alchemy/>
std::set<LLUUID>::const_iterator it = inventory_selected.begin();
const std::set<LLUUID>::const_iterator it_end = inventory_selected.end();
for (; it != it_end; ++it)
{
const LLUUID id(*it);
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(id);
// any category can be offered.
if (inv_cat && !gInventory.isObjectDescendentOf(inv_cat->getUUID(), trash_id)) // <alchemy/>
{
continue;
}
// check if inventory item can be given
else if (!inv_cat && gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID())) // Singu Note: These three ifs comprise the item half of LLInvFVBridge::canShare, which LL calls here.
if (LLViewerInventoryItem* item = gInventory.getItem(id))
if (LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item) && LLGiveInventory::isInventoryGiveAcceptable(item))
/*
LLFolderViewItem* item = *it;
if (!item) return false;
LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getViewModelItem());
if (bridge && bridge->canShare())
*/
{
continue;
}
// there are neither item nor category in inventory
can_share = false;
break;
}
return can_share;
}
// static
void LLAvatarActions::toggleBlock(const LLUUID& id)
@@ -898,6 +1270,21 @@ bool LLAvatarActions::canBlock(const LLUUID& id)
return !is_self && !is_linden;
}
//static
bool LLAvatarActions::isAgentMappable(const LLUUID& agent_id)
{
const LLRelationship* buddy_info = NULL;
bool is_friend = LLAvatarActions::isFriend(agent_id);
if (is_friend)
buddy_info = LLAvatarTracker::instance().getBuddyInfo(agent_id);
return (buddy_info &&
buddy_info->isOnline() &&
buddy_info->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)
);
}
// static
void LLAvatarActions::copyUUIDs(const uuid_vec_t& ids)
{

View File

@@ -28,7 +28,9 @@
#define LL_LLAVATARACTIONS_H
class LLAvatarName;
class LLInventoryPanel;
class LLFloater;
class LLView;
/**
* Friend-related actions (add, remove, offer teleport, etc)
@@ -108,6 +110,16 @@ public:
static void teleportRequest(const LLUUID& id);
static void teleport_request_callback(const LLSD& notification, const LLSD& response);
/**
* Share items with the avatar.
*/
static void share(const LLUUID& id);
/**
* Share items with the picked avatars.
*/
static void shareWithAvatars(LLView * panel);
/**
* Block/unblock the avatar.
*/
@@ -190,6 +202,20 @@ public:
*/
static bool canOfferTeleport(const uuid_vec_t& ids);
/**
* Checks whether all items selected in the given inventory panel can be shared
*
* @param inv_panel Inventory panel to get selection from. If NULL, the active inventory panel is used.
*
* @return false if the selected items cannot be shared or the active inventory panel cannot be obtained
*/
static bool canShareSelectedItems(LLInventoryPanel* inv_panel = NULL);
/**
* Checks whether agent is mappable
*/
static bool isAgentMappable(const LLUUID& agent_id);
/**
* Builds a string of residents' display names separated by "words_separator" string.
*
@@ -206,6 +232,8 @@ public:
*/
static void buildResidentsString(const uuid_vec_t& avatar_uuids, std::string& residents_string);
static std::set<LLUUID> getInventorySelectedUUIDs();
/**
* Copy the selected avatar's UUID to clipboard
*/

View File

@@ -50,6 +50,7 @@
#include "llscrolllistitem.h"
#include "lltabcontainer.h"
#include "lluictrlfactory.h"
#include "lldraghandle.h"
#include "message.h"
@@ -58,17 +59,21 @@ static std::map<LLUUID, LLAvatarName> sAvatarNameMap;
LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,
BOOL allow_multiple,
BOOL closeOnSelect)
BOOL closeOnSelect,
BOOL skip_agent,
const std::string& name,
LLView * frustumOrigin)
{
// *TODO: Use a key to allow this not to be an effective singleton
LLFloaterAvatarPicker* floater = getInstance();
LLFloaterAvatarPicker* floater =
getInstance();
floater->open();
floater->mSelectionCallback = callback;
floater->setAllowMultiple(allow_multiple);
floater->mNearMeListComplete = FALSE;
floater->mCloseOnSelect = closeOnSelect;
floater->mExcludeAgentFromSearchResults = skip_agent;
if (!closeOnSelect)
{
@@ -79,6 +84,11 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,
floater->getChild<LLButton>("cancel_btn")->setLabel(close_string);
}
if(frustumOrigin)
{
floater->mFrustumOrigin = frustumOrigin->getHandle();
}
return floater;
}
@@ -87,10 +97,18 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker()
: LLFloater(),
mNumResultsReturned(0),
mNearMeListComplete(FALSE),
mCloseOnSelect(FALSE)
mCloseOnSelect(FALSE),
mContextConeOpacity (0.f),
mContextConeInAlpha(0.f),
mContextConeOutAlpha(0.f),
mContextConeFadeTime(0.f)
{
mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this));
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_avatar_picker.xml", NULL);
mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
}
BOOL LLFloaterAvatarPicker::postBuild()
@@ -188,11 +206,10 @@ static void addAvatarUUID(const LLUUID av_id, uuid_vec_t& avatar_ids, std::vecto
static void getSelectedAvatarData(const LLUICtrl* from, uuid_vec_t& avatar_ids, std::vector<LLAvatarName>& avatar_names)
{
const LLScrollListCtrl* list = dynamic_cast<const LLScrollListCtrl*>(from);
if(list)
if(const LLScrollListCtrl* list = dynamic_cast<const LLScrollListCtrl*>(from))
{
std::vector<LLScrollListItem*> items = list->getAllSelected();
for (std::vector<LLScrollListItem*>::iterator iter = items.begin(); iter != items.end(); ++iter)
const std::vector<LLScrollListItem*> items = list->getAllSelected();
for (std::vector<LLScrollListItem*>::const_iterator iter = items.begin(); iter != items.end(); ++iter)
{
addAvatarUUID((*iter)->getUUID(), avatar_ids, avatar_names);
}
@@ -366,8 +383,67 @@ void LLFloaterAvatarPicker::populateFriend()
friends_scroller->sortByColumnIndex(0, TRUE);
}
void LLFloaterAvatarPicker::drawFrustum()
{
if (mFrustumOrigin.get())
{
LLView * frustumOrigin = mFrustumOrigin.get();
LLRect origin_rect;
frustumOrigin->localRectToOtherView(frustumOrigin->getLocalRect(), &origin_rect, this);
// draw context cone connecting color picker with color swatch in parent floater
LLRect local_rect = getLocalRect();
if (hasFocus() && frustumOrigin->isInVisibleChain() && mContextConeOpacity > 0.001f)
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLGLEnable(GL_CULL_FACE);
gGL.begin(LLRender::QUADS);
{
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
gGL.vertex2i(local_rect.mRight, local_rect.mTop);
gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
gGL.vertex2i(local_rect.mRight, local_rect.mTop);
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
}
gGL.end();
}
if (gFocusMgr.childHasMouseCapture(getDragHandle()))
{
mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(mContextConeFadeTime));
}
else
{
mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime));
}
}
}
void LLFloaterAvatarPicker::draw()
{
drawFrustum();
// sometimes it is hard to determine when Select/Ok button should be disabled (see LLAvatarActions::shareWithAvatars).
// lets check this via mOkButtonValidateSignal callback periodically.
static LLFrameTimer timer;
@@ -411,19 +487,20 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
return FALSE;
}
extern AIHTTPTimeoutPolicy avatarPickerResponder_timeout;
class LLAvatarPickerResponder : public LLHTTPClient::ResponderWithCompleted
{
LOG_CLASS(LLAvatarPickerResponder);
public:
LLUUID mQueryID;
LLAvatarPickerResponder(const LLUUID& id) : mQueryID(id) { }
/*virtual*/ void httpCompleted(void)
protected:
/*virtual*/ void httpCompleted()
{
//std::ostringstream ss;
//LLSDSerialize::toPrettyXML(mContent, ss);
//llinfos << ss.str() << llendl;
//LLSDSerialize::toPrettyXML(content, ss);
//LL_INFOS() << ss.str() << LL_ENDL;
// in case of invalid characters, the avatar picker returns a 400
// just set it to process so it displays 'not found'
@@ -436,12 +513,11 @@ public:
}
else
{
llwarns << "avatar picker failed " << mStatus << " reason " << mReason << llendl;
llwarns << "avatar picker failed " << dumpResponse() << LL_ENDL;
}
}
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return avatarPickerResponder_timeout; }
/*virtual*/ char const* getName(void) const { return "LLAvatarPickerResponder"; }
};
@@ -460,9 +536,7 @@ void LLFloaterAvatarPicker::find()
LLViewerRegion* region = gAgent.getRegion();
url = region->getCapability("AvatarPickerSearch");
// Prefer use of capabilities to search on both SLID and display name
// but allow display name search to be manually turned off for test
if (!url.empty()
&& LLAvatarNameCache::useDisplayNames())
if (!url.empty())
{
// capability urls don't end in '/', but we need one to parse
// query parameters correctly
@@ -471,6 +545,7 @@ void LLFloaterAvatarPicker::find()
url += "/";
}
url += "?page_size=100&names=";
std::replace(text.begin(), text.end(), '.', ' ');
url += LLURI::escape(text);
llinfos << "avatar picker " << url << llendl;
LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID));
@@ -595,8 +670,7 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*
// Not for us
if (agent_id != gAgent.getID()) return;
if(!instanceExists())
return;
if (!instanceExists()) return;
LLFloaterAvatarPicker* floater = getInstance();
// floater is closed or these are not results from our last request
@@ -620,35 +694,38 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*
msg->getUUIDFast( _PREHASH_Data,_PREHASH_AvatarID, avatar_id, i);
msg->getStringFast(_PREHASH_Data,_PREHASH_FirstName, first_name, i);
msg->getStringFast(_PREHASH_Data,_PREHASH_LastName, last_name, i);
std::string avatar_name;
if (avatar_id.isNull())
{
LLStringUtil::format_map_t map;
map["[TEXT]"] = floater->getChild<LLUICtrl>("Edit")->getValue().asString();
avatar_name = floater->getString("not_found", map);
search_results->setEnabled(FALSE);
floater->getChildView("ok_btn")->setEnabled(FALSE);
}
else
{
avatar_name = LLCacheName::buildFullName(first_name, last_name);
search_results->setEnabled(TRUE);
found_one = TRUE;
LLAvatarName av_name;
av_name.mLegacyFirstName = first_name;
av_name.mLegacyLastName = last_name;
av_name.mDisplayName = avatar_name;
const LLUUID& agent_id = avatar_id;
sAvatarNameMap[agent_id] = av_name;
if (avatar_id != agent_id || !floater->isExcludeAgentFromSearchResults()) // exclude agent from search results?
{
std::string avatar_name;
if (avatar_id.isNull())
{
LLStringUtil::format_map_t map;
map["[TEXT]"] = floater->getChild<LLUICtrl>("Edit")->getValue().asString();
avatar_name = floater->getString("not_found", map);
search_results->setEnabled(FALSE);
floater->getChildView("ok_btn")->setEnabled(FALSE);
}
else
{
avatar_name = LLCacheName::buildFullName(first_name, last_name);
search_results->setEnabled(TRUE);
found_one = TRUE;
LLAvatarName av_name;
av_name.mLegacyFirstName = first_name;
av_name.mLegacyLastName = last_name;
av_name.mDisplayName = avatar_name;
const LLUUID& agent_id = avatar_id;
sAvatarNameMap[agent_id] = av_name;
}
LLSD element;
element["id"] = avatar_id; // value
element["columns"][0]["column"] = "name";
element["columns"][0]["value"] = avatar_name;
search_results->addElement(element);
}
LLSD element;
element["id"] = avatar_id; // value
element["columns"][0]["column"] = "name";
element["columns"][0]["value"] = avatar_name;
search_results->addElement(element);
}
if (found_one)
@@ -690,18 +767,21 @@ void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD&
for ( ; it != agents.endArray(); ++it)
{
const LLSD& row = *it;
item["id"] = row["id"];
LLSD& columns = item["columns"];
columns[0]["column"] = "name";
columns[0]["value"] = row["display_name"];
columns[1]["column"] = "username";
columns[1]["value"] = row["username"];
search_results->addElement(item);
if (row["id"].asUUID() != gAgent.getID() || !mExcludeAgentFromSearchResults)
{
item["id"] = row["id"];
LLSD& columns = item["columns"];
columns[0]["column"] = "name";
columns[0]["value"] = row["display_name"];
columns[1]["column"] = "username";
columns[1]["value"] = row["username"];
search_results->addElement(item);
// add the avatar name to our list
LLAvatarName avatar_name;
avatar_name.fromLLSD(row);
sAvatarNameMap[row["id"].asUUID()] = avatar_name;
// add the avatar name to our list
LLAvatarName avatar_name;
avatar_name.fromLLSD(row);
sAvatarNameMap[row["id"].asUUID()] = avatar_name;
}
}
getChildView("ok_btn")->setEnabled(true);
@@ -713,10 +793,10 @@ void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD&
void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller)
{
if(caller->getName() == "Edit")
if (caller->getName() == "Edit")
getChildView("Find")->setEnabled(caller->getText().size() >= 3);
else
childSetEnabled("Select", caller->getValue().asUUID().notNull());
getChildView("Select")->setEnabled(caller->getValue().asUUID().notNull());
}
// virtual

View File

@@ -45,11 +45,15 @@ public:
// Call this to select an avatar.
static LLFloaterAvatarPicker* show(select_callback_t callback,
BOOL allow_multiple = FALSE,
BOOL closeOnSelect = FALSE);
BOOL closeOnSelect = FALSE,
BOOL skip_agent = FALSE,
const std::string& name = "",
LLView * frustumOrigin = NULL);
// do not call these directly
LLFloaterAvatarPicker();
virtual ~LLFloaterAvatarPicker();
virtual BOOL postBuild();
void setOkBtnEnableCb(validate_callback_t cb);
@@ -63,6 +67,7 @@ public:
std::string& tooltip_msg);
void openFriendsTab();
BOOL isExcludeAgentFromSearchResults() { return mExcludeAgentFromSearchResults; }
private:
void editKeystroke(class LLLineEditor* caller);
@@ -84,6 +89,7 @@ private:
void setAllowMultiple(BOOL allow_multiple);
LLScrollListCtrl* getActiveList();
void drawFrustum();
virtual void draw();
virtual BOOL handleKeyHere(KEY key, MASK mask);
@@ -91,6 +97,12 @@ private:
int mNumResultsReturned;
BOOL mNearMeListComplete;
BOOL mCloseOnSelect;
BOOL mExcludeAgentFromSearchResults;
LLHandle <LLView> mFrustumOrigin;
F32 mContextConeOpacity;
F32 mContextConeInAlpha;
F32 mContextConeOutAlpha;
F32 mContextConeFadeTime;
validate_signal_t mOkButtonValidateSignal;
select_callback_t mSelectionCallback;

View File

@@ -82,7 +82,7 @@ public:
virtual void pasteLinkFromClipboard() = 0;
virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0;
virtual BOOL isUpToDate() const = 0;
virtual BOOL hasChildren() const = 0;
virtual bool hasChildren() const = 0;
virtual LLInventoryType::EType getInventoryType() const = 0;
virtual void performAction(LLInventoryModel* model, std::string action) = 0;
virtual LLWearableType::EType getWearableType() const = 0;

View File

@@ -231,23 +231,25 @@ bool LLGiveInventory::doGiveInventoryItem(const LLUUID& to_agent,
return res;
}
void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent,
bool LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent,
const LLInventoryCategory* cat,
const LLUUID& im_session_id)
const LLUUID& im_session_id,
const std::string& notification_name)
{
if (!cat)
{
return;
return false;
}
llinfos << "LLGiveInventory::giveInventoryCategory() - "
<< cat->getUUID() << llendl;
if (!isAgentAvatarValid())
{
return;
return false;
}
bool give_successful = true;
// Test out how many items are being given.
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
@@ -270,24 +272,24 @@ void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent,
if(!complete)
{
LLNotificationsUtil::add("IncompleteInventory");
return;
give_successful = false;
}
count = items.count() + cats.count();
if(count > MAX_ITEMS)
{
LLNotificationsUtil::add("TooManyItems");
return;
give_successful = false;
}
else if(count == 0)
{
LLNotificationsUtil::add("NoItems");
return;
give_successful = false;
}
else
else if (give_successful)
{
if(0 == giveable.countNoCopy())
{
LLGiveInventory::commitGiveInventoryCategory(to_agent, cat, im_session_id);
give_successful = LLGiveInventory::commitGiveInventoryCategory(to_agent, cat, im_session_id);
}
else
{
@@ -296,9 +298,16 @@ void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent,
LLSD payload;
payload["agent_id"] = to_agent;
payload["folder_id"] = cat->getUUID();
if (!notification_name.empty())
{
payload["success_notification"] = notification_name;
}
LLNotificationsUtil::add("CannotCopyCountItems", args, payload, &LLGiveInventory::handleCopyProtectedCategory);
give_successful = false;
}
}
return give_successful;
}
//////////////////////////////////////////////////////////////////////////
@@ -377,6 +386,10 @@ bool LLGiveInventory::handleCopyProtectedItem(const LLSD& notification, const LL
give_successful = false;
}
}
if (give_successful && notification["payload"]["success_notification"].isDefined())
{
LLNotificationsUtil::add(notification["payload"]["success_notification"].asString());
}
break;
default: // no, cancel, whatever, who cares, not yes.
@@ -445,13 +458,14 @@ bool LLGiveInventory::handleCopyProtectedCategory(const LLSD& notification, cons
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLInventoryCategory* cat = NULL;
bool give_successful = true;
switch(option)
{
case 0: // "Yes"
cat = gInventory.getCategory(notification["payload"]["folder_id"].asUUID());
if(cat)
{
LLGiveInventory::commitGiveInventoryCategory(notification["payload"]["agent_id"].asUUID(),
give_successful = LLGiveInventory::commitGiveInventoryCategory(notification["payload"]["agent_id"].asUUID(),
cat);
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
@@ -467,29 +481,36 @@ bool LLGiveInventory::handleCopyProtectedCategory(const LLSD& notification, cons
gInventory.deleteObject(items.get(i)->getUUID());
}
gInventory.notifyObservers();
if (give_successful && notification["payload"]["success_notification"].isDefined())
{
LLNotificationsUtil::add(notification["payload"]["success_notification"].asString());
}
}
else
{
LLNotificationsUtil::add("CannotGiveCategory");
give_successful = false;
}
break;
default: // no, cancel, whatever, who cares, not yes.
LLNotificationsUtil::add("TransactionCancelled");
give_successful = false;
break;
}
return false;
return give_successful;
}
// static
void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
const LLInventoryCategory* cat,
const LLUUID& im_session_id)
{
if(!cat)
if (!cat)
{
return;
return false;
}
llinfos << "LLGiveInventory::commitGiveInventoryCategory() - "
<< cat->getUUID() << llendl;
@@ -504,6 +525,7 @@ void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
LLInventoryModel::EXCLUDE_TRASH,
giveable);
bool give_successful = true;
// MAX ITEMS is based on (sizeof(uuid)+2) * count must be <
// MTUBYTES or 18 * count < 1200 => count < 1200/18 =>
// 66. I've cut it down a bit from there to give some pad.
@@ -511,12 +533,12 @@ void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
if(count > MAX_ITEMS)
{
LLNotificationsUtil::add("TooManyItems");
return;
give_successful = false;
}
else if(count == 0)
{
LLNotificationsUtil::add("NoItems");
return;
give_successful = false;
}
else
{
@@ -589,6 +611,8 @@ void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
logInventoryOffer(to_agent, im_session_id);
}
return give_successful;
}
// EOF

View File

@@ -62,9 +62,11 @@ public:
/**
* Gives passed inventory category to specified avatar in specified session.
*/
static void doGiveInventoryCategory(const LLUUID& to_agent,
static bool doGiveInventoryCategory(const LLUUID& to_agent,
const LLInventoryCategory* item,
const LLUUID &session_id = LLUUID::null);
const LLUUID &session_id = LLUUID::null,
const std::string& notification = std::string());
// give inventory item functionality
static bool handleCopyProtectedItem(const LLSD& notification, const LLSD& response);
@@ -84,7 +86,7 @@ private:
// give inventory category functionality
static bool handleCopyProtectedCategory(const LLSD& notification, const LLSD& response);
static void commitGiveInventoryCategory(const LLUUID& to_agent,
static bool commitGiveInventoryCategory(const LLUUID& to_agent,
const LLInventoryCategory* cat,
const LLUUID &im_session_id = LLUUID::null);

View File

@@ -34,6 +34,7 @@
#include "llagentwearables.h"
#include "llappearancemgr.h"
#include "llavataractions.h"
#include "llfloaterperms.h"
#include "llfoldervieweventlistener.h"
#include "llimview.h"
@@ -627,6 +628,7 @@ void init_object_inventory_panel_actions(LLPanelObjectInventory *panel)
void init_inventory_actions(LLInventoryView *floater)
{
(new LLDoToSelectedFloater())->registerListener(floater, "Inventory.DoToSelected");
(new LLDoToSelectedFloater())->registerListener(floater, "Inventory.DoToSelected");
(new LLCloseAllFoldersFloater())->registerListener(floater, "Inventory.CloseAllFolders");
(new LLEmptyTrashFloater())->registerListener(floater, "Inventory.EmptyTrash");
@@ -640,6 +642,15 @@ void init_inventory_actions(LLInventoryView *floater)
(new LLSetSearchType())->registerListener(floater, "Inventory.SetSearchType");
}
class LLShare : public inventory_panel_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
LLAvatarActions::shareWithAvatars(mPtr);
return true;
}
};
void init_inventory_panel_actions(LLInventoryPanel *panel)
{
(new LLDoToSelected())->registerListener(panel, "Inventory.DoToSelected");
@@ -649,4 +660,5 @@ void init_inventory_panel_actions(LLInventoryPanel *panel)
(new LLEmptyLostAndFound())->registerListener(panel, "Inventory.EmptyLostAndFound");
(new LLDoCreate())->registerListener(panel, "Inventory.DoCreate");
(new LLBeginIMSession())->registerListener(panel, "Inventory.BeginIMSession");
(new LLShare())->registerListener(panel, "Inventory.Share");
}

View File

@@ -804,6 +804,12 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else
{
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
addOpenRightClickMenuOption(items);
items.push_back(std::string("Properties"));
@@ -1235,6 +1241,33 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
}
}
bool LLInvFVBridge::canShare() const
{
bool can_share = false;
if (!isItemInTrash() && isAgentInventory())
{
const LLInventoryModel* model = getInventoryModel();
if (model)
{
const LLViewerInventoryItem *item = model->getItem(mUUID);
if (item)
{
if (LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item))
{
can_share = LLGiveInventory::isInventoryGiveAcceptable(item);
}
}
else
{
// Categories can be given.
can_share = (model->getCategory(mUUID) != NULL);
}
}
}
return can_share;
}
bool LLInvFVBridge::canListOnMarketplace() const
{
@@ -2613,8 +2646,17 @@ void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer)
LLInventoryModel::item_array_t* item_array;
gInventory.getDirectDescendentsOf(*current_folder, cat_array, item_array);
S32 item_count = item_array->count();
S32 cat_count = cat_array->count();
S32 item_count(0);
if (item_array)
{
item_count = item_array->count();
}
S32 cat_count(0);
if (cat_array)
{
cat_count = cat_array->count();
}
// Move to next if current folder empty
if ((item_count == 0) && (cat_count == 0))
@@ -3387,6 +3429,15 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)
{
mDisabledItems.push_back(std::string("Delete System Folder"));
}
if (!isOutboxFolder() && !isItemInTrash()) // <alchemy/>
{
mItems.push_back(std::string("Share"));
if (!canShare())
{
mDisabledItems.push_back(std::string("Share"));
}
}
}
void LLFolderBridge::buildContextMenuFolderOptions(U32 flags)
@@ -3528,7 +3579,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
menu.arrangeAndClear();
}
BOOL LLFolderBridge::hasChildren() const
bool LLFolderBridge::hasChildren() const
{
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
@@ -4321,6 +4372,12 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else
{
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
addOpenRightClickMenuOption(items);
items.push_back(std::string("Properties"));
@@ -4412,6 +4469,11 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else
{
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
items.push_back(std::string("Sound Open"));
items.push_back(std::string("Properties"));
@@ -4465,6 +4527,11 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else
{
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
items.push_back(std::string("Landmark Open"));
items.push_back(std::string("Properties"));
@@ -4734,6 +4801,11 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else
{
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
/* Singu Note: Multiple profiles get opened in a multifloater
if ((flags & FIRST_SELECTED_ITEM) == 0)
{
@@ -5039,6 +5111,11 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else
{
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
addOpenRightClickMenuOption(items);
items.push_back(std::string("Properties"));
@@ -5094,6 +5171,11 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else
{
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
items.push_back(std::string("Animation Open"));
items.push_back(std::string("Properties"));
@@ -5411,6 +5493,12 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else
{
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
items.push_back(std::string("Properties"));
getClipboardEntries(true, items, disabled_items, flags);
@@ -5819,6 +5907,12 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
can_open = FALSE;
}
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
if (can_open)
{
addOpenRightClickMenuOption(items);

View File

@@ -69,6 +69,7 @@ public:
U32 flags = 0x00);
virtual ~LLInvFVBridge() {}
bool canShare() const;
bool canListOnMarketplace() const;
bool canListOnMarketplaceNow() const;
@@ -121,6 +122,8 @@ public:
void* cargo_data) { return FALSE; }
virtual LLInventoryType::EType getInventoryType() const { return mInvType; }
virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; }
virtual LLInventoryObject* getInventoryObject() const;
//--------------------------------------------------------------------
// Convenience functions for adding various common menu options.
@@ -137,16 +140,15 @@ protected:
protected:
LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid);
LLInventoryObject* getInventoryObject() const;
LLInventoryModel* getInventoryModel() const;
BOOL isLinkedObjectInTrash() const; // Is this obj or its baseobj in the trash?
BOOL isLinkedObjectMissing() const; // Is this a linked obj whose baseobj is not in inventory?
BOOL isAgentInventory() const; // false if lost or in the inventory library
BOOL isCOFFolder() const; // true if COF or descendent of
BOOL isInboxFolder() const; // true if COF or descendent of marketplace inbox
BOOL isOutboxFolder() const; // true if COF or descendent of marketplace outbox
BOOL isCOFFolder() const; // true if COF or descendant of
BOOL isInboxFolder() const; // true if COF or descendant of marketplace inbox
BOOL isOutboxFolder() const; // true if COF or descendant of marketplace outbox
BOOL isOutboxFolderDirectParent() const;
const LLUUID getOutboxFolder() const;
@@ -165,7 +167,7 @@ protected:
LLFolderView* mRoot;
const LLUUID mUUID; // item id
LLInventoryType::EType mInvType;
BOOL mIsLink;
bool mIsLink;
void purgeItem(LLInventoryModel *model, const LLUUID &uuid);
};
@@ -213,7 +215,7 @@ public:
virtual BOOL renameItem(const std::string& new_name);
virtual BOOL removeItem();
virtual BOOL isItemCopyable() const;
virtual BOOL hasChildren() const { return FALSE; }
virtual bool hasChildren() const { return FALSE; }
virtual BOOL isUpToDate() const { return TRUE; }
static void showFloaterImagePreview(LLInventoryItem* item, AIFilePicker* filepicker);
@@ -235,8 +237,8 @@ class LLFolderBridge : public LLInvFVBridge
public:
LLFolderBridge(LLInventoryPanel* inventory,
LLFolderView* root,
const LLUUID& uuid) :
LLInvFVBridge(inventory, root, uuid),
const LLUUID& uuid)
: LLInvFVBridge(inventory, root, uuid),
mCallingCards(FALSE),
mWearables(FALSE)
{}
@@ -265,7 +267,7 @@ public:
virtual void pasteFromClipboard(bool only_copies = false);
virtual void pasteLinkFromClipboard();
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
virtual BOOL hasChildren() const;
virtual bool hasChildren() const;
virtual BOOL dragOrDrop(MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data);
@@ -326,8 +328,9 @@ public:
static void staticFolderOptionsMenu();
private:
BOOL mCallingCards;
BOOL mWearables;
bool mCallingCards;
bool mWearables;
menuentry_vec_t mItems;
menuentry_vec_t mDisabledItems;
LLRootHandle<LLFolderBridge> mHandle;
@@ -405,7 +408,6 @@ protected:
LLCallingCardObserver* mObserver;
};
class LLNotecardBridge : public LLItemBridge
{
public:
@@ -436,7 +438,6 @@ public:
static void playGesture(const LLUUID& item_id);
};
class LLAnimationBridge : public LLItemBridge
{
public:
@@ -450,7 +451,6 @@ public:
virtual void openItem();
};
class LLObjectBridge : public LLItemBridge
{
public:
@@ -515,8 +515,6 @@ public:
void editOnAvatar();
static BOOL canRemoveFromAvatar( void* userdata );
//static void onRemoveFromAvatar( void* userdata );
//static void onRemoveFromAvatarArrived( LLViewerWearable* wearable, void* userdata );
//static void removeAllClothesFromAvatar();
void removeFromAvatar();
protected:
@@ -629,7 +627,8 @@ public:
class LLRecentInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder
{
public:
LLRecentInventoryBridgeBuilder(): LLInventoryFVBridgeBuilder() {}
LLRecentInventoryBridgeBuilder() {}
// Overrides FolderBridge for Recent Inventory Panel.
// It use base functionality for bridges other than FolderBridge.
virtual LLInvFVBridge* createBridge(LLAssetType::EType asset_type,

View File

@@ -137,7 +137,7 @@ public:
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
virtual void performAction(LLInventoryModel* model, std::string action);
virtual BOOL isUpToDate() const { return TRUE; }
virtual BOOL hasChildren() const { return FALSE; }
virtual bool hasChildren() const { return FALSE; }
virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; }
virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; }
@@ -872,7 +872,7 @@ public:
virtual BOOL renameItem(const std::string& new_name);
virtual BOOL isItemRemovable() const;
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
virtual BOOL hasChildren() const;
virtual bool hasChildren() const;
virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;
virtual BOOL dragOrDrop(MASK mask, BOOL drop,
EDragAndDropType cargo_type,
@@ -922,7 +922,7 @@ void LLTaskCategoryBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
hide_context_entries(menu, items, disabled_items);
}
BOOL LLTaskCategoryBridge::hasChildren() const
bool LLTaskCategoryBridge::hasChildren() const
{
// return TRUE if we have or do know know if we have children.
// *FIX: For now, return FALSE - we will know for sure soon enough.

View File

@@ -0,0 +1,67 @@
/**
* @file llshareavatarhandler.cpp
* @brief slapp to handle sharing with an avatar
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, 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 "llcommandhandler.h"
#include "llavataractions.h"
#include "llnotificationsutil.h"
#include "llui.h"
class LLShareWithAvatarHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
LLShareWithAvatarHandler() : LLCommandHandler("sharewithavatar", UNTRUSTED_THROTTLE)
{
}
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
{
/*if (!LLUI::sSettingGroups["config"]->getBOOL("EnableAvatarShare"))
{
LLNotificationsUtil::add("NoAvatarShare", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
return true;
}*/
//Make sure we have some parameters
if (params.size() == 0)
{
return false;
}
//Get the ID
LLUUID id;
if (!id.set( params[0], FALSE))
{
return false;
}
//instigate share with this avatar
LLAvatarActions::share(id);
return true;
}
};
LLShareWithAvatarHandler gShareWithAvatar;

View File

@@ -2930,6 +2930,7 @@ class LLObjectImportUpload : public view_listener_t
//---------------------------------------------------------------------------
// Parcel freeze, eject, etc.
//---------------------------------------------------------------------------
void send_freeze(const LLUUID& avatar_id, bool freeze);
bool callback_freeze(const LLSD& notification, const LLSD& response)
{
LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
@@ -2937,27 +2938,7 @@ bool callback_freeze(const LLSD& notification, const LLSD& response)
if (0 == option || 1 == option)
{
U32 flags = KICK_FLAGS_FREEZE;
if (1 == option)
{
// unfreeze
flags |= KICK_FLAGS_UNFREEZE;
}
LLMessageSystem* msg = gMessageSystem;
LLVOAvatar* avatarp = gObjectList.findAvatar(avatar_id);
if (avatarp && avatarp->getRegion())
{
msg->newMessage("FreezeUser");
msg->nextBlock("AgentData");
msg->addUUID("AgentID", gAgent.getID());
msg->addUUID("SessionID", gAgent.getSessionID());
msg->nextBlock("Data");
msg->addUUID("TargetID", avatar_id );
msg->addU32("Flags", flags );
msg->sendReliable( avatarp->getRegion()->getHost() );
}
send_freeze(avatar_id, !option);
}
return false;
}
@@ -9105,6 +9086,15 @@ class ListRequestTeleport : public view_listener_t
}
};
class ListShare : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
LLAvatarActions::share(get_focused_list_id_selected());
return true;
}
};
class ListShowProfile : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
@@ -9559,6 +9549,7 @@ void initialize_menus()
addMenu(new ListRemoveFriend(), "List.RemoveFriend");
addMenu(new ListRequestFriendship(), "List.RequestFriendship");
addMenu(new ListRequestTeleport(), "List.RequestTeleport");
addMenu(new ListShare(), "List.Share");
addMenu(new ListShowProfile(), "List.ShowProfile");
addMenu(new ListShowWebProfile(), "List.ShowWebProfile");
addMenu(new ListStartAdhocCall(), "List.StartAdhocCall");

View File

@@ -56,6 +56,10 @@
<on_click function="List.RequestTeleport"/>
<on_visible function="List.EnableSingleSelected"/>
</menu_item_call>
<menu_item_call label="Share" name="Share">
<on_click function="List.Share"/>
<on_visible function="List.EnableSingleSelected"/>
</menu_item_call>
<menu_item_separator/>
<menu_item_call label="Mute/Unmute" name="Mute/Unmute">
<on_click function="List.ToggleMute"/>

View File

@@ -1,6 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<menu bottom="100" color="MenuDefaultBgColor" drop_shadow="true" height="101" left="100"
mouse_opaque="false" name="Popup" opaque="true" width="128">
<menu_item_call
label="Share"
layout="topleft"
name="Share"
visible="true">
<menu_item_call.on_click
function="Inventory.Share" />
</menu_item_call>
<menu_item_call bottom_delta="-18" height="18" label="Buy" left="0" mouse_opaque="true"
name="Task Buy" width="128">
<on_click filter="" function="Inventory.DoToSelected" userdata="task_buy" />

View File

@@ -57,6 +57,10 @@
<on_click function="List.RequestTeleport"/>
<on_visible function="List.EnableSingleSelected"/>
</menu_item_call>
<menu_item_call label="Share" name="Share">
<on_click function="List.Share"/>
<on_visible function="List.EnableSingleSelected"/>
</menu_item_call>
<menu_item_call label="Track/Untrack" name="Track/Untrack">
<on_click function="Radar.Track"/>
<on_enable function="List.EnableSingleSelected"/>

View File

@@ -2142,15 +2142,6 @@ Multiple parcels selected.
Try selecting a single parcel.
</notification>
<notification
icon="notifytip.tga"
name="DeedToGroupFail"
type="notifytip">
Deed to group failed.
<tag>group</tag>
<tag>fail</tag>
</notification>
<notification
icon="alertmodal.tga"
name="ParcelCanPlayMedia"
@@ -7738,6 +7729,13 @@ Server Error: Media update or get failed.
yestext="OK"/>
</notification>
<notification
icon="notifytip.tga"
name="ShareNotification"
type="notifytip">
Select residents to share with.
</notification>
<notification
name="MeshUploadError"
icon="alert.tga"
@@ -7761,6 +7759,61 @@ See the log file for details.
Could not get region capability &apos;[CAPABILITY]&apos;.
</notification>
<notification
icon="notifytip.tga"
name="ShareItemsConfirmation"
type="alertmodal">
Are you sure you want to share the following items:
[ITEMS]
With the following Residents:
[RESIDENTS]
<tag>confirm</tag>
<usetemplate
name="okcancelbuttons"
notext="Cancel"
yestext="OK"/>
</notification>
<notification
icon="notifytip.tga"
name="ShareFolderConfirmation"
type="alertmodal">
Only one folder at a time can be shared.
Are you sure you want to share the following items:
[ITEMS]
With the following Residents:
[RESIDENTS]
<tag>confirm</tag>
<usetemplate
name="okcancelbuttons"
notext="Cancel"
yestext="Ok"/>
</notification>
<notification
icon="notifytip.tga"
name="ItemsShared"
type="notifytip">
Items successfully shared.
</notification>
<notification
icon="notifytip.tga"
name="DeedToGroupFail"
type="notifytip">
Deed to group failed.
<tag>group</tag>
<tag>fail</tag>
</notification>
<notification
icon="notifytip.tga"
name="AvatarRezNotification"

View File

@@ -4185,6 +4185,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="inventory_item_offered_rlv">
Inventory item offered to [NAME]
</string>
<string name="share_alert">
Drag items from inventory here
</string>
<string name="only_user_message">