PageRenderTime 126ms CodeModel.GetById 49ms app.highlight 67ms RepoModel.GetById 1ms app.codeStats 1ms

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