llfloaterproperties.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101
  1. /**
  2. * @file llfloaterproperties.cpp
  3. * @brief A floater which shows an inventory item's properties.
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewergpl$
  6. *
  7. * Copyright (c) 2002-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llfloaterproperties.h"
  34. #include "llbutton.h"
  35. #include "llcachename.h"
  36. #include "llcheckboxctrl.h"
  37. #include "lllineeditor.h"
  38. #include "llradiogroup.h"
  39. #include "lltextbox.h"
  40. #include "lluictrlfactory.h"
  41. #include "roles_constants.h"
  42. #include "llagent.h"
  43. #include "llfloateravatarinfo.h"
  44. #include "llfloatergroupinfo.h"
  45. #include "hbfloaterthumbnail.h"
  46. #include "llgridmanager.h"
  47. //MK
  48. #include "mkrlinterface.h"
  49. //mk
  50. #include "llviewercontrol.h"
  51. #include "llviewermessage.h" // For formatted_time()
  52. #include "llviewerobjectlist.h"
  53. //static
  54. LLFloaterProperties::instance_map_t LLFloaterProperties::sInstances;
  55. //static
  56. LLFloaterProperties* LLFloaterProperties::find(const LLUUID& item_id,
  57. const LLUUID& object_id)
  58. {
  59. // For simplicity's sake, we key the properties window with a single uuid.
  60. // However, the items are keyed by item and object (obj == null -> agent
  61. // inventory). So, we xor the two ids, and use that as a lookup key.
  62. instance_map_t::iterator it = sInstances.find(item_id ^ object_id);
  63. return it != sInstances.end() ? it->second : NULL;
  64. }
  65. //static
  66. void LLFloaterProperties::show(const LLUUID& item_id, const LLUUID& object_id,
  67. LLView* ownerp)
  68. {
  69. LLFloaterProperties* self = find(item_id, object_id);
  70. if (self)
  71. {
  72. LLMultiFloater* hostp = LLFloater::getFloaterHost();
  73. if (hostp && hostp != self->getHost())
  74. {
  75. // This properties window is being opened in a new context and
  76. // needs to be rehosted.
  77. // Remove ourselves from any dependency on another floater. Hb
  78. LLFloater* dependeep = self->getDependee();
  79. if (dependeep)
  80. {
  81. dependeep->removeDependentFloater(self);
  82. }
  83. // Rehost ourselves.
  84. hostp->addFloater(self, true);
  85. }
  86. self->refresh();
  87. self->open();
  88. }
  89. else
  90. {
  91. // Open a new floater.
  92. new LLFloaterProperties(item_id, object_id, ownerp);
  93. }
  94. }
  95. //static
  96. void LLFloaterProperties::dirtyAll()
  97. {
  98. LLUUID thumb_floater_id;
  99. for (instance_map_t::iterator it = sInstances.begin(),
  100. end = sInstances.end();
  101. it != end; ++it)
  102. {
  103. it->second->mDirty = true;
  104. // Close any associated thumbnail floater. HB
  105. thumb_floater_id = it->second->mItemID ^ it->second->mObjectID;
  106. HBFloaterThumbnail::hideInstance(thumb_floater_id);
  107. }
  108. }
  109. //static
  110. void LLFloaterProperties::closeByID(const LLUUID& item_id,
  111. const LLUUID& object_id)
  112. {
  113. LLFloaterProperties* self = find(item_id, object_id);
  114. if (self)
  115. {
  116. self->close();
  117. }
  118. }
  119. // Default constructor
  120. LLFloaterProperties::LLFloaterProperties(const LLUUID& item_id,
  121. const LLUUID& object_id,
  122. LLView* ownerp)
  123. : LLFloater(object_id.isNull() ? "inventory item properties"
  124. : "object inventory item properties"),
  125. mItemID(item_id),
  126. mObjectID(object_id),
  127. mDirty(true)
  128. {
  129. LLUICtrlFactory* factoryp = LLUICtrlFactory::getInstance();
  130. factoryp->buildFloater(this, "floater_inventory_item_properties.xml");
  131. if (!getHost()) // Hosted floaters shall not mess up with position. HB
  132. {
  133. LLView* parentp = ownerp;
  134. // Search for our owner's parent floater and register as dependent of
  135. // it if found. HB
  136. while (parentp)
  137. {
  138. LLFloater* floaterp = parentp->asFloater();
  139. if (floaterp)
  140. {
  141. floaterp->addDependentFloater(this);
  142. break;
  143. }
  144. parentp = parentp->getParent();
  145. }
  146. if (!parentp)
  147. {
  148. // Place ourselves in a smart way, like preview floaters...
  149. S32 left, top;
  150. gFloaterViewp->getNewFloaterPosition(&left, &top);
  151. translate(left - getRect().mLeft, top - getRect().mTop);
  152. gFloaterViewp->adjustToFitScreen(this);
  153. }
  154. }
  155. gInventory.addObserver(this);
  156. // Add the object to the static structure
  157. sInstances[mItemID ^ mObjectID] = this;
  158. }
  159. //virtual
  160. bool LLFloaterProperties::postBuild()
  161. {
  162. // Item name & description
  163. childSetPrevalidate("LabelItemName",
  164. LLLineEditor::prevalidatePrintableNotPipe);
  165. childSetCommitCallback("LabelItemName", onCommitName, this);
  166. childSetPrevalidate("LabelItemDesc",
  167. LLLineEditor::prevalidatePrintableNotPipe);
  168. childSetCommitCallback("LabelItemDesc", onCommitDescription, this);
  169. // Creator information
  170. childSetAction("BtnCreator", onClickCreator, this);
  171. // Owner information
  172. childSetAction("BtnOwner", onClickOwner, this);
  173. // Last owner information
  174. childSetAction("BtnLastOwner", onClickLastOwner, this);
  175. // Permissions
  176. // Group permissions
  177. childSetCommitCallback("CheckGroupCopy", onCommitPermissions, this);
  178. childSetCommitCallback("CheckGroupMod", onCommitPermissions, this);
  179. childSetCommitCallback("CheckGroupMove", onCommitPermissions, this);
  180. // Everyone's permissions
  181. childSetCommitCallback("CheckEveryoneCopy", onCommitPermissions, this);
  182. childSetCommitCallback("CheckEveryoneMove", onCommitPermissions, this);
  183. childSetCommitCallback("CheckEveryoneExport", onCommitPermissions, this);
  184. // Next owner permissions
  185. childSetCommitCallback("CheckNextOwnerModify", onCommitPermissions, this);
  186. childSetCommitCallback("CheckNextOwnerCopy", onCommitPermissions, this);
  187. childSetCommitCallback("CheckNextOwnerTransfer", onCommitPermissions, this);
  188. // Mark for sale or not, and sale info
  189. childSetCommitCallback("CheckPurchase", onCommitSale, this);
  190. childSetCommitCallback("RadioSaleType", onCommitSale, this);
  191. // "Price" label for edit
  192. childSetCommitCallback("EditPrice", onCommitSale, this);
  193. bool is_inv_item = mObjectID.isNull();
  194. setTitle(getString(is_inv_item ? "inv_item_prop" : "obj_item_prop"));
  195. // *TODO: implement thumbnails support for task inventory (does not work
  196. // properly for now, but since task inventory updates go through UDP and
  197. // not AISv3, this is rather "normal"). HB
  198. childSetVisible("BtnThumbnail", is_inv_item);
  199. if (is_inv_item)
  200. {
  201. // Associated thumbnail management. HB
  202. childSetAction("BtnThumbnail", onClickThumbnail, this);
  203. }
  204. // The UI has been built, now fill in all the values
  205. refresh();
  206. return true;
  207. }
  208. //virtual
  209. LLFloaterProperties::~LLFloaterProperties()
  210. {
  211. gInventory.removeObserver(this);
  212. // Clean up the static data.
  213. sInstances.erase(mItemID ^ mObjectID);
  214. }
  215. //virtual
  216. void LLFloaterProperties::changed(U32 mask)
  217. {
  218. // If there is a change we are interested in...
  219. constexpr U32 INTEREST_MASK = LLInventoryObserver::LABEL |
  220. LLInventoryObserver::INTERNAL |
  221. LLInventoryObserver::REMOVE;
  222. if (mask & INTEREST_MASK)
  223. {
  224. mDirty = true;
  225. }
  226. }
  227. //virtual
  228. void LLFloaterProperties::refresh()
  229. {
  230. LLInventoryItem* itemp = findItem();
  231. if (itemp)
  232. {
  233. refreshFromItem(itemp);
  234. return;
  235. }
  236. // RN: it is possible that the container object is in the middle of an
  237. // inventory refresh causing findItem() to fail, so just temporarily
  238. // disable everything
  239. mDirty = true;
  240. static const char* enable_names[] =
  241. {
  242. "LabelItemName",
  243. "LabelItemDesc",
  244. "LabelCreatorName",
  245. "BtnCreator",
  246. "LabelOwnerName",
  247. "BtnOwner",
  248. "LabelLastOwnerName",
  249. "BtnLastOwner",
  250. "BtnThumbnail",
  251. "CheckOwnerModify",
  252. "CheckOwnerCopy",
  253. "CheckOwnerTransfer",
  254. "CheckOwnerExport",
  255. "CheckGroupCopy",
  256. "CheckGroupMod",
  257. "CheckGroupMove",
  258. "CheckEveryoneCopy",
  259. "CheckEveryoneMove",
  260. "CheckEveryoneExport",
  261. "CheckNextOwnerModify",
  262. "CheckNextOwnerCopy",
  263. "CheckNextOwnerTransfer",
  264. "CheckPurchase",
  265. "RadioSaleType",
  266. "EditPrice"
  267. };
  268. constexpr size_t enable_names_count = LL_ARRAY_SIZE(enable_names);
  269. for (size_t t = 0; t < enable_names_count; ++t)
  270. {
  271. childSetEnabled(enable_names[t], false);
  272. }
  273. static const char* hide_names[] =
  274. {
  275. "BaseMaskDebug",
  276. "OwnerMaskDebug",
  277. "GroupMaskDebug",
  278. "EveryoneMaskDebug",
  279. "NextMaskDebug"
  280. };
  281. constexpr size_t hide_names_count = LL_ARRAY_SIZE(hide_names);
  282. for (size_t t = 0; t < hide_names_count; ++t)
  283. {
  284. childSetVisible(hide_names[t], false);
  285. }
  286. }
  287. //virtual
  288. void LLFloaterProperties::draw()
  289. {
  290. if (mDirty)
  291. {
  292. // Clear mDirty first because refresh() can set it back to true...
  293. mDirty = false;
  294. refresh();
  295. }
  296. LLFloater::draw();
  297. }
  298. void LLFloaterProperties::refreshFromItem(LLInventoryItem* itemp)
  299. {
  300. ////////////////////////
  301. // PERMISSIONS LOOKUP //
  302. ////////////////////////
  303. // Do not enable the UI for incomplete items.
  304. LLViewerInventoryItem* vitemp = (LLViewerInventoryItem*)itemp;
  305. bool is_complete = vitemp->isFinished();
  306. bool is_link = vitemp->getIsLinkType();
  307. bool is_object = !is_link && itemp->getType() == LLAssetType::AT_OBJECT;
  308. bool no_restrict =
  309. LLInventoryType::cannotRestrictPermissions(vitemp->getInventoryType());
  310. const LLPermissions& perm = itemp->getPermissions();
  311. bool can_agent_manipulate = gAgent.allowOperation(PERM_OWNER, perm,
  312. GP_OBJECT_MANIPULATE);
  313. bool can_agent_sell = !no_restrict &&
  314. gAgent.allowOperation(PERM_OWNER, perm,
  315. GP_OBJECT_SET_SALE);
  316. // You need permission to modify the object to modify an inventory item in
  317. // it.
  318. LLViewerObject* object = NULL;
  319. if (mObjectID.notNull())
  320. {
  321. object = gObjectList.findObject(mObjectID);
  322. }
  323. bool is_obj_modify = !object || object->permOwnerModify();
  324. //////////////////////
  325. // ITEM NAME & DESC //
  326. //////////////////////
  327. bool is_modifiable = is_obj_modify && is_complete &&
  328. gAgent.allowOperation(PERM_MODIFY, perm,
  329. GP_OBJECT_MANIPULATE);
  330. childSetEnabled("LabelItemNameTitle", true);
  331. bool can_rename =
  332. is_modifiable &&
  333. // Do not allow to rename calling cards
  334. vitemp->getInventoryType() != LLInventoryType::IT_CALLINGCARD;
  335. childSetEnabled("LabelItemName", can_rename);
  336. childSetText("LabelItemName", itemp->getName());
  337. childSetEnabled("LabelItemDescTitle", true);
  338. childSetEnabled("LabelItemDesc", is_modifiable);
  339. childSetVisible("IconLocked", !is_modifiable);
  340. childSetText("LabelItemDesc", itemp->getDescription());
  341. if (is_link)
  342. {
  343. LL_DEBUGS("Properties") << "Link description for: " << itemp->getName()
  344. << " : " << itemp->getActualDescription()
  345. << LL_ENDL;
  346. }
  347. //////////////////
  348. // CREATOR NAME //
  349. //////////////////
  350. if (!gCacheNamep) return;
  351. if (itemp->getCreatorUUID().notNull())
  352. {
  353. childSetEnabled("BtnCreator", true);
  354. childSetEnabled("LabelCreatorTitle", true);
  355. childSetEnabled("LabelCreatorName", true);
  356. std::string name;
  357. gCacheNamep->getFullName(itemp->getCreatorUUID(), name);
  358. childSetText("LabelCreatorName", name);
  359. }
  360. else
  361. {
  362. childSetEnabled("BtnCreator", false);
  363. childSetEnabled("LabelCreatorTitle", false);
  364. childSetEnabled("LabelCreatorName", false);
  365. childSetText("LabelCreatorName", getString("unknown"));
  366. }
  367. ////////////////
  368. // OWNER NAME //
  369. ////////////////
  370. if (perm.isOwned())
  371. {
  372. childSetEnabled("BtnOwner", true);
  373. childSetEnabled("LabelOwnerTitle", true);
  374. childSetEnabled("LabelOwnerName", true);
  375. std::string name;
  376. if (perm.isGroupOwned())
  377. {
  378. gCacheNamep->getGroupName(perm.getGroup(), name);
  379. }
  380. else
  381. {
  382. gCacheNamep->getFullName(perm.getOwner(), name);
  383. //MK
  384. if (gRLenabled &&
  385. (gRLInterface.mContainsShownames ||
  386. gRLInterface.mContainsShownametags))
  387. {
  388. name = gRLInterface.getDummyName(name);
  389. }
  390. //mk
  391. }
  392. childSetText("LabelOwnerName", name);
  393. }
  394. else
  395. {
  396. childSetEnabled("BtnOwner", false);
  397. childSetEnabled("LabelOwnerTitle", false);
  398. childSetEnabled("LabelOwnerName", false);
  399. childSetText("LabelOwnerName", getString("public"));
  400. }
  401. /////////////////////
  402. // LAST OWNER NAME //
  403. /////////////////////
  404. if (perm.getLastOwner().notNull())
  405. {
  406. childSetEnabled("BtnLastOwner", true);
  407. childSetEnabled("LabelLastOwnerTitle", true);
  408. childSetEnabled("LabelLastOwnerName", true);
  409. std::string name;
  410. gCacheNamep->getFullName(perm.getLastOwner(), name);
  411. //MK
  412. if (gRLenabled &&
  413. (gRLInterface.mContainsShownames ||
  414. gRLInterface.mContainsShownametags))
  415. {
  416. name = gRLInterface.getDummyName(name);
  417. }
  418. //mk
  419. childSetText("LabelLastOwnerName", name);
  420. }
  421. else
  422. {
  423. childSetEnabled("BtnLastOwner", false);
  424. childSetEnabled("LabelLastOwnerTitle", false);
  425. childSetEnabled("LabelLastOwnerName", false);
  426. childSetText("LabelLastOwnerName", getString("unknown"));
  427. }
  428. //////////////////
  429. // ACQUIRE DATE //
  430. //////////////////
  431. time_t time_utc = itemp->getCreationDate();
  432. std::string timestr;
  433. if (time_utc == 0)
  434. {
  435. timestr = getString("unknown");
  436. }
  437. else
  438. {
  439. timestr = formatted_time(time_utc);
  440. }
  441. childSetText("LabelAcquiredDate", timestr);
  442. ///////////////////////
  443. // OWNER PERMISSIONS //
  444. ///////////////////////
  445. if (can_agent_manipulate)
  446. {
  447. childSetText("OwnerLabel", getString("you_can"));
  448. }
  449. else
  450. {
  451. childSetText("OwnerLabel", getString("owner_can"));
  452. }
  453. U32 base_mask = perm.getMaskBase();
  454. U32 owner_mask = perm.getMaskOwner();
  455. U32 group_mask = perm.getMaskGroup();
  456. U32 everyone_mask = perm.getMaskEveryone();
  457. U32 next_owner_mask = perm.getMaskNextOwner();
  458. childSetEnabled("OwnerLabel", true);
  459. childSetEnabled("CheckOwnerModify", false);
  460. childSetValue("CheckOwnerModify", (owner_mask & PERM_MODIFY) != 0);
  461. childSetEnabled("CheckOwnerCopy", false);
  462. childSetValue("CheckOwnerCopy", (owner_mask & PERM_COPY) != 0);
  463. childSetEnabled("CheckOwnerTransfer", false);
  464. childSetValue("CheckOwnerTransfer", (owner_mask & PERM_TRANSFER) != 0);
  465. bool export_support = gAgent.regionHasExportPermSupport();
  466. // You can never change this yourself !
  467. childSetEnabled("CheckOwnerExport", false);
  468. childSetValue("CheckOwnerExport",
  469. export_support && (owner_mask & PERM_EXPORT) != 0);
  470. childSetVisible("CheckOwnerExport", export_support);
  471. ///////////////////////
  472. // DEBUG PERMISSIONS //
  473. ///////////////////////
  474. static LLCachedControl<bool> debug_permissions(gSavedSettings,
  475. "DebugPermissions");
  476. if (debug_permissions)
  477. {
  478. bool slam_perm = false;
  479. bool overwrite_group = false;
  480. bool overwrite_everyone = false;
  481. if (is_object)
  482. {
  483. U32 flags = itemp->getFlags();
  484. slam_perm =
  485. (flags & LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM) != 0;
  486. overwrite_everyone =
  487. (flags & LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE) != 0;
  488. overwrite_group =
  489. (flags & LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP) != 0;
  490. }
  491. std::string perm_string;
  492. perm_string = "B: ";
  493. perm_string += mask_to_string(base_mask, export_support);
  494. childSetText("BaseMaskDebug", perm_string);
  495. childSetVisible("BaseMaskDebug", true);
  496. perm_string = "O: ";
  497. perm_string += mask_to_string(owner_mask, export_support);
  498. childSetText("OwnerMaskDebug",perm_string);
  499. childSetVisible("OwnerMaskDebug", true);
  500. perm_string = "G";
  501. perm_string += overwrite_group ? "*: " : ": ";
  502. perm_string += mask_to_string(group_mask);
  503. childSetText("GroupMaskDebug", perm_string);
  504. childSetVisible("GroupMaskDebug", true);
  505. perm_string = "E";
  506. perm_string += overwrite_everyone ? "*: " : ": ";
  507. perm_string += mask_to_string(everyone_mask, export_support);
  508. childSetText("EveryoneMaskDebug", perm_string);
  509. childSetVisible("EveryoneMaskDebug", true);
  510. perm_string = "N";
  511. perm_string += slam_perm ? "*: " : ": ";
  512. perm_string += mask_to_string(next_owner_mask, export_support);
  513. childSetText("NextMaskDebug", perm_string);
  514. childSetVisible("NextMaskDebug", true);
  515. }
  516. else
  517. {
  518. childSetVisible("BaseMaskDebug", false);
  519. childSetVisible("OwnerMaskDebug", false);
  520. childSetVisible("GroupMaskDebug", false);
  521. childSetVisible("EveryoneMaskDebug", false);
  522. childSetVisible("NextMaskDebug", false);
  523. }
  524. /////////////
  525. // SHARING //
  526. /////////////
  527. // Check for ability to change values.
  528. if (!is_link && is_obj_modify && can_agent_manipulate)
  529. {
  530. bool can_share = (owner_mask & PERM_COPY) != 0 &&
  531. (owner_mask & PERM_TRANSFER) != 0;
  532. childSetEnabled("GroupLabel", true);
  533. childSetEnabled("CheckGroupCopy", can_share && !no_restrict);
  534. childSetEnabled("CheckGroupMod",
  535. can_share && !no_restrict &&
  536. (owner_mask & PERM_MODIFY) != 0);
  537. childSetEnabled("CheckGroupMove", is_object && !no_restrict);
  538. childSetEnabled("EveryoneLabel", true);
  539. childSetEnabled("CheckEveryoneCopy", can_share && !no_restrict);
  540. childSetEnabled("CheckEveryoneMove", is_object && !no_restrict);
  541. childSetEnabled("CheckEveryoneExport",
  542. export_support && !no_restrict &&
  543. itemp->getCreatorUUID() == gAgentID &&
  544. can_set_export(base_mask, owner_mask,
  545. next_owner_mask));
  546. }
  547. else
  548. {
  549. childSetEnabled("GroupLabel", false);
  550. childSetEnabled("CheckGroupCopy", false);
  551. childSetEnabled("CheckGroupMod", false);
  552. childSetEnabled("CheckGroupMove", false);
  553. childSetEnabled("EveryoneLabel", false);
  554. childSetEnabled("CheckEveryoneCopy", false);
  555. childSetEnabled("CheckEveryoneMove", false);
  556. childSetEnabled("CheckEveryoneExport", false);
  557. }
  558. childSetVisible("CheckGroupMove", is_object);
  559. childSetVisible("CheckEveryoneMove", is_object);
  560. childSetVisible("CheckEveryoneExport", export_support);
  561. // Set values.
  562. childSetValue("CheckGroupCopy", (group_mask & PERM_COPY) != 0);
  563. childSetValue("CheckGroupMod", (group_mask & PERM_MODIFY) != 0);
  564. childSetValue("CheckGroupMove", (group_mask & PERM_MOVE) != 0);
  565. childSetValue("CheckEveryoneCopy", (everyone_mask & PERM_COPY) != 0);
  566. childSetValue("CheckEveryoneMove", (everyone_mask & PERM_MOVE) != 0);
  567. childSetValue("CheckEveryoneExport",
  568. export_support && (everyone_mask & PERM_EXPORT) != 0);
  569. ///////////////
  570. // SALE INFO //
  571. ///////////////
  572. const LLSaleInfo& sale_info = itemp->getSaleInfo();
  573. bool is_for_sale = sale_info.isForSale();
  574. // Check for ability to change values.
  575. if (is_obj_modify && can_agent_sell &&
  576. gAgent.allowOperation(PERM_TRANSFER, perm, GP_OBJECT_MANIPULATE))
  577. {
  578. childSetEnabled("CheckPurchase", is_complete);
  579. // Next owner perms can't be changed if export is set
  580. bool no_export = (everyone_mask & PERM_EXPORT) == 0;
  581. childSetEnabled("NextOwnerLabel", no_export && !no_restrict);
  582. childSetEnabled("CheckNextOwnerModify",
  583. no_export && !no_restrict &&
  584. (base_mask & PERM_MODIFY) != 0);
  585. childSetEnabled("CheckNextOwnerCopy",
  586. no_export && !no_restrict &&
  587. (base_mask & PERM_COPY) != 0);
  588. childSetEnabled("CheckNextOwnerTransfer",
  589. no_export && !no_restrict &&
  590. (next_owner_mask & PERM_COPY) != 0);
  591. childSetEnabled("RadioSaleType", is_complete && is_for_sale);
  592. childSetEnabled("TextPrice", is_complete && is_for_sale);
  593. childSetEnabled("EditPrice", is_complete && is_for_sale);
  594. }
  595. else
  596. {
  597. childSetEnabled("CheckPurchase", false);
  598. childSetEnabled("NextOwnerLabel", false);
  599. childSetEnabled("CheckNextOwnerModify", false);
  600. childSetEnabled("CheckNextOwnerCopy", false);
  601. childSetEnabled("CheckNextOwnerTransfer", false);
  602. childSetEnabled("RadioSaleType", false);
  603. childSetEnabled("TextPrice", false);
  604. childSetEnabled("EditPrice", false);
  605. }
  606. // Set values.
  607. childSetValue("CheckPurchase", is_for_sale);
  608. childSetValue("CheckNextOwnerModify",
  609. LLSD((next_owner_mask & PERM_MODIFY) != 0));
  610. childSetValue("CheckNextOwnerCopy",
  611. LLSD((next_owner_mask & PERM_COPY) != 0));
  612. childSetValue("CheckNextOwnerTransfer",
  613. LLSD((next_owner_mask & PERM_TRANSFER) != 0));
  614. LLRadioGroup* radioSaleType = getChild<LLRadioGroup>("RadioSaleType");
  615. if (is_for_sale)
  616. {
  617. childSetEnabled("contents", is_object);
  618. radioSaleType->setSelectedIndex((S32)sale_info.getSaleType() - 1);
  619. S32 numerical_price;
  620. numerical_price = sale_info.getSalePrice();
  621. childSetText("EditPrice", llformat("%d", numerical_price));
  622. }
  623. else
  624. {
  625. radioSaleType->setSelectedIndex(-1);
  626. childSetText("EditPrice", llformat("%d", 0));
  627. }
  628. }
  629. //static
  630. void LLFloaterProperties::onClickCreator(void* datap)
  631. {
  632. LLFloaterProperties* self = (LLFloaterProperties*)datap;
  633. LLInventoryItem* itemp = self ? self->findItem() : NULL;
  634. if (itemp)
  635. {
  636. const LLUUID& creator_id = itemp->getCreatorUUID();
  637. if (creator_id.notNull())
  638. {
  639. LLFloaterAvatarInfo::showFromObject(creator_id);
  640. }
  641. }
  642. }
  643. //static
  644. void LLFloaterProperties::onClickOwner(void* datap)
  645. {
  646. //MK
  647. if (gRLenabled &&
  648. (gRLInterface.mContainsShownames ||
  649. gRLInterface.mContainsShownametags))
  650. {
  651. return;
  652. }
  653. //mk
  654. LLFloaterProperties* self = (LLFloaterProperties*)datap;
  655. LLInventoryItem* itemp = self ? self->findItem() : NULL;
  656. if (itemp)
  657. {
  658. const LLPermissions& perms = itemp->getPermissions();
  659. if (perms.isGroupOwned())
  660. {
  661. LLFloaterGroupInfo::showFromUUID(perms.getGroup());
  662. }
  663. else if (perms.getOwner().notNull())
  664. {
  665. LLFloaterAvatarInfo::showFromObject(perms.getOwner());
  666. }
  667. }
  668. }
  669. //static
  670. void LLFloaterProperties::onClickLastOwner(void* datap)
  671. {
  672. //MK
  673. if (gRLenabled &&
  674. (gRLInterface.mContainsShownames ||
  675. gRLInterface.mContainsShownametags))
  676. {
  677. return;
  678. }
  679. //mk
  680. LLFloaterProperties* self = (LLFloaterProperties*)datap;
  681. LLInventoryItem* itemp = self ? self->findItem() : NULL;
  682. if (itemp)
  683. {
  684. const LLPermissions& perms = itemp->getPermissions();
  685. if (perms.getLastOwner().notNull())
  686. {
  687. LLFloaterAvatarInfo::showFromObject(perms.getLastOwner());
  688. }
  689. }
  690. }
  691. //static
  692. void LLFloaterProperties::onClickThumbnail(void* datap)
  693. {
  694. LLFloaterProperties* self = (LLFloaterProperties*)datap;
  695. if (self)
  696. {
  697. HBFloaterThumbnail::showInstance(self->mItemID, self->mObjectID);
  698. }
  699. }
  700. //static
  701. void LLFloaterProperties::onCommitName(LLUICtrl*, void* datap)
  702. {
  703. LLFloaterProperties* self = (LLFloaterProperties*)datap;
  704. if (!self)
  705. {
  706. return;
  707. }
  708. LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)self->findItem();
  709. if (!itemp)
  710. {
  711. return;
  712. }
  713. LLLineEditor* lineeditp = self->getChild<LLLineEditor>("LabelItemName");
  714. if (itemp->getName() != lineeditp->getText() &&
  715. gAgent.allowOperation(PERM_MODIFY, itemp->getPermissions(),
  716. GP_OBJECT_MANIPULATE))
  717. {
  718. LLPointer<LLViewerInventoryItem> new_itemp =
  719. new LLViewerInventoryItem(itemp);
  720. new_itemp->rename(lineeditp->getText());
  721. if (self->mObjectID.isNull())
  722. {
  723. new_itemp->updateServer(false);
  724. gInventory.updateItem(new_itemp);
  725. gInventory.notifyObservers();
  726. }
  727. else
  728. {
  729. LLViewerObject* objectp = gObjectList.findObject(self->mObjectID);
  730. if (objectp)
  731. {
  732. objectp->updateInventory(new_itemp);
  733. }
  734. }
  735. }
  736. }
  737. //static
  738. void LLFloaterProperties::onCommitDescription(LLUICtrl*, void* datap)
  739. {
  740. LLFloaterProperties* self = (LLFloaterProperties*)datap;
  741. if (!self) return;
  742. LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)self->findItem();
  743. if (!itemp) return;
  744. LLLineEditor* descp = self->getChild<LLLineEditor>("LabelItemDesc");
  745. if (!descp)
  746. {
  747. return;
  748. }
  749. if (itemp->getDescription() != descp->getText() &&
  750. gAgent.allowOperation(PERM_MODIFY, itemp->getPermissions(),
  751. GP_OBJECT_MANIPULATE))
  752. {
  753. LLPointer<LLViewerInventoryItem> new_itemp =
  754. new LLViewerInventoryItem(itemp);
  755. new_itemp->setDescription(descp->getText());
  756. if (self->mObjectID.isNull())
  757. {
  758. new_itemp->updateServer(false);
  759. gInventory.updateItem(new_itemp);
  760. gInventory.notifyObservers();
  761. }
  762. else
  763. {
  764. LLViewerObject* objectp = gObjectList.findObject(self->mObjectID);
  765. if (objectp)
  766. {
  767. objectp->updateInventory(new_itemp);
  768. }
  769. }
  770. }
  771. }
  772. //static
  773. void LLFloaterProperties::onCommitPermissions(LLUICtrl*, void* datap)
  774. {
  775. LLFloaterProperties* self = (LLFloaterProperties*)datap;
  776. if (!self) return;
  777. LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)self->findItem();
  778. if (!itemp) return;
  779. const LLUUID& group_id = gAgent.getGroupID();
  780. LLPermissions perm(itemp->getPermissions());
  781. LLCheckBoxCtrl* checkp = self->getChild<LLCheckBoxCtrl>("CheckGroupMod");
  782. perm.setGroupBits(gAgentID, group_id, checkp->get(), PERM_MODIFY);
  783. checkp = self->getChild<LLCheckBoxCtrl>("CheckGroupCopy");
  784. perm.setGroupBits(gAgentID, group_id, checkp->get(), PERM_COPY);
  785. checkp = self->getChild<LLCheckBoxCtrl>("CheckGroupMove");
  786. // Do not attempt to change this permission when not supported (not an
  787. // object, i.e. not rezzable)...
  788. if (checkp->getVisible())
  789. {
  790. perm.setGroupBits(gAgentID, group_id, checkp->get(), PERM_MOVE);
  791. }
  792. checkp = self->getChild<LLCheckBoxCtrl>("CheckEveryoneCopy");
  793. perm.setEveryoneBits(gAgentID, group_id, checkp->get(), PERM_COPY);
  794. checkp = self->getChild<LLCheckBoxCtrl>("CheckEveryoneMove");
  795. // Do not attempt to change this permission when not supported (not an
  796. // object, i.e. not rezzable)...
  797. if (checkp->getVisible())
  798. {
  799. perm.setEveryoneBits(gAgentID, group_id, checkp->get(), PERM_MOVE);
  800. }
  801. checkp = self->getChild<LLCheckBoxCtrl>("CheckEveryoneExport");
  802. // Do not attempt to change this permission when not supported...
  803. if (checkp->getVisible())
  804. {
  805. perm.setEveryoneBits(gAgentID, group_id, checkp->get(), PERM_EXPORT);
  806. }
  807. checkp = self->getChild<LLCheckBoxCtrl>("CheckNextOwnerModify");
  808. perm.setNextOwnerBits(gAgentID, group_id, checkp->get(), PERM_MODIFY);
  809. checkp = self->getChild<LLCheckBoxCtrl>("CheckNextOwnerCopy");
  810. perm.setNextOwnerBits(gAgentID, group_id, checkp->get(), PERM_COPY);
  811. checkp = self->getChild<LLCheckBoxCtrl>("CheckNextOwnerTransfer");
  812. perm.setNextOwnerBits(gAgentID, group_id, checkp->get(), PERM_TRANSFER);
  813. if (perm != itemp->getPermissions() && itemp->isFinished())
  814. {
  815. LLPointer<LLViewerInventoryItem> new_itemp =
  816. new LLViewerInventoryItem(itemp);
  817. new_itemp->setPermissions(perm);
  818. U32 flags = new_itemp->getFlags();
  819. // Object permissions
  820. if (itemp->getType() == LLAssetType::AT_OBJECT)
  821. {
  822. // If next owner permissions have changed then set the slam
  823. // permissions flag so that they are applied on rez.
  824. if (perm.getMaskNextOwner() !=
  825. itemp->getPermissions().getMaskNextOwner())
  826. {
  827. flags |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM;
  828. }
  829. // If everyone permissions have changed then set the overwrite
  830. // everyone permissions flag so they are applied on rez.
  831. if (perm.getMaskEveryone() !=
  832. itemp->getPermissions().getMaskEveryone())
  833. {
  834. flags |=
  835. LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
  836. }
  837. // If group permissions have changed then set the overwrite group
  838. // permissions flag so they are applied on rez.
  839. if (perm.getMaskGroup() != itemp->getPermissions().getMaskGroup())
  840. {
  841. flags |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
  842. }
  843. }
  844. new_itemp->setFlags(flags);
  845. if (self->mObjectID.isNull())
  846. {
  847. new_itemp->updateServer(false);
  848. gInventory.updateItem(new_itemp);
  849. gInventory.notifyObservers();
  850. }
  851. else
  852. {
  853. LLViewerObject* objectp = gObjectList.findObject(self->mObjectID);
  854. if (objectp)
  855. {
  856. objectp->updateInventory(new_itemp);
  857. }
  858. }
  859. }
  860. else
  861. {
  862. // Need to make sure we do not just follow the click
  863. self->refresh();
  864. }
  865. }
  866. //static
  867. void LLFloaterProperties::onCommitSale(LLUICtrl*, void* data)
  868. {
  869. LLFloaterProperties* self = (LLFloaterProperties*)data;
  870. if (self)
  871. {
  872. self->updateSaleInfo();
  873. }
  874. }
  875. void LLFloaterProperties::updateSaleInfo()
  876. {
  877. LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
  878. if (!item) return;
  879. LLSaleInfo sale_info(item->getSaleInfo());
  880. if (!gAgent.allowOperation(PERM_TRANSFER, item->getPermissions(),
  881. GP_OBJECT_SET_SALE))
  882. {
  883. childSetValue("CheckPurchase", false);
  884. }
  885. if (childGetValue("CheckPurchase").asBoolean())
  886. {
  887. // turn on sale info
  888. LLSaleInfo::EForSale sale_type = LLSaleInfo::FS_COPY;
  889. LLRadioGroup* RadioSaleType = getChild<LLRadioGroup>("RadioSaleType");
  890. if (RadioSaleType)
  891. {
  892. switch (RadioSaleType->getSelectedIndex())
  893. {
  894. case 0:
  895. sale_type = LLSaleInfo::FS_ORIGINAL;
  896. break;
  897. case 2:
  898. sale_type = LLSaleInfo::FS_CONTENTS;
  899. break;
  900. case 1:
  901. default:
  902. sale_type = LLSaleInfo::FS_COPY;
  903. break;
  904. }
  905. }
  906. if (sale_type == LLSaleInfo::FS_COPY &&
  907. !gAgent.allowOperation(PERM_COPY, item->getPermissions(),
  908. GP_OBJECT_SET_SALE))
  909. {
  910. sale_type = LLSaleInfo::FS_ORIGINAL;
  911. }
  912. LLLineEditor* EditPrice = getChild<LLLineEditor>("EditPrice");
  913. S32 price = -1;
  914. if (EditPrice)
  915. {
  916. price = atoi(EditPrice->getText().c_str());
  917. }
  918. // Invalid data - turn off the sale
  919. if (price < 0)
  920. {
  921. sale_type = LLSaleInfo::FS_NOT;
  922. price = 0;
  923. }
  924. sale_info.setSaleType(sale_type);
  925. sale_info.setSalePrice(price);
  926. }
  927. else
  928. {
  929. sale_info.setSaleType(LLSaleInfo::FS_NOT);
  930. }
  931. if (sale_info != item->getSaleInfo() && item->isFinished())
  932. {
  933. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
  934. // Force an update on the sale price at rez
  935. if (item->getType() == LLAssetType::AT_OBJECT)
  936. {
  937. U32 flags = new_item->getFlags();
  938. flags |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_SALE;
  939. new_item->setFlags(flags);
  940. }
  941. new_item->setSaleInfo(sale_info);
  942. if (mObjectID.isNull())
  943. {
  944. // This is in the agent's inventory.
  945. new_item->updateServer(false);
  946. gInventory.updateItem(new_item);
  947. gInventory.notifyObservers();
  948. }
  949. else
  950. {
  951. // This is in an object's contents.
  952. LLViewerObject* object = gObjectList.findObject(mObjectID);
  953. if (object)
  954. {
  955. object->updateInventory(new_item);
  956. }
  957. }
  958. }
  959. else
  960. {
  961. // need to make sure we do not just follow the click
  962. refresh();
  963. }
  964. }
  965. LLInventoryItem* LLFloaterProperties::findItem() const
  966. {
  967. if (mObjectID.isNull())
  968. {
  969. // It should be in the agent's inventory
  970. return (LLInventoryItem*)gInventory.getItem(mItemID);
  971. }
  972. LLViewerObject* objectp = gObjectList.findObject(mObjectID);
  973. if (objectp)
  974. {
  975. return (LLInventoryItem*)objectp->getInventoryObject(mItemID);
  976. }
  977. return NULL;
  978. }
  979. ///----------------------------------------------------------------------------
  980. /// LLMultiProperties
  981. ///----------------------------------------------------------------------------
  982. LLMultiProperties::LLMultiProperties(const LLRect& rect)
  983. : LLMultiFloater(std::string("Properties"), rect)
  984. {
  985. }