llpreview.cpp

Go to the documentation of this file.
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 // Constants
00055 
00056 // Globals and statics
00057 LLPreview::preview_multimap_t LLPreview::sPreviewsBySource;
00058 LLPreview::preview_map_t LLPreview::sInstances;
00059 std::map<LLUUID, LLHandle<LLFloater> > LLMultiPreview::sAutoOpenPreviewHandles;
00060 
00061 // Functions
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         // don't add to instance list, since ItemID is null
00073         mAuxItem = new LLInventoryItem; // (LLPointer is auto-deleted)
00074         // don't necessarily steal focus on creation -- sometimes these guys pop up without user action
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         // don't necessarily steal focus on creation -- sometimes these guys pop up without user action
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 ); // calls onCommit()
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                 // erase old one
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                 // it's an inventory item, so get the item.
00174                 item = gInventory.getItem(mItemUUID);
00175         }
00176         else
00177         {
00178                 // it's an object's inventory item.
00179                 LLViewerObject* object = gObjectList.findObject(mObjectUUID);
00180                 if(object)
00181                 {
00182                         item = (LLViewerInventoryItem*)object->getInventoryObject(mItemUUID);
00183                 }
00184         }
00185         return item;
00186 }
00187 
00188 // Sub-classes should override this function if they allow editing
00189 void LLPreview::onCommit()
00190 {
00191         const LLViewerInventoryItem *item = getItem();
00192         if(item)
00193         {
00194                 if (!item->isComplete())
00195                 {
00196                         // We are attempting to save an item that was never loaded
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                         // must be in an object
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                         // If the item is an attachment that is currently being worn,
00225                         // update the object itself.
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 // static 
00275 void LLPreview::onText(LLUICtrl*, void* userdata)
00276 {
00277         LLPreview* self = (LLPreview*) userdata;
00278         self->onCommit();
00279 }
00280 
00281 // static
00282 void LLPreview::onRadio(LLUICtrl*, void* userdata)
00283 {
00284         LLPreview* self = (LLPreview*) userdata;
00285         self->onCommit();
00286 }
00287 
00288 // static
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 // static
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                         // this preview window is being opened in a new context
00309                         // needs to be rehosted
00310                         LLFloater::getFloaterHost()->addFloater(instance, TRUE);
00311                 }
00312                 instance->open();  /*Flawfinder: ignore*/
00313                 if (take_focus)
00314                 {
00315                         instance->setFocus(TRUE);
00316                 }
00317         }
00318 
00319         return instance;
00320 }
00321 
00322 // static
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 // static
00339 void LLPreview::hide(const LLUUID& item_uuid, BOOL no_saving /* = FALSE */ )
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 // static
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                 // No handler needed for focus lost since this class has no
00371                 // state that depends on it.
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()  /*Flawfinder: ignore*/
00429 {
00430         if (!getFloaterHost() && !getHost() && getAssetStatus() == PREVIEW_ASSET_UNLOADED)
00431         {
00432                 loadAsset();
00433         }
00434         LLFloater::open();              /*Flawfinder: ignore*/
00435 }
00436 
00437 // virtual
00438 bool LLPreview::saveItem(LLPointer<LLInventoryItem>* itemptr)
00439 {
00440         return false;
00441 }
00442 
00443 
00444 // static
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                 // Copy to inventory
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 // static
00474 void LLPreview::onKeepBtn(void* data)
00475 {
00476         LLPreview* self = (LLPreview*)data;
00477         self->close();
00478 }
00479 
00480 // static
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         // Delete the item entirely
00492         /*
00493         item->removeFromServer();
00494         gInventory.deleteObject(item->getUUID());
00495         gInventory.notifyObservers();
00496         */
00497 
00498         // Move the item to the trash
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                 // no need to restamp it though it's a move into trash because
00512                 // it's a brand new item already.
00513                 new_item->updateParentOnServer(FALSE);
00514                 gInventory.updateItem(new_item);
00515                 gInventory.notifyObservers();
00516         }
00517 }
00518 
00519 //static
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                 // just return first one
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 // LLMultiPreview
00542 //
00543 
00544 LLMultiPreview::LLMultiPreview(const LLRect& rect) : LLMultiFloater("Preview", rect)
00545 {
00546         setCanResize(TRUE);
00547 }
00548 
00549 void LLMultiPreview::open()             /*Flawfinder: ignore*/
00550 {
00551         LLMultiFloater::open();         /*Flawfinder: ignore*/
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 //static 
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 //static
00592 void LLMultiPreview::setAutoOpenInstance(LLMultiPreview* previewp, const LLUUID& id)
00593 {
00594         if (previewp)
00595         {
00596                 sAutoOpenPreviewHandles[id] = previewp->getHandle();
00597         }
00598 }

Generated on Fri May 16 08:33:56 2008 for SecondLife by  doxygen 1.5.5