llpanelinventory.cpp

Go to the documentation of this file.
00001 
00032 //*****************************************************************************
00033 //
00034 // Implementation of the panel inventory - used to view and control a
00035 // task's inventory.
00036 //
00037 //*****************************************************************************
00038 
00039 #include "llviewerprecompiledheaders.h"
00040 
00041 #include <sstream> // for std::ostringstream
00042 #include <utility> // for std::pair<>
00043 
00044 #include "stdenums.h"
00045 #include "llpanelinventory.h"
00046 
00047 #include "message.h"
00048 #include "lldarray.h"
00049 #include "llfontgl.h"
00050 #include "llassetstorage.h"
00051 #include "llinventory.h"
00052 
00053 #include "llagent.h"
00054 #include "llcallbacklist.h"
00055 #include "llfocusmgr.h"
00056 #include "llfloaterbuycurrency.h"
00057 #include "llfloaterproperties.h"
00058 #include "llfolderview.h"
00059 #include "llgl.h"
00060 #include "llinventorymodel.h"
00061 #include "llinventoryview.h"
00062 #include "llmenugl.h"
00063 #include "llpreviewanim.h"
00064 #include "llpreviewgesture.h"
00065 #include "llpreviewnotecard.h"
00066 #include "llpreviewscript.h"
00067 #include "llpreviewsound.h"
00068 #include "llpreviewtexture.h"
00069 #include "roles_constants.h"
00070 #include "llscrollcontainer.h"
00071 #include "llselectmgr.h"
00072 #include "llstatusbar.h"
00073 #include "lltooldraganddrop.h"
00074 #include "llviewercontrol.h"
00075 #include "llviewerregion.h"
00076 #include "llviewerimagelist.h"
00077 #include "llviewerinventory.h"
00078 #include "llviewermessage.h"
00079 #include "llviewerobject.h"
00080 #include "llviewerobjectlist.h"
00081 #include "llviewerwindow.h"
00082 #include "llwearable.h"
00083 
00087 
00088 
00092 
00093 class LLTaskInvFVBridge : public LLFolderViewEventListener
00094 {
00095 protected:
00096         LLUUID mUUID;
00097         LLString mName;
00098         mutable LLString mDisplayName;
00099         LLPanelInventory* mPanel;
00100         U32 mFlags;
00101 
00102         LLInventoryItem* findItem() const;
00103 
00104 public:
00105         LLTaskInvFVBridge(
00106                 LLPanelInventory* panel,
00107                 const LLUUID& uuid,
00108                 const LLString& name,
00109                 U32 flags=0);
00110         virtual ~LLTaskInvFVBridge( void ) {}
00111 
00112         virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; }
00113         virtual LLString getLabelSuffix() const { return LLString::null; }
00114 
00115         static LLTaskInvFVBridge* createObjectBridge(LLPanelInventory* panel,
00116                                                                                                  LLInventoryObject* object);
00117         void showProperties();
00118         void buyItem();
00119         S32 getPrice();
00120         static void commitBuyItem(S32 option, void* data);
00121 
00122         // LLFolderViewEventListener functionality
00123         virtual const LLString& getName() const;
00124         virtual const LLString& getDisplayName() const;
00125         virtual PermissionMask getPermissionMask() const { return PERM_NONE; }
00126         virtual const LLUUID& getUUID() const { return mUUID; }
00127         virtual U32 getCreationDate() const;
00128         virtual LLViewerImage* getIcon() const;
00129         virtual void openItem();
00130         virtual void previewItem();
00131         virtual void selectItem() {}
00132         virtual BOOL isItemRenameable() const;
00133         virtual BOOL renameItem(const LLString& new_name);
00134         virtual BOOL isItemMovable();
00135         virtual BOOL isItemRemovable();
00136         virtual BOOL removeItem();
00137         virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch);
00138         virtual void move(LLFolderViewEventListener* parent_listener);
00139         virtual BOOL isItemCopyable() const;
00140         virtual BOOL copyToClipboard() const;
00141         virtual void cutToClipboard();
00142         virtual BOOL isClipboardPasteable() const;
00143         virtual void pasteFromClipboard();
00144         virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
00145         virtual void performAction(LLFolderView* folder, LLInventoryModel* model, LLString action);
00146         virtual BOOL isUpToDate() const { return TRUE; }
00147         virtual BOOL hasChildren() const { return FALSE; }
00148         virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; }
00149         // LLDragAndDropBridge functionality
00150         virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id);
00151         virtual BOOL dragOrDrop(MASK mask, BOOL drop,
00152                                                         EDragAndDropType cargo_type,
00153                                                         void* cargo_data);
00154 //      virtual void dropped();
00155 
00156 };
00157 
00158 LLTaskInvFVBridge::LLTaskInvFVBridge(
00159         LLPanelInventory* panel,
00160         const LLUUID& uuid,
00161         const LLString& name,
00162         U32 flags):
00163         mUUID(uuid),
00164         mName(name),
00165         mPanel(panel),
00166         mFlags(flags)
00167 {
00168 
00169 }
00170 
00171 LLInventoryItem* LLTaskInvFVBridge::findItem() const
00172 {
00173         LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
00174         if(object)
00175         {
00176                 return (LLInventoryItem*)(object->getInventoryObject(mUUID));
00177         }
00178         return NULL;
00179 }
00180 
00181 void LLTaskInvFVBridge::showProperties()
00182 {
00183         if(!LLFloaterProperties::show(mUUID, mPanel->getTaskUUID()))
00184         {
00185                 S32 left, top;
00186                 gFloaterView->getNewFloaterPosition(&left, &top);
00187                 LLRect rect = gSavedSettings.getRect("PropertiesRect");
00188                 rect.translate( left - rect.mLeft, top - rect.mTop );
00189                 LLFloaterProperties* floater = new LLFloaterProperties("obj item properties",
00190                                                                                                            rect,
00191                                                                                                            "Object Inventory Item Properties",
00192                                                                                                            mUUID,
00193                                                                                                            mPanel->getTaskUUID());
00194                 floater->open();                /*Flawfinder: ignore*/
00195         }
00196 }
00197 
00198 struct LLBuyInvItemData
00199 {
00200         LLUUID mTaskID;
00201         LLUUID mItemID;
00202         LLAssetType::EType mType;
00203 
00204         LLBuyInvItemData(const LLUUID& task,
00205                                          const LLUUID& item,
00206                                          LLAssetType::EType type) :
00207                 mTaskID(task), mItemID(item), mType(type)
00208         {}
00209 };
00210 
00211 void LLTaskInvFVBridge::buyItem()
00212 {
00213         llinfos << "LLTaskInvFVBridge::buyItem()" << llendl;
00214         LLInventoryItem* item = findItem();
00215         if(!item || !item->getSaleInfo().isForSale()) return;
00216         LLBuyInvItemData* inv = new LLBuyInvItemData(mPanel->getTaskUUID(),
00217                                                                                                  mUUID,
00218                                                                                                  item->getType());
00219 
00220         const LLSaleInfo& sale_info = item->getSaleInfo();
00221         const LLPermissions& perm = item->getPermissions();
00222         const LLString owner_name; // no owner name currently... FIXME?
00223 
00224         LLViewerObject* obj;
00225         if( ( obj = gObjectList.findObject( mPanel->getTaskUUID() ) ) && obj->isAttachment() )
00226         {
00227                 gViewerWindow->alertXml("Cannot_Purchase_an_Attachment");
00228                 llinfos << "Attempt to purchase an attachment" << llendl;
00229                 delete inv;
00230         }
00231         else
00232         {
00233         LLString::format_map_t args;
00234         args["[PRICE]"] = llformat("%d",sale_info.getSalePrice());
00235         args["[OWNER]"] = owner_name;
00236         if (sale_info.getSaleType() != LLSaleInfo::FS_CONTENTS)
00237         {
00238                 U32 next_owner_mask = perm.getMaskNextOwner();
00239                 args["[MODIFYPERM]"] = LLAlertDialog::getTemplateMessage((next_owner_mask & PERM_MODIFY) ? "PermYes" : "PermNo");
00240                 args["[COPYPERM]"] = LLAlertDialog::getTemplateMessage((next_owner_mask & PERM_COPY) ? "PermYes" : "PermNo");
00241                 args["[RESELLPERM]"] = LLAlertDialog::getTemplateMessage((next_owner_mask & PERM_TRANSFER) ? "PermYes" : "PermNo");
00242         }
00243 
00244                 LLString alertdesc;
00245         switch(sale_info.getSaleType())
00246         {
00247           case LLSaleInfo::FS_ORIGINAL:
00248                 alertdesc = owner_name.empty() ? "BuyOriginalNoOwner" : "BuyOriginal";
00249                 break;
00250           case LLSaleInfo::FS_CONTENTS:
00251                 alertdesc = owner_name.empty() ? "BuyContentsNoOwner" : "BuyContents";
00252                 break;
00253                   case LLSaleInfo::FS_COPY:
00254           default:
00255                 alertdesc = owner_name.empty() ? "BuyCopyNoOwner" : "BuyCopy";
00256                 break;
00257         }
00258 
00259         gViewerWindow->alertXml(alertdesc, args, LLTaskInvFVBridge::commitBuyItem, (void*)inv);
00260         }
00261 }
00262 
00263 S32 LLTaskInvFVBridge::getPrice()
00264 {
00265         LLInventoryItem* item = findItem();
00266         if(item)
00267         {
00268                 return item->getSaleInfo().getSalePrice();
00269         }
00270         else
00271         {
00272                 return -1;
00273         }
00274 }
00275 
00276 // static
00277 void LLTaskInvFVBridge::commitBuyItem(S32 option, void* data)
00278 {
00279         LLBuyInvItemData* inv = (LLBuyInvItemData*)data;
00280         if(!inv) return;
00281         if(0 == option)
00282         {
00283                 LLViewerObject* object = gObjectList.findObject(inv->mTaskID);
00284                 if(!object || !object->getRegion()) return;
00285 
00286 
00287                 LLMessageSystem* msg = gMessageSystem;
00288                 msg->newMessageFast(_PREHASH_BuyObjectInventory);
00289                 msg->nextBlockFast(_PREHASH_AgentData);
00290                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00291                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00292                 msg->nextBlockFast(_PREHASH_Data);
00293                 msg->addUUIDFast(_PREHASH_ObjectID, inv->mTaskID);
00294                 msg->addUUIDFast(_PREHASH_ItemID, inv->mItemID);
00295                 msg->addUUIDFast(_PREHASH_FolderID,
00296                                                  gInventory.findCategoryUUIDForType(inv->mType));
00297                 msg->sendReliable(object->getRegion()->getHost());
00298         }
00299         delete inv;
00300 }
00301 
00302 const LLString& LLTaskInvFVBridge::getName() const
00303 {
00304         return mName;
00305 }
00306 
00307 const LLString& LLTaskInvFVBridge::getDisplayName() const
00308 {
00309         LLInventoryItem* item = findItem();
00310         if(item)
00311         {
00312                 mDisplayName.assign(item->getName());
00313 
00314                 const LLPermissions& perm(item->getPermissions());
00315                 BOOL copy = gAgent.allowOperation(PERM_COPY, perm, GP_OBJECT_MANIPULATE);
00316                 BOOL mod  = gAgent.allowOperation(PERM_MODIFY, perm, GP_OBJECT_MANIPULATE);
00317                 BOOL xfer = gAgent.allowOperation(PERM_TRANSFER, perm, GP_OBJECT_MANIPULATE);
00318 
00319                 if(!copy)
00320                 {
00321                         mDisplayName.append(" (no copy)");
00322                 }
00323                 if(!mod)
00324                 {
00325                         mDisplayName.append(" (no modify)");
00326                 }
00327                 if(!xfer)
00328                 {
00329                         mDisplayName.append(" (no transfer)");
00330                 }
00331         }
00332 
00333         return mDisplayName;
00334 }
00335 
00336 // BUG: No creation dates for task inventory
00337 U32 LLTaskInvFVBridge::getCreationDate() const
00338 {
00339         return 0;
00340 }
00341 
00342 LLViewerImage* LLTaskInvFVBridge::getIcon() const
00343 {
00344         BOOL item_is_multi = FALSE;
00345         if ( mFlags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS )
00346         {
00347                 item_is_multi = TRUE;
00348         }
00349 
00350         return get_item_icon(LLAssetType::AT_OBJECT, LLInventoryType::IT_OBJECT, 0, item_is_multi );
00351 }
00352 
00353 void LLTaskInvFVBridge::openItem()
00354 {
00355         // no-op.
00356         lldebugs << "LLTaskInvFVBridge::openItem()" << llendl;
00357 }
00358 
00359 void LLTaskInvFVBridge::previewItem()
00360 {
00361         openItem();
00362 }
00363 
00364 BOOL LLTaskInvFVBridge::isItemRenameable() const
00365 {
00366         if(gAgent.isGodlike()) return TRUE;
00367         LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
00368         if(object)
00369         {
00370                 LLInventoryItem* item;
00371                 item = (LLInventoryItem*)(object->getInventoryObject(mUUID));
00372                 if(item && gAgent.allowOperation(PERM_MODIFY, item->getPermissions(),
00373                                                                                  GP_OBJECT_MANIPULATE, GOD_LIKE))
00374                 {
00375                         return TRUE;
00376                 }
00377         }
00378         return FALSE;
00379 }
00380 
00381 BOOL LLTaskInvFVBridge::renameItem(const LLString& new_name)
00382 {
00383         LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
00384         if(object)
00385         {
00386                 LLViewerInventoryItem* item = NULL;
00387                 item = (LLViewerInventoryItem*)object->getInventoryObject(mUUID);
00388                 if(item && (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(),
00389                                                                                 GP_OBJECT_MANIPULATE, GOD_LIKE)))
00390                 {
00391                         LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
00392                         new_item->rename(new_name);
00393                         object->updateInventory(
00394                                 new_item,
00395                                 TASK_INVENTORY_ITEM_KEY,
00396                                 false);
00397                 }
00398         }
00399         return TRUE;
00400 }
00401 
00402 BOOL LLTaskInvFVBridge::isItemMovable()
00403 {
00404         //LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
00405         //if(object && (object->permModify() || gAgent.isGodlike()))
00406         //{
00407         //      return TRUE;
00408         //}
00409         //return FALSE;
00410         return TRUE;
00411 }
00412 
00413 BOOL LLTaskInvFVBridge::isItemRemovable()
00414 {
00415         LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
00416         if(object
00417            && (object->permModify() || object->permYouOwner()))
00418         {
00419                 return TRUE;
00420         }
00421         return FALSE;
00422 }
00423 
00424 // helper for remove
00425 typedef std::pair<LLUUID, std::list<LLUUID> > two_uuids_list_t;
00426 typedef std::pair<LLPanelInventory*, two_uuids_list_t> remove_data_t;
00427 
00428 void remove_task_inventory_callback(S32 option, void* user_data)
00429 {
00430         remove_data_t* data = (remove_data_t*)user_data;
00431         LLViewerObject* object = NULL;
00432         object = gObjectList.findObject(data->second.first);
00433         if(option == 0 && object)
00434         {
00435                 // yes
00436                 std::list<LLUUID>::iterator list_it;
00437                 std::list<LLUUID>& id_list = data->second.second;
00438                 for (list_it = id_list.begin(); list_it != id_list.end(); ++list_it)
00439                 {
00440                         object->removeInventory(*list_it);
00441                 }
00442 
00443                 // refresh the UI.
00444                 data->first->refresh();
00445         }
00446         delete data;
00447 }
00448 
00449 BOOL LLTaskInvFVBridge::removeItem()
00450 {
00451         if(isItemRemovable() && mPanel)
00452         {
00453                 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
00454                 if(object)
00455                 {
00456                         if(object->permModify())
00457                         {
00458                                 // just do it.
00459                                 object->removeInventory(mUUID);
00460                                 return TRUE;
00461                         }
00462                         else
00463                         {
00464                                 remove_data_t* data = new remove_data_t;
00465                                 data->first = mPanel;
00466                                 data->second.first = mPanel->getTaskUUID();
00467                                 data->second.second.push_back(mUUID);
00468                                 gViewerWindow->alertXml("RemoveItemWarn", remove_task_inventory_callback, (void*)data);
00469                                 return FALSE;
00470                         }
00471                 }
00472         }
00473         return FALSE;
00474 }
00475 
00476 void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch)
00477 {
00478         if (!mPanel)
00479         {
00480                 return;
00481         }
00482 
00483         LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
00484         if (!object)
00485         {
00486                 return;
00487         }
00488 
00489         if (!object->permModify())
00490         {
00491                 remove_data_t* data = new remove_data_t;
00492                 data->first = mPanel;
00493                 data->second.first = mPanel->getTaskUUID();
00494                 for (S32 i = 0; i < (S32)batch.size(); i++)
00495                 {
00496                         LLTaskInvFVBridge* itemp = (LLTaskInvFVBridge*)batch[i];
00497                         data->second.second.push_back(itemp->getUUID());
00498                 }
00499                 gViewerWindow->alertXml("RemoveItemWarn", remove_task_inventory_callback, (void*)data);
00500         }
00501         else
00502         {
00503                 for (S32 i = 0; i < (S32)batch.size(); i++)
00504                 {
00505                         LLTaskInvFVBridge* itemp = (LLTaskInvFVBridge*)batch[i];
00506 
00507                         if(itemp->isItemRemovable())
00508                         {
00509                                 // just do it.
00510                                 object->removeInventory(itemp->getUUID());
00511                         }
00512                 }
00513         }
00514 }
00515 
00516 void LLTaskInvFVBridge::move(LLFolderViewEventListener* parent_listener)
00517 {
00518 }
00519 
00520 BOOL LLTaskInvFVBridge::isItemCopyable() const
00521 {
00522         LLInventoryItem* item = findItem();
00523         if(!item) return FALSE;
00524         return gAgent.allowOperation(PERM_COPY, item->getPermissions(),
00525                                                                 GP_OBJECT_MANIPULATE);
00526 }
00527 
00528 BOOL LLTaskInvFVBridge::copyToClipboard() const
00529 {
00530         return FALSE;
00531 }
00532 
00533 void LLTaskInvFVBridge::cutToClipboard()
00534 {
00535 }
00536 
00537 BOOL LLTaskInvFVBridge::isClipboardPasteable() const
00538 {
00539         return FALSE;
00540 }
00541 
00542 void LLTaskInvFVBridge::pasteFromClipboard()
00543 {
00544 }
00545 
00546 BOOL LLTaskInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id)
00547 {
00548         //llinfos << "LLTaskInvFVBridge::startDrag()" << llendl;
00549         if(mPanel)
00550         {
00551                 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
00552                 if(object)
00553                 {
00554                         LLInventoryItem* inv = NULL;
00555                         if((inv = (LLInventoryItem*)object->getInventoryObject(mUUID)))
00556                         {
00557                                 const LLPermissions& perm = inv->getPermissions();
00558                                 bool can_copy = gAgent.allowOperation(PERM_COPY, perm,
00559                                                                                                                 GP_OBJECT_MANIPULATE);
00560                                 if (object->isAttachment() && !can_copy)
00561                                 {
00562                     //RN: no copy contents of attachments cannot be dragged out
00563                     // due to a race condition and possible exploit where
00564                     // attached objects do not update their inventory items
00565                     // when their contents are manipulated
00566                     return FALSE;
00567                                 }
00568                                 if((can_copy && perm.allowTransferTo(gAgent.getID()))
00569                                    || object->permYouOwner())
00570 //                                 || gAgent.isGodlike())
00571 
00572                                 {
00573                                         *type = LLAssetType::lookupDragAndDropType(inv->getType());
00574 
00575                                         *id = inv->getUUID();
00576                                         return TRUE;
00577                                 }
00578                         }
00579                 }
00580         }
00581         return FALSE;
00582 }
00583 
00584 BOOL LLTaskInvFVBridge::dragOrDrop(MASK mask, BOOL drop,
00585                                                                    EDragAndDropType cargo_type,
00586                                                                    void* cargo_data)
00587 {
00588         //llinfos << "LLTaskInvFVBridge::dragOrDrop()" << llendl;
00589         return FALSE;
00590 }
00591 
00592 //void LLTaskInvFVBridge::dropped()
00593 //{
00594 //      llwarns << "LLTaskInvFVBridge::dropped() - not implemented" << llendl;
00595 //}
00596 
00597 // virtual
00598 void LLTaskInvFVBridge::performAction(LLFolderView* folder, LLInventoryModel* model, LLString action)
00599 {
00600         if (action == "task_buy")
00601         {
00602                 // Check the price of the item.
00603                 S32 price = getPrice();
00604                 if (-1 == price)
00605                 {
00606                         llwarns << "label_buy_task_bridged_item: Invalid price" << llendl;
00607                 }
00608                 else
00609                 {
00610                         if (price > 0 && price > gStatusBar->getBalance())
00611                         {
00612                                 LLFloaterBuyCurrency::buyCurrency("This costs", price);
00613                         }
00614                         else
00615                         {
00616                                 buyItem();
00617                         }
00618                 }
00619         }
00620         else if (action == "task_open")
00621         {
00622                 openItem();
00623         }
00624         else if (action == "task_properties")
00625         {
00626                 showProperties();
00627         }
00628 }
00629 
00630 void LLTaskInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
00631 {
00632         LLInventoryItem* item = findItem();
00633         if(!item) return;
00634         std::vector<LLString> items;
00635         std::vector<LLString> disabled_items;
00636 
00637         if(gAgent.allowOperation(PERM_OWNER, item->getPermissions(),
00638                                                          GP_OBJECT_MANIPULATE)
00639            && item->getSaleInfo().isForSale())
00640         {
00641                 items.push_back("Task Buy");
00642 
00643                 LLString label("Buy");
00644                 // Check the price of the item.
00645                 S32 price = getPrice();
00646                 if (-1 == price)
00647                 {
00648                         llwarns << "label_buy_task_bridged_item: Invalid price" << llendl;
00649                 }
00650                 else
00651                 {
00652                         std::ostringstream info;
00653                         info << "Buy for L$" << price;
00654                         label.assign(info.str());
00655                 }
00656 
00657                 const LLView::child_list_t *list = menu.getChildList();
00658                 LLView::child_list_t::const_iterator itor;
00659                 for (itor = list->begin(); itor != list->end(); ++itor)
00660                 {
00661                         LLString name = (*itor)->getName();
00662                         if (name == "Task Buy" && (*itor)->getWidgetTag() == LL_MENU_ITEM_CALL_GL_TAG)
00663                         {
00664                                 ((LLMenuItemCallGL*)(*itor))->setLabel(label);
00665                         }
00666                 }
00667         }
00668         else
00669         {
00670                 items.push_back("Task Open");
00671                 if (!isItemCopyable())
00672                 {
00673                         disabled_items.push_back("Task Open");
00674                 }
00675         }
00676         items.push_back("Task Properties");
00677         if(isItemRenameable())
00678         {
00679                 items.push_back("Task Rename");
00680         }
00681         if(isItemRemovable())
00682         {
00683                 items.push_back("Task Remove");
00684         }
00685 
00686         hideContextEntries(menu, items, disabled_items);
00687 }
00688 
00689 
00693 
00694 class LLTaskCategoryBridge : public LLTaskInvFVBridge
00695 {
00696 public:
00697         LLTaskCategoryBridge(
00698                 LLPanelInventory* panel,
00699                 const LLUUID& uuid,
00700                 const LLString& name);
00701 
00702         virtual LLViewerImage* getIcon() const;
00703         virtual const LLString& getDisplayName() const { return getName(); }
00704         virtual BOOL isItemRenameable() const;
00705         virtual BOOL renameItem(const LLString& new_name);
00706         virtual BOOL isItemRemovable();
00707         virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
00708         virtual BOOL hasChildren() const;
00709         virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id);
00710         virtual BOOL dragOrDrop(MASK mask, BOOL drop,
00711                                                         EDragAndDropType cargo_type,
00712                                                         void* cargo_data);
00713 };
00714 
00715 LLTaskCategoryBridge::LLTaskCategoryBridge(
00716         LLPanelInventory* panel,
00717         const LLUUID& uuid,
00718         const LLString& name) :
00719         LLTaskInvFVBridge(panel, uuid, name)
00720 {
00721 }
00722 
00723 LLViewerImage* LLTaskCategoryBridge::getIcon() const
00724 {
00725         LLString uuid_string = gViewerArt.getString("inv_folder_plain_closed.tga");
00726         return gImageList.getImage(LLUUID(uuid_string), MIPMAP_FALSE, TRUE);
00727 }
00728 
00729 BOOL LLTaskCategoryBridge::isItemRenameable() const
00730 {
00731         return FALSE;
00732 }
00733 
00734 BOOL LLTaskCategoryBridge::renameItem(const LLString& new_name)
00735 {
00736         return FALSE;
00737 }
00738 
00739 BOOL LLTaskCategoryBridge::isItemRemovable()
00740 {
00741         return FALSE;
00742 }
00743 
00744 void LLTaskCategoryBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
00745 {
00746         std::vector<LLString> items;
00747         std::vector<LLString> disabled_items;
00748         items.push_back("Task Open");
00749         hideContextEntries(menu, items, disabled_items);
00750 }
00751 
00752 BOOL LLTaskCategoryBridge::hasChildren() const
00753 {
00754         // return TRUE if we have or do know know if we have children.
00755         // *FIX: For now, return FALSE - we will know for sure soon enough.
00756         return FALSE;
00757 }
00758 
00759 BOOL LLTaskCategoryBridge::startDrag(EDragAndDropType* type, LLUUID* id)
00760 {
00761         //llinfos << "LLTaskInvFVBridge::startDrag()" << llendl;
00762         if(mPanel)
00763         {
00764                 LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
00765                 if(object)
00766                 {
00767                         LLInventoryItem* inv = NULL;
00768                         if((inv = (LLInventoryItem*)object->getInventoryObject(mUUID)))
00769                         {
00770                                 const LLPermissions& perm = inv->getPermissions();
00771                                 bool can_copy = gAgent.allowOperation(PERM_COPY, perm,
00772                                                                                                                 GP_OBJECT_MANIPULATE);
00773                                 if((can_copy && perm.allowTransferTo(gAgent.getID()))
00774                                    || object->permYouOwner())
00775 //                                 || gAgent.isGodlike())
00776 
00777                                 {
00778                                         *type = LLAssetType::lookupDragAndDropType(inv->getType());
00779 
00780                                         *id = inv->getUUID();
00781                                         return TRUE;
00782                                 }
00783                         }
00784                 }
00785         }
00786         return FALSE;
00787 }
00788 
00789 BOOL LLTaskCategoryBridge::dragOrDrop(MASK mask, BOOL drop,
00790                                                                           EDragAndDropType cargo_type,
00791                                                                           void* cargo_data)
00792 {
00793         //llinfos << "LLTaskCategoryBridge::dragOrDrop()" << llendl;
00794         BOOL accept = FALSE;
00795         LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
00796         if(object)
00797         {
00798                 switch(cargo_type)
00799                 {
00800                 case DAD_CATEGORY:
00801                         accept = gToolDragAndDrop->dadUpdateInventoryCategory(object,drop);
00802                         break;
00803                 case DAD_TEXTURE:
00804                 case DAD_SOUND:
00805                 case DAD_LANDMARK:
00806                 case DAD_OBJECT:
00807                 case DAD_NOTECARD:
00808                 case DAD_CLOTHING:
00809                 case DAD_BODYPART:
00810                 case DAD_ANIMATION:
00811                 case DAD_GESTURE:
00812                         // *HACK: In order to resolve SL-22177, we need to block
00813                         // drags from notecards and objects onto other
00814                         // objects. uncomment the simpler version when we have
00815                         // that right.
00816                         //accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data);
00817                         if(LLToolDragAndDrop::isInventoryDropAcceptable(
00818                                    object, (LLViewerInventoryItem*)cargo_data)
00819                            && (LLToolDragAndDrop::SOURCE_WORLD != gToolDragAndDrop->getSource())
00820                            && (LLToolDragAndDrop::SOURCE_NOTECARD != gToolDragAndDrop->getSource()))
00821                         {
00822                                 accept = TRUE;
00823                         }
00824                         if(accept && drop)
00825                         {
00826                                 LLToolDragAndDrop::dropInventory(object,
00827                                                                                                  (LLViewerInventoryItem*)cargo_data,
00828                                                                                                  gToolDragAndDrop->getSource(),
00829                                                                                                  gToolDragAndDrop->getSourceID());
00830                         }
00831                         break;
00832                 case DAD_SCRIPT:
00833                         // *HACK: In order to resolve SL-22177, we need to block
00834                         // drags from notecards and objects onto other
00835                         // objects. uncomment the simpler version when we have
00836                         // that right.
00837                         //accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data);
00838                         if(LLToolDragAndDrop::isInventoryDropAcceptable(
00839                                    object, (LLViewerInventoryItem*)cargo_data)
00840                            && (LLToolDragAndDrop::SOURCE_WORLD != gToolDragAndDrop->getSource())
00841                            && (LLToolDragAndDrop::SOURCE_NOTECARD != gToolDragAndDrop->getSource()))
00842                         {
00843                                 accept = TRUE;
00844                         }
00845                         if(accept && drop)
00846                         {
00847                                 LLViewerInventoryItem* item = (LLViewerInventoryItem*)cargo_data;
00848                                 // rez in the script active by default, rez in
00849                                 // inactive if the control key is being held down.
00850                                 BOOL active = ((mask & MASK_CONTROL) == 0);
00851                                 LLToolDragAndDrop::dropScript(object, item, active,
00852                                                                                           gToolDragAndDrop->getSource(),
00853                                                                                           gToolDragAndDrop->getSourceID());
00854                         }
00855                         break;
00856                 case DAD_CALLINGCARD:
00857                 default:
00858                         break;
00859                 }
00860         }
00861         return accept;
00862 }
00863 
00867 
00868 class LLTaskTextureBridge : public LLTaskInvFVBridge
00869 {
00870 public:
00871         LLTaskTextureBridge(
00872                 LLPanelInventory* panel,
00873                 const LLUUID& uuid,
00874                 const LLString& name,
00875                 LLInventoryType::EType it);
00876 
00877         virtual LLViewerImage* getIcon() const;
00878         virtual void openItem();
00879 protected:
00880         LLInventoryType::EType mInventoryType;
00881 };
00882 
00883 LLTaskTextureBridge::LLTaskTextureBridge(
00884         LLPanelInventory* panel,
00885         const LLUUID& uuid,
00886         const LLString& name,
00887         LLInventoryType::EType it) :
00888         LLTaskInvFVBridge(panel, uuid, name),
00889         mInventoryType(it)
00890 {
00891 }
00892 
00893 LLViewerImage* LLTaskTextureBridge::getIcon() const
00894 {
00895         return get_item_icon(LLAssetType::AT_TEXTURE, mInventoryType, 0, FALSE);
00896 }
00897 
00898 void LLTaskTextureBridge::openItem()
00899 {
00900         llinfos << "LLTaskTextureBridge::openItem()" << llendl;
00901         if(!LLPreview::show(mUUID))
00902         {
00903                 // There isn't one, so make a new preview
00904                 S32 left, top;
00905                 gFloaterView->getNewFloaterPosition(&left, &top);
00906                 LLRect rect = gSavedSettings.getRect("PreviewTextureRect");
00907                 rect.translate( left - rect.mLeft, top - rect.mTop );
00908                 LLPreviewTexture* preview = new LLPreviewTexture("preview task texture",
00909                                                                                                  rect,
00910                                                                                                  getName(),
00911                                                                                                  mUUID,
00912                                                                                                  mPanel->getTaskUUID());
00913                 preview->setFocus(TRUE);
00914         }
00915 }
00916 
00917 
00921 
00922 class LLTaskSoundBridge : public LLTaskInvFVBridge
00923 {
00924 public:
00925         LLTaskSoundBridge(
00926                 LLPanelInventory* panel,
00927                 const LLUUID& uuid,
00928                 const LLString& name);
00929 
00930         virtual LLViewerImage* getIcon() const;
00931         virtual void openItem();
00932         virtual void performAction(LLFolderView* folder, LLInventoryModel* model, LLString action);
00933         virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
00934         static void openSoundPreview(void* data);
00935 };
00936 
00937 LLTaskSoundBridge::LLTaskSoundBridge(
00938         LLPanelInventory* panel,
00939         const LLUUID& uuid,
00940         const LLString& name) :
00941         LLTaskInvFVBridge(panel, uuid, name)
00942 {
00943 }
00944 
00945 LLViewerImage* LLTaskSoundBridge::getIcon() const
00946 {
00947         return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE);
00948 }
00949 
00950 void LLTaskSoundBridge::openItem()
00951 {
00952         openSoundPreview((void*)this);
00953 }
00954 
00955 void LLTaskSoundBridge::openSoundPreview(void* data)
00956 {
00957         LLTaskSoundBridge* self = (LLTaskSoundBridge*)data;
00958         if(!self) return;
00959         if(!LLPreview::show(self->mUUID))
00960         {
00961                 // There isn't one, so make a new preview
00962                 S32 left, top;
00963                 gFloaterView->getNewFloaterPosition(&left, &top);
00964                 LLRect rect = gSavedSettings.getRect("PreviewSoundRect");
00965                 rect.translate(left - rect.mLeft, top - rect.mTop);
00966                 LLPreviewSound* floaterp =      new LLPreviewSound("preview task sound",
00967                                                            rect,
00968                                                            self->getName(),
00969                                                            self->mUUID,
00970                                                            self->mPanel->getTaskUUID());
00971                 floaterp->open();       /*Flawfinder: ignore*/
00972         }
00973 }
00974 
00975 // virtual
00976 void LLTaskSoundBridge::performAction(LLFolderView* folder, LLInventoryModel* model, LLString action)
00977 {
00978         if (action == "task_play")
00979         {
00980                 LLInventoryItem* item = findItem();
00981                 if(item)
00982                 {
00983                         send_sound_trigger(item->getAssetUUID(), 1.0);
00984                 }
00985         }
00986         LLTaskInvFVBridge::performAction(folder, model, action);
00987 }
00988 
00989 void LLTaskSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
00990 {
00991         LLInventoryItem* item = findItem();
00992         if(!item) return;
00993         std::vector<LLString> items;
00994         std::vector<LLString> disabled_items;
00995 
00996         if(item->getPermissions().getOwner() != gAgent.getID()
00997            && item->getSaleInfo().isForSale())
00998         {
00999                 items.push_back("Task Buy");
01000 
01001                 LLString label("Buy");
01002                 // Check the price of the item.
01003                 S32 price = getPrice();
01004                 if (-1 == price)
01005                 {
01006                         llwarns << "label_buy_task_bridged_item: Invalid price" << llendl;
01007                 }
01008                 else
01009                 {
01010                         std::ostringstream info;
01011                         info << "Buy for L$" << price;
01012                         label.assign(info.str());
01013                 }
01014 
01015                 const LLView::child_list_t *list = menu.getChildList();
01016                 LLView::child_list_t::const_iterator itor;
01017                 for (itor = list->begin(); itor != list->end(); ++itor)
01018                 {
01019                         LLString name = (*itor)->getName();
01020                         if (name == "Task Buy" && (*itor)->getWidgetTag() == LL_MENU_ITEM_CALL_GL_TAG)
01021                         {
01022                                 ((LLMenuItemCallGL*)(*itor))->setLabel(label);
01023                         }
01024                 }
01025         }
01026         else
01027         {
01028                 items.push_back("Task Open");
01029                 if (!isItemCopyable())
01030                 {
01031                         disabled_items.push_back("Task Open");
01032                 }
01033         }
01034         items.push_back("Task Properties");
01035         if(isItemRenameable())
01036         {
01037                 items.push_back("Task Rename");
01038         }
01039         if(isItemRemovable())
01040         {
01041                 items.push_back("Task Remove");
01042         }
01043 
01044         items.push_back("Task Play");
01045         /*menu.appendSeparator();
01046         menu.append(new LLMenuItemCallGL("Play",
01047                                                                          &LLTaskSoundBridge::playSound,
01048                                                                          NULL,
01049                                                                          (void*)this));*/
01050 
01051         hideContextEntries(menu, items, disabled_items);
01052 }
01053 
01057 
01058 class LLTaskLandmarkBridge : public LLTaskInvFVBridge
01059 {
01060 public:
01061         LLTaskLandmarkBridge(
01062                 LLPanelInventory* panel,
01063                 const LLUUID& uuid,
01064                 const LLString& name);
01065 
01066         virtual LLViewerImage* getIcon() const;
01067 };
01068 
01069 LLTaskLandmarkBridge::LLTaskLandmarkBridge(
01070         LLPanelInventory* panel,
01071         const LLUUID& uuid,
01072         const LLString& name) :
01073         LLTaskInvFVBridge(panel, uuid, name)
01074 {
01075 }
01076 
01077 LLViewerImage* LLTaskLandmarkBridge::getIcon() const
01078 {
01079         return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, 0, FALSE);
01080 }
01081 
01082 
01086 
01087 class LLTaskCallingCardBridge : public LLTaskInvFVBridge
01088 {
01089 public:
01090         LLTaskCallingCardBridge(
01091                 LLPanelInventory* panel,
01092                 const LLUUID& uuid,
01093                 const LLString& name);
01094 
01095         virtual LLViewerImage* getIcon() const;
01096         virtual BOOL isItemRenameable() const;
01097         virtual BOOL renameItem(const LLString& new_name);
01098 };
01099 
01100 LLTaskCallingCardBridge::LLTaskCallingCardBridge(
01101         LLPanelInventory* panel,
01102         const LLUUID& uuid,
01103         const LLString& name) :
01104         LLTaskInvFVBridge(panel, uuid, name)
01105 {
01106 }
01107 
01108 LLViewerImage* LLTaskCallingCardBridge::getIcon() const
01109 {
01110         return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, 0, FALSE);
01111 }
01112 
01113 BOOL LLTaskCallingCardBridge::isItemRenameable() const
01114 {
01115         return FALSE;
01116 }
01117 
01118 BOOL LLTaskCallingCardBridge::renameItem(const LLString& new_name)
01119 {
01120         return FALSE;
01121 }
01122 
01123 
01127 
01128 class LLTaskScriptBridge : public LLTaskInvFVBridge
01129 {
01130 public:
01131         LLTaskScriptBridge(
01132                 LLPanelInventory* panel,
01133                 const LLUUID& uuid,
01134                 const LLString& name);
01135 
01136         virtual LLViewerImage* getIcon() const;
01137         //static BOOL enableIfCopyable( void* userdata );
01138 };
01139 
01140 LLTaskScriptBridge::LLTaskScriptBridge(
01141         LLPanelInventory* panel,
01142         const LLUUID& uuid,
01143         const LLString& name) :
01144         LLTaskInvFVBridge(panel, uuid, name)
01145 {
01146 }
01147 
01148 LLViewerImage* LLTaskScriptBridge::getIcon() const
01149 {
01150         return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
01151 }
01152 
01153 
01154 class LLTaskLSLBridge : public LLTaskScriptBridge
01155 {
01156 public:
01157         LLTaskLSLBridge(
01158                 LLPanelInventory* panel,
01159                 const LLUUID& uuid,
01160                 const LLString& name);
01161 
01162         virtual void openItem();
01163         virtual BOOL removeItem();
01164         //virtual void buildContextMenu(LLMenuGL& menu);
01165 
01166         //static void copyToInventory(void* userdata);
01167 };
01168 
01169 LLTaskLSLBridge::LLTaskLSLBridge(
01170         LLPanelInventory* panel,
01171         const LLUUID& uuid,
01172         const LLString& name) :
01173         LLTaskScriptBridge(panel, uuid, name)
01174 {
01175 }
01176 
01177 void LLTaskLSLBridge::openItem()
01178 {
01179         llinfos << "LLTaskLSLBridge::openItem() " << mUUID << llendl;
01180         if(LLLiveLSLEditor::show(mUUID, mPanel->getTaskUUID()))
01181         {
01182                 return;
01183         }
01184         LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
01185         if(!object || object->isInventoryPending())
01186         {
01187                 return;
01188         }
01189         if(object->permModify() || gAgent.isGodlike())
01190         {
01191                 LLString title("Script: ");
01192                 LLInventoryItem* item = findItem();
01193                 if (item)
01194                 {
01195                         title.append(item->getName());
01196                 }
01197 
01198                 S32 left, top;
01199                 gFloaterView->getNewFloaterPosition(&left, &top);
01200                 LLRect rect = gSavedSettings.getRect("PreviewScriptRect");
01201                 rect.translate(left - rect.mLeft, top - rect.mTop);
01202                 LLLiveLSLEditor* editor;
01203                 editor = new LLLiveLSLEditor("lsl ed",
01204                                                                            rect,
01205                                                                            title,
01206                                                                            mPanel->getTaskUUID(),
01207                                                                            mUUID);
01208                 LLMultiFloater* previous_host = LLFloater::getFloaterHost();
01209                 LLFloater::setFloaterHost(NULL);
01210                 editor->open(); /*Flawfinder: ignore*/
01211                 LLFloater::setFloaterHost(previous_host);
01212 
01213                 // keep onscreen
01214                 gFloaterView->adjustToFitScreen(editor, FALSE);
01215         }
01216 }
01217 
01218 BOOL LLTaskLSLBridge::removeItem()
01219 {
01220         LLLiveLSLEditor::hide(mUUID, mPanel->getTaskUUID());
01221         return LLTaskInvFVBridge::removeItem();
01222 }
01223 
01227 
01228 class LLTaskObjectBridge : public LLTaskInvFVBridge
01229 {
01230 public:
01231         LLTaskObjectBridge(
01232                 LLPanelInventory* panel,
01233                 const LLUUID& uuid,
01234                 const LLString& name);
01235 
01236         virtual LLViewerImage* getIcon() const;
01237 };
01238 
01239 LLTaskObjectBridge::LLTaskObjectBridge(
01240         LLPanelInventory* panel,
01241         const LLUUID& uuid,
01242         const LLString& name) :
01243         LLTaskInvFVBridge(panel, uuid, name)
01244 {
01245 }
01246 
01247 LLViewerImage* LLTaskObjectBridge::getIcon() const
01248 {
01249         BOOL item_is_multi = FALSE;
01250         if ( mFlags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS )
01251         {
01252                 item_is_multi = TRUE;
01253         }
01254 
01255         return get_item_icon(LLAssetType::AT_OBJECT, LLInventoryType::IT_OBJECT, 0, item_is_multi);
01256 }
01257 
01261 
01262 class LLTaskNotecardBridge : public LLTaskInvFVBridge
01263 {
01264 public:
01265         LLTaskNotecardBridge(
01266                 LLPanelInventory* panel,
01267                 const LLUUID& uuid,
01268                 const LLString& name);
01269 
01270         virtual LLViewerImage* getIcon() const;
01271         virtual void openItem();
01272         virtual BOOL removeItem();
01273 };
01274 
01275 LLTaskNotecardBridge::LLTaskNotecardBridge(
01276         LLPanelInventory* panel,
01277         const LLUUID& uuid,
01278         const LLString& name) :
01279         LLTaskInvFVBridge(panel, uuid, name)
01280 {
01281 }
01282 
01283 LLViewerImage* LLTaskNotecardBridge::getIcon() const
01284 {
01285         return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE);
01286 }
01287 
01288 void LLTaskNotecardBridge::openItem()
01289 {
01290         if(LLPreview::show(mUUID))
01291         {
01292                 return;
01293         }
01294         LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
01295         if(!object || object->isInventoryPending())
01296         {
01297                 return;
01298         }
01299         if(object->permModify() || gAgent.isGodlike())
01300         {
01301                 S32 left, top;
01302                 gFloaterView->getNewFloaterPosition(&left, &top);
01303                 LLRect rect = gSavedSettings.getRect("PreviewScriptRect");
01304                 rect.translate(left - rect.mLeft, top - rect.mTop);
01305                 LLPreviewNotecard* preview;
01306                 preview = new LLPreviewNotecard("live notecard editor",
01307                                                                                  rect,
01308                                                                                  getName(),
01309                                                                                  mUUID,
01310                                                                                  mPanel->getTaskUUID());
01311                 preview->setFocus(TRUE);  // if you're opening a notecard from an object's inventory, it takes focus
01312 
01313                 // keep onscreen
01314                 gFloaterView->adjustToFitScreen(preview, FALSE);
01315         }
01316 }
01317 
01318 BOOL LLTaskNotecardBridge::removeItem()
01319 {
01320         LLPreview::hide(mUUID);
01321         return LLTaskInvFVBridge::removeItem();
01322 }
01323 
01327 
01328 class LLTaskGestureBridge : public LLTaskInvFVBridge
01329 {
01330 public:
01331         LLTaskGestureBridge(
01332                 LLPanelInventory* panel,
01333                 const LLUUID& uuid,
01334                 const LLString& name);
01335 
01336         virtual LLViewerImage* getIcon() const;
01337         virtual void openItem();
01338         virtual BOOL removeItem();
01339 };
01340 
01341 LLTaskGestureBridge::LLTaskGestureBridge(
01342         LLPanelInventory* panel,
01343         const LLUUID& uuid,
01344         const LLString& name) :
01345         LLTaskInvFVBridge(panel, uuid, name)
01346 {
01347 }
01348 
01349 LLViewerImage* LLTaskGestureBridge::getIcon() const
01350 {
01351         return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE);
01352 }
01353 
01354 void LLTaskGestureBridge::openItem()
01355 {
01356         if(LLPreview::show(mUUID))
01357         {
01358                 return;
01359         }
01360         LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
01361         if(!object || object->isInventoryPending())
01362         {
01363                 return;
01364         }
01365 
01366         // TODO: save rectangle
01367         LLString title = getName();
01368         LLUUID item_id = mUUID;
01369         LLUUID object_id = mPanel->getTaskUUID();
01370         LLPreviewGesture* preview = LLPreviewGesture::show(title, item_id, object_id);
01371 
01372         // keep onscreen
01373         gFloaterView->adjustToFitScreen(preview, FALSE);
01374 }
01375 
01376 BOOL LLTaskGestureBridge::removeItem()
01377 {
01378         // Don't need to deactivate gesture because gestures inside objects
01379         // can never be active.
01380         LLPreview::hide(mUUID);
01381         return LLTaskInvFVBridge::removeItem();
01382 }
01383 
01387 
01388 class LLTaskAnimationBridge : public LLTaskInvFVBridge
01389 {
01390 public:
01391         LLTaskAnimationBridge(
01392                 LLPanelInventory* panel,
01393                 const LLUUID& uuid,
01394                 const LLString& name);
01395 
01396         virtual LLViewerImage* getIcon() const;
01397         virtual void openItem();
01398         virtual BOOL removeItem();
01399 };
01400 
01401 LLTaskAnimationBridge::LLTaskAnimationBridge(
01402         LLPanelInventory* panel,
01403         const LLUUID& uuid,
01404         const LLString& name) :
01405         LLTaskInvFVBridge(panel, uuid, name)
01406 {
01407 }
01408 
01409 LLViewerImage* LLTaskAnimationBridge::getIcon() const
01410 {
01411         return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE);
01412 }
01413 
01414 void LLTaskAnimationBridge::openItem()
01415 {
01416         if(LLPreview::show(mUUID))
01417         {
01418                 return;
01419         }
01420         LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
01421         if(!object || object->isInventoryPending())
01422         {
01423                 return;
01424         }
01425 
01426         // TODO: what permissions allow looking at animation?
01427         if(object->permModify() || gAgent.isGodlike())
01428         {
01429                 // TODO: save rectangle
01430                 LLString title = getName();
01431                 LLUUID item_id = mUUID;
01432                 LLUUID object_id = mPanel->getTaskUUID();
01433 
01434                 if(!LLPreview::show(mUUID))
01435                 {
01436                         // There isn't one, so make a new preview
01437                         S32 left, top;
01438                         gFloaterView->getNewFloaterPosition(&left, &top);
01439                         LLRect rect = gSavedSettings.getRect("PreviewAnimRect");
01440                         rect.translate(left - rect.mLeft, top - rect.mTop);
01441 
01442                         LLPreviewAnim* preview = new LLPreviewAnim("preview anim",
01443                                                                         rect,
01444                                                                    getName(),
01445                                                                    mUUID,
01446                                                                    0,
01447                                                                    mPanel->getTaskUUID());
01448                         preview->setFocus(TRUE);  // take focus if you're looking at one of these
01449 
01450                         // Force to be entirely onscreen.
01451                         gFloaterView->adjustToFitScreen(preview, FALSE);
01452                 }
01453         }
01454 }
01455 
01456 BOOL LLTaskAnimationBridge::removeItem()
01457 {
01458         LLPreview::hide(mUUID);
01459         return LLTaskInvFVBridge::removeItem();
01460 }
01461 
01465 
01466 class LLTaskWearableBridge : public LLTaskInvFVBridge
01467 {
01468 public:
01469         LLTaskWearableBridge(
01470                 LLPanelInventory* panel,
01471                 const LLUUID& uuid,
01472                 const LLString& name,
01473                 LLAssetType::EType asset_type,
01474                 U32 flags);
01475 
01476         virtual LLViewerImage* getIcon() const;
01477 
01478 protected:
01479         LLAssetType::EType              mAssetType;
01480 };
01481 
01482 LLTaskWearableBridge::LLTaskWearableBridge(
01483         LLPanelInventory* panel,
01484         const LLUUID& uuid,
01485         const LLString& name,
01486         LLAssetType::EType asset_type,
01487         U32 flags) :
01488         LLTaskInvFVBridge(panel, uuid, name, flags),
01489         mAssetType( asset_type )
01490 {
01491 }
01492 
01493 LLViewerImage* LLTaskWearableBridge::getIcon() const
01494 {
01495         return get_item_icon(mAssetType, LLInventoryType::IT_WEARABLE, mFlags, FALSE );
01496 }
01497 
01498 
01501 //----------------------------------------------------------------------------
01502 
01503 LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelInventory* panel,
01504                                                                                                                  LLInventoryObject* object)
01505 {
01506         LLTaskInvFVBridge* new_bridge = NULL;
01507         LLAssetType::EType type = object->getType();
01508         LLInventoryItem* item = NULL;
01509         switch(type)
01510         {
01511         case LLAssetType::AT_TEXTURE:
01512                 item = (LLInventoryItem*)object;
01513                 new_bridge = new LLTaskTextureBridge(panel,
01514                                                                                          object->getUUID(),
01515                                                                                          object->getName(),
01516                                                                                          item->getInventoryType());
01517                 break;
01518         case LLAssetType::AT_SOUND:
01519                 new_bridge = new LLTaskSoundBridge(panel,
01520                                                                                    object->getUUID(),
01521                                                                                    object->getName());
01522                 break;
01523         case LLAssetType::AT_LANDMARK:
01524                 new_bridge = new LLTaskLandmarkBridge(panel,
01525                                                                                           object->getUUID(),
01526                                                                                           object->getName());
01527                 break;
01528         case LLAssetType::AT_CALLINGCARD:
01529                 new_bridge = new LLTaskCallingCardBridge(panel,
01530                                                                                                  object->getUUID(),
01531                                                                                                  object->getName());
01532                 break;
01533         case LLAssetType::AT_SCRIPT:
01534                 // OLD SCRIPTS DEPRECATED - JC
01535                 llwarns << "Old script" << llendl;
01536                 //new_bridge = new LLTaskOldScriptBridge(panel,
01537                 //                                                                         object->getUUID(),
01538                 //                                                                         object->getName());
01539                 break;
01540         case LLAssetType::AT_OBJECT:
01541                 new_bridge = new LLTaskObjectBridge(panel,
01542                                                                                         object->getUUID(),
01543                                                                                         object->getName());
01544                 break;
01545         case LLAssetType::AT_NOTECARD:
01546                 new_bridge = new LLTaskNotecardBridge(panel,
01547                                                                                           object->getUUID(),
01548                                                                                           object->getName());
01549                 break;
01550         case LLAssetType::AT_ANIMATION:
01551                 new_bridge = new LLTaskAnimationBridge(panel,
01552                                                                                           object->getUUID(),
01553                                                                                           object->getName());
01554                 break;
01555         case LLAssetType::AT_GESTURE:
01556                 new_bridge = new LLTaskGestureBridge(panel,
01557                                                                                           object->getUUID(),
01558                                                                                           object->getName());
01559                 break;
01560         case LLAssetType::AT_CLOTHING:
01561         case LLAssetType::AT_BODYPART:
01562                 item = (LLInventoryItem*)object;
01563                 new_bridge = new LLTaskWearableBridge(panel,
01564                                                                                           object->getUUID(),
01565                                                                                           object->getName(),
01566                                                                                           type,
01567                                                                                           item->getFlags());
01568                 break;
01569         case LLAssetType::AT_CATEGORY:
01570                 new_bridge = new LLTaskCategoryBridge(panel,
01571                                                                                           object->getUUID(),
01572                                                                                           object->getName());
01573                 break;
01574         case LLAssetType::AT_LSL_TEXT:
01575                 new_bridge = new LLTaskLSLBridge(panel,
01576                                                                                  object->getUUID(),
01577                                                                                  object->getName());
01578                 break;
01579         default:
01580                 llinfos << "Unhandled inventory type (llassetstorage.h): "
01581                                 << (S32)type << llendl;
01582                 break;
01583         }
01584         return new_bridge;
01585 }
01586 
01587 
01591 
01592 // Default constructor
01593 LLPanelInventory::LLPanelInventory(const LLString& name, const LLRect& rect) :
01594         LLPanel(name, rect),
01595         mScroller(NULL),
01596         mFolders(NULL),
01597         mHaveInventory(FALSE),
01598         mIsInventoryEmpty(TRUE),
01599         mInventoryNeedsUpdate(FALSE)
01600 {
01601         reset();
01602         // Callbacks
01603         init_object_inventory_panel_actions(this);
01604         gIdleCallbacks.addFunction(idle, this);
01605 }
01606 
01607 // Destroys the object
01608 LLPanelInventory::~LLPanelInventory()
01609 {
01610         if (!gIdleCallbacks.deleteFunction(idle, this))
01611         {
01612                 llwarns << "LLPanelInventory::~LLPanelInventory() failed to delete callback" << llendl;
01613         }
01614 }
01615 
01616 
01617 void LLPanelInventory::clearContents()
01618 {
01619         mHaveInventory = FALSE;
01620         mIsInventoryEmpty = TRUE;
01621         if (gToolDragAndDrop && gToolDragAndDrop->getSource() == LLToolDragAndDrop::SOURCE_WORLD)
01622         {
01623                 gToolDragAndDrop->endDrag();
01624         }
01625 
01626         if( mScroller )
01627         {
01628                 // removes mFolders
01629                 removeChild( mScroller );
01630                 mScroller->die();
01631                 mScroller = NULL;
01632                 mFolders = NULL;
01633         }
01634 }
01635 
01636 
01637 void LLPanelInventory::reset()
01638 {
01639         clearContents();
01640 
01641         setBorderVisible(FALSE);
01642 
01643         LLRect dummy_rect(0, 1, 1, 0);
01644         mFolders = new LLFolderView("task inventory", NULL, dummy_rect, getTaskUUID(), this);
01645         // this ensures that we never say "searching..." or "no items found"
01646         mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS);
01647 
01648         LLRect scroller_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
01649         mScroller = new LLScrollableContainerView(
01650                 "task inventory scroller", scroller_rect, mFolders );
01651         mScroller->setFollowsAll();
01652         addChild(mScroller);
01653 
01654         mFolders->setScrollContainer( mScroller );
01655 }
01656 
01657 void LLPanelInventory::inventoryChanged(LLViewerObject* object,
01658                                                                                 InventoryObjectList* inventory,
01659                                                                                 S32 serial_num,
01660                                                                                 void* data)
01661 {
01662         if(!object) return;
01663 
01664         //llinfos << "invetnory arrived: \n"
01665         //              << " panel UUID: " << panel->mTaskUUID << "\n"
01666         //              << " task  UUID: " << object->mID << llendl;
01667         if(mTaskUUID == object->mID)
01668         {
01669                 mInventoryNeedsUpdate = TRUE;
01670         }
01671 
01672         // refresh any properties floaters that are hanging around.
01673         if(inventory)
01674         {
01675                 // We need to copy the ones that need refreshing onto a
01676                 // temporary object because we cannot iterate through the
01677                 // object inventory twice... A pox on stateful iteration!
01678                 LLFloaterProperties* floater = NULL;
01679                 LLDynamicArray<LLFloaterProperties*> refresh;
01680 
01681                 InventoryObjectList::const_iterator it = inventory->begin();
01682                 InventoryObjectList::const_iterator end = inventory->end();
01683                 for( ;  it != end;      ++it)
01684                 {
01685                         floater = LLFloaterProperties::find((*it)->getUUID(),
01686                                                                                                 object->getID());
01687                         if(floater)
01688                         {
01689                                 refresh.put(floater);
01690                         }
01691                 }
01692                 S32 count = refresh.count();
01693                 for(S32 i = 0; i < count; ++i)
01694                 {
01695                         refresh.get(i)->refresh();
01696                 }
01697         }
01698 }
01699 
01700 void LLPanelInventory::updateInventory()
01701 {
01702         //llinfos << "inventory arrived: \n"
01703         //              << " panel UUID: " << panel->mTaskUUID << "\n"
01704         //              << " task  UUID: " << object->mID << llendl;
01705         // We're still interested in this task's inventory.
01706         std::set<LLUUID> selected_items;
01707         BOOL inventory_has_focus = FALSE;
01708         if (mHaveInventory && mFolders->getNumSelectedDescendants())
01709         {
01710                 mFolders->getSelectionList(selected_items);
01711                 inventory_has_focus = gFocusMgr.childHasKeyboardFocus(mFolders);
01712         }
01713 
01714         reset();
01715 
01716         LLViewerObject* objectp = gObjectList.findObject(mTaskUUID);
01717         if (objectp)
01718         {
01719                 LLInventoryObject* inventory_root = objectp->getInventoryRoot();
01720                 InventoryObjectList contents;
01721                 objectp->getInventoryContents(contents);
01722                 if (inventory_root)
01723                 {
01724                         createFolderViews(inventory_root, contents);
01725                         mHaveInventory = TRUE;
01726                         mIsInventoryEmpty = FALSE;
01727                         mFolders->setEnabled(TRUE);
01728                 }
01729                 else
01730                 {
01731                         // TODO: create an empty inventory
01732                         mIsInventoryEmpty = TRUE;
01733                         mHaveInventory = TRUE;
01734                 }
01735         }
01736         else
01737         {
01738                 // TODO: create an empty inventory
01739                 mIsInventoryEmpty = TRUE;
01740                 mHaveInventory = TRUE;
01741         }
01742 
01743         // restore previous selection
01744         std::set<LLUUID>::iterator selection_it;
01745         BOOL first_item = TRUE;
01746         for (selection_it = selected_items.begin(); selection_it != selected_items.end(); ++selection_it)
01747         {
01748                 LLFolderViewItem* selected_item = mFolders->getItemByID(*selection_it);
01749                 if (selected_item)
01750                 {
01751                         //HACK: "set" first item then "change" each other one to get keyboard focus right
01752                         if (first_item)
01753                         {
01754                                 mFolders->setSelection(selected_item, TRUE, inventory_has_focus);
01755                                 first_item = FALSE;
01756                         }
01757                         else
01758                         {
01759                                 mFolders->changeSelection(selected_item, TRUE);
01760                         }
01761                 }
01762         }
01763 
01764         mFolders->arrangeFromRoot();
01765         mInventoryNeedsUpdate = FALSE;
01766 }
01767 
01768 // *FIX: This is currently a very expensive operation, because we have
01769 // to iterate through the inventory one time for each category. This
01770 // leads to an N^2 based on the category count. This could be greatly
01771 // speeded with an efficient multimap implementation, but we don't
01772 // have that in our current arsenal.
01773 void LLPanelInventory::createFolderViews(LLInventoryObject* inventory_root, InventoryObjectList& contents)
01774 {
01775         if (!inventory_root)
01776         {
01777                 return;
01778         }
01779         // Create a visible root category.
01780         LLTaskInvFVBridge* bridge = NULL;
01781         bridge = LLTaskInvFVBridge::createObjectBridge(this, inventory_root);
01782         if(bridge)
01783         {
01784                 LLFolderViewFolder* new_folder = NULL;
01785                 new_folder = new LLFolderViewFolder(inventory_root->getName(),
01786                                                                                         bridge->getIcon(),
01787                                                                                         mFolders,
01788                                                                                         bridge);
01789                 new_folder->addToFolder(mFolders, mFolders);
01790                 new_folder->toggleOpen();
01791 
01792                 createViewsForCategory(&contents, inventory_root, new_folder);
01793         }
01794 }
01795 
01796 typedef std::pair<LLInventoryObject*, LLFolderViewFolder*> obj_folder_pair;
01797 
01798 // Replace LLLinkedList with std:: equivalant.
01799 void LLPanelInventory::createViewsForCategory(InventoryObjectList* inventory, //LLLinkedList<LLInventoryObject>* inventory,
01800                                                                                           LLInventoryObject* parent,
01801                                                                                           LLFolderViewFolder* folder)
01802 {
01803         // Find all in the first pass
01804         LLDynamicArray<obj_folder_pair*> child_categories;
01805         LLTaskInvFVBridge* bridge;
01806         LLFolderViewItem* view;
01807 
01808         InventoryObjectList::iterator it = inventory->begin();
01809         InventoryObjectList::iterator end = inventory->end();
01810         for( ; it != end; ++it)
01811         {
01812                 LLInventoryObject* obj = *it;
01813 
01814                 if(parent->getUUID() == obj->getParentUUID())
01815                 {
01816                         bridge = LLTaskInvFVBridge::createObjectBridge(this, obj);
01817                         if(!bridge)
01818                         {
01819                                 continue;
01820                         }
01821                         if(LLAssetType::AT_CATEGORY == obj->getType())
01822                         {
01823                                 view = new LLFolderViewFolder(obj->getName(),
01824                                                                                           bridge->getIcon(),
01825                                                                                           mFolders,
01826                                                                                           bridge);
01827                                 child_categories.put(new obj_folder_pair(obj,
01828                                                                                                                  (LLFolderViewFolder*)view));
01829                         }
01830                         else
01831                         {
01832                                 view = new LLFolderViewItem(obj->getName(),
01833                                                                                         bridge->getIcon(),
01834                                                                                         bridge->getCreationDate(),
01835                                                                                         mFolders,
01836                                                                                         bridge);
01837                         }
01838                         view->addToFolder(folder, mFolders);
01839                 }
01840         }
01841 
01842         // now, for each category, do the second pass
01843         for(S32 i = 0; i < child_categories.count(); i++)
01844         {
01845                 createViewsForCategory(inventory, child_categories[i]->first,
01846                                                            child_categories[i]->second );
01847                 delete child_categories[i];
01848         }
01849 }
01850 
01851 void LLPanelInventory::refresh()
01852 {
01853         //llinfos << "LLPanelInventory::refresh()" << llendl;
01854         BOOL has_inventory = FALSE;
01855         const BOOL non_root_ok = TRUE;
01856         LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(NULL, non_root_ok);
01857         if(node)
01858         {
01859                 LLViewerObject* object = node->getObject();
01860                 if(object && ((gSelectMgr->getSelection()->getRootObjectCount() == 1)
01861                                           || (gSelectMgr->getSelection()->getObjectCount() == 1)))
01862                 {
01863                         // determine if we need to make a request. Start with a
01864                         // default based on if we have inventory at all.
01865                         BOOL make_request = !mHaveInventory;
01866 
01867                         // If the task id is different than what we've stored,
01868                         // then make the request.
01869                         if(mTaskUUID != object->mID)
01870                         {
01871                                 mTaskUUID = object->mID;
01872                                 make_request = TRUE;
01873 
01874                                 // This is a new object so pre-emptively clear the contents
01875                                 // Otherwise we show the old stuff until the update comes in
01876                                 clearContents();
01877 
01878                                 // Register for updates from this object,
01879                                 registerVOInventoryListener(object,NULL);
01880                         }
01881 
01882                         // Based on the node information, we may need to dirty the
01883                         // object inventory and get it again.
01884                         if(node->mValid)
01885                         {
01886                                 if(node->mInventorySerial != object->getInventorySerial() || object->isInventoryDirty())
01887                                 {
01888                                         make_request = TRUE;
01889                                 }
01890                         }
01891 
01892                         // do the request if necessary.
01893                         if(make_request)
01894                         {
01895                                 requestVOInventory();
01896                         }
01897                         has_inventory = TRUE;
01898                 }
01899         }
01900         if(!has_inventory)
01901         {
01902                 mTaskUUID = LLUUID::null;
01903                 removeVOInventoryListener();
01904                 clearContents();
01905         }
01906         //llinfos << "LLPanelInventory::refresh() " << mTaskUUID << llendl;
01907 }
01908 
01909 void LLPanelInventory::removeSelectedItem()
01910 {
01911         if(mFolders)
01912         {
01913                 mFolders->removeSelectedItems();
01914         }
01915 }
01916 
01917 void LLPanelInventory::startRenamingSelectedItem()
01918 {
01919         if(mFolders)
01920         {
01921                 mFolders->startRenamingSelectedItem();
01922         }
01923 }
01924 
01925 void LLPanelInventory::draw()
01926 {
01927         if( getVisible() )
01928         {
01929                 LLPanel::draw();
01930 
01931                 if(mIsInventoryEmpty)
01932                 {
01933                         if((LLUUID::null != mTaskUUID) && (!mHaveInventory))
01934                         {
01935                                 LLFontGL::sSansSerif->renderUTF8("Loading contents...", 0,
01936                                                                                          (S32)(mRect.getWidth() * 0.5f),
01937                                                                                          10,
01938                                                                                          LLColor4( 1, 1, 1, 1 ),
01939                                                                                          LLFontGL::HCENTER,
01940                                                                                          LLFontGL::BOTTOM);
01941                         }
01942                         else if(mHaveInventory)
01943                         {
01944                                 LLFontGL::sSansSerif->renderUTF8("No contents", 0,
01945                                                                                          (S32)(mRect.getWidth() * 0.5f),
01946                                                                                          10,
01947                                                                                          LLColor4( 1, 1, 1, 1 ),
01948                                                                                          LLFontGL::HCENTER,
01949                                                                                          LLFontGL::BOTTOM);
01950                         }
01951                 }
01952         }
01953 }
01954 
01955 void LLPanelInventory::deleteAllChildren()
01956 {
01957         mScroller = NULL;
01958         mFolders = NULL;
01959         LLView::deleteAllChildren();
01960 }
01961 
01962 BOOL LLPanelInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, LLString& tooltip_msg)
01963 {
01964         if (mFolders && mHaveInventory)
01965         {
01966                 LLFolderViewItem* folderp = mFolders->getNextFromChild(NULL);
01967                 if (!folderp)
01968                 {
01969                         return FALSE;
01970                 }
01971                 // Try to pass on unmodified mouse coordinates
01972                 S32 local_x = x - mFolders->getRect().mLeft;
01973                 S32 local_y = y - mFolders->getRect().mBottom;
01974 
01975                 if (mFolders->pointInView(local_x, local_y))
01976                 {
01977                         return mFolders->handleDragAndDrop(local_x, local_y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
01978                 }
01979                 else
01980                 {
01981                         //force mouse coordinates to be inside folder rectangle
01982                         return mFolders->handleDragAndDrop(5, 1, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
01983                 }
01984         }
01985         else
01986         {
01987                 return FALSE;
01988         }
01989 }
01990 
01991 //static
01992 void LLPanelInventory::idle(void* user_data)
01993 {
01994         LLPanelInventory* self = (LLPanelInventory*)user_data;
01995 
01996 
01997         if (self->mInventoryNeedsUpdate)
01998         {
01999                 self->updateInventory();
02000         }
02001 }

Generated on Thu Jul 1 06:08:58 2010 for Second Life Viewer by  doxygen 1.4.7