llfloaterinventory.cpp 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217
  1. /**
  2. * @filell llfloaterinventory.cpp
  3. * @brief Implementation of the inventory floater and associated stuff.
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llfloaterinventory.h"
  34. #include "llcheckboxctrl.h"
  35. #include "lldir.h"
  36. #include "llfasttimer.h"
  37. #include "lllocale.h"
  38. #include "llscrollcontainer.h"
  39. #include "llsdserialize.h"
  40. #include "llspinctrl.h"
  41. #include "lltabcontainer.h"
  42. #include "lluictrlfactory.h"
  43. #include "llwindow.h"
  44. #include "llmessage.h"
  45. #include "llagent.h"
  46. #include "llappviewer.h"
  47. #include "llavatartracker.h"
  48. #include "llfirstuse.h"
  49. #include "llfloateravatarinfo.h"
  50. #include "llfloaterchat.h"
  51. #include "llfloatercustomize.h"
  52. #include "hbfloaterthumbnail.h"
  53. #include "llgesturemgr.h"
  54. #include "llinventoryactions.h"
  55. #include "llinventorybridge.h"
  56. #include "llinventorymodelfetch.h"
  57. #include "llmarketplacefunctions.h"
  58. #include "llpreviewanim.h"
  59. #include "llpreviewgesture.h"
  60. #include "llpreviewlandmark.h"
  61. #include "llpreviewnotecard.h"
  62. #include "llpreviewscript.h"
  63. #include "llpreviewsound.h"
  64. #include "llpreviewtexture.h"
  65. //MK
  66. #include "mkrlinterface.h"
  67. //mk
  68. #include "llselectmgr.h"
  69. #include "llstartup.h"
  70. #include "lltooldraganddrop.h"
  71. #include "llviewercontrol.h"
  72. #include "llviewerinventory.h"
  73. #include "llviewerobjectlist.h"
  74. #include "llviewerregion.h"
  75. #include "llviewertexturelist.h"
  76. #include "llwearablelist.h"
  77. std::vector<LLFloaterInventory*> LLFloaterInventory::sActiveViews;
  78. constexpr S32 INV_MIN_WIDTH = 240;
  79. constexpr S32 INV_MIN_HEIGHT = 150;
  80. constexpr S32 INV_FINDER_WIDTH = 300;
  81. constexpr S32 INV_FINDER_HEIGHT = 430;
  82. ///----------------------------------------------------------------------------
  83. /// LLFloaterInventoryFilters
  84. ///----------------------------------------------------------------------------
  85. LLFloaterInventoryFilters::LLFloaterInventoryFilters(const std::string& name,
  86. const LLRect& rect,
  87. LLFloaterInventory* inv)
  88. : LLFloater(name, rect, "Filters", RESIZE_NO, INV_FINDER_WIDTH,
  89. INV_FINDER_HEIGHT, DRAG_ON_TOP, MINIMIZE_NO, CLOSE_YES),
  90. mInventoryView(inv),
  91. mFilter(inv->mActivePanel->getFilter()),
  92. mHasMaterial(gAgent.hasRegionCapability("UpdateMaterialAgentInventory"))
  93. {
  94. LLUICtrlFactory::getInstance()->buildFloater(this,
  95. "floater_inventory_filters.xml");
  96. }
  97. //virtual
  98. bool LLFloaterInventoryFilters::postBuild()
  99. {
  100. childSetAction("All", selectAllTypes, this);
  101. childSetAction("None", selectNoTypes, this);
  102. childSetAction("Reset", onResetFilters, this);
  103. childSetAction("Close", onCloseBtn, this);
  104. mSpinSinceHours = getChild<LLSpinCtrl>("spin_hours_ago");
  105. mSpinSinceHours->setCommitCallback(onTimeAgo);
  106. mSpinSinceHours->setCallbackUserData(this);
  107. mSpinSinceDays = getChild<LLSpinCtrl>("spin_days_ago");
  108. mSpinSinceDays->setCommitCallback(onTimeAgo);
  109. mSpinSinceDays->setCallbackUserData(this);
  110. mCheckSinceLogoff = getChild<LLCheckBoxCtrl>("check_since_logoff");
  111. mCheckShowEmpty = getChild<LLCheckBoxCtrl>("check_show_empty");
  112. mCheckAnimation = getChild<LLCheckBoxCtrl>("check_animation");
  113. mCheckCallingcard = getChild<LLCheckBoxCtrl>("check_callingcard");
  114. mCheckClothing = getChild<LLCheckBoxCtrl>("check_clothing");
  115. mCheckGesture = getChild<LLCheckBoxCtrl>("check_gesture");
  116. mCheckLandmark = getChild<LLCheckBoxCtrl>("check_landmark");
  117. mCheckMaterial = getChild<LLCheckBoxCtrl>("check_material");
  118. if (!mHasMaterial)
  119. {
  120. mCheckMaterial->set(false);
  121. mCheckMaterial->setEnabled(false);
  122. std::string tooltip = getString("not_supported");
  123. childSetToolTip("check_material", tooltip);
  124. childSetToolTip("icon_material", tooltip);
  125. }
  126. mCheckNotecard = getChild<LLCheckBoxCtrl>("check_notecard");
  127. mCheckObject = getChild<LLCheckBoxCtrl>("check_object");
  128. mCheckScript = getChild<LLCheckBoxCtrl>("check_script");
  129. mCheckSnapshot = getChild<LLCheckBoxCtrl>("check_snapshot");
  130. mCheckSound = getChild<LLCheckBoxCtrl>("check_sound");
  131. mCheckTexture = getChild<LLCheckBoxCtrl>("check_texture");
  132. #if LL_MESH_ASSET_SUPPORT
  133. mCheckMesh = getChild<LLCheckBoxCtrl>("check_mesh");
  134. mCheckMesh->setEnabled(true);
  135. childEnable("icon_mesh");
  136. #else
  137. std::string tooltip = getString("mesh_deprecated");
  138. childSetToolTip("check_mesh", tooltip);
  139. childSetToolTip("icon_mesh", tooltip);
  140. #endif
  141. mCheckSettings = getChild<LLCheckBoxCtrl>("check_settings");
  142. updateElementsFromFilter();
  143. return true;
  144. }
  145. void LLFloaterInventoryFilters::onResetFilters(void* userdata)
  146. {
  147. LLFloaterInventoryFilters* self = (LLFloaterInventoryFilters*)userdata;
  148. if (self)
  149. {
  150. LLInventoryPanel* panelp = self->mInventoryView->mActivePanel;
  151. if (panelp)
  152. {
  153. panelp->getFilter()->resetDefault();
  154. self->updateElementsFromFilter();
  155. self->mInventoryView->setFilterTextFromFilter();
  156. }
  157. }
  158. }
  159. void LLFloaterInventoryFilters::onTimeAgo(LLUICtrl*, void* userdata)
  160. {
  161. LLFloaterInventoryFilters* self = (LLFloaterInventoryFilters*)userdata;
  162. if (self)
  163. {
  164. self->mCheckSinceLogoff->set(!self->mSpinSinceDays->get() &&
  165. !self->mSpinSinceHours->get());
  166. }
  167. }
  168. void LLFloaterInventoryFilters::changeFilter(LLInventoryFilter* filter)
  169. {
  170. mFilter = filter;
  171. updateElementsFromFilter();
  172. }
  173. void LLFloaterInventoryFilters::updateElementsFromFilter()
  174. {
  175. if (!mFilter)
  176. {
  177. return;
  178. }
  179. U32 filter = mFilter->getFilterTypes();
  180. mCheckAnimation->set(filter & 0x1 << LLInventoryType::IT_ANIMATION);
  181. mCheckCallingcard->set(filter & 0x1 << LLInventoryType::IT_CALLINGCARD);
  182. mCheckClothing->set(filter & 0x1 << LLInventoryType::IT_WEARABLE);
  183. mCheckGesture->set(filter & 0x1 << LLInventoryType::IT_GESTURE);
  184. mCheckLandmark->set(filter & 0x1 << LLInventoryType::IT_LANDMARK);
  185. mCheckMaterial->set(mHasMaterial &&
  186. (filter & 0x1 << LLInventoryType::IT_MATERIAL));
  187. mCheckNotecard->set(filter & 0x1 << LLInventoryType::IT_NOTECARD);
  188. mCheckObject->set(filter & 0x1 << LLInventoryType::IT_OBJECT);
  189. mCheckScript->set(filter & 0x1 << LLInventoryType::IT_LSL);
  190. mCheckSound->set(filter & 0x1 << LLInventoryType::IT_SOUND);
  191. mCheckTexture->set(filter & 0x1 << LLInventoryType::IT_TEXTURE);
  192. mCheckSnapshot->set(filter & 0x1 << LLInventoryType::IT_SNAPSHOT);
  193. #if LL_MESH_ASSET_SUPPORT
  194. mCheckMesh->set(filter & 0x1 << LLInventoryType::IT_MESH);
  195. #endif
  196. mCheckSettings->set(filter & 0x1 << LLInventoryType::IT_SETTINGS);
  197. mCheckShowEmpty->set(mFilter->getShowFolderState() ==
  198. LLInventoryFilter::SHOW_ALL_FOLDERS);
  199. mCheckSinceLogoff->set(mFilter->isSinceLogoff());
  200. U32 hours = mFilter->getHoursAgo();
  201. mSpinSinceHours->set((F32)(hours % 24));
  202. mSpinSinceDays->set((F32)(hours / 24));
  203. }
  204. void LLFloaterInventoryFilters::draw()
  205. {
  206. //MK
  207. // Fast enough that it can be kept here
  208. if (gRLenabled && gRLInterface.mContainsShowinv)
  209. {
  210. close();
  211. return;
  212. }
  213. //mk
  214. U32 filter = 0xffffffff;
  215. bool filtered_by_all_types = true;
  216. if (!mCheckAnimation->get())
  217. {
  218. filter &= ~(0x1 << LLInventoryType::IT_ANIMATION);
  219. filtered_by_all_types = false;
  220. }
  221. if (!mCheckCallingcard->get())
  222. {
  223. filter &= ~(0x1 << LLInventoryType::IT_CALLINGCARD);
  224. filtered_by_all_types = false;
  225. }
  226. if (!mCheckClothing->get())
  227. {
  228. filter &= ~(0x1 << LLInventoryType::IT_WEARABLE);
  229. filtered_by_all_types = false;
  230. }
  231. if (!mCheckGesture->get())
  232. {
  233. filter &= ~(0x1 << LLInventoryType::IT_GESTURE);
  234. filtered_by_all_types = false;
  235. }
  236. if (!mCheckLandmark->get())
  237. {
  238. filter &= ~(0x1 << LLInventoryType::IT_LANDMARK);
  239. filtered_by_all_types = false;
  240. }
  241. if (mHasMaterial && !mCheckMaterial->get())
  242. {
  243. filter &= ~(0x1 << LLInventoryType::IT_MATERIAL);
  244. filtered_by_all_types = false;
  245. }
  246. if (!mCheckNotecard->get())
  247. {
  248. filter &= ~(0x1 << LLInventoryType::IT_NOTECARD);
  249. filtered_by_all_types = false;
  250. }
  251. if (!mCheckObject->get())
  252. {
  253. filter &= ~(0x1 << LLInventoryType::IT_OBJECT);
  254. filter &= ~(0x1 << LLInventoryType::IT_ATTACHMENT);
  255. filtered_by_all_types = false;
  256. }
  257. if (!mCheckScript->get())
  258. {
  259. filter &= ~(0x1 << LLInventoryType::IT_LSL);
  260. filtered_by_all_types = false;
  261. }
  262. if (!mCheckSound->get())
  263. {
  264. filter &= ~(0x1 << LLInventoryType::IT_SOUND);
  265. filtered_by_all_types = false;
  266. }
  267. if (!mCheckTexture->get())
  268. {
  269. filter &= ~(0x1 << LLInventoryType::IT_TEXTURE);
  270. filtered_by_all_types = false;
  271. }
  272. if (!mCheckSnapshot->get())
  273. {
  274. filter &= ~(0x1 << LLInventoryType::IT_SNAPSHOT);
  275. filtered_by_all_types = false;
  276. }
  277. #if LL_MESH_ASSET_SUPPORT
  278. if (!mCheckMesh->get())
  279. {
  280. filter &= ~(0x1 << LLInventoryType::IT_MESH);
  281. filtered_by_all_types = false;
  282. }
  283. #endif
  284. if (!mCheckSettings->get())
  285. {
  286. filter &= ~(0x1 << LLInventoryType::IT_SETTINGS);
  287. filtered_by_all_types = false;
  288. }
  289. if (!filtered_by_all_types)
  290. {
  291. // Do not include folders in filter, unless everything is selected
  292. filter &= ~(0x1 << LLInventoryType::IT_CATEGORY);
  293. }
  294. LLInventoryPanel* panelp = mInventoryView->mActivePanel;
  295. if (panelp)
  296. {
  297. // Update the panel, which will update the filter
  298. LLInventoryFilter::EFolderShow show =
  299. mCheckShowEmpty->get() ? LLInventoryFilter::SHOW_ALL_FOLDERS
  300. : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS;
  301. panelp->setShowFolderState(show);
  302. panelp->setFilterTypes(filter);
  303. bool since_logoff = mCheckSinceLogoff->get();
  304. if (since_logoff)
  305. {
  306. mSpinSinceDays->set(0);
  307. mSpinSinceHours->set(0);
  308. }
  309. U32 days = (U32)mSpinSinceDays->get();
  310. U32 hours = (U32)mSpinSinceHours->get();
  311. if (hours > 24)
  312. {
  313. days += hours / 24;
  314. hours = (U32)hours % 24;
  315. mSpinSinceDays->set((F32)days);
  316. mSpinSinceHours->set((F32)hours);
  317. }
  318. hours += days * 24;
  319. panelp->setHoursAgo(hours);
  320. panelp->setSinceLogoff(since_logoff);
  321. }
  322. mInventoryView->setFilterTextFromFilter();
  323. LLFloater::draw();
  324. }
  325. void LLFloaterInventoryFilters::onClose(bool app_quitting)
  326. {
  327. if (mInventoryView)
  328. {
  329. mInventoryView->getControl("Inventory.ShowFilters")->setValue(false);
  330. }
  331. destroy();
  332. }
  333. void LLFloaterInventoryFilters::onCloseBtn(void* userdata)
  334. {
  335. LLFloaterInventoryFilters* self = (LLFloaterInventoryFilters*)userdata;
  336. if (self)
  337. {
  338. self->close();
  339. }
  340. }
  341. //static
  342. void LLFloaterInventoryFilters::selectAllTypes(void* userdata)
  343. {
  344. LLFloaterInventoryFilters* self = (LLFloaterInventoryFilters*)userdata;
  345. if (!self) return;
  346. self->mCheckAnimation->set(true);
  347. self->mCheckCallingcard->set(true);
  348. self->mCheckClothing->set(true);
  349. self->mCheckGesture->set(true);
  350. self->mCheckLandmark->set(true);
  351. self->mCheckMaterial->set(self->mHasMaterial);
  352. self->mCheckNotecard->set(true);
  353. self->mCheckObject->set(true);
  354. self->mCheckScript->set(true);
  355. self->mCheckSound->set(true);
  356. self->mCheckTexture->set(true);
  357. self->mCheckSnapshot->set(true);
  358. #if LL_MESH_ASSET_SUPPORT
  359. self->mCheckMesh->set(true);
  360. #endif
  361. self->mCheckSettings->set(true);
  362. }
  363. //static
  364. void LLFloaterInventoryFilters::selectNoTypes(void* userdata)
  365. {
  366. LLFloaterInventoryFilters* self = (LLFloaterInventoryFilters*)userdata;
  367. if (!self) return;
  368. self->mCheckAnimation->set(false);
  369. self->mCheckCallingcard->set(false);
  370. self->mCheckClothing->set(false);
  371. self->mCheckGesture->set(false);
  372. self->mCheckLandmark->set(false);
  373. self->mCheckMaterial->set(false);
  374. self->mCheckNotecard->set(false);
  375. self->mCheckObject->set(false);
  376. self->mCheckScript->set(false);
  377. self->mCheckSound->set(false);
  378. self->mCheckTexture->set(false);
  379. self->mCheckSnapshot->set(false);
  380. #if LL_MESH_ASSET_SUPPORT
  381. self->mCheckMesh->set(false);
  382. #endif
  383. self->mCheckSettings->set(false);
  384. }
  385. ///----------------------------------------------------------------------------
  386. /// Helper classes for LLFloaterInventory
  387. ///----------------------------------------------------------------------------
  388. void LLSaveFolderState::setApply(bool apply)
  389. {
  390. mApply = apply;
  391. // Before generating new list of open folders, clear the old one
  392. if (!apply)
  393. {
  394. clearOpenFolders();
  395. }
  396. }
  397. void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)
  398. {
  399. if (!folder) return; // Paranoia
  400. if (mApply)
  401. {
  402. // We are applying the open state
  403. LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
  404. if (!bridge) return;
  405. const LLUUID& id = bridge->getUUID();
  406. if (mOpenFolders.find(id) != mOpenFolders.end())
  407. {
  408. folder->setOpen(true);
  409. }
  410. else if (!folder->isSelected())
  411. {
  412. // Keep selected filter in its current state, this is less jarring
  413. // to user
  414. folder->setOpen(false);
  415. }
  416. }
  417. else if (folder->isOpen())
  418. {
  419. // We are recording state at this point
  420. LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
  421. if (bridge)
  422. {
  423. mOpenFolders.emplace(bridge->getUUID());
  424. }
  425. }
  426. }
  427. void LLOpenFilteredFolders::doItem(LLFolderViewItem* item)
  428. {
  429. if (item && item->getFiltered())
  430. {
  431. LLFolderViewFolder* parentp = item->getParentFolder();
  432. if (parentp)
  433. {
  434. parentp->setOpenArrangeRecursively(true,
  435. LLFolderViewFolder::RECURSE_UP);
  436. }
  437. }
  438. }
  439. void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder)
  440. {
  441. if (!folder) return; // Paranoia
  442. LLFolderViewFolder* parentp = folder->getParentFolder();
  443. if (parentp && folder->getFiltered())
  444. {
  445. parentp->setOpenArrangeRecursively(true,
  446. LLFolderViewFolder::RECURSE_UP);
  447. }
  448. // If this folder did not pass the filter, and none of its descendants did
  449. else if (!folder->getFiltered() && !folder->hasFilteredDescendants())
  450. {
  451. folder->setOpenArrangeRecursively(false,
  452. LLFolderViewFolder::RECURSE_NO);
  453. }
  454. }
  455. void LLOpenFoldersWithSelection::doItem(LLFolderViewItem* item)
  456. {
  457. if (item && item->getParentFolder() && item->isSelected())
  458. {
  459. LLFolderViewFolder* parentp = item->getParentFolder();
  460. if (parentp)
  461. {
  462. parentp->setOpenArrangeRecursively(true,
  463. LLFolderViewFolder::RECURSE_UP);
  464. }
  465. }
  466. }
  467. void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder)
  468. {
  469. if (folder && folder->getParentFolder() && folder->isSelected())
  470. {
  471. LLFolderViewFolder* parentp = folder->getParentFolder();
  472. if (parentp)
  473. {
  474. parentp->setOpenArrangeRecursively(true,
  475. LLFolderViewFolder::RECURSE_UP);
  476. }
  477. }
  478. }
  479. ///----------------------------------------------------------------------------
  480. /// LLFloaterInventory
  481. ///----------------------------------------------------------------------------
  482. // Default constructor
  483. LLFloaterInventory::LLFloaterInventory(const std::string& name,
  484. const std::string& rect,
  485. LLInventoryModel* modelp)
  486. : LLFloater(name, rect, "Inventory", RESIZE_YES, INV_MIN_WIDTH,
  487. INV_MIN_HEIGHT, DRAG_ON_TOP, MINIMIZE_NO, CLOSE_YES),
  488. mActivePanel(NULL)
  489. // LLHandle<LLFloater> mInvFiltersHandle takes care of its own
  490. // initialization
  491. {
  492. init(modelp);
  493. }
  494. LLFloaterInventory::LLFloaterInventory(const std::string& name,
  495. const LLRect& rect,
  496. LLInventoryModel* modelp)
  497. : LLFloater(name, rect, "Inventory", RESIZE_YES, INV_MIN_WIDTH,
  498. INV_MIN_HEIGHT, DRAG_ON_TOP, MINIMIZE_NO, CLOSE_YES),
  499. mActivePanel(NULL)
  500. // LLHandle<LLFloater> mInvFiltersHandle takes care of its own
  501. // initialization
  502. {
  503. init(modelp);
  504. setRect(rect); // Override XML
  505. }
  506. void LLFloaterInventory::init(LLInventoryModel* modelp)
  507. {
  508. mLastCount = 0;
  509. // Callbacks
  510. init_inventory_actions(this);
  511. // Controls
  512. addBoolControl("Inventory.ShowFilters", false);
  513. addBoolControl("Inventory.SortByName", false);
  514. addBoolControl("Inventory.SortByDate", true);
  515. addBoolControl("Inventory.FoldersAlwaysByName", true);
  516. addBoolControl("Inventory.SystemFoldersToTop", true);
  517. updateSortControls();
  518. addBoolControl("Inventory.SearchName", true);
  519. addBoolControl("Inventory.SearchDesc", false);
  520. addBoolControl("Inventory.SearchCreator", false);
  521. LLUICtrlFactory::getInstance()->buildFloater(this,
  522. "floater_inventory.xml");
  523. // Now load the stored settings from disk, if available.
  524. std::ostringstream filter_sream;
  525. filter_sream << gDirUtil.getFullPath(LL_PATH_PER_ACCOUNT, "filters.xml");
  526. llifstream file(filter_sream.str().c_str());
  527. if (file.is_open())
  528. {
  529. llinfos << "Reading filters settings from " << filter_sream.str()
  530. << llendl;
  531. LLSD saved_filter_state;
  532. LLSDSerialize::fromXML(saved_filter_state, file);
  533. file.close();
  534. // Load the persistent "Recent Items" settings. Note that the "All
  535. // Items" and "Worn Items" settings do not persist per-account.
  536. if (mRecentPanel &&
  537. saved_filter_state.has(mRecentPanel->getFilter()->getName()))
  538. {
  539. LLSD recent_items =
  540. saved_filter_state.get(mRecentPanel->getFilter()->getName());
  541. mRecentPanel->getFilter()->fromLLSD(recent_items);
  542. }
  543. }
  544. sActiveViews.push_back(this);
  545. gInventory.addObserver(this);
  546. // *HACK: make sure everything is fetched (especially thumbnails for
  547. // folders parented to the root). HB
  548. LLInventoryModelFetch::forceFetchFolder(modelp->getRootFolderID());
  549. }
  550. bool LLFloaterInventory::postBuild()
  551. {
  552. mSavedFolderState = new LLSaveFolderState();
  553. mSavedFolderState->setApply(false);
  554. mFilterTabs = getChild<LLTabContainer>("inventory filter tabs");
  555. U32 default_sort_order = gSavedSettings.getU32("InventorySortOrder");
  556. // Set up the default inv. panel/filter settings.
  557. mEverythingPanel = getChild<LLInventoryPanel>("All Items");
  558. mEverythingPanel->setSortOrder(default_sort_order);
  559. mEverythingPanel->getFilter()->markDefault();
  560. mEverythingPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
  561. mEverythingPanel->setSelectCallback(onSelectionChange, mEverythingPanel);
  562. mFilterTabs->setTabChangeCallback(mEverythingPanel, onFilterSelected);
  563. mFilterTabs->setTabUserData(mEverythingPanel, this);
  564. mActivePanel = mEverythingPanel;
  565. mRecentPanel = getChild<LLInventoryPanel>("Recent Items", true, false);
  566. if (mRecentPanel)
  567. {
  568. U32 sort_order = gSavedSettings.getU32("RecentItemsSortOrder");
  569. mRecentPanel->setSinceLogoff(true);
  570. mRecentPanel->setSortOrder(sort_order);
  571. mRecentPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
  572. mRecentPanel->getFilter()->markDefault();
  573. mRecentPanel->setSelectCallback(onSelectionChange, mRecentPanel);
  574. mFilterTabs->setTabChangeCallback(mRecentPanel, onFilterSelected);
  575. mFilterTabs->setTabUserData(mRecentPanel, this);
  576. }
  577. mWornPanel = getChild<LLInventoryPanel>("Worn Items", true, false);
  578. if (mWornPanel)
  579. {
  580. U32 sort_order = gSavedSettings.getU32("WornItemsSortOrder");
  581. mWornPanel->setSortOrder(sort_order);
  582. mWornPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
  583. mWornPanel->getFilter()->markDefault();
  584. mWornPanel->setFilterWorn(true);
  585. mWornPanel->setSelectCallback(onSelectionChange, mWornPanel);
  586. mFilterTabs->setTabChangeCallback(mWornPanel, onFilterSelected);
  587. mFilterTabs->setTabUserData(mWornPanel, this);
  588. }
  589. mLastOpenPanel = getChild<LLInventoryPanel>("Last Open", true, false);
  590. if (mLastOpenPanel)
  591. {
  592. mLastOpenPanel->setSortOrder(default_sort_order);
  593. mLastOpenPanel->getFilter()->markDefault();
  594. mLastOpenPanel->setFilterLastOpen(true);
  595. mLastOpenPanel->setFilterShowLinks(true);
  596. mLastOpenPanel->setSelectCallback(onSelectionChange, mLastOpenPanel);
  597. mFilterTabs->setTabChangeCallback(mLastOpenPanel, onFilterSelected);
  598. mFilterTabs->setTabUserData(mLastOpenPanel, this);
  599. }
  600. mSearchEditor = getChild<LLSearchEditor>("inventory search editor");
  601. mSearchEditor->setSearchCallback(onSearchEdit, this);
  602. mLockLastOpenCheck = getChild<LLCheckBoxCtrl>("lock_last_open");
  603. mLockLastOpenCheck->setCommitCallback(onCommitLockLastOpenCheck);
  604. mLockLastOpenCheck->setCallbackUserData(this);
  605. mLockLastOpenCheck->setVisible(false);
  606. mNewSettingsMenuItem = getChild<LLView>("New Settings");
  607. mNewMaterialMenuItem = getChild<LLView>("New Material");
  608. return true;
  609. }
  610. // Destroys the object
  611. LLFloaterInventory::~LLFloaterInventory()
  612. {
  613. // Save the filters state.
  614. LLInventoryFilter* filter = mEverythingPanel->getFilter();
  615. LLSD filter_state;
  616. filter->toLLSD(filter_state);
  617. LLSD filter_root;
  618. filter_root[filter->getName()] = filter_state;
  619. if (mRecentPanel)
  620. {
  621. LLInventoryFilter* filter = mRecentPanel->getFilter();
  622. LLSD filter_state;
  623. filter->toLLSD(filter_state);
  624. filter_root[filter->getName()] = filter_state;
  625. }
  626. if (mWornPanel)
  627. {
  628. LLInventoryFilter* filter = mWornPanel->getFilter();
  629. LLSD filter_state;
  630. filter->toLLSD(filter_state);
  631. filter_root[filter->getName()] = filter_state;
  632. }
  633. if (mLastOpenPanel)
  634. {
  635. LLInventoryFilter* filter = mLastOpenPanel->getFilter();
  636. LLSD filter_state;
  637. filter->toLLSD(filter_state);
  638. filter_root[filter->getName()] = filter_state;
  639. }
  640. std::ostringstream filter_sream;
  641. filter_sream << gDirUtil.getFullPath(LL_PATH_PER_ACCOUNT, "filters.xml");
  642. llofstream filters_file(filter_sream.str().c_str());
  643. if (!filters_file.is_open() ||
  644. !LLSDSerialize::toPrettyXML(filter_root, filters_file))
  645. {
  646. llwarns << "Could not write to filters save file "
  647. << filter_sream.str() << llendl;
  648. }
  649. else
  650. {
  651. filters_file.close();
  652. }
  653. std::vector<LLFloaterInventory*>::iterator end = sActiveViews.end();
  654. std::vector<LLFloaterInventory*>::iterator it =
  655. std::find(sActiveViews.begin(), end, this);
  656. if (it != end)
  657. {
  658. sActiveViews.erase(it);
  659. }
  660. gInventory.removeObserver(this);
  661. delete mSavedFolderState;
  662. }
  663. void LLFloaterInventory::draw()
  664. {
  665. //MK
  666. if (gRLenabled && gRLInterface.mContainsShowinv)
  667. {
  668. setVisible(false);
  669. return;
  670. }
  671. //mk
  672. if (LLInventoryModelFetch::getInstance()->isEverythingFetched())
  673. {
  674. if (mLastCount != gInventory.getItemCount())
  675. {
  676. mLastCount = gInventory.getItemCount();
  677. mLastCountString.clear();
  678. LLLocale locale(LLLocale::USER_LOCALE);
  679. LLLocale::getIntegerString(mLastCountString, mLastCount);
  680. }
  681. setTitle("Inventory (" + mLastCountString + " items)" + mFilterText);
  682. }
  683. if (mActivePanel)
  684. {
  685. mSearchEditor->setText(mActivePanel->getFilterSubString());
  686. LLMarketplace::updateAllCounts();
  687. }
  688. // Enable/disable inventory items creation menu entries depending on
  689. // available features in the agent region. HB
  690. mNewSettingsMenuItem->setEnabled(gAgent.hasInventorySettings());
  691. mNewMaterialMenuItem->setEnabled(gAgent.hasInventoryMaterial());
  692. LLFloater::draw();
  693. }
  694. void LLFloaterInventory::startSearch()
  695. {
  696. // This forces focus to line editor portion of search editor
  697. mSearchEditor->focusFirstItem(true);
  698. }
  699. //virtual
  700. void LLFloaterInventory::setVisible(bool visible)
  701. {
  702. gSavedSettings.setBool("ShowInventory", visible);
  703. LLFloater::setVisible(visible);
  704. if (visible && LLStartUp::isLoggedIn())
  705. {
  706. static bool warn = true;
  707. // Verify that the Marketplace is initialized.
  708. LLMarketplace::setup(warn);
  709. warn = false; // Warn only once per session
  710. }
  711. }
  712. //virtual
  713. void LLFloaterInventory::onClose(bool app_quitting)
  714. {
  715. if (sActiveViews.size() > 1)
  716. {
  717. destroy();
  718. return;
  719. }
  720. if (!app_quitting)
  721. {
  722. gSavedSettings.setBool("ShowInventory", false);
  723. }
  724. // Clear filters, but save user's folder state first
  725. if (mActivePanel && !mActivePanel->getRootFolder()->isFilterModified())
  726. {
  727. mSavedFolderState->setApply(false);
  728. mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
  729. }
  730. #if 0
  731. onClearSearch(this);
  732. #endif
  733. // Close the temporary thumbnail view floater, if open.
  734. HBFloaterThumbnail::hideInstance();
  735. // Pass up
  736. LLFloater::setVisible(false);
  737. }
  738. bool LLFloaterInventory::handleKeyHere(KEY key, MASK mask)
  739. {
  740. LLFolderView* root_folder = mActivePanel ? mActivePanel->getRootFolder()
  741. : NULL;
  742. if (root_folder)
  743. {
  744. // First check for user accepting current search results
  745. if (mSearchEditor->hasFocus() && mask == MASK_NONE &&
  746. (key == KEY_RETURN || key == KEY_DOWN))
  747. {
  748. // Move focus to inventory proper
  749. root_folder->setFocus(true);
  750. root_folder->scrollToShowSelection();
  751. return true;
  752. }
  753. if (root_folder->hasFocus() && key == KEY_UP)
  754. {
  755. startSearch();
  756. }
  757. }
  758. return LLFloater::handleKeyHere(key, mask);
  759. }
  760. void LLFloaterInventory::changed(U32 mask)
  761. {
  762. std::ostringstream title;
  763. title << "Inventory";
  764. if (LLInventoryModelFetch::getInstance()->backgroundFetchActive())
  765. {
  766. LLLocale locale(LLLocale::USER_LOCALE);
  767. std::string item_count_string;
  768. LLLocale::getIntegerString(item_count_string,
  769. gInventory.getItemCount());
  770. title << " (Fetched " << item_count_string << " items...)";
  771. }
  772. title << mFilterText;
  773. setTitle(title.str());
  774. }
  775. //static
  776. LLFloaterInventory* LLFloaterInventory::showAgentInventory()
  777. {
  778. if (gDisconnected)
  779. {
  780. return NULL;
  781. }
  782. //MK
  783. if (gRLenabled && gRLInterface.mContainsShowinv)
  784. {
  785. return NULL;
  786. }
  787. //mk
  788. LLFloaterInventory* inv = LLFloaterInventory::getActiveFloater();
  789. if (!inv && !gAgent.cameraMouselook())
  790. {
  791. // Create one.
  792. inv = new LLFloaterInventory("Inventory", "FloaterInventoryRect",
  793. &gInventory);
  794. inv->open();
  795. // Keep on screen
  796. gFloaterViewp->adjustToFitScreen(inv);
  797. gSavedSettings.setBool("ShowInventory", true);
  798. }
  799. if (inv)
  800. {
  801. // Make sure it is in front and it makes a noise
  802. inv->setTitle("Inventory");
  803. inv->open();
  804. }
  805. return inv;
  806. }
  807. //static
  808. LLFloaterInventory* LLFloaterInventory::getActiveFloater()
  809. {
  810. LLFloaterInventory* self = NULL;
  811. S32 count = sActiveViews.size();
  812. if (count > 0)
  813. {
  814. self = sActiveViews[0];
  815. S32 z_order = gFloaterViewp->getZOrder(self);
  816. S32 z_next = 0;
  817. for (S32 i = 1; i < count; ++i)
  818. {
  819. LLFloaterInventory* next_invp = sActiveViews[i];
  820. z_next = gFloaterViewp->getZOrder(next_invp);
  821. if (z_next < z_order)
  822. {
  823. self = next_invp;
  824. z_order = z_next;
  825. }
  826. }
  827. }
  828. return self;
  829. }
  830. //static
  831. void LLFloaterInventory::toggleVisibility(void*)
  832. {
  833. //MK
  834. if (gRLenabled && gRLInterface.mContainsShowinv)
  835. {
  836. return;
  837. }
  838. //mk
  839. S32 count = sActiveViews.size();
  840. if (count == 0)
  841. {
  842. showAgentInventory();
  843. }
  844. else if (count == 1)
  845. {
  846. if (sActiveViews[0]->getVisible())
  847. {
  848. sActiveViews[0]->close();
  849. gSavedSettings.setBool("ShowInventory", false);
  850. }
  851. else
  852. {
  853. showAgentInventory();
  854. }
  855. }
  856. else
  857. {
  858. // With more than one open, we know at least one is visible. Close the
  859. // last spawned one.
  860. sActiveViews.back()->close();
  861. }
  862. }
  863. //static
  864. void LLFloaterInventory::cleanup()
  865. {
  866. for (S32 i = 0, count = sActiveViews.size(); i < count; ++i)
  867. {
  868. sActiveViews[i]->destroy();
  869. }
  870. }
  871. //static
  872. void LLFloaterInventory::onCommitLockLastOpenCheck(LLUICtrl* ctrl,
  873. void* userdata)
  874. {
  875. LLFloaterInventory* self = (LLFloaterInventory*)userdata;
  876. LLCheckBoxCtrl* check = (LLCheckBoxCtrl*)ctrl;
  877. if (self && check)
  878. {
  879. bool locked = check->get();
  880. self->mEverythingPanel->setLastOpenLocked(locked);
  881. self->mRecentPanel->setLastOpenLocked(locked);
  882. self->mWornPanel->setLastOpenLocked(locked);
  883. self->mLastOpenPanel->setLastOpenLocked(locked);
  884. }
  885. }
  886. void LLFloaterInventory::setFilterTextFromFilter()
  887. {
  888. mFilterText = mActivePanel->getFilter()->getFilterText();
  889. }
  890. const std::string LLFloaterInventory::getFilterSubString()
  891. {
  892. return mActivePanel->getFilterSubString();
  893. }
  894. void LLFloaterInventory::setFilterSubString(const std::string& string)
  895. {
  896. mActivePanel->setFilterSubString(string);
  897. }
  898. void LLFloaterInventory::toggleFindOptions()
  899. {
  900. LLFloater* floaterp = getInvFilters();
  901. if (floaterp)
  902. {
  903. floaterp->close();
  904. mControls["Inventory.ShowFilters"]->setValue(false);
  905. return;
  906. }
  907. LLRect rect(getRect().mLeft - INV_FINDER_WIDTH, getRect().mTop,
  908. getRect().mLeft, getRect().mTop - INV_FINDER_HEIGHT);
  909. LLFloaterInventoryFilters* filtersp =
  910. new LLFloaterInventoryFilters("Inventory Finder", rect, this);
  911. mInvFiltersHandle = filtersp->getHandle();
  912. filtersp->open();
  913. addDependentFloater(mInvFiltersHandle);
  914. mControls["Inventory.ShowFilters"]->setValue(true);
  915. }
  916. void LLFloaterInventory::updateSortControls()
  917. {
  918. U32 order = mActivePanel ? mActivePanel->getSortOrder()
  919. : gSavedSettings.getU32("InventorySortOrder");
  920. bool sort_by_date = order & LLInventoryFilter::SO_DATE;
  921. bool folders_by_name = order & LLInventoryFilter::SO_FOLDERS_BY_NAME;
  922. bool sys_folders_on_top = order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
  923. getControl("Inventory.SortByDate")->setValue(sort_by_date);
  924. getControl("Inventory.SortByName")->setValue(!sort_by_date);
  925. getControl("Inventory.FoldersAlwaysByName")->setValue(folders_by_name);
  926. getControl("Inventory.SystemFoldersToTop")->setValue(sys_folders_on_top);
  927. }
  928. //static
  929. void LLFloaterInventory::onClearSearch(void* userdata)
  930. {
  931. LLFloaterInventory* self = (LLFloaterInventory*)userdata;
  932. if (!self) return;
  933. LLInventoryPanel* panelp = self->mActivePanel;
  934. if (panelp)
  935. {
  936. panelp->setFilterSubString(LLStringUtil::null);
  937. panelp->setFilterTypes(0xffffffff);
  938. }
  939. LLFloater* filters = self->getInvFilters();
  940. if (filters)
  941. {
  942. LLFloaterInventoryFilters::selectAllTypes(filters);
  943. }
  944. // Re-open folders that were initially open
  945. if (panelp)
  946. {
  947. self->mSavedFolderState->setApply(true);
  948. panelp->getRootFolder()->applyFunctorRecursively(*self->mSavedFolderState);
  949. LLOpenFoldersWithSelection opener;
  950. panelp->getRootFolder()->applyFunctorRecursively(opener);
  951. panelp->getRootFolder()->scrollToShowSelection();
  952. }
  953. }
  954. //static
  955. void LLFloaterInventory::onSearchEdit(const std::string& search_string,
  956. void* userdata)
  957. {
  958. LLFloaterInventory* self = (LLFloaterInventory*)userdata;
  959. if (!self)
  960. {
  961. return;
  962. }
  963. if (search_string.empty())
  964. {
  965. onClearSearch(userdata);
  966. }
  967. LLInventoryPanel* panelp = self->mActivePanel;
  968. if (!panelp)
  969. {
  970. return;
  971. }
  972. std::string filter_text = search_string;
  973. std::string uc_search_string = filter_text;
  974. LLStringUtil::toUpper(uc_search_string);
  975. if (panelp->getFilterSubString().empty() && uc_search_string.empty())
  976. {
  977. // Current filter and new filter empty, do nothing
  978. return;
  979. }
  980. // Save current folder open state if no filter currently applied
  981. if (!panelp->getRootFolder()->isFilterModified())
  982. {
  983. self->mSavedFolderState->setApply(false);
  984. panelp->getRootFolder()->applyFunctorRecursively(*self->mSavedFolderState);
  985. }
  986. // Set new filter string
  987. panelp->setFilterSubString(uc_search_string);
  988. }
  989. //static
  990. void LLFloaterInventory::onFilterSelected(void* userdata, bool)
  991. {
  992. LLFloaterInventory* self = (LLFloaterInventory*)userdata;
  993. if (!self)
  994. {
  995. return;
  996. }
  997. // Find my index
  998. LLInventoryPanel* panel =
  999. (LLInventoryPanel*)self->mFilterTabs->getCurrentPanel();
  1000. self->mActivePanel = panel;
  1001. if (!panel)
  1002. {
  1003. return;
  1004. }
  1005. LLInventoryFilter* filter = panel->getFilter();
  1006. if (filter)
  1007. {
  1008. if (filter->isActive())
  1009. {
  1010. // If our filter is active we may be the first thing requiring a
  1011. // fetch in this folder, so we better start it here.
  1012. const LLFolderViewEventListener* listener =
  1013. panel->getRootFolder()->getListener();
  1014. if (listener)
  1015. {
  1016. const LLUUID& cat_id = listener->getUUID();
  1017. LLInventoryModelFetch::getInstance()->start(cat_id);
  1018. }
  1019. }
  1020. bool is_last_open = panel == self->mLastOpenPanel;
  1021. if (is_last_open && panel->makeLastOpenCurrent())
  1022. {
  1023. // Force a refresh of the Last Open tab
  1024. filter->setLastOpenID(panel->getLastOpenID());
  1025. filter->setModified();
  1026. }
  1027. self->mLockLastOpenCheck->setVisible(is_last_open);
  1028. LLFloaterInventoryFilters* filters = self->getInvFilters();
  1029. if (filters)
  1030. {
  1031. filters->changeFilter(filter);
  1032. }
  1033. }
  1034. self->setFilterTextFromFilter();
  1035. self->updateSortControls();
  1036. }
  1037. //static
  1038. void LLFloaterInventory::onSelectionChange(LLFolderView* folderp, bool, void*)
  1039. {
  1040. // If auto-selecting a new user-created asset and preparing to rename
  1041. if (folderp && folderp->needsAutoRename())
  1042. {
  1043. folderp->setNeedsAutoRename(false);
  1044. if (folderp->getSelectedItems().size())
  1045. {
  1046. // New asset is visible and selected
  1047. folderp->startRenamingSelectedItem();
  1048. }
  1049. }
  1050. }
  1051. bool LLFloaterInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop,
  1052. EDragAndDropType cargo_type,
  1053. void* cargo_data,
  1054. EAcceptance* accept,
  1055. std::string& tooltip_msg)
  1056. {
  1057. // Check to see if we are auto scrolling from the last frame
  1058. LLInventoryPanel* panel = (LLInventoryPanel*)getActivePanel();
  1059. if (mFilterTabs && panel && panel->getScrollableContainer())
  1060. {
  1061. if (panel->getScrollableContainer()->needsToScroll(x, y,
  1062. LLScrollableContainer::VERTICAL))
  1063. {
  1064. mFilterTabs->startDragAndDropDelayTimer();
  1065. }
  1066. }
  1067. return LLFloater::handleDragAndDrop(x, y, mask, drop, cargo_type,
  1068. cargo_data, accept, tooltip_msg);
  1069. }