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

/indra/newview/llpanellandmarks.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1505 lines | 1116 code | 224 blank | 165 comment | 295 complexity | 85f00590ad37b0ae85b0aebe2b630c78 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llpanellandmarks.cpp
  3. * @brief Landmarks tab for Side Bar "Places" panel
  4. *
  5. * $LicenseInfo:firstyear=2009&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 "llpanellandmarks.h"
  28. #include "llbutton.h"
  29. #include "llfloaterreg.h"
  30. #include "llnotificationsutil.h"
  31. #include "llsdutil.h"
  32. #include "llsdutil_math.h"
  33. #include "llregionhandle.h"
  34. #include "llaccordionctrl.h"
  35. #include "llaccordionctrltab.h"
  36. #include "llagent.h"
  37. #include "llagentpicksinfo.h"
  38. #include "llagentui.h"
  39. #include "llcallbacklist.h"
  40. #include "lldndbutton.h"
  41. #include "llfloatersidepanelcontainer.h"
  42. #include "llfloaterworldmap.h"
  43. #include "llfolderviewitem.h"
  44. #include "llinventorymodelbackgroundfetch.h"
  45. #include "llinventorypanel.h"
  46. #include "llinventoryfunctions.h"
  47. #include "lllandmarkactions.h"
  48. #include "llmenubutton.h"
  49. #include "llplacesinventorybridge.h"
  50. #include "llplacesinventorypanel.h"
  51. #include "lltoggleablemenu.h"
  52. #include "llviewermenu.h"
  53. #include "llviewerregion.h"
  54. // Not yet implemented; need to remove buildPanel() from constructor when we switch
  55. //static LLRegisterPanelClassWrapper<LLLandmarksPanel> t_landmarks("panel_landmarks");
  56. static const std::string OPTIONS_BUTTON_NAME = "options_gear_btn";
  57. static const std::string ADD_BUTTON_NAME = "add_btn";
  58. static const std::string ADD_FOLDER_BUTTON_NAME = "add_folder_btn";
  59. static const std::string TRASH_BUTTON_NAME = "trash_btn";
  60. // helper functions
  61. static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string);
  62. static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list);
  63. static void collapse_all_folders(LLFolderView* root_folder);
  64. static void expand_all_folders(LLFolderView* root_folder);
  65. static bool has_expanded_folders(LLFolderView* root_folder);
  66. static bool has_collapsed_folders(LLFolderView* root_folder);
  67. static void toggle_restore_menu(LLMenuGL* menu, BOOL visible, BOOL enabled);
  68. /**
  69. * Functor counting expanded and collapsed folders in folder view tree to know
  70. * when to enable or disable "Expand all folders" and "Collapse all folders" commands.
  71. */
  72. class LLCheckFolderState : public LLFolderViewFunctor
  73. {
  74. public:
  75. LLCheckFolderState()
  76. : mCollapsedFolders(0),
  77. mExpandedFolders(0)
  78. {}
  79. virtual ~LLCheckFolderState() {}
  80. virtual void doFolder(LLFolderViewFolder* folder);
  81. virtual void doItem(LLFolderViewItem* item) {}
  82. S32 getCollapsedFolders() { return mCollapsedFolders; }
  83. S32 getExpandedFolders() { return mExpandedFolders; }
  84. private:
  85. S32 mCollapsedFolders;
  86. S32 mExpandedFolders;
  87. };
  88. // virtual
  89. void LLCheckFolderState::doFolder(LLFolderViewFolder* folder)
  90. {
  91. // Counting only folders that pass the filter.
  92. // The listener check allow us to avoid counting the folder view
  93. // object itself because it has no listener assigned.
  94. if (folder->hasFilteredDescendants() && folder->getListener())
  95. {
  96. if (folder->isOpen())
  97. {
  98. ++mExpandedFolders;
  99. }
  100. else
  101. {
  102. ++mCollapsedFolders;
  103. }
  104. }
  105. }
  106. // Functor searching and opening a folder specified by UUID
  107. // in a folder view tree.
  108. class LLOpenFolderByID : public LLFolderViewFunctor
  109. {
  110. public:
  111. LLOpenFolderByID(const LLUUID& folder_id)
  112. : mFolderID(folder_id)
  113. , mIsFolderOpen(false)
  114. {}
  115. virtual ~LLOpenFolderByID() {}
  116. /*virtual*/ void doFolder(LLFolderViewFolder* folder);
  117. /*virtual*/ void doItem(LLFolderViewItem* item) {}
  118. bool isFolderOpen() { return mIsFolderOpen; }
  119. private:
  120. bool mIsFolderOpen;
  121. LLUUID mFolderID;
  122. };
  123. // virtual
  124. void LLOpenFolderByID::doFolder(LLFolderViewFolder* folder)
  125. {
  126. if (folder->getListener() && folder->getListener()->getUUID() == mFolderID)
  127. {
  128. if (!folder->isOpen())
  129. {
  130. folder->setOpen(TRUE);
  131. mIsFolderOpen = true;
  132. }
  133. }
  134. }
  135. /**
  136. * Bridge to support knowing when the inventory has changed to update Landmarks tab
  137. * ShowFolderState filter setting to show all folders when the filter string is empty and
  138. * empty folder message when Landmarks inventory category has no children.
  139. * Ensures that "Landmarks" folder in the Library is open on strart up.
  140. */
  141. class LLLandmarksPanelObserver : public LLInventoryObserver
  142. {
  143. public:
  144. LLLandmarksPanelObserver(LLLandmarksPanel* lp)
  145. : mLP(lp),
  146. mIsLibraryLandmarksOpen(false)
  147. {}
  148. virtual ~LLLandmarksPanelObserver() {}
  149. /*virtual*/ void changed(U32 mask);
  150. private:
  151. LLLandmarksPanel* mLP;
  152. bool mIsLibraryLandmarksOpen;
  153. };
  154. void LLLandmarksPanelObserver::changed(U32 mask)
  155. {
  156. mLP->updateShowFolderState();
  157. LLPlacesInventoryPanel* library = mLP->getLibraryInventoryPanel();
  158. if (!mIsLibraryLandmarksOpen && library)
  159. {
  160. // Search for "Landmarks" folder in the Library and open it once on start up. See EXT-4827.
  161. const LLUUID &landmarks_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false, true);
  162. if (landmarks_cat.notNull())
  163. {
  164. LLOpenFolderByID opener(landmarks_cat);
  165. library->getRootFolder()->applyFunctorRecursively(opener);
  166. mIsLibraryLandmarksOpen = opener.isFolderOpen();
  167. }
  168. }
  169. }
  170. LLLandmarksPanel::LLLandmarksPanel()
  171. : LLPanelPlacesTab()
  172. , mFavoritesInventoryPanel(NULL)
  173. , mLandmarksInventoryPanel(NULL)
  174. , mMyInventoryPanel(NULL)
  175. , mLibraryInventoryPanel(NULL)
  176. , mCurrentSelectedList(NULL)
  177. , mListCommands(NULL)
  178. , mGearButton(NULL)
  179. , mGearFolderMenu(NULL)
  180. , mGearLandmarkMenu(NULL)
  181. {
  182. mInventoryObserver = new LLLandmarksPanelObserver(this);
  183. gInventory.addObserver(mInventoryObserver);
  184. buildFromFile( "panel_landmarks.xml");
  185. }
  186. LLLandmarksPanel::~LLLandmarksPanel()
  187. {
  188. if (gInventory.containsObserver(mInventoryObserver))
  189. {
  190. gInventory.removeObserver(mInventoryObserver);
  191. }
  192. }
  193. BOOL LLLandmarksPanel::postBuild()
  194. {
  195. if (!gInventory.isInventoryUsable())
  196. return FALSE;
  197. // mast be called before any other initXXX methods to init Gear menu
  198. initListCommandsHandlers();
  199. initFavoritesInventoryPanel();
  200. initLandmarksInventoryPanel();
  201. initMyInventoryPanel();
  202. initLibraryInventoryPanel();
  203. return TRUE;
  204. }
  205. // virtual
  206. void LLLandmarksPanel::onSearchEdit(const std::string& string)
  207. {
  208. // give FolderView a chance to be refreshed. So, made all accordions visible
  209. for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
  210. {
  211. LLAccordionCtrlTab* tab = *iter;
  212. tab->setVisible(TRUE);
  213. // expand accordion to see matched items in each one. See EXT-2014.
  214. if (string != "")
  215. {
  216. tab->changeOpenClose(false);
  217. }
  218. LLPlacesInventoryPanel* inventory_list = dynamic_cast<LLPlacesInventoryPanel*>(tab->getAccordionView());
  219. if (NULL == inventory_list) continue;
  220. if (inventory_list->getFilter())
  221. {
  222. filter_list(inventory_list, string);
  223. }
  224. }
  225. if (sFilterSubString != string)
  226. sFilterSubString = string;
  227. // show all folders in Landmarks Accordion for empty filter
  228. // only if Landmarks inventory folder is not empty
  229. updateShowFolderState();
  230. }
  231. // virtual
  232. void LLLandmarksPanel::onShowOnMap()
  233. {
  234. if (NULL == mCurrentSelectedList)
  235. {
  236. llwarns << "There are no selected list. No actions are performed." << llendl;
  237. return;
  238. }
  239. // Disable the "Map" button because loading landmark can take some time.
  240. // During this time the button is useless. It will be enabled on callback finish
  241. // or upon switching to other item.
  242. mShowOnMapBtn->setEnabled(FALSE);
  243. doActionOnCurSelectedLandmark(boost::bind(&LLLandmarksPanel::doShowOnMap, this, _1));
  244. }
  245. //virtual
  246. void LLLandmarksPanel::onShowProfile()
  247. {
  248. LLFolderViewItem* cur_item = getCurSelectedItem();
  249. if(!cur_item)
  250. return;
  251. cur_item->getListener()->performAction(mCurrentSelectedList->getModel(),"about");
  252. }
  253. // virtual
  254. void LLLandmarksPanel::onTeleport()
  255. {
  256. LLFolderViewItem* current_item = getCurSelectedItem();
  257. if (!current_item)
  258. {
  259. llwarns << "There are no selected list. No actions are performed." << llendl;
  260. return;
  261. }
  262. LLFolderViewEventListener* listenerp = current_item->getListener();
  263. if (listenerp && listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
  264. {
  265. listenerp->openItem();
  266. }
  267. }
  268. // virtual
  269. bool LLLandmarksPanel::isSingleItemSelected()
  270. {
  271. bool result = false;
  272. if (mCurrentSelectedList != NULL)
  273. {
  274. LLPlacesFolderView* root_view =
  275. static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder());
  276. if (root_view->getSelectedCount() == 1)
  277. {
  278. result = isLandmarkSelected();
  279. }
  280. }
  281. return result;
  282. }
  283. // virtual
  284. void LLLandmarksPanel::updateVerbs()
  285. {
  286. if (!isTabVisible())
  287. return;
  288. bool landmark_selected = isLandmarkSelected();
  289. mTeleportBtn->setEnabled(landmark_selected && isActionEnabled("teleport"));
  290. mShowProfile->setEnabled(landmark_selected && isActionEnabled("more_info"));
  291. mShowOnMapBtn->setEnabled(landmark_selected && isActionEnabled("show_on_map"));
  292. // TODO: mantipov: Uncomment when mShareBtn is supported
  293. // Share button should be enabled when neither a folder nor a landmark is selected
  294. //mShareBtn->setEnabled(NULL != current_item);
  295. updateListCommands();
  296. }
  297. void LLLandmarksPanel::onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
  298. {
  299. if (user_action && (items.size() > 0))
  300. {
  301. deselectOtherThan(inventory_list);
  302. mCurrentSelectedList = inventory_list;
  303. }
  304. updateVerbs();
  305. }
  306. void LLLandmarksPanel::onSelectorButtonClicked()
  307. {
  308. // TODO: mantipov: update getting of selected item
  309. // TODO: bind to "i" button
  310. LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem();
  311. if (!cur_item) return;
  312. LLFolderViewEventListener* listenerp = cur_item->getListener();
  313. if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
  314. {
  315. LLSD key;
  316. key["type"] = "landmark";
  317. key["id"] = listenerp->getUUID();
  318. LLFloaterSidePanelContainer::showPanel("places", key);
  319. }
  320. }
  321. void LLLandmarksPanel::updateShowFolderState()
  322. {
  323. if (!mLandmarksInventoryPanel->getFilter())
  324. return;
  325. bool show_all_folders = mLandmarksInventoryPanel->getRootFolder()->getFilterSubString().empty();
  326. if (show_all_folders)
  327. {
  328. show_all_folders = category_has_descendents(mLandmarksInventoryPanel);
  329. }
  330. mLandmarksInventoryPanel->setShowFolderState(show_all_folders ?
  331. LLInventoryFilter::SHOW_ALL_FOLDERS :
  332. LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS
  333. );
  334. }
  335. void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus)
  336. {
  337. if (selectItemInAccordionTab(mFavoritesInventoryPanel, "tab_favorites", obj_id, take_keyboard_focus))
  338. {
  339. return;
  340. }
  341. if (selectItemInAccordionTab(mLandmarksInventoryPanel, "tab_landmarks", obj_id, take_keyboard_focus))
  342. {
  343. return;
  344. }
  345. if (selectItemInAccordionTab(mMyInventoryPanel, "tab_inventory", obj_id, take_keyboard_focus))
  346. {
  347. return;
  348. }
  349. if (selectItemInAccordionTab(mLibraryInventoryPanel, "tab_library", obj_id, take_keyboard_focus))
  350. {
  351. return;
  352. }
  353. }
  354. //////////////////////////////////////////////////////////////////////////
  355. // PROTECTED METHODS
  356. //////////////////////////////////////////////////////////////////////////
  357. bool LLLandmarksPanel::isLandmarkSelected() const
  358. {
  359. LLFolderViewItem* current_item = getCurSelectedItem();
  360. if(current_item && current_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
  361. {
  362. return true;
  363. }
  364. return false;
  365. }
  366. bool LLLandmarksPanel::isReceivedFolderSelected() const
  367. {
  368. // Received Folder can be only in Landmarks accordion
  369. if (mCurrentSelectedList != mLandmarksInventoryPanel) return false;
  370. // *TODO: it should be filled with logic when EXT-976 is done.
  371. llwarns << "Not implemented yet until EXT-976 is done." << llendl;
  372. return false;
  373. }
  374. void LLLandmarksPanel::doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb)
  375. {
  376. LLFolderViewItem* cur_item = getCurSelectedItem();
  377. if(cur_item && cur_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
  378. {
  379. LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID(), cb);
  380. if (landmark)
  381. {
  382. cb(landmark);
  383. }
  384. }
  385. }
  386. LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem() const
  387. {
  388. return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL;
  389. }
  390. LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list,
  391. const std::string& tab_name,
  392. const LLUUID& obj_id,
  393. BOOL take_keyboard_focus) const
  394. {
  395. if (!inventory_list)
  396. return NULL;
  397. LLFolderView* root = inventory_list->getRootFolder();
  398. LLFolderViewItem* item = root->getItemByID(obj_id);
  399. if (!item)
  400. return NULL;
  401. LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(tab_name);
  402. if (!tab->isExpanded())
  403. {
  404. tab->changeOpenClose(false);
  405. }
  406. root->setSelection(item, FALSE, take_keyboard_focus);
  407. LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion");
  408. LLRect screen_rc;
  409. localRectToScreen(item->getRect(), &screen_rc);
  410. accordion->notifyParent(LLSD().with("scrollToShowRect", screen_rc.getValue()));
  411. return item;
  412. }
  413. void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate)
  414. {
  415. if(!panel) return;
  416. U32 order = panel->getSortOrder();
  417. if (byDate)
  418. {
  419. panel->setSortOrder( order | LLInventoryFilter::SO_DATE );
  420. }
  421. else
  422. {
  423. panel->setSortOrder( order & ~LLInventoryFilter::SO_DATE );
  424. }
  425. }
  426. // virtual
  427. void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)
  428. {
  429. //this function will be called after user will try to create a pick for selected landmark.
  430. // We have to make request to sever to get parcel_id and snaption_id.
  431. if(isLandmarkSelected())
  432. {
  433. LLFolderViewItem* cur_item = getCurSelectedItem();
  434. if (!cur_item) return;
  435. LLUUID id = cur_item->getListener()->getUUID();
  436. LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id);
  437. doActionOnCurSelectedLandmark(boost::bind(
  438. &LLLandmarksPanel::doProcessParcelInfo, this, _1, cur_item, inv_item, parcel_data));
  439. }
  440. }
  441. // virtual
  442. void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id)
  443. {
  444. if (!parcel_id.isNull())
  445. {
  446. LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
  447. LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
  448. }
  449. }
  450. // virtual
  451. void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason)
  452. {
  453. llwarns << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
  454. }
  455. //////////////////////////////////////////////////////////////////////////
  456. // PRIVATE METHODS
  457. //////////////////////////////////////////////////////////////////////////
  458. void LLLandmarksPanel::initFavoritesInventoryPanel()
  459. {
  460. mFavoritesInventoryPanel = getChild<LLPlacesInventoryPanel>("favorites_list");
  461. initLandmarksPanel(mFavoritesInventoryPanel);
  462. mFavoritesInventoryPanel->getFilter()->setEmptyLookupMessage("FavoritesNoMatchingItems");
  463. initAccordion("tab_favorites", mFavoritesInventoryPanel, true);
  464. }
  465. void LLLandmarksPanel::initLandmarksInventoryPanel()
  466. {
  467. mLandmarksInventoryPanel = getChild<LLPlacesInventoryPanel>("landmarks_list");
  468. initLandmarksPanel(mLandmarksInventoryPanel);
  469. // Check if mLandmarksInventoryPanel is properly initialized and has a Filter created.
  470. // In case of a dummy widget getFilter() will return NULL.
  471. if (mLandmarksInventoryPanel->getFilter())
  472. {
  473. mLandmarksInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS);
  474. }
  475. // subscribe to have auto-rename functionality while creating New Folder
  476. mLandmarksInventoryPanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mLandmarksInventoryPanel, _1, _2));
  477. mMyLandmarksAccordionTab = initAccordion("tab_landmarks", mLandmarksInventoryPanel, true);
  478. }
  479. void LLLandmarksPanel::initMyInventoryPanel()
  480. {
  481. mMyInventoryPanel= getChild<LLPlacesInventoryPanel>("my_inventory_list");
  482. initLandmarksPanel(mMyInventoryPanel);
  483. initAccordion("tab_inventory", mMyInventoryPanel, false);
  484. }
  485. void LLLandmarksPanel::initLibraryInventoryPanel()
  486. {
  487. mLibraryInventoryPanel = getChild<LLPlacesInventoryPanel>("library_list");
  488. initLandmarksPanel(mLibraryInventoryPanel);
  489. // We want to fetch only "Landmarks" category from the library.
  490. const LLUUID &landmarks_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false, true);
  491. if (landmarks_cat.notNull())
  492. {
  493. LLInventoryModelBackgroundFetch::instance().start(landmarks_cat);
  494. }
  495. // Expanding "Library" tab for new users who have no landmarks in "My Inventory".
  496. initAccordion("tab_library", mLibraryInventoryPanel, true);
  497. }
  498. void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list)
  499. {
  500. // In case of a dummy widget further we have no Folder View widget and no Filter,
  501. // so further initialization leads to crash.
  502. if (!inventory_list->getFilter())
  503. return;
  504. inventory_list->getFilter()->setEmptyLookupMessage("PlacesNoMatchingItems");
  505. inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK);
  506. inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2));
  507. inventory_list->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
  508. bool sorting_order = gSavedSettings.getBOOL("LandmarksSortedByDate");
  509. updateSortOrder(inventory_list, sorting_order);
  510. LLPlacesFolderView* root_folder = dynamic_cast<LLPlacesFolderView*>(inventory_list->getRootFolder());
  511. if (root_folder)
  512. {
  513. root_folder->setupMenuHandle(LLInventoryType::IT_CATEGORY, mGearFolderMenu->getHandle());
  514. root_folder->setupMenuHandle(LLInventoryType::IT_LANDMARK, mGearLandmarkMenu->getHandle());
  515. root_folder->setParentLandmarksPanel(this);
  516. }
  517. inventory_list->saveFolderState();
  518. }
  519. LLAccordionCtrlTab* LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list, bool expand_tab)
  520. {
  521. LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name);
  522. mAccordionTabs.push_back(accordion_tab);
  523. accordion_tab->setDropDownStateChangedCallback(
  524. boost::bind(&LLLandmarksPanel::onAccordionExpandedCollapsed, this, _2, inventory_list));
  525. accordion_tab->setDisplayChildren(expand_tab);
  526. return accordion_tab;
  527. }
  528. void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list)
  529. {
  530. bool expanded = param.asBoolean();
  531. if(!expanded && (mCurrentSelectedList == inventory_list))
  532. {
  533. inventory_list->getRootFolder()->clearSelection();
  534. mCurrentSelectedList = NULL;
  535. updateVerbs();
  536. }
  537. // Start background fetch, mostly for My Inventory and Library
  538. if (expanded)
  539. {
  540. const LLUUID &cat_id = inventory_list->getRootFolderID();
  541. // Just because the category itself has been fetched, doesn't mean its child folders have.
  542. /*
  543. if (!gInventory.isCategoryComplete(cat_id))
  544. */
  545. {
  546. LLInventoryModelBackgroundFetch::instance().start(cat_id);
  547. }
  548. // Apply filter substring because it might have been changed
  549. // while accordion was closed. See EXT-3714.
  550. filter_list(inventory_list, sFilterSubString);
  551. }
  552. }
  553. void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory_list)
  554. {
  555. if (inventory_list != mFavoritesInventoryPanel)
  556. {
  557. mFavoritesInventoryPanel->getRootFolder()->clearSelection();
  558. }
  559. if (inventory_list != mLandmarksInventoryPanel)
  560. {
  561. mLandmarksInventoryPanel->getRootFolder()->clearSelection();
  562. }
  563. if (inventory_list != mMyInventoryPanel)
  564. {
  565. mMyInventoryPanel->getRootFolder()->clearSelection();
  566. }
  567. if (inventory_list != mLibraryInventoryPanel)
  568. {
  569. mLibraryInventoryPanel->getRootFolder()->clearSelection();
  570. }
  571. }
  572. // List Commands Handlers
  573. void LLLandmarksPanel::initListCommandsHandlers()
  574. {
  575. mListCommands = getChild<LLPanel>("bottom_panel");
  576. mGearButton = getChild<LLMenuButton>(OPTIONS_BUTTON_NAME);
  577. mGearButton->setMouseDownCallback(boost::bind(&LLLandmarksPanel::onActionsButtonClick, this));
  578. mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this));
  579. LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>(TRASH_BUTTON_NAME);
  580. trash_btn->setDragAndDropHandler(boost::bind(&LLLandmarksPanel::handleDragAndDropToTrash, this
  581. , _4 // BOOL drop
  582. , _5 // EDragAndDropType cargo_type
  583. , _6 // void* cargo_data
  584. , _7 // EAcceptance* accept
  585. ));
  586. mCommitCallbackRegistrar.add("Places.LandmarksGear.Add.Action", boost::bind(&LLLandmarksPanel::onAddAction, this, _2));
  587. mCommitCallbackRegistrar.add("Places.LandmarksGear.CopyPaste.Action", boost::bind(&LLLandmarksPanel::onClipboardAction, this, _2));
  588. mCommitCallbackRegistrar.add("Places.LandmarksGear.Custom.Action", boost::bind(&LLLandmarksPanel::onCustomAction, this, _2));
  589. mCommitCallbackRegistrar.add("Places.LandmarksGear.Folding.Action", boost::bind(&LLLandmarksPanel::onFoldingAction, this, _2));
  590. mEnableCallbackRegistrar.add("Places.LandmarksGear.Check", boost::bind(&LLLandmarksPanel::isActionChecked, this, _2));
  591. mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2));
  592. mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  593. mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  594. mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  595. mGearLandmarkMenu->setVisibilityChangeCallback(boost::bind(&LLLandmarksPanel::onMenuVisibilityChange, this, _1, _2));
  596. mGearFolderMenu->setVisibilityChangeCallback(boost::bind(&LLLandmarksPanel::onMenuVisibilityChange, this, _1, _2));
  597. mListCommands->childSetAction(ADD_BUTTON_NAME, boost::bind(&LLLandmarksPanel::showActionMenu, this, mMenuAdd, ADD_BUTTON_NAME));
  598. }
  599. void LLLandmarksPanel::updateListCommands()
  600. {
  601. bool add_folder_enabled = isActionEnabled("category");
  602. bool trash_enabled = isActionEnabled("delete");
  603. // keep Options & Add Landmark buttons always enabled
  604. mListCommands->getChildView(ADD_FOLDER_BUTTON_NAME)->setEnabled(add_folder_enabled);
  605. mListCommands->getChildView(TRASH_BUTTON_NAME)->setEnabled(trash_enabled);
  606. }
  607. void LLLandmarksPanel::onActionsButtonClick()
  608. {
  609. LLToggleableMenu* menu = mGearFolderMenu;
  610. LLFolderViewItem* cur_item = NULL;
  611. if(mCurrentSelectedList)
  612. {
  613. cur_item = mCurrentSelectedList->getRootFolder()->getCurSelectedItem();
  614. if(!cur_item)
  615. return;
  616. LLFolderViewEventListener* listenerp = cur_item->getListener();
  617. if(!listenerp)
  618. return;
  619. if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
  620. {
  621. menu = mGearLandmarkMenu;
  622. }
  623. }
  624. mGearButton->setMenu(menu);
  625. }
  626. void LLLandmarksPanel::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
  627. {
  628. if (menu)
  629. {
  630. menu->buildDrawLabels();
  631. menu->updateParent(LLMenuGL::sMenuContainer);
  632. menu->arrangeAndClear();
  633. LLView* spawning_view = getChild<LLView>(spawning_view_name);
  634. S32 menu_x, menu_y;
  635. //show menu in co-ordinates of panel
  636. spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
  637. menu_y += menu->getRect().getHeight();
  638. LLMenuGL::showPopup(this, menu, menu_x, menu_y);
  639. }
  640. }
  641. void LLLandmarksPanel::onTrashButtonClick() const
  642. {
  643. onClipboardAction("delete");
  644. }
  645. void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
  646. {
  647. std::string command_name = userdata.asString();
  648. if("add_landmark" == command_name)
  649. {
  650. LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos();
  651. if(landmark)
  652. {
  653. LLNotificationsUtil::add("LandmarkAlreadyExists");
  654. }
  655. else
  656. {
  657. LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "create_landmark"));
  658. }
  659. }
  660. else if ("category" == command_name)
  661. {
  662. LLFolderViewItem* item = getCurSelectedItem();
  663. if (item && mCurrentSelectedList == mLandmarksInventoryPanel)
  664. {
  665. LLFolderViewEventListener* folder_bridge = NULL;
  666. if (item-> getListener()->getInventoryType()
  667. == LLInventoryType::IT_LANDMARK)
  668. {
  669. // for a landmark get parent folder bridge
  670. folder_bridge = item->getParentFolder()->getListener();
  671. }
  672. else if (item-> getListener()->getInventoryType()
  673. == LLInventoryType::IT_CATEGORY)
  674. {
  675. // for a folder get its own bridge
  676. folder_bridge = item->getListener();
  677. }
  678. menu_create_inventory_item(mCurrentSelectedList->getRootFolder(),
  679. dynamic_cast<LLFolderBridge*> (folder_bridge), LLSD(
  680. "category"), gInventory.findCategoryUUIDForType(
  681. LLFolderType::FT_LANDMARK));
  682. }
  683. else
  684. {
  685. //in case My Landmarks tab is completely empty (thus cannot be determined as being selected)
  686. menu_create_inventory_item(mLandmarksInventoryPanel->getRootFolder(), NULL, LLSD("category"),
  687. gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK));
  688. if (mMyLandmarksAccordionTab)
  689. {
  690. mMyLandmarksAccordionTab->changeOpenClose(false);
  691. }
  692. }
  693. }
  694. }
  695. void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const
  696. {
  697. if(!mCurrentSelectedList)
  698. return;
  699. std::string command_name = userdata.asString();
  700. if("copy_slurl" == command_name)
  701. {
  702. LLFolderViewItem* cur_item = getCurSelectedItem();
  703. if(cur_item)
  704. LLLandmarkActions::copySLURLtoClipboard(cur_item->getListener()->getUUID());
  705. }
  706. else if ( "paste" == command_name)
  707. {
  708. mCurrentSelectedList->getRootFolder()->paste();
  709. }
  710. else if ( "cut" == command_name)
  711. {
  712. mCurrentSelectedList->getRootFolder()->cut();
  713. }
  714. else
  715. {
  716. mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(),command_name);
  717. }
  718. }
  719. void LLLandmarksPanel::onFoldingAction(const LLSD& userdata)
  720. {
  721. std::string command_name = userdata.asString();
  722. if ("expand_all" == command_name)
  723. {
  724. expand_all_folders(mFavoritesInventoryPanel->getRootFolder());
  725. expand_all_folders(mLandmarksInventoryPanel->getRootFolder());
  726. expand_all_folders(mMyInventoryPanel->getRootFolder());
  727. expand_all_folders(mLibraryInventoryPanel->getRootFolder());
  728. for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
  729. {
  730. (*iter)->changeOpenClose(false);
  731. }
  732. }
  733. else if ("collapse_all" == command_name)
  734. {
  735. collapse_all_folders(mFavoritesInventoryPanel->getRootFolder());
  736. collapse_all_folders(mLandmarksInventoryPanel->getRootFolder());
  737. collapse_all_folders(mMyInventoryPanel->getRootFolder());
  738. collapse_all_folders(mLibraryInventoryPanel->getRootFolder());
  739. for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
  740. {
  741. (*iter)->changeOpenClose(true);
  742. }
  743. }
  744. else if ("sort_by_date" == command_name)
  745. {
  746. bool sorting_order = gSavedSettings.getBOOL("LandmarksSortedByDate");
  747. sorting_order=!sorting_order;
  748. gSavedSettings.setBOOL("LandmarksSortedByDate",sorting_order);
  749. updateSortOrder(mLandmarksInventoryPanel, sorting_order);
  750. updateSortOrder(mMyInventoryPanel, sorting_order);
  751. updateSortOrder(mLibraryInventoryPanel, sorting_order);
  752. }
  753. else
  754. {
  755. if(mCurrentSelectedList)
  756. {
  757. mCurrentSelectedList->getRootFolder()->doToSelected(&gInventory, userdata);
  758. }
  759. }
  760. }
  761. bool LLLandmarksPanel::isActionChecked(const LLSD& userdata) const
  762. {
  763. const std::string command_name = userdata.asString();
  764. if ( "sort_by_date" == command_name)
  765. {
  766. bool sorting_order = gSavedSettings.getBOOL("LandmarksSortedByDate");
  767. return sorting_order;
  768. }
  769. return false;
  770. }
  771. bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
  772. {
  773. std::string command_name = userdata.asString();
  774. LLPlacesFolderView* root_folder_view = mCurrentSelectedList ?
  775. static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder()) : NULL;
  776. if ("collapse_all" == command_name)
  777. {
  778. bool disable_collapse_all = !has_expanded_folders(mFavoritesInventoryPanel->getRootFolder())
  779. && !has_expanded_folders(mLandmarksInventoryPanel->getRootFolder())
  780. && !has_expanded_folders(mMyInventoryPanel->getRootFolder())
  781. && !has_expanded_folders(mLibraryInventoryPanel->getRootFolder());
  782. if (disable_collapse_all)
  783. {
  784. for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
  785. {
  786. if ((*iter)->isExpanded())
  787. {
  788. disable_collapse_all = false;
  789. break;
  790. }
  791. }
  792. }
  793. return !disable_collapse_all;
  794. }
  795. else if ("expand_all" == command_name)
  796. {
  797. bool disable_expand_all = !has_collapsed_folders(mFavoritesInventoryPanel->getRootFolder())
  798. && !has_collapsed_folders(mLandmarksInventoryPanel->getRootFolder())
  799. && !has_collapsed_folders(mMyInventoryPanel->getRootFolder())
  800. && !has_collapsed_folders(mLibraryInventoryPanel->getRootFolder());
  801. if (disable_expand_all)
  802. {
  803. for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
  804. {
  805. if (!(*iter)->isExpanded())
  806. {
  807. disable_expand_all = false;
  808. break;
  809. }
  810. }
  811. }
  812. return !disable_expand_all;
  813. }
  814. else if ("sort_by_date" == command_name)
  815. {
  816. // disable "sort_by_date" for Favorites accordion because
  817. // it has its own items order. EXT-1758
  818. if (mCurrentSelectedList == mFavoritesInventoryPanel)
  819. {
  820. return false;
  821. }
  822. }
  823. else if ( "paste" == command_name
  824. || "cut" == command_name
  825. || "copy" == command_name
  826. || "delete" == command_name
  827. || "collapse" == command_name
  828. || "expand" == command_name
  829. )
  830. {
  831. if (!root_folder_view) return false;
  832. std::set<LLUUID> selected_uuids = root_folder_view->getSelectionList();
  833. // Allow to execute the command only if it can be applied to all selected items.
  834. for (std::set<LLUUID>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter)
  835. {
  836. LLFolderViewItem* item = root_folder_view->getItemByID(*iter);
  837. // If no item is found it might be a folder id.
  838. if (!item)
  839. {
  840. item = root_folder_view->getFolderByID(*iter);
  841. }
  842. if (!item) return false;
  843. if (!canItemBeModified(command_name, item)) return false;
  844. }
  845. return true;
  846. }
  847. else if ( "teleport" == command_name
  848. || "more_info" == command_name
  849. || "show_on_map" == command_name
  850. || "copy_slurl" == command_name
  851. || "rename" == command_name
  852. )
  853. {
  854. // disable some commands for multi-selection. EXT-1757
  855. bool is_single_selection = root_folder_view && root_folder_view->getSelectedCount() == 1;
  856. if (!is_single_selection)
  857. {
  858. return false;
  859. }
  860. if ("show_on_map" == command_name)
  861. {
  862. LLFolderViewItem* cur_item = root_folder_view->getCurSelectedItem();
  863. if (!cur_item) return false;
  864. LLViewerInventoryItem* inv_item = cur_item->getInventoryItem();
  865. if (!inv_item) return false;
  866. LLUUID asset_uuid = inv_item->getAssetUUID();
  867. if (asset_uuid.isNull()) return false;
  868. // Disable "Show on Map" if landmark loading is in progress.
  869. return !gLandmarkList.isAssetInLoadedCallbackMap(asset_uuid);
  870. }
  871. else if ("rename" == command_name)
  872. {
  873. LLFolderViewItem* selected_item = getCurSelectedItem();
  874. if (!selected_item) return false;
  875. return canItemBeModified(command_name, selected_item);
  876. }
  877. return true;
  878. }
  879. else if("category" == command_name)
  880. {
  881. // we can add folder only in Landmarks Accordion
  882. if (mCurrentSelectedList == mLandmarksInventoryPanel)
  883. {
  884. // ... but except Received folder
  885. return !isReceivedFolderSelected();
  886. }
  887. //"Add a folder" is enabled by default (case when My Landmarks is empty)
  888. else return true;
  889. }
  890. else if("create_pick" == command_name)
  891. {
  892. if (mCurrentSelectedList)
  893. {
  894. std::set<LLUUID> selection = mCurrentSelectedList->getRootFolder()->getSelectionList();
  895. if (!selection.empty())
  896. {
  897. return ( 1 == selection.size() && !LLAgentPicksInfo::getInstance()->isPickLimitReached() );
  898. }
  899. }
  900. return false;
  901. }
  902. else
  903. {
  904. llwarns << "Unprocessed command has come: " << command_name << llendl;
  905. }
  906. return true;
  907. }
  908. void LLLandmarksPanel::onCustomAction(const LLSD& userdata)
  909. {
  910. std::string command_name = userdata.asString();
  911. if("more_info" == command_name)
  912. {
  913. onShowProfile();
  914. }
  915. else if ("teleport" == command_name)
  916. {
  917. onTeleport();
  918. }
  919. else if ("show_on_map" == command_name)
  920. {
  921. onShowOnMap();
  922. }
  923. else if ("create_pick" == command_name)
  924. {
  925. doActionOnCurSelectedLandmark(boost::bind(&LLLandmarksPanel::doCreatePick, this, _1));
  926. }
  927. else if ("restore" == command_name && mCurrentSelectedList)
  928. {
  929. mCurrentSelectedList->doToSelected(userdata);
  930. }
  931. }
  932. void LLLandmarksPanel::onMenuVisibilityChange(LLUICtrl* ctrl, const LLSD& param)
  933. {
  934. bool new_visibility = param["visibility"].asBoolean();
  935. // We don't have to update items visibility if the menu is hiding.
  936. if (!new_visibility) return;
  937. BOOL are_any_items_in_trash = FALSE;
  938. BOOL are_all_items_in_trash = TRUE;
  939. LLFolderView* root_folder_view = mCurrentSelectedList ? mCurrentSelectedList->getRootFolder() : NULL;
  940. if(root_folder_view)
  941. {
  942. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  943. std::set<LLUUID> selected_uuids = root_folder_view->getSelectionList();
  944. // Iterate through selected items to find out if any of these items are in Trash
  945. // or all the items are in Trash category.
  946. for (std::set<LLUUID>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter)
  947. {
  948. LLFolderViewItem* item = root_folder_view->getItemByID(*iter);
  949. // If no item is found it might be a folder id.
  950. if (!item)
  951. {
  952. item = root_folder_view->getFolderByID(*iter);
  953. }
  954. if (!item) continue;
  955. LLFolderViewEventListener* listenerp = item->getListener();
  956. if(!listenerp) continue;
  957. // Trash category itself should not be included because it can't be
  958. // actually restored from trash.
  959. are_all_items_in_trash &= listenerp->isItemInTrash() && *iter != trash_id;
  960. // If there are any selected items in Trash including the Trash category itself
  961. // we show "Restore Item" in context menu and hide other irrelevant items.
  962. are_any_items_in_trash |= listenerp->isItemInTrash();
  963. }
  964. }
  965. // Display "Restore Item" menu entry if at least one of the selected items
  966. // is in Trash or the Trash category itself is among selected items.
  967. // Hide other menu entries in this case.
  968. // Enable this menu entry only if all selected items are in the Trash category.
  969. toggle_restore_menu((LLMenuGL*)ctrl, are_any_items_in_trash, are_all_items_in_trash);
  970. }
  971. /*
  972. Processes such actions: cut/rename/delete/paste actions
  973. Rules:
  974. 1. We can't perform any action in Library
  975. 2. For Landmarks we can:
  976. - cut/rename/delete in any other accordions
  977. - paste - only in Favorites, Landmarks accordions
  978. 3. For Folders we can: perform any action in Landmarks accordion, except Received folder
  979. 4. We can not paste folders from Clipboard (processed by LLFolderView::canPaste())
  980. 5. Check LLFolderView/Inventory Bridges rules
  981. */
  982. bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFolderViewItem* item) const
  983. {
  984. // validate own rules first
  985. if (!item) return false;
  986. // nothing can be modified in Library
  987. if (mLibraryInventoryPanel == mCurrentSelectedList) return false;
  988. bool can_be_modified = false;
  989. // landmarks can be modified in any other accordion...
  990. if (item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
  991. {
  992. can_be_modified = true;
  993. // we can modify landmarks anywhere except paste to My Inventory
  994. if ("paste" == command_name)
  995. {
  996. can_be_modified = (mCurrentSelectedList != mMyInventoryPanel);
  997. }
  998. }
  999. else
  1000. {
  1001. // ...folders only in the Landmarks accordion...
  1002. can_be_modified = mLandmarksInventoryPanel == mCurrentSelectedList;
  1003. // ...except "Received" folder
  1004. can_be_modified &= !isReceivedFolderSelected();
  1005. }
  1006. // then ask LLFolderView permissions
  1007. LLFolderView* root_folder = mCurrentSelectedList->getRootFolder();
  1008. if ("copy" == command_name)
  1009. {
  1010. return root_folder->canCopy();
  1011. }
  1012. else if ("collapse" == command_name)
  1013. {
  1014. return item->isOpen();
  1015. }
  1016. else if ("expand" == command_name)
  1017. {
  1018. return !item->isOpen();
  1019. }
  1020. if (can_be_modified)
  1021. {
  1022. LLFolderViewEventListener* listenerp = item->getListener();
  1023. if ("cut" == command_name)
  1024. {
  1025. // "Cut" disabled for folders. See EXT-8697.
  1026. can_be_modified = root_folder->canCut() && listenerp->getInventoryType() != LLInventoryType::IT_CATEGORY;
  1027. }
  1028. else if ("rename" == command_name)
  1029. {
  1030. can_be_modified = listenerp ? listenerp->isItemRenameable() : false;
  1031. }
  1032. else if ("delete" == command_name)
  1033. {
  1034. can_be_modified = listenerp ? listenerp->isItemRemovable() && !listenerp->isItemInTrash() : false;
  1035. }
  1036. else if("paste" == command_name)
  1037. {
  1038. can_be_modified = root_folder->canPaste();
  1039. }
  1040. else
  1041. {
  1042. llwarns << "Unprocessed command has come: " << command_name << llendl;
  1043. }
  1044. }
  1045. return can_be_modified;
  1046. }
  1047. void LLLandmarksPanel::onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params)
  1048. {
  1049. pick_panel->setVisible(FALSE);
  1050. owner->removeChild(pick_panel);
  1051. //we need remove observer to avoid processParcelInfo in the future.
  1052. LLRemoteParcelInfoProcessor::getInstance()->removeObserver(params["parcel_id"].asUUID(), this);
  1053. delete pick_panel;
  1054. pick_panel = NULL;
  1055. }
  1056. bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data , EAcceptance* accept)
  1057. {
  1058. *accept = ACCEPT_NO;
  1059. switch (cargo_type)
  1060. {
  1061. case DAD_LANDMARK:
  1062. case DAD_CATEGORY:
  1063. {
  1064. bool is_enabled = isActionEnabled("delete");
  1065. if (is_enabled) *accept = ACCEPT_YES_MULTI;
  1066. if (is_enabled && drop)
  1067. {
  1068. // don't call onClipboardAction("delete")
  1069. // this lead to removing (N * 2 - 1) items if drag N>1 items into trash. EXT-6757
  1070. // So, let remove items one by one.
  1071. LLInventoryItem* item = static_cast<LLInventoryItem*>(cargo_data);
  1072. if (item)
  1073. {
  1074. LLFolderViewItem* fv_item = (mCurrentSelectedList && mCurrentSelectedList->getRootFolder()) ?
  1075. mCurrentSelectedList->getRootFolder()->getItemByID(item->getUUID()) : NULL;
  1076. if (fv_item)
  1077. {
  1078. // is Item Removable checked inside of remove()
  1079. fv_item->remove();
  1080. }
  1081. }
  1082. }
  1083. }
  1084. break;
  1085. default:
  1086. break;
  1087. }
  1088. return true;
  1089. }
  1090. void LLLandmarksPanel::doShowOnMap(LLLandmark* landmark)
  1091. {
  1092. LLVector3d landmark_global_pos;
  1093. if (!landmark->getGlobalPos(landmark_global_pos))
  1094. return;
  1095. LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
  1096. if (!landmark_global_pos.isExactlyZero() && worldmap_instance)
  1097. {
  1098. worldmap_instance->trackLocation(landmark_global_pos);
  1099. LLFloaterReg::showInstance("world_map", "center");
  1100. }
  1101. mShowOnMapBtn->setEnabled(TRUE);
  1102. mGearLandmarkMenu->setItemEnabled("show_on_map", TRUE);
  1103. }
  1104. void LLLandmarksPanel::doProcessParcelInfo(LLLandmark* landmark,
  1105. LLFolderViewItem* cur_item,
  1106. LLInventoryItem* inv_item,
  1107. const LLParcelData& parcel_data)
  1108. {
  1109. LLPanelPickEdit* panel_pick = LLPanelPickEdit::create();
  1110. LLVector3d landmark_global_pos;
  1111. landmark->getGlobalPos(landmark_global_pos);
  1112. // let's toggle pick panel into panel places
  1113. LLPanel* panel_places = NULL;
  1114. LLFloaterSidePanelContainer* floaterp = LLFloaterReg::getTypedInstance<LLFloaterSidePanelContainer>("places");
  1115. if (floaterp)
  1116. {
  1117. panel_places = floaterp->findChild<LLPanel>("main_panel");
  1118. }
  1119. if (!panel_places)
  1120. {
  1121. llassert(NULL != panel_places);
  1122. return;
  1123. }
  1124. panel_places->addChild(panel_pick);
  1125. LLRect paren_rect(panel_places->getRect());
  1126. panel_pick->reshape(paren_rect.getWidth(),paren_rect.getHeight(), TRUE);
  1127. panel_pick->setRect(paren_rect);
  1128. panel_pick->onOpen(LLSD());
  1129. LLPickData data;
  1130. data.pos_global = landmark_global_pos;
  1131. data.name = cur_item->getName();
  1132. data.desc = inv_item->getDescription();
  1133. data.snapshot_id = parcel_data.snapshot_id;
  1134. data.parcel_id = parcel_data.parcel_id;
  1135. panel_pick->setPickData(&data);
  1136. LLSD params;
  1137. params["parcel_id"] = parcel_data.parcel_id;
  1138. /* set exit callback to get back onto panel places
  1139. in callback we will make cleaning up( delete pick_panel instance,
  1140. remove landmark panel from observer list
  1141. */
  1142. panel_pick->setExitCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
  1143. panel_pick, panel_places,params));
  1144. panel_pick->setSaveCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
  1145. panel_pick, panel_places,params));
  1146. panel_pick->setCancelCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
  1147. panel_pick, panel_places,params));
  1148. }
  1149. void LLLandmarksPanel::doCreatePick(LLLandmark* landmark)
  1150. {
  1151. LLViewerRegion* region = gAgent.getRegion();
  1152. if (!region) return;
  1153. LLGlobalVec pos_global;
  1154. LLUUID region_id;
  1155. landmark->getGlobalPos(pos_global);
  1156. landmark->getRegionID(region_id);
  1157. LLVector3 region_pos((F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS),
  1158. (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS),
  1159. (F32)pos_global.mdV[VZ]);
  1160. LLSD body;
  1161. std::string url = region->getCapability("RemoteParcelRequest");
  1162. if (!url.empty())
  1163. {
  1164. body["location"] = ll_sd_from_vector3(region_pos);
  1165. if (!region_id.isNull())
  1166. {
  1167. body["region_id"] = region_id;
  1168. }
  1169. if (!pos_global.isExactlyZero())
  1170. {
  1171. U64 region_handle = to_region_handle(pos_global);
  1172. body["region_handle"] = ll_sd_from_U64(region_handle);
  1173. }
  1174. LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle()));
  1175. }
  1176. else
  1177. {
  1178. llwarns << "Can't create pick for landmark for region" << region_id
  1179. << ". Region: " << region->getName()
  1180. << " does not support RemoteParcelRequest" << llendl;
  1181. }
  1182. }
  1183. //////////////////////////////////////////////////////////////////////////
  1184. // HELPER FUNCTIONS
  1185. //////////////////////////////////////////////////////////////////////////
  1186. static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string)
  1187. {
  1188. // When search is cleared, restore the old folder state.
  1189. if (!inventory_list->getRootFolder()->getFilterSubString().empty() && string == "")
  1190. {
  1191. inventory_list->setFilterSubString(LLStringUtil::null);
  1192. // Re-open folders that were open before
  1193. inventory_list->restoreFolderState();
  1194. }
  1195. if (inventory_list->getFilterSubString().empty() && string.empty())
  1196. {
  1197. // current filter and new filter empty, do nothing
  1198. return;
  1199. }
  1200. // save current folder open state if no filter currently applied
  1201. if (inventory_list->getRootFolder()->getFilterSubString().empty())
  1202. {
  1203. inventory_list->saveFolderState();
  1204. }
  1205. // Set new filter string
  1206. inventory_list->setFilterSubString(string);
  1207. }
  1208. static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list)
  1209. {
  1210. LLViewerInventoryCategory* category = gInventory.getCategory(inventory_list->getRootFolderID());
  1211. if (category)
  1212. {
  1213. return category->getDescendentCount() > 0;
  1214. }
  1215. return false;
  1216. }
  1217. static void collapse_all_folders(LLFolderView* root_folder)
  1218. {
  1219. if (!root_folder)
  1220. return;
  1221. root_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN);
  1222. // The top level folder is invisible, it must be open to
  1223. // display its sub-folders.
  1224. root_folder->openTopLevelFolders();
  1225. root_folder->arrangeAll();
  1226. }
  1227. static void expand_all_folders(LLFolderView* root_folder)
  1228. {
  1229. if (!root_folder)
  1230. return;
  1231. root_folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN);
  1232. root_folder->arrangeAll();
  1233. }
  1234. static bool has_expanded_folders(LLFolderView* root_folder)
  1235. {
  1236. LLCheckFolderState checker;
  1237. root_folder->applyFunctorRecursively(checker);
  1238. // We assume that the root folder is always expanded so we enable "collapse_all"
  1239. // command when we have at least one more expanded folder.
  1240. if (checker.getExpandedFolders() < 2)
  1241. {
  1242. return false;
  1243. }
  1244. return true;
  1245. }
  1246. static bool has_collapsed_folders(LLFolderView* root_folder)
  1247. {
  1248. LLCheckFolderState checker;
  1249. root_folder->applyFunctorRecursively(checker);
  1250. if (checker.getCollapsedFolders() < 1)
  1251. {
  1252. return false;
  1253. }
  1254. return true;
  1255. }
  1256. // Displays "Restore Item" context menu entry while hiding
  1257. // all other entries or vice versa.
  1258. // Sets "Restore Item" enabled state.
  1259. void toggle_restore_menu(LLMenuGL *menu, BOOL visible, BOOL enabled)
  1260. {
  1261. if (!menu) return;
  1262. const LLView::child_list_t *list = menu->getChildList();
  1263. for (LLView::child_list_t::const_iterator itor = list->begin();
  1264. itor != list->end();
  1265. ++itor)
  1266. {
  1267. LLView *menu_item = (*itor);
  1268. std::string name = menu_item->getName();
  1269. if ("restore_item" == name)
  1270. {
  1271. menu_item->setVisible(visible);
  1272. menu_item->setEnabled(enabled);
  1273. }
  1274. else
  1275. {
  1276. menu_item->setVisible(!visible);
  1277. }
  1278. }
  1279. }
  1280. // EOF