PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/newview/llinventoryfunctions.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1090 lines | 864 code | 146 blank | 80 comment | 198 complexity | 68ddf5bc43f3beb3fda5bc436f51f25b MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llinventoryfunctions.cpp
  3. * @brief Implementation of the inventory view and associated stuff.
  4. *
  5. * $LicenseInfo:firstyear=2001&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 <utility> // for std::pair<>
  28. #include "llinventoryfunctions.h"
  29. // library includes
  30. #include "llagent.h"
  31. #include "llagentwearables.h"
  32. #include "llcallingcard.h"
  33. #include "llfloaterreg.h"
  34. #include "llinventorydefines.h"
  35. #include "llsdserialize.h"
  36. #include "llfiltereditor.h"
  37. #include "llspinctrl.h"
  38. #include "llui.h"
  39. #include "message.h"
  40. // newview includes
  41. #include "llappearancemgr.h"
  42. #include "llappviewer.h"
  43. //#include "llfirstuse.h"
  44. #include "llfloaterinventory.h"
  45. #include "llfloatersidepanelcontainer.h"
  46. #include "llfocusmgr.h"
  47. #include "llfolderview.h"
  48. #include "llgesturemgr.h"
  49. #include "lliconctrl.h"
  50. #include "llimview.h"
  51. #include "llinventorybridge.h"
  52. #include "llinventoryclipboard.h"
  53. #include "llinventorymodel.h"
  54. #include "llinventorypanel.h"
  55. #include "lllineeditor.h"
  56. #include "llmarketplacenotifications.h"
  57. #include "llmenugl.h"
  58. #include "llnotificationsutil.h"
  59. #include "llpanelmaininventory.h"
  60. #include "llpreviewanim.h"
  61. #include "llpreviewgesture.h"
  62. #include "llpreviewnotecard.h"
  63. #include "llpreviewscript.h"
  64. #include "llpreviewsound.h"
  65. #include "llpreviewtexture.h"
  66. #include "llresmgr.h"
  67. #include "llscrollbar.h"
  68. #include "llscrollcontainer.h"
  69. #include "llselectmgr.h"
  70. #include "llsidepanelinventory.h"
  71. #include "lltabcontainer.h"
  72. #include "lltooldraganddrop.h"
  73. #include "lluictrlfactory.h"
  74. #include "llviewermessage.h"
  75. #include "llviewerobjectlist.h"
  76. #include "llviewerregion.h"
  77. #include "llviewerwindow.h"
  78. #include "llvoavatarself.h"
  79. #include "llwearablelist.h"
  80. #include <boost/foreach.hpp>
  81. BOOL LLInventoryState::sWearNewClothing = FALSE;
  82. LLUUID LLInventoryState::sWearNewClothingTransactionID;
  83. // Generates a string containing the path to the item specified by
  84. // item_id.
  85. void append_path(const LLUUID& id, std::string& path)
  86. {
  87. std::string temp;
  88. const LLInventoryObject* obj = gInventory.getObject(id);
  89. LLUUID parent_id;
  90. if(obj) parent_id = obj->getParentUUID();
  91. std::string forward_slash("/");
  92. while(obj)
  93. {
  94. obj = gInventory.getCategory(parent_id);
  95. if(obj)
  96. {
  97. temp.assign(forward_slash + obj->getName() + temp);
  98. parent_id = obj->getParentUUID();
  99. }
  100. }
  101. path.append(temp);
  102. }
  103. void change_item_parent(LLInventoryModel* model,
  104. LLViewerInventoryItem* item,
  105. const LLUUID& new_parent_id,
  106. BOOL restamp)
  107. {
  108. if (item->getParentUUID() != new_parent_id)
  109. {
  110. LLInventoryModel::update_list_t update;
  111. LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
  112. update.push_back(old_folder);
  113. LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
  114. update.push_back(new_folder);
  115. gInventory.accountForUpdate(update);
  116. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
  117. new_item->setParent(new_parent_id);
  118. new_item->updateParentOnServer(restamp);
  119. model->updateItem(new_item);
  120. model->notifyObservers();
  121. }
  122. }
  123. void change_category_parent(LLInventoryModel* model,
  124. LLViewerInventoryCategory* cat,
  125. const LLUUID& new_parent_id,
  126. BOOL restamp)
  127. {
  128. if (!model || !cat)
  129. {
  130. return;
  131. }
  132. // Can't move a folder into a child of itself.
  133. if (model->isObjectDescendentOf(new_parent_id, cat->getUUID()))
  134. {
  135. return;
  136. }
  137. LLInventoryModel::update_list_t update;
  138. LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
  139. update.push_back(old_folder);
  140. LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
  141. update.push_back(new_folder);
  142. model->accountForUpdate(update);
  143. LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
  144. new_cat->setParent(new_parent_id);
  145. new_cat->updateParentOnServer(restamp);
  146. model->updateCategory(new_cat);
  147. model->notifyObservers();
  148. }
  149. void remove_category(LLInventoryModel* model, const LLUUID& cat_id)
  150. {
  151. if (!model || !get_is_category_removable(model, cat_id))
  152. {
  153. return;
  154. }
  155. // Look for any gestures and deactivate them
  156. LLInventoryModel::cat_array_t descendent_categories;
  157. LLInventoryModel::item_array_t descendent_items;
  158. gInventory.collectDescendents(cat_id, descendent_categories, descendent_items, FALSE);
  159. for (LLInventoryModel::item_array_t::const_iterator iter = descendent_items.begin();
  160. iter != descendent_items.end();
  161. ++iter)
  162. {
  163. const LLViewerInventoryItem* item = (*iter);
  164. const LLUUID& item_id = item->getUUID();
  165. if (item->getType() == LLAssetType::AT_GESTURE
  166. && LLGestureMgr::instance().isGestureActive(item_id))
  167. {
  168. LLGestureMgr::instance().deactivateGesture(item_id);
  169. }
  170. }
  171. LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
  172. if (cat)
  173. {
  174. const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
  175. change_category_parent(model, cat, trash_id, TRUE);
  176. }
  177. }
  178. void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name)
  179. {
  180. LLViewerInventoryCategory* cat;
  181. if (!model ||
  182. !get_is_category_renameable(model, cat_id) ||
  183. (cat = model->getCategory(cat_id)) == NULL ||
  184. cat->getName() == new_name)
  185. {
  186. return;
  187. }
  188. LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
  189. new_cat->rename(new_name);
  190. new_cat->updateServer(FALSE);
  191. model->updateCategory(new_cat);
  192. model->notifyObservers();
  193. }
  194. class LLInventoryCollectAllItems : public LLInventoryCollectFunctor
  195. {
  196. public:
  197. virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
  198. {
  199. return true;
  200. }
  201. };
  202. BOOL get_is_parent_to_worn_item(const LLUUID& id)
  203. {
  204. const LLViewerInventoryCategory* cat = gInventory.getCategory(id);
  205. if (!cat)
  206. {
  207. return FALSE;
  208. }
  209. LLInventoryModel::cat_array_t cats;
  210. LLInventoryModel::item_array_t items;
  211. LLInventoryCollectAllItems collect_all;
  212. gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), cats, items, LLInventoryModel::EXCLUDE_TRASH, collect_all);
  213. for (LLInventoryModel::item_array_t::const_iterator it = items.begin(); it != items.end(); ++it)
  214. {
  215. const LLViewerInventoryItem * const item = *it;
  216. llassert(item->getIsLinkType());
  217. LLUUID linked_id = item->getLinkedUUID();
  218. const LLViewerInventoryItem * const linked_item = gInventory.getItem(linked_id);
  219. if (linked_item)
  220. {
  221. LLUUID parent_id = linked_item->getParentUUID();
  222. while (!parent_id.isNull())
  223. {
  224. LLInventoryCategory * parent_cat = gInventory.getCategory(parent_id);
  225. if (cat == parent_cat)
  226. {
  227. return TRUE;
  228. }
  229. parent_id = parent_cat->getParentUUID();
  230. }
  231. }
  232. }
  233. return FALSE;
  234. }
  235. BOOL get_is_item_worn(const LLUUID& id)
  236. {
  237. const LLViewerInventoryItem* item = gInventory.getItem(id);
  238. if (!item)
  239. return FALSE;
  240. // Consider the item as worn if it has links in COF.
  241. if (LLAppearanceMgr::instance().isLinkInCOF(id))
  242. {
  243. return TRUE;
  244. }
  245. switch(item->getType())
  246. {
  247. case LLAssetType::AT_OBJECT:
  248. {
  249. if (isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item->getLinkedUUID()))
  250. return TRUE;
  251. break;
  252. }
  253. case LLAssetType::AT_BODYPART:
  254. case LLAssetType::AT_CLOTHING:
  255. if(gAgentWearables.isWearingItem(item->getLinkedUUID()))
  256. return TRUE;
  257. break;
  258. case LLAssetType::AT_GESTURE:
  259. if (LLGestureMgr::instance().isGestureActive(item->getLinkedUUID()))
  260. return TRUE;
  261. break;
  262. default:
  263. break;
  264. }
  265. return FALSE;
  266. }
  267. BOOL get_can_item_be_worn(const LLUUID& id)
  268. {
  269. const LLViewerInventoryItem* item = gInventory.getItem(id);
  270. if (!item)
  271. return FALSE;
  272. if (LLAppearanceMgr::isLinkInCOF(item->getLinkedUUID()))
  273. {
  274. // an item having links in COF (i.e. a worn item)
  275. return FALSE;
  276. }
  277. if (gInventory.isObjectDescendentOf(id, LLAppearanceMgr::instance().getCOF()))
  278. {
  279. // a non-link object in COF (should not normally happen)
  280. return FALSE;
  281. }
  282. const LLUUID trash_id = gInventory.findCategoryUUIDForType(
  283. LLFolderType::FT_TRASH);
  284. // item can't be worn if base obj in trash, see EXT-7015
  285. if (gInventory.isObjectDescendentOf(item->getLinkedUUID(),
  286. trash_id))
  287. {
  288. return false;
  289. }
  290. switch(item->getType())
  291. {
  292. case LLAssetType::AT_OBJECT:
  293. {
  294. if (isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item->getLinkedUUID()))
  295. {
  296. // Already being worn
  297. return FALSE;
  298. }
  299. else
  300. {
  301. // Not being worn yet.
  302. return TRUE;
  303. }
  304. break;
  305. }
  306. case LLAssetType::AT_BODYPART:
  307. case LLAssetType::AT_CLOTHING:
  308. if(gAgentWearables.isWearingItem(item->getLinkedUUID()))
  309. {
  310. // Already being worn
  311. return FALSE;
  312. }
  313. else
  314. {
  315. // Not being worn yet.
  316. return TRUE;
  317. }
  318. break;
  319. default:
  320. break;
  321. }
  322. return FALSE;
  323. }
  324. BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id)
  325. {
  326. if (!model)
  327. {
  328. return FALSE;
  329. }
  330. // Can't delete an item that's in the library.
  331. if (!model->isObjectDescendentOf(id, gInventory.getRootFolderID()))
  332. {
  333. return FALSE;
  334. }
  335. // Disable delete from COF folder; have users explicitly choose "detach/take off",
  336. // unless the item is not worn but in the COF (i.e. is bugged).
  337. if (LLAppearanceMgr::instance().getIsProtectedCOFItem(id))
  338. {
  339. if (get_is_item_worn(id))
  340. {
  341. return FALSE;
  342. }
  343. }
  344. const LLInventoryObject *obj = model->getItem(id);
  345. if (obj && obj->getIsLinkType())
  346. {
  347. return TRUE;
  348. }
  349. if (get_is_item_worn(id))
  350. {
  351. return FALSE;
  352. }
  353. return TRUE;
  354. }
  355. BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id)
  356. {
  357. // NOTE: This function doesn't check the folder's children.
  358. // See LLFolderBridge::isItemRemovable for a function that does
  359. // consider the children.
  360. if (!model)
  361. {
  362. return FALSE;
  363. }
  364. if (!model->isObjectDescendentOf(id, gInventory.getRootFolderID()))
  365. {
  366. return FALSE;
  367. }
  368. if (!isAgentAvatarValid()) return FALSE;
  369. const LLInventoryCategory* category = model->getCategory(id);
  370. if (!category)
  371. {
  372. return FALSE;
  373. }
  374. const LLFolderType::EType folder_type = category->getPreferredType();
  375. if (LLFolderType::lookupIsProtectedType(folder_type))
  376. {
  377. return FALSE;
  378. }
  379. // Can't delete the outfit that is currently being worn.
  380. if (folder_type == LLFolderType::FT_OUTFIT)
  381. {
  382. const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();
  383. if (base_outfit_link && (category == base_outfit_link->getLinkedCategory()))
  384. {
  385. return FALSE;
  386. }
  387. }
  388. return TRUE;
  389. }
  390. BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id)
  391. {
  392. if (!model)
  393. {
  394. return FALSE;
  395. }
  396. LLViewerInventoryCategory* cat = model->getCategory(id);
  397. if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) &&
  398. cat->getOwnerID() == gAgent.getID())
  399. {
  400. return TRUE;
  401. }
  402. return FALSE;
  403. }
  404. void show_task_item_profile(const LLUUID& item_uuid, const LLUUID& object_id)
  405. {
  406. LLFloaterSidePanelContainer::showPanel("inventory", LLSD().with("id", item_uuid).with("object", object_id));
  407. }
  408. void show_item_profile(const LLUUID& item_uuid)
  409. {
  410. LLUUID linked_uuid = gInventory.getLinkedItemID(item_uuid);
  411. LLFloaterSidePanelContainer::showPanel("inventory", LLSD().with("id", linked_uuid));
  412. }
  413. void show_item_original(const LLUUID& item_uuid)
  414. {
  415. LLFloater* floater_inventory = LLFloaterReg::getInstance("inventory");
  416. if (!floater_inventory)
  417. {
  418. llwarns << "Could not find My Inventory floater" << llendl;
  419. return;
  420. }
  421. //sidetray inventory panel
  422. LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
  423. bool reset_inventory_filter = !floater_inventory->isInVisibleChain();
  424. LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel();
  425. if (!active_panel)
  426. {
  427. //this may happen when there is no floatera and other panel is active in inventory tab
  428. if (sidepanel_inventory)
  429. {
  430. sidepanel_inventory->showInventoryPanel();
  431. }
  432. }
  433. active_panel = LLInventoryPanel::getActiveInventoryPanel();
  434. if (!active_panel)
  435. {
  436. return;
  437. }
  438. active_panel->setSelection(gInventory.getLinkedItemID(item_uuid), TAKE_FOCUS_NO);
  439. if(reset_inventory_filter)
  440. {
  441. //inventory floater
  442. bool floater_inventory_visible = false;
  443. LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory");
  444. for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
  445. {
  446. LLFloaterInventory* floater_inventory = dynamic_cast<LLFloaterInventory*>(*iter);
  447. if (floater_inventory)
  448. {
  449. LLPanelMainInventory* main_inventory = floater_inventory->getMainInventoryPanel();
  450. main_inventory->onFilterEdit("");
  451. if(floater_inventory->getVisible())
  452. {
  453. floater_inventory_visible = true;
  454. }
  455. }
  456. }
  457. if(sidepanel_inventory && !floater_inventory_visible)
  458. {
  459. LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel();
  460. main_inventory->onFilterEdit("");
  461. }
  462. }
  463. }
  464. void open_outbox()
  465. {
  466. LLFloaterReg::showInstance("outbox");
  467. }
  468. LLUUID create_folder_in_outbox_for_item(LLInventoryItem* item, const LLUUID& destFolderId, S32 operation_id)
  469. {
  470. llassert(item);
  471. llassert(destFolderId.notNull());
  472. LLUUID created_folder_id = gInventory.createNewCategory(destFolderId, LLFolderType::FT_NONE, item->getName());
  473. gInventory.notifyObservers();
  474. LLNotificationsUtil::add("OutboxFolderCreated");
  475. return created_folder_id;
  476. }
  477. void move_to_outbox_cb_action(const LLSD& payload)
  478. {
  479. LLViewerInventoryItem * viitem = gInventory.getItem(payload["item_id"].asUUID());
  480. LLUUID dest_folder_id = payload["dest_folder_id"].asUUID();
  481. if (viitem)
  482. {
  483. // when moving item directly into outbox create folder with that name
  484. if (dest_folder_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
  485. {
  486. S32 operation_id = payload["operation_id"].asInteger();
  487. dest_folder_id = create_folder_in_outbox_for_item(viitem, dest_folder_id, operation_id);
  488. }
  489. LLUUID parent = viitem->getParentUUID();
  490. change_item_parent(
  491. &gInventory,
  492. viitem,
  493. dest_folder_id,
  494. false);
  495. LLUUID top_level_folder = payload["top_level_folder"].asUUID();
  496. if (top_level_folder != LLUUID::null)
  497. {
  498. LLViewerInventoryCategory* category;
  499. while (parent.notNull())
  500. {
  501. LLInventoryModel::cat_array_t* cat_array;
  502. LLInventoryModel::item_array_t* item_array;
  503. gInventory.getDirectDescendentsOf(parent,cat_array,item_array);
  504. LLUUID next_parent;
  505. category = gInventory.getCategory(parent);
  506. if (!category) break;
  507. next_parent = category->getParentUUID();
  508. if (cat_array->empty() && item_array->empty())
  509. {
  510. remove_category(&gInventory, parent);
  511. }
  512. if (parent == top_level_folder)
  513. {
  514. break;
  515. }
  516. parent = next_parent;
  517. }
  518. }
  519. open_outbox();
  520. }
  521. }
  522. void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id)
  523. {
  524. // Collapse links directly to items/folders
  525. LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
  526. LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory();
  527. if (linked_category != NULL)
  528. {
  529. copy_folder_to_outbox(linked_category, dest_folder, top_level_folder, operation_id);
  530. }
  531. else
  532. {
  533. LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
  534. if (linked_item != NULL)
  535. {
  536. inv_item = (LLInventoryItem *) linked_item;
  537. }
  538. // Check for copy permissions
  539. if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
  540. {
  541. // when moving item directly into outbox create folder with that name
  542. if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
  543. {
  544. dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, operation_id);
  545. }
  546. copy_inventory_item(gAgent.getID(),
  547. inv_item->getPermissions().getOwner(),
  548. inv_item->getUUID(),
  549. dest_folder,
  550. inv_item->getName(),
  551. LLPointer<LLInventoryCallback>(NULL));
  552. open_outbox();
  553. }
  554. else
  555. {
  556. LLSD payload;
  557. payload["item_id"] = inv_item->getUUID();
  558. payload["dest_folder_id"] = dest_folder;
  559. payload["top_level_folder"] = top_level_folder;
  560. payload["operation_id"] = operation_id;
  561. LLMarketplaceInventoryNotifications::addNoCopyNotification(payload, move_to_outbox_cb_action);
  562. }
  563. }
  564. }
  565. void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id)
  566. {
  567. // when moving item directly into outbox create folder with that name
  568. if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
  569. {
  570. dest_folder = create_folder_in_outbox_for_item(inv_item, dest_folder, operation_id);
  571. }
  572. LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
  573. change_item_parent(&gInventory,
  574. viewer_inv_item,
  575. dest_folder,
  576. false);
  577. }
  578. void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id)
  579. {
  580. LLUUID new_folder_id = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_cat->getName());
  581. gInventory.notifyObservers();
  582. LLInventoryModel::cat_array_t* cat_array;
  583. LLInventoryModel::item_array_t* item_array;
  584. gInventory.getDirectDescendentsOf(inv_cat->getUUID(),cat_array,item_array);
  585. // copy the vector because otherwise the iterator won't be happy if we delete from it
  586. LLInventoryModel::item_array_t item_array_copy = *item_array;
  587. for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
  588. {
  589. LLInventoryItem* item = *iter;
  590. copy_item_to_outbox(item, new_folder_id, top_level_folder, operation_id);
  591. }
  592. LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
  593. for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
  594. {
  595. LLViewerInventoryCategory* category = *iter;
  596. copy_folder_to_outbox(category, new_folder_id, top_level_folder, operation_id);
  597. }
  598. open_outbox();
  599. }
  600. ///----------------------------------------------------------------------------
  601. /// LLInventoryCollectFunctor implementations
  602. ///----------------------------------------------------------------------------
  603. // static
  604. bool LLInventoryCollectFunctor::itemTransferCommonlyAllowed(const LLInventoryItem* item)
  605. {
  606. if (!item)
  607. return false;
  608. switch(item->getType())
  609. {
  610. case LLAssetType::AT_OBJECT:
  611. case LLAssetType::AT_BODYPART:
  612. case LLAssetType::AT_CLOTHING:
  613. if (!get_is_item_worn(item->getUUID()))
  614. return true;
  615. break;
  616. default:
  617. return true;
  618. break;
  619. }
  620. return false;
  621. }
  622. bool LLIsType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
  623. {
  624. if(mType == LLAssetType::AT_CATEGORY)
  625. {
  626. if(cat) return TRUE;
  627. }
  628. if(item)
  629. {
  630. if(item->getType() == mType) return TRUE;
  631. }
  632. return FALSE;
  633. }
  634. bool LLIsNotType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
  635. {
  636. if(mType == LLAssetType::AT_CATEGORY)
  637. {
  638. if(cat) return FALSE;
  639. }
  640. if(item)
  641. {
  642. if(item->getType() == mType) return FALSE;
  643. else return TRUE;
  644. }
  645. return TRUE;
  646. }
  647. bool LLIsOfAssetType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
  648. {
  649. if(mType == LLAssetType::AT_CATEGORY)
  650. {
  651. if(cat) return TRUE;
  652. }
  653. if(item)
  654. {
  655. if(item->getActualType() == mType) return TRUE;
  656. }
  657. return FALSE;
  658. }
  659. bool LLIsTypeWithPermissions::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
  660. {
  661. if(mType == LLAssetType::AT_CATEGORY)
  662. {
  663. if(cat)
  664. {
  665. return TRUE;
  666. }
  667. }
  668. if(item)
  669. {
  670. if(item->getType() == mType)
  671. {
  672. LLPermissions perm = item->getPermissions();
  673. if ((perm.getMaskBase() & mPerm) == mPerm)
  674. {
  675. return TRUE;
  676. }
  677. }
  678. }
  679. return FALSE;
  680. }
  681. bool LLBuddyCollector::operator()(LLInventoryCategory* cat,
  682. LLInventoryItem* item)
  683. {
  684. if(item)
  685. {
  686. if((LLAssetType::AT_CALLINGCARD == item->getType())
  687. && (!item->getCreatorUUID().isNull())
  688. && (item->getCreatorUUID() != gAgent.getID()))
  689. {
  690. return true;
  691. }
  692. }
  693. return false;
  694. }
  695. bool LLUniqueBuddyCollector::operator()(LLInventoryCategory* cat,
  696. LLInventoryItem* item)
  697. {
  698. if(item)
  699. {
  700. if((LLAssetType::AT_CALLINGCARD == item->getType())
  701. && (item->getCreatorUUID().notNull())
  702. && (item->getCreatorUUID() != gAgent.getID()))
  703. {
  704. mSeen.insert(item->getCreatorUUID());
  705. return true;
  706. }
  707. }
  708. return false;
  709. }
  710. bool LLParticularBuddyCollector::operator()(LLInventoryCategory* cat,
  711. LLInventoryItem* item)
  712. {
  713. if(item)
  714. {
  715. if((LLAssetType::AT_CALLINGCARD == item->getType())
  716. && (item->getCreatorUUID() == mBuddyID))
  717. {
  718. return TRUE;
  719. }
  720. }
  721. return FALSE;
  722. }
  723. bool LLNameCategoryCollector::operator()(
  724. LLInventoryCategory* cat, LLInventoryItem* item)
  725. {
  726. if(cat)
  727. {
  728. if (!LLStringUtil::compareInsensitive(mName, cat->getName()))
  729. {
  730. return true;
  731. }
  732. }
  733. return false;
  734. }
  735. bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat,
  736. LLInventoryItem* item)
  737. {
  738. // Valid COF items are:
  739. // - links to wearables (body parts or clothing)
  740. // - links to attachments
  741. // - links to gestures
  742. // - links to ensemble folders
  743. LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem();
  744. if (linked_item)
  745. {
  746. LLAssetType::EType type = linked_item->getType();
  747. return (type == LLAssetType::AT_CLOTHING ||
  748. type == LLAssetType::AT_BODYPART ||
  749. type == LLAssetType::AT_GESTURE ||
  750. type == LLAssetType::AT_OBJECT);
  751. }
  752. else
  753. {
  754. LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory();
  755. // BAP remove AT_NONE support after ensembles are fully working?
  756. return (linked_category &&
  757. ((linked_category->getPreferredType() == LLFolderType::FT_NONE) ||
  758. (LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType()))));
  759. }
  760. }
  761. bool LLFindWearables::operator()(LLInventoryCategory* cat,
  762. LLInventoryItem* item)
  763. {
  764. if(item)
  765. {
  766. if((item->getType() == LLAssetType::AT_CLOTHING)
  767. || (item->getType() == LLAssetType::AT_BODYPART))
  768. {
  769. return TRUE;
  770. }
  771. }
  772. return FALSE;
  773. }
  774. LLFindWearablesEx::LLFindWearablesEx(bool is_worn, bool include_body_parts)
  775. : mIsWorn(is_worn)
  776. , mIncludeBodyParts(include_body_parts)
  777. {}
  778. bool LLFindWearablesEx::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
  779. {
  780. LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
  781. if (!vitem) return false;
  782. // Skip non-wearables.
  783. if (!vitem->isWearableType() && vitem->getType() != LLAssetType::AT_OBJECT)
  784. {
  785. return false;
  786. }
  787. // Skip body parts if requested.
  788. if (!mIncludeBodyParts && vitem->getType() == LLAssetType::AT_BODYPART)
  789. {
  790. return false;
  791. }
  792. // Skip broken links.
  793. if (vitem->getIsBrokenLink())
  794. {
  795. return false;
  796. }
  797. return (bool) get_is_item_worn(item->getUUID()) == mIsWorn;
  798. }
  799. bool LLFindWearablesOfType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
  800. {
  801. if (!item) return false;
  802. if (item->getType() != LLAssetType::AT_CLOTHING &&
  803. item->getType() != LLAssetType::AT_BODYPART)
  804. {
  805. return false;
  806. }
  807. LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
  808. if (!vitem || vitem->getWearableType() != mWearableType) return false;
  809. return true;
  810. }
  811. void LLFindWearablesOfType::setType(LLWearableType::EType type)
  812. {
  813. mWearableType = type;
  814. }
  815. bool LLFindNonRemovableObjects::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
  816. {
  817. if (item)
  818. {
  819. return !get_is_item_removable(&gInventory, item->getUUID());
  820. }
  821. if (cat)
  822. {
  823. return !get_is_category_removable(&gInventory, cat->getUUID());
  824. }
  825. llwarns << "Not a category and not an item?" << llendl;
  826. return false;
  827. }
  828. ///----------------------------------------------------------------------------
  829. /// LLAssetIDMatches
  830. ///----------------------------------------------------------------------------
  831. bool LLAssetIDMatches::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
  832. {
  833. return (item && item->getAssetUUID() == mAssetID);
  834. }
  835. ///----------------------------------------------------------------------------
  836. /// LLLinkedItemIDMatches
  837. ///----------------------------------------------------------------------------
  838. bool LLLinkedItemIDMatches::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
  839. {
  840. return (item &&
  841. (item->getIsLinkType()) &&
  842. (item->getLinkedUUID() == mBaseItemID)); // A linked item's assetID will be the compared-to item's itemID.
  843. }
  844. void LLSaveFolderState::setApply(BOOL apply)
  845. {
  846. mApply = apply;
  847. // before generating new list of open folders, clear the old one
  848. if(!apply)
  849. {
  850. clearOpenFolders();
  851. }
  852. }
  853. void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)
  854. {
  855. LLMemType mt(LLMemType::MTYPE_INVENTORY_DO_FOLDER);
  856. if(mApply)
  857. {
  858. // we're applying the open state
  859. LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
  860. if(!bridge) return;
  861. LLUUID id(bridge->getUUID());
  862. if(mOpenFolders.find(id) != mOpenFolders.end())
  863. {
  864. folder->setOpen(TRUE);
  865. }
  866. else
  867. {
  868. // keep selected filter in its current state, this is less jarring to user
  869. if (!folder->isSelected())
  870. {
  871. folder->setOpen(FALSE);
  872. }
  873. }
  874. }
  875. else
  876. {
  877. // we're recording state at this point
  878. if(folder->isOpen())
  879. {
  880. LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
  881. if(!bridge) return;
  882. mOpenFolders.insert(bridge->getUUID());
  883. }
  884. }
  885. }
  886. void LLOpenFilteredFolders::doItem(LLFolderViewItem *item)
  887. {
  888. if (item->getFiltered())
  889. {
  890. item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
  891. }
  892. }
  893. void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder)
  894. {
  895. if (folder->getFiltered() && folder->getParentFolder())
  896. {
  897. folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
  898. }
  899. // if this folder didn't pass the filter, and none of its descendants did
  900. else if (!folder->getFiltered() && !folder->hasFilteredDescendants())
  901. {
  902. folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO);
  903. }
  904. }
  905. void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item)
  906. {
  907. if (item->getFiltered() && !mItemSelected)
  908. {
  909. item->getRoot()->setSelection(item, FALSE, FALSE);
  910. if (item->getParentFolder())
  911. {
  912. item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
  913. }
  914. item->getRoot()->scrollToShowSelection();
  915. mItemSelected = TRUE;
  916. }
  917. }
  918. void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder)
  919. {
  920. if (folder->getFiltered() && !mItemSelected)
  921. {
  922. folder->getRoot()->setSelection(folder, FALSE, FALSE);
  923. if (folder->getParentFolder())
  924. {
  925. folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
  926. }
  927. folder->getRoot()->scrollToShowSelection();
  928. mItemSelected = TRUE;
  929. }
  930. }
  931. void LLOpenFoldersWithSelection::doItem(LLFolderViewItem *item)
  932. {
  933. if (item->getParentFolder() && item->isSelected())
  934. {
  935. item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
  936. }
  937. }
  938. void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder)
  939. {
  940. if (folder->getParentFolder() && folder->isSelected())
  941. {
  942. folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
  943. }
  944. }