diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llui/llfolderview.cpp | 9 | ||||
| -rw-r--r-- | indra/llui/llfolderview.h | 2 | ||||
| -rw-r--r-- | indra/newview/llconversationmodel.cpp | 43 | ||||
| -rwxr-xr-x | indra/newview/llconversationmodel.h | 19 | ||||
| -rw-r--r-- | indra/newview/llimfloater.h | 1 | ||||
| -rw-r--r-- | indra/newview/llimfloatercontainer.cpp | 199 | ||||
| -rw-r--r-- | indra/newview/llimfloatercontainer.h | 5 | ||||
| -rw-r--r-- | indra/newview/llinventorypanel.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_conversation.xml | 109 | 
9 files changed, 383 insertions, 5 deletions
| diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index ce1bc5914c..9a4a90206b 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -138,7 +138,8 @@ LLFolderView::Params::Params()  	use_label_suffix("use_label_suffix"),  	allow_multiselect("allow_multiselect", true),  	show_empty_message("show_empty_message", true), -	use_ellipses("use_ellipses", false) +	use_ellipses("use_ellipses", false), +    options_menu("options_menu", "")  {  	folder_indentation = -4;  } @@ -228,7 +229,7 @@ LLFolderView::LLFolderView(const Params& p)  	// make the popup menu available -	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); +	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(p.options_menu, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());  	if (!menu)  	{  		menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu"); @@ -1530,14 +1531,18 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )  		&& menu )  	{  		if (mCallbackRegistrar) +        {  			mCallbackRegistrar->pushScope(); +        }  		updateMenuOptions(menu);  		menu->updateParent(LLMenuGL::sMenuContainer);  		LLMenuGL::showPopup(this, menu, x, y);  		if (mCallbackRegistrar) +        {  			mCallbackRegistrar->popScope(); +        }  	}  	else  	{ diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 81b0f087e8..487391a477 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -94,6 +94,8 @@ public:  								use_ellipses,  								show_item_link_overlays;  		Mandatory<LLFolderViewModelInterface*>	view_model; +        Mandatory<std::string>   options_menu; +  		Params();  	}; diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 9fa8758d11..265f77365f 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -84,6 +84,24 @@ void LLConversationItem::showProperties(void)  {  } +void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t&   items) +{ +    items.push_back(std::string("view_profile")); +    items.push_back(std::string("im")); +    items.push_back(std::string("offer_teleport")); +    items.push_back(std::string("voice_call")); +    items.push_back(std::string("chat_history")); +    items.push_back(std::string("separator_chat_history")); +    items.push_back(std::string("add_friend")); +    items.push_back(std::string("remove_friend")); +    items.push_back(std::string("invite_to_group")); +    items.push_back(std::string("separator_invite_to_group")); +    items.push_back(std::string("map")); +    items.push_back(std::string("share")); +    items.push_back(std::string("pay")); +    items.push_back(std::string("block_unblock")); +} +  //  // LLConversationItemSession  //  @@ -191,6 +209,22 @@ void LLConversationItemSession::setDistance(const LLUUID& participant_id, F64 di  	}  } +void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags) +{ +    lldebugs << "LLConversationItemParticipant::buildContextMenu()" << llendl; +    menuentry_vec_t items; +    menuentry_vec_t disabled_items; + +    if(this->getType() == CONV_SESSION_1_ON_1) +    { +        items.push_back(std::string("close_conversation")); +        items.push_back(std::string("separator_disconnect_from_voice")); +        buildParticipantMenuOptions(items); +    } + +    hide_context_entries(menu, items, disabled_items); +} +  // The time of activity of a session is the time of the most recent activity, session and participants included  const bool LLConversationItemSession::getTime(F64& time) const  { @@ -249,6 +283,15 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid,  	mConvType = CONV_PARTICIPANT;  } +void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) +{ +    menuentry_vec_t items; +    menuentry_vec_t disabled_items; + +    buildParticipantMenuOptions(items); +    hide_context_entries(menu, items, disabled_items); +} +  void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name)  {  	mName = (av_name.mUsername.empty() ? av_name.mDisplayName : av_name.mUsername); diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 30f94d51ae..f84fbe39f1 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -41,6 +41,8 @@ class LLConversationItemParticipant;  typedef std::map<LLUUID, LLConversationItem*> conversations_items_map;  typedef std::map<LLUUID, LLFolderViewItem*> conversations_widgets_map; +typedef std::vector<std::string> menuentry_vec_t; +  // Conversation items: we hold a list of those and create an LLFolderViewItem widget for each    // that we tuck into the mConversationsListPanel.   class LLConversationItem : public LLFolderViewModelItemCommon @@ -124,6 +126,8 @@ public:  	void resetRefresh() { mNeedsRefresh = false; }  	bool needsRefresh() { return mNeedsRefresh; } +    void buildParticipantMenuOptions(menuentry_vec_t&   items); +  protected:  	std::string mName;	// Name of the session or the participant  	LLUUID mUUID;		// UUID of the session or the participant @@ -155,6 +159,7 @@ public:  	bool isLoaded() { return mIsLoaded; } +    void buildContextMenu(LLMenuGL& menu, U32 flags);  	virtual const bool getTime(F64& time) const;  	void dumpDebugData(); @@ -178,7 +183,8 @@ public:  	void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; }  	void setTimeNow() { mLastActiveTime = LLFrameTimer::getElapsedSeconds(); mNeedsRefresh = true; }  	void setDistance(F64 dist) { mDistToAgent = dist; mNeedsRefresh = true; } -	 + +    void buildContextMenu(LLMenuGL& menu, U32 flags);  	void onAvatarNameCache(const LLAvatarName& av_name);  	virtual const bool getDistanceToAgent(F64& dist) const { dist = mDistToAgent; return (dist >= 0.0); } @@ -273,4 +279,15 @@ public:  private:  }; +// Utility function to hide all entries except those in the list +// Can be called multiple times on the same menu (e.g. if multiple items +// are selected).  If "append" is false, then only common enabled items +// are set as enabled. + +//(defined in inventorybridge.cpp) +//TODO: Gilbert Linden - Refactor to make this function non-global +void hide_context_entries(LLMenuGL& menu,  +    const menuentry_vec_t &entries_to_show,  +    const menuentry_vec_t &disabled_entries); +  #endif // LL_LLCONVERSATIONMODEL_H diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index d444270716..5ed1d1ab35 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -127,6 +127,7 @@ public:  	static void onIMChicletCreated(const LLUUID& session_id);  	bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; } +    const LLUUID& getOtherParticipantUUID() {return mOtherParticipantUUID;}  	static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb);  	static floater_showed_signal_t sIMFloaterShowedSignal; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 6f7eb7822a..d25a195f33 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -58,8 +58,12 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed)  	mConversationsRoot(NULL),  	mInitialized(false)  { +    mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLIMFloaterContainer::isActionChecked, this, _2));  	mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLIMFloaterContainer::onCustomAction,  this, _2)); -	mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLIMFloaterContainer::isActionChecked, this, _2)); +	 +    mEnableCallbackRegistrar.add("Avatar.CheckItem",  boost::bind(&LLIMFloaterContainer::checkContextMenuItem,	this, _2)); +    mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLIMFloaterContainer::enableContextMenuItem,	this, _2)); +    mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLIMFloaterContainer::doToSelected, this, _2));  	// Firstly add our self to IMSession observers, so we catch session events      LLIMMgr::getInstance()->addSessionObserver(this); @@ -134,7 +138,9 @@ BOOL LLIMFloaterContainer::postBuild()      p.view_model = &mConversationViewModel;      p.root = NULL;      p.use_ellipses = true; +    p.options_menu = "menu_conversation.xml";  	mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); +    mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);  	// a scroller for folder view  	LLRect scroller_view_rect = mConversationsListPanel->getRect(); @@ -547,7 +553,7 @@ void LLIMFloaterContainer::collapseConversationsPane(bool collapse)  		    {  		    	widget->setOpen(false);  		    } -		} +}  	}  } @@ -711,6 +717,195 @@ void LLIMFloaterContainer::setSortOrder(const LLConversationSort& order)  	gSavedSettings.setU32("ConversationSortOrder", (U32)order);  } +void LLIMFloaterContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids) +{ +    const std::set<LLFolderViewItem*> selectedItems = mConversationsRoot->getSelectionList(); + +    std::set<LLFolderViewItem*>::const_iterator it = selectedItems.begin(); +    const std::set<LLFolderViewItem*>::const_iterator it_end = selectedItems.end(); +    LLConversationItem * conversationItem; + +    for (; it != it_end; ++it) +    { +        conversationItem = static_cast<LLConversationItem *>((*it)->getViewModelItem()); +        selected_uuids.push_back(conversationItem->getUUID()); +    } +} +void LLIMFloaterContainer::doToSelected(const LLSD& userdata) +{ +    std::string command = userdata.asString(); +    uuid_vec_t selected_uuids; +    LLUUID currentSelectedUUID; +    LLIMFloater * conversation; + +    getSelectedUUIDs(selected_uuids); +    //Find the conversation floater associated with the selected id +    conversation = LLIMFloater::findInstance(selected_uuids.front()); + +    //When a one-on-one conversation exists, retrieve the participant id from the conversation floater b/c +    //selected_uuids.front() does not pertain to the UUID of the person you are having the conversation with. +    if(conversation &&  +           mConversationsRoot &&  +           mConversationsRoot->getCurSelectedItem() &&  +           mConversationsRoot->getCurSelectedItem()->getViewModelItem() && +        static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem())->getType() == LLConversationItem::CONV_SESSION_1_ON_1) +    { +        currentSelectedUUID = conversation->getOtherParticipantUUID(); +    } +    //Otherwise can get the UUID directly from selected_uuids +    else +    { +        currentSelectedUUID = selected_uuids.front(); +    } + +    //Close the selected conversation +    if(conversation && "close_conversation" == command) +    { +        LLFloater::onClickClose(conversation); +    } +    else if ("view_profile" == command) +    { +        LLAvatarActions::showProfile(currentSelectedUUID); +    } +    else if("im" == command) +    { +        LLAvatarActions::startIM(currentSelectedUUID); +    } +    else if("offer_teleport" == command) +    { +        LLAvatarActions::offerTeleport(selected_uuids); +    } +    else if("voice_call" == command) +    { +        LLAvatarActions::startCall(currentSelectedUUID); +    } +    else if("add_friend" == command) +    { +        LLAvatarActions::requestFriendshipDialog(currentSelectedUUID); +    } +    else if("remove_friend" == command) +    { +        LLAvatarActions::removeFriendDialog(currentSelectedUUID); +    } +    else if("invite_to_group" == command) +    { +        LLAvatarActions::inviteToGroup(currentSelectedUUID); +    } +    else if("map" == command) +    { +        LLAvatarActions::showOnMap(currentSelectedUUID); +    } +    else if("share" == command) +    { +        LLAvatarActions::share(currentSelectedUUID); +    } +    else if("pay" == command) +    { +        LLAvatarActions::pay(currentSelectedUUID); +    } +    else if("block_unblock" == command) +    { +        LLAvatarActions::toggleBlock(currentSelectedUUID); +    } +} + +bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) +{ +    std::string item = userdata.asString(); +    uuid_vec_t mUUIDs; +    getSelectedUUIDs(mUUIDs); + +    // Note: can_block and can_delete is used only for one person selected menu +    // so we don't need to go over all uuids. + +    if (item == std::string("can_block")) +    { +        const LLUUID& id = mUUIDs.front(); +        return LLAvatarActions::canBlock(id); +    } +    else if (item == std::string("can_add")) +    { +        // We can add friends if: +        // - there are selected people +        // - and there are no friends among selection yet. + +        //EXT-7389 - disable for more than 1 +        if(mUUIDs.size() > 1) +        { +            return false; +        } + +        bool result = (mUUIDs.size() > 0); + +        uuid_vec_t::const_iterator +            id = mUUIDs.begin(), +            uuids_end = mUUIDs.end(); + +        for (;id != uuids_end; ++id) +        { +            if ( LLAvatarActions::isFriend(*id) ) +            { +                result = false; +                break; +            } +        } + +        return result; +    } +    else if (item == std::string("can_delete")) +    { +        // We can remove friends if: +        // - there are selected people +        // - and there are only friends among selection. + +        bool result = (mUUIDs.size() > 0); + +        uuid_vec_t::const_iterator +            id = mUUIDs.begin(), +            uuids_end = mUUIDs.end(); + +        for (;id != uuids_end; ++id) +        { +            if ( !LLAvatarActions::isFriend(*id) ) +            { +                result = false; +                break; +            } +        } + +        return result; +    } +    else if (item == std::string("can_call")) +    { +        return LLAvatarActions::canCall(); +    } +    else if (item == std::string("can_show_on_map")) +    { +        const LLUUID& id = mUUIDs.front(); + +        return (LLAvatarTracker::instance().isBuddyOnline(id) && is_agent_mappable(id)) +            || gAgent.isGodlike(); +    } +    else if(item == std::string("can_offer_teleport")) +    { +        return LLAvatarActions::canOfferTeleport(mUUIDs); +    } +    return false; +} + +bool LLIMFloaterContainer::checkContextMenuItem(const LLSD& userdata) +{ +    std::string item = userdata.asString(); +    const LLUUID& id = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem())->getUUID(); + +    if (item == std::string("is_blocked")) +    { +        return LLAvatarActions::isBlocked(id); +    } + +    return false; +} +  void LLIMFloaterContainer::setConvItemSelect(const LLUUID& session_id)  {  	LLFolderViewItem* widget = mConversationsWidgets[session_id]; diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 2debc2455b..49a41e5cdd 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -111,6 +111,11 @@ private:  	void setSortOrderParticipants(const LLConversationFilter::ESortOrderType order);  	void setSortOrder(const LLConversationSort& order); +    void getSelectedUUIDs(uuid_vec_t& selected_uuids); +    void doToSelected(const LLSD& userdata); +    bool checkContextMenuItem(const LLSD& userdata); +    bool enableContextMenuItem(const LLSD& userdata); +  	LLButton* mExpandCollapseBtn;  	LLLayoutPanel* mMessagesPane;  	LLLayoutPanel* mConversationsPane; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index a77b57638f..a8d99ad7de 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -172,6 +172,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )      p.show_empty_message = mShowEmptyMessage;      p.show_item_link_overlays = mShowItemLinkOverlays;      p.root = NULL; +    p.options_menu = "menu_inventory.xml";      return LLUICtrlFactory::create<LLFolderView>(p);  } diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml new file mode 100644 index 0000000000..94399be61c --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + bottom="806" + layout="topleft" + left="0" + mouse_opaque="false" + name="menu_conversation_participant" + visible="false"> +     <menu_item_call +     label="Close conversation" +     layout="topleft" +     name="close_conversation"> +        <on_click function="Avatar.DoToSelected" parameter="close_conversation"/> +	 </menu_item_call> +     <menu_item_call +     label="Open voice conversation" +     layout="topleft" +     name="open_voice_conversation"> +        <on_click function="Avatar.DoToSelected" parameter="open_voice_conversation"/> +     </menu_item_call>	 +     <menu_item_call +     label="Disconnect from voice" +     layout="topleft" +     name="disconnect_from_voice"> +        <on_click function="Avatar.DoToSelected" parameter="disconnect_from_voice"/> +    </menu_item_call>	 +	<menu_item_separator layout="topleft" name="separator_disconnect_from_voice"/>	 +    <menu_item_call +     label="View Profile" +     layout="topleft" +     name="view_profile"> +        <on_click function="Avatar.DoToSelected" parameter="view_profile"/> +    </menu_item_call> +    <menu_item_call +     label="IM" +     layout="topleft" +     name="im"> +        <on_click function="Avatar.DoToSelected" parameter="im"/> +    </menu_item_call> +    <menu_item_call +     label="Offer teleport" +     layout="topleft" +     name="offer_teleport"> +        <on_click function="Avatar.DoToSelected" parameter="offer_teleport"/> +        <on_enable function="Avatar.EnableItem" parameter="can_offer_teleport"/> +    </menu_item_call> +    <menu_item_call +     label="Voice call" +     layout="topleft" +     name="voice_call"> +        <on_click function="Avatar.DoToSelected" parameter="voice_call"/> +        <on_enable function="Avatar.EnableItem" parameter="can_call" /> +    </menu_item_call> +    <menu_item_call +     label="Chat history..." +     layout="topleft" +     name="chat_history"> +        <on_click function="Avatar.DoToSelected" parameter="chat_history"/> +    </menu_item_call>	 +    <menu_item_separator layout="topleft" name="separator_chat_history"/>	 +    <menu_item_call +     label="Add friend" +     layout="topleft" +     name="add_friend"> +        <on_click function="Avatar.DoToSelected" parameter="add_friend"/> +        <on_enable function="Avatar.EnableItem" parameter="can_add" /> +    </menu_item_call> +    <menu_item_call +     label="Remove friend" +     layout="topleft" +     name="remove_friend"> +        <on_click function="Avatar.DoToSelected" parameter="remove_friend" /> +        <on_enable function="Avatar.EnableItem" parameter="can_delete" /> +    </menu_item_call>	 +    <menu_item_call +     label="Invite to group..." +     layout="topleft" +     name="invite_to_group"> +        <on_click function="Avatar.DoToSelected" parameter="invite_to_group" /> +    </menu_item_call> +    <menu_item_separator layout="topleft" name="separator_invite_to_group"/>		 +    <menu_item_call +     label="Map" +     layout="topleft" +     name="map"> +        <on_click function="Avatar.DoToSelected" parameter="map" /> +        <on_enable function="Avatar.EnableItem" parameter="can_show_on_map" /> +    </menu_item_call> +    <menu_item_call +     label="Share" +     layout="topleft" +     name="share"> +        <on_click function="Avatar.DoToSelected" parameter="share" /> +    </menu_item_call> +    <menu_item_call +     label="Pay" +     layout="topleft" +     name="pay"> +        <on_click function="Avatar.DoToSelected" parameter="pay" /> +    </menu_item_call> +    <menu_item_check +     label="Block / unblock" +     layout="topleft" +     name="block_unblock"> +        <on_click function="Avatar.DoToSelected" parameter="block_unblock" /> +		<on_check function="Avatar.CheckItem" parameter="is_blocked" /> +		<on_enable  function="Avatar.EnableItem" parameter="can_block" /> +    </menu_item_check> +</toggleable_menu> | 
