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, LLViewHandle> 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 {
00071         // don't add to instance list, since ItemID is null
00072         mAuxItem = new LLInventoryItem; // (LLPointer is auto-deleted)
00073         // don't necessarily steal focus on creation -- sometimes these guys pop up without user action
00074         mAutoFocus = FALSE;
00075 }
00076 
00077 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 )
00078 :       LLFloater(name, rect, title, allow_resize, min_width, min_height ),
00079         mItemUUID(item_uuid),
00080         mSourceID(LLUUID::null),
00081         mObjectUUID(object_uuid),
00082         mCopyToInvBtn( NULL ),
00083         mForceClose( FALSE ),
00084         mUserResized(FALSE),
00085         mCloseAfterSave(FALSE),
00086         mAssetStatus(PREVIEW_ASSET_UNLOADED),
00087         mItem(inv_item)
00088 {
00089         mAuxItem = new LLInventoryItem;
00090         // don't necessarily steal focus on creation -- sometimes these guys pop up without user action
00091         mAutoFocus = FALSE;
00092 
00093         if (mItemUUID.notNull())
00094         {
00095                 sInstances[mItemUUID] = this;
00096         }
00097 
00098 }
00099 
00100 LLPreview::~LLPreview()
00101 {
00102         gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
00103 
00104         if (mItemUUID.notNull())
00105         {
00106                 sInstances.erase( mItemUUID );
00107         }
00108 
00109         if (mSourceID.notNull())
00110         {
00111                 preview_multimap_t::iterator found_it = sPreviewsBySource.find(mSourceID);
00112                 for (; found_it != sPreviewsBySource.end(); ++found_it)
00113                 {
00114                         if (found_it->second == mViewHandle)
00115                         {
00116                                 sPreviewsBySource.erase(found_it);
00117                                 break;
00118                         }
00119                 }
00120         }
00121 }
00122 
00123 void LLPreview::setItemID(const LLUUID& item_id)
00124 {
00125         if (mItemUUID.notNull())
00126         {
00127                 sInstances.erase(mItemUUID);
00128         }
00129 
00130         mItemUUID = item_id;
00131 
00132         if (mItemUUID.notNull())
00133         {
00134                 sInstances[mItemUUID] = this;
00135         }
00136 }
00137 
00138 void LLPreview::setObjectID(const LLUUID& object_id)
00139 {
00140         mObjectUUID = object_id;
00141 }
00142 
00143 void LLPreview::setSourceID(const LLUUID& source_id)
00144 {
00145         if (mSourceID.notNull())
00146         {
00147                 // erase old one
00148                 preview_multimap_t::iterator found_it = sPreviewsBySource.find(mSourceID);
00149                 for (; found_it != sPreviewsBySource.end(); ++found_it)
00150                 {
00151                         if (found_it->second == mViewHandle)
00152                         {
00153                                 sPreviewsBySource.erase(found_it);
00154                                 break;
00155                         }
00156                 }
00157         }
00158         mSourceID = source_id;
00159         sPreviewsBySource.insert(preview_multimap_t::value_type(mSourceID, mViewHandle));
00160 }
00161 
00162 const LLViewerInventoryItem *LLPreview::getItem() const
00163 {
00164         if(mItem)
00165                 return mItem;
00166         const LLViewerInventoryItem *item = NULL;
00167         if(mObjectUUID.isNull())
00168         {
00169                 // it's an inventory item, so get the item.
00170                 item = gInventory.getItem(mItemUUID);
00171         }
00172         else
00173         {
00174                 // it's an object's inventory item.
00175                 LLViewerObject* object = gObjectList.findObject(mObjectUUID);
00176                 if(object)
00177                 {
00178                         item = (LLViewerInventoryItem*)object->getInventoryObject(mItemUUID);
00179                 }
00180         }
00181         return item;
00182 }
00183 
00184 // Sub-classes should override this function if they allow editing
00185 void LLPreview::onCommit()
00186 {
00187         const LLViewerInventoryItem *item = getItem();
00188         if(item)
00189         {
00190                 if (!item->isComplete())
00191                 {
00192                         // We are attempting to save an item that was never loaded
00193                         llwarns << "LLPreview::onCommit() called with mIsComplete == FALSE"
00194                                         << " Type: " << item->getType()
00195                                         << " ID: " << item->getUUID()
00196                                         << llendl;
00197                         return;
00198                 }
00199                 
00200                 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
00201                 new_item->setDescription(childGetText("desc"));
00202                 if(mObjectUUID.notNull())
00203                 {
00204                         // must be in an object
00205                         LLViewerObject* object = gObjectList.findObject(mObjectUUID);
00206                         if(object)
00207                         {
00208                                 object->updateInventory(
00209                                         new_item,
00210                                         TASK_INVENTORY_ITEM_KEY,
00211                                         false);
00212                         }
00213                 }
00214                 else if(item->getPermissions().getOwner() == gAgent.getID())
00215                 {
00216                         new_item->updateServer(FALSE);
00217                         gInventory.updateItem(new_item);
00218 
00219                         // If the item is an attachment that is currently being worn,
00220                         // update the object itself.
00221                         if( item->getType() == LLAssetType::AT_OBJECT )
00222                         {
00223                                 LLVOAvatar* avatar = gAgent.getAvatarObject();
00224                                 if( avatar )
00225                                 {
00226                                         LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() );
00227                                         if( obj )
00228                                         {
00229                                                 gSelectMgr->deselectAll();
00230                                                 gSelectMgr->addAsIndividual( obj, SELECT_ALL_TES, FALSE );
00231                                                 gSelectMgr->selectionSetObjectDescription( childGetText("desc") );
00232 
00233                                                 gSelectMgr->deselectAll();
00234                                         }
00235                                 }
00236                         }
00237                 }
00238         }
00239 }
00240 
00241 // static 
00242 void LLPreview::onText(LLUICtrl*, void* userdata)
00243 {
00244         LLPreview* self = (LLPreview*) userdata;
00245         self->onCommit();
00246 }
00247 
00248 // static
00249 void LLPreview::onRadio(LLUICtrl*, void* userdata)
00250 {
00251         LLPreview* self = (LLPreview*) userdata;
00252         self->onCommit();
00253 }
00254 
00255 // static
00256 LLPreview* LLPreview::find(const LLUUID& item_uuid)
00257 {
00258         LLPreview* instance = NULL;
00259         preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid);
00260         if(found_it != LLPreview::sInstances.end())
00261         {
00262                 instance = found_it->second;
00263         }
00264         return instance;
00265 }
00266 
00267 // static
00268 LLPreview* LLPreview::show( const LLUUID& item_uuid, BOOL take_focus )
00269 {
00270         LLPreview* instance = LLPreview::find(item_uuid);
00271         if(instance)
00272         {
00273                 if (LLFloater::getFloaterHost() && LLFloater::getFloaterHost() != instance->getHost())
00274                 {
00275                         // this preview window is being opened in a new context
00276                         // needs to be rehosted
00277                         LLFloater::getFloaterHost()->addFloater(instance, TRUE);
00278                 }
00279                 instance->open();  /*Flawfinder: ignore*/
00280                 if (take_focus)
00281                 {
00282                         instance->setFocus(TRUE);
00283                 }
00284         }
00285 
00286         return instance;
00287 }
00288 
00289 // static
00290 bool LLPreview::save( const LLUUID& item_uuid, LLPointer<LLInventoryItem>* itemptr )
00291 {
00292         bool res = false;
00293         LLPreview* instance = LLPreview::find(item_uuid);
00294         if(instance)
00295         {
00296                 res = instance->saveItem(itemptr);
00297         }
00298         if (!res)
00299         {
00300                 delete itemptr;
00301         }
00302         return res;
00303 }
00304 
00305 // static
00306 void LLPreview::hide(const LLUUID& item_uuid, BOOL no_saving /* = FALSE */ )
00307 {
00308         preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid);
00309         if(found_it != LLPreview::sInstances.end())
00310         {
00311                 LLPreview* instance = found_it->second;
00312 
00313                 if ( no_saving )
00314                 {
00315                         instance->mForceClose = TRUE;
00316                 }
00317 
00318                 instance->close();
00319         }
00320 }
00321 
00322 // static
00323 void LLPreview::rename(const LLUUID& item_uuid, const std::string& new_name)
00324 {
00325         preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid);
00326         if(found_it != LLPreview::sInstances.end())
00327         {
00328                 LLPreview* instance = found_it->second;
00329                 instance->setTitle( new_name );
00330         }
00331 }
00332 
00333 BOOL LLPreview::handleMouseDown(S32 x, S32 y, MASK mask)
00334 {
00335         if(mClientRect.pointInRect(x, y))
00336         {
00337                 // No handler needed for focus lost since this class has no
00338                 // state that depends on it.
00339                 bringToFront(x, y);
00340                 gFocusMgr.setMouseCapture(this);
00341                 S32 screen_x;
00342                 S32 screen_y;
00343                 localPointToScreen(x, y, &screen_x, &screen_y );
00344                 gToolDragAndDrop->setDragStart(screen_x, screen_y);
00345                 return TRUE;
00346         }
00347         return LLFloater::handleMouseDown(x, y, mask);
00348 }
00349 
00350 BOOL LLPreview::handleMouseUp(S32 x, S32 y, MASK mask)
00351 {
00352         if(hasMouseCapture())
00353         {
00354                 gFocusMgr.setMouseCapture(NULL);
00355                 return TRUE;
00356         }
00357         return LLFloater::handleMouseUp(x, y, mask);
00358 }
00359 
00360 BOOL LLPreview::handleHover(S32 x, S32 y, MASK mask)
00361 {
00362         if(hasMouseCapture())
00363         {
00364                 S32 screen_x;
00365                 S32 screen_y;
00366                 const LLViewerInventoryItem *item = getItem();
00367 
00368                 localPointToScreen(x, y, &screen_x, &screen_y );
00369                 if(item
00370                    && item->getPermissions().allowCopyBy(gAgent.getID(),
00371                                                                                                  gAgent.getGroupID())
00372                    && gToolDragAndDrop->isOverThreshold(screen_x, screen_y))
00373                 {
00374                         EDragAndDropType type;
00375                         type = LLAssetType::lookupDragAndDropType(item->getType());
00376                         LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_LIBRARY;
00377                         if(!mObjectUUID.isNull())
00378                         {
00379                                 src = LLToolDragAndDrop::SOURCE_WORLD;
00380                         }
00381                         else if(item->getPermissions().getOwner() == gAgent.getID())
00382                         {
00383                                 src = LLToolDragAndDrop::SOURCE_AGENT;
00384                         }
00385                         gToolDragAndDrop->beginDrag(type,
00386                                                                                 item->getUUID(),
00387                                                                                 src,
00388                                                                                 mObjectUUID);
00389                         return gToolDragAndDrop->handleHover(x, y, mask );
00390                 }
00391         }
00392         return LLFloater::handleHover(x,y,mask);
00393 }
00394 
00395 void LLPreview::open()  /*Flawfinder: ignore*/
00396 {
00397         LLMultiFloater* hostp = getHost();
00398         if (!sHostp && !hostp && getAssetStatus() == PREVIEW_ASSET_UNLOADED)
00399         {
00400                 loadAsset();
00401         }
00402         LLFloater::open();              /*Flawfinder: ignore*/
00403 }
00404 
00405 // virtual
00406 bool LLPreview::saveItem(LLPointer<LLInventoryItem>* itemptr)
00407 {
00408         return false;
00409 }
00410 
00411 
00412 // static
00413 void LLPreview::onBtnCopyToInv(void* userdata)
00414 {
00415         LLPreview* self = (LLPreview*) userdata;
00416         LLInventoryItem *item = self->mAuxItem;
00417 
00418         if(item && item->getUUID().notNull())
00419         {
00420                 // Copy to inventory
00421                 if (self->mNotecardInventoryID.notNull())
00422                 {
00423                         copy_inventory_from_notecard(self->mObjectID,
00424                                 self->mNotecardInventoryID, item);
00425                 }
00426                 else
00427                 {
00428                         LLPointer<LLInventoryCallback> cb = NULL;
00429                         copy_inventory_item(
00430                                 gAgent.getID(),
00431                                 item->getPermissions().getOwner(),
00432                                 item->getUUID(),
00433                                 LLUUID::null,
00434                                 std::string(),
00435                                 cb);
00436                 }
00437         }
00438 }
00439 
00440 // static
00441 void LLPreview::onKeepBtn(void* data)
00442 {
00443         LLPreview* self = (LLPreview*)data;
00444         self->close();
00445 }
00446 
00447 // static
00448 void LLPreview::onDiscardBtn(void* data)
00449 {
00450         LLPreview* self = (LLPreview*)data;
00451 
00452         const LLViewerInventoryItem* item = self->getItem();
00453         if (!item) return;
00454 
00455         self->mForceClose = TRUE;
00456         self->close();
00457 
00458         // Delete the item entirely
00459         /*
00460         item->removeFromServer();
00461         gInventory.deleteObject(item->getUUID());
00462         gInventory.notifyObservers();
00463         */
00464 
00465         // Move the item to the trash
00466         LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
00467         if (item->getParentUUID() != trash_id)
00468         {
00469                 LLInventoryModel::update_list_t update;
00470                 LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
00471                 update.push_back(old_folder);
00472                 LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1);
00473                 update.push_back(new_folder);
00474                 gInventory.accountForUpdate(update);
00475 
00476                 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
00477                 new_item->setParent(trash_id);
00478                 // no need to restamp it though it's a move into trash because
00479                 // it's a brand new item already.
00480                 new_item->updateParentOnServer(FALSE);
00481                 gInventory.updateItem(new_item);
00482                 gInventory.notifyObservers();
00483         }
00484 }
00485 
00486 //static
00487 LLPreview* LLPreview::getFirstPreviewForSource(const LLUUID& source_id)
00488 {
00489         preview_multimap_t::iterator found_it = sPreviewsBySource.find(source_id);
00490         if (found_it != sPreviewsBySource.end())
00491         {
00492                 // just return first one
00493                 return (LLPreview*)LLFloater::getFloaterByHandle(found_it->second);
00494         }
00495         return NULL;
00496 }
00497 
00498 void LLPreview::userSetShape(const LLRect& new_rect)
00499 {
00500         if(new_rect.getWidth() != mRect.getWidth() || new_rect.getHeight() != mRect.getHeight())
00501         {
00502                 userResized();
00503         }
00504         LLFloater::userSetShape(new_rect);
00505 }
00506 
00507 //
00508 // LLMultiPreview
00509 //
00510 
00511 LLMultiPreview::LLMultiPreview(const LLRect& rect) : LLMultiFloater("Preview", rect)
00512 {
00513         setCanResize(TRUE);
00514 }
00515 
00516 void LLMultiPreview::open()             /*Flawfinder: ignore*/
00517 {
00518         LLMultiFloater::open();         /*Flawfinder: ignore*/
00519         LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel();
00520         if (frontmost_preview && frontmost_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED)
00521         {
00522                 frontmost_preview->loadAsset();
00523         }
00524 }
00525 
00526 
00527 void LLMultiPreview::userSetShape(const LLRect& new_rect)
00528 {
00529         if(new_rect.getWidth() != mRect.getWidth() || new_rect.getHeight() != mRect.getHeight())
00530         {
00531                 LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel();
00532                 if (frontmost_preview) frontmost_preview->userResized();
00533         }
00534         LLFloater::userSetShape(new_rect);
00535 }
00536 
00537 
00538 void LLMultiPreview::tabOpen(LLFloater* opened_floater, bool from_click)
00539 {
00540         LLPreview* opened_preview = (LLPreview*)opened_floater;
00541         if (opened_preview && opened_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED)
00542         {
00543                 opened_preview->loadAsset();
00544         }
00545 }
00546 
00547 //static 
00548 LLMultiPreview* LLMultiPreview::getAutoOpenInstance(const LLUUID& id)
00549 {
00550         handle_map_t::iterator found_it = sAutoOpenPreviewHandles.find(id);
00551         if (found_it != sAutoOpenPreviewHandles.end())
00552         {
00553                 return (LLMultiPreview*)gFloaterView->getFloaterByHandle(found_it->second);     
00554         }
00555         return NULL;
00556 }
00557 
00558 //static
00559 void LLMultiPreview::setAutoOpenInstance(LLMultiPreview* previewp, const LLUUID& id)
00560 {
00561         if (previewp)
00562         {
00563                 sAutoOpenPreviewHandles[id] = previewp->getHandle();
00564         }
00565 }

Generated on Thu Jul 1 06:09:01 2010 for Second Life Viewer by  doxygen 1.4.7