PageRenderTime 77ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llpreview.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 523 lines | 408 code | 56 blank | 59 comment | 74 complexity | 0f34c756c996692109ffd37ce9d81101 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llpreview.cpp
  3. * @brief LLPreview class implementation
  4. *
  5. * $LicenseInfo:firstyear=2002&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 "stdenums.h"
  28. #include "llpreview.h"
  29. #include "lllineeditor.h"
  30. #include "llinventorydefines.h"
  31. #include "llinventorymodel.h"
  32. #include "llresmgr.h"
  33. #include "lltextbox.h"
  34. #include "llfloaterreg.h"
  35. #include "llfocusmgr.h"
  36. #include "lltooldraganddrop.h"
  37. #include "llradiogroup.h"
  38. #include "llassetstorage.h"
  39. #include "llviewerassettype.h"
  40. #include "llviewerobject.h"
  41. #include "llviewerobjectlist.h"
  42. #include "lldbstrings.h"
  43. #include "llagent.h"
  44. #include "llvoavatarself.h"
  45. #include "llselectmgr.h"
  46. #include "llviewerinventory.h"
  47. #include "llviewerwindow.h"
  48. #include "lltrans.h"
  49. // Constants
  50. LLPreview::LLPreview(const LLSD& key)
  51. : LLFloater(key),
  52. mItemUUID(key.asUUID()),
  53. mObjectUUID(), // set later by setObjectID()
  54. mCopyToInvBtn( NULL ),
  55. mForceClose(FALSE),
  56. mUserResized(FALSE),
  57. mCloseAfterSave(FALSE),
  58. mAssetStatus(PREVIEW_ASSET_UNLOADED),
  59. mDirty(TRUE)
  60. {
  61. mAuxItem = new LLInventoryItem;
  62. // don't necessarily steal focus on creation -- sometimes these guys pop up without user action
  63. setAutoFocus(FALSE);
  64. gInventory.addObserver(this);
  65. refreshFromItem();
  66. }
  67. BOOL LLPreview::postBuild()
  68. {
  69. refreshFromItem();
  70. return TRUE;
  71. }
  72. LLPreview::~LLPreview()
  73. {
  74. gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
  75. gInventory.removeObserver(this);
  76. }
  77. void LLPreview::setObjectID(const LLUUID& object_id)
  78. {
  79. mObjectUUID = object_id;
  80. if (getAssetStatus() == PREVIEW_ASSET_UNLOADED)
  81. {
  82. loadAsset();
  83. }
  84. }
  85. void LLPreview::setItem( LLInventoryItem* item )
  86. {
  87. mItem = item;
  88. if (mItem && getAssetStatus() == PREVIEW_ASSET_UNLOADED)
  89. {
  90. loadAsset();
  91. }
  92. }
  93. const LLInventoryItem *LLPreview::getItem() const
  94. {
  95. const LLInventoryItem *item = NULL;
  96. if (mItem.notNull())
  97. {
  98. item = mItem;
  99. }
  100. else if (mObjectUUID.isNull())
  101. {
  102. // it's an inventory item, so get the item.
  103. item = gInventory.getItem(mItemUUID);
  104. }
  105. else
  106. {
  107. // it's an object's inventory item.
  108. LLViewerObject* object = gObjectList.findObject(mObjectUUID);
  109. if(object)
  110. {
  111. item = dynamic_cast<LLInventoryItem*>(object->getInventoryObject(mItemUUID));
  112. }
  113. }
  114. return item;
  115. }
  116. // Sub-classes should override this function if they allow editing
  117. void LLPreview::onCommit()
  118. {
  119. const LLViewerInventoryItem *item = dynamic_cast<const LLViewerInventoryItem*>(getItem());
  120. if(item)
  121. {
  122. if (!item->isFinished())
  123. {
  124. // We are attempting to save an item that was never loaded
  125. llwarns << "LLPreview::onCommit() called with mIsComplete == FALSE"
  126. << " Type: " << item->getType()
  127. << " ID: " << item->getUUID()
  128. << llendl;
  129. return;
  130. }
  131. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
  132. new_item->setDescription(getChild<LLUICtrl>("desc")->getValue().asString());
  133. std::string new_name = getChild<LLUICtrl>("name")->getValue().asString();
  134. if ( (new_item->getName() != new_name) && !new_name.empty())
  135. {
  136. new_item->rename(getChild<LLUICtrl>("name")->getValue().asString());
  137. }
  138. if(mObjectUUID.notNull())
  139. {
  140. // must be in an object
  141. LLViewerObject* object = gObjectList.findObject(mObjectUUID);
  142. if(object)
  143. {
  144. object->updateInventory(
  145. new_item,
  146. TASK_INVENTORY_ITEM_KEY,
  147. false);
  148. }
  149. }
  150. else if(item->getPermissions().getOwner() == gAgent.getID())
  151. {
  152. new_item->updateServer(FALSE);
  153. gInventory.updateItem(new_item);
  154. gInventory.notifyObservers();
  155. // If the item is an attachment that is currently being worn,
  156. // update the object itself.
  157. if( item->getType() == LLAssetType::AT_OBJECT )
  158. {
  159. if (isAgentAvatarValid())
  160. {
  161. LLViewerObject* obj = gAgentAvatarp->getWornAttachment( item->getUUID() );
  162. if( obj )
  163. {
  164. LLSelectMgr::getInstance()->deselectAll();
  165. LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE );
  166. LLSelectMgr::getInstance()->selectionSetObjectDescription( getChild<LLUICtrl>("desc")->getValue().asString() );
  167. LLSelectMgr::getInstance()->deselectAll();
  168. }
  169. }
  170. }
  171. }
  172. }
  173. }
  174. void LLPreview::changed(U32 mask)
  175. {
  176. mDirty = TRUE;
  177. }
  178. void LLPreview::setNotecardInfo(const LLUUID& notecard_inv_id,
  179. const LLUUID& object_id)
  180. {
  181. mNotecardInventoryID = notecard_inv_id;
  182. mNotecardObjectID = object_id;
  183. }
  184. void LLPreview::draw()
  185. {
  186. LLFloater::draw();
  187. if (mDirty)
  188. {
  189. mDirty = FALSE;
  190. refreshFromItem();
  191. }
  192. }
  193. void LLPreview::refreshFromItem()
  194. {
  195. const LLInventoryItem* item = getItem();
  196. if (!item)
  197. {
  198. return;
  199. }
  200. if (hasString("Title"))
  201. {
  202. LLStringUtil::format_map_t args;
  203. args["[NAME]"] = item->getName();
  204. LLUIString title = getString("Title", args);
  205. setTitle(title.getString());
  206. }
  207. getChild<LLUICtrl>("desc")->setValue(item->getDescription());
  208. BOOL can_agent_manipulate = item->getPermissions().allowModifyBy(gAgent.getID());
  209. getChildView("desc")->setEnabled(can_agent_manipulate);
  210. }
  211. // static
  212. void LLPreview::onText(LLUICtrl*, void* userdata)
  213. {
  214. LLPreview* self = (LLPreview*) userdata;
  215. self->onCommit();
  216. }
  217. // static
  218. void LLPreview::onRadio(LLUICtrl*, void* userdata)
  219. {
  220. LLPreview* self = (LLPreview*) userdata;
  221. self->onCommit();
  222. }
  223. // static
  224. void LLPreview::hide(const LLUUID& item_uuid, BOOL no_saving /* = FALSE */ )
  225. {
  226. LLFloater* floater = LLFloaterReg::findInstance("preview", LLSD(item_uuid));
  227. if (!floater) floater = LLFloaterReg::findInstance("preview_avatar", LLSD(item_uuid));
  228. LLPreview* preview = dynamic_cast<LLPreview*>(floater);
  229. if (preview)
  230. {
  231. if ( no_saving )
  232. {
  233. preview->mForceClose = TRUE;
  234. }
  235. preview->closeFloater();
  236. }
  237. }
  238. // static
  239. void LLPreview::dirty(const LLUUID& item_uuid)
  240. {
  241. LLFloater* floater = LLFloaterReg::findInstance("preview", LLSD(item_uuid));
  242. if (!floater) floater = LLFloaterReg::findInstance("preview_avatar", LLSD(item_uuid));
  243. LLPreview* preview = dynamic_cast<LLPreview*>(floater);
  244. if(preview)
  245. {
  246. preview->mDirty = TRUE;
  247. }
  248. }
  249. BOOL LLPreview::handleMouseDown(S32 x, S32 y, MASK mask)
  250. {
  251. if(mClientRect.pointInRect(x, y))
  252. {
  253. // No handler needed for focus lost since this class has no
  254. // state that depends on it.
  255. bringToFront(x, y);
  256. gFocusMgr.setMouseCapture(this);
  257. S32 screen_x;
  258. S32 screen_y;
  259. localPointToScreen(x, y, &screen_x, &screen_y );
  260. LLToolDragAndDrop::getInstance()->setDragStart(screen_x, screen_y);
  261. return TRUE;
  262. }
  263. return LLFloater::handleMouseDown(x, y, mask);
  264. }
  265. BOOL LLPreview::handleMouseUp(S32 x, S32 y, MASK mask)
  266. {
  267. if(hasMouseCapture())
  268. {
  269. gFocusMgr.setMouseCapture(NULL);
  270. return TRUE;
  271. }
  272. return LLFloater::handleMouseUp(x, y, mask);
  273. }
  274. BOOL LLPreview::handleHover(S32 x, S32 y, MASK mask)
  275. {
  276. if(hasMouseCapture())
  277. {
  278. S32 screen_x;
  279. S32 screen_y;
  280. const LLInventoryItem *item = getItem();
  281. localPointToScreen(x, y, &screen_x, &screen_y );
  282. if(item
  283. && item->getPermissions().allowCopyBy(gAgent.getID(),
  284. gAgent.getGroupID())
  285. && LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y))
  286. {
  287. EDragAndDropType type;
  288. type = LLViewerAssetType::lookupDragAndDropType(item->getType());
  289. LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_LIBRARY;
  290. if(!mObjectUUID.isNull())
  291. {
  292. src = LLToolDragAndDrop::SOURCE_WORLD;
  293. }
  294. else if(item->getPermissions().getOwner() == gAgent.getID())
  295. {
  296. src = LLToolDragAndDrop::SOURCE_AGENT;
  297. }
  298. LLToolDragAndDrop::getInstance()->beginDrag(type,
  299. item->getUUID(),
  300. src,
  301. mObjectUUID);
  302. return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask );
  303. }
  304. }
  305. return LLFloater::handleHover(x,y,mask);
  306. }
  307. void LLPreview::onOpen(const LLSD& key)
  308. {
  309. if (!getFloaterHost() && !getHost() && getAssetStatus() == PREVIEW_ASSET_UNLOADED)
  310. {
  311. loadAsset();
  312. }
  313. }
  314. void LLPreview::setAuxItem( const LLInventoryItem* item )
  315. {
  316. if ( mAuxItem )
  317. mAuxItem->copyItem(item);
  318. }
  319. // static
  320. void LLPreview::onBtnCopyToInv(void* userdata)
  321. {
  322. LLPreview* self = (LLPreview*) userdata;
  323. LLInventoryItem *item = self->mAuxItem;
  324. if(item && item->getUUID().notNull())
  325. {
  326. // Copy to inventory
  327. if (self->mNotecardInventoryID.notNull())
  328. {
  329. copy_inventory_from_notecard(LLUUID::null,
  330. self->mNotecardObjectID,
  331. self->mNotecardInventoryID,
  332. item);
  333. }
  334. else
  335. {
  336. LLPointer<LLInventoryCallback> cb = NULL;
  337. copy_inventory_item(
  338. gAgent.getID(),
  339. item->getPermissions().getOwner(),
  340. item->getUUID(),
  341. LLUUID::null,
  342. std::string(),
  343. cb);
  344. }
  345. }
  346. self->closeFloater();
  347. }
  348. // static
  349. void LLPreview::onKeepBtn(void* data)
  350. {
  351. LLPreview* self = (LLPreview*)data;
  352. self->closeFloater();
  353. }
  354. // static
  355. void LLPreview::onDiscardBtn(void* data)
  356. {
  357. LLPreview* self = (LLPreview*)data;
  358. const LLInventoryItem* item = self->getItem();
  359. if (!item) return;
  360. self->mForceClose = TRUE;
  361. self->closeFloater();
  362. // Delete the item entirely
  363. /*
  364. item->removeFromServer();
  365. gInventory.deleteObject(item->getUUID());
  366. gInventory.notifyObservers();
  367. */
  368. // Move the item to the trash
  369. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  370. if (item->getParentUUID() != trash_id)
  371. {
  372. LLInventoryModel::update_list_t update;
  373. LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
  374. update.push_back(old_folder);
  375. LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1);
  376. update.push_back(new_folder);
  377. gInventory.accountForUpdate(update);
  378. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
  379. new_item->setParent(trash_id);
  380. // no need to restamp it though it's a move into trash because
  381. // it's a brand new item already.
  382. new_item->updateParentOnServer(FALSE);
  383. gInventory.updateItem(new_item);
  384. gInventory.notifyObservers();
  385. }
  386. }
  387. void LLPreview::handleReshape(const LLRect& new_rect, bool by_user)
  388. {
  389. if(by_user
  390. && (new_rect.getWidth() != getRect().getWidth() || new_rect.getHeight() != getRect().getHeight()))
  391. {
  392. userResized();
  393. }
  394. LLFloater::handleReshape(new_rect, by_user);
  395. }
  396. //
  397. // LLMultiPreview
  398. //
  399. LLMultiPreview::LLMultiPreview()
  400. : LLMultiFloater(LLSD())
  401. {
  402. // start with a rect in the top-left corner ; will get resized
  403. LLRect rect;
  404. rect.setLeftTopAndSize(0, gViewerWindow->getWindowHeightScaled(), 200, 400);
  405. setRect(rect);
  406. LLFloater* last_floater = LLFloaterReg::getLastFloaterInGroup("preview");
  407. if (last_floater)
  408. {
  409. stackWith(*last_floater);
  410. }
  411. setTitle(LLTrans::getString("MultiPreviewTitle"));
  412. buildTabContainer();
  413. setCanResize(TRUE);
  414. mAutoResize = FALSE;
  415. }
  416. void LLMultiPreview::onOpen(const LLSD& key)
  417. {
  418. LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel();
  419. if (frontmost_preview && frontmost_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED)
  420. {
  421. frontmost_preview->loadAsset();
  422. }
  423. LLMultiFloater::onOpen(key);
  424. }
  425. void LLMultiPreview::handleReshape(const LLRect& new_rect, bool by_user)
  426. {
  427. if(new_rect.getWidth() != getRect().getWidth() || new_rect.getHeight() != getRect().getHeight())
  428. {
  429. LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel();
  430. if (frontmost_preview) frontmost_preview->userResized();
  431. }
  432. LLFloater::handleReshape(new_rect, by_user);
  433. }
  434. void LLMultiPreview::tabOpen(LLFloater* opened_floater, bool from_click)
  435. {
  436. LLPreview* opened_preview = (LLPreview*)opened_floater;
  437. if (opened_preview && opened_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED)
  438. {
  439. opened_preview->loadAsset();
  440. }
  441. }
  442. void LLPreview::setAssetId(const LLUUID& asset_id)
  443. {
  444. const LLViewerInventoryItem* item = dynamic_cast<const LLViewerInventoryItem*>(getItem());
  445. if(NULL == item)
  446. {
  447. return;
  448. }
  449. if(mObjectUUID.isNull())
  450. {
  451. // Update avatar inventory asset_id.
  452. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
  453. new_item->setAssetUUID(asset_id);
  454. gInventory.updateItem(new_item);
  455. gInventory.notifyObservers();
  456. }
  457. else
  458. {
  459. // Update object inventory asset_id.
  460. LLViewerObject* object = gObjectList.findObject(mObjectUUID);
  461. if(NULL == object)
  462. {
  463. return;
  464. }
  465. object->updateViewerInventoryAsset(item, asset_id);
  466. }
  467. }