llfloaterbuycontents.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /**
  2. * @file llfloaterbuycontents.cpp
  3. * @author James Cook
  4. * @brief LLFloaterBuyContents class implementation
  5. *
  6. * $LicenseInfo:firstyear=2004&license=viewergpl$
  7. *
  8. * Copyright (c) 2004-2009, Linden Research, Inc.
  9. *
  10. * Second Life Viewer Source Code
  11. * The source code in this file ("Source Code") is provided by Linden Lab
  12. * to you under the terms of the GNU General Public License, version 2.0
  13. * ("GPL"), unless you have obtained a separate licensing agreement
  14. * ("Other License"), formally executed by you and Linden Lab. Terms of
  15. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17. *
  18. * There are special exceptions to the terms and conditions of the GPL as
  19. * it is applied to this Source Code. View the full text of the exception
  20. * in the file doc/FLOSS-exception.txt in this software distribution, or
  21. * online at
  22. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23. *
  24. * By copying, modifying or distributing this software, you acknowledge
  25. * that you have read and understood your obligations described above,
  26. * and agree to abide by those obligations.
  27. *
  28. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30. * COMPLETENESS OR PERFORMANCE.
  31. * $/LicenseInfo$
  32. */
  33. /**
  34. * Shows the contents of an object and their permissions when you click
  35. * "Buy..." on an object with "Sell Contents" checked.
  36. */
  37. #include "llviewerprecompiledheaders.h"
  38. #include "llfloaterbuycontents.h"
  39. #include "llalertdialog.h"
  40. #include "llcachename.h"
  41. #include "llcheckboxctrl.h"
  42. #include "llscrolllistctrl.h"
  43. #include "lluictrlfactory.h"
  44. #include "llagent.h" // For gAgentID
  45. #include "llinventoryicon.h" // For getIconName
  46. #include "llinventorymodel.h" // For gInventory
  47. #include "llselectmgr.h"
  48. #include "llviewerobject.h"
  49. #include "llviewerregion.h"
  50. LLFloaterBuyContents::LLFloaterBuyContents(const LLSD&)
  51. {
  52. LLUICtrlFactory::getInstance()->buildFloater(this,
  53. "floater_buy_contents.xml");
  54. }
  55. //virtual
  56. LLFloaterBuyContents::~LLFloaterBuyContents()
  57. {
  58. // Drop reference to current selection so that it goes away
  59. mObjectSelection = NULL;
  60. }
  61. //virtual
  62. bool LLFloaterBuyContents::postBuild()
  63. {
  64. childSetAction("cancel_btn", onClickCancel, this);
  65. childSetAction("buy_btn", onClickBuy, this);
  66. childDisable("item_list");
  67. childDisable("buy_btn");
  68. childDisable("wear_check");
  69. setDefaultBtn("cancel_btn"); // To avoid accidental buy (SL-43130)
  70. return true;
  71. }
  72. //static
  73. void LLFloaterBuyContents::show(const LLSaleInfo& sale_info)
  74. {
  75. LLObjectSelectionHandle selection = gSelectMgr.getSelection();
  76. if (selection->getRootObjectCount() != 1)
  77. {
  78. gNotifications.add("BuyContentsOneOnly");
  79. return;
  80. }
  81. // Create a new instance only if needed
  82. LLFloaterBuyContents* self = getInstance();
  83. LLScrollListCtrl* list = self->getChild<LLScrollListCtrl>("item_list");
  84. list->deleteAllItems();
  85. self->open();
  86. self->setFocus(true);
  87. self->mObjectSelection = gSelectMgr.getEditSelection();
  88. // Always center the dialog. User can change the size, but purchases are
  89. // important and should be center screen. This also avoids problems where
  90. // the user resizes the application window mid-session and the saved rect
  91. // is off-center.
  92. self->center();
  93. LLUUID owner_id;
  94. std::string owner_name;
  95. bool owners_identical = gSelectMgr.selectGetOwner(owner_id, owner_name);
  96. if (!owners_identical)
  97. {
  98. gNotifications.add("BuyContentsOneOwner");
  99. return;
  100. }
  101. self->mSaleInfo = sale_info;
  102. // Update the display
  103. LLSelectNode* node = selection->getFirstRootNode();
  104. if (!node) return;
  105. if (node->mPermissions->isGroupOwned() && gCacheNamep)
  106. {
  107. gCacheNamep->getGroupName(owner_id, owner_name);
  108. }
  109. self->childSetTextArg("contains_text", "[NAME]", node->mName);
  110. self->childSetTextArg("buy_text", "[AMOUNT]",
  111. llformat("%d", sale_info.getSalePrice()));
  112. self->childSetTextArg("buy_text", "[NAME]", owner_name);
  113. // Must do this after the floater is created, because sometimes the
  114. // inventory is already there and the callback is called immediately.
  115. LLViewerObject* obj = selection->getFirstRootObject();
  116. if (obj)
  117. {
  118. self->registerVOInventoryListener(obj, NULL);
  119. self->requestVOInventory();
  120. }
  121. }
  122. void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj,
  123. LLInventoryObject::object_list_t* inv,
  124. S32 serial_num, void* data)
  125. {
  126. if (!obj)
  127. {
  128. llwarns << "No object !" << llendl;
  129. return;
  130. }
  131. if (!inv)
  132. {
  133. llwarns << "No inventory !" << llendl;
  134. removeVOInventoryListener();
  135. return;
  136. }
  137. // Default to turning off the buy button.
  138. childDisable("buy_btn");
  139. LLScrollListCtrl* item_list = getChild<LLScrollListCtrl>("item_list");
  140. LLUUID owner_id;
  141. bool is_group_owned;
  142. LLAssetType::EType asset_type;
  143. LLInventoryType::EType inv_type;
  144. S32 wearable_count = 0;
  145. std::string icon_name;
  146. for (LLInventoryObject::object_list_t::const_iterator it = inv->begin(),
  147. end = inv->end();
  148. it != end; ++it)
  149. {
  150. LLInventoryObject* obj = *it;
  151. if (!obj) continue;
  152. asset_type = obj->getType();
  153. // Skip folders, so we know we have inventory items only
  154. if (asset_type == LLAssetType::AT_CATEGORY)
  155. {
  156. continue;
  157. }
  158. LLInventoryItem* inv_item = (LLInventoryItem*)obj;
  159. inv_type = inv_item->getInventoryType();
  160. // Count clothing items for later
  161. if (LLInventoryType::IT_WEARABLE == inv_type)
  162. {
  163. ++wearable_count;
  164. }
  165. // Skip items the object's owner can't copy (and hence cannot sell)
  166. if (!inv_item->getPermissions().allowTransferTo(gAgentID) ||
  167. !inv_item->getPermissions().allowCopyBy(owner_id, owner_id) ||
  168. !inv_item->getPermissions().getOwnership(owner_id, is_group_owned))
  169. {
  170. continue;
  171. }
  172. // There will be at least one item shown in the display, so go
  173. // ahead and enable the buy button.
  174. childEnable("buy_btn");
  175. // Create the line in the list
  176. LLSD row;
  177. bool item_is_multi = false;
  178. if (inv_item->getFlags() & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
  179. {
  180. item_is_multi = true;
  181. }
  182. icon_name = LLInventoryIcon::getIconName(inv_item->getType(),
  183. inv_item->getInventoryType(),
  184. inv_item->getFlags(),
  185. item_is_multi);
  186. row["columns"][0]["column"] = "icon";
  187. row["columns"][0]["type"] = "icon";
  188. row["columns"][0]["value"] = icon_name;
  189. // Append the permissions that you will acquire (not the current
  190. // permissions).
  191. U32 next_owner_mask = inv_item->getPermissions().getMaskNextOwner();
  192. std::string text = obj->getName();
  193. if (!(next_owner_mask & PERM_COPY))
  194. {
  195. text.append(getString("no_copy_text"));
  196. }
  197. if (!(next_owner_mask & PERM_MODIFY))
  198. {
  199. text.append(getString("no_modify_text"));
  200. }
  201. if (!(next_owner_mask & PERM_TRANSFER))
  202. {
  203. text.append(getString("no_transfer_text"));
  204. }
  205. row["columns"][1]["column"] = "text";
  206. row["columns"][1]["value"] = text;
  207. row["columns"][1]["font"] = "SANSSERIF";
  208. item_list->addElement(row);
  209. }
  210. if (wearable_count > 0)
  211. {
  212. childEnable("wear_check");
  213. childSetValue("wear_check", LLSD(false));
  214. }
  215. removeVOInventoryListener();
  216. }
  217. //static
  218. void LLFloaterBuyContents::onClickBuy(void* data)
  219. {
  220. LLFloaterBuyContents* self = (LLFloaterBuyContents*)data;
  221. if (!self) return;
  222. // Make sure this was not selected through other mechanisms (i.e. being the
  223. // default button and pressing enter).
  224. if (!self->childIsEnabled("buy_btn"))
  225. {
  226. // We shouldn't be enabled. Just close.
  227. self->close();
  228. return;
  229. }
  230. // We may want to wear this item
  231. if (self->childGetValue("wear_check"))
  232. {
  233. LLInventoryModel::sWearNewClothing = true;
  234. }
  235. // Put the items where we put new folders.
  236. const LLUUID& category_id = gInventory.getRootFolderID();
  237. // *NOTE: does not work for multiple object buy, which UI does not
  238. // currently support sale info is used for verification only, if it does
  239. // not match region info then the sale is cancelled.
  240. gSelectMgr.sendBuy(gAgentID, category_id, self->mSaleInfo);
  241. self->close();
  242. }
  243. //static
  244. void LLFloaterBuyContents::onClickCancel(void* data)
  245. {
  246. LLFloaterBuyContents* self = (LLFloaterBuyContents*)data;
  247. if (self)
  248. {
  249. self->close();
  250. }
  251. }