diff options
-rw-r--r-- | indra/llui/llfolderview.h | 1 | ||||
-rw-r--r-- | indra/newview/llconversationmodel.cpp | 7 | ||||
-rw-r--r-- | indra/newview/llfloaterimcontainer.cpp | 250 | ||||
-rw-r--r-- | indra/newview/llfloaterimcontainer.h | 11 | ||||
-rw-r--r-- | indra/newview/llfloaterimnearbychat.cpp | 21 | ||||
-rw-r--r-- | indra/newview/llfloaterimnearbychat.h | 2 | ||||
-rw-r--r-- | indra/newview/llfloaterimsessiontab.cpp | 59 | ||||
-rw-r--r-- | indra/newview/llfloaterimsessiontab.h | 7 | ||||
-rw-r--r-- | indra/newview/llinventoryfunctions.cpp | 2 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/menu_conversation.xml | 12 |
10 files changed, 227 insertions, 145 deletions
diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 487391a477..525efe425a 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -148,7 +148,6 @@ public: virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); virtual std::set<LLFolderViewItem*> getSelectionList() const; - S32 getNumSelectedItems() { return mSelectedItems.size(); } // Make sure if ancestor is selected, descendants are not void sanitizeSelection(); diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 1c56bd672d..0837a49095 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -27,7 +27,6 @@ #include "llviewerprecompiledheaders.h" -#include "llagent.h" #include "llavatarnamecache.h" #include "llavataractions.h" #include "llevents.h" @@ -422,10 +421,8 @@ void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t items; menuentry_vec_t disabled_items; - if(gAgent.getID() != mUUID) - { - buildParticipantMenuOptions(items); - } + buildParticipantMenuOptions(items); + hide_context_entries(menu, items, disabled_items); } diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 304fb78260..ae66a5f2cf 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -99,7 +99,6 @@ LLFloaterIMContainer::~LLFloaterIMContainer() void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, BOOL has_offline_msg) { - llinfos << "Merov debug : sessionAdded, uuid = " << session_id << ", name = " << name << llendl; addConversationListItem(session_id); LLFloaterIMSessionTab::addToHost(session_id); } @@ -877,67 +876,83 @@ void LLFloaterIMContainer::getParticipantUUIDs(uuid_vec_t& selected_uuids) void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec_t& selectedIDS) { - if(selectedIDS.size() > 0) + if (selectedIDS.size() == 1) { const LLUUID& userID = selectedIDS.front(); - if(gAgent.getID() != userID) + if ("view_profile" == command) { - if ("view_profile" == command) - { - LLAvatarActions::showProfile(userID); - } - else if("im" == command) - { - LLAvatarActions::startIM(userID); - } - else if("offer_teleport" == command) - { - LLAvatarActions::offerTeleport(selectedIDS); - } - else if("voice_call" == command) - { - LLAvatarActions::startCall(userID); - } - else if("chat_history" == command) - { - LLAvatarActions::viewChatHistory(userID); - } - else if("add_friend" == command) - { - LLAvatarActions::requestFriendshipDialog(userID); - } - else if("remove_friend" == command) - { - LLAvatarActions::removeFriendDialog(userID); - } - else if("invite_to_group" == command) - { - LLAvatarActions::inviteToGroup(userID); - } - else if("map" == command) - { - LLAvatarActions::showOnMap(userID); - } - else if("share" == command) - { - LLAvatarActions::share(userID); - } - else if("pay" == command) - { - LLAvatarActions::pay(userID); - } - else if("block_unblock" == command) - { - LLAvatarActions::toggleBlock(userID); - } - else if("selected" == command || "mute_all" == command || "unmute_all" == command) - { - moderateVoice(command, userID); - } - else if ("toggle_allow_text_chat" == command) - { - toggleAllowTextChat(userID); - } + LLAvatarActions::showProfile(userID); + } + else if ("im" == command) + { + LLAvatarActions::startIM(userID); + } + else if ("offer_teleport" == command) + { + LLAvatarActions::offerTeleport(selectedIDS); + } + else if ("voice_call" == command) + { + LLAvatarActions::startCall(userID); + } + else if ("chat_history" == command) + { + LLAvatarActions::viewChatHistory(userID); + } + else if ("add_friend" == command) + { + LLAvatarActions::requestFriendshipDialog(userID); + } + else if ("remove_friend" == command) + { + LLAvatarActions::removeFriendDialog(userID); + } + else if ("invite_to_group" == command) + { + LLAvatarActions::inviteToGroup(userID); + } + else if ("map" == command) + { + LLAvatarActions::showOnMap(userID); + } + else if ("share" == command) + { + LLAvatarActions::share(userID); + } + else if ("pay" == command) + { + LLAvatarActions::pay(userID); + } + else if ("block_unblock" == command) + { + LLAvatarActions::toggleBlock(userID); + } + else if ("selected" == command || "mute_all" == command || "unmute_all" == command) + { + moderateVoice(command, userID); + } + else if ("toggle_allow_text_chat" == command) + { + toggleAllowTextChat(userID); + } + } + else if (selectedIDS.size() > 1) + { + if ("im" == command) + { + LLAvatarActions::startConference(selectedIDS); + } + else if ("offer_teleport" == command) + { + LLAvatarActions::offerTeleport(selectedIDS); + } + else if ("voice_call" == command) + { + LLAvatarActions::startAdhocCall(selectedIDS); + } + else if ("remove_friend" == command) + { + LLAvatarActions::removeFriendsDialog(selectedIDS); } } } @@ -989,7 +1004,7 @@ void LLFloaterIMContainer::doToSelected(const LLSD& userdata) if(conversationItem != NULL) { getParticipantUUIDs(selected_uuids); - + if(conversationItem->getType() == LLConversationItem::CONV_PARTICIPANT) { doToParticipants(command, selected_uuids); @@ -1031,75 +1046,64 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) LLUUID selected_group_id = getCurSelectedViewModelItem()->getUUID(); return gAgent.getGroupID() != selected_group_id; } + + return enableContextMenuItem(item, uuids); +} - if("conversation_log" == item) +bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_vec_t& uuids) +{ + if ("conversation_log" == item) { return gSavedSettings.getBOOL("KeepConversationLogTranscripts"); } - if(uuids.size() <= 0) + // If nothing is selected, everything needs to be disabled + if (uuids.size() <= 0) { return false; } + + // Extract the single select info + bool is_single_select = (uuids.size() == 1); + const LLUUID& single_id = uuids.front(); + + // Handle options that are applicable to all including the user agent + if ("can_view_profile" == item) + { + return is_single_select; + } + + // Beyond that point, if only the user agent is selected, everything is disabled + if (is_single_select && (single_id == gAgentID)) + { + return false; + } - // 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 ("can_block" == item) + // Handle all other options + if (("can_invite" == item) || ("can_chat_history" == item) || ("can_share" == item) || ("can_pay" == item)) + { + // Those menu items are enable only if a single avatar is selected + return is_single_select; + } + else if ("can_block" == item) { - const LLUUID& id = uuids.front(); - return LLAvatarActions::canBlock(id); + return (is_single_select ? LLAvatarActions::canBlock(single_id) : false); } else if ("can_add" == item) { // 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(uuids.size() > 1) - { - return false; - } - - bool result = true; - - uuid_vec_t::const_iterator - id = uuids.begin(), - uuids_end = uuids.end(); - - for (;id != uuids_end; ++id) - { - if ( LLAvatarActions::isFriend(*id) ) - { - result = false; - break; - } - } - - return result; + // - there is only 1 selected avatar (EXT-7389) + // - this avatar is not already a friend + return (is_single_select ? !LLAvatarActions::isFriend(single_id) : false); } else if ("can_delete" == item) { - // We can remove friends if: - // - there are selected people - // - and there are only friends among selection. - - bool result = (uuids.size() > 0); - - uuid_vec_t::const_iterator - id = uuids.begin(), - uuids_end = uuids.end(); - - for (;id != uuids_end; ++id) + // We can remove friends if there are only friends among the selection + bool result = true; + for (uuid_vec_t::const_iterator id = uuids.begin(); id != uuids.end(); ++id) { - if ( !LLAvatarActions::isFriend(*id) ) - { - result = false; - break; - } + result &= LLAvatarActions::isFriend(*id); } - return result; } else if ("can_call" == item) @@ -1108,34 +1112,38 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) } else if ("can_show_on_map" == item) { - const LLUUID& id = uuids.front(); - - return (LLAvatarTracker::instance().isBuddyOnline(id) && is_agent_mappable(id)) - || gAgent.isGodlike(); + return (is_single_select ? (LLAvatarTracker::instance().isBuddyOnline(single_id) && is_agent_mappable(single_id)) || gAgent.isGodlike() : false); } - else if("can_offer_teleport" == item) + else if ("can_offer_teleport" == item) { return LLAvatarActions::canOfferTeleport(uuids); } - else if("can_moderate_voice" == item || "can_allow_text_chat" == item || "can_mute" == item || "can_unmute" == item) + else if (("can_moderate_voice" == item) || ("can_allow_text_chat" == item) || ("can_mute" == item) || ("can_unmute" == item)) { + // *TODO : get that out of here... return enableModerateContextMenuItem(item); } - return false; + // By default, options that not explicitely disabled are enabled + return true; } bool LLFloaterIMContainer::checkContextMenuItem(const LLSD& userdata) { std::string item = userdata.asString(); - uuid_vec_t mUUIDs; - getParticipantUUIDs(mUUIDs); + uuid_vec_t uuids; + getParticipantUUIDs(uuids); + + return checkContextMenuItem(item, uuids); +} - if(mUUIDs.size() > 0 ) +bool LLFloaterIMContainer::checkContextMenuItem(const std::string& item, uuid_vec_t& uuids) +{ + if (uuids.size() == 1) { if ("is_blocked" == item) { - return LLAvatarActions::isBlocked(mUUIDs.front()); + return LLAvatarActions::isBlocked(uuids.front()); } else if ("is_allowed_text_chat" == item) { diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 9cd6b9bc5d..1badce0d2d 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -99,6 +99,12 @@ public: void onNearbyChatClosed(); + // Handling of lists of participants is public so to be common with llfloatersessiontab + // *TODO : Find a better place for this. + bool checkContextMenuItem(const std::string& item, uuid_vec_t& selectedIDS); + bool enableContextMenuItem(const std::string& item, uuid_vec_t& selectedIDS); + void doToParticipants(const std::string& item, uuid_vec_t& selectedIDS); + private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; avatarID_panel_map_t mSessions; @@ -129,11 +135,10 @@ private: const LLConversationItem * getCurSelectedViewModelItem(); void getParticipantUUIDs(uuid_vec_t& selected_uuids); void doToSelected(const LLSD& userdata); - void doToSelectedConversation(const std::string& command, uuid_vec_t& selectedIDS); - void doToParticipants(const std::string& item, uuid_vec_t& selectedIDS); - void doToSelectedGroup(const LLSD& userdata); bool checkContextMenuItem(const LLSD& userdata); bool enableContextMenuItem(const LLSD& userdata); + void doToSelectedConversation(const std::string& command, uuid_vec_t& selectedIDS); + void doToSelectedGroup(const LLSD& userdata); static void confirmMuteAllCallback(const LLSD& notification, const LLSD& response); bool enableModerateContextMenuItem(const std::string& userdata); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 5867eb3e84..7002342c0b 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -112,6 +112,7 @@ BOOL LLFloaterIMNearbyChat::postBuild() { setIsSingleInstance(TRUE); BOOL result = LLFloaterIMSessionTab::postBuild(); + mInputEditor->setCommitCallback(boost::bind(&LLFloaterIMNearbyChat::onChatBoxCommit, this)); mInputEditor->setKeystrokeCallback(boost::bind(&onChatBoxKeystroke, _1, this)); mInputEditor->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); @@ -122,24 +123,24 @@ BOOL LLFloaterIMNearbyChat::postBuild() // mOutputMonitor->setVisible(FALSE); // Register for font change notifications - LLViewerChat::setFontChangedCallback(boost::bind(&LLFloaterIMNearbyChat::onChatFontChange, this, _1)); +// LLViewerChat::setFontChangedCallback(boost::bind(&LLFloaterIMNearbyChat::onChatFontChange, this, _1)); // title must be defined BEFORE call addConversationListItem() because // it is used for show the item's name in the conversations list setTitle(LLTrans::getString("NearbyChatTitle")); //for menu - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; +// LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +// LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - enable_registrar.add("NearbyChat.Check", boost::bind(&LLFloaterIMNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); - registrar.add("NearbyChat.Action", boost::bind(&LLFloaterIMNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); +// enable_registrar.add("NearbyChat.Check", boost::bind(&LLFloaterIMNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); +// registrar.add("NearbyChat.Action", boost::bind(&LLFloaterIMNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(menu) - { - mPopupMenuHandle = menu->getHandle(); - } +// LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +// if(menu) +// { +// mPopupMenuHandle = menu->getHandle(); +// } // obsolete, but may be needed for backward compatibility? gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true); diff --git a/indra/newview/llfloaterimnearbychat.h b/indra/newview/llfloaterimnearbychat.h index 1479746fbd..5ed639136b 100644 --- a/indra/newview/llfloaterimnearbychat.h +++ b/indra/newview/llfloaterimnearbychat.h @@ -117,7 +117,7 @@ private: /*virtual*/ void refresh(); - LLHandle<LLView> mPopupMenuHandle; +// LLHandle<LLView> mPopupMenuHandle; std::vector<LLChat> mMessageArchive; }; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index dcf1b52118..6e58a66bcd 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -70,6 +70,11 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", boost::bind(&LLFloaterIMSessionTab::onIMShowModesMenuItemEnable, this, _2)); + + // Right click menu handling + mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem, this, _2)); + mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMSessionTab::enableContextMenuItem, this, _2)); + mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2)); } LLFloaterIMSessionTab::~LLFloaterIMSessionTab() @@ -397,6 +402,7 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant() 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); // Attach that root to the scroller @@ -768,3 +774,56 @@ bool LLFloaterIMSessionTab::checkIfTornOff() return isTorn; } + +void LLFloaterIMSessionTab::doToSelected(const LLSD& userdata) +{ + // Get the list of selected items in the tab + std::string command = userdata.asString(); + uuid_vec_t selected_uuids; + getSelectedUUIDs(selected_uuids); + + // Perform the command (IM, profile, etc...) on the list using the general conversation container method + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + // Note: By construction, those can only be participants so we can call doToParticipants() directly + floater_container->doToParticipants(command, selected_uuids); +} + +bool LLFloaterIMSessionTab::enableContextMenuItem(const LLSD& userdata) +{ + // Get the list of selected items in the tab + std::string command = userdata.asString(); + uuid_vec_t selected_uuids; + getSelectedUUIDs(selected_uuids); + + // Perform the item enable test on the list using the general conversation container method + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + return floater_container->enableContextMenuItem(command, selected_uuids); +} + +bool LLFloaterIMSessionTab::checkContextMenuItem(const LLSD& userdata) +{ + // Get the list of selected items in the tab + std::string command = userdata.asString(); + uuid_vec_t selected_uuids; + getSelectedUUIDs(selected_uuids); + + // Perform the item check on the list using the general conversation container method + LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); + return floater_container->checkContextMenuItem(command, selected_uuids); +} + +void LLFloaterIMSessionTab::getSelectedUUIDs(uuid_vec_t& selected_uuids) +{ + const std::set<LLFolderViewItem*> selected_items = mConversationsRoot->getSelectionList(); + + std::set<LLFolderViewItem*>::const_iterator it = selected_items.begin(); + const std::set<LLFolderViewItem*>::const_iterator it_end = selected_items.end(); + + for (; it != it_end; ++it) + { + LLConversationItem* conversation_item = static_cast<LLConversationItem *>((*it)->getViewModelItem()); + selected_uuids.push_back(conversation_item->getUUID()); + } +} + + diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index b765d121de..8efa0955fc 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -157,6 +157,13 @@ protected: LLButton* mCloseBtn; private: + // Handling selection and contextual menu + void doToSelected(const LLSD& userdata); + bool enableContextMenuItem(const LLSD& userdata); + bool checkContextMenuItem(const LLSD& userdata); + + void getSelectedUUIDs(uuid_vec_t& selected_uuids); + /// Refreshes the floater at a constant rate. virtual void refresh() = 0; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 1ae6fd91ce..1426567196 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -1068,7 +1068,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root if ("delete" == action) { LLSD args; - args["QUESTION"] = LLTrans::getString(root->getNumSelectedItems() > 1 ? "DeleteItems" : "DeleteItem"); + args["QUESTION"] = LLTrans::getString(root->getSelectedCount() > 1 ? "DeleteItems" : "DeleteItem"); LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root)); return; } diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index 2e9bda5804..908b2c174f 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -30,12 +30,14 @@ layout="topleft" name="view_profile"> <on_click function="Avatar.DoToSelected" parameter="view_profile"/> + <on_enable function="Avatar.EnableItem" parameter="can_view_profile"/> </menu_item_call> <menu_item_call label="IM" layout="topleft" name="im"> <on_click function="Avatar.DoToSelected" parameter="im"/> + <on_enable function="Avatar.EnableItem" parameter="can_im"/> </menu_item_call> <menu_item_call label="Offer teleport" @@ -56,6 +58,7 @@ layout="topleft" name="chat_history"> <on_click function="Avatar.DoToSelected" parameter="chat_history"/> + <on_enable function="Avatar.EnableItem" parameter="can_chat_history"/> </menu_item_call> <menu_item_separator layout="topleft" name="separator_chat_history"/> <menu_item_call @@ -77,6 +80,7 @@ layout="topleft" name="invite_to_group"> <on_click function="Avatar.DoToSelected" parameter="invite_to_group" /> + <on_enable function="Avatar.EnableItem" parameter="can_invite" /> </menu_item_call> <menu_item_separator layout="topleft" name="separator_invite_to_group"/> <menu_item_call @@ -91,12 +95,14 @@ layout="topleft" name="share"> <on_click function="Avatar.DoToSelected" parameter="share" /> + <on_enable function="Avatar.EnableItem" parameter="can_share" /> </menu_item_call> <menu_item_call label="Pay" layout="topleft" name="pay"> <on_click function="Avatar.DoToSelected" parameter="pay" /> + <on_enable function="Avatar.EnableItem" parameter="can_pay" /> </menu_item_call> <menu_item_check label="Block / unblock" @@ -111,6 +117,7 @@ layout="topleft" name="group_profile"> <on_click function="Group.DoToSelected" parameter="group_profile"/> + <on_enable function="Avatar.EnableItem" parameter="can_group_profile" /> </menu_item_call> <menu_item_call label="Activate Group" @@ -124,10 +131,9 @@ layout="topleft" name="leave_group"> <on_click function="Group.DoToSelected" parameter="leave_group"/> + <on_enable function="Avatar.EnableItem" parameter="can_leave_group" /> </menu_item_call> - <menu_item_separator - layout="topleft" - name="Moderator Options Separator"/> + <menu_item_separator layout="topleft" name="Moderator Options Separator"/> <context_menu label="Moderator Options" layout="topleft" |