llinventorybridge.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include <utility> // for std::pair<>
00035 
00036 #include "llinventoryview.h"
00037 #include "llinventorybridge.h"
00038 
00039 #include "message.h"
00040 
00041 #include "llagent.h"
00042 #include "llcallingcard.h"
00043 #include "llcheckboxctrl.h"             // for radio buttons
00044 #include "llradiogroup.h"
00045 #include "llspinctrl.h"
00046 #include "lltextbox.h"
00047 #include "llui.h"
00048 
00049 #include "llviewercontrol.h"
00050 #include "llfirstuse.h"
00051 #include "llfloateravatarinfo.h"
00052 #include "llfloaterchat.h"
00053 #include "llfloatercustomize.h"
00054 #include "llfloaterproperties.h"
00055 #include "llfloaterworldmap.h"
00056 #include "llfocusmgr.h"
00057 #include "llfolderview.h"
00058 #include "llgesturemgr.h"
00059 #include "lliconctrl.h"
00060 #include "llinventorymodel.h"
00061 #include "llinventoryclipboard.h"
00062 #include "lllineeditor.h"
00063 #include "llmenugl.h"
00064 #include "llpreviewanim.h"
00065 #include "llpreviewgesture.h"
00066 #include "llpreviewlandmark.h"
00067 #include "llpreviewnotecard.h"
00068 #include "llpreviewscript.h"
00069 #include "llpreviewsound.h"
00070 #include "llpreviewtexture.h"
00071 #include "llresmgr.h"
00072 #include "llscrollcontainer.h"
00073 #include "llimview.h"
00074 #include "lltooldraganddrop.h"
00075 #include "llviewerimagelist.h"
00076 #include "llviewerinventory.h"
00077 #include "llviewerobjectlist.h"
00078 #include "llviewerwindow.h"
00079 #include "llwearable.h"
00080 #include "llwearablelist.h"
00081 #include "llviewermessage.h" 
00082 #include "llviewerregion.h"
00083 #include "lltabcontainer.h"
00084 #include "lluictrlfactory.h"
00085 #include "llselectmgr.h"
00086 #include "llfloateropenobject.h"
00087 
00088 // Helpers
00089 // bug in busy count inc/dec right now, logic is complex... do we really need it?
00090 void inc_busy_count()
00091 {
00092 //      gViewerWindow->getWindow()->incBusyCount();
00093 //  check balance of these calls if this code is changed to ever actually
00094 //  *do* something!
00095 }
00096 void dec_busy_count()
00097 {
00098 //      gViewerWindow->getWindow()->decBusyCount();
00099 //  check balance of these calls if this code is changed to ever actually
00100 //  *do* something!
00101 }
00102 
00103 // Function declarations
00104 struct LLWearableHoldingPattern;
00105 void wear_inventory_category_on_avatar(LLInventoryCategory* category, BOOL append);
00106 void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata);
00107 void wear_inventory_category_on_avatar_loop(LLWearable* wearable, void*);
00108 void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, BOOL append);
00109 void remove_inventory_category_from_avatar(LLInventoryCategory* category);
00110 void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata);
00111 void move_task_inventory_callback(S32 option, void* user_data);
00112 void confirm_replace_attachment_rez(S32 option, void* user_data);
00113 
00114 const char* ICON_NAME[ICON_NAME_COUNT] =
00115 {
00116         "inv_item_texture.tga",
00117         "inv_item_sound.tga",
00118         "inv_item_callingcard_online.tga",
00119         "inv_item_callingcard_offline.tga",
00120         "inv_item_landmark.tga",
00121         "inv_item_landmark_visited.tga",
00122         "inv_item_script.tga",
00123         "inv_item_clothing.tga",
00124         "inv_item_object.tga",
00125         "inv_item_object_multi.tga",
00126         "inv_item_notecard.tga",
00127         "inv_item_skin.tga",
00128         "inv_item_snapshot.tga",
00129 
00130         "inv_item_shape.tga",
00131         "inv_item_skin.tga",
00132         "inv_item_hair.tga",
00133         "inv_item_eyes.tga",
00134         "inv_item_shirt.tga",
00135         "inv_item_pants.tga",
00136         "inv_item_shoes.tga",
00137         "inv_item_socks.tga",
00138         "inv_item_jacket.tga",
00139         "inv_item_gloves.tga",
00140         "inv_item_undershirt.tga",
00141         "inv_item_underpants.tga",
00142         "inv_item_skirt.tga",
00143 
00144         "inv_item_animation.tga",
00145         "inv_item_gesture.tga",
00146 };
00147 
00148 struct LLWearInfo
00149 {
00150         LLUUID  mCategoryID;
00151         BOOL    mAppend;
00152 };
00153 
00154 BOOL gAddToOutfit = FALSE;
00155 
00156 // +=================================================+
00157 // |        LLInvFVBridge                            |
00158 // +=================================================+
00159 
00160 const LLString& LLInvFVBridge::getName() const
00161 {
00162         LLInventoryObject* obj = getInventoryObject();
00163         if(obj)
00164         {
00165                 return obj->getName();
00166         }
00167         return LLString::null;
00168 }
00169 
00170 const LLString& LLInvFVBridge::getDisplayName() const
00171 {
00172         return getName();
00173 }
00174 
00175 // Folders have full perms
00176 PermissionMask LLInvFVBridge::getPermissionMask() const
00177 {
00178 
00179         return PERM_ALL;
00180 }
00181 
00182 // Folders don't have creation dates.
00183 U32 LLInvFVBridge::getCreationDate() const
00184 {
00185         return 0;
00186 }
00187 
00188 // Can be destoryed (or moved to trash)
00189 BOOL LLInvFVBridge::isItemRemovable()
00190 {
00191         LLInventoryModel* model = mInventoryPanel->getModel();
00192         if(!model) return FALSE;
00193         if(model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID()))
00194         {
00195                 return TRUE;
00196         }
00197         return FALSE;
00198 }
00199 
00200 // Can be moved to another folder
00201 BOOL LLInvFVBridge::isItemMovable()
00202 {
00203         return TRUE;
00204 }
00205 
00206 // *TODO: make sure this does the right thing
00207 void LLInvFVBridge::showProperties()
00208 {
00209         LLShowProps::showProperties(mUUID);
00210 }
00211 
00212 void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch)
00213 {
00214         // Deactivate gestures when moving them into Trash
00215         LLInvFVBridge* bridge;
00216         LLInventoryModel* model = mInventoryPanel->getModel();
00217         LLViewerInventoryItem* item = NULL;
00218         LLViewerInventoryCategory* cat = NULL;
00219         LLInventoryModel::cat_array_t   descendent_categories;
00220         LLInventoryModel::item_array_t  descendent_items;
00221         S32 count = batch.count();
00222         S32 i,j;
00223         for(i = 0; i < count; ++i)
00224         {       
00225                 bridge = (LLInvFVBridge*)(batch.get(i));
00226                 if(!bridge || !bridge->isItemRemovable()) continue;
00227                 item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
00228                 if (item)
00229                 {
00230                         if(LLAssetType::AT_GESTURE == item->getType())
00231                         {
00232                                 gGestureManager.deactivateGesture(item->getUUID());
00233                         }
00234                 }
00235         }
00236         for(i = 0; i < count; ++i)
00237         {               
00238                 bridge = (LLInvFVBridge*)(batch.get(i));
00239                 if(!bridge || !bridge->isItemRemovable()) continue;
00240                 cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
00241                 if (cat)
00242                 {
00243                         gInventory.collectDescendents( cat->getUUID(), descendent_categories, descendent_items, FALSE );
00244                         for (j=0; j<descendent_items.count(); j++)
00245                         {
00246                                 if(LLAssetType::AT_GESTURE == descendent_items[j]->getType())
00247                                 {
00248                                         gGestureManager.deactivateGesture(descendent_items[j]->getUUID());
00249                                 }
00250                         }
00251                 }
00252         }
00253         removeBatchNoCheck(batch);
00254 }
00255 
00256 void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch)
00257 {
00258         // this method moves a bunch of items and folders to the trash. As
00259         // per design guidelines for the inventory model, the message is
00260         // built and the accounting is performed first. After all of that,
00261         // we call LLInventoryModel::moveObject() to move everything
00262         // around.
00263         LLInvFVBridge* bridge;
00264         LLInventoryModel* model = mInventoryPanel->getModel();
00265         if(!model) return;
00266         LLMessageSystem* msg = gMessageSystem;
00267         LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
00268         LLViewerInventoryItem* item = NULL;
00269         LLViewerInventoryCategory* cat = NULL;
00270         std::vector<LLUUID> move_ids;
00271         LLInventoryModel::update_map_t update;
00272         bool start_new_message = true;
00273         S32 count = batch.count();
00274         S32 i;
00275         for(i = 0; i < count; ++i)
00276         {
00277                 bridge = (LLInvFVBridge*)(batch.get(i));
00278                 if(!bridge || !bridge->isItemRemovable()) continue;
00279                 item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
00280                 if(item)
00281                 {
00282                         if(item->getParentUUID() == trash_id) continue;
00283                         move_ids.push_back(item->getUUID());
00284                         LLPreview::hide(item->getUUID());
00285                         --update[item->getParentUUID()];
00286                         ++update[trash_id];
00287                         if(start_new_message)
00288                         {
00289                                 start_new_message = false;
00290                                 msg->newMessageFast(_PREHASH_MoveInventoryItem);
00291                                 msg->nextBlockFast(_PREHASH_AgentData);
00292                                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00293                                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00294                                 msg->addBOOLFast(_PREHASH_Stamp, TRUE);
00295                         }
00296                         msg->nextBlockFast(_PREHASH_InventoryData);
00297                         msg->addUUIDFast(_PREHASH_ItemID, item->getUUID());
00298                         msg->addUUIDFast(_PREHASH_FolderID, trash_id);
00299                         msg->addString("NewName", NULL);
00300                         if(msg->isSendFullFast(_PREHASH_InventoryData))
00301                         {
00302                                 start_new_message = true;
00303                                 gAgent.sendReliableMessage();
00304                                 gInventory.accountForUpdate(update);
00305                                 update.clear();
00306                         }
00307                 }
00308         }
00309         if(!start_new_message)
00310         {
00311                 start_new_message = true;
00312                 gAgent.sendReliableMessage();
00313                 gInventory.accountForUpdate(update);
00314                 update.clear();
00315         }
00316         for(i = 0; i < count; ++i)
00317         {
00318                 bridge = (LLInvFVBridge*)(batch.get(i));
00319                 if(!bridge || !bridge->isItemRemovable()) continue;
00320                 cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
00321                 if(cat)
00322                 {
00323                         if(cat->getParentUUID() == trash_id) continue;
00324                         move_ids.push_back(cat->getUUID());
00325                         --update[cat->getParentUUID()];
00326                         ++update[trash_id];
00327                         if(start_new_message)
00328                         {
00329                                 start_new_message = false;
00330                                 msg->newMessageFast(_PREHASH_MoveInventoryFolder);
00331                                 msg->nextBlockFast(_PREHASH_AgentData);
00332                                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00333                                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00334                                 msg->addBOOL("Stamp", TRUE);
00335                         }
00336                         msg->nextBlockFast(_PREHASH_InventoryData);
00337                         msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID());
00338                         msg->addUUIDFast(_PREHASH_ParentID, trash_id);
00339                         if(msg->isSendFullFast(_PREHASH_InventoryData))
00340                         {
00341                                 start_new_message = true;
00342                                 gAgent.sendReliableMessage();
00343                                 gInventory.accountForUpdate(update);
00344                                 update.clear();
00345                         }
00346                 }
00347         }
00348         if(!start_new_message)
00349         {
00350                 gAgent.sendReliableMessage();
00351                 gInventory.accountForUpdate(update);
00352         }
00353 
00354         // move everything.
00355         std::vector<LLUUID>::iterator it = move_ids.begin();
00356         std::vector<LLUUID>::iterator end = move_ids.end();
00357         for(; it != end; ++it)
00358         {
00359                 gInventory.moveObject((*it), trash_id);
00360         }
00361 
00362         // notify inventory observers.
00363         model->notifyObservers();
00364 }
00365 
00366 BOOL LLInvFVBridge::isClipboardPasteable() const
00367 {
00368         LLInventoryModel* model = mInventoryPanel->getModel();
00369         if(!model) return FALSE;
00370         BOOL is_agent_inventory = model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID());
00371 
00372         if(LLInventoryClipboard::instance().hasContents() && is_agent_inventory)
00373         {
00374                 return TRUE;
00375         }
00376         return FALSE;
00377 }
00378 
00379 void hideContextEntries(LLMenuGL& menu, 
00380                                                                            const std::vector<LLString> &entries_to_show,
00381                                                                            const std::vector<LLString> &disabled_entries)
00382 {
00383         const LLView::child_list_t *list = menu.getChildList();
00384 
00385         LLView::child_list_t::const_iterator itor;
00386         for (itor = list->begin(); itor != list->end(); ++itor)
00387         {
00388                 LLString name = (*itor)->getName();
00389 
00390                 // descend into split menus:
00391                 LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(*itor);
00392                 if ((name == "More") && branchp)
00393                 {
00394                         hideContextEntries(*branchp->getBranch(), entries_to_show, disabled_entries);
00395                 }
00396                 
00397                 
00398                 bool found = false;
00399                 std::vector<LLString>::const_iterator itor2;
00400                 for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2)
00401                 {
00402                         if (*itor2 == name)
00403                         {
00404                                 found = true;
00405                         }
00406                 }
00407                 if (!found)
00408                 {
00409                         (*itor)->setVisible(FALSE);
00410                 }
00411                 else
00412                 {
00413                         for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
00414                         {
00415                                 if (*itor2 == name)
00416                                 {
00417                                         (*itor)->setEnabled(FALSE);
00418                                 }
00419                         }
00420                 }
00421         }
00422 }
00423 
00424 // Helper for commonly-used entries
00425 void LLInvFVBridge::getClipboardEntries(bool show_asset_id, std::vector<LLString> &items, 
00426                 std::vector<LLString> &disabled_items, U32 flags)
00427 {
00428         items.push_back("Rename");
00429         if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0)
00430         {
00431                 disabled_items.push_back("Rename");
00432         }
00433 
00434         if (show_asset_id)
00435         {
00436                 items.push_back("Copy Asset UUID");
00437                 if ( (! ( isItemPermissive() || gAgent.isGodlike() ) ) 
00438                           || (flags & FIRST_SELECTED_ITEM) == 0)
00439                 {
00440                         disabled_items.push_back("Copy Asset UUID");
00441                 }
00442         }
00443 
00444         items.push_back("Copy Separator");
00445 
00446         items.push_back("Copy");
00447         if (!isItemCopyable())
00448         {
00449                 disabled_items.push_back("Copy");
00450         }
00451 
00452         items.push_back("Paste");
00453         if (!isClipboardPasteable() || (flags & FIRST_SELECTED_ITEM) == 0)
00454         {
00455                 disabled_items.push_back("Paste");
00456         }
00457 
00458         items.push_back("Paste Separator");
00459 
00460         items.push_back("Delete");
00461         if (!isItemRemovable())
00462         {
00463                 disabled_items.push_back("Delete");
00464         }
00465 }
00466 
00467 void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
00468 {
00469         lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl;
00470         std::vector<LLString> items;
00471         std::vector<LLString> disabled_items;
00472         if(isInTrash())
00473         {
00474                 items.push_back("Purge Item");
00475                 if (!isItemRemovable())
00476                 {
00477                         disabled_items.push_back("Purge Item");
00478                 }
00479                 items.push_back("Restore Item");
00480         }
00481         else
00482         {
00483                 items.push_back("Open");
00484                 items.push_back("Properties");
00485 
00486                 getClipboardEntries(true, items, disabled_items, flags);
00487         }
00488         hideContextEntries(menu, items, disabled_items);
00489 }
00490 
00491 // *TODO: remove this
00492 BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
00493 {
00494         BOOL rv = FALSE;
00495 
00496         const LLInventoryObject* obj = getInventoryObject();
00497 
00498         if(obj)
00499         {
00500                 *type = LLAssetType::lookupDragAndDropType(obj->getType());
00501                 if(*type == DAD_NONE)
00502                 {
00503                         return FALSE;
00504                 }
00505                 
00506                 *id = obj->getUUID();
00507                 //object_ids.put(obj->getUUID());
00508 
00509                 if (*type == DAD_CATEGORY)
00510                 {
00511                         gInventory.startBackgroundFetch(obj->getUUID());
00512                 }
00513 
00514                 rv = TRUE;
00515         }
00516 
00517         return rv;
00518 }
00519 
00520 LLInventoryObject* LLInvFVBridge::getInventoryObject() const
00521 {
00522         LLInventoryObject* obj = NULL;
00523         LLInventoryModel* model = mInventoryPanel->getModel();
00524         if(model)
00525         {
00526                 obj = (LLInventoryObject*)model->getObject(mUUID);
00527         }
00528         return obj;
00529 }
00530 
00531 BOOL LLInvFVBridge::isInTrash() const
00532 {
00533         LLInventoryModel* model = mInventoryPanel->getModel();
00534         if(!model) return FALSE;
00535         LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
00536         return model->isObjectDescendentOf(mUUID, trash_id);
00537 }
00538 
00539 BOOL LLInvFVBridge::isAgentInventory() const
00540 {
00541         LLInventoryModel* model = mInventoryPanel->getModel();
00542         if(!model) return FALSE;
00543         if(gAgent.getInventoryRootID() == mUUID) return TRUE;
00544         return model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID());
00545 }
00546 
00547 BOOL LLInvFVBridge::isItemPermissive() const
00548 {
00549         return FALSE;
00550 }
00551 
00552 // static
00553 void LLInvFVBridge::changeItemParent(LLInventoryModel* model,
00554                                                                          LLViewerInventoryItem* item,
00555                                                                          const LLUUID& new_parent,
00556                                                                          BOOL restamp)
00557 {
00558         if(item->getParentUUID() != new_parent)
00559         {
00560                 LLInventoryModel::update_list_t update;
00561                 LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
00562                 update.push_back(old_folder);
00563                 LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
00564                 update.push_back(new_folder);
00565                 gInventory.accountForUpdate(update);
00566 
00567                 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
00568                 new_item->setParent(new_parent);
00569                 new_item->updateParentOnServer(restamp);
00570                 model->updateItem(new_item);
00571                 model->notifyObservers();
00572         }
00573 }
00574 
00575 // static
00576 void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model,
00577                                                                                  LLViewerInventoryCategory* cat,
00578                                                                                  const LLUUID& new_parent,
00579                                                                                  BOOL restamp)
00580 {
00581         if(cat->getParentUUID() != new_parent)
00582         {
00583                 LLInventoryModel::update_list_t update;
00584                 LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
00585                 update.push_back(old_folder);
00586                 LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
00587                 update.push_back(new_folder);
00588                 gInventory.accountForUpdate(update);
00589 
00590                 LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
00591                 new_cat->setParent(new_parent);
00592                 new_cat->updateParentOnServer(restamp);
00593                 model->updateCategory(new_cat);
00594                 model->notifyObservers();
00595         }
00596 }
00597 
00598 
00599 const char* safe_inv_type_lookup(LLInventoryType::EType inv_type)
00600 {
00601         const char* rv = LLInventoryType::lookup(inv_type);
00602         if(!rv)
00603         {
00604                 const char* INVALID_TYPE = "<invalid>";
00605                 rv = INVALID_TYPE;
00606         }
00607         return rv;
00608 }
00609 
00610 LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
00611                                            LLInventoryType::EType inv_type,
00612                                            LLInventoryPanel* inventory,
00613                                            const LLUUID& uuid,
00614                                            U32 flags)
00615 {
00616         LLInvFVBridge* new_listener = NULL;
00617         switch(asset_type)
00618         {
00619         case LLAssetType::AT_TEXTURE:
00620                 if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT))
00621                 {
00622                         llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
00623                 }
00624                 new_listener = new LLTextureBridge(inventory, uuid, inv_type);
00625                 break;
00626 
00627         case LLAssetType::AT_SOUND:
00628                 if(!(inv_type == LLInventoryType::IT_SOUND))
00629                 {
00630                         llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
00631                 }
00632                 new_listener = new LLSoundBridge(inventory, uuid);
00633                 break;
00634 
00635         case LLAssetType::AT_LANDMARK:
00636                 if(!(inv_type == LLInventoryType::IT_LANDMARK))
00637                 {
00638                         llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
00639                 }
00640                 new_listener = new LLLandmarkBridge(inventory, uuid, flags);
00641                 break;
00642                 
00643         case LLAssetType::AT_CALLINGCARD:
00644                 if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
00645                 {
00646                         llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
00647                 }
00648                 new_listener = new LLCallingCardBridge(inventory, uuid);
00649                 break;
00650 
00651         case LLAssetType::AT_SCRIPT:
00652                 if(!(inv_type == LLInventoryType::IT_LSL))
00653                 {
00654                         llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
00655                 }
00656                 new_listener = new LLScriptBridge(inventory, uuid);
00657                 break;
00658 
00659         case LLAssetType::AT_OBJECT:
00660                 if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT))
00661                 {
00662                         llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
00663                 }
00664                 new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags);
00665                 break;
00666 
00667         case LLAssetType::AT_NOTECARD:
00668                 if(!(inv_type == LLInventoryType::IT_NOTECARD))
00669                 {
00670                         llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
00671                 }
00672                 new_listener = new LLNotecardBridge(inventory, uuid);
00673                 break;
00674 
00675         case LLAssetType::AT_ANIMATION:
00676                 if(!(inv_type == LLInventoryType::IT_ANIMATION))
00677                 {
00678                         llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
00679                 }
00680                 new_listener = new LLAnimationBridge(inventory, uuid);
00681                 break;
00682 
00683         case LLAssetType::AT_GESTURE:
00684                 if(!(inv_type == LLInventoryType::IT_GESTURE))
00685                 {
00686                         llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
00687                 }
00688                 new_listener = new LLGestureBridge(inventory, uuid);
00689                 break;
00690 
00691         case LLAssetType::AT_LSL_TEXT:
00692                 if(!(inv_type == LLInventoryType::IT_LSL))
00693                 {
00694                         llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
00695                 }
00696                 new_listener = new LLLSLTextBridge(inventory, uuid);
00697                 break;
00698 
00699         case LLAssetType::AT_CLOTHING:
00700         case LLAssetType::AT_BODYPART:
00701                 if(!(inv_type == LLInventoryType::IT_WEARABLE))
00702                 {
00703                         llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
00704                 }
00705                 new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags);
00706                 break;
00707 
00708         case LLAssetType::AT_CATEGORY:
00709         case LLAssetType::AT_ROOT_CATEGORY:
00710                 new_listener = new LLFolderBridge(inventory, uuid);
00711                 break;
00712                 
00713         default:
00714                 llinfos << "Unhandled asset type (llassetstorage.h): "
00715                                 << (S32)asset_type << llendl;
00716                 break;
00717         }
00718 
00719         if (new_listener)
00720         {
00721                 new_listener->mInvType = inv_type;
00722         }
00723 
00724         return new_listener;
00725 }
00726 
00727 // +=================================================+
00728 // |        LLItemBridge                             |
00729 // +=================================================+
00730 
00731 void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, LLString action)
00732 {
00733         if ("open" == action)
00734         {
00735                 openItem();
00736         }
00737         else if ("properties" == action)
00738         {
00739                 showProperties();
00740         }
00741         else if ("purge" == action)
00742         {
00743                 LLInventoryCategory* cat = model->getCategory(mUUID);
00744                 if(cat)
00745                 {
00746                         model->purgeDescendentsOf(mUUID);
00747                 }
00748                 LLInventoryObject* obj = model->getObject(mUUID);
00749                 if(!obj) return;
00750                 obj->removeFromServer();
00751                 LLPreview::hide(mUUID);
00752                 model->deleteObject(mUUID);
00753                 model->notifyObservers();
00754         }
00755         else if ("restore" == action)
00756         {
00757                 restoreItem();
00758         }
00759         else if ("copy_uuid" == action)
00760         {
00761                 // Single item only
00762                 LLInventoryItem* item = model->getItem(mUUID);
00763                 if(!item) return;
00764                 LLUUID asset_id = item->getAssetUUID();
00765                 char buffer[UUID_STR_LENGTH];           /*Flawfinder: ignore*/
00766                 asset_id.toString(buffer);
00767 
00768                 gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer));
00769                 return;
00770         }
00771         else if ("copy" == action)
00772         {
00773                 copyToClipboard();
00774                 return;
00775         }
00776         else if ("paste" == action)
00777         {
00778                 // Single item only
00779                 LLInventoryItem* itemp = model->getItem(mUUID);
00780                 if (!itemp) return;
00781 
00782                 LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
00783                 if (!folder_view_itemp) return;
00784 
00785                 folder_view_itemp->getListener()->pasteFromClipboard();
00786                 return;
00787         }
00788 }
00789 
00790 void LLItemBridge::selectItem()
00791 {
00792         LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
00793         if(item && !item->isComplete())
00794         {
00795                 item->fetchFromServer();
00796         }
00797 }
00798 
00799 void LLItemBridge::restoreItem()
00800 {
00801         LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
00802         if(item)
00803         {
00804                 LLInventoryModel* model = mInventoryPanel->getModel();
00805                 LLUUID new_parent = model->findCategoryUUIDForType(item->getType());
00806                 // do not restamp on restore.
00807                 LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE);
00808         }
00809 }
00810 
00811 LLUIImagePtr LLItemBridge::getIcon() const
00812 {
00813         return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]);
00814 }
00815 
00816 PermissionMask LLItemBridge::getPermissionMask() const
00817 {
00818         LLViewerInventoryItem* item = getItem();
00819         PermissionMask perm_mask = 0;
00820         if(item) 
00821         {
00822                 BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
00823                 BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
00824                 BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
00825                                                                                                                         gAgent.getID());
00826 
00827                 if (copy) perm_mask |= PERM_COPY;
00828                 if (mod)  perm_mask |= PERM_MODIFY;
00829                 if (xfer) perm_mask |= PERM_TRANSFER;
00830 
00831         }
00832         return perm_mask;
00833 }
00834         
00835 const LLString& LLItemBridge::getDisplayName() const
00836 {
00837         if(mDisplayName.empty())
00838         {
00839                 buildDisplayName(getItem(), mDisplayName);
00840         }
00841         return mDisplayName;
00842 }
00843 
00844 void LLItemBridge::buildDisplayName(LLInventoryItem* item, LLString& name)
00845 {
00846         if(item) 
00847         {
00848                 name.assign(item->getName());                   
00849         }
00850         else
00851         {
00852                 name.assign(LLString::null);
00853         }
00854 }
00855 
00856 LLString LLItemBridge::getLabelSuffix() const
00857 {
00858         LLString suffix;
00859         LLInventoryItem* item = getItem();
00860         if(item) 
00861         {
00862                 // it's a bit confusing to put nocopy/nomod/etc on calling cards.
00863                 if(LLAssetType::AT_CALLINGCARD != item->getType()
00864                    && item->getPermissions().getOwner() == gAgent.getID())
00865                 {
00866                         BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
00867                         BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
00868                         BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
00869                                                                                                                                 gAgent.getID());
00870                         const char* EMPTY = "";
00871                         const char* NO_COPY = " (no copy)";
00872                         const char* NO_MOD = " (no modify)";
00873                         const char* NO_XFER = " (no transfer)";
00874                         const char* scopy;
00875                         if(copy) scopy = EMPTY;
00876                         else scopy = NO_COPY;
00877                         const char* smod;
00878                         if(mod) smod = EMPTY;
00879                         else smod = NO_MOD;
00880                         const char* sxfer;
00881                         if(xfer) sxfer = EMPTY;
00882                         else sxfer = NO_XFER;
00883                         char buffer[MAX_STRING];                /*Flawfinder: ignore*/
00884                         snprintf(                                               /* Flawfinder: ignore */
00885                                 buffer,
00886                                 MAX_STRING,
00887                                 "%s%s%s",
00888                                 scopy,
00889                                 smod,
00890                                 sxfer);
00891                         suffix.assign(buffer);
00892                 }
00893         }
00894         return suffix;
00895 }
00896 
00897 U32 LLItemBridge::getCreationDate() const
00898 {
00899         LLViewerInventoryItem* item = getItem();
00900         if (item)
00901         {
00902                 return item->getCreationDate();
00903         }
00904         return 0;
00905 }
00906 
00907 
00908 BOOL LLItemBridge::isItemRenameable() const
00909 {
00910         LLViewerInventoryItem* item = getItem();
00911         if(item)
00912         {
00913                 return (item->getPermissions().allowModifyBy(gAgent.getID()));
00914         }
00915         return FALSE;
00916 }
00917 
00918 BOOL LLItemBridge::renameItem(const LLString& new_name)
00919 {
00920         if(!isItemRenameable()) return FALSE;
00921         LLPreview::rename(mUUID, getPrefix() + new_name);
00922         LLInventoryModel* model = mInventoryPanel->getModel();
00923         if(!model) return FALSE;
00924         LLViewerInventoryItem* item = getItem();
00925         if(item && (item->getName() != new_name))
00926         {
00927                 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
00928                 new_item->rename(new_name);
00929                 buildDisplayName(new_item, mDisplayName);
00930                 new_item->updateServer(FALSE);
00931                 model->updateItem(new_item);
00932                 model->notifyObservers();
00933         }
00934         // return FALSE because we either notified observers (& therefore
00935         // rebuilt) or we didn't update.
00936         return FALSE;
00937 }
00938 
00939 
00940 BOOL LLItemBridge::removeItem()
00941 {
00942         if(!isItemRemovable())
00943         {
00944                 return FALSE;
00945         }
00946         // move it to the trash
00947         LLPreview::hide(mUUID, TRUE);
00948         LLInventoryModel* model = mInventoryPanel->getModel();
00949         if(!model) return FALSE;
00950         LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
00951         LLViewerInventoryItem* item = getItem();
00952 
00953         // if item is not already in trash
00954         if(item && !model->isObjectDescendentOf(mUUID, trash_id))
00955         {
00956                 // move to trash, and restamp
00957                 LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE);
00958                 // delete was successful
00959                 return TRUE;
00960         }
00961         else
00962         {
00963                 // tried to delete already item in trash (should purge?)
00964                 return FALSE;
00965         }
00966 }
00967 
00968 BOOL LLItemBridge::isItemCopyable() const
00969 {
00970         LLViewerInventoryItem* item = getItem();
00971         if (item)
00972         {
00973                 return (item->getPermissions().allowCopyBy(gAgent.getID()));
00974         }
00975         return FALSE;
00976 }
00977 BOOL LLItemBridge::copyToClipboard() const
00978 {
00979         if(isItemCopyable())
00980         {
00981                 LLInventoryClipboard::instance().add(mUUID);
00982                 return TRUE;
00983         }
00984         return FALSE;
00985 }
00986 
00987 LLViewerInventoryItem* LLItemBridge::getItem() const
00988 {
00989         LLViewerInventoryItem* item = NULL;
00990         LLInventoryModel* model = mInventoryPanel->getModel();
00991         if(model)
00992         {
00993                 item = (LLViewerInventoryItem*)model->getItem(mUUID);
00994         }
00995         return item;
00996 }
00997 
00998 BOOL LLItemBridge::isItemPermissive() const
00999 {
01000         LLViewerInventoryItem* item = getItem();
01001         if(item)
01002         {
01003                 U32 mask = item->getPermissions().getMaskBase();
01004                 if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
01005                 {
01006                         return TRUE;
01007                 }
01008         }
01009         return FALSE;
01010 }
01011 
01012 // +=================================================+
01013 // |        LLFolderBridge                           |
01014 // +=================================================+
01015 
01016 LLFolderBridge* LLFolderBridge::sSelf=NULL;
01017 
01018 // Can be moved to another folder
01019 BOOL LLFolderBridge::isItemMovable()
01020 {
01021         LLInventoryObject* obj = getInventoryObject();
01022         if(obj)
01023         {
01024                 return (LLAssetType::AT_NONE == ((LLInventoryCategory*)obj)->getPreferredType());
01025         }
01026         return FALSE;
01027 }
01028 
01029 void LLFolderBridge::selectItem()
01030 {
01031 }
01032 
01033 
01034 // Can be destroyed (or moved to trash)
01035 BOOL LLFolderBridge::isItemRemovable()
01036 {
01037         LLInventoryModel* model = mInventoryPanel->getModel();
01038         if(!model) 
01039         {
01040                 return FALSE;
01041         }
01042 
01043         if(!model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID()))
01044         {
01045                 return FALSE;
01046         }
01047 
01048         LLVOAvatar* avatar = gAgent.getAvatarObject();
01049         if( !avatar )
01050         {
01051                 return FALSE;
01052         }
01053 
01054         LLInventoryCategory* category = model->getCategory(mUUID);
01055         if( !category )
01056         {
01057                 return FALSE;
01058         }
01059 
01060         if( LLAssetType::AT_NONE != category->getPreferredType() )
01061         {
01062                 return FALSE;
01063         }
01064 
01065         LLInventoryModel::cat_array_t   descendent_categories;
01066         LLInventoryModel::item_array_t  descendent_items;
01067         gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
01068 
01069         S32 i;
01070         for( i = 0; i < descendent_categories.count(); i++ )
01071         {
01072                 LLInventoryCategory* category = descendent_categories[i];
01073                 if( LLAssetType::AT_NONE != category->getPreferredType() )
01074                 {
01075                         return FALSE;
01076                 }
01077         }
01078 
01079         for( i = 0; i < descendent_items.count(); i++ )
01080         {
01081                 LLInventoryItem* item = descendent_items[i];
01082                 if( (item->getType() == LLAssetType::AT_CLOTHING) ||
01083                         (item->getType() == LLAssetType::AT_BODYPART) )
01084                 {
01085                         if( gAgent.isWearingItem( item->getUUID() ) )
01086                         {
01087                                 return FALSE;
01088                         }
01089                 }
01090                 else
01091                 if( item->getType() == LLAssetType::AT_OBJECT )
01092                 {
01093                         if( avatar->isWearingAttachment( item->getUUID() ) )
01094                         {
01095                                 return FALSE;
01096                         }
01097                 }
01098         }
01099 
01100         return TRUE;
01101 }
01102 
01103 BOOL LLFolderBridge::isUpToDate() const
01104 {
01105         LLInventoryModel* model = mInventoryPanel->getModel();
01106         if(!model) return FALSE;
01107         LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
01108         if( !category )
01109         {
01110                 return FALSE;
01111         }
01112 
01113         return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN;
01114 }
01115 
01116 BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
01117                                                                                         BOOL drop)
01118 {
01119         // This should never happen, but if an inventory item is incorrectly parented, 
01120         // the UI will get confused and pass in a NULL.
01121         if(!inv_cat) return FALSE;
01122 
01123         LLInventoryModel* model = mInventoryPanel->getModel();
01124         if(!model) return FALSE;
01125 
01126         LLVOAvatar* avatar = gAgent.getAvatarObject();
01127         if(!avatar) return FALSE;
01128 
01129         // cannot drag into library
01130         if(!isAgentInventory())
01131         {
01132                 return FALSE;
01133         }
01134 
01135         // check to make sure source is agent inventory, and is represented there.
01136         LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
01137         BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL)
01138                 && (LLToolDragAndDrop::SOURCE_AGENT == source);
01139 
01140         BOOL accept = FALSE;
01141         S32 i;
01142         LLInventoryModel::cat_array_t   descendent_categories;
01143         LLInventoryModel::item_array_t  descendent_items;
01144         if(is_agent_inventory)
01145         {
01146                 const LLUUID& cat_id = inv_cat->getUUID();
01147 
01148                 // Is the destination the trash?
01149                 LLUUID trash_id;
01150                 trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
01151                 BOOL move_is_into_trash = (mUUID == trash_id)
01152                                 || model->isObjectDescendentOf(mUUID, trash_id);
01153                 BOOL is_movable = (LLAssetType::AT_NONE == inv_cat->getPreferredType());
01154                 if( is_movable )
01155                 {
01156                         gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE );
01157 
01158                         for( i = 0; i < descendent_categories.count(); i++ )
01159                         {
01160                                 LLInventoryCategory* category = descendent_categories[i];
01161                                 if( LLAssetType::AT_NONE != category->getPreferredType() )
01162                                 {
01163                                         // ...can't move "special folders" like Textures
01164                                         is_movable = FALSE;
01165                                         break;
01166                                 }
01167                         }
01168                         
01169                         if( is_movable )
01170                         {
01171                                 if( move_is_into_trash )
01172                                 {
01173                                         for( i = 0; i < descendent_items.count(); i++ )
01174                                         {
01175                                                 LLInventoryItem* item = descendent_items[i];
01176                                                 if( (item->getType() == LLAssetType::AT_CLOTHING) ||
01177                                                         (item->getType() == LLAssetType::AT_BODYPART) )
01178                                                 {
01179                                                         if( gAgent.isWearingItem( item->getUUID() ) )
01180                                                         {
01181                                                                 is_movable = FALSE;  // It's generally movable, but not into the trash!
01182                                                                 break;
01183                                                         }
01184                                                 }
01185                                                 else
01186                                                 if( item->getType() == LLAssetType::AT_OBJECT )
01187                                                 {
01188                                                         if( avatar->isWearingAttachment( item->getUUID() ) )
01189                                                         {
01190                                                                 is_movable = FALSE;  // It's generally movable, but not into the trash!
01191                                                                 break;
01192                                                         }
01193                                                 }
01194                                         }
01195                                 }
01196                         }
01197                 }
01198 
01199                 
01200                 accept =        is_movable
01201                                         && (mUUID != cat_id)                                                            // Can't move a folder into itself
01202                                         && (mUUID != inv_cat->getParentUUID())                          // Avoid moves that would change nothing
01203                                         && !(model->isObjectDescendentOf(mUUID, cat_id));       // Avoid circularity
01204                 if(accept && drop)
01205                 {
01206                         // Look for any gestures and deactivate them
01207                         if (move_is_into_trash)
01208                         {
01209                                 for (i = 0; i < descendent_items.count(); i++)
01210                                 {
01211                                         LLInventoryItem* item = descendent_items[i];
01212                                         if (item->getType() == LLAssetType::AT_GESTURE
01213                                                 && gGestureManager.isGestureActive(item->getUUID()))
01214                                         {
01215                                                 gGestureManager.deactivateGesture(item->getUUID());
01216                                         }
01217                                 }
01218                         }
01219 
01220                         // Reparent the folder and restamp children if it's moving
01221                         // into trash.
01222                         LLInvFVBridge::changeCategoryParent(
01223                                 model,
01224                                 (LLViewerInventoryCategory*)inv_cat,
01225                                 mUUID,
01226                                 move_is_into_trash);
01227                 }
01228         }
01229         else if(LLToolDragAndDrop::SOURCE_WORLD == source)
01230         {
01231                 // content category has same ID as object itself
01232                 LLUUID object_id = inv_cat->getUUID();
01233                 LLUUID category_id = mUUID;
01234                 accept = move_inv_category_world_to_agent(object_id, category_id, drop);
01235         }
01236         return accept;
01237 }
01238 
01239 void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv)
01240 {
01241         const char* dialog = NULL;
01242         if (object->flagScripted())
01243         {
01244                 dialog = "MoveInventoryFromScriptedObject";
01245         }
01246         else
01247         {
01248                 dialog = "MoveInventoryFromObject";
01249         }
01250         gViewerWindow->alertXml(dialog, move_task_inventory_callback, move_inv);
01251 }
01252 
01253 // Move/copy all inventory items from the Contents folder of an in-world
01254 // object to the agent's inventory, inside a given category.
01255 BOOL move_inv_category_world_to_agent(const LLUUID& object_id, 
01256                                                                           const LLUUID& category_id,
01257                                                                           BOOL drop,
01258                                                                           void (*callback)(S32, void*),
01259                                                                           void* user_data)
01260 {
01261         // Make sure the object exists. If we allowed dragging from
01262         // anonymous objects, it would be possible to bypass
01263         // permissions.
01264         // content category has same ID as object itself
01265         LLViewerObject* object = gObjectList.findObject(object_id);
01266         if(!object)
01267         {
01268                 llinfos << "Object not found for drop." << llendl;
01269                 return FALSE;
01270         }
01271 
01272         // this folder is coming from an object, as there is only one folder in an object, the root,
01273         // we need to collect the entire contents and handle them as a group
01274         InventoryObjectList inventory_objects;
01275         object->getInventoryContents(inventory_objects);
01276 
01277         if (inventory_objects.empty())
01278         {
01279                 llinfos << "Object contents not found for drop." << llendl;
01280                 return FALSE;
01281         }
01282         
01283         BOOL accept = TRUE;
01284         BOOL is_move = FALSE;
01285 
01286         // coming from a task. Need to figure out if the person can
01287         // move/copy this item.
01288         InventoryObjectList::iterator it = inventory_objects.begin();
01289         InventoryObjectList::iterator end = inventory_objects.end();
01290         for ( ; it != end; ++it)
01291         {
01292                 // coming from a task. Need to figure out if the person can
01293                 // move/copy this item.
01294                 LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions());
01295                 if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
01296                         && perm.allowTransferTo(gAgent.getID())))
01297 //                      || gAgent.isGodlike())
01298                 {
01299                         accept = TRUE;
01300                 }
01301                 else if(object->permYouOwner())
01302                 {
01303                         // If the object cannot be copied, but the object the
01304                         // inventory is owned by the agent, then the item can be
01305                         // moved from the task to agent inventory.
01306                         is_move = TRUE;
01307                         accept = TRUE;
01308                 }
01309                 else
01310                 {
01311                         accept = FALSE;
01312                         break;
01313                 }
01314         }
01315 
01316         if(drop && accept)
01317         {
01318                 it = inventory_objects.begin();
01319                 InventoryObjectList::iterator first_it = inventory_objects.begin();
01320                 LLMoveInv* move_inv = new LLMoveInv;
01321                 move_inv->mObjectID = object_id;
01322                 move_inv->mCategoryID = category_id;
01323                 move_inv->mCallback = callback;
01324                 move_inv->mUserData = user_data;
01325 
01326                 for ( ; it != end; ++it)
01327                 {
01328                         two_uuids_t two(category_id, (*it)->getUUID());
01329                         move_inv->mMoveList.push_back(two);
01330                 }
01331 
01332                 if(is_move)
01333                 {
01334                         // Callback called from within here.
01335                         warn_move_inventory(object, move_inv);
01336                 }
01337                 else
01338                 {
01339                         move_task_inventory_callback(0, (void*)(move_inv));
01340                 }
01341         }
01342         return accept;
01343 }
01344 
01345 class LLFindWearables : public LLInventoryCollectFunctor
01346 {
01347 public:
01348         LLFindWearables() {}
01349         virtual ~LLFindWearables() {}
01350         virtual bool operator()(LLInventoryCategory* cat,
01351                                                         LLInventoryItem* item);
01352 };
01353 
01354 bool LLFindWearables::operator()(LLInventoryCategory* cat,
01355                                                                  LLInventoryItem* item)
01356 {
01357         if(item)
01358         {
01359                 if((item->getType() == LLAssetType::AT_CLOTHING)
01360                    || (item->getType() == LLAssetType::AT_BODYPART))
01361                 {
01362                         return TRUE;
01363                 }
01364         }
01365         return FALSE;
01366 }
01367 
01368 //Used by LLFolderBridge as callback for directory recursion.
01369 class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver
01370 {
01371 public:
01372         LLRightClickInventoryFetchObserver()  {};
01373         LLRightClickInventoryFetchObserver(const LLUUID& cat_id, bool copy_items) :
01374                 mCatID(cat_id),
01375                 mCopyItems(copy_items)
01376                 { };
01377         virtual void done()
01378         {
01379                 // we've downloaded all the items, so repaint the dialog
01380                 LLFolderBridge::staticFolderOptionsMenu();
01381 
01382                 gInventory.removeObserver(this);
01383                 delete this;
01384         }
01385         
01386 
01387 protected:
01388         LLUUID mCatID;
01389         bool mCopyItems;
01390 
01391 };
01392 
01393 //Used by LLFolderBridge as callback for directory recursion.
01394 class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
01395 {
01396 public:
01397         LLRightClickInventoryFetchDescendentsObserver(bool copy_items) : mCopyItems(copy_items) {}
01398         ~LLRightClickInventoryFetchDescendentsObserver() {}
01399         virtual void done();
01400 protected:
01401         bool mCopyItems;
01402 };
01403 
01404 void LLRightClickInventoryFetchDescendentsObserver::done()
01405 {
01406         // Avoid passing a NULL-ref as mCompleteFolders.front() down to
01407         // gInventory.collectDescendents()
01408         if( mCompleteFolders.empty() )
01409         {
01410                 llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl;
01411                 dec_busy_count();
01412                 gInventory.removeObserver(this);
01413                 delete this;
01414                 return;
01415         }
01416 
01417         // What we do here is get the complete information on the items in
01418         // the library, and set up an observer that will wait for that to
01419         // happen.
01420         LLInventoryModel::cat_array_t cat_array;
01421         LLInventoryModel::item_array_t item_array;
01422         gInventory.collectDescendents(mCompleteFolders.front(),
01423                                                                   cat_array,
01424                                                                   item_array,
01425                                                                   LLInventoryModel::EXCLUDE_TRASH);
01426         S32 count = item_array.count();
01427 #if 0 // HACK/TODO: Why?
01428         // This early causes a giant menu to get produced, and doesn't seem to be needed.
01429         if(!count)
01430         {
01431                 llwarns << "Nothing fetched in category " << mCompleteFolders.front()
01432                                 << llendl;
01433                 dec_busy_count();
01434                 gInventory.removeObserver(this);
01435                 delete this;
01436                 return;
01437         }
01438 #endif
01439 
01440         LLRightClickInventoryFetchObserver* outfit;
01441         outfit = new LLRightClickInventoryFetchObserver(mCompleteFolders.front(), mCopyItems);
01442         LLInventoryFetchObserver::item_ref_t ids;
01443         for(S32 i = 0; i < count; ++i)
01444         {
01445                 ids.push_back(item_array.get(i)->getUUID());
01446         }
01447 
01448         // clean up, and remove this as an observer since the call to the
01449         // outfit could notify observers and throw us into an infinite
01450         // loop.
01451         dec_busy_count();
01452         gInventory.removeObserver(this);
01453         delete this;
01454 
01455         // increment busy count and either tell the inventory to check &
01456         // call done, or add this object to the inventory for observation.
01457         inc_busy_count();
01458 
01459         // do the fetch
01460         outfit->fetchItems(ids);
01461         outfit->done();                         //Not interested in waiting and this will be right 99% of the time.
01462 //Uncomment the following code for laggy Inventory UI.
01463 /*      if(outfit->isEverythingComplete())
01464         {
01465                 // everything is already here - call done.
01466                 outfit->done();
01467         }
01468         else
01469         {
01470                 // it's all on it's way - add an observer, and the inventory
01471                 // will call done for us when everything is here.
01472                 gInventory.addObserver(outfit);
01473         }*/
01474 }
01475 
01476 
01477 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
01478 // Class LLInventoryWearObserver
01479 //
01480 // Observer for "copy and wear" operation to support knowing 
01481 // when the all of the contents have been added to inventory.
01482 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
01483 class LLInventoryCopyAndWearObserver : public LLInventoryObserver
01484 {
01485 public:
01486         LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) :mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {}
01487         virtual ~LLInventoryCopyAndWearObserver() {}
01488         virtual void changed(U32 mask);
01489 
01490 protected:
01491         LLUUID mCatID;
01492         int    mContentsCount;
01493         BOOL   mFolderAdded;
01494 };
01495 
01496 
01497 
01498 void LLInventoryCopyAndWearObserver::changed(U32 mask)
01499 {
01500         if((mask & (LLInventoryObserver::ADD)) != 0)
01501         {
01502                 if (!mFolderAdded) 
01503                 {
01504                         const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
01505 
01506                         std::set<LLUUID>::const_iterator id_it = changed_items.begin();
01507                         std::set<LLUUID>::const_iterator id_end = changed_items.end();
01508                         for (;id_it != id_end; ++id_it)
01509                         {
01510                                 if ((*id_it) == mCatID) 
01511                                 {
01512                                         mFolderAdded = TRUE;
01513                                         break;
01514                                 }
01515                         }
01516                 }
01517 
01518                 if (mFolderAdded) 
01519                 {
01520                         LLViewerInventoryCategory* category = gInventory.getCategory(mCatID);
01521 
01522                         if (NULL == category)
01523                         {
01524                                 llwarns << "gInventory.getCategory(" << mCatID
01525                                         << ") was NULL" << llendl;
01526                         }
01527                         else
01528                         {
01529                                 if (category->getDescendentCount() ==
01530                                     mContentsCount)
01531                                 {
01532                                         gInventory.removeObserver(this);
01533                                         wear_inventory_category(category, FALSE, TRUE);
01534                                         delete this;
01535                                 }
01536                         }               
01537                 }
01538 
01539         }
01540 }
01541 
01542 
01543 
01544 void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, LLString action)
01545 {
01546         if ("open" == action)
01547         {
01548                 openItem();
01549         }
01550         else if ("paste" == action)
01551         {
01552                 pasteFromClipboard();
01553         }
01554         else if ("properties" == action)
01555         {
01556                 showProperties();
01557         }
01558         else if ("replaceoutfit" == action)
01559         {
01560                 modifyOutfit(FALSE);
01561         }
01562         else if ("addtooutfit" == action)
01563         {
01564                 modifyOutfit(TRUE);
01565         }
01566         else if ("removefromoutfit" == action)
01567         {
01568                 LLInventoryModel* model = mInventoryPanel->getModel();
01569                 if(!model) return;
01570                 LLViewerInventoryCategory* cat = getCategory();
01571                 if(!cat) return;
01572                 
01573                 remove_inventory_category_from_avatar ( cat );
01574         }       
01575         else if ("purge" == action)
01576         {               
01577                 LLViewerInventoryCategory* cat;
01578                 cat = (LLViewerInventoryCategory*)getCategory();
01579 
01580                 if(cat)
01581                 {
01582                         model->purgeDescendentsOf(mUUID);
01583                 }
01584                 LLInventoryObject* obj = model->getObject(mUUID);
01585                 if(!obj) return;
01586                 obj->removeFromServer();
01587                 model->deleteObject(mUUID);
01588                 model->notifyObservers();
01589         }
01590         else if ("restore" == action)
01591         {
01592                 restoreItem();
01593         }
01594 }
01595 
01596 void LLFolderBridge::openItem()
01597 {
01598         lldebugs << "LLFolderBridge::openItem()" << llendl;
01599         LLInventoryModel* model = mInventoryPanel->getModel();
01600         if(!model) return;
01601         model->fetchDescendentsOf(mUUID);
01602 }
01603 
01604 BOOL LLFolderBridge::isItemRenameable() const
01605 {
01606         LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory();
01607         if(cat && (cat->getPreferredType() == LLAssetType::AT_NONE)
01608            && (cat->getOwnerID() == gAgent.getID()))
01609         {
01610                 return TRUE;
01611         }
01612         return FALSE;
01613 }
01614 
01615 void LLFolderBridge::restoreItem()
01616 {
01617         LLViewerInventoryCategory* cat;
01618         cat = (LLViewerInventoryCategory*)getCategory();
01619         if(cat)
01620         {
01621                 LLInventoryModel* model = mInventoryPanel->getModel();
01622                 LLUUID new_parent = model->findCategoryUUIDForType(cat->getType());
01623                 // do not restamp children on restore
01624                 LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE);
01625         }
01626 }
01627 
01628 // Icons for folders are based on the preferred type
01629 LLUIImagePtr LLFolderBridge::getIcon() const
01630 {
01631         const char* control = NULL;
01632         LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
01633         LLViewerInventoryCategory* cat = getCategory();
01634         if(cat)
01635         {
01636                 preferred_type = cat->getPreferredType();
01637         }
01638         switch(preferred_type)
01639         {
01640         case LLAssetType::AT_TEXTURE:
01641                 control = "inv_folder_texture.tga";
01642                 break;
01643         case LLAssetType::AT_SOUND:
01644                 control = "inv_folder_sound.tga";
01645                 break;
01646         case LLAssetType::AT_CALLINGCARD:
01647                 control = "inv_folder_callingcard.tga";
01648                 break;
01649         case LLAssetType::AT_LANDMARK:
01650                 control = "inv_folder_landmark.tga";
01651                 break;
01652         case LLAssetType::AT_SCRIPT:
01653         case LLAssetType::AT_LSL_TEXT:
01654                 control = "inv_folder_script.tga";
01655                 break;
01656         case LLAssetType::AT_OBJECT:
01657                 control = "inv_folder_object.tga";
01658                 break;
01659         case LLAssetType::AT_NOTECARD:
01660                 control = "inv_folder_notecard.tga";
01661                 break;
01662         case LLAssetType::AT_CATEGORY:
01663                 control = "inv_folder_plain_closed.tga";
01664                 break;
01665         case LLAssetType::AT_CLOTHING:
01666                 control = "inv_folder_clothing.tga";
01667                 break;
01668         case LLAssetType::AT_BODYPART:
01669                 control = "inv_folder_bodypart.tga";
01670                 break;
01671         case LLAssetType::AT_TRASH:
01672                 control = "inv_folder_trash.tga";
01673                 break;
01674         case LLAssetType::AT_SNAPSHOT_CATEGORY:
01675                 control = "inv_folder_snapshot.tga";
01676                 break;
01677         case LLAssetType::AT_LOST_AND_FOUND:
01678                 control = "inv_folder_lostandfound.tga";
01679                 break;
01680         case LLAssetType::AT_ANIMATION:
01681                 control = "inv_folder_animation.tga";
01682                 break;
01683         case LLAssetType::AT_GESTURE:
01684                 control = "inv_folder_gesture.tga";
01685                 break;
01686         default:
01687                 control = "inv_folder_plain_closed.tga";
01688                 break;
01689         }
01690         return LLUI::getUIImage(control);
01691 }
01692 
01693 BOOL LLFolderBridge::renameItem(const LLString& new_name)
01694 {
01695         if(!isItemRenameable()) return FALSE;
01696         LLInventoryModel* model = mInventoryPanel->getModel();
01697         if(!model) return FALSE;
01698         LLViewerInventoryCategory* cat = getCategory();
01699         if(cat && (cat->getName() != new_name))
01700         {
01701                 LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
01702                 new_cat->rename(new_name);
01703                 new_cat->updateServer(FALSE);
01704                 model->updateCategory(new_cat);
01705                 model->notifyObservers();
01706         }
01707         // return FALSE because we either notified observers (& therefore
01708         // rebuilt) or we didn't update.
01709         return FALSE;
01710 }
01711 
01712 BOOL LLFolderBridge::removeItem()
01713 {
01714         if(!isItemRemovable())
01715         {
01716                 return FALSE;
01717         }
01718         // move it to the trash
01719         LLPreview::hide(mUUID);
01720         LLInventoryModel* model = mInventoryPanel->getModel();
01721         if(!model) return FALSE;
01722 
01723         LLUUID trash_id;
01724         trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
01725 
01726         // Look for any gestures and deactivate them
01727         LLInventoryModel::cat_array_t   descendent_categories;
01728         LLInventoryModel::item_array_t  descendent_items;
01729         gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
01730 
01731         S32 i;
01732         for (i = 0; i < descendent_items.count(); i++)
01733         {
01734                 LLInventoryItem* item = descendent_items[i];
01735                 if (item->getType() == LLAssetType::AT_GESTURE
01736                         && gGestureManager.isGestureActive(item->getUUID()))
01737                 {
01738                         gGestureManager.deactivateGesture(item->getUUID());
01739                 }
01740         }
01741 
01742         // go ahead and do the normal remove if no 'last calling
01743         // cards' are being removed.
01744         LLViewerInventoryCategory* cat = getCategory();
01745         if(cat)
01746         {
01747                 LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE);
01748         }
01749 
01750         return TRUE;
01751 }
01752 
01753 BOOL LLFolderBridge::isClipboardPasteable() const
01754 {
01755         if(LLInventoryClipboard::instance().hasContents() && isAgentInventory())
01756         {
01757                 return TRUE;
01758         }
01759         return FALSE;
01760 }
01761 
01762 void LLFolderBridge::pasteFromClipboard()
01763 {
01764         LLInventoryModel* model = mInventoryPanel->getModel();
01765         if(model && isClipboardPasteable())
01766         {
01767                 LLInventoryItem* item = NULL;
01768                 LLDynamicArray<LLUUID> objects;
01769                 LLInventoryClipboard::instance().retrieve(objects);
01770                 S32 count = objects.count();
01771                 LLUUID parent_id(mUUID);
01772                 for(S32 i = 0; i < count; i++)
01773                 {
01774                         item = model->getItem(objects.get(i));
01775                         if (item)
01776                         {
01777                                 copy_inventory_item(
01778                                         gAgent.getID(),
01779                                         item->getPermissions().getOwner(),
01780                                         item->getUUID(),
01781                                         parent_id,
01782                                         std::string(),
01783                                         LLPointer<LLInventoryCallback>(NULL));
01784                         }
01785                 }
01786         }
01787 }
01788 
01789 void LLFolderBridge::staticFolderOptionsMenu()
01790 {
01791         if (!sSelf) return;
01792         sSelf->folderOptionsMenu();
01793 }
01794 
01795 void LLFolderBridge::folderOptionsMenu()
01796 {
01797         std::vector<LLString> disabled_items;
01798 
01799         LLInventoryModel* model = mInventoryPanel->getModel();
01800         if(!model) return;
01801         
01802         // calling card related functionality for folders.
01803 
01804         LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
01805         if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))
01806         {
01807                 mItems.push_back("Calling Card Separator");
01808                 mItems.push_back("Conference Chat Folder");
01809                 mItems.push_back("IM All Contacts In Folder");
01810         }
01811         
01812         // wearables related functionality for folders.
01813         //is_wearable
01814         LLFindWearables is_wearable;
01815         LLIsType is_object( LLAssetType::AT_OBJECT );
01816         LLIsType is_gesture( LLAssetType::AT_GESTURE );
01817 
01818         if (mWearables ||
01819                 checkFolderForContentsOfType(model, is_wearable)  ||
01820                 checkFolderForContentsOfType(model, is_object) ||
01821                 checkFolderForContentsOfType(model, is_gesture) )
01822         {
01823                 mItems.push_back("Folder Wearables Separator");
01824 
01825                 // Only enable add/replace outfit for non-default folders.
01826                 const LLInventoryCategory* category = model->getCategory(mUUID);
01827                 if (!category || (LLAssetType::AT_NONE == category->getPreferredType()))
01828                 {
01829                         mItems.push_back("Add To Outfit");
01830                         mItems.push_back("Replace Outfit");
01831                 }
01832                 mItems.push_back("Take Off Items");
01833         }
01834         hideContextEntries(*mMenu, mItems, disabled_items);
01835 }
01836 
01837 BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
01838 {
01839         LLInventoryModel::cat_array_t cat_array;
01840         LLInventoryModel::item_array_t item_array;
01841         model->collectDescendentsIf(mUUID,
01842                                                                 cat_array,
01843                                                                 item_array,
01844                                                                 LLInventoryModel::EXCLUDE_TRASH,
01845                                                                 is_type);
01846         return ((item_array.count() > 0) ? TRUE : FALSE );
01847 }
01848 
01849 // Flags unused
01850 void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
01851 {
01852         lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;
01853 //      std::vector<LLString> disabled_items;
01854         LLInventoryModel* model = mInventoryPanel->getModel();
01855         if(!model) return;
01856         LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
01857         LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
01858 
01859         if (lost_and_found_id == mUUID)
01860           {
01861                 // This is the lost+found folder.
01862                 mItems.push_back("Empty Lost And Found");
01863           }
01864 
01865         if(trash_id == mUUID)
01866         {
01867                 // This is the trash.
01868                 mItems.push_back("Empty Trash");
01869         }
01870         else if(model->isObjectDescendentOf(mUUID, trash_id))
01871         {
01872                 // This is a folder in the trash.
01873                 mItems.clear(); // clear any items that used to exist
01874                 mItems.push_back("Purge Item");
01875                 if (!isItemRemovable())
01876                 {
01877                         mDisabledItems.push_back("Purge Item");
01878                 }
01879 
01880                 mItems.push_back("Restore Item");
01881         }
01882         else if(isAgentInventory()) // do not allow creating in library
01883         {
01884                         // only mature accounts can create undershirts/underwear
01885                         /*if (!gAgent.isTeen())
01886                         {
01887                                 sub_menu->append(new LLMenuItemCallGL("New Undershirt",
01888                                                                                                         &createNewUndershirt,
01889                                                                                                         NULL,
01890                                                                                                         (void*)this));
01891                                 sub_menu->append(new LLMenuItemCallGL("New Underpants",
01892                                                                                                         &createNewUnderpants,
01893                                                                                                         NULL,
01894                                                                                                         (void*)this));
01895                         }*/
01896 
01897 /*              BOOL contains_calling_cards = FALSE;
01898                 LLInventoryModel::cat_array_t cat_array;
01899                 LLInventoryModel::item_array_t item_array;
01900 
01901                 LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
01902                 model->collectDescendentsIf(mUUID,
01903                                                                         cat_array,
01904                                                                         item_array,
01905                                                                         LLInventoryModel::EXCLUDE_TRASH,
01906                                                                         is_callingcard);
01907                 if(item_array.count() > 0) contains_calling_cards = TRUE;
01908 */
01909                 mItems.push_back("New Folder");
01910                 mItems.push_back("New Script");
01911                 mItems.push_back("New Note");
01912                 mItems.push_back("New Gesture");
01913                 mItems.push_back("New Clothes");
01914                 mItems.push_back("New Body Parts");
01915 
01916                 getClipboardEntries(false, mItems, mDisabledItems, flags);
01917 
01918                 //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06
01919                 mCallingCards = mWearables = FALSE;
01920 
01921                 LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
01922                 if (checkFolderForContentsOfType(model, is_callingcard))
01923                 {
01924                         mCallingCards=TRUE;
01925                 }
01926                 
01927                 LLFindWearables is_wearable;
01928                 LLIsType is_object( LLAssetType::AT_OBJECT );
01929                 LLIsType is_gesture( LLAssetType::AT_GESTURE );
01930 
01931                 if (checkFolderForContentsOfType(model, is_wearable)  ||
01932                         checkFolderForContentsOfType(model, is_object) ||
01933                         checkFolderForContentsOfType(model, is_gesture) )
01934                 {
01935                         mWearables=TRUE;
01936                 }
01937                 
01938                 mMenu = &menu;
01939                 sSelf = this;
01940                 LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE);
01941 
01942                 LLInventoryFetchDescendentsObserver::folder_ref_t folders;
01943                 LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
01944                 folders.push_back(category->getUUID());
01945                 fetch->fetchDescendents(folders);
01946                 inc_busy_count();
01947                 if(fetch->isEverythingComplete())
01948                 {
01949                         // everything is already here - call done.
01950                         fetch->done();
01951                 }
01952                 else
01953                 {
01954                         // it's all on it's way - add an observer, and the inventory
01955                         // will call done for us when everything is here.
01956                         gInventory.addObserver(fetch);
01957                 }
01958         }
01959         else
01960         {
01961                 mItems.push_back("--no options--");
01962                 mDisabledItems.push_back("--no options--");
01963         }
01964         hideContextEntries(menu, mItems, mDisabledItems);
01965 }
01966 
01967 BOOL LLFolderBridge::hasChildren() const
01968 {
01969         LLInventoryModel* model = mInventoryPanel->getModel();
01970         if(!model) return FALSE;
01971         LLInventoryModel::EHasChildren has_children;
01972         has_children = gInventory.categoryHasChildren(mUUID);
01973         return has_children != LLInventoryModel::CHILDREN_NO;
01974 }
01975 
01976 BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
01977                                                                 EDragAndDropType cargo_type,
01978                                                                 void* cargo_data)
01979 {
01980         //llinfos << "LLFolderBridge::dragOrDrop()" << llendl;
01981         BOOL accept = FALSE;
01982         switch(cargo_type)
01983         {
01984         case DAD_TEXTURE:
01985         case DAD_SOUND:
01986         case DAD_CALLINGCARD:
01987         case DAD_LANDMARK:
01988         case DAD_SCRIPT:
01989         case DAD_OBJECT:
01990         case DAD_NOTECARD:
01991         case DAD_CLOTHING:
01992         case DAD_BODYPART:
01993         case DAD_ANIMATION:
01994         case DAD_GESTURE:
01995                 accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
01996                                                                         drop);
01997                 break;
01998         case DAD_CATEGORY:
01999                 accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data,
02000                                                                                 drop);
02001                 break;
02002         default:
02003                 break;
02004         }
02005         return accept;
02006 }
02007 
02008 LLViewerInventoryCategory* LLFolderBridge::getCategory() const
02009 {
02010         LLViewerInventoryCategory* cat = NULL;
02011         LLInventoryModel* model = mInventoryPanel->getModel();
02012         if(model)
02013         {
02014                 cat = (LLViewerInventoryCategory*)model->getCategory(mUUID);
02015         }
02016         return cat;
02017 }
02018 
02019 
02020 // static
02021 void LLFolderBridge::pasteClipboard(void* user_data)
02022 {
02023         LLFolderBridge* self = (LLFolderBridge*)user_data;
02024         if(self) self->pasteFromClipboard();
02025 }
02026 
02027 void LLFolderBridge::createNewCategory(void* user_data)
02028 {
02029         LLFolderBridge* bridge = (LLFolderBridge*)user_data;
02030         if(!bridge) return;
02031         LLInventoryPanel* panel = bridge->mInventoryPanel;
02032         LLInventoryModel* model = panel->getModel();
02033         if(!model) return;
02034         LLUUID id;
02035         id = model->createNewCategory(bridge->getUUID(),
02036                                                                   LLAssetType::AT_NONE,
02037                                                                   NULL);
02038         model->notifyObservers();
02039 
02040         // At this point, the bridge has probably been deleted, but the
02041         // view is still there.
02042         panel->setSelection(id, TAKE_FOCUS_YES);
02043 }
02044 
02045 void LLFolderBridge::createNewShirt(void* user_data)
02046 {
02047         LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHIRT);
02048 }
02049 
02050 void LLFolderBridge::createNewPants(void* user_data)
02051 {
02052         LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_PANTS);
02053 }
02054 
02055 void LLFolderBridge::createNewShoes(void* user_data)
02056 {
02057         LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHOES);
02058 }
02059 
02060 void LLFolderBridge::createNewSocks(void* user_data)
02061 {
02062         LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SOCKS);
02063 }
02064 
02065 void LLFolderBridge::createNewJacket(void* user_data)
02066 {
02067         LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_JACKET);
02068 }
02069 
02070 void LLFolderBridge::createNewSkirt(void* user_data)
02071 {
02072         LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIRT);
02073 }
02074 
02075 void LLFolderBridge::createNewGloves(void* user_data)
02076 {
02077         LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_GLOVES);
02078 }
02079 
02080 void LLFolderBridge::createNewUndershirt(void* user_data)
02081 {
02082         LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERSHIRT);
02083 }
02084 
02085 void LLFolderBridge::createNewUnderpants(void* user_data)
02086 {
02087         LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERPANTS);
02088 }
02089 
02090 void LLFolderBridge::createNewShape(void* user_data)
02091 {
02092         LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHAPE);
02093 }
02094 
02095 void LLFolderBridge::createNewSkin(void* user_data)
02096 {
02097         LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIN);
02098 }
02099 
02100 void LLFolderBridge::createNewHair(void* user_data)
02101 {
02102         LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_HAIR);
02103 }
02104 
02105 void LLFolderBridge::createNewEyes(void* user_data)
02106 {
02107         LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_EYES);
02108 }
02109 
02110 // static
02111 void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type)
02112 {
02113         if(!bridge) return;
02114         LLUUID parent_id = bridge->getUUID();
02115         createWearable(parent_id, type);
02116 }
02117 
02118 // Separate function so can be called by global menu as well as right-click
02119 // menu.
02120 // static
02121 void LLFolderBridge::createWearable(LLUUID parent_id, EWearableType type)
02122 {
02123         LLWearable* wearable = gWearableList.createNewWearable(type);
02124         LLAssetType::EType asset_type = wearable->getAssetType();
02125         LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
02126         create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
02127                 parent_id, wearable->getTransactionID(), wearable->getName(),
02128                 wearable->getDescription(), asset_type, inv_type, wearable->getType(),
02129                 wearable->getPermissions().getMaskNextOwner(),
02130                 LLPointer<LLInventoryCallback>(NULL));
02131 }
02132 
02133 void LLFolderBridge::modifyOutfit(BOOL append)
02134 {
02135         LLInventoryModel* model = mInventoryPanel->getModel();
02136         if(!model) return;
02137         LLViewerInventoryCategory* cat = getCategory();
02138         if(!cat) return;
02139         
02140         wear_inventory_category_on_avatar( cat, append );
02141 }
02142 
02143 // helper stuff
02144 void move_task_inventory_callback(S32 option, void* user_data)
02145 {
02146         LLMoveInv* move_inv = (LLMoveInv*)user_data;
02147         LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData;
02148         LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID);
02149         
02150         if(option == 0 && object)
02151         {
02152                 if (cat_and_wear && cat_and_wear->mWear)
02153                 {
02154                         InventoryObjectList inventory_objects;
02155                         object->getInventoryContents(inventory_objects);
02156                         int contents_count = inventory_objects.size()-1; //subtract one for containing folder
02157 
02158                         LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count);
02159                         gInventory.addObserver(inventoryObserver);
02160                 }
02161 
02162                 two_uuids_list_t::iterator move_it;
02163                 for (move_it = move_inv->mMoveList.begin(); 
02164                         move_it != move_inv->mMoveList.end(); 
02165                         ++move_it)
02166                 {
02167                         object->moveInventory(move_it->first, move_it->second);
02168                 }
02169 
02170                 // update the UI.
02171                 dialog_refresh_all();
02172         }
02173 
02174         if (move_inv->mCallback)
02175         {
02176                 move_inv->mCallback(option, move_inv->mUserData);
02177         }
02178 
02179         delete move_inv;
02180 }
02181 
02182 BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
02183                                                                                 BOOL drop)
02184 {
02185         LLInventoryModel* model = mInventoryPanel->getModel();
02186         if(!model) return FALSE;
02187 
02188         // cannot drag into library
02189         if(!isAgentInventory())
02190         {
02191                 return FALSE;
02192         }
02193 
02194         LLVOAvatar* avatar = gAgent.getAvatarObject();
02195         if(!avatar) return FALSE;
02196 
02197         LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
02198         BOOL accept = FALSE;
02199         LLViewerObject* object = NULL;
02200         if(LLToolDragAndDrop::SOURCE_AGENT == source)
02201         {
02202 
02203                 BOOL is_movable = TRUE;
02204                 switch( inv_item->getType() )
02205                 {
02206                 case LLAssetType::AT_ROOT_CATEGORY:
02207                         is_movable = FALSE;
02208                         break;
02209 
02210                 case LLAssetType::AT_CATEGORY:
02211                         is_movable = ( LLAssetType::AT_NONE == ((LLInventoryCategory*)inv_item)->getPreferredType() );
02212                         break;
02213                 default:
02214                         break;
02215                 }
02216 
02217                 LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
02218                 BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
02219                 if(is_movable && move_is_into_trash)
02220                 {
02221                         switch(inv_item->getType())
02222                         {
02223                         case LLAssetType::AT_CLOTHING:
02224                         case LLAssetType::AT_BODYPART:
02225                                 is_movable = !gAgent.isWearingItem(inv_item->getUUID());
02226                                 break;
02227 
02228                         case LLAssetType::AT_OBJECT:
02229                                 is_movable = !avatar->isWearingAttachment(inv_item->getUUID());
02230                                 break;
02231                         default:
02232                                 break;
02233                         }
02234                 }
02235  
02236                 accept = is_movable && (mUUID != inv_item->getParentUUID());
02237                 if(accept && drop)
02238                 {
02239                         if (inv_item->getType() == LLAssetType::AT_GESTURE
02240                                 && gGestureManager.isGestureActive(inv_item->getUUID()))
02241                         {
02242                                 gGestureManager.deactivateGesture(inv_item->getUUID());
02243                         }
02244                         // If an item is being dragged between windows, unselect
02245                         // everything in the active window so that we don't follow
02246                         // the selection to its new location (which is very
02247                         // annoying).
02248                         if (LLInventoryView::getActiveInventory())
02249                         {
02250                                 LLInventoryPanel* active_panel = LLInventoryView::getActiveInventory()->getPanel();
02251                                 if (active_panel && (mInventoryPanel != active_panel))
02252                                 {
02253                                         active_panel->unSelectAll();
02254                                 }
02255                         }
02256 
02257                         // restamp if the move is into the trash.
02258                         LLInvFVBridge::changeItemParent(
02259                                 model,
02260                                 (LLViewerInventoryItem*)inv_item,
02261                                 mUUID,
02262                                 move_is_into_trash);
02263                 }
02264         }
02265         else if(LLToolDragAndDrop::SOURCE_WORLD == source)
02266         {
02267                 // Make sure the object exists. If we allowed dragging from
02268                 // anonymous objects, it would be possible to bypass
02269                 // permissions.
02270                 object = gObjectList.findObject(inv_item->getParentUUID());
02271                 if(!object)
02272                 {
02273                         llinfos << "Object not found for drop." << llendl;
02274                         return FALSE;
02275                 }
02276 
02277                 // coming from a task. Need to figure out if the person can
02278                 // move/copy this item.
02279                 LLPermissions perm(inv_item->getPermissions());
02280                 BOOL is_move = FALSE;
02281                 if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
02282                         && perm.allowTransferTo(gAgent.getID())))
02283 //                 || gAgent.isGodlike())
02284                         
02285                 {
02286                         accept = TRUE;
02287                 }
02288                 else if(object->permYouOwner())
02289                 {
02290                         // If the object cannot be copied, but the object the
02291                         // inventory is owned by the agent, then the item can be
02292                         // moved from the task to agent inventory.
02293                         is_move = TRUE;
02294                         accept = TRUE;
02295                 }
02296                 if(drop && accept)
02297                 {
02298                         LLMoveInv* move_inv = new LLMoveInv;
02299                         move_inv->mObjectID = inv_item->getParentUUID();
02300                         two_uuids_t item_pair(mUUID, inv_item->getUUID());
02301                         move_inv->mMoveList.push_back(item_pair);
02302                         move_inv->mCallback = NULL;
02303                         move_inv->mUserData = NULL;
02304                         if(is_move)
02305                         {
02306                                 warn_move_inventory(object, move_inv);
02307                         }
02308                         else
02309                         {
02310                                 move_task_inventory_callback(0, (void*)(move_inv));
02311                         }
02312                 }
02313                 
02314         }
02315         else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
02316         {
02317                 accept = TRUE;
02318                 if(drop)
02319                 {
02320                         copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(),
02321                                 LLToolDragAndDrop::getInstance()->getSourceID(), inv_item);
02322                 }
02323         }
02324         else if(LLToolDragAndDrop::SOURCE_LIBRARY == source)
02325         {
02326                 LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item;
02327                 if(item && item->isComplete())
02328                 {
02329                         accept = TRUE;
02330                         if(drop)
02331                         {
02332                                 copy_inventory_item(
02333                                         gAgent.getID(),
02334                                         inv_item->getPermissions().getOwner(),
02335                                         inv_item->getUUID(),
02336                                         mUUID,
02337                                         std::string(),
02338                                         LLPointer<LLInventoryCallback>(NULL));
02339                         }
02340                 }
02341         }
02342         else
02343         {
02344                 llwarns << "unhandled drag source" << llendl;
02345         }
02346         return accept;
02347 }
02348 
02349 // +=================================================+
02350 // |        LLScriptBridge (DEPRECTED)               |
02351 // +=================================================+
02352 
02353 LLUIImagePtr LLScriptBridge::getIcon() const
02354 {
02355         return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
02356 }
02357 
02358 // +=================================================+
02359 // |        LLTextureBridge                          |
02360 // +=================================================+
02361 
02362 LLString LLTextureBridge::sPrefix("Texture: ");
02363 
02364 
02365 LLUIImagePtr LLTextureBridge::getIcon() const
02366 {
02367         return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE);
02368 }
02369         
02370 void open_texture(const LLUUID& item_id, 
02371                                    const LLString& title,
02372                                    BOOL show_keep_discard,
02373                                    const LLUUID& source_id,
02374                                    BOOL take_focus)
02375 {
02376         // See if we can bring an exiting preview to the front
02377         if( !LLPreview::show( item_id, take_focus ) )
02378         {
02379                 // There isn't one, so make a new preview
02380                 S32 left, top;
02381                 gFloaterView->getNewFloaterPosition(&left, &top);
02382                 LLRect rect = gSavedSettings.getRect("PreviewTextureRect");
02383                 rect.translate( left - rect.mLeft, top - rect.mTop );
02384 
02385                 LLPreviewTexture* preview;
02386                 preview = new LLPreviewTexture("preview texture",
02387                                                                                   rect,
02388                                                                                   title,
02389                                                                                   item_id,
02390                                                                                   LLUUID::null,
02391                                                                                   show_keep_discard);
02392                 preview->setSourceID(source_id);
02393                 if(take_focus) preview->setFocus(TRUE);
02394 
02395                 gFloaterView->adjustToFitScreen(preview, FALSE);
02396         }
02397 }
02398 
02399 void LLTextureBridge::openItem()
02400 {
02401         LLViewerInventoryItem* item = getItem();
02402         if(item)
02403         {
02404                 open_texture(mUUID, getPrefix() + item->getName(), FALSE);
02405         }
02406 }
02407 
02408 // +=================================================+
02409 // |        LLSoundBridge                            |
02410 // +=================================================+
02411 
02412 LLString LLSoundBridge::sPrefix("Sound: ");
02413 
02414 
02415 LLUIImagePtr LLSoundBridge::getIcon() const
02416 {
02417         return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE);
02418 }
02419 
02420 void LLSoundBridge::openItem()
02421 {
02422 // Changed this back to the way it USED to work:
02423 // only open the preview dialog through the contextual right-click menu
02424 // double-click just plays the sound
02425 
02426         LLViewerInventoryItem* item = getItem();
02427         if(item)
02428         {
02429                 openSoundPreview((void*)this);
02430                 //send_uuid_sound_trigger(item->getAssetUUID(), 1.0);
02431         }
02432 
02433 //      if(!LLPreview::show(mUUID))
02434 //      {
02435 //              S32 left, top;
02436 //              gFloaterView->getNewFloaterPosition(&left, &top);
02437 //              LLRect rect = gSavedSettings.getRect("PreviewSoundRect");
02438 //              rect.translate(left - rect.mLeft, top - rect.mTop);
02439 //                      new LLPreviewSound("preview sound",
02440 //                                                         rect,
02441 //                                                         getPrefix() + getName(),
02442 //                                                         mUUID));
02443 //      }
02444 }
02445 
02446 void LLSoundBridge::previewItem()
02447 {
02448         LLViewerInventoryItem* item = getItem();
02449         if(item)
02450         {
02451                 send_sound_trigger(item->getAssetUUID(), 1.0);
02452         }
02453 }
02454 
02455 void LLSoundBridge::openSoundPreview(void* which)
02456 {
02457         LLSoundBridge *me = (LLSoundBridge *)which;
02458         if(!LLPreview::show(me->mUUID))
02459         {
02460                 S32 left, top;
02461                 gFloaterView->getNewFloaterPosition(&left, &top);
02462                 LLRect rect = gSavedSettings.getRect("PreviewSoundRect");
02463                 rect.translate(left - rect.mLeft, top - rect.mTop);
02464                 LLPreviewSound* preview = new LLPreviewSound("preview sound",
02465                                                                                    rect,
02466                                                                                    me->getPrefix() + me->getName(),
02467                                                                                    me->mUUID);
02468                 preview->setFocus(TRUE);
02469                 // Keep entirely onscreen.
02470                 gFloaterView->adjustToFitScreen(preview, FALSE);
02471         }
02472 }
02473 
02474 void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
02475 {
02476         lldebugs << "LLTextureBridge::buildContextMenu()" << llendl;
02477         std::vector<LLString> items;
02478         std::vector<LLString> disabled_items;
02479 
02480         if(isInTrash())
02481         {
02482                 items.push_back("Purge Item");
02483                 if (!isItemRemovable())
02484                 {
02485                         disabled_items.push_back("Purge Item");
02486                 }
02487 
02488                 items.push_back("Restore Item");
02489         }
02490         else
02491         {
02492                 items.push_back("Sound Open");
02493                 items.push_back("Properties");
02494 
02495                 getClipboardEntries(true, items, disabled_items, flags);
02496         }
02497 
02498         items.push_back("Sound Separator");
02499         items.push_back("Sound Play");
02500 
02501         hideContextEntries(menu, items, disabled_items);
02502 }
02503 
02504 // +=================================================+
02505 // |        LLLandmarkBridge                         |
02506 // +=================================================+
02507 
02508 LLString LLLandmarkBridge::sPrefix("Landmark:  ");
02509 
02510 LLUIImagePtr LLLandmarkBridge::getIcon() const
02511 {
02512         return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE);
02513 }
02514 
02515 void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
02516 {
02517         std::vector<LLString> items;
02518         std::vector<LLString> disabled_items;
02519 
02520         lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl;
02521         if(isInTrash())
02522         {
02523                 items.push_back("Purge Item");
02524                 if (!isItemRemovable())
02525                 {
02526                         disabled_items.push_back("Purge Item");
02527                 }
02528 
02529                 items.push_back("Restore Item");
02530         }
02531         else
02532         {
02533                 items.push_back("Landmark Open");
02534                 items.push_back("Properties");
02535 
02536                 getClipboardEntries(true, items, disabled_items, flags);
02537         }
02538 
02539         items.push_back("Landmark Separator");
02540         items.push_back("Teleport To Landmark");
02541 
02542         hideContextEntries(menu, items, disabled_items);
02543 
02544 }
02545 
02546 // virtual
02547 void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* model, LLString action)
02548 {
02549         if ("teleport" == action)
02550         {
02551                 LLViewerInventoryItem* item = getItem();
02552                 if(item)
02553                 {
02554                         gAgent.teleportViaLandmark(item->getAssetUUID());
02555 
02556                         // we now automatically track the landmark you're teleporting to
02557                         // because you'll probably arrive at a telehub instead
02558                         if( gFloaterWorldMap )
02559                         {
02560                                 gFloaterWorldMap->trackLandmark( item->getAssetUUID() );
02561                         }
02562                 }
02563         }
02564         if ("about" == action)
02565         {
02566                 LLViewerInventoryItem* item = getItem();
02567                 if(item)
02568                 {
02569                         open_landmark(item, LLString("  ") + getPrefix() + item->getName(), FALSE);
02570                 }
02571         }
02572         else LLItemBridge::performAction(folder, model, action);
02573 }
02574 
02575 void open_landmark(LLViewerInventoryItem* inv_item,
02576                                    const LLString& title,
02577                                    BOOL show_keep_discard,
02578                                    const LLUUID& source_id,
02579                                    BOOL take_focus)
02580 {
02581         // See if we can bring an exiting preview to the front
02582         if( !LLPreview::show( inv_item->getUUID(), take_focus ) )
02583         {
02584                 // There isn't one, so make a new preview
02585                 S32 left, top;
02586                 gFloaterView->getNewFloaterPosition(&left, &top);
02587                 LLRect rect = gSavedSettings.getRect("PreviewLandmarkRect");
02588                 rect.translate( left - rect.mLeft, top - rect.mTop );
02589 
02590                 LLPreviewLandmark* preview = new LLPreviewLandmark(title,
02591                                                                   rect,
02592                                                                   title,
02593                                                                   inv_item->getUUID(),
02594                                                                   show_keep_discard,
02595                                                                   inv_item);
02596                 preview->setSourceID(source_id);
02597                 if(take_focus) preview->setFocus(TRUE);
02598                 // keep onscreen
02599                 gFloaterView->adjustToFitScreen(preview, FALSE);
02600         }
02601 }
02602 
02603 static void open_landmark_callback(S32 option, void* data)
02604 {
02605         LLUUID* asset_idp = (LLUUID*)data;
02606         if (option == 0)
02607         {
02608                 // HACK: This is to demonstrate teleport on double click for landmarks
02609                 gAgent.teleportViaLandmark( *asset_idp );
02610 
02611                 // we now automatically track the landmark you're teleporting to
02612                 // because you'll probably arrive at a telehub instead
02613                 if( gFloaterWorldMap )
02614                 {
02615                         gFloaterWorldMap->trackLandmark( *asset_idp );
02616                 }
02617         }
02618         delete asset_idp;
02619 }
02620 
02621 void LLLandmarkBridge::openItem()
02622 {
02623         LLViewerInventoryItem* item = getItem();
02624         if( item )
02625         {
02626                 // Opening (double-clicking) a landmark immediately teleports,
02627                 // but warns you the first time.
02628                 // open_landmark(item, LLString("  ") + getPrefix() + item->getName(), FALSE);
02629                 LLUUID* asset_idp = new LLUUID(item->getAssetUUID());
02630                 LLAlertDialog::showXml("TeleportFromLandmark",
02631                         open_landmark_callback, (void*)asset_idp);
02632         }
02633 }
02634 
02635 
02636 // +=================================================+
02637 // |        LLCallingCardObserver                    |
02638 // +=================================================+
02639 void LLCallingCardObserver::changed(U32 mask)
02640 {
02641         mBridgep->refreshFolderViewItem();
02642 }
02643 
02644 // +=================================================+
02645 // |        LLCallingCardBridge                      |
02646 // +=================================================+
02647 
02648 LLString LLCallingCardBridge::sPrefix("Calling Card: ");
02649 
02650 LLCallingCardBridge::LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ) :
02651         LLItemBridge(inventory, uuid)
02652 {
02653         mObserver = new LLCallingCardObserver(this);
02654         LLAvatarTracker::instance().addObserver(mObserver);
02655 }
02656 
02657 LLCallingCardBridge::~LLCallingCardBridge()
02658 {
02659         LLAvatarTracker::instance().removeObserver(mObserver);
02660         delete mObserver;
02661 }
02662 
02663 void LLCallingCardBridge::refreshFolderViewItem()
02664 {
02665         LLFolderViewItem* itemp = mInventoryPanel->getRootFolder()->getItemByID(mUUID);
02666         if (itemp)
02667         {
02668                 itemp->refresh();
02669         }
02670 }
02671 
02672 // virtual
02673 void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel* model, LLString action)
02674 {
02675         if ("begin_im" == action)
02676         {
02677                 LLViewerInventoryItem *item = getItem();
02678                 if (item && (item->getCreatorUUID() != gAgent.getID()) &&
02679                         (!item->getCreatorUUID().isNull()))
02680                 {
02681                         gIMMgr->setFloaterOpen(TRUE);
02682                         gIMMgr->addSession(item->getName(), IM_NOTHING_SPECIAL, item->getCreatorUUID());
02683                 }
02684         }
02685         else if ("lure" == action)
02686         {
02687                 LLViewerInventoryItem *item = getItem();
02688                 if (item && (item->getCreatorUUID() != gAgent.getID()) &&
02689                         (!item->getCreatorUUID().isNull()))
02690                 {
02691                         handle_lure(item->getCreatorUUID());
02692                 }
02693         }
02694         else LLItemBridge::performAction(folder, model, action);
02695 }
02696 
02697 LLUIImagePtr LLCallingCardBridge::getIcon() const
02698 {
02699         BOOL online = FALSE;
02700         LLViewerInventoryItem* item = getItem();
02701         if(item)
02702         {
02703                 online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID());
02704         }
02705         return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE);
02706 }
02707 
02708 LLString LLCallingCardBridge::getLabelSuffix() const
02709 {
02710         LLViewerInventoryItem* item = getItem();
02711         if( item && LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()) )
02712         {
02713                 return LLItemBridge::getLabelSuffix() + " (online)";
02714         }
02715         else
02716         {
02717                 return LLItemBridge::getLabelSuffix();
02718         }
02719 }
02720 
02721 void LLCallingCardBridge::openItem()
02722 {
02723         LLViewerInventoryItem* item = getItem();
02724         if(item && !item->getCreatorUUID().isNull())
02725         {
02726                 BOOL online;
02727                 online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID());
02728                 LLFloaterAvatarInfo::showFromFriend(item->getCreatorUUID(), online);
02729         }
02730 }
02731 
02732 void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
02733 {
02734         lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl;
02735         std::vector<LLString> items;
02736         std::vector<LLString> disabled_items;
02737 
02738         if(isInTrash())
02739         {
02740                 items.push_back("Purge Item");
02741                 if (!isItemRemovable())
02742                 {
02743                         disabled_items.push_back("Purge Item");
02744                 }
02745 
02746                 items.push_back("Restore Item");
02747         }
02748         else
02749         {
02750                 items.push_back("Open");
02751                 items.push_back("Properties");
02752 
02753                 getClipboardEntries(true, items, disabled_items, flags);
02754 
02755                 LLInventoryItem* item = getItem();
02756                 BOOL good_card = (item
02757                                                   && (LLUUID::null != item->getCreatorUUID())
02758                                                   && (item->getCreatorUUID() != gAgent.getID()));
02759                 BOOL user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()));
02760                 items.push_back("Send Instant Message Separator");
02761                 items.push_back("Send Instant Message");
02762                 items.push_back("Offer Teleport...");
02763                 items.push_back("Conference Chat");
02764 
02765                 if (!good_card)
02766                 {
02767                         disabled_items.push_back("Send Instant Message");
02768                 }
02769                 if (!good_card || !user_online)
02770                 {
02771                         disabled_items.push_back("Offer Teleport...");
02772                         disabled_items.push_back("Conference Chat");
02773                 }
02774         }
02775         hideContextEntries(menu, items, disabled_items);
02776 }
02777 
02778 BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
02779                                                                          EDragAndDropType cargo_type,
02780                                                                          void* cargo_data)
02781 {
02782         LLViewerInventoryItem* item = getItem();
02783         BOOL rv = FALSE;
02784         if(item)
02785         {
02786                 // check the type
02787                 switch(cargo_type)
02788                 {
02789                 case DAD_TEXTURE:
02790                 case DAD_SOUND:
02791                 case DAD_LANDMARK:
02792                 case DAD_SCRIPT:
02793                 case DAD_CLOTHING:
02794                 case DAD_OBJECT:
02795                 case DAD_NOTECARD:
02796                 case DAD_BODYPART:
02797                 case DAD_ANIMATION:
02798                 case DAD_GESTURE:
02799                         {
02800                                 LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
02801                                 const LLPermissions& perm = inv_item->getPermissions();
02802                                 if(gInventory.getItem(inv_item->getUUID())
02803                                    && perm.allowOperationBy(PERM_TRANSFER, gAgent.getID()))
02804                                 {
02805                                         rv = TRUE;
02806                                         if(drop)
02807                                         {
02808                                                 LLToolDragAndDrop::giveInventory(item->getCreatorUUID(),
02809                                                                                                                  (LLInventoryItem*)cargo_data);
02810                                         }
02811                                 }
02812                                 else
02813                                 {
02814                                         // It's not in the user's inventory (it's probably in
02815                                         // an object's contents), so disallow dragging it here.
02816                                         // You can't give something you don't yet have.
02817                                         rv = FALSE;
02818                                 }
02819                                 break;
02820                         }
02821                 case DAD_CATEGORY:
02822                         {
02823                                 LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data;
02824                                 if( gInventory.getCategory( inv_cat->getUUID() ) )
02825                                 {
02826                                         rv = TRUE;
02827                                         if(drop)
02828                                         {
02829                                                 LLToolDragAndDrop::giveInventoryCategory(
02830                                                         item->getCreatorUUID(),
02831                                                         inv_cat);
02832                                         }
02833                                 }
02834                                 else
02835                                 {
02836                                         // It's not in the user's inventory (it's probably in
02837                                         // an object's contents), so disallow dragging it here.
02838                                         // You can't give something you don't yet have.
02839                                         rv = FALSE;
02840                                 }
02841                                 break;
02842                         }
02843                 default:
02844                         break;
02845                 }
02846         }
02847         return rv;
02848 }
02849 
02850 // +=================================================+
02851 // |        LLNotecardBridge                         |
02852 // +=================================================+
02853 
02854 LLString LLNotecardBridge::sPrefix("Note: ");
02855 
02856 
02857 LLUIImagePtr LLNotecardBridge::getIcon() const
02858 {
02859         return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE);
02860 }
02861 
02862 void open_notecard(LLViewerInventoryItem* inv_item,
02863                                    const LLString& title,
02864                                    const LLUUID& object_id,
02865                                    BOOL show_keep_discard,
02866                                    const LLUUID& source_id,
02867                                    BOOL take_focus)
02868 {
02869         // See if we can bring an existing preview to the front
02870         if(!LLPreview::show(inv_item->getUUID(), take_focus))
02871         {
02872                 // There isn't one, so make a new preview
02873                 S32 left, top;
02874                 gFloaterView->getNewFloaterPosition(&left, &top);
02875                 LLRect rect = gSavedSettings.getRect("NotecardEditorRect");
02876                 rect.translate(left - rect.mLeft, top - rect.mTop);
02877                 LLPreviewNotecard* preview;
02878                 preview = new LLPreviewNotecard("preview notecard", rect, title,
02879                                                 inv_item->getUUID(), object_id, inv_item->getAssetUUID(),
02880                                                 show_keep_discard, inv_item);
02881                 preview->setSourceID(source_id);
02882                 if(take_focus) preview->setFocus(TRUE);
02883                 // Force to be entirely onscreen.
02884                 gFloaterView->adjustToFitScreen(preview, FALSE);
02885 
02886                 //if (source_id.notNull())
02887                 //{
02888                 //      // look for existing tabbed view for content from same source
02889                 //      LLPreview* existing_preview = LLPreview::getPreviewForSource(source_id);
02890                 //      if (existing_preview)
02891                 //      {
02892                 //              // found existing preview from this source
02893                 //              // is it already hosted in a multi-preview window?
02894                 //              LLMultiPreview* preview_hostp = (LLMultiPreview*)existing_preview->getHost();
02895                 //              if (!preview_hostp)
02896                 //              {
02897                 //                      // create new multipreview if it doesn't exist
02898                 //                      LLMultiPreview* preview_hostp = new LLMultiPreview(existing_preview->getRect());
02899                 //                      preview_hostp->addFloater(existing_preview);
02900                 //              }
02901                 //              // add this preview to existing host
02902                 //              preview_hostp->addFloater(preview);
02903                 //      }
02904                 //}
02905         }
02906 }
02907 
02908 
02909 void LLNotecardBridge::openItem()
02910 {
02911         LLViewerInventoryItem* item = getItem();
02912         if (item)
02913         {
02914                 open_notecard(item, getPrefix() + item->getName(), LLUUID::null, FALSE);
02915         }
02916 }
02917 
02918 
02919 // +=================================================+
02920 // |        LLGestureBridge                          |
02921 // +=================================================+
02922 
02923 LLString LLGestureBridge::sPrefix("Gesture: ");
02924 
02925 LLUIImagePtr LLGestureBridge::getIcon() const
02926 {
02927         return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE);
02928 }
02929 
02930 LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const
02931 {
02932         if( gGestureManager.isGestureActive(mUUID) )
02933         {
02934                 return LLFontGL::BOLD;
02935         }
02936         else
02937         {
02938                 return LLFontGL::NORMAL;
02939         }
02940 }
02941 
02942 LLString LLGestureBridge::getLabelSuffix() const
02943 {
02944         if( gGestureManager.isGestureActive(mUUID) )
02945         {
02946                 return LLItemBridge::getLabelSuffix() + " (active)";
02947         }
02948         else
02949         {
02950                 return LLItemBridge::getLabelSuffix();
02951         }
02952 }
02953 
02954 // virtual
02955 void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, LLString action)
02956 {
02957         if ("activate" == action)
02958         {
02959                 gGestureManager.activateGesture(mUUID);
02960 
02961                 LLViewerInventoryItem* item = gInventory.getItem(mUUID);
02962                 if (!item) return;
02963 
02964                 // Since we just changed the suffix to indicate (active)
02965                 // the server doesn't need to know, just the viewer.
02966                 gInventory.updateItem(item);
02967                 gInventory.notifyObservers();
02968         }
02969         else if ("deactivate" == action)
02970         {
02971                 gGestureManager.deactivateGesture(mUUID);
02972 
02973                 LLViewerInventoryItem* item = gInventory.getItem(mUUID);
02974                 if (!item) return;
02975 
02976                 // Since we just changed the suffix to indicate (active)
02977                 // the server doesn't need to know, just the viewer.
02978                 gInventory.updateItem(item);
02979                 gInventory.notifyObservers();
02980         }
02981         else LLItemBridge::performAction(folder, model, action);
02982 }
02983 
02984 void LLGestureBridge::openItem()
02985 {
02986         LLViewerInventoryItem* item = getItem();
02987         if (!item) return;
02988 
02989         // See if we can bring an existing preview to the front
02990         if(!LLPreview::show(mUUID))
02991         {
02992                 LLUUID item_id = mUUID;
02993                 LLString title = getPrefix() + item->getName();
02994                 LLUUID object_id = LLUUID::null;
02995 
02996                 // TODO: save the rectangle
02997                 LLPreviewGesture* preview = LLPreviewGesture::show(title, item_id, object_id);
02998                 preview->setFocus(TRUE);
02999 
03000                 // Force to be entirely onscreen.
03001                 gFloaterView->adjustToFitScreen(preview, FALSE);
03002         }
03003 }
03004 
03005 BOOL LLGestureBridge::removeItem()
03006 {
03007         // Force close the preview window, if it exists
03008         gGestureManager.deactivateGesture(mUUID);
03009         return LLItemBridge::removeItem();
03010 }
03011 
03012 void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
03013 {
03014         lldebugs << "LLGestureBridge::buildContextMenu()" << llendl;
03015         std::vector<LLString> items;
03016         std::vector<LLString> disabled_items;
03017         if(isInTrash())
03018         {
03019                 items.push_back("Purge Item");
03020                 if (!isItemRemovable())
03021                 {
03022                         disabled_items.push_back("Purge Item");
03023                 }
03024 
03025                 items.push_back("Restore Item");
03026         }
03027         else
03028         {
03029                 items.push_back("Open");
03030                 items.push_back("Properties");
03031 
03032                 getClipboardEntries(true, items, disabled_items, flags);
03033 
03034                 items.push_back("Gesture Separator");
03035                 items.push_back("Activate");
03036                 items.push_back("Deactivate");
03037 
03038                 /*menu.append(new LLMenuItemCallGL("Activate",
03039                                                                                  handleActivateGesture,
03040                                                                                  enableActivateGesture,
03041                                                                                  (void*)this));
03042                 menu.append(new LLMenuItemCallGL("Deactivate",
03043                                                                                  handleDeactivateGesture,
03044                                                                                  enableDeactivateGesture,
03045                                                                                  (void*)this));*/
03046         }
03047         hideContextEntries(menu, items, disabled_items);
03048 }
03049 
03050 // +=================================================+
03051 // |        LLAnimationBridge                        |
03052 // +=================================================+
03053 
03054 LLString LLAnimationBridge::sPrefix("Animation: ");
03055 
03056 
03057 LLUIImagePtr LLAnimationBridge::getIcon() const
03058 {
03059         return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE);
03060 }
03061 
03062 void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
03063 {
03064         std::vector<LLString> items;
03065         std::vector<LLString> disabled_items;
03066 
03067         lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl;
03068         if(isInTrash())
03069         {
03070                 items.push_back("Purge Item");
03071                 if (!isItemRemovable())
03072                 {
03073                         disabled_items.push_back("Purge Item");
03074                 }
03075 
03076                 items.push_back("Restore Item");
03077         }
03078         else
03079         {
03080                 items.push_back("Animation Open");
03081                 items.push_back("Properties");
03082 
03083                 getClipboardEntries(true, items, disabled_items, flags);
03084         }
03085 
03086         items.push_back("Animation Separator");
03087         items.push_back("Animation Play");
03088         items.push_back("Animation Audition");
03089 
03090         hideContextEntries(menu, items, disabled_items);
03091 
03092 }
03093 
03094 // virtual
03095 void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* model, LLString action)
03096 {
03097         S32 activate = 0;
03098 
03099         if ((action == "playworld") || (action == "playlocal"))
03100         {
03101         
03102                 if ("playworld" == action) activate = 1;
03103                 if ("playlocal" == action) activate = 2;
03104 
03105                 // See if we can bring an existing preview to the front
03106                 if( !LLPreview::show( mUUID ) )
03107                 {
03108                         // There isn't one, so make a new preview
03109                         LLViewerInventoryItem* item = getItem();
03110                         if( item )
03111                         {
03112                                 S32 left, top;
03113                                 gFloaterView->getNewFloaterPosition(&left, &top);
03114                                 LLRect rect = gSavedSettings.getRect("PreviewAnimRect");
03115                                 rect.translate( left - rect.mLeft, top - rect.mTop );
03116                                 LLPreviewAnim* preview = new LLPreviewAnim("preview anim",
03117                                                                                 rect,
03118                                                                                 getPrefix() + item->getName(),
03119                                                                                 mUUID,
03120                                                                                 activate);
03121                                 // Force to be entirely onscreen.
03122                                 gFloaterView->adjustToFitScreen(preview, FALSE);
03123                         }
03124                 }
03125         }
03126         else
03127         {
03128                 LLItemBridge::performAction(folder, model, action);
03129         }
03130 }
03131 
03132 void LLAnimationBridge::openItem()
03133 {
03134         // See if we can bring an existing preview to the front
03135         if( !LLPreview::show( mUUID ) )
03136         {
03137                 // There isn't one, so make a new preview
03138                 LLViewerInventoryItem* item = getItem();
03139                 if( item )
03140                 {
03141                         S32 left, top;
03142                         gFloaterView->getNewFloaterPosition(&left, &top);
03143                         LLRect rect = gSavedSettings.getRect("PreviewAnimRect");
03144                         rect.translate( left - rect.mLeft, top - rect.mTop );
03145                         LLPreviewAnim* preview = new LLPreviewAnim("preview anim",
03146                                                                         rect,
03147                                                                         getPrefix() + item->getName(),
03148                                                                         mUUID,
03149                                                                         0);
03150                         preview->setFocus(TRUE);
03151                         // Force to be entirely onscreen.
03152                         gFloaterView->adjustToFitScreen(preview, FALSE);
03153                 }
03154         }
03155 }
03156 
03157 // +=================================================+
03158 // |        LLObjectBridge                           |
03159 // +=================================================+
03160 
03161 // static
03162 LLString LLObjectBridge::sPrefix("Object: ");
03163 
03164 // static
03165 LLUUID LLObjectBridge::sContextMenuItemID;
03166 
03167 BOOL LLObjectBridge::isItemRemovable()
03168 {
03169         LLVOAvatar* avatar = gAgent.getAvatarObject();
03170         if(!avatar) return FALSE;
03171         if(avatar->isWearingAttachment(mUUID)) return FALSE;
03172         return LLInvFVBridge::isItemRemovable();
03173 }
03174 
03175 LLUIImagePtr LLObjectBridge::getIcon() const
03176 {
03177         return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject );
03178 }
03179 
03180 void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment);
03181 
03182 // virtual
03183 void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, LLString action)
03184 {
03185         if ("attach" == action)
03186         {
03187                 LLUUID object_id = mUUID;
03188                 LLViewerInventoryItem* item;
03189                 item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
03190                 if(item && gInventory.isObjectDescendentOf(object_id, gAgent.getInventoryRootID()))
03191                 {
03192                         rez_attachment(item, NULL);
03193                 }
03194                 else if(item && item->isComplete())
03195                 {
03196                         // must be in library. copy it to our inventory and put it on.
03197                         LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0);
03198                         copy_inventory_item(
03199                                 gAgent.getID(),
03200                                 item->getPermissions().getOwner(),
03201                                 item->getUUID(),
03202                                 LLUUID::null,
03203                                 std::string(),
03204                                 cb);
03205                 }
03206                 gFocusMgr.setKeyboardFocus(NULL);
03207         }
03208         else if ("detach" == action)
03209         {
03210                 LLInventoryItem* item = gInventory.getItem(mUUID);
03211                 if( item )
03212                 {
03213                         gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
03214                         gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
03215                         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
03216                         gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getUUID() );
03217 
03218                         gMessageSystem->sendReliable( gAgent.getRegion()->getHost() );
03219                 }
03220                 // this object might have been selected, so let the selection manager know it's gone now
03221                 LLViewerObject *found_obj =
03222                         gObjectList.findObject(item->getUUID());
03223                 if (found_obj)
03224                 {
03225                         LLSelectMgr::getInstance()->remove(found_obj);
03226                 }
03227                 else
03228                 {
03229                         llwarns << "object not found - ignoring" << llendl;
03230                 }
03231         }
03232         else LLItemBridge::performAction(folder, model, action);
03233 }
03234 
03235 void LLObjectBridge::openItem()
03236 {
03237         /* Disabled -- this preview isn't useful. JC */
03238         // CP: actually, this code is required - made changes to match LLAnimationBridge::openItem() idiom
03239         // The properties preview is useful, converting to show object properties. - DaveP
03240         LLShowProps::showProperties(mUUID);
03241 }
03242 
03243 LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
03244 { 
03245         LLVOAvatar* avatar = gAgent.getAvatarObject();
03246         if( avatar && avatar->isWearingAttachment( mUUID ) )
03247         {
03248                 return LLFontGL::BOLD;
03249         }
03250         else
03251         {
03252                 return LLFontGL::NORMAL;
03253         }
03254 }
03255 
03256 LLString LLObjectBridge::getLabelSuffix() const
03257 {
03258         LLVOAvatar* avatar = gAgent.getAvatarObject();
03259         if( avatar && avatar->isWearingAttachment( mUUID ) )
03260         {
03261                 LLString attachment_point_name = avatar->getAttachedPointName(mUUID);
03262                 LLString::toLower(attachment_point_name);
03263                 return LLItemBridge::getLabelSuffix() + LLString(" (worn on ") + attachment_point_name + LLString(")");
03264         }
03265         else
03266         {
03267                 return LLItemBridge::getLabelSuffix();
03268         }
03269 }
03270 
03271 void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment)
03272 {
03273         LLAttachmentRezAction* rez_action = new LLAttachmentRezAction;
03274         rez_action->mItemID = item->getUUID();
03275         S32 attach_pt = 0;
03276         if (gAgent.getAvatarObject() && attachment)
03277         {
03278                 for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin();
03279                          iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter)
03280                 {
03281                         if (iter->second == attachment)
03282                         {
03283                                 attach_pt = iter->first;
03284                                 break;
03285                         }
03286                 }
03287         }
03288         rez_action->mAttachPt = attach_pt;
03289         if (attachment && attachment->getObject())
03290         {
03291                 gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action);
03292         }
03293         else
03294         {
03295                 confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action);
03296         }
03297 }
03298 
03299 void confirm_replace_attachment_rez(S32 option, void* user_data)
03300 {
03301         LLAttachmentRezAction* rez_action = (LLAttachmentRezAction*)user_data;
03302         if (option == 0/*YES*/)
03303         {
03304                 if (rez_action)
03305                 {
03306                         LLViewerInventoryItem* itemp = gInventory.getItem(rez_action->mItemID);
03307                         
03308                         if (itemp)
03309                         {
03310                                 LLMessageSystem* msg = gMessageSystem;
03311                                 msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv);
03312                                 msg->nextBlockFast(_PREHASH_AgentData);
03313                                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
03314                                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03315                                 msg->nextBlockFast(_PREHASH_ObjectData);
03316                                 msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID());
03317                                 msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner());
03318                                 msg->addU8Fast(_PREHASH_AttachmentPt, rez_action->mAttachPt);
03319                                 pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions());
03320                                 msg->addStringFast(_PREHASH_Name, itemp->getName());
03321                                 msg->addStringFast(_PREHASH_Description, itemp->getDescription());
03322                                 msg->sendReliable(gAgent.getRegion()->getHost());
03323                         }
03324                 }
03325         }
03326         delete rez_action;
03327 }
03328 
03329 void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
03330 {
03331         std::vector<LLString> items;
03332         std::vector<LLString> disabled_items;
03333         if(isInTrash())
03334         {
03335                 items.push_back("Purge Item");
03336                 if (!isItemRemovable())
03337                 {
03338                         disabled_items.push_back("Purge Item");
03339                 }
03340 
03341                 items.push_back("Restore Item");
03342         }
03343         else
03344         {
03345                 items.push_back("Properties");
03346 
03347                 getClipboardEntries(true, items, disabled_items, flags);
03348 
03349                 LLObjectBridge::sContextMenuItemID = mUUID;
03350 
03351                 LLInventoryItem* item = getItem();
03352                 if(item)
03353                 {
03354                         LLVOAvatar *avatarp = gAgent.getAvatarObject();
03355                         if( !avatarp )
03356                         {
03357                                 return;
03358                         }
03359                         
03360                         if( avatarp->isWearingAttachment( mUUID ) )
03361                         {
03362                                 items.push_back("Detach From Yourself");
03363                         }
03364                         else
03365                         if( !isInTrash() )
03366                         {
03367                                 items.push_back("Attach Separator");
03368                                 items.push_back("Object Wear");
03369                                 items.push_back("Attach To");
03370                                 items.push_back("Attach To HUD");
03371 
03372                                 LLMenuGL* attach_menu = menu.getChildMenuByName("Attach To", TRUE);
03373                                 LLMenuGL* attach_hud_menu = menu.getChildMenuByName("Attach To HUD", TRUE);
03374                                 LLVOAvatar *avatarp = gAgent.getAvatarObject();
03375                                 if (attach_menu && (attach_menu->getChildCount() == 0) &&
03376                                         attach_hud_menu && (attach_hud_menu->getChildCount() == 0) &&
03377                                         avatarp)
03378                                 {
03379                                         for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); 
03380                                                  iter != avatarp->mAttachmentPoints.end(); )
03381                                         {
03382                                                 LLVOAvatar::attachment_map_t::iterator curiter = iter++;
03383                                                 LLViewerJointAttachment* attachment = curiter->second;
03384                                                 LLMenuItemCallGL *new_item;
03385                                                 if (attachment->getIsHUDAttachment())
03386                                                 {
03387                                                         attach_hud_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(), 
03388                                                                 NULL, //&LLObjectBridge::attachToAvatar, 
03389                                                                 NULL, &attach_label, (void*)attachment));
03390                                                 }
03391                                                 else
03392                                                 {
03393                                                         attach_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(), 
03394                                                                 NULL, //&LLObjectBridge::attachToAvatar,
03395                                                                 NULL, &attach_label, (void*)attachment));
03396                                                 }
03397 
03398                                                 LLSimpleListener* callback = mInventoryPanel->getListenerByName("Inventory.AttachObject");
03399 
03400                                                 if (callback)
03401                                                 {
03402                                                         new_item->addListener(callback, "on_click", LLSD(attachment->getName()));
03403                                                 }
03404                                         }
03405                                 }
03406                         }
03407                 }
03408         }
03409         hideContextEntries(menu, items, disabled_items);
03410 }
03411 
03412 BOOL LLObjectBridge::renameItem(const LLString& new_name)
03413 {
03414         if(!isItemRenameable()) return FALSE;
03415         LLPreview::rename(mUUID, getPrefix() + new_name);
03416         LLInventoryModel* model = mInventoryPanel->getModel();
03417         if(!model) return FALSE;
03418         LLViewerInventoryItem* item = getItem();
03419         if(item && (item->getName() != new_name))
03420         {
03421                 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
03422                 new_item->rename(new_name);
03423                 buildDisplayName(new_item, mDisplayName);
03424                 new_item->updateServer(FALSE);
03425                 model->updateItem(new_item);
03426                 model->notifyObservers();
03427 
03428                 LLVOAvatar* avatar = gAgent.getAvatarObject();
03429                 if( avatar )
03430                 {
03431                         LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() );
03432                         if( obj )
03433                         {
03434                                 LLSelectMgr::getInstance()->deselectAll();
03435                                 LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE );
03436                                 LLSelectMgr::getInstance()->selectionSetObjectName( new_name );
03437                                 LLSelectMgr::getInstance()->deselectAll();
03438                         }
03439                 }
03440         }
03441         // return FALSE because we either notified observers (& therefore
03442         // rebuilt) or we didn't update.
03443         return FALSE;
03444 }
03445 
03446 // +=================================================+
03447 // |        LLLSLTextBridge                          |
03448 // +=================================================+
03449 
03450 LLString LLLSLTextBridge::sPrefix("Script: ");
03451 
03452 LLUIImagePtr LLLSLTextBridge::getIcon() const
03453 {
03454         return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
03455 }
03456 
03457 void LLLSLTextBridge::openItem()
03458 {
03459         // See if we can bring an exiting preview to the front
03460         if(!LLPreview::show(mUUID))
03461         {
03462                 LLViewerInventoryItem* item = getItem();
03463                 if (item)
03464                 {
03465                         // There isn't one, so make a new preview
03466                         S32 left, top;
03467                         gFloaterView->getNewFloaterPosition(&left, &top);
03468                         LLRect rect = gSavedSettings.getRect("PreviewScriptRect");
03469                         rect.translate(left - rect.mLeft, top - rect.mTop);
03470                         
03471                         LLPreviewLSL* preview = new LLPreviewLSL("preview lsl text",
03472                                                                                          rect,
03473                                                                                          getPrefix() + item->getName(),
03474                                                                                          mUUID);
03475                         preview->setFocus(TRUE);
03476                         // keep onscreen
03477                         gFloaterView->adjustToFitScreen(preview, FALSE);
03478                 }
03479         }
03480 }
03481 
03482 // +=================================================+
03483 // |        LLWearableBridge                         |
03484 // +=================================================+
03485 
03486 // *NOTE: hack to get from avatar inventory to avatar
03487 void wear_inventory_item_on_avatar( LLInventoryItem* item )
03488 {
03489         if(item)
03490         {
03491                 lldebugs << "wear_inventory_item_on_avatar( " << item->getName()
03492                                  << " )" << llendl;
03493                         
03494                 gWearableList.getAsset(item->getAssetUUID(),
03495                                                            item->getName(),
03496                                                            item->getType(),
03497                                                            LLWearableBridge::onWearOnAvatarArrived,
03498                                                            new LLUUID(item->getUUID()));
03499         }
03500 }
03501 
03502 struct LLFoundData
03503 {
03504         LLFoundData(const LLUUID& item_id,
03505                                 const LLUUID& asset_id,
03506                                 const LLString& name,
03507                                 LLAssetType::EType asset_type) :
03508                 mItemID(item_id),
03509                 mAssetID(asset_id),
03510                 mName(name),
03511                 mAssetType(asset_type),
03512                 mWearable( NULL ) {}
03513         
03514         LLUUID mItemID;
03515         LLUUID mAssetID;
03516         LLString mName;
03517         LLAssetType::EType mAssetType;
03518         LLWearable* mWearable;
03519 };
03520 
03521 struct LLWearableHoldingPattern
03522 {
03523         LLWearableHoldingPattern() : mResolved(0) {}
03524         ~LLWearableHoldingPattern()
03525         {
03526                 for_each(mFoundList.begin(), mFoundList.end(), DeletePointer());
03527                 mFoundList.clear();
03528         }
03529         typedef std::list<LLFoundData*> found_list_t;
03530         found_list_t mFoundList;
03531         S32 mResolved;
03532 };
03533 
03534 
03535 class LLOutfitObserver : public LLInventoryFetchObserver
03536 {
03537 public:
03538         LLOutfitObserver(const LLUUID& cat_id, bool copy_items, bool append) :
03539                 mCatID(cat_id),
03540                 mCopyItems(copy_items),
03541                 mAppend(append)
03542         {}
03543         ~LLOutfitObserver() {}
03544         virtual void done(); //public
03545 
03546 protected:
03547         LLUUID mCatID;
03548         bool mCopyItems;
03549         bool mAppend;
03550 };
03551 
03552 class LLWearInventoryCategoryCallback : public LLInventoryCallback
03553 {
03554 public:
03555         LLWearInventoryCategoryCallback(const LLUUID& cat_id, bool append)
03556         {
03557                 mCatID = cat_id;
03558                 mAppend = append;
03559         }
03560         void fire(const LLUUID& item_id)
03561         {
03562                 /*
03563                  * Do nothing.  We only care about the destructor
03564                  *
03565                  * The reason for this is that this callback is used in a hack where the
03566                  * same callback is given to dozens of items, and the destructor is called
03567                  * after the last item has fired the event and dereferenced it -- if all
03568                  * the events actually fire!
03569                  */
03570         }
03571 
03572 protected:
03573         ~LLWearInventoryCategoryCallback()
03574         {
03575                 // Is the destructor called by ordinary dereference, or because the app's shutting down?
03576                 // If the inventory callback manager goes away, we're shutting down, no longer want the callback.
03577                 if( LLInventoryCallbackManager::is_instantiated() )
03578                 {
03579                         wear_inventory_category_on_avatar(gInventory.getCategory(mCatID), mAppend);
03580                 }
03581                 else
03582                 {
03583                         llwarns << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl;
03584                 }
03585         }
03586 
03587 private:
03588         LLUUID mCatID;
03589         bool mAppend;
03590 };
03591 
03592 void LLOutfitObserver::done()
03593 {
03594         // We now have an outfit ready to be copied to agent inventory. Do
03595         // it, and wear that outfit normally.
03596         if(mCopyItems)
03597         {
03598                 LLInventoryCategory* cat = gInventory.getCategory(mCatID);
03599                 LLString name;
03600                 if(!cat)
03601                 {
03602                         // should never happen.
03603                         name = "New Outfit";
03604                 }
03605                 else
03606                 {
03607                         name = cat->getName();
03608                 }
03609                 LLViewerInventoryItem* item = NULL;
03610                 item_ref_t::iterator it = mComplete.begin();
03611                 item_ref_t::iterator end = mComplete.end();
03612                 LLUUID pid;
03613                 for(; it < end; ++it)
03614                 {
03615                         item = (LLViewerInventoryItem*)gInventory.getItem(*it);
03616                         if(item)
03617                         {
03618                                 if(LLInventoryType::IT_GESTURE == item->getInventoryType())
03619                                 {
03620                                         pid = gInventory.findCategoryUUIDForType(LLAssetType::AT_GESTURE);
03621                                 }
03622                                 else
03623                                 {
03624                                         pid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
03625                                 }
03626                                 break;
03627                         }
03628                 }
03629                 if(pid.isNull())
03630                 {
03631                         pid = gAgent.getInventoryRootID();
03632                 }
03633                 
03634                 LLUUID cat_id = gInventory.createNewCategory(
03635                         pid,
03636                         LLAssetType::AT_NONE,
03637                         name);
03638                 mCatID = cat_id;
03639                 LLPointer<LLInventoryCallback> cb = new LLWearInventoryCategoryCallback(mCatID, mAppend);
03640                 it = mComplete.begin();
03641                 for(; it < end; ++it)
03642                 {
03643                         item = (LLViewerInventoryItem*)gInventory.getItem(*it);
03644                         if(item)
03645                         {
03646                                 copy_inventory_item(
03647                                         gAgent.getID(),
03648                                         item->getPermissions().getOwner(),
03649                                         item->getUUID(),
03650                                         cat_id,
03651                                         std::string(),
03652                                         cb);
03653                         }
03654                 }
03655         }
03656         else
03657         {
03658                 // Wear the inventory category.
03659                 wear_inventory_category_on_avatar(gInventory.getCategory(mCatID), mAppend);
03660         }
03661 }
03662 
03663 class LLOutfitFetch : public LLInventoryFetchDescendentsObserver
03664 {
03665 public:
03666         LLOutfitFetch(bool copy_items, bool append) : mCopyItems(copy_items), mAppend(append) {}
03667         ~LLOutfitFetch() {}
03668         virtual void done();
03669 protected:
03670         bool mCopyItems;
03671         bool mAppend;
03672 };
03673 
03674 void LLOutfitFetch::done()
03675 {
03676         // What we do here is get the complete information on the items in
03677         // the library, and set up an observer that will wait for that to
03678         // happen.
03679         LLInventoryModel::cat_array_t cat_array;
03680         LLInventoryModel::item_array_t item_array;
03681         gInventory.collectDescendents(mCompleteFolders.front(),
03682                                                                   cat_array,
03683                                                                   item_array,
03684                                                                   LLInventoryModel::EXCLUDE_TRASH);
03685         S32 count = item_array.count();
03686         if(!count)
03687         {
03688                 llwarns << "Nothing fetched in category " << mCompleteFolders.front()
03689                                 << llendl;
03690                 dec_busy_count();
03691                 gInventory.removeObserver(this);
03692                 delete this;
03693                 return;
03694         }
03695 
03696         LLOutfitObserver* outfit;
03697         outfit = new LLOutfitObserver(mCompleteFolders.front(), mCopyItems, mAppend);
03698         LLInventoryFetchObserver::item_ref_t ids;
03699         for(S32 i = 0; i < count; ++i)
03700         {
03701                 ids.push_back(item_array.get(i)->getUUID());
03702         }
03703 
03704         // clean up, and remove this as an observer since the call to the
03705         // outfit could notify observers and throw us into an infinite
03706         // loop.
03707         dec_busy_count();
03708         gInventory.removeObserver(this);
03709         delete this;
03710 
03711         // increment busy count and either tell the inventory to check &
03712         // call done, or add this object to the inventory for observation.
03713         inc_busy_count();
03714 
03715         // do the fetch
03716         outfit->fetchItems(ids);
03717         if(outfit->isEverythingComplete())
03718         {
03719                 // everything is already here - call done.
03720                 outfit->done();
03721         }
03722         else
03723         {
03724                 // it's all on it's way - add an observer, and the inventory
03725                 // will call done for us when everything is here.
03726                 gInventory.addObserver(outfit);
03727         }
03728 }
03729 
03730 void wear_outfit_by_name(const char* name)
03731 {
03732         llinfos << "Wearing category " << name << llendl;
03733         inc_busy_count();
03734 
03735         LLInventoryModel::cat_array_t cat_array;
03736         LLInventoryModel::item_array_t item_array;
03737         LLNameCategoryCollector has_name(name);
03738         gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
03739                                                                         cat_array,
03740                                                                         item_array,
03741                                                                         LLInventoryModel::EXCLUDE_TRASH,
03742                                                                         has_name);
03743         bool copy_items = false;
03744         LLInventoryCategory* cat = NULL;
03745         if (cat_array.count() > 0)
03746         {
03747                 // Just wear the first one that matches
03748                 cat = cat_array.get(0);
03749         }
03750         else
03751         {
03752                 gInventory.collectDescendentsIf(LLUUID::null,
03753                                                                                 cat_array,
03754                                                                                 item_array,
03755                                                                                 LLInventoryModel::EXCLUDE_TRASH,
03756                                                                                 has_name);
03757                 if(cat_array.count() > 0)
03758                 {
03759                         cat = cat_array.get(0);
03760                         copy_items = true;
03761                 }
03762         }
03763 
03764         if(cat)
03765         {
03766                 wear_inventory_category(cat, copy_items, false);
03767         }
03768         else
03769         {
03770                 llwarns << "Couldn't find outfit " <<name<< " in wear_outfit_by_name()"
03771                                 << llendl;
03772         }
03773 
03774         dec_busy_count();
03775 }
03776 
03777 void wear_inventory_category(LLInventoryCategory* category, bool copy, bool append)
03778 {
03779         if(!category) return;
03780 
03781         lldebugs << "wear_inventory_category( " << category->getName()
03782                          << " )" << llendl;
03783         // What we do here is get the complete information on the items in
03784         // the inventory, and set up an observer that will wait for that to
03785         // happen.
03786         LLOutfitFetch* outfit;
03787         outfit = new LLOutfitFetch(copy, append);
03788         LLInventoryFetchDescendentsObserver::folder_ref_t folders;
03789         folders.push_back(category->getUUID());
03790         outfit->fetchDescendents(folders);
03791         inc_busy_count();
03792         if(outfit->isEverythingComplete())
03793         {
03794                 // everything is already here - call done.
03795                 outfit->done();
03796         }
03797         else
03798         {
03799                 // it's all on it's way - add an observer, and the inventory
03800                 // will call done for us when everything is here.
03801                 gInventory.addObserver(outfit);
03802         }
03803 }
03804 
03805 // *NOTE: hack to get from avatar inventory to avatar
03806 void wear_inventory_category_on_avatar( LLInventoryCategory* category, BOOL append )
03807 {
03808         // Avoid unintentionally overwriting old wearables.  We have to do
03809         // this up front to avoid having to deal with the case of multiple
03810         // wearables being dirty.
03811         if(!category) return;
03812         lldebugs << "wear_inventory_category_on_avatar( " << category->getName()
03813                          << " )" << llendl;
03814                                 
03815         LLWearInfo* userdata = new LLWearInfo;
03816         userdata->mAppend = append;
03817         userdata->mCategoryID = category->getUUID();
03818 
03819         if( gFloaterCustomize )
03820         {
03821                 gFloaterCustomize->askToSaveAllIfDirty(
03822                         wear_inventory_category_on_avatar_step2,
03823                         userdata);
03824         }
03825         else
03826         {
03827                 wear_inventory_category_on_avatar_step2(
03828                         TRUE,
03829                         userdata );
03830         }
03831 }
03832 
03833 
03834 void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata )
03835 {
03836         LLWearInfo* wear_info = (LLWearInfo*)userdata;
03837         if (!wear_info) return;
03838 
03839         // Find all the wearables that are in the category's subtree.   
03840         lldebugs << "wear_inventory_category_on_avatar_step2()" << llendl;
03841         if(proceed)
03842         {
03843                 LLInventoryModel::cat_array_t cat_array;
03844                 LLInventoryModel::item_array_t item_array;
03845                 LLFindWearables is_wearable;
03846                 gInventory.collectDescendentsIf(wear_info->mCategoryID,
03847                                                                                 cat_array,
03848                                                                                 item_array,
03849                                                                                 LLInventoryModel::EXCLUDE_TRASH,
03850                                                                                 is_wearable);
03851                 S32 i;
03852                 S32 wearable_count = item_array.count();
03853 
03854                 LLInventoryModel::cat_array_t   obj_cat_array;
03855                 LLInventoryModel::item_array_t  obj_item_array;
03856                 LLIsType is_object( LLAssetType::AT_OBJECT );
03857                 gInventory.collectDescendentsIf(wear_info->mCategoryID,
03858                                                                                 obj_cat_array,
03859                                                                                 obj_item_array,
03860                                                                                 LLInventoryModel::EXCLUDE_TRASH,
03861                                                                                 is_object);
03862                 S32 obj_count = obj_item_array.count();
03863 
03864                 // Find all gestures in this folder
03865                 LLInventoryModel::cat_array_t   gest_cat_array;
03866                 LLInventoryModel::item_array_t  gest_item_array;
03867                 LLIsType is_gesture( LLAssetType::AT_GESTURE );
03868                 gInventory.collectDescendentsIf(wear_info->mCategoryID,
03869                                                                                 gest_cat_array,
03870                                                                                 gest_item_array,
03871                                                                                 LLInventoryModel::EXCLUDE_TRASH,
03872                                                                                 is_gesture);
03873                 S32 gest_count = gest_item_array.count();
03874 
03875                 if( !wearable_count && !obj_count && !gest_count)
03876                 {
03877                         gViewerWindow->alertXml("CouldNotPutOnOutfit");
03878                         delete wear_info;
03879                         return;
03880                 }
03881 
03882                 // Processes that take time should show the busy cursor
03883                 if (wearable_count > 0 || obj_count > 0)
03884                 {
03885                         inc_busy_count();
03886                 }
03887 
03888                 // Activate all gestures in this folder
03889                 if (gest_count > 0)
03890                 {
03891                         llinfos << "Activating " << gest_count << " gestures" << llendl;
03892 
03893                         gGestureManager.activateGestures(gest_item_array);
03894 
03895                         // Update the inventory item labels to reflect the fact
03896                         // they are active.
03897                         LLViewerInventoryCategory* catp = gInventory.getCategory(wear_info->mCategoryID);
03898                         if (catp)
03899                         {
03900                                 gInventory.updateCategory(catp);
03901                                 gInventory.notifyObservers();
03902                         }
03903                 }
03904 
03905                 if(wearable_count > 0)
03906                 {
03907                         // Note: can't do normal iteration, because if all the
03908                         // wearables can be resolved immediately, then the
03909                         // callback will be called (and this object deleted)
03910                         // before the final getNextData().
03911                         LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
03912                         LLFoundData* found;
03913                         LLDynamicArray<LLFoundData*> found_container;
03914                         for(i = 0; i  < wearable_count; ++i)
03915                         {
03916                                 found = new LLFoundData(item_array.get(i)->getUUID(),
03917                                                                                 item_array.get(i)->getAssetUUID(),
03918                                                                                 item_array.get(i)->getName(),
03919                                                                                 item_array.get(i)->getType());
03920                                 holder->mFoundList.push_front(found);
03921                                 found_container.put(found);
03922                         }
03923                         for(i = 0; i < wearable_count; ++i)
03924                         {
03925                                 gAddToOutfit = wear_info->mAppend;
03926 
03927                                 found = found_container.get(i);
03928                                 gWearableList.getAsset(found->mAssetID,
03929                                                                                 found->mName,
03930                                                                            found->mAssetType,
03931                                                                            wear_inventory_category_on_avatar_loop,
03932                                                                            (void*)holder);
03933                         }
03934                 }
03935 
03936 
03937                 //If not appending and the folder doesn't contain only gestures, take off all attachments.
03938                 if (!wear_info->mAppend 
03939                         && !(wearable_count == 0 && obj_count == 0 && gest_count > 0) )
03940                 {
03941                         LLAgent::userRemoveAllAttachments(NULL);
03942                 }
03943 
03944                 if( obj_count > 0 )
03945                 {
03946                         // We've found some attachements.  Add these.
03947 
03948                         LLVOAvatar* avatar = gAgent.getAvatarObject();
03949                         if( avatar )
03950                         {
03951                                 // Build a compound message to send all the objects that need to be rezzed.
03952 
03953                                 // Limit number of packets to send
03954                                 const S32 MAX_PACKETS_TO_SEND = 10;
03955                                 const S32 OBJECTS_PER_PACKET = 4;
03956                                 const S32 MAX_OBJECTS_TO_SEND = MAX_PACKETS_TO_SEND * OBJECTS_PER_PACKET;
03957                                 if( obj_count > MAX_OBJECTS_TO_SEND )
03958                                 {
03959                                         obj_count = MAX_OBJECTS_TO_SEND;
03960                                 }
03961                                 
03962                                 // Create an id to keep the parts of the compound message together
03963                                 LLUUID compound_msg_id;
03964                                 compound_msg_id.generate();
03965                                 LLMessageSystem* msg = gMessageSystem;
03966 
03967                                 for(i = 0; i < obj_count; ++i)
03968                                 {
03969                                         if( 0 == (i % OBJECTS_PER_PACKET) )
03970                                         {
03971                                                 // Start a new message chunk
03972                                                 msg->newMessageFast(_PREHASH_RezMultipleAttachmentsFromInv);
03973                                                 msg->nextBlockFast(_PREHASH_AgentData);
03974                                                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
03975                                                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03976                                                 msg->nextBlockFast(_PREHASH_HeaderData);
03977                                                 msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id );
03978                                                 msg->addU8Fast(_PREHASH_TotalObjects, obj_count );
03979                                                 msg->addBOOLFast(_PREHASH_FirstDetachAll, !wear_info->mAppend );
03980                                         }
03981 
03982                                         LLInventoryItem* item = obj_item_array.get(i);
03983                                         msg->nextBlockFast(_PREHASH_ObjectData );
03984                                         msg->addUUIDFast(_PREHASH_ItemID, item->getUUID() );
03985                                         msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner());
03986                                         msg->addU8Fast(_PREHASH_AttachmentPt, 0 );      // Wear at the previous or default attachment point
03987                                         pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
03988                                         msg->addStringFast(_PREHASH_Name, item->getName());
03989                                         msg->addStringFast(_PREHASH_Description, item->getDescription());
03990 
03991                                         if( (i+1 == obj_count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) )
03992                                         {
03993                                                 // End of message chunk
03994                                                 msg->sendReliable( gAgent.getRegion()->getHost() );
03995                                         }
03996                                 }
03997                         }
03998                 }
03999         }
04000         delete wear_info;
04001         wear_info = NULL;
04002 }
04003 
04004 void wear_inventory_category_on_avatar_loop(LLWearable* wearable, void* data)
04005 {
04006         LLWearableHoldingPattern* holder = (LLWearableHoldingPattern*)data;
04007         BOOL append= gAddToOutfit;
04008         
04009         if(wearable)
04010         {
04011                 for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
04012                          iter != holder->mFoundList.end(); ++iter)
04013                 {
04014                         LLFoundData* data = *iter;
04015                         if(wearable->getID() == data->mAssetID)
04016                         {
04017                                 data->mWearable = wearable;
04018                                 break;
04019                         }
04020                 }
04021         }
04022         holder->mResolved += 1;
04023         if(holder->mResolved >= (S32)holder->mFoundList.size())
04024         {
04025                 wear_inventory_category_on_avatar_step3(holder, append);
04026         }
04027 }
04028 
04029 void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, BOOL append)
04030 {
04031         lldebugs << "wear_inventory_category_on_avatar_step3()" << llendl;
04032         LLInventoryItem::item_array_t items;
04033         LLDynamicArray< LLWearable* > wearables;
04034 
04035         // For each wearable type, find the first instance in the category
04036         // that we recursed through.
04037         for( S32 i = 0; i < WT_COUNT; i++ )
04038         {
04039                 for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
04040                          iter != holder->mFoundList.end(); ++iter)
04041                 {
04042                         LLFoundData* data = *iter;
04043                         LLWearable* wearable = data->mWearable;
04044                         if( wearable && ((S32)wearable->getType() == i) )
04045                         {
04046                                 LLViewerInventoryItem* item;
04047                                 item = (LLViewerInventoryItem*)gInventory.getItem(data->mItemID);
04048                                 if( item && (item->getAssetUUID() == wearable->getID()) )
04049                                 {
04050                                 //RN: after discussing with Brashears, I disabled this code
04051                                 //Metadata should reside in the item, not the asset
04052                                 //And this code does not handle failed asset uploads properly
04053 //                                      if(!wearable->isMatchedToInventoryItem(item ))
04054 //                                      {
04055 //                                              wearable = gWearableList.createWearableMatchedToInventoryItem( wearable, item );
04056 //                                              // Now that we have an asset that matches the
04057 //                                              // item, update the item to point to the new
04058 //                                              // asset.
04059 //                                              item->setAssetUUID(wearable->getID());
04060 //                                              item->updateAssetOnServer();
04061 //                                      }
04062                                         items.put(item);
04063                                         wearables.put(wearable);
04064                                 }
04065                                 break;
04066                         }
04067                 }
04068         }
04069 
04070         if(wearables.count() > 0)
04071         {
04072                 gAgent.setWearableOutfit(items, wearables, !append);
04073                 gInventory.notifyObservers();
04074         }
04075 
04076         delete holder;
04077 
04078         dec_busy_count();
04079 }
04080 
04081 void remove_inventory_category_from_avatar( LLInventoryCategory* category )
04082 {
04083         if(!category) return;
04084         lldebugs << "remove_inventory_category_from_avatar( " << category->getName()
04085                          << " )" << llendl;
04086                          
04087         
04088         LLUUID* uuid    = new LLUUID(category->getUUID());
04089 
04090         if( gFloaterCustomize )
04091         {
04092                 gFloaterCustomize->askToSaveAllIfDirty(
04093                         remove_inventory_category_from_avatar_step2,
04094                         uuid);
04095         }
04096         else
04097         {
04098                 remove_inventory_category_from_avatar_step2(
04099                         TRUE,
04100                         uuid );
04101         }
04102 }
04103 
04104 
04105 void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata)
04106 {
04107 
04108         // Find all the wearables that are in the category's subtree.
04109         LLUUID* category_id = (LLUUID *)userdata;
04110         
04111         lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl;
04112         if(proceed)
04113         {
04114                 LLInventoryModel::cat_array_t cat_array;
04115                 LLInventoryModel::item_array_t item_array;
04116                 LLFindWearables is_wearable;
04117                 gInventory.collectDescendentsIf(*category_id,
04118                                                                                 cat_array,
04119                                                                                 item_array,
04120                                                                                 LLInventoryModel::EXCLUDE_TRASH,
04121                                                                                 is_wearable);
04122                 S32 i;
04123                 S32 wearable_count = item_array.count();
04124 
04125                 LLInventoryModel::cat_array_t   obj_cat_array;
04126                 LLInventoryModel::item_array_t  obj_item_array;
04127                 LLIsType is_object( LLAssetType::AT_OBJECT );
04128                 gInventory.collectDescendentsIf(*category_id,
04129                                                                                 obj_cat_array,
04130                                                                                 obj_item_array,
04131                                                                                 LLInventoryModel::EXCLUDE_TRASH,
04132                                                                                 is_object);
04133                 S32 obj_count = obj_item_array.count();
04134 
04135                 // Find all gestures in this folder
04136                 LLInventoryModel::cat_array_t   gest_cat_array;
04137                 LLInventoryModel::item_array_t  gest_item_array;
04138                 LLIsType is_gesture( LLAssetType::AT_GESTURE );
04139                 gInventory.collectDescendentsIf(*category_id,
04140                                                                                 gest_cat_array,
04141                                                                                 gest_item_array,
04142                                                                                 LLInventoryModel::EXCLUDE_TRASH,
04143                                                                                 is_gesture);
04144                 S32 gest_count = gest_item_array.count();
04145 
04146                 if (wearable_count > 0) //Loop through wearables.  If worn, remove.
04147                 {
04148                         for(i = 0; i  < wearable_count; ++i)
04149                         {
04150                                 if( gAgent.isWearingItem (item_array.get(i)->getUUID()) )
04151                                 {
04152                                         gWearableList.getAsset(item_array.get(i)->getAssetUUID(),
04153                                                                         item_array.get(i)->getName(),
04154                                                                    item_array.get(i)->getType(),
04155                                                                     LLWearableBridge::onRemoveFromAvatarArrived,
04156                                                                    new LLUUID(item_array.get(i)->getUUID()));
04157 
04158                                 }
04159                         }
04160                 }
04161                 
04162                 
04163                 if (obj_count > 0)
04164                 {
04165                         for(i = 0; i  < obj_count; ++i)
04166                         {
04167                                 gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
04168                                 gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
04169                                 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
04170                                 gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item_array.get(i)->getUUID() );
04171 
04172                                 gMessageSystem->sendReliable( gAgent.getRegion()->getHost() );
04173 
04174                                 // this object might have been selected, so let the selection manager know it's gone now
04175                                 LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID());
04176                                 if (found_obj)
04177                                 {
04178                                         LLSelectMgr::getInstance()->remove(found_obj);
04179                                 }
04180                                 else
04181                                 {
04182                                         llwarns << "object not found, ignoring" << llendl;
04183                                 }
04184                         }
04185                 }
04186 
04187                 if (gest_count > 0)
04188                 {
04189                         for(i = 0; i  < gest_count; ++i)
04190                         {
04191                                 if ( gGestureManager.isGestureActive( gest_item_array.get(i)->getUUID()) )
04192                                 {
04193                                         gGestureManager.deactivateGesture( gest_item_array.get(i)->getUUID() );
04194                                         gInventory.updateItem( gest_item_array.get(i) );
04195                                         gInventory.notifyObservers();
04196                                 }
04197 
04198                         }
04199                 }
04200         }
04201         delete category_id;
04202         category_id = NULL;
04203 }
04204 
04205 BOOL LLWearableBridge::renameItem(const LLString& new_name)
04206 {
04207         if( gAgent.isWearingItem( mUUID ) )
04208         {
04209                 gAgent.setWearableName( mUUID, new_name );
04210         }
04211         return LLItemBridge::renameItem(new_name);
04212 }
04213 
04214 BOOL LLWearableBridge::isItemRemovable()
04215 {
04216         if(gAgent.isWearingItem(mUUID)) return FALSE;
04217         return LLInvFVBridge::isItemRemovable();
04218 }
04219 
04220 LLFontGL::StyleFlags LLWearableBridge::getLabelStyle() const
04221 { 
04222         if( gAgent.isWearingItem( mUUID ) )
04223         {
04224                 // llinfos << "BOLD" << llendl;
04225                 return LLFontGL::BOLD;
04226         }
04227         else
04228         {
04229                 return LLFontGL::NORMAL;
04230         }
04231 }
04232 
04233 LLString LLWearableBridge::getLabelSuffix() const
04234 {
04235         if( gAgent.isWearingItem( mUUID ) )
04236         {
04237                 return LLItemBridge::getLabelSuffix() + " (worn)";
04238         }
04239         else
04240         {
04241                 return LLItemBridge::getLabelSuffix();
04242         }
04243 }
04244 
04245 LLUIImagePtr LLWearableBridge::getIcon() const
04246 {
04247         return get_item_icon(mAssetType, mInvType, mWearableType, FALSE);
04248 }
04249 
04250 // virtual
04251 void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* model, LLString action)
04252 {
04253         if ("wear" == action)
04254         {
04255                 wearOnAvatar();
04256         }
04257         else if ("edit" == action)
04258         {
04259                 editOnAvatar();
04260                 return;
04261         }
04262         else if ("take_off" == action)
04263         {
04264                 if(gAgent.isWearingItem(mUUID))
04265                 {
04266                         LLViewerInventoryItem* item = getItem();
04267                         if (item)
04268                         {
04269                                 gWearableList.getAsset(item->getAssetUUID(),
04270                                                                                 item->getName(),
04271                                                                         item->getType(),
04272                                                                         LLWearableBridge::onRemoveFromAvatarArrived,
04273                                                                         new LLUUID(mUUID));
04274                         }
04275                 }
04276         }
04277         else LLItemBridge::performAction(folder, model, action);
04278 }
04279 
04280 void LLWearableBridge::openItem()
04281 {
04282         if( isInTrash() )
04283         {
04284                 gViewerWindow->alertXml("CannotWearTrash");
04285         }
04286         else if(isAgentInventory())
04287         {
04288                 if( !gAgent.isWearingItem( mUUID ) )
04289                 {
04290                         wearOnAvatar();
04291                 }
04292         }
04293         else
04294         {
04295                 // must be in the inventory library. copy it to our inventory
04296                 // and put it on right away.
04297                 LLViewerInventoryItem* item = getItem();
04298                 if(item && item->isComplete())
04299                 {
04300                         LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
04301                         copy_inventory_item(
04302                                 gAgent.getID(),
04303                                 item->getPermissions().getOwner(),
04304                                 item->getUUID(),
04305                                 LLUUID::null,
04306                                 std::string(),
04307                                 cb);
04308                 }
04309                 else if(item)
04310                 {
04311                         // *TODO: We should fetch the item details, and then do
04312                         // the operation above.
04313                         gViewerWindow->alertXml("CannotWearInfoNotComplete");
04314                 }
04315         }
04316 }
04317 
04318 void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
04319 {
04320         lldebugs << "LLWearableBridge::buildContextMenu()" << llendl;
04321         std::vector<LLString> items;
04322         std::vector<LLString> disabled_items;
04323         if(isInTrash())
04324         {
04325                 items.push_back("Purge Item");
04326                 if (!isItemRemovable())
04327                 {
04328                         disabled_items.push_back("Purge Item");
04329                 }
04330 
04331                 items.push_back("Restore Item");
04332         }
04333         else
04334         {       // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere
04335                 BOOL no_open = ((flags & SUPPRESS_OPEN_ITEM) == SUPPRESS_OPEN_ITEM);
04336 
04337                 // If we have clothing, don't add "Open" as it's the same action as "Wear"   SL-18976
04338                 LLViewerInventoryItem* item = getItem();
04339                 if( !no_open && item )
04340                 {
04341                         no_open = (item->getType() == LLAssetType::AT_CLOTHING) ||
04342                                           (item->getType() == LLAssetType::AT_BODYPART);
04343                 }
04344                 if (!no_open)
04345                 {
04346                         items.push_back("Open");
04347                 }
04348 
04349                 items.push_back("Properties");
04350 
04351                 getClipboardEntries(true, items, disabled_items, flags);
04352 
04353                 items.push_back("Wearable Separator");
04354                 
04355                 items.push_back("Wearable Wear");
04356                 items.push_back("Wearable Edit");
04357 
04358 
04359                 if ((flags & FIRST_SELECTED_ITEM) == 0)
04360                 {
04361                         disabled_items.push_back("Wearable Edit");
04362                 }
04363                 //menu.appendSeparator();
04364                 //menu.append(new LLMenuItemCallGL("Wear",
04365                 //                                                               LLWearableBridge::onWearOnAvatar,
04366                 //                                                               LLWearableBridge::canWearOnAvatar,
04367                 //                                                               (void*)this));
04368                 //menu.append(new LLMenuItemCallGL("Edit",
04369                 //                                                               LLWearableBridge::onEditOnAvatar,
04370                 //                                                               LLWearableBridge::canEditOnAvatar,
04371                 //                                                               (void*)this));
04372 
04373                 if( item && (item->getType() == LLAssetType::AT_CLOTHING) )
04374                 {
04375                         items.push_back("Take Off");
04376                         /*menu.append(new LLMenuItemCallGL("Take Off",
04377                                                                                          LLWearableBridge::onRemoveFromAvatar,
04378                                                                                          LLWearableBridge::canRemoveFromAvatar,
04379                                                                                          (void*)this));*/
04380                 }
04381         }
04382         hideContextEntries(menu, items, disabled_items);
04383 }
04384 
04385 // Called from menus
04386 // static
04387 BOOL LLWearableBridge::canWearOnAvatar(void* user_data)
04388 {
04389         LLWearableBridge* self = (LLWearableBridge*)user_data;
04390         if(!self) return FALSE;
04391         if(!self->isAgentInventory())
04392         {
04393                 LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem();
04394                 if(!item || !item->isComplete()) return FALSE;
04395         }
04396         return (!gAgent.isWearingItem(self->mUUID));
04397 }
04398 
04399 // Called from menus
04400 // static
04401 void LLWearableBridge::onWearOnAvatar(void* user_data)
04402 {
04403         LLWearableBridge* self = (LLWearableBridge*)user_data;
04404         if(!self) return;
04405         self->wearOnAvatar();
04406 }
04407 
04408 void LLWearableBridge::wearOnAvatar()
04409 {
04410         // Don't wear anything until initial wearables are loaded, can
04411         // destroy clothing items.
04412         if (!gAgent.areWearablesLoaded()) 
04413         {
04414                 gViewerWindow->alertXml("CanNotChangeAppearanceUntilLoaded");
04415                 return;
04416         }
04417 
04418         LLViewerInventoryItem* item = getItem();
04419         if(item)
04420         {
04421                 if(!isAgentInventory())
04422                 {
04423                         LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
04424                         copy_inventory_item(
04425                                 gAgent.getID(),
04426                                 item->getPermissions().getOwner(),
04427                                 item->getUUID(),
04428                                 LLUUID::null,
04429                                 std::string(),
04430                                 cb);
04431                 }
04432                 else
04433                 {
04434                         wear_inventory_item_on_avatar(item);
04435                 }
04436         }
04437 }
04438 
04439 // static
04440 void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata )
04441 {
04442         LLUUID* item_id = (LLUUID*) userdata;
04443         if(wearable)
04444         {
04445                 LLViewerInventoryItem* item = NULL;
04446                 item = (LLViewerInventoryItem*)gInventory.getItem(*item_id);
04447                 if(item)
04448                 {
04449                         if(item->getAssetUUID() == wearable->getID())
04450                         {
04451                                 //RN: after discussing with Brashears, I disabled this code
04452                                 //Metadata should reside in the item, not the asset
04453                                 //And this code does not handle failed asset uploads properly
04454 
04455 //                              if(!wearable->isMatchedToInventoryItem(item))
04456 //                              {
04457 //                                      LLWearable* new_wearable = gWearableList.createWearableMatchedToInventoryItem( wearable, item );
04458 //
04459 //                                      // Now that we have an asset that matches the
04460 //                                      // item, update the item to point to the new
04461 //                                      // asset.
04462 //                                      item->setAssetUUID(new_wearable->getID());
04463 //                                      item->updateAssetOnServer();
04464 //                                      wearable = new_wearable;
04465 //                              }
04466                                 gAgent.setWearable(item, wearable);
04467                                 gInventory.notifyObservers();
04468                                 //self->getFolderItem()->refreshFromRoot();
04469                         }
04470                         else
04471                         {
04472                                 llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl;
04473                         }
04474                 }
04475         }
04476         delete item_id;
04477 }
04478 
04479 // static
04480 BOOL LLWearableBridge::canEditOnAvatar(void* user_data)
04481 {
04482         LLWearableBridge* self = (LLWearableBridge*)user_data;
04483         if(!self) return FALSE;
04484 
04485         return (gAgent.isWearingItem(self->mUUID));
04486 }
04487 
04488 // static 
04489 void LLWearableBridge::onEditOnAvatar(void* user_data)
04490 {
04491         LLWearableBridge* self = (LLWearableBridge*)user_data;
04492         if(self)
04493         {
04494                 self->editOnAvatar();
04495         }
04496 }
04497 
04498 void LLWearableBridge::editOnAvatar()
04499 {
04500         LLWearable* wearable = gAgent.getWearableFromWearableItem(mUUID);
04501         if( wearable )
04502         {
04503                 // Set the tab to the right wearable.
04504                 LLFloaterCustomize::setCurrentWearableType( wearable->getType() );
04505 
04506                 if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() )
04507                 {
04508                         // Start Avatar Customization
04509                         gAgent.changeCameraToCustomizeAvatar();
04510                 }
04511         }
04512 }
04513 
04514 // static
04515 BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data)
04516 {
04517         LLWearableBridge* self = (LLWearableBridge*)user_data;
04518         if( self && (LLAssetType::AT_BODYPART != self->mAssetType) )
04519         {
04520                 return gAgent.isWearingItem( self->mUUID );
04521         }
04522         return FALSE;
04523 }
04524 
04525 // static 
04526 void LLWearableBridge::onRemoveFromAvatar(void* user_data)
04527 {
04528         LLWearableBridge* self = (LLWearableBridge*)user_data;
04529         if(!self) return;
04530         if(gAgent.isWearingItem(self->mUUID))
04531         {
04532                 LLViewerInventoryItem* item = self->getItem();
04533                 if (item)
04534                 {
04535                         gWearableList.getAsset(item->getAssetUUID(),
04536                                                                         item->getName(),
04537                                                                    item->getType(),
04538                                                                    onRemoveFromAvatarArrived,
04539                                                                    new LLUUID(self->mUUID));
04540                 }
04541         }
04542 }
04543 
04544 // static
04545 void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
04546                                                                                                  void* userdata)
04547 {
04548         LLUUID* item_id = (LLUUID*) userdata;
04549         if(wearable)
04550         {
04551                 if( gAgent.isWearingItem( *item_id ) )
04552                 {
04553                         EWearableType type = wearable->getType();
04554         
04555                         if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR ) ) //&&
04557                         {
04558                                 gAgent.removeWearable( type );
04559                         }
04560                 }
04561         }
04562         delete item_id;
04563 }

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