/indra/newview/llfloaterbuycontents.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 297 lines · 182 code · 55 blank · 60 comment · 26 complexity · e3d27db4bcd9a84b009292d4b62b3f0f MD5 · raw file

  1. /**
  2. * @file llfloaterbuycontents.cpp
  3. * @author James Cook
  4. * @brief LLFloaterBuyContents class implementation
  5. *
  6. * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  7. * Second Life Viewer Source Code
  8. * Copyright (C) 2010, Linden Research, Inc.
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation;
  13. * version 2.1 of the License only.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  25. * $/LicenseInfo$
  26. */
  27. /**
  28. * Shows the contents of an object and their permissions when you
  29. * click "Buy..." on an object with "Sell Contents" checked.
  30. */
  31. #include "llviewerprecompiledheaders.h"
  32. #include "llfloaterbuycontents.h"
  33. #include "llcachename.h"
  34. #include "llagent.h" // for agent id
  35. #include "llcheckboxctrl.h"
  36. #include "llinventorydefines.h"
  37. #include "llinventoryfunctions.h"
  38. #include "llinventorymodel.h" // for gInventory
  39. #include "llfirstuse.h"
  40. #include "llfloaterreg.h"
  41. #include "llfloaterinventory.h" // for LLInventoryIcon::getIcon
  42. #include "llnotificationsutil.h"
  43. #include "llselectmgr.h"
  44. #include "llscrolllistctrl.h"
  45. #include "llviewerobject.h"
  46. #include "llviewerregion.h"
  47. #include "lluictrlfactory.h"
  48. #include "llviewerwindow.h"
  49. LLFloaterBuyContents::LLFloaterBuyContents(const LLSD& key)
  50. : LLFloater(key)
  51. {
  52. }
  53. BOOL LLFloaterBuyContents::postBuild()
  54. {
  55. getChild<LLUICtrl>("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyContents::onClickCancel, this));
  56. getChild<LLUICtrl>("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyContents::onClickBuy, this));
  57. getChildView("item_list")->setEnabled(FALSE);
  58. getChildView("buy_btn")->setEnabled(FALSE);
  59. getChildView("wear_check")->setEnabled(FALSE);
  60. setDefaultBtn("cancel_btn"); // to avoid accidental buy (SL-43130)
  61. // Always center the dialog. User can change the size,
  62. // but purchases are important and should be center screen.
  63. // This also avoids problems where the user resizes the application window
  64. // mid-session and the saved rect is off-center.
  65. center();
  66. return TRUE;
  67. }
  68. LLFloaterBuyContents::~LLFloaterBuyContents()
  69. {
  70. }
  71. // static
  72. void LLFloaterBuyContents::show(const LLSaleInfo& sale_info)
  73. {
  74. LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
  75. if (selection->getRootObjectCount() != 1)
  76. {
  77. LLNotificationsUtil::add("BuyContentsOneOnly");
  78. return;
  79. }
  80. LLFloaterBuyContents* floater = LLFloaterReg::showTypedInstance<LLFloaterBuyContents>("buy_object_contents");
  81. if (!floater)
  82. return;
  83. LLScrollListCtrl* list = floater->getChild<LLScrollListCtrl>("item_list");
  84. if (list)
  85. list->deleteAllItems();
  86. floater->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
  87. LLUUID owner_id;
  88. std::string owner_name;
  89. BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
  90. if (!owners_identical)
  91. {
  92. LLNotificationsUtil::add("BuyContentsOneOwner");
  93. return;
  94. }
  95. floater->mSaleInfo = sale_info;
  96. // Update the display
  97. LLSelectNode* node = selection->getFirstRootNode();
  98. if (!node) return;
  99. if(node->mPermissions->isGroupOwned())
  100. {
  101. gCacheName->getGroupName(owner_id, owner_name);
  102. }
  103. floater->getChild<LLUICtrl>("contains_text")->setTextArg("[NAME]", node->mName);
  104. floater->getChild<LLUICtrl>("buy_text")->setTextArg("[AMOUNT]", llformat("%d", sale_info.getSalePrice()));
  105. floater->getChild<LLUICtrl>("buy_text")->setTextArg("[NAME]", owner_name);
  106. // Must do this after the floater is created, because
  107. // sometimes the inventory is already there and
  108. // the callback is called immediately.
  109. LLViewerObject* obj = selection->getFirstRootObject();
  110. floater->registerVOInventoryListener(obj,NULL);
  111. floater->requestVOInventory();
  112. }
  113. void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj,
  114. LLInventoryObject::object_list_t* inv,
  115. S32 serial_num,
  116. void* data)
  117. {
  118. if (!obj)
  119. {
  120. llwarns << "No object in LLFloaterBuyContents::inventoryChanged" << llendl;
  121. return;
  122. }
  123. if (!inv)
  124. {
  125. llwarns << "No inventory in LLFloaterBuyContents::inventoryChanged"
  126. << llendl;
  127. removeVOInventoryListener();
  128. return;
  129. }
  130. LLCtrlListInterface *item_list = childGetListInterface("item_list");
  131. if (!item_list)
  132. {
  133. removeVOInventoryListener();
  134. return;
  135. }
  136. // default to turning off the buy button.
  137. getChildView("buy_btn")->setEnabled(FALSE);
  138. LLUUID owner_id;
  139. BOOL is_group_owned;
  140. LLAssetType::EType asset_type;
  141. LLInventoryType::EType inv_type;
  142. S32 wearable_count = 0;
  143. LLInventoryObject::object_list_t::const_iterator it = inv->begin();
  144. LLInventoryObject::object_list_t::const_iterator end = inv->end();
  145. for ( ; it != end; ++it )
  146. {
  147. asset_type = (*it)->getType();
  148. // Skip folders, so we know we have inventory items only
  149. if (asset_type == LLAssetType::AT_CATEGORY)
  150. continue;
  151. LLInventoryItem* inv_item = (LLInventoryItem*)((LLInventoryObject*)(*it));
  152. inv_type = inv_item->getInventoryType();
  153. // Count clothing items for later
  154. if (LLInventoryType::IT_WEARABLE == inv_type)
  155. {
  156. wearable_count++;
  157. }
  158. // Skip items the object's owner can't copy (and hence can't sell)
  159. if (!inv_item->getPermissions().getOwnership(owner_id, is_group_owned))
  160. continue;
  161. if (!inv_item->getPermissions().allowCopyBy(owner_id, owner_id))
  162. continue;
  163. // Skip items we can't transfer
  164. if (!inv_item->getPermissions().allowTransferTo(gAgent.getID()))
  165. continue;
  166. // There will be at least one item shown in the display, so go
  167. // ahead and enable the buy button.
  168. getChildView("buy_btn")->setEnabled(TRUE);
  169. // Create the line in the list
  170. LLSD row;
  171. BOOL item_is_multi = FALSE;
  172. if ( inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED )
  173. {
  174. item_is_multi = TRUE;
  175. }
  176. std::string icon_name = LLInventoryIcon::getIconName(inv_item->getType(),
  177. inv_item->getInventoryType(),
  178. inv_item->getFlags(),
  179. item_is_multi);
  180. row["columns"][0]["column"] = "icon";
  181. row["columns"][0]["type"] = "icon";
  182. row["columns"][0]["value"] = icon_name;
  183. // Append the permissions that you will acquire (not the current
  184. // permissions).
  185. U32 next_owner_mask = inv_item->getPermissions().getMaskNextOwner();
  186. std::string text = (*it)->getName();
  187. if (!(next_owner_mask & PERM_COPY))
  188. {
  189. text.append(getString("no_copy_text"));
  190. }
  191. if (!(next_owner_mask & PERM_MODIFY))
  192. {
  193. text.append(getString("no_modify_text"));
  194. }
  195. if (!(next_owner_mask & PERM_TRANSFER))
  196. {
  197. text.append(getString("no_transfer_text"));
  198. }
  199. row["columns"][1]["column"] = "text";
  200. row["columns"][1]["value"] = text;
  201. row["columns"][1]["font"] = "SANSSERIF";
  202. item_list->addElement(row);
  203. }
  204. if (wearable_count > 0)
  205. {
  206. getChildView("wear_check")->setEnabled(TRUE);
  207. getChild<LLUICtrl>("wear_check")->setValue(LLSD(false) );
  208. }
  209. removeVOInventoryListener();
  210. }
  211. void LLFloaterBuyContents::onClickBuy()
  212. {
  213. // Make sure this wasn't selected through other mechanisms
  214. // (ie, being the default button and pressing enter.
  215. if(!getChildView("buy_btn")->getEnabled())
  216. {
  217. // We shouldn't be enabled. Just close.
  218. closeFloater();
  219. return;
  220. }
  221. // We may want to wear this item
  222. if (getChild<LLUICtrl>("wear_check")->getValue())
  223. {
  224. LLInventoryState::sWearNewClothing = TRUE;
  225. }
  226. // Put the items where we put new folders.
  227. LLUUID category_id;
  228. category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_ROOT_INVENTORY);
  229. // *NOTE: doesn't work for multiple object buy, which UI does not
  230. // currently support sale info is used for verification only, if
  231. // it doesn't match region info then sale is canceled.
  232. LLSelectMgr::getInstance()->sendBuy(gAgent.getID(), category_id, mSaleInfo);
  233. // NOTE: do this here instead of on receipt of object, since contents are transfered
  234. // via a generic BulkUpdateInventory message with no way of distinguishing it from
  235. // other inventory operations
  236. LLFirstUse::newInventory();
  237. closeFloater();
  238. }
  239. void LLFloaterBuyContents::onClickCancel()
  240. {
  241. closeFloater();
  242. }