llinventorypanel.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:28k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /* 
  2.  * @file llinventorypanel.cpp
  3.  * @brief Implementation of the inventory panel and associated stuff.
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, 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 "llinventorypanel.h"
  34. #include <utility> // for std::pair<>
  35. #include "llagent.h"
  36. #include "llagentwearables.h"
  37. #include "llappearancemgr.h"
  38. #include "llfloaterinventory.h"
  39. #include "llfloaterreg.h"
  40. #include "llimfloater.h"
  41. #include "llimview.h"
  42. #include "llinventorybridge.h"
  43. #include "llsidepanelinventory.h"
  44. #include "llsidetray.h"
  45. #include "llscrollcontainer.h"
  46. #include "llviewerfoldertype.h"
  47. #include "llvoavatarself.h"
  48. static LLDefaultChildRegistry::Register<LLInventoryPanel> r("inventory_panel");
  49. const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder");
  50. const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder");
  51. const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string("");
  52. static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER;
  53. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  54. // Class LLInventoryPanelObserver
  55. //
  56. // Bridge to support knowing when the inventory has changed.
  57. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  58. class LLInventoryPanelObserver : public LLInventoryObserver
  59. {
  60. public:
  61. LLInventoryPanelObserver(LLInventoryPanel* ip) : mIP(ip) {}
  62. virtual ~LLInventoryPanelObserver() {}
  63. virtual void changed(U32 mask) 
  64. {
  65. mIP->modelChanged(mask);
  66. }
  67. protected:
  68. LLInventoryPanel* mIP;
  69. };
  70. LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
  71. LLPanel(p),
  72. mInventoryObserver(NULL),
  73. mFolders(NULL),
  74. mScroller(NULL),
  75. mSortOrderSetting(p.sort_order_setting),
  76. mInventory(p.inventory),
  77. mAllowMultiSelect(p.allow_multi_select),
  78. mViewsInitialized(false),
  79. mStartFolderString(p.start_folder),
  80. mBuildDefaultHierarchy(true),
  81. mInvFVBridgeBuilder(NULL)
  82. {
  83. mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER;
  84. // contex menu callbacks
  85. mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2));
  86. mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));
  87. mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND));
  88. mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLInventoryPanel::doCreate, this, _2));
  89. mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&LLInventoryPanel::attachObject, this, _2));
  90. mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this));
  91. if (mStartFolderString != "")
  92. {
  93. mBuildDefaultHierarchy = false;
  94. }
  95. }
  96. BOOL LLInventoryPanel::postBuild()
  97. {
  98. LLMemType mt(LLMemType::MTYPE_INVENTORY_POST_BUILD);
  99. mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves
  100. // Create root folder
  101. {
  102. LLRect folder_rect(0,
  103.    0,
  104.    getRect().getWidth(),
  105.    0);
  106. LLFolderView::Params p;
  107. p.name = getName();
  108. p.rect = folder_rect;
  109. p.parent_panel = this;
  110. p.tool_tip = p.name;
  111. mFolders = LLUICtrlFactory::create<LLFolderView>(p);
  112. mFolders->setAllowMultiSelect(mAllowMultiSelect);
  113. }
  114. mCommitCallbackRegistrar.popScope();
  115. mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar);
  116. // Scroller
  117. {
  118. LLRect scroller_view_rect = getRect();
  119. scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
  120. LLScrollContainer::Params p;
  121. p.name("Inventory Scroller");
  122. p.rect(scroller_view_rect);
  123. p.follows.flags(FOLLOWS_ALL);
  124. p.reserve_scroll_corner(true);
  125. p.tab_stop(true);
  126. mScroller = LLUICtrlFactory::create<LLScrollContainer>(p);
  127. addChild(mScroller);
  128. mScroller->addChild(mFolders);
  129. mFolders->setScrollContainer(mScroller);
  130. mFolders->addChild(mFolders->mStatusTextBox);
  131. }
  132. // Set up the callbacks from the inventory we're viewing, and then build everything.
  133. mInventoryObserver = new LLInventoryPanelObserver(this);
  134. mInventory->addObserver(mInventoryObserver);
  135. // Build view of inventory if we need default full hierarchy and inventory ready,
  136. // otherwise wait for idle callback.
  137. if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mViewsInitialized)
  138. {
  139. initializeViews();
  140. }
  141. gIdleCallbacks.addFunction(onIdle, (void*)this);
  142. if (mSortOrderSetting != INHERIT_SORT_ORDER)
  143. {
  144. setSortOrder(gSavedSettings.getU32(mSortOrderSetting));
  145. }
  146. else
  147. {
  148. setSortOrder(gSavedSettings.getU32(DEFAULT_SORT_ORDER));
  149. }
  150. mFolders->setSortOrder(getFilter()->getSortOrder());
  151. return TRUE;
  152. }
  153. LLInventoryPanel::~LLInventoryPanel()
  154. {
  155. if (mFolders)
  156. {
  157. U32 sort_order = mFolders->getSortOrder();
  158. if (mSortOrderSetting != INHERIT_SORT_ORDER)
  159. {
  160. gSavedSettings.setU32(mSortOrderSetting, sort_order);
  161. }
  162. }
  163. // LLView destructor will take care of the sub-views.
  164. mInventory->removeObserver(mInventoryObserver);
  165. delete mInventoryObserver;
  166. mScroller = NULL;
  167. }
  168. void LLInventoryPanel::draw()
  169. {
  170. // Select the desired item (in case it wasn't loaded when the selection was requested)
  171. mFolders->updateSelection();
  172. LLPanel::draw();
  173. }
  174. LLInventoryFilter* LLInventoryPanel::getFilter()
  175. {
  176. if (mFolders) 
  177. {
  178. return mFolders->getFilter();
  179. }
  180. return NULL;
  181. }
  182. void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type)
  183. {
  184. if (filter_type == LLInventoryFilter::FILTERTYPE_OBJECT)
  185. getFilter()->setFilterObjectTypes(types);
  186. if (filter_type == LLInventoryFilter::FILTERTYPE_CATEGORY)
  187. getFilter()->setFilterCategoryTypes(types);
  188. }
  189. void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask)
  190. {
  191. getFilter()->setFilterPermissions(filter_perm_mask);
  192. }
  193. void LLInventoryPanel::setFilterSubString(const std::string& string)
  194. {
  195. getFilter()->setFilterSubString(string);
  196. }
  197. void LLInventoryPanel::setSortOrder(U32 order)
  198. {
  199. getFilter()->setSortOrder(order);
  200. if (getFilter()->isModified())
  201. {
  202. mFolders->setSortOrder(order);
  203. // try to keep selection onscreen, even if it wasn't to start with
  204. mFolders->scrollToShowSelection();
  205. }
  206. }
  207. void LLInventoryPanel::setSinceLogoff(BOOL sl)
  208. {
  209. getFilter()->setDateRangeLastLogoff(sl);
  210. }
  211. void LLInventoryPanel::setHoursAgo(U32 hours)
  212. {
  213. getFilter()->setHoursAgo(hours);
  214. }
  215. void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show)
  216. {
  217. getFilter()->setShowFolderState(show);
  218. }
  219. LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()
  220. {
  221. return getFilter()->getShowFolderState();
  222. }
  223. void LLInventoryPanel::modelChanged(U32 mask)
  224. {
  225. static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh");
  226. LLFastTimer t2(FTM_REFRESH);
  227. bool handled = false;
  228. if (!mViewsInitialized) return;
  229. const LLInventoryModel* model = getModel();
  230. if (!model) return;
  231. const LLInventoryModel::changed_items_t& changed_items = model->getChangedIDs();
  232. if (changed_items.empty()) return;
  233. for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin();
  234.  items_iter != changed_items.end();
  235.  ++items_iter)
  236. {
  237. const LLUUID& item_id = (*items_iter);
  238. const LLInventoryObject* model_item = model->getObject(item_id);
  239. LLFolderViewItem* view_item = mFolders->getItemByID(item_id);
  240. LLFolderViewFolder* view_folder = mFolders->getFolderByID(item_id);
  241. //////////////////////////////
  242. // LABEL Operation
  243. // Empty out the display name for relabel.
  244. if (mask & LLInventoryObserver::LABEL)
  245. {
  246. handled = true;
  247. if (view_item)
  248. {
  249. // Request refresh on this item (also flags for filtering)
  250. LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getListener();
  251. if(bridge)
  252. { // Clear the display name first, so it gets properly re-built during refresh()
  253. bridge->clearDisplayName();
  254. view_item->refresh();
  255. // Set the new tooltip with the new display name.
  256. view_item->setToolTip(bridge->getDisplayName());
  257. }
  258. }
  259. }
  260. //////////////////////////////
  261. // REBUILD Operation
  262. // Destroy and regenerate the UI.
  263. if (mask & LLInventoryObserver::REBUILD)
  264. {
  265. handled = true;
  266. if (model_item && view_item)
  267. {
  268. view_item->destroyView();
  269. }
  270. buildNewViews(item_id);
  271. }
  272. //////////////////////////////
  273. // INTERNAL Operation
  274. // This could be anything.  For now, just refresh the item.
  275. if (mask & LLInventoryObserver::INTERNAL)
  276. {
  277. if (view_item)
  278. {
  279. view_item->refresh();
  280. }
  281. }
  282. //////////////////////////////
  283. // SORT Operation
  284. // Sort the folder.
  285. if (mask & LLInventoryObserver::SORT)
  286. {
  287. if (view_folder)
  288. {
  289. view_folder->requestSort();
  290. }
  291. }
  292. // We don't typically care which of these masks the item is actually flagged with, since the masks
  293. // may not be accurate (e.g. in the main inventory panel, I move an item from My Inventory into
  294. // Landmarks; this is a STRUCTURE change for that panel but is an ADD change for the Landmarks
  295. // panel).  What's relevant is that the item and UI are probably out of sync and thus need to be
  296. // resynchronized.
  297. if (mask & (LLInventoryObserver::STRUCTURE |
  298. LLInventoryObserver::ADD |
  299. LLInventoryObserver::REMOVE))
  300. {
  301. handled = true;
  302. //////////////////////////////
  303. // ADD Operation
  304. // Item exists in memory but a UI element hasn't been created for it.
  305. if (model_item && !view_item)
  306. {
  307. // Add the UI element for this item.
  308. buildNewViews(item_id);
  309. // Select any newly created object that has the auto rename at top of folder root set.
  310. if(mFolders->getRoot()->needsAutoRename())
  311. {
  312. setSelection(item_id, FALSE);
  313. }
  314. }
  315. //////////////////////////////
  316. // STRUCTURE Operation
  317. // This item already exists in both memory and UI.  It was probably reparented.
  318. if (model_item && view_item)
  319. {
  320. // Don't process the item if it's hanging from the root, since its
  321. // model_item's parent will be NULL.
  322. if (view_item->getRoot() != view_item->getParent())
  323. {
  324. LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID());
  325. // Item has been moved.
  326. if (view_item->getParentFolder() != new_parent)
  327. {
  328. if (new_parent != NULL)
  329. {
  330. // Item is to be moved and we found its new parent in the panel's directory, so move the item's UI.
  331. view_item->getParentFolder()->extractItem(view_item);
  332. view_item->addToFolder(new_parent, mFolders);
  333. }
  334. else 
  335. {
  336. // Item is to be moved outside the panel's directory (e.g. moved to trash for a panel that 
  337. // doesn't include trash).  Just remove the item's UI.
  338. view_item->destroyView();
  339. }
  340. }
  341. }
  342. }
  343. //////////////////////////////
  344. // REMOVE Operation
  345. // This item has been removed from memory, but its associated UI element still exists.
  346. if (!model_item && view_item)
  347. {
  348. // Remove the item's UI.
  349. view_item->destroyView();
  350. }
  351. }
  352. }
  353. }
  354. // static
  355. void LLInventoryPanel::onIdle(void *userdata)
  356. {
  357. if (!gInventory.isInventoryUsable())
  358. return;
  359. LLInventoryPanel *self = (LLInventoryPanel*)userdata;
  360. // Inventory just initialized, do complete build
  361. if (!self->mViewsInitialized)
  362. {
  363. self->initializeViews();
  364. }
  365. if (self->mViewsInitialized)
  366. {
  367. gIdleCallbacks.deleteFunction(onIdle, (void*)self);
  368. }
  369. }
  370. void LLInventoryPanel::initializeViews()
  371. {
  372. if (!gInventory.isInventoryUsable()) return;
  373. // Determine the root folder in case specified, and
  374. // build the views starting with that folder.
  375. const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
  376. if ("LIBRARY" == mStartFolderString)
  377. {
  378. mStartFolderID = gInventory.getLibraryRootFolderID();
  379. }
  380. else
  381. {
  382. mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
  383. }
  384. rebuildViewsFor(mStartFolderID);
  385. mViewsInitialized = true;
  386. openStartFolderOrMyInventory();
  387. // Special case for new user login
  388. if (gAgent.isFirstLogin())
  389. {
  390. // Auto open the user's library
  391. LLFolderViewFolder* lib_folder = mFolders->getFolderByID(gInventory.getLibraryRootFolderID());
  392. if (lib_folder)
  393. {
  394. lib_folder->setOpen(TRUE);
  395. }
  396. // Auto close the user's my inventory folder
  397. LLFolderViewFolder* my_inv_folder = mFolders->getFolderByID(gInventory.getRootFolderID());
  398. if (my_inv_folder)
  399. {
  400. my_inv_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN);
  401. }
  402. }
  403. }
  404. void LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
  405. {
  406. // Destroy the old view for this ID so we can rebuild it.
  407. LLFolderViewItem* old_view = mFolders->getItemByID(id);
  408. if (old_view && id.notNull())
  409. {
  410. old_view->destroyView();
  411. }
  412. buildNewViews(id);
  413. }
  414. void LLInventoryPanel::buildNewViews(const LLUUID& id)
  415. {
  416. LLMemType mt(LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS);
  417. LLFolderViewItem* itemp = NULL;
  418. LLInventoryObject* objectp = gInventory.getObject(id);
  419. if (objectp)
  420. {
  421. const LLUUID &parent_id = objectp->getParentUUID();
  422. LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)mFolders->getItemByID(parent_id);
  423. if (id == mStartFolderID)
  424. {
  425. parent_folder = mFolders;
  426. }
  427. else if ((mStartFolderID != LLUUID::null) && (!gInventory.isObjectDescendentOf(id, mStartFolderID)))
  428. {
  429. // This item exists outside the inventory's hierarchy, so don't add it.
  430. return;
  431. }
  432. if (objectp->getType() <= LLAssetType::AT_NONE ||
  433. objectp->getType() >= LLAssetType::AT_COUNT)
  434. {
  435. llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : "
  436. << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() 
  437. << llendl;
  438. return;
  439. }
  440. if ((objectp->getType() == LLAssetType::AT_CATEGORY) &&
  441. (objectp->getActualType() != LLAssetType::AT_LINK_FOLDER))
  442. {
  443. LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(),
  444. objectp->getType(),
  445. LLInventoryType::IT_CATEGORY,
  446. this,
  447. objectp->getUUID());
  448. if (new_listener)
  449. {
  450. LLFolderViewFolder::Params params;
  451. params.name = new_listener->getDisplayName();
  452. params.icon = new_listener->getIcon();
  453. params.icon_open = new_listener->getOpenIcon();
  454. params.root = mFolders;
  455. params.listener = new_listener;
  456. params.tool_tip = params.name;
  457. LLFolderViewFolder* folderp = LLUICtrlFactory::create<LLFolderViewFolder>(params);
  458. folderp->setItemSortOrder(mFolders->getSortOrder());
  459. itemp = folderp;
  460. // Hide the root folder, so we can show the contents of a folder flat
  461. // but still have the parent folder present for listener-related operations.
  462. if (id == mStartFolderID)
  463. {
  464. folderp->setHidden(TRUE);
  465. }
  466. const LLViewerInventoryCategory *cat = dynamic_cast<LLViewerInventoryCategory *>(objectp);
  467. if (cat && getIsHiddenFolderType(cat->getPreferredType()))
  468. {
  469. folderp->setHidden(TRUE);
  470. }
  471. }
  472. }
  473. else 
  474. {
  475. // Build new view for item.
  476. LLInventoryItem* item = (LLInventoryItem*)objectp;
  477. LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(),
  478. item->getActualType(),
  479. item->getInventoryType(),
  480. this,
  481. item->getUUID(),
  482. item->getFlags());
  483. if (new_listener)
  484. {
  485. LLFolderViewItem::Params params;
  486. params.name = new_listener->getDisplayName();
  487. params.icon = new_listener->getIcon();
  488. params.icon_open = new_listener->getOpenIcon();
  489. params.creation_date = new_listener->getCreationDate();
  490. params.root = mFolders;
  491. params.listener = new_listener;
  492. params.rect = LLRect (0, 0, 0, 0);
  493. params.tool_tip = params.name;
  494. itemp = LLUICtrlFactory::create<LLFolderViewItem> (params);
  495. }
  496. }
  497. if (itemp)
  498. {
  499. itemp->addToFolder(parent_folder, mFolders);
  500. // Don't add children of hidden folders unless this is the panel's root folder.
  501. if (itemp->getHidden() && (id != mStartFolderID))
  502. {
  503. return;
  504. }
  505. }
  506. }
  507. // If this is a folder, add the children of the folder and recursively add any 
  508. // child folders.
  509. if ((id == mStartFolderID) ||
  510. (objectp && objectp->getType() == LLAssetType::AT_CATEGORY))
  511. {
  512. LLViewerInventoryCategory::cat_array_t* categories;
  513. LLViewerInventoryItem::item_array_t* items;
  514. mInventory->lockDirectDescendentArrays(id, categories, items);
  515. if(categories)
  516. {
  517. for (LLViewerInventoryCategory::cat_array_t::const_iterator cat_iter = categories->begin();
  518.  cat_iter != categories->end();
  519.  ++cat_iter)
  520. {
  521. const LLViewerInventoryCategory* cat = (*cat_iter);
  522. buildNewViews(cat->getUUID());
  523. }
  524. }
  525. if(items)
  526. {
  527. for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items->begin();
  528.  item_iter != items->end();
  529.  ++item_iter)
  530. {
  531. const LLViewerInventoryItem* item = (*item_iter);
  532. buildNewViews(item->getUUID());
  533. }
  534. }
  535. mInventory->unlockDirectDescendentArrays(id);
  536. }
  537. }
  538. // bit of a hack to make sure the inventory is open.
  539. void LLInventoryPanel::openStartFolderOrMyInventory()
  540. {
  541. if (mStartFolderString != "")
  542. {
  543. mFolders->openFolder(mStartFolderString);
  544. }
  545. else
  546. {
  547. // Find My Inventory folder and open it up by name
  548. for (LLView *child = mFolders->getFirstChild(); child; child = mFolders->findNextSibling(child))
  549. {
  550. LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child);
  551. if (fchild && fchild->getListener() &&
  552. (fchild->getListener()->getUUID() == gInventory.getRootFolderID()))
  553. {
  554. const std::string& child_name = child->getName();
  555. mFolders->openFolder(child_name);
  556. break;
  557. }
  558. }
  559. }
  560. }
  561. void LLInventoryPanel::openSelected()
  562. {
  563. LLFolderViewItem* folder_item = mFolders->getCurSelectedItem();
  564. if(!folder_item) return;
  565. LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener();
  566. if(!bridge) return;
  567. bridge->openItem();
  568. }
  569. BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask)
  570. {
  571. BOOL handled = LLView::handleHover(x, y, mask);
  572. if(handled)
  573. {
  574. ECursorType cursor = getWindow()->getCursor();
  575. if (LLInventoryModel::backgroundFetchActive() && cursor == UI_CURSOR_ARROW)
  576. {
  577. // replace arrow cursor with arrow and hourglass cursor
  578. getWindow()->setCursor(UI_CURSOR_WORKING);
  579. }
  580. }
  581. else
  582. {
  583. getWindow()->setCursor(UI_CURSOR_ARROW);
  584. }
  585. return TRUE;
  586. }
  587. BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
  588.    EDragAndDropType cargo_type,
  589.    void* cargo_data,
  590.    EAcceptance* accept,
  591.    std::string& tooltip_msg)
  592. {
  593. BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
  594. // If folder view is empty the (x, y) point won't be in its rect
  595. // so the handler must be called explicitly.
  596. if (!mFolders->hasVisibleChildren())
  597. {
  598. handled = mFolders->handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
  599. }
  600. if (handled)
  601. {
  602. mFolders->setDragAndDropThisFrame();
  603. }
  604. return handled;
  605. }
  606. void LLInventoryPanel::onFocusLost()
  607. {
  608. // inventory no longer handles cut/copy/paste/delete
  609. if (LLEditMenuHandler::gEditMenuHandler == mFolders)
  610. {
  611. LLEditMenuHandler::gEditMenuHandler = NULL;
  612. }
  613. LLPanel::onFocusLost();
  614. }
  615. void LLInventoryPanel::onFocusReceived()
  616. {
  617. // inventory now handles cut/copy/paste/delete
  618. LLEditMenuHandler::gEditMenuHandler = mFolders;
  619. LLPanel::onFocusReceived();
  620. }
  621. void LLInventoryPanel::openAllFolders()
  622. {
  623. mFolders->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN);
  624. mFolders->arrangeAll();
  625. }
  626. void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus)
  627. {
  628. // Don't select objects in COF (e.g. to prevent refocus when items are worn).
  629. const LLInventoryObject *obj = gInventory.getObject(obj_id);
  630. if (obj && obj->getParentUUID() == LLAppearanceManager::instance().getCOF())
  631. {
  632. return;
  633. }
  634. mFolders->setSelectionByID(obj_id, take_keyboard_focus);
  635. }
  636. void LLInventoryPanel::setSelectCallback(const LLFolderView::signal_t::slot_type& cb) 
  637. if (mFolders) 
  638. {
  639. mFolders->setSelectCallback(cb);
  640. }
  641. }
  642. void LLInventoryPanel::clearSelection()
  643. {
  644. mFolders->clearSelection();
  645. }
  646. void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action)
  647. {
  648. LLFolderView* fv = getRootFolder();
  649. if (fv->needsAutoRename()) // auto-selecting a new user-created asset and preparing to rename
  650. {
  651. fv->setNeedsAutoRename(FALSE);
  652. if (items.size()) // new asset is visible and selected
  653. {
  654. fv->startRenamingSelectedItem();
  655. }
  656. }
  657. // Seraph - Put determineFolderType in here for ensemble typing?
  658. }
  659. void LLInventoryPanel::doToSelected(const LLSD& userdata)
  660. {
  661. mFolders->doToSelected(&gInventory, userdata);
  662. }
  663. void LLInventoryPanel::doCreate(const LLSD& userdata)
  664. {
  665. menu_create_inventory_item(mFolders, LLFolderBridge::sSelf, userdata);
  666. }
  667. bool LLInventoryPanel::beginIMSession()
  668. {
  669. std::set<LLUUID> selected_items;
  670. mFolders->getSelectionList(selected_items);
  671. std::string name;
  672. static int session_num = 1;
  673. LLDynamicArray<LLUUID> members;
  674. EInstantMessage type = IM_SESSION_CONFERENCE_START;
  675. std::set<LLUUID>::const_iterator iter;
  676. for (iter = selected_items.begin(); iter != selected_items.end(); iter++)
  677. {
  678. LLUUID item = *iter;
  679. LLFolderViewItem* folder_item = mFolders->getItemByID(item);
  680. if(folder_item) 
  681. {
  682. LLFolderViewEventListener* fve_listener = folder_item->getListener();
  683. if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY))
  684. {
  685. LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener();
  686. if(!bridge) return true;
  687. LLViewerInventoryCategory* cat = bridge->getCategory();
  688. if(!cat) return true;
  689. name = cat->getName();
  690. LLUniqueBuddyCollector is_buddy;
  691. LLInventoryModel::cat_array_t cat_array;
  692. LLInventoryModel::item_array_t item_array;
  693. gInventory.collectDescendentsIf(bridge->getUUID(),
  694. cat_array,
  695. item_array,
  696. LLInventoryModel::EXCLUDE_TRASH,
  697. is_buddy);
  698. S32 count = item_array.count();
  699. if(count > 0)
  700. {
  701. //*TODO by what to replace that?
  702. //LLFloaterReg::showInstance("communicate");
  703. // create the session
  704. LLAvatarTracker& at = LLAvatarTracker::instance();
  705. LLUUID id;
  706. for(S32 i = 0; i < count; ++i)
  707. {
  708. id = item_array.get(i)->getCreatorUUID();
  709. if(at.isBuddyOnline(id))
  710. {
  711. members.put(id);
  712. }
  713. }
  714. }
  715. }
  716. else
  717. {
  718. LLFolderViewItem* folder_item = mFolders->getItemByID(item);
  719. if(!folder_item) return true;
  720. LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener();
  721. if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD)
  722. {
  723. LLInventoryItem* inv_item = gInventory.getItem(listenerp->getUUID());
  724. if (inv_item)
  725. {
  726. LLAvatarTracker& at = LLAvatarTracker::instance();
  727. LLUUID id = inv_item->getCreatorUUID();
  728. if(at.isBuddyOnline(id))
  729. {
  730. members.put(id);
  731. }
  732. }
  733. } //if IT_CALLINGCARD
  734. } //if !IT_CATEGORY
  735. }
  736. } //for selected_items
  737. // the session_id is randomly generated UUID which will be replaced later
  738. // with a server side generated number
  739. if (name.empty())
  740. {
  741. name = llformat("Session %d", session_num++);
  742. }
  743. LLUUID session_id = gIMMgr->addSession(name, type, members[0], members);
  744. if (session_id != LLUUID::null)
  745. {
  746. LLIMFloater::show(session_id);
  747. }
  748. return true;
  749. }
  750. bool LLInventoryPanel::attachObject(const LLSD& userdata)
  751. {
  752. std::set<LLUUID> selected_items;
  753. mFolders->getSelectionList(selected_items);
  754. std::string joint_name = userdata.asString();
  755. LLVOAvatar *avatarp = static_cast<LLVOAvatar*>(gAgent.getAvatarObject());
  756. LLViewerJointAttachment* attachmentp = NULL;
  757. for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); 
  758.  iter != avatarp->mAttachmentPoints.end(); )
  759. {
  760. LLVOAvatar::attachment_map_t::iterator curiter = iter++;
  761. LLViewerJointAttachment* attachment = curiter->second;
  762. if (attachment->getName() == joint_name)
  763. {
  764. attachmentp = attachment;
  765. break;
  766. }
  767. }
  768. if (attachmentp == NULL)
  769. {
  770. return true;
  771. }
  772. for (std::set<LLUUID>::const_iterator set_iter = selected_items.begin(); 
  773.  set_iter != selected_items.end(); 
  774.  ++set_iter)
  775. {
  776. const LLUUID &id = *set_iter;
  777. LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(id);
  778. if(item && gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID()))
  779. {
  780. rez_attachment(item, attachmentp);
  781. }
  782. else if(item && item->isComplete())
  783. {
  784. // must be in library. copy it to our inventory and put it on.
  785. LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(attachmentp);
  786. copy_inventory_item(gAgent.getID(),
  787. item->getPermissions().getOwner(),
  788. item->getUUID(),
  789. LLUUID::null,
  790. std::string(),
  791. cb);
  792. }
  793. }
  794. gFocusMgr.setKeyboardFocus(NULL);
  795. return true;
  796. }
  797. BOOL LLInventoryPanel::getSinceLogoff()
  798. {
  799. return getFilter()->isSinceLogoff();
  800. }
  801. // DEBUG ONLY
  802. // static 
  803. void LLInventoryPanel::dumpSelectionInformation(void* user_data)
  804. {
  805. LLInventoryPanel* iv = (LLInventoryPanel*)user_data;
  806. iv->mFolders->dumpSelectionInformation();
  807. }
  808. BOOL is_inventorysp_active()
  809. {
  810. if (!LLSideTray::getInstance()->isPanelActive("sidepanel_inventory")) return FALSE;
  811. LLSidepanelInventory *inventorySP = dynamic_cast<LLSidepanelInventory *>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
  812. if (!inventorySP) return FALSE; 
  813. return inventorySP->isMainInventoryPanelActive();
  814. }
  815. // static
  816. LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)
  817. {
  818. // A. If the inventory side panel is open, use that preferably.
  819. if (is_inventorysp_active())
  820. {
  821. LLSidepanelInventory *inventorySP = dynamic_cast<LLSidepanelInventory *>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
  822. if (inventorySP)
  823. {
  824. return inventorySP->getActivePanel();
  825. }
  826. }
  827. // B. Iterate through the inventory floaters and return whichever is on top.
  828. LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory");
  829. S32 z_min = S32_MAX;
  830. LLInventoryPanel* res = NULL;
  831. for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
  832. {
  833. LLFloaterInventory* iv = dynamic_cast<LLFloaterInventory*>(*iter);
  834. if (iv && iv->getVisible())
  835. {
  836. S32 z_order = gFloaterView->getZOrder(iv);
  837. if (z_order < z_min)
  838. {
  839. res = iv->getPanel();
  840. z_min = z_order;
  841. }
  842. }
  843. }
  844. if (res) return res;
  845. // C. If no panels are open and we don't want to force open a panel, then just abort out.
  846. if (!auto_open) return NULL;
  847. // D. Open the inventory side panel and use that.
  848.     LLSD key;
  849. LLSidepanelInventory *sidepanel_inventory =
  850. dynamic_cast<LLSidepanelInventory *>(LLSideTray::getInstance()->showPanel("sidepanel_inventory", key));
  851. if (sidepanel_inventory)
  852. {
  853. return sidepanel_inventory->getActivePanel();
  854. }
  855. return NULL;
  856. }
  857. void LLInventoryPanel::addHideFolderType(LLFolderType::EType folder_type)
  858. {
  859. if (!getIsHiddenFolderType(folder_type))
  860. {
  861. mHiddenFolderTypes.push_back(folder_type);
  862. }
  863. }
  864. BOOL LLInventoryPanel::getIsHiddenFolderType(LLFolderType::EType folder_type) const
  865. {
  866. return (std::find(mHiddenFolderTypes.begin(), mHiddenFolderTypes.end(), folder_type) != mHiddenFolderTypes.end());
  867. }