/indra/newview/llavataractions.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 1033 lines · 770 code · 136 blank · 127 comment · 121 complexity · d270770c431d19f9510d590f7711dd6f MD5 · raw file

  1. /**
  2. * @file llavataractions.cpp
  3. * @brief Friend-related actions (add, remove, offer teleport, etc)
  4. *
  5. * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llavataractions.h"
  28. #include "boost/lambda/lambda.hpp" // for lambda::constant
  29. #include "llavatarnamecache.h" // IDEVO
  30. #include "llsd.h"
  31. #include "lldarray.h"
  32. #include "llnotifications.h"
  33. #include "llnotificationsutil.h"
  34. #include "roles_constants.h" // for GP_MEMBER_INVITE
  35. #include "llagent.h"
  36. #include "llappviewer.h" // for gLastVersionChannel
  37. #include "llcachename.h"
  38. #include "llcallingcard.h" // for LLAvatarTracker
  39. #include "llfloateravatarpicker.h" // for LLFloaterAvatarPicker
  40. #include "llfloatergroupinvite.h"
  41. #include "llfloatergroups.h"
  42. #include "llfloaterreg.h"
  43. #include "llfloaterpay.h"
  44. #include "llfloatersidepanelcontainer.h"
  45. #include "llfloaterwebcontent.h"
  46. #include "llfloaterworldmap.h"
  47. #include "llfolderview.h"
  48. #include "llgiveinventory.h"
  49. #include "llinventorybridge.h"
  50. #include "llinventorymodel.h" // for gInventory.findCategoryUUIDForType
  51. #include "llinventorypanel.h"
  52. #include "llimview.h" // for gIMMgr
  53. #include "llmutelist.h"
  54. #include "llnotificationsutil.h" // for LLNotificationsUtil
  55. #include "llpaneloutfitedit.h"
  56. #include "llpanelprofile.h"
  57. #include "llrecentpeople.h"
  58. #include "lltrans.h"
  59. #include "llviewercontrol.h"
  60. #include "llviewerobjectlist.h"
  61. #include "llviewermessage.h" // for handle_lure
  62. #include "llviewerregion.h"
  63. #include "llimfloater.h"
  64. #include "lltrans.h"
  65. #include "llcallingcard.h"
  66. #include "llslurl.h" // IDEVO
  67. #include "llsidepanelinventory.h"
  68. // static
  69. void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name)
  70. {
  71. if(id == gAgentID)
  72. {
  73. LLNotificationsUtil::add("AddSelfFriend");
  74. return;
  75. }
  76. LLSD args;
  77. args["NAME"] = LLSLURL("agent", id, "completename").getSLURLString();
  78. LLSD payload;
  79. payload["id"] = id;
  80. payload["name"] = name;
  81. LLNotificationsUtil::add("AddFriendWithMessage", args, payload, &callbackAddFriendWithMessage);
  82. // add friend to recent people list
  83. LLRecentPeople::instance().add(id);
  84. }
  85. void on_avatar_name_friendship(const LLUUID& id, const LLAvatarName av_name)
  86. {
  87. LLAvatarActions::requestFriendshipDialog(id, av_name.getCompleteName());
  88. }
  89. // static
  90. void LLAvatarActions::requestFriendshipDialog(const LLUUID& id)
  91. {
  92. if(id.isNull())
  93. {
  94. return;
  95. }
  96. LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_friendship, _1, _2));
  97. }
  98. // static
  99. void LLAvatarActions::removeFriendDialog(const LLUUID& id)
  100. {
  101. if (id.isNull())
  102. return;
  103. uuid_vec_t ids;
  104. ids.push_back(id);
  105. removeFriendsDialog(ids);
  106. }
  107. // static
  108. void LLAvatarActions::removeFriendsDialog(const uuid_vec_t& ids)
  109. {
  110. if(ids.size() == 0)
  111. return;
  112. LLSD args;
  113. std::string msgType;
  114. if(ids.size() == 1)
  115. {
  116. LLUUID agent_id = ids[0];
  117. LLAvatarName av_name;
  118. if(LLAvatarNameCache::get(agent_id, &av_name))
  119. {
  120. args["NAME"] = av_name.mDisplayName;
  121. }
  122. msgType = "RemoveFromFriends";
  123. }
  124. else
  125. {
  126. msgType = "RemoveMultipleFromFriends";
  127. }
  128. LLSD payload;
  129. for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
  130. {
  131. payload["ids"].append(*it);
  132. }
  133. LLNotificationsUtil::add(msgType,
  134. args,
  135. payload,
  136. &handleRemove);
  137. }
  138. // static
  139. void LLAvatarActions::offerTeleport(const LLUUID& invitee)
  140. {
  141. if (invitee.isNull())
  142. return;
  143. LLDynamicArray<LLUUID> ids;
  144. ids.push_back(invitee);
  145. offerTeleport(ids);
  146. }
  147. // static
  148. void LLAvatarActions::offerTeleport(const uuid_vec_t& ids)
  149. {
  150. if (ids.size() == 0)
  151. return;
  152. handle_lure(ids);
  153. }
  154. static void on_avatar_name_cache_start_im(const LLUUID& agent_id,
  155. const LLAvatarName& av_name)
  156. {
  157. std::string name = av_name.getCompleteName();
  158. LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id);
  159. if (session_id != LLUUID::null)
  160. {
  161. LLIMFloater::show(session_id);
  162. }
  163. make_ui_sound("UISndStartIM");
  164. }
  165. // static
  166. void LLAvatarActions::startIM(const LLUUID& id)
  167. {
  168. if (id.isNull())
  169. return;
  170. LLAvatarNameCache::get(id,
  171. boost::bind(&on_avatar_name_cache_start_im, _1, _2));
  172. }
  173. // static
  174. void LLAvatarActions::endIM(const LLUUID& id)
  175. {
  176. if (id.isNull())
  177. return;
  178. LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, id);
  179. if (session_id != LLUUID::null)
  180. {
  181. gIMMgr->leaveSession(session_id);
  182. }
  183. }
  184. static void on_avatar_name_cache_start_call(const LLUUID& agent_id,
  185. const LLAvatarName& av_name)
  186. {
  187. std::string name = av_name.getCompleteName();
  188. LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id, true);
  189. if (session_id != LLUUID::null)
  190. {
  191. gIMMgr->startCall(session_id);
  192. }
  193. make_ui_sound("UISndStartIM");
  194. }
  195. // static
  196. void LLAvatarActions::startCall(const LLUUID& id)
  197. {
  198. if (id.isNull())
  199. {
  200. return;
  201. }
  202. LLAvatarNameCache::get(id,
  203. boost::bind(&on_avatar_name_cache_start_call, _1, _2));
  204. }
  205. // static
  206. void LLAvatarActions::startAdhocCall(const uuid_vec_t& ids)
  207. {
  208. if (ids.size() == 0)
  209. {
  210. return;
  211. }
  212. // convert vector into LLDynamicArray for addSession
  213. LLDynamicArray<LLUUID> id_array;
  214. for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
  215. {
  216. id_array.push_back(*it);
  217. }
  218. // create the new ad hoc voice session
  219. const std::string title = LLTrans::getString("conference-title");
  220. LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START,
  221. ids[0], id_array, true);
  222. if (session_id == LLUUID::null)
  223. {
  224. return;
  225. }
  226. gIMMgr->autoStartCallOnStartup(session_id);
  227. make_ui_sound("UISndStartIM");
  228. }
  229. /* AD *TODO: Is this function needed any more?
  230. I fixed it a bit(added check for canCall), but it appears that it is not used
  231. anywhere. Maybe it should be removed?
  232. // static
  233. bool LLAvatarActions::isCalling(const LLUUID &id)
  234. {
  235. if (id.isNull() || !canCall())
  236. {
  237. return false;
  238. }
  239. LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, id);
  240. return (LLIMModel::getInstance()->findIMSession(session_id) != NULL);
  241. }*/
  242. //static
  243. bool LLAvatarActions::canCall()
  244. {
  245. return LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
  246. }
  247. // static
  248. void LLAvatarActions::startConference(const uuid_vec_t& ids)
  249. {
  250. // *HACK: Copy into dynamic array
  251. LLDynamicArray<LLUUID> id_array;
  252. for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
  253. {
  254. id_array.push_back(*it);
  255. }
  256. const std::string title = LLTrans::getString("conference-title");
  257. LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array);
  258. if (session_id != LLUUID::null)
  259. {
  260. LLIMFloater::show(session_id);
  261. }
  262. make_ui_sound("UISndStartIM");
  263. }
  264. static const char* get_profile_floater_name(const LLUUID& avatar_id)
  265. {
  266. // Use different floater XML for our profile to be able to save its rect.
  267. return avatar_id == gAgentID ? "my_profile" : "profile";
  268. }
  269. static void on_avatar_name_show_profile(const LLUUID& agent_id, const LLAvatarName& av_name)
  270. {
  271. std::string username = av_name.mUsername;
  272. if (username.empty())
  273. {
  274. username = LLCacheName::buildUsername(av_name.mDisplayName);
  275. }
  276. llinfos << "opening web profile for " << username << llendl;
  277. std::string url = getProfileURL(username);
  278. // PROFILES: open in webkit window
  279. LLFloaterWebContent::Params p;
  280. p.url(url).
  281. id(agent_id.asString());
  282. LLFloaterReg::showInstance(get_profile_floater_name(agent_id), p);
  283. }
  284. // static
  285. void LLAvatarActions::showProfile(const LLUUID& id)
  286. {
  287. if (id.notNull())
  288. {
  289. LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_show_profile, _1, _2));
  290. }
  291. }
  292. //static
  293. bool LLAvatarActions::profileVisible(const LLUUID& id)
  294. {
  295. LLSD sd;
  296. sd["id"] = id;
  297. LLFloater* browser = getProfileFloater(id);
  298. return browser && browser->isShown();
  299. }
  300. //static
  301. LLFloater* LLAvatarActions::getProfileFloater(const LLUUID& id)
  302. {
  303. LLFloaterWebContent *browser = dynamic_cast<LLFloaterWebContent*>
  304. (LLFloaterReg::findInstance(get_profile_floater_name(id), LLSD().with("id", id)));
  305. return browser;
  306. }
  307. //static
  308. void LLAvatarActions::hideProfile(const LLUUID& id)
  309. {
  310. LLSD sd;
  311. sd["id"] = id;
  312. LLFloater* browser = getProfileFloater(id);
  313. if (browser)
  314. {
  315. browser->closeFloater();
  316. }
  317. }
  318. // static
  319. void LLAvatarActions::showOnMap(const LLUUID& id)
  320. {
  321. LLAvatarName av_name;
  322. if (!LLAvatarNameCache::get(id, &av_name))
  323. {
  324. LLAvatarNameCache::get(id, boost::bind(&LLAvatarActions::showOnMap, id));
  325. return;
  326. }
  327. gFloaterWorldMap->trackAvatar(id, av_name.mDisplayName);
  328. LLFloaterReg::showInstance("world_map");
  329. }
  330. // static
  331. void LLAvatarActions::pay(const LLUUID& id)
  332. {
  333. LLNotification::Params params("BusyModePay");
  334. params.functor.function(boost::bind(&LLAvatarActions::handlePay, _1, _2, id));
  335. if (gAgent.getBusy())
  336. {
  337. // warn users of being in busy mode during a transaction
  338. LLNotifications::instance().add(params);
  339. }
  340. else
  341. {
  342. LLNotifications::instance().forceResponse(params, 1);
  343. }
  344. }
  345. // static
  346. void LLAvatarActions::kick(const LLUUID& id)
  347. {
  348. LLSD payload;
  349. payload["avatar_id"] = id;
  350. LLNotifications::instance().add("KickUser", LLSD(), payload, handleKick);
  351. }
  352. // static
  353. void LLAvatarActions::freeze(const LLUUID& id)
  354. {
  355. LLSD payload;
  356. payload["avatar_id"] = id;
  357. LLNotifications::instance().add("FreezeUser", LLSD(), payload, handleFreeze);
  358. }
  359. // static
  360. void LLAvatarActions::unfreeze(const LLUUID& id)
  361. {
  362. LLSD payload;
  363. payload["avatar_id"] = id;
  364. LLNotifications::instance().add("UnFreezeUser", LLSD(), payload, handleUnfreeze);
  365. }
  366. //static
  367. void LLAvatarActions::csr(const LLUUID& id, std::string name)
  368. {
  369. if (name.empty()) return;
  370. std::string url = "http://csr.lindenlab.com/agent/";
  371. // slow and stupid, but it's late
  372. S32 len = name.length();
  373. for (S32 i = 0; i < len; i++)
  374. {
  375. if (name[i] == ' ')
  376. {
  377. url += "%20";
  378. }
  379. else
  380. {
  381. url += name[i];
  382. }
  383. }
  384. LLWeb::loadURL(url);
  385. }
  386. //static
  387. void LLAvatarActions::share(const LLUUID& id)
  388. {
  389. LLSD key;
  390. LLFloaterSidePanelContainer::showPanel("inventory", key);
  391. LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL,id);
  392. if (!gIMMgr->hasSession(session_id))
  393. {
  394. startIM(id);
  395. }
  396. if (gIMMgr->hasSession(session_id))
  397. {
  398. // we should always get here, but check to verify anyways
  399. LLIMModel::getInstance()->addMessage(session_id, SYSTEM_FROM, LLUUID::null, LLTrans::getString("share_alert"), false);
  400. }
  401. }
  402. namespace action_give_inventory
  403. {
  404. /**
  405. * Returns a pointer to 'Add More' inventory panel of Edit Outfit SP.
  406. */
  407. static LLInventoryPanel* get_outfit_editor_inventory_panel()
  408. {
  409. LLPanelOutfitEdit* panel_outfit_edit = dynamic_cast<LLPanelOutfitEdit*>(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit"));
  410. if (NULL == panel_outfit_edit) return NULL;
  411. LLInventoryPanel* inventory_panel = panel_outfit_edit->findChild<LLInventoryPanel>("folder_view");
  412. return inventory_panel;
  413. }
  414. /**
  415. * @return active inventory panel, or NULL if there's no such panel
  416. */
  417. static LLInventoryPanel* get_active_inventory_panel()
  418. {
  419. LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
  420. if (!active_panel)
  421. {
  422. active_panel = get_outfit_editor_inventory_panel();
  423. }
  424. return active_panel;
  425. }
  426. /**
  427. * Checks My Inventory visibility.
  428. */
  429. static bool is_give_inventory_acceptable()
  430. {
  431. // check selection in the panel
  432. const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
  433. if (inventory_selected_uuids.empty()) return false; // nothing selected
  434. bool acceptable = false;
  435. std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
  436. const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
  437. for (; it != it_end; ++it)
  438. {
  439. LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
  440. // any category can be offered.
  441. if (inv_cat)
  442. {
  443. acceptable = true;
  444. continue;
  445. }
  446. LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
  447. // check if inventory item can be given
  448. if (LLGiveInventory::isInventoryGiveAcceptable(inv_item))
  449. {
  450. acceptable = true;
  451. continue;
  452. }
  453. // there are neither item nor category in inventory
  454. acceptable = false;
  455. break;
  456. }
  457. return acceptable;
  458. }
  459. static void build_residents_string(const std::vector<LLAvatarName> avatar_names, std::string& residents_string)
  460. {
  461. llassert(avatar_names.size() > 0);
  462. const std::string& separator = LLTrans::getString("words_separator");
  463. for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; )
  464. {
  465. LLAvatarName av_name = *it;
  466. residents_string.append(av_name.mDisplayName);
  467. if (++it == avatar_names.end())
  468. {
  469. break;
  470. }
  471. residents_string.append(separator);
  472. }
  473. }
  474. static void build_items_string(const std::set<LLUUID>& inventory_selected_uuids , std::string& items_string)
  475. {
  476. llassert(inventory_selected_uuids.size() > 0);
  477. const std::string& separator = LLTrans::getString("words_separator");
  478. for (std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); ; )
  479. {
  480. LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
  481. if (NULL != inv_cat)
  482. {
  483. items_string = inv_cat->getName();
  484. break;
  485. }
  486. LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
  487. if (NULL != inv_item)
  488. {
  489. items_string.append(inv_item->getName());
  490. }
  491. if(++it == inventory_selected_uuids.end())
  492. {
  493. break;
  494. }
  495. items_string.append(separator);
  496. }
  497. }
  498. struct LLShareInfo : public LLSingleton<LLShareInfo>
  499. {
  500. std::vector<LLAvatarName> mAvatarNames;
  501. uuid_vec_t mAvatarUuids;
  502. };
  503. static void give_inventory_cb(const LLSD& notification, const LLSD& response)
  504. {
  505. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  506. // if Cancel pressed
  507. if (option == 1)
  508. {
  509. return;
  510. }
  511. const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
  512. if (inventory_selected_uuids.empty())
  513. {
  514. return;
  515. }
  516. S32 count = LLShareInfo::instance().mAvatarNames.size();
  517. bool shared = false;
  518. // iterate through avatars
  519. for(S32 i = 0; i < count; ++i)
  520. {
  521. const LLUUID& avatar_uuid = LLShareInfo::instance().mAvatarUuids[i];
  522. // We souldn't open IM session, just calculate session ID for logging purpose. See EXT-6710
  523. const LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, avatar_uuid);
  524. std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
  525. const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
  526. const std::string& separator = LLTrans::getString("words_separator");
  527. std::string noncopy_item_names;
  528. LLSD noncopy_items = LLSD::emptyArray();
  529. // iterate through selected inventory objects
  530. for (; it != it_end; ++it)
  531. {
  532. LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
  533. if (inv_cat)
  534. {
  535. LLGiveInventory::doGiveInventoryCategory(avatar_uuid, inv_cat, session_id);
  536. shared = true;
  537. break;
  538. }
  539. LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
  540. if (!inv_item->getPermissions().allowCopyBy(gAgentID))
  541. {
  542. if (!noncopy_item_names.empty())
  543. {
  544. noncopy_item_names.append(separator);
  545. }
  546. noncopy_item_names.append(inv_item->getName());
  547. noncopy_items.append(*it);
  548. }
  549. else
  550. {
  551. LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id);
  552. shared = true;
  553. }
  554. }
  555. if (noncopy_items.beginArray() != noncopy_items.endArray())
  556. {
  557. LLSD substitutions;
  558. substitutions["ITEMS"] = noncopy_item_names;
  559. LLSD payload;
  560. payload["agent_id"] = avatar_uuid;
  561. payload["items"] = noncopy_items;
  562. LLNotificationsUtil::add("CannotCopyWarning", substitutions, payload,
  563. &LLGiveInventory::handleCopyProtectedItem);
  564. break;
  565. }
  566. }
  567. if (shared)
  568. {
  569. LLFloaterReg::hideInstance("avatar_picker");
  570. LLNotificationsUtil::add("ItemsShared");
  571. }
  572. }
  573. /**
  574. * Performs "give inventory" operations for provided avatars.
  575. *
  576. * Sends one requests to give all selected inventory items for each passed avatar.
  577. * Avatars are represent by two vectors: names and UUIDs which must be sychronized with each other.
  578. *
  579. * @param avatar_names - avatar names request to be sent.
  580. * @param avatar_uuids - avatar names request to be sent.
  581. */
  582. static void give_inventory(const uuid_vec_t& avatar_uuids, const std::vector<LLAvatarName> avatar_names)
  583. {
  584. llassert(avatar_names.size() == avatar_uuids.size());
  585. const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
  586. if (inventory_selected_uuids.empty())
  587. {
  588. return;
  589. }
  590. std::string residents;
  591. build_residents_string(avatar_names, residents);
  592. std::string items;
  593. build_items_string(inventory_selected_uuids, items);
  594. int folders_count = 0;
  595. std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
  596. //traverse through selected inventory items and count folders among them
  597. for ( ; it != inventory_selected_uuids.end() && folders_count <=1 ; ++it)
  598. {
  599. LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
  600. if (NULL != inv_cat)
  601. {
  602. folders_count++;
  603. }
  604. }
  605. // EXP-1599
  606. // In case of sharing multiple folders, make the confirmation
  607. // dialog contain a warning that only one folder can be shared at a time.
  608. std::string notification = (folders_count > 1) ? "ShareFolderConfirmation" : "ShareItemsConfirmation";
  609. LLSD substitutions;
  610. substitutions["RESIDENTS"] = residents;
  611. substitutions["ITEMS"] = items;
  612. LLShareInfo::instance().mAvatarNames = avatar_names;
  613. LLShareInfo::instance().mAvatarUuids = avatar_uuids;
  614. LLNotificationsUtil::add(notification, substitutions, LLSD(), &give_inventory_cb);
  615. }
  616. }
  617. //static
  618. std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs()
  619. {
  620. std::set<LLUUID> inventory_selected_uuids;
  621. LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel();
  622. if (active_panel)
  623. {
  624. inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
  625. }
  626. if (inventory_selected_uuids.empty())
  627. {
  628. LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
  629. if (sidepanel_inventory)
  630. {
  631. inventory_selected_uuids = sidepanel_inventory->getInboxSelectionList();
  632. }
  633. }
  634. return inventory_selected_uuids;
  635. }
  636. //static
  637. void LLAvatarActions::shareWithAvatars()
  638. {
  639. using namespace action_give_inventory;
  640. LLFloaterAvatarPicker* picker =
  641. LLFloaterAvatarPicker::show(boost::bind(give_inventory, _1, _2), TRUE, FALSE);
  642. picker->setOkBtnEnableCb(boost::bind(is_give_inventory_acceptable));
  643. picker->openFriendsTab();
  644. LLNotificationsUtil::add("ShareNotification");
  645. }
  646. // static
  647. bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NULL*/)
  648. {
  649. using namespace action_give_inventory;
  650. if (!inv_panel)
  651. {
  652. LLInventoryPanel* active_panel = get_active_inventory_panel();
  653. if (!active_panel) return false;
  654. inv_panel = active_panel;
  655. }
  656. // check selection in the panel
  657. LLFolderView* root_folder = inv_panel->getRootFolder();
  658. const std::set<LLUUID> inventory_selected_uuids = root_folder->getSelectionList();
  659. if (inventory_selected_uuids.empty()) return false; // nothing selected
  660. bool can_share = true;
  661. std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
  662. const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
  663. for (; it != it_end; ++it)
  664. {
  665. LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
  666. // any category can be offered.
  667. if (inv_cat)
  668. {
  669. continue;
  670. }
  671. // check if inventory item can be given
  672. LLFolderViewItem* item = root_folder->getItemByID(*it);
  673. if (!item) return false;
  674. LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getListener());
  675. if (bridge && bridge->canShare())
  676. {
  677. continue;
  678. }
  679. // there are neither item nor category in inventory
  680. can_share = false;
  681. break;
  682. }
  683. return can_share;
  684. }
  685. // static
  686. void LLAvatarActions::toggleBlock(const LLUUID& id)
  687. {
  688. std::string name;
  689. gCacheName->getFullName(id, name); // needed for mute
  690. LLMute mute(id, name, LLMute::AGENT);
  691. if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName))
  692. {
  693. LLMuteList::getInstance()->remove(mute);
  694. }
  695. else
  696. {
  697. LLMuteList::getInstance()->add(mute);
  698. }
  699. }
  700. // static
  701. bool LLAvatarActions::canOfferTeleport(const LLUUID& id)
  702. {
  703. // First use LLAvatarTracker::isBuddy()
  704. // If LLAvatarTracker::instance().isBuddyOnline function only is used
  705. // then for avatars that are online and not a friend it will return false.
  706. // But we should give an ability to offer a teleport for such avatars.
  707. if(LLAvatarTracker::instance().isBuddy(id))
  708. {
  709. return LLAvatarTracker::instance().isBuddyOnline(id);
  710. }
  711. return true;
  712. }
  713. // static
  714. bool LLAvatarActions::canOfferTeleport(const uuid_vec_t& ids)
  715. {
  716. // We can't send more than 250 lures in a single message, so disable this
  717. // button when there are too many id's selected.
  718. if(ids.size() > 250) return false;
  719. bool result = true;
  720. for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
  721. {
  722. if(!canOfferTeleport(*it))
  723. {
  724. result = false;
  725. break;
  726. }
  727. }
  728. return result;
  729. }
  730. void LLAvatarActions::inviteToGroup(const LLUUID& id)
  731. {
  732. LLFloaterGroupPicker* widget = LLFloaterReg::showTypedInstance<LLFloaterGroupPicker>("group_picker", LLSD(id));
  733. if (widget)
  734. {
  735. widget->center();
  736. widget->setPowersMask(GP_MEMBER_INVITE);
  737. widget->removeNoneOption();
  738. widget->setSelectGroupCallback(boost::bind(callback_invite_to_group, _1, id));
  739. }
  740. }
  741. //== private methods ========================================================================================
  742. // static
  743. bool LLAvatarActions::handleRemove(const LLSD& notification, const LLSD& response)
  744. {
  745. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  746. const LLSD& ids = notification["payload"]["ids"];
  747. for (LLSD::array_const_iterator itr = ids.beginArray(); itr != ids.endArray(); ++itr)
  748. {
  749. LLUUID id = itr->asUUID();
  750. const LLRelationship* ip = LLAvatarTracker::instance().getBuddyInfo(id);
  751. if (ip)
  752. {
  753. switch (option)
  754. {
  755. case 0: // YES
  756. if( ip->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS))
  757. {
  758. LLAvatarTracker::instance().empower(id, FALSE);
  759. LLAvatarTracker::instance().notifyObservers();
  760. }
  761. LLAvatarTracker::instance().terminateBuddy(id);
  762. LLAvatarTracker::instance().notifyObservers();
  763. break;
  764. case 1: // NO
  765. default:
  766. llinfos << "No removal performed." << llendl;
  767. break;
  768. }
  769. }
  770. }
  771. return false;
  772. }
  773. // static
  774. bool LLAvatarActions::handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id)
  775. {
  776. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  777. if (option == 0)
  778. {
  779. gAgent.clearBusy();
  780. }
  781. LLFloaterPayUtil::payDirectly(&give_money, avatar_id, /*is_group=*/false);
  782. return false;
  783. }
  784. // static
  785. void LLAvatarActions::callback_invite_to_group(LLUUID group_id, LLUUID id)
  786. {
  787. uuid_vec_t agent_ids;
  788. agent_ids.push_back(id);
  789. LLFloaterGroupInvite::showForGroup(group_id, &agent_ids);
  790. }
  791. // static
  792. bool LLAvatarActions::callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response)
  793. {
  794. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  795. if (option == 0)
  796. {
  797. requestFriendship(notification["payload"]["id"].asUUID(),
  798. notification["payload"]["name"].asString(),
  799. response["message"].asString());
  800. }
  801. return false;
  802. }
  803. // static
  804. bool LLAvatarActions::handleKick(const LLSD& notification, const LLSD& response)
  805. {
  806. S32 option = LLNotification::getSelectedOption(notification, response);
  807. if (option == 0)
  808. {
  809. LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
  810. LLMessageSystem* msg = gMessageSystem;
  811. msg->newMessageFast(_PREHASH_GodKickUser);
  812. msg->nextBlockFast(_PREHASH_UserInfo);
  813. msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() );
  814. msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID());
  815. msg->addUUIDFast(_PREHASH_AgentID, avatar_id );
  816. msg->addU32("KickFlags", KICK_FLAGS_DEFAULT );
  817. msg->addStringFast(_PREHASH_Reason, response["message"].asString() );
  818. gAgent.sendReliableMessage();
  819. }
  820. return false;
  821. }
  822. bool LLAvatarActions::handleFreeze(const LLSD& notification, const LLSD& response)
  823. {
  824. S32 option = LLNotification::getSelectedOption(notification, response);
  825. if (option == 0)
  826. {
  827. LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
  828. LLMessageSystem* msg = gMessageSystem;
  829. msg->newMessageFast(_PREHASH_GodKickUser);
  830. msg->nextBlockFast(_PREHASH_UserInfo);
  831. msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() );
  832. msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID());
  833. msg->addUUIDFast(_PREHASH_AgentID, avatar_id );
  834. msg->addU32("KickFlags", KICK_FLAGS_FREEZE );
  835. msg->addStringFast(_PREHASH_Reason, response["message"].asString() );
  836. gAgent.sendReliableMessage();
  837. }
  838. return false;
  839. }
  840. bool LLAvatarActions::handleUnfreeze(const LLSD& notification, const LLSD& response)
  841. {
  842. S32 option = LLNotification::getSelectedOption(notification, response);
  843. std::string text = response["message"].asString();
  844. if (option == 0)
  845. {
  846. LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
  847. LLMessageSystem* msg = gMessageSystem;
  848. msg->newMessageFast(_PREHASH_GodKickUser);
  849. msg->nextBlockFast(_PREHASH_UserInfo);
  850. msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() );
  851. msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID());
  852. msg->addUUIDFast(_PREHASH_AgentID, avatar_id );
  853. msg->addU32("KickFlags", KICK_FLAGS_UNFREEZE );
  854. msg->addStringFast(_PREHASH_Reason, text );
  855. gAgent.sendReliableMessage();
  856. }
  857. return false;
  858. }
  859. // static
  860. void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message)
  861. {
  862. const LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
  863. send_improved_im(target_id,
  864. target_name,
  865. message,
  866. IM_ONLINE,
  867. IM_FRIENDSHIP_OFFERED,
  868. calling_card_folder_id);
  869. LLSD args;
  870. args["TO_NAME"] = target_name;
  871. LLSD payload;
  872. payload["from_id"] = target_id;
  873. payload["SUPPRESS_TOAST"] = true;
  874. LLNotificationsUtil::add("FriendshipOffered", args, payload);
  875. }
  876. //static
  877. bool LLAvatarActions::isFriend(const LLUUID& id)
  878. {
  879. return ( NULL != LLAvatarTracker::instance().getBuddyInfo(id) );
  880. }
  881. // static
  882. bool LLAvatarActions::isBlocked(const LLUUID& id)
  883. {
  884. std::string name;
  885. gCacheName->getFullName(id, name); // needed for mute
  886. return LLMuteList::getInstance()->isMuted(id, name);
  887. }
  888. // static
  889. bool LLAvatarActions::canBlock(const LLUUID& id)
  890. {
  891. std::string full_name;
  892. gCacheName->getFullName(id, full_name); // needed for mute
  893. bool is_linden = (full_name.find("Linden") != std::string::npos);
  894. bool is_self = id == gAgentID;
  895. return !is_self && !is_linden;
  896. }