00001
00032 #include "llviewerprecompiledheaders.h"
00033 #include "stdenums.h"
00034
00035 #include "llpreview.h"
00036 #include "lllineeditor.h"
00037 #include "llinventory.h"
00038 #include "llinventorymodel.h"
00039 #include "llresmgr.h"
00040 #include "lltextbox.h"
00041 #include "llfocusmgr.h"
00042 #include "lltooldraganddrop.h"
00043 #include "llradiogroup.h"
00044 #include "llassetstorage.h"
00045 #include "llviewerobject.h"
00046 #include "llviewerobjectlist.h"
00047 #include "lldbstrings.h"
00048 #include "llagent.h"
00049 #include "llvoavatar.h"
00050 #include "llselectmgr.h"
00051 #include "llinventoryview.h"
00052 #include "llviewerinventory.h"
00053
00054
00055
00056
00057 LLPreview::preview_multimap_t LLPreview::sPreviewsBySource;
00058 LLPreview::preview_map_t LLPreview::sInstances;
00059 std::map<LLUUID, LLHandle<LLFloater> > LLMultiPreview::sAutoOpenPreviewHandles;
00060
00061
00062 LLPreview::LLPreview(const std::string& name) :
00063 LLFloater(name),
00064 mCopyToInvBtn(NULL),
00065 mForceClose(FALSE),
00066 mUserResized(FALSE),
00067 mCloseAfterSave(FALSE),
00068 mAssetStatus(PREVIEW_ASSET_UNLOADED),
00069 mItem(NULL),
00070 mDirty(TRUE)
00071 {
00072
00073 mAuxItem = new LLInventoryItem;
00074
00075 setAutoFocus(FALSE);
00076 gInventory.addObserver(this);
00077 }
00078
00079 LLPreview::LLPreview(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_uuid, const LLUUID& object_uuid, BOOL allow_resize, S32 min_width, S32 min_height, LLPointer<LLViewerInventoryItem> inv_item )
00080 : LLFloater(name, rect, title, allow_resize, min_width, min_height ),
00081 mItemUUID(item_uuid),
00082 mSourceID(LLUUID::null),
00083 mObjectUUID(object_uuid),
00084 mCopyToInvBtn( NULL ),
00085 mForceClose( FALSE ),
00086 mUserResized(FALSE),
00087 mCloseAfterSave(FALSE),
00088 mAssetStatus(PREVIEW_ASSET_UNLOADED),
00089 mItem(inv_item),
00090 mDirty(TRUE)
00091 {
00092 mAuxItem = new LLInventoryItem;
00093
00094 setAutoFocus(FALSE);
00095
00096 if (mItemUUID.notNull())
00097 {
00098 sInstances[mItemUUID] = this;
00099 }
00100 gInventory.addObserver(this);
00101 }
00102
00103 LLPreview::~LLPreview()
00104 {
00105 gFocusMgr.releaseFocusIfNeeded( this );
00106
00107 if (mItemUUID.notNull())
00108 {
00109 sInstances.erase( mItemUUID );
00110 }
00111
00112 if (mSourceID.notNull())
00113 {
00114 preview_multimap_t::iterator found_it = sPreviewsBySource.find(mSourceID);
00115 for (; found_it != sPreviewsBySource.end(); ++found_it)
00116 {
00117 if (found_it->second == getHandle())
00118 {
00119 sPreviewsBySource.erase(found_it);
00120 break;
00121 }
00122 }
00123 }
00124 gInventory.removeObserver(this);
00125 }
00126
00127 void LLPreview::setItemID(const LLUUID& item_id)
00128 {
00129 if (mItemUUID.notNull())
00130 {
00131 sInstances.erase(mItemUUID);
00132 }
00133
00134 mItemUUID = item_id;
00135
00136 if (mItemUUID.notNull())
00137 {
00138 sInstances[mItemUUID] = this;
00139 }
00140 }
00141
00142 void LLPreview::setObjectID(const LLUUID& object_id)
00143 {
00144 mObjectUUID = object_id;
00145 }
00146
00147 void LLPreview::setSourceID(const LLUUID& source_id)
00148 {
00149 if (mSourceID.notNull())
00150 {
00151
00152 preview_multimap_t::iterator found_it = sPreviewsBySource.find(mSourceID);
00153 for (; found_it != sPreviewsBySource.end(); ++found_it)
00154 {
00155 if (found_it->second == getHandle())
00156 {
00157 sPreviewsBySource.erase(found_it);
00158 break;
00159 }
00160 }
00161 }
00162 mSourceID = source_id;
00163 sPreviewsBySource.insert(preview_multimap_t::value_type(mSourceID, getHandle()));
00164 }
00165
00166 const LLViewerInventoryItem *LLPreview::getItem() const
00167 {
00168 if(mItem)
00169 return mItem;
00170 const LLViewerInventoryItem *item = NULL;
00171 if(mObjectUUID.isNull())
00172 {
00173
00174 item = gInventory.getItem(mItemUUID);
00175 }
00176 else
00177 {
00178
00179 LLViewerObject* object = gObjectList.findObject(mObjectUUID);
00180 if(object)
00181 {
00182 item = (LLViewerInventoryItem*)object->getInventoryObject(mItemUUID);
00183 }
00184 }
00185 return item;
00186 }
00187
00188
00189 void LLPreview::onCommit()
00190 {
00191 const LLViewerInventoryItem *item = getItem();
00192 if(item)
00193 {
00194 if (!item->isComplete())
00195 {
00196
00197 llwarns << "LLPreview::onCommit() called with mIsComplete == FALSE"
00198 << " Type: " << item->getType()
00199 << " ID: " << item->getUUID()
00200 << llendl;
00201 return;
00202 }
00203
00204 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
00205 new_item->setDescription(childGetText("desc"));
00206 if(mObjectUUID.notNull())
00207 {
00208
00209 LLViewerObject* object = gObjectList.findObject(mObjectUUID);
00210 if(object)
00211 {
00212 object->updateInventory(
00213 new_item,
00214 TASK_INVENTORY_ITEM_KEY,
00215 false);
00216 }
00217 }
00218 else if(item->getPermissions().getOwner() == gAgent.getID())
00219 {
00220 new_item->updateServer(FALSE);
00221 gInventory.updateItem(new_item);
00222 gInventory.notifyObservers();
00223
00224
00225
00226 if( item->getType() == LLAssetType::AT_OBJECT )
00227 {
00228 LLVOAvatar* avatar = gAgent.getAvatarObject();
00229 if( avatar )
00230 {
00231 LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() );
00232 if( obj )
00233 {
00234 LLSelectMgr::getInstance()->deselectAll();
00235 LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE );
00236 LLSelectMgr::getInstance()->selectionSetObjectDescription( childGetText("desc") );
00237
00238 LLSelectMgr::getInstance()->deselectAll();
00239 }
00240 }
00241 }
00242 }
00243 }
00244 }
00245
00246 void LLPreview::changed(U32 mask)
00247 {
00248 mDirty = TRUE;
00249 }
00250
00251 void LLPreview::draw()
00252 {
00253 LLFloater::draw();
00254 if (mDirty)
00255 {
00256 mDirty = FALSE;
00257 const LLViewerInventoryItem *item = getItem();
00258 if (item)
00259 {
00260 refreshFromItem(item);
00261 }
00262 }
00263 }
00264
00265 void LLPreview::refreshFromItem(const LLInventoryItem* item)
00266 {
00267 setTitle(llformat("%s: %s",getTitleName(),item->getName().c_str()));
00268 childSetText("desc",item->getDescription());
00269
00270 BOOL can_agent_manipulate = item->getPermissions().allowModifyBy(gAgent.getID());
00271 childSetEnabled("desc",can_agent_manipulate);
00272 }
00273
00274
00275 void LLPreview::onText(LLUICtrl*, void* userdata)
00276 {
00277 LLPreview* self = (LLPreview*) userdata;
00278 self->onCommit();
00279 }
00280
00281
00282 void LLPreview::onRadio(LLUICtrl*, void* userdata)
00283 {
00284 LLPreview* self = (LLPreview*) userdata;
00285 self->onCommit();
00286 }
00287
00288
00289 LLPreview* LLPreview::find(const LLUUID& item_uuid)
00290 {
00291 LLPreview* instance = NULL;
00292 preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid);
00293 if(found_it != LLPreview::sInstances.end())
00294 {
00295 instance = found_it->second;
00296 }
00297 return instance;
00298 }
00299
00300
00301 LLPreview* LLPreview::show( const LLUUID& item_uuid, BOOL take_focus )
00302 {
00303 LLPreview* instance = LLPreview::find(item_uuid);
00304 if(instance)
00305 {
00306 if (LLFloater::getFloaterHost() && LLFloater::getFloaterHost() != instance->getHost())
00307 {
00308
00309
00310 LLFloater::getFloaterHost()->addFloater(instance, TRUE);
00311 }
00312 instance->open();
00313 if (take_focus)
00314 {
00315 instance->setFocus(TRUE);
00316 }
00317 }
00318
00319 return instance;
00320 }
00321
00322
00323 bool LLPreview::save( const LLUUID& item_uuid, LLPointer<LLInventoryItem>* itemptr )
00324 {
00325 bool res = false;
00326 LLPreview* instance = LLPreview::find(item_uuid);
00327 if(instance)
00328 {
00329 res = instance->saveItem(itemptr);
00330 }
00331 if (!res)
00332 {
00333 delete itemptr;
00334 }
00335 return res;
00336 }
00337
00338
00339 void LLPreview::hide(const LLUUID& item_uuid, BOOL no_saving )
00340 {
00341 preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid);
00342 if(found_it != LLPreview::sInstances.end())
00343 {
00344 LLPreview* instance = found_it->second;
00345
00346 if ( no_saving )
00347 {
00348 instance->mForceClose = TRUE;
00349 }
00350
00351 instance->close();
00352 }
00353 }
00354
00355
00356 void LLPreview::rename(const LLUUID& item_uuid, const std::string& new_name)
00357 {
00358 preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid);
00359 if(found_it != LLPreview::sInstances.end())
00360 {
00361 LLPreview* instance = found_it->second;
00362 instance->setTitle( new_name );
00363 }
00364 }
00365
00366 BOOL LLPreview::handleMouseDown(S32 x, S32 y, MASK mask)
00367 {
00368 if(mClientRect.pointInRect(x, y))
00369 {
00370
00371
00372 bringToFront(x, y);
00373 gFocusMgr.setMouseCapture(this);
00374 S32 screen_x;
00375 S32 screen_y;
00376 localPointToScreen(x, y, &screen_x, &screen_y );
00377 LLToolDragAndDrop::getInstance()->setDragStart(screen_x, screen_y);
00378 return TRUE;
00379 }
00380 return LLFloater::handleMouseDown(x, y, mask);
00381 }
00382
00383 BOOL LLPreview::handleMouseUp(S32 x, S32 y, MASK mask)
00384 {
00385 if(hasMouseCapture())
00386 {
00387 gFocusMgr.setMouseCapture(NULL);
00388 return TRUE;
00389 }
00390 return LLFloater::handleMouseUp(x, y, mask);
00391 }
00392
00393 BOOL LLPreview::handleHover(S32 x, S32 y, MASK mask)
00394 {
00395 if(hasMouseCapture())
00396 {
00397 S32 screen_x;
00398 S32 screen_y;
00399 const LLViewerInventoryItem *item = getItem();
00400
00401 localPointToScreen(x, y, &screen_x, &screen_y );
00402 if(item
00403 && item->getPermissions().allowCopyBy(gAgent.getID(),
00404 gAgent.getGroupID())
00405 && LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y))
00406 {
00407 EDragAndDropType type;
00408 type = LLAssetType::lookupDragAndDropType(item->getType());
00409 LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_LIBRARY;
00410 if(!mObjectUUID.isNull())
00411 {
00412 src = LLToolDragAndDrop::SOURCE_WORLD;
00413 }
00414 else if(item->getPermissions().getOwner() == gAgent.getID())
00415 {
00416 src = LLToolDragAndDrop::SOURCE_AGENT;
00417 }
00418 LLToolDragAndDrop::getInstance()->beginDrag(type,
00419 item->getUUID(),
00420 src,
00421 mObjectUUID);
00422 return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask );
00423 }
00424 }
00425 return LLFloater::handleHover(x,y,mask);
00426 }
00427
00428 void LLPreview::open()
00429 {
00430 if (!getFloaterHost() && !getHost() && getAssetStatus() == PREVIEW_ASSET_UNLOADED)
00431 {
00432 loadAsset();
00433 }
00434 LLFloater::open();
00435 }
00436
00437
00438 bool LLPreview::saveItem(LLPointer<LLInventoryItem>* itemptr)
00439 {
00440 return false;
00441 }
00442
00443
00444
00445 void LLPreview::onBtnCopyToInv(void* userdata)
00446 {
00447 LLPreview* self = (LLPreview*) userdata;
00448 LLInventoryItem *item = self->mAuxItem;
00449
00450 if(item && item->getUUID().notNull())
00451 {
00452
00453 if (self->mNotecardInventoryID.notNull())
00454 {
00455 copy_inventory_from_notecard(self->mObjectID,
00456 self->mNotecardInventoryID, item);
00457 }
00458 else
00459 {
00460 LLPointer<LLInventoryCallback> cb = NULL;
00461 copy_inventory_item(
00462 gAgent.getID(),
00463 item->getPermissions().getOwner(),
00464 item->getUUID(),
00465 LLUUID::null,
00466 std::string(),
00467 cb);
00468 }
00469 }
00470 self->close();
00471 }
00472
00473
00474 void LLPreview::onKeepBtn(void* data)
00475 {
00476 LLPreview* self = (LLPreview*)data;
00477 self->close();
00478 }
00479
00480
00481 void LLPreview::onDiscardBtn(void* data)
00482 {
00483 LLPreview* self = (LLPreview*)data;
00484
00485 const LLViewerInventoryItem* item = self->getItem();
00486 if (!item) return;
00487
00488 self->mForceClose = TRUE;
00489 self->close();
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499 LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
00500 if (item->getParentUUID() != trash_id)
00501 {
00502 LLInventoryModel::update_list_t update;
00503 LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
00504 update.push_back(old_folder);
00505 LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1);
00506 update.push_back(new_folder);
00507 gInventory.accountForUpdate(update);
00508
00509 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
00510 new_item->setParent(trash_id);
00511
00512
00513 new_item->updateParentOnServer(FALSE);
00514 gInventory.updateItem(new_item);
00515 gInventory.notifyObservers();
00516 }
00517 }
00518
00519
00520 LLPreview* LLPreview::getFirstPreviewForSource(const LLUUID& source_id)
00521 {
00522 preview_multimap_t::iterator found_it = sPreviewsBySource.find(source_id);
00523 if (found_it != sPreviewsBySource.end())
00524 {
00525
00526 return (LLPreview*)found_it->second.get();
00527 }
00528 return NULL;
00529 }
00530
00531 void LLPreview::userSetShape(const LLRect& new_rect)
00532 {
00533 if(new_rect.getWidth() != getRect().getWidth() || new_rect.getHeight() != getRect().getHeight())
00534 {
00535 userResized();
00536 }
00537 LLFloater::userSetShape(new_rect);
00538 }
00539
00540
00541
00542
00543
00544 LLMultiPreview::LLMultiPreview(const LLRect& rect) : LLMultiFloater("Preview", rect)
00545 {
00546 setCanResize(TRUE);
00547 }
00548
00549 void LLMultiPreview::open()
00550 {
00551 LLMultiFloater::open();
00552 LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel();
00553 if (frontmost_preview && frontmost_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED)
00554 {
00555 frontmost_preview->loadAsset();
00556 }
00557 }
00558
00559
00560 void LLMultiPreview::userSetShape(const LLRect& new_rect)
00561 {
00562 if(new_rect.getWidth() != getRect().getWidth() || new_rect.getHeight() != getRect().getHeight())
00563 {
00564 LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel();
00565 if (frontmost_preview) frontmost_preview->userResized();
00566 }
00567 LLFloater::userSetShape(new_rect);
00568 }
00569
00570
00571 void LLMultiPreview::tabOpen(LLFloater* opened_floater, bool from_click)
00572 {
00573 LLPreview* opened_preview = (LLPreview*)opened_floater;
00574 if (opened_preview && opened_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED)
00575 {
00576 opened_preview->loadAsset();
00577 }
00578 }
00579
00580
00581 LLMultiPreview* LLMultiPreview::getAutoOpenInstance(const LLUUID& id)
00582 {
00583 handle_map_t::iterator found_it = sAutoOpenPreviewHandles.find(id);
00584 if (found_it != sAutoOpenPreviewHandles.end())
00585 {
00586 return (LLMultiPreview*)found_it->second.get();
00587 }
00588 return NULL;
00589 }
00590
00591
00592 void LLMultiPreview::setAutoOpenInstance(LLMultiPreview* previewp, const LLUUID& id)
00593 {
00594 if (previewp)
00595 {
00596 sAutoOpenPreviewHandles[id] = previewp->getHandle();
00597 }
00598 }