From de92d5ce329235847f9f77292b0072f99ce61f43 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Mon, 23 Nov 2009 17:57:25 +0000 Subject: re-upgrade to vivox v3 sdk here. --- indra/newview/viewer_manifest.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 4193343d64..4133315480 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -278,10 +278,12 @@ class WindowsManifest(ViewerManifest): # Vivox runtimes self.path("SLVoice.exe") - self.path("alut.dll") self.path("vivoxsdk.dll") self.path("ortp.dll") - self.path("wrap_oal.dll") + self.path("libsndfile-1.dll") + self.path("zlib1.dll") + self.path("vivoxplatform.dll") + self.path("vivoxoal.dll") # For google-perftools tcmalloc allocator. try: @@ -537,10 +539,11 @@ class DarwinManifest(ViewerManifest): self.path("zh-Hans.lproj") # SLVoice and vivox lols - self.path("vivox-runtime/universal-darwin/libalut.dylib", "libalut.dylib") - self.path("vivox-runtime/universal-darwin/libopenal.dylib", "libopenal.dylib") + self.path("vivox-runtime/universal-darwin/libsndfile.dylib", "libsndfile.dylib") + self.path("vivox-runtime/universal-darwin/libvivoxoal.dylib", "libvivoxoal.dylib") self.path("vivox-runtime/universal-darwin/libortp.dylib", "libortp.dylib") self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.dylib") + self.path("vivox-runtime/universal-darwin/libvivoxplatform.dylib", "libvivoxplatform.dylib") self.path("vivox-runtime/universal-darwin/SLVoice", "SLVoice") libdir = "../../libraries/universal-darwin/lib_release" @@ -839,7 +842,10 @@ class Linux_i686Manifest(LinuxManifest): self.end_prefix() if self.prefix(src="vivox-runtime/i686-linux", dst="lib"): self.path("libortp.so") + self.path("libsndfile.so.1") + self.path("libvivoxoal.so.1") self.path("libvivoxsdk.so") + self.path("libvivoxplatform.so") self.end_prefix("lib") class Linux_x86_64Manifest(LinuxManifest): -- cgit v1.2.3 From d159daa8d7766be78f890e2fdc2160413099970c Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 25 Nov 2009 11:31:03 -0500 Subject: For EXT-2584: Select and rename new folder when creating new outfit --HG-- branch : avatar-pipeline --- indra/newview/llinventorybridge.cpp | 2 ++ indra/newview/llpaneloutfitsinventory.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 9421cf5716..fedc45b1fb 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2385,6 +2385,8 @@ void LLFolderBridge::folderOptionsMenu() if (is_sidepanel) { mItems.clear(); + mItems.push_back("Rename"); + mItems.push_back("Delete"); } // Only enable calling-card related options for non-default folders. diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index 7769a7d172..aa0ab4efbc 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -65,10 +65,12 @@ public: // Otherwise, return NULL. LLFolderViewEventListener* getCorrectListenerForAction(); void setParent(LLSidepanelAppearance *parent); + + LLFolderView* getRootFolder(); + protected: void updateParent(); bool getIsCorrectType(const LLFolderViewEventListener *listenerp) const; - LLFolderView* getRootFolder(); private: LLSidepanelAppearance* mParent; -- cgit v1.2.3 From c60165a93c4ee13dafa1c6eadbe1d19fb2cdec17 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 25 Nov 2009 13:39:45 -0500 Subject: For EXT-2584: Select and rename new folder when creating new outfit --HG-- branch : avatar-pipeline --- indra/newview/llagentwearables.cpp | 42 +++++++++++++++++++++++-------- indra/newview/llpaneloutfitsinventory.cpp | 5 +--- 2 files changed, 33 insertions(+), 14 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 475f34dc2b..f0742876e2 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -49,6 +49,9 @@ #include "llgesturemgr.h" #include "llappearancemgr.h" #include "lltexlayer.h" +#include "llsidetray.h" +#include "llpaneloutfitsinventory.h" +#include "llfolderview.h" #include @@ -1295,6 +1298,33 @@ void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name, } } +class LLAutoRenameFolder: public LLInventoryCallback +{ +public: + LLAutoRenameFolder(LLUUID& folder_id): + mFolderID(folder_id) + { + } + + virtual ~LLAutoRenameFolder() + { + LLSD key; + LLSideTray::getInstance()->showPanel("panel_outfits_inventory", key); + LLPanelOutfitsInventory *outfit_panel = + dynamic_cast(LLSideTray::getInstance()->getPanel("panel_outfits_inventory")); + outfit_panel->getRootFolder()->clearSelection(); + outfit_panel->getRootFolder()->setSelectionByID(mFolderID, TRUE); + outfit_panel->getRootFolder()->setNeedsAutoRename(TRUE); + } + + virtual void fire(const LLUUID&) + { + } + +private: + LLUUID mFolderID; +}; + LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name) { if (mAvatarObject.isNull()) @@ -1309,17 +1339,9 @@ LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name) LLFolderType::FT_OUTFIT, new_folder_name); - LLAppearanceManager::instance().shallowCopyCategory(LLAppearanceManager::instance().getCOF(),folder_id, NULL); + LLPointer cb = new LLAutoRenameFolder(folder_id); + LLAppearanceManager::instance().shallowCopyCategory(LLAppearanceManager::instance().getCOF(),folder_id, cb); -#if 0 // BAP - fix to go into rename state automatically after outfit is created. - LLViewerInventoryCategory *parent_category = gInventory.getCategory(parent_id); - if (parent_category) - { - parent_category->setSelectionByID(folder_id,TRUE); - parent_category->setNeedsAutoRename(TRUE); - } -#endif - return folder_id; } diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 5af26c1ad9..951e74abf9 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -144,16 +144,13 @@ void LLPanelOutfitsInventory::onNew() { const std::string& outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT); LLUUID outfit_folder = gAgentWearables.makeNewOutfitLinks(outfit_name); - - getRootFolder()->setSelectionByID(outfit_folder, TRUE); - getRootFolder()->setNeedsAutoRename(TRUE); } void LLPanelOutfitsInventory::onSelectionChange(const std::deque &items, BOOL user_action) { updateListCommands(); updateParent(); - if (getRootFolder()->needsAutoRename()) + if (getRootFolder()->needsAutoRename() && items.size()) { getRootFolder()->startRenamingSelectedItem(); getRootFolder()->setNeedsAutoRename(FALSE); -- cgit v1.2.3 From 45e9a060b4244b93720c0c21bd35f17199fbafd1 Mon Sep 17 00:00:00 2001 From: Rick Pasetto Date: Wed, 25 Nov 2009 10:40:26 -0800 Subject: DEV-41422 Show Home button and make Stop button remain enabled in time-based media controls --- indra/newview/llpanelprimmediacontrols.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 71c1b0cbb9..0ca2f0025c 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -332,13 +332,12 @@ void LLPanelPrimMediaControls::updateShape() if(media_plugin && media_plugin->pluginSupportsMediaTime()) { - mReloadCtrl->setEnabled(FALSE); - mReloadCtrl->setVisible(FALSE); + mReloadCtrl->setEnabled(false); + mReloadCtrl->setVisible(false); mMediaStopCtrl->setVisible(has_focus); - mHomeCtrl->setVisible(FALSE); - // No nav controls - mBackCtrl->setVisible(FALSE); - mFwdCtrl->setEnabled(FALSE); + mHomeCtrl->setVisible(has_focus); + mBackCtrl->setVisible(false); + mFwdCtrl->setVisible(false); mMediaAddressCtrl->setVisible(false); mMediaAddressCtrl->setEnabled(false); mMediaPlaySliderPanel->setVisible(has_focus && !mini_controls); @@ -416,7 +415,6 @@ void LLPanelPrimMediaControls::updateShape() mPlayCtrl->setVisible(FALSE); mPauseCtrl->setEnabled(TRUE); mPauseCtrl->setVisible(has_focus); - mMediaStopCtrl->setEnabled(TRUE); break; case LLPluginClassMediaOwner::MEDIA_PAUSED: @@ -425,7 +423,6 @@ void LLPanelPrimMediaControls::updateShape() mPauseCtrl->setVisible(FALSE); mPlayCtrl->setEnabled(TRUE); mPlayCtrl->setVisible(has_focus); - mMediaStopCtrl->setEnabled(FALSE); break; } } -- cgit v1.2.3 From 43d52671c8c71af188456c200baba7c3bc8d4799 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Wed, 25 Nov 2009 13:59:23 -0500 Subject: EXT-2769 hair alpha not applied immediately Apparently none of the texture pickers were invalidating the baked textures causing selected textures to not appear on the avatar until you actually saved the wearable. This patch forces the composites to update when you change any texture or color (or invisibility flag). Code reviewed by Seraph --HG-- branch : avatar-pipeline --- indra/newview/llagentwearables.cpp | 6 +++--- indra/newview/llvoavatarself.cpp | 6 +++--- indra/newview/llvoavatarself.h | 2 +- indra/newview/llwearable.cpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 475f34dc2b..e2d0daa245 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -408,7 +408,7 @@ void LLAgentWearables::saveWearable(const EWearableType type, const U32 index, B return; } - gAgent.getAvatarObject()->wearableUpdated( type ); + gAgent.getAvatarObject()->wearableUpdated( type, TRUE ); if (send_update) { @@ -698,7 +698,7 @@ U32 LLAgentWearables::pushWearable(const EWearableType type, LLWearable *wearabl void LLAgentWearables::wearableUpdated(LLWearable *wearable) { - mAvatarObject->wearableUpdated(wearable->getType()); + mAvatarObject->wearableUpdated(wearable->getType(), TRUE); wearable->setLabelUpdated(); // Hack pt 2. If the wearable we just loaded has definition version 24, @@ -739,7 +739,7 @@ void LLAgentWearables::popWearable(const EWearableType type, U32 index) if (wearable) { mWearableDatas[type].erase(mWearableDatas[type].begin() + index); - mAvatarObject->wearableUpdated(wearable->getType()); + mAvatarObject->wearableUpdated(wearable->getType(), TRUE); wearable->setLabelUpdated(); } } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index f3e787ae7e..7d6401acde 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -918,9 +918,9 @@ void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode) //----------------------------------------------------------------------------- // updatedWearable( EWearableType type ) // forces an update to any baked textures relevant to type. -// Should be called only on saving the wearable +// will force an upload of the resulting bake if the second parameter is TRUE //----------------------------------------------------------------------------- -void LLVOAvatarSelf::wearableUpdated( EWearableType type ) +void LLVOAvatarSelf::wearableUpdated( EWearableType type, BOOL upload_result ) { for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); @@ -939,7 +939,7 @@ void LLVOAvatarSelf::wearableUpdated( EWearableType type ) { if (mBakedTextureDatas[index].mTexLayerSet) { - invalidateComposite(mBakedTextureDatas[index].mTexLayerSet, TRUE); + invalidateComposite(mBakedTextureDatas[index].mTexLayerSet, upload_result); } break; } diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index e376e5e9ef..6bf4ef5496 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -270,7 +270,7 @@ protected: public: /*virtual*/ BOOL isWearingWearableType(EWearableType type) const; - void wearableUpdated(EWearableType type); + void wearableUpdated(EWearableType type, BOOL upload_result); protected: U32 getNumWearables(LLVOAvatarDefines::ETextureIndex i) const; diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index d92da4ef44..050b218356 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -703,7 +703,7 @@ void LLWearable::removeFromAvatar( EWearableType type, BOOL upload_bake ) } avatar->updateVisualParams(); - avatar->wearableUpdated(type); + avatar->wearableUpdated(type, TRUE); // if( upload_bake ) // { -- cgit v1.2.3 From 751a9049822ab39f1762ab6758cc3ee0aabb4a4b Mon Sep 17 00:00:00 2001 From: Rick Pasetto Date: Wed, 25 Nov 2009 13:22:18 -0800 Subject: DEV-43046: Move media controls to the bottom of media - Tweaked the algorithm to shift controls down when zoomed in. - Adjusted some numbers in the XUI file - Moved some hard-coded constants into the XUI file so they can be data-driven --- indra/newview/llpanelprimmediacontrols.cpp | 33 +++++++++--------- indra/newview/llpanelprimmediacontrols.h | 5 +++ .../default/xui/en/panel_prim_media_controls.xml | 39 ++++++++++++---------- 3 files changed, 43 insertions(+), 34 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 0ca2f0025c..ceb37ae790 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -66,10 +66,6 @@ glh::matrix4f glh_get_current_modelview(); glh::matrix4f glh_get_current_projection(); -const F32 ZOOM_NEAR_PADDING = 1.0f; -const F32 ZOOM_MEDIUM_PADDING = 1.15f; -const F32 ZOOM_FAR_PADDING = 1.5f; - // Warning: make sure these two match! const LLPanelPrimMediaControls::EZoomLevel LLPanelPrimMediaControls::kZoomLevels[] = { ZOOM_NONE, ZOOM_MEDIUM }; const int LLPanelPrimMediaControls::kNumZoomLevels = 2; @@ -152,6 +148,11 @@ BOOL LLPanelPrimMediaControls::postBuild() mRightBookend = getChild("right_bookend"); mBackgroundImage = LLUI::getUIImage(getString("control_background_image_name")); LLStringUtil::convertToF32(getString("skip_step"), mSkipStep); + LLStringUtil::convertToS32(getString("min_width"), mMinWidth); + LLStringUtil::convertToS32(getString("min_height"), mMinHeight); + LLStringUtil::convertToF32(getString("zoom_near_padding"), mZoomNearPadding); + LLStringUtil::convertToF32(getString("zoom_medium_padding"), mZoomMediumPadding); + LLStringUtil::convertToF32(getString("zoom_far_padding"), mZoomFarPadding); // These are currently removed...but getChild creates a "dummy" widget. // This class handles them missing. @@ -257,9 +258,6 @@ LLPluginClassMedia* LLPanelPrimMediaControls::getTargetMediaPlugin() void LLPanelPrimMediaControls::updateShape() { - const S32 MIN_HUD_WIDTH=400; - const S32 MIN_HUD_HEIGHT=120; - LLViewerMediaImpl* media_impl = getTargetMediaImpl(); LLViewerObject* objectp = getTargetObject(); @@ -596,12 +594,12 @@ void LLPanelPrimMediaControls::updateShape() } LLCoordGL screen_min; - screen_min.mX = llround((F32)gViewerWindow->getWorldViewWidthRaw() * (min.mV[VX] + 1.f) * 0.5f); - screen_min.mY = llround((F32)gViewerWindow->getWorldViewHeightRaw() * (min.mV[VY] + 1.f) * 0.5f); + screen_min.mX = llround((F32)gViewerWindow->getWorldViewWidthScaled() * (min.mV[VX] + 1.f) * 0.5f); + screen_min.mY = llround((F32)gViewerWindow->getWorldViewHeightScaled() * (min.mV[VY] + 1.f) * 0.5f); LLCoordGL screen_max; - screen_max.mX = llround((F32)gViewerWindow->getWorldViewWidthRaw() * (max.mV[VX] + 1.f) * 0.5f); - screen_max.mY = llround((F32)gViewerWindow->getWorldViewHeightRaw() * (max.mV[VY] + 1.f) * 0.5f); + screen_max.mX = llround((F32)gViewerWindow->getWorldViewWidthScaled() * (max.mV[VX] + 1.f) * 0.5f); + screen_max.mY = llround((F32)gViewerWindow->getWorldViewHeightScaled() * (max.mV[VY] + 1.f) * 0.5f); // grow panel so that screenspace bounding box fits inside "media_region" element of HUD LLRect media_controls_rect; @@ -610,14 +608,15 @@ void LLPanelPrimMediaControls::updateShape() media_controls_rect.mBottom -= mMediaRegion->getRect().mBottom; media_controls_rect.mTop += getRect().getHeight() - mMediaRegion->getRect().mTop; media_controls_rect.mRight += getRect().getWidth() - mMediaRegion->getRect().mRight; - - LLRect old_hud_rect = media_controls_rect; + // keep all parts of HUD on-screen media_controls_rect.intersectWith(getParent()->getLocalRect()); + if (mCurrentZoom != ZOOM_NONE) + media_controls_rect.mBottom -= mMediaControlsStack->getRect().getHeight() + mMediaProgressPanel->getRect().getHeight(); // clamp to minimum size, keeping centered media_controls_rect.setCenterAndSize(media_controls_rect.getCenterX(), media_controls_rect.getCenterY(), - llmax(MIN_HUD_WIDTH, media_controls_rect.getWidth()), llmax(MIN_HUD_HEIGHT, media_controls_rect.getHeight())); + llmax(mMinWidth, media_controls_rect.getWidth()), llmax(mMinHeight, media_controls_rect.getHeight())); setShape(media_controls_rect, true); @@ -965,17 +964,17 @@ void LLPanelPrimMediaControls::updateZoom() } case ZOOM_FAR: { - zoom_padding = ZOOM_FAR_PADDING; + zoom_padding = mZoomFarPadding; break; } case ZOOM_MEDIUM: { - zoom_padding = ZOOM_MEDIUM_PADDING; + zoom_padding = mZoomMediumPadding; break; } case ZOOM_NEAR: { - zoom_padding = ZOOM_NEAR_PADDING; + zoom_padding = mZoomNearPadding; break; } default: diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h index accfb72a04..4bb05265c8 100644 --- a/indra/newview/llpanelprimmediacontrols.h +++ b/indra/newview/llpanelprimmediacontrols.h @@ -160,6 +160,11 @@ private: LLUICtrl *mRightBookend; LLUIImage* mBackgroundImage; F32 mSkipStep; + S32 mMinWidth; + S32 mMinHeight; + F32 mZoomNearPadding; + F32 mZoomMediumPadding; + F32 mZoomFarPadding; LLUICtrl *mMediaPanelScroll; LLButton *mScrollUpCtrl; diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml index af4c01185a..8b86067b03 100644 --- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml @@ -9,6 +9,11 @@ width="800"> Inspector_Background 0.2 + 400 + 120 + 1.0 + 1.25 + 1.5 user_resize="false" follows="left|right|top|bottom" layout="topleft" + height="16" min_width="100" width="200"> user_resize="false" /> name="media_progress_bar" color_bar="1 1 1 0.96" follows="left|right|top" + top="5" height="8" layout="topleft" left="0" -- cgit v1.2.3 From 9f84a348ca08dd0487b2a7dff13da905fd8e11bd Mon Sep 17 00:00:00 2001 From: Erica Date: Wed, 25 Nov 2009 14:30:16 -0800 Subject: EXT-2779 World map - clean up layout and simplify --- .../skins/default/textures/icon_event_adult.tga | Bin 648 -> 1006 bytes .../skins/default/textures/icon_top_pick.tga | Bin 858 -> 1068 bytes .../skins/default/textures/map_avatar_16.tga | Bin 1068 -> 1068 bytes .../skins/default/textures/map_avatar_8.tga | Bin 300 -> 300 bytes indra/newview/skins/default/textures/map_event.tga | Bin 1068 -> 1068 bytes .../skins/default/textures/map_event_adult.tga | Bin 648 -> 1006 bytes .../skins/default/textures/map_event_mature.tga | Bin 1068 -> 1068 bytes indra/newview/skins/default/textures/map_home.tga | Bin 1068 -> 1068 bytes .../newview/skins/default/textures/map_infohub.tga | Bin 1068 -> 1068 bytes .../newview/skins/default/textures/map_telehub.tga | Bin 1068 -> 1068 bytes indra/newview/skins/default/textures/textures.xml | 15 +- .../skins/default/xui/en/floater_world_map.xml | 714 ++++++++++++--------- .../default/xui/en/panel_region_general_layout.xml | 242 ------- 13 files changed, 426 insertions(+), 545 deletions(-) delete mode 100644 indra/newview/skins/default/xui/en/panel_region_general_layout.xml (limited to 'indra/newview') diff --git a/indra/newview/skins/default/textures/icon_event_adult.tga b/indra/newview/skins/default/textures/icon_event_adult.tga index c344fb1e78..f548126e5a 100644 Binary files a/indra/newview/skins/default/textures/icon_event_adult.tga and b/indra/newview/skins/default/textures/icon_event_adult.tga differ diff --git a/indra/newview/skins/default/textures/icon_top_pick.tga b/indra/newview/skins/default/textures/icon_top_pick.tga index 7fe119a818..0b34882d2f 100644 Binary files a/indra/newview/skins/default/textures/icon_top_pick.tga and b/indra/newview/skins/default/textures/icon_top_pick.tga differ diff --git a/indra/newview/skins/default/textures/map_avatar_16.tga b/indra/newview/skins/default/textures/map_avatar_16.tga index ce129e3590..f59e9e9193 100644 Binary files a/indra/newview/skins/default/textures/map_avatar_16.tga and b/indra/newview/skins/default/textures/map_avatar_16.tga differ diff --git a/indra/newview/skins/default/textures/map_avatar_8.tga b/indra/newview/skins/default/textures/map_avatar_8.tga index 28552f2237..8500eadeba 100644 Binary files a/indra/newview/skins/default/textures/map_avatar_8.tga and b/indra/newview/skins/default/textures/map_avatar_8.tga differ diff --git a/indra/newview/skins/default/textures/map_event.tga b/indra/newview/skins/default/textures/map_event.tga index c229b379a2..2c06d08fd2 100644 Binary files a/indra/newview/skins/default/textures/map_event.tga and b/indra/newview/skins/default/textures/map_event.tga differ diff --git a/indra/newview/skins/default/textures/map_event_adult.tga b/indra/newview/skins/default/textures/map_event_adult.tga index c344fb1e78..f548126e5a 100644 Binary files a/indra/newview/skins/default/textures/map_event_adult.tga and b/indra/newview/skins/default/textures/map_event_adult.tga differ diff --git a/indra/newview/skins/default/textures/map_event_mature.tga b/indra/newview/skins/default/textures/map_event_mature.tga index 61c879bc92..71067c0dfd 100644 Binary files a/indra/newview/skins/default/textures/map_event_mature.tga and b/indra/newview/skins/default/textures/map_event_mature.tga differ diff --git a/indra/newview/skins/default/textures/map_home.tga b/indra/newview/skins/default/textures/map_home.tga index 7478de371a..acaaa3db44 100644 Binary files a/indra/newview/skins/default/textures/map_home.tga and b/indra/newview/skins/default/textures/map_home.tga differ diff --git a/indra/newview/skins/default/textures/map_infohub.tga b/indra/newview/skins/default/textures/map_infohub.tga index d0134fa5fe..545b8e532c 100644 Binary files a/indra/newview/skins/default/textures/map_infohub.tga and b/indra/newview/skins/default/textures/map_infohub.tga differ diff --git a/indra/newview/skins/default/textures/map_telehub.tga b/indra/newview/skins/default/textures/map_telehub.tga index ef63a3eb72..545b8e532c 100644 Binary files a/indra/newview/skins/default/textures/map_telehub.tga and b/indra/newview/skins/default/textures/map_telehub.tga differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index f4a239be62..5e2105206d 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -1,19 +1,19 @@ @@ -707,7 +707,6 @@ with the same filename but different name - diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml index c60cc163c8..c0eca91a46 100644 --- a/indra/newview/skins/default/xui/en/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en/floater_world_map.xml @@ -4,7 +4,7 @@ can_resize="true" center_horiz="true" center_vert="true" - height="600" + height="535" layout="topleft" min_height="520" min_width="520" @@ -17,389 +17,493 @@ width="800"> - + - You + left="15" + name="events_label" + top="3" + width="215"> + Legend - + + + - Home + name="person_label" + width="90"> + Me - + - + - Auction + name="person_label" + width="90"> + Person - + - - Land For Sale + name="infohub_label" + width="90"> + Infohub - + left="3" + name="land_for_sale_chk" + top_pad="2" + width="22" /> - + + name="land_sale_label" + width="90"> + Land Sale + - - + by owner + + - - + land auction + + + + + name="Home_label" + width="70"> + Home + + top_pad="9" + width="66"> Events: - + + + PG + + + left="135" + name="event_mature_chk" + top_pad="3" + width="22" /> + + Mature + + + left="135" + name="event_adult_chk" + top_pad="3" + width="22" /> - - + Adult + + + + + + + Find on Map + + + + + + tool_tip="Show friends on map" + width="182"> - + width="182"> - - - - - Search Results: - + + width="193" /> - + + + + + + + + + + - - - + left="20" + mouse_opaque="true" + name="zoom_icon" + top_pad="7" + width="16" /> + width="200" /> + diff --git a/indra/newview/skins/default/xui/en/panel_region_general_layout.xml b/indra/newview/skins/default/xui/en/panel_region_general_layout.xml deleted file mode 100644 index bffd84877f..0000000000 --- a/indra/newview/skins/default/xui/en/panel_region_general_layout.xml +++ /dev/null @@ -1,242 +0,0 @@ - - - - Region: - - - unknown - - - Version: - - - unknown - - - Type: - - - unknown - - - - - - - - - - - - Rating: - - - - - - - - -- cgit v1.2.3 From 3efbd20980175f6dae2cecbfbbd23bb326948189 Mon Sep 17 00:00:00 2001 From: Rick Pasetto Date: Wed, 25 Nov 2009 14:39:05 -0800 Subject: Implement fade-out for llprogressbar, fix problem where setTopCtrl was being called Review #47 --- indra/newview/llpanelprimmediacontrols.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index ceb37ae790..c3aa602ee6 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -503,12 +503,10 @@ void LLPanelPrimMediaControls::updateShape() { mMediaProgressPanel->setVisible(true); mMediaProgressBar->setPercent(media_plugin->getProgressPercent()); - gFocusMgr.setTopCtrl(mMediaProgressPanel); } - else if (mMediaProgressPanel->getVisible()) + else { mMediaProgressPanel->setVisible(false); - gFocusMgr.setTopCtrl(NULL); } } -- cgit v1.2.3 From a7fde5f5304651d3afb82e5a202089d78c3c57c7 Mon Sep 17 00:00:00 2001 From: Rick Pasetto Date: Wed, 25 Nov 2009 15:50:31 -0800 Subject: DEV-43402: Don't change the zoom level on the media controls if you click away Review #46 This also adds a feature where llpanelprimmediacontrols remembers the object/face that you've zoomed in on, and only switches the zoom/unzoom icon to "unzoom" if the object/face you are hovering over is actually the object/face you are zoomed in on --- indra/newview/llpanelprimmediacontrols.cpp | 21 +++++++++++++++++---- indra/newview/llpanelprimmediacontrols.h | 3 +++ indra/newview/llviewermediafocus.cpp | 9 --------- 3 files changed, 20 insertions(+), 13 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index c3aa602ee6..e86123d565 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -82,7 +82,13 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() : mUpdateSlider(true), mClearFaceOnFade(false), mCurrentRate(0.0), - mMovieDuration(0.0) + mMovieDuration(0.0), + mTargetObjectID(LLUUID::null), + mTargetObjectFace(0), + mTargetImplID(LLUUID::null), + mTargetObjectNormal(LLVector3::zero), + mZoomObjectID(LLUUID::null), + mZoomObjectFace(0) { mCommitCallbackRegistrar.add("MediaCtrl.Close", boost::bind(&LLPanelPrimMediaControls::onClickClose, this)); mCommitCallbackRegistrar.add("MediaCtrl.Back", boost::bind(&LLPanelPrimMediaControls::onClickBack, this)); @@ -277,7 +283,7 @@ void LLPanelPrimMediaControls::updateShape() bool can_navigate = parcel->getMediaAllowNavigate(); bool enabled = false; - bool is_zoomed = (mCurrentZoom != ZOOM_NONE); + bool is_zoomed = (mCurrentZoom != ZOOM_NONE) && (mTargetObjectID == mZoomObjectID) && (mTargetObjectFace == mZoomObjectFace); // There is no such thing as "has_focus" being different from normal controls set // anymore (as of user feedback from bri 10/09). So we cheat here and force 'has_focus' // to 'true' (or, actually, we use a setting) @@ -307,7 +313,7 @@ void LLPanelPrimMediaControls::updateShape() mStopCtrl->setVisible(false); mHomeCtrl->setVisible(has_focus); mZoomCtrl->setVisible(!is_zoomed); - mUnzoomCtrl->setVisible(has_focus && is_zoomed); + mUnzoomCtrl->setVisible(is_zoomed); mOpenCtrl->setVisible(true); mMediaAddressCtrl->setVisible(has_focus && !mini_controls); mMediaPlaySliderPanel->setVisible(has_focus && !mini_controls); @@ -982,9 +988,16 @@ void LLPanelPrimMediaControls::updateZoom() } } - if (zoom_padding > 0.0f) + if (zoom_padding > 0.0f) + { LLViewerMediaFocus::setCameraZoom(getTargetObject(), mTargetObjectNormal, zoom_padding); + } + + // Remember the object ID/face we zoomed into, so we can update the zoom icon appropriately + mZoomObjectID = mTargetObjectID; + mZoomObjectFace = mTargetObjectFace; } + void LLPanelPrimMediaControls::onScrollUp(void* user_data) { LLPanelPrimMediaControls* this_panel = static_cast (user_data); diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h index 4bb05265c8..fe8f100abe 100644 --- a/indra/newview/llpanelprimmediacontrols.h +++ b/indra/newview/llpanelprimmediacontrols.h @@ -195,6 +195,9 @@ private: S32 mTargetObjectFace; LLUUID mTargetImplID; LLVector3 mTargetObjectNormal; + + LLUUID mZoomObjectID; + S32 mZoomObjectFace; }; #endif // LL_PANELPRIMMEDIACONTROLS_H diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp index fd74c9c2fc..f639c841e7 100644 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -138,15 +138,6 @@ void LLViewerMediaFocus::setFocusFace(LLPointer objectp, S32 fac } else { - if(mFocusedImplID.notNull()) - { - if(mMediaControls.get()) - { - // Don't reset camera zoom by default, just tell the controls they're no longer controlling zoom. - mMediaControls.get()->resetZoomLevel(false); - } - } - if(hasFocus()) { gFocusMgr.setKeyboardFocus(NULL); -- cgit v1.2.3 From 52a387e00f963d9920f36ffc0dcc855889f36cad Mon Sep 17 00:00:00 2001 From: James Cook Date: Wed, 25 Nov 2009 17:45:07 -0800 Subject: Fix up nav bar buy icon spacing. Trivial, not reviewed. --- indra/newview/lllocationinputctrl.cpp | 2 +- indra/newview/skins/default/xui/en/widgets/location_input.xml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 45c60df84f..9d4dc2b285 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -638,7 +638,7 @@ static S32 layout_widget(LLUICtrl* widget, S32 right) void LLLocationInputCtrl::refreshParcelIcons() { // Our "cursor" moving right to left - S32 x = mAddLandmarkBtn->getRect().mLeft - mIconHPad; + S32 x = mAddLandmarkBtn->getRect().mLeft; static LLUICachedControl show_properties("NavBarShowParcelProperties", false); if (show_properties) diff --git a/indra/newview/skins/default/xui/en/widgets/location_input.xml b/indra/newview/skins/default/xui/en/widgets/location_input.xml index 90887dead6..ea78f6d0dd 100644 --- a/indra/newview/skins/default/xui/en/widgets/location_input.xml +++ b/indra/newview/skins/default/xui/en/widgets/location_input.xml @@ -11,7 +11,7 @@ add_landmark_image_disabled="Favorite_Star_Off" add_landmark_image_hover="Favorite_Star_Over" add_landmark_image_selected="Favorite_Star_Press" - add_landmark_hpad="10" + add_landmark_hpad="12" icon_hpad="2" allow_text_entry="true" list_position="below" @@ -42,6 +42,7 @@ Date: Wed, 25 Nov 2009 18:24:39 -0800 Subject: created container for LLFloaterView for future z-swapping with sidetray floaters can now overlap sidetray fixed text selection background color to be inverse of text fg color EXT-2713 Script editor automatically scrolls to the top of script text when text is longer than the window. reviewed by James --- indra/newview/llchathistory.cpp | 2 +- indra/newview/llchiclet.cpp | 2 +- indra/newview/llviewerwindow.cpp | 6 +++-- indra/newview/llviewerwindow.h | 5 +++- indra/newview/skins/default/xui/en/main_view.xml | 18 ++++++++++---- .../skins/default/xui/en/panel_chat_header.xml | 28 ++++++++++++---------- 6 files changed, 39 insertions(+), 22 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 2c9b38b82a..d08be335c3 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -284,7 +284,7 @@ private: time_box->translate(delta_pos_x, delta_pos_y); //... & change width of the name control - LLTextBox* user_name = getChild("user_name"); + LLUICtrl* user_name = getChild("user_name"); const LLRect& user_rect = user_name->getRect(); user_name->reshape(user_rect.getWidth() + delta_pos_x, user_rect.getHeight()); } diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index f41e326dd0..9aef02c5c8 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -1362,7 +1362,7 @@ void LLChicletNotificationCounterCtrl::setCounter(S32 counter) LLRect LLChicletNotificationCounterCtrl::getRequiredRect() { LLRect rc; - S32 text_width = getContentsRect().getWidth(); + S32 text_width = getTextPixelWidth(); rc.mRight = rc.mLeft + llmax(text_width, mInitialWidth); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index f12937194d..9ba056a17c 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1417,10 +1417,12 @@ void LLViewerWindow::initBase() // placeholder widget that controls where "world" is rendered mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle(); + mNonSideTrayView = main_view->getChildView("non_side_tray_view")->getHandle(); + mFloaterViewHolder = main_view->getChildView("floater_view_holder")->getHandle(); // Constrain floaters to inside the menu and status bar regions. - gFloaterView = getRootView()->getChild("Floater View"); - gSnapshotFloaterView = getRootView()->getChild("Snapshot Floater View"); + gFloaterView = main_view->getChild("Floater View"); + gSnapshotFloaterView = main_view->getChild("Snapshot Floater View"); // Console llassert( !gConsole ); diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 747fd3b253..1d564a1338 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -298,7 +298,8 @@ public: void updateKeyboardFocus(); void updateWorldViewRect(bool use_full_window=false); - + LLView* getNonSideTrayView() { return mNonSideTrayView.get(); } + LLView* getFloaterViewHolder() { return mFloaterViewHolder.get(); } BOOL handleKey(KEY key, MASK mask); void handleScrollWheel (S32 clicks); @@ -459,6 +460,8 @@ protected: std::string mInitAlert; // Window / GL initialization requires an alert LLHandle mWorldViewPlaceholder; // widget that spans the portion of screen dedicated to rendering the 3d world + LLHandle mNonSideTrayView; // parent of world view + bottom bar, etc...everything but the side tray + LLHandle mFloaterViewHolder; // container for floater_view class LLDebugText* mDebugText; // Internal class for debug text diff --git a/indra/newview/skins/default/xui/en/main_view.xml b/indra/newview/skins/default/xui/en/main_view.xml index 3bf7f50a2c..d99205b2fe 100644 --- a/indra/newview/skins/default/xui/en/main_view.xml +++ b/indra/newview/skins/default/xui/en/main_view.xml @@ -48,7 +48,7 @@ height="500" layout="topleft" mouse_opaque="false" - name="main_view" + name="non_side_tray_view" user_resize="true" width="500"> - + width="1024"> + + + allow_scroll="false" + v_pad = "0" + read_only = "true" + follows="left|right" + font.style="BOLD" + height="12" + layout="topleft" + left_pad="5" + right="-60" + name="user_name" + text_color="white" + bg_readonly_color="black" + top="8" + use_ellipses="true" + value="Ericag Vader" /> Date: Wed, 25 Nov 2009 18:55:15 -0800 Subject: forgot to apply resize fix for when text is selected EXT-1995 - [BSI] Get rid of the *blop* sound when a textbox contains more text than displayable --- indra/newview/skins/default/xui/en/floater_aaa.xml | 32 +++++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml index 0c64408b50..30eacec060 100644 --- a/indra/newview/skins/default/xui/en/floater_aaa.xml +++ b/indra/newview/skins/default/xui/en/floater_aaa.xml @@ -1,10 +1,34 @@ - 4 - + width="500"> + + Second Life is brought to you by Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les and many others. + + Thank you to the following residents for helping to ensure that this is the best version yet: (in progress) + + + + + + + + + It is a rare mind indeed that can render the hitherto non-existent blindingly obvious. The cry 'I could have thought of that' is a very popular and misleading one, for the fact is that they didn't, and a very significant and revealing fact it is too. + -- Douglas Adams + -- cgit v1.2.3 From 4885ddab8d729dd036155e479f1ce2221074a4ac Mon Sep 17 00:00:00 2001 From: richard Date: Wed, 25 Nov 2009 19:55:24 -0800 Subject: EXT-1944 - Implement ellipsis in message well EXT-699 - Toasts should display maximum 6 lines of text before ellipses are applied EXT-2453 - TextBox displays an extra line of text --- indra/newview/skins/default/xui/en/panel_sys_well_item.xml | 1 + indra/newview/skins/default/xui/en/panel_toast.xml | 2 ++ indra/newview/skins/default/xui/en/widgets/textbase.xml | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml index ccb57b6552..2822f7b841 100644 --- a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml +++ b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml @@ -14,6 +14,7 @@ background_visible="true" bg_alpha_color="0.0 0.0 0.0 0.0" > Toast text; diff --git a/indra/newview/skins/default/xui/en/widgets/textbase.xml b/indra/newview/skins/default/xui/en/widgets/textbase.xml index 6dd92ea34b..166e8555fe 100644 --- a/indra/newview/skins/default/xui/en/widgets/textbase.xml +++ b/indra/newview/skins/default/xui/en/widgets/textbase.xml @@ -1,2 +1,2 @@ - + -- cgit v1.2.3 From 3858992603aabbdfdcdd9f3d8040a2d3431e74d0 Mon Sep 17 00:00:00 2001 From: James Cook Date: Fri, 27 Nov 2009 22:24:57 -0800 Subject: Add CMake var LL_TESTS to optionally disable tests for build timing --- indra/newview/CMakeLists.txt | 80 +++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 39 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e632cbaaf2..fc6955bc70 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1651,48 +1651,50 @@ if (INSTALL) include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake) endif (INSTALL) -# To add a viewer unit test, just add the test .cpp file below -# This creates a separate test project per file listed. -include(LLAddBuildTest) -SET(viewer_TEST_SOURCE_FILES - llagentaccess.cpp - lldateutil.cpp - llmediadataclient.cpp - llviewerhelputil.cpp - lllogininstance.cpp - ) -set_source_files_properties( - ${viewer_TEST_SOURCE_FILES} - PROPERTIES - LL_TEST_ADDITIONAL_SOURCE_FILES llviewerprecompiledheaders.cpp - ) -LL_ADD_PROJECT_UNIT_TESTS(${VIEWER_BINARY_NAME} "${viewer_TEST_SOURCE_FILES}") - -#set(TEST_DEBUG on) -set(test_sources llcapabilitylistener.cpp llviewerprecompiledheaders.cpp) -set(test_libs - ${LLMESSAGE_LIBRARIES} - ${WINDOWS_LIBRARIES} - ${LLVFS_LIBRARIES} - ${LLMATH_LIBRARIES} - ${LLCOMMON_LIBRARIES} - ${GOOGLEMOCK_LIBRARIES} +if (LL_TESTS) + # To add a viewer unit test, just add the test .cpp file below + # This creates a separate test project per file listed. + include(LLAddBuildTest) + SET(viewer_TEST_SOURCE_FILES + llagentaccess.cpp + lldateutil.cpp + llmediadataclient.cpp + llviewerhelputil.cpp + lllogininstance.cpp ) + set_source_files_properties( + ${viewer_TEST_SOURCE_FILES} + PROPERTIES + LL_TEST_ADDITIONAL_SOURCE_FILES llviewerprecompiledheaders.cpp + ) + LL_ADD_PROJECT_UNIT_TESTS(${VIEWER_BINARY_NAME} "${viewer_TEST_SOURCE_FILES}") -LL_ADD_INTEGRATION_TEST(llcapabilitylistener - "${test_sources}" - "${test_libs}" - ${PYTHON_EXECUTABLE} - "${CMAKE_SOURCE_DIR}/llmessage/tests/test_llsdmessage_peer.py" - ) + #set(TEST_DEBUG on) + set(test_sources llcapabilitylistener.cpp llviewerprecompiledheaders.cpp) + set(test_libs + ${LLMESSAGE_LIBRARIES} + ${WINDOWS_LIBRARIES} + ${LLVFS_LIBRARIES} + ${LLMATH_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${GOOGLEMOCK_LIBRARIES} + ) + + LL_ADD_INTEGRATION_TEST(llcapabilitylistener + "${test_sources}" + "${test_libs}" + ${PYTHON_EXECUTABLE} + "${CMAKE_SOURCE_DIR}/llmessage/tests/test_llsdmessage_peer.py" + ) -#ADD_VIEWER_BUILD_TEST(llmemoryview viewer) -#ADD_VIEWER_BUILD_TEST(llagentaccess viewer) -#ADD_VIEWER_BUILD_TEST(llworldmap viewer) -#ADD_VIEWER_BUILD_TEST(llworldmipmap viewer) -#ADD_VIEWER_BUILD_TEST(lltextureinfo viewer) -#ADD_VIEWER_BUILD_TEST(lltextureinfodetails viewer) -#ADD_VIEWER_BUILD_TEST(lltexturestatsuploader viewer) + #ADD_VIEWER_BUILD_TEST(llmemoryview viewer) + #ADD_VIEWER_BUILD_TEST(llagentaccess viewer) + #ADD_VIEWER_BUILD_TEST(llworldmap viewer) + #ADD_VIEWER_BUILD_TEST(llworldmipmap viewer) + #ADD_VIEWER_BUILD_TEST(lltextureinfo viewer) + #ADD_VIEWER_BUILD_TEST(lltextureinfodetails viewer) + #ADD_VIEWER_BUILD_TEST(lltexturestatsuploader viewer) +endif (LL_TESTS) # Don't do these for DARWIN or LINUX here -- they're taken care of by viewer_manifest.py -- cgit v1.2.3 From f280c43d616d013747a9aab05141635868e00136 Mon Sep 17 00:00:00 2001 From: James Cook Date: Sat, 28 Nov 2009 16:51:02 -0800 Subject: Use extern template for common singletons to reduce code bloat/link time. --- indra/newview/llbottomtray.cpp | 3 +++ indra/newview/llbottomtray.h | 3 +++ indra/newview/llfloatertestlistview.cpp | 7 +++++++ indra/newview/llfloatertestlistview.h | 4 ++++ indra/newview/llselectmgr.cpp | 2 ++ indra/newview/llselectmgr.h | 3 +++ indra/newview/llviewercamera.cpp | 3 +++ indra/newview/llviewercamera.h | 3 +++ 8 files changed, 28 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 9cc7b8c785..4823932951 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -46,6 +46,9 @@ #include "llsyswellwindow.h" #include "llfloatercamera.h" +// Build time optimization, generate this once in .cpp file +template class LLBottomTray* LLSingleton::getInstance(); + LLBottomTray::LLBottomTray(const LLSD&) : mChicletPanel(NULL), mSysWell(NULL), diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 7640cdcf9d..3db5184f6b 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -47,6 +47,9 @@ class LLSpeakButton; class LLNearbyChatBar; class LLIMChiclet; +// Build time optimization, generate this once in .cpp file +extern template class LLBottomTray* LLSingleton::getInstance(); + class LLBottomTray : public LLSingleton , public LLPanel diff --git a/indra/newview/llfloatertestlistview.cpp b/indra/newview/llfloatertestlistview.cpp index 7171449738..ae96dfc0ed 100644 --- a/indra/newview/llfloatertestlistview.cpp +++ b/indra/newview/llfloatertestlistview.cpp @@ -31,6 +31,12 @@ */ #include "llviewerprecompiledheaders.h" +int do_foo(int i) +{ + return i + 1; +} + +/* #include "llfloatertestlistview.h" LLFloaterTestListView::LLFloaterTestListView(const LLSD& seed) @@ -39,3 +45,4 @@ LLFloaterTestListView::LLFloaterTestListView(const LLSD& seed) LLFloaterTestListView::~LLFloaterTestListView() {} +*/ diff --git a/indra/newview/llfloatertestlistview.h b/indra/newview/llfloatertestlistview.h index 0c47c2ee31..311bd18bc0 100644 --- a/indra/newview/llfloatertestlistview.h +++ b/indra/newview/llfloatertestlistview.h @@ -32,6 +32,9 @@ #ifndef LLFLOATERTESTLISTVIEW_H #define LLFLOATERTESTLISTVIEW_H +int do_foo(int i); + +/* #include "llfloater.h" class LLSD; @@ -45,5 +48,6 @@ private: LLFloaterTestListView(const LLSD& seed); ~LLFloaterTestListView(); }; +*/ #endif diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 2554f1ccd5..4394271ec4 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -175,6 +175,8 @@ LLObjectSelection *get_null_object_selection() return sNullSelection; } +// Build time optimization, generate this function once here +template class LLSelectMgr* LLSingleton::getInstance(); //----------------------------------------------------------------------------- // LLSelectMgr() diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 2050a73f26..7a5c583711 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -323,6 +323,9 @@ private: typedef LLSafeHandle LLObjectSelectionHandle; +// Build time optimization, generate this once in .cpp file +extern template class LLSelectMgr* LLSingleton::getInstance(); + class LLSelectMgr : public LLEditMenuHandler, public LLSingleton { public: diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index f3c64088c9..221db2defa 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -105,6 +105,9 @@ glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up) } +// Build time optimization, generate this once in .cpp file +template class LLViewerCamera* LLSingleton::getInstance(); + LLViewerCamera::LLViewerCamera() : LLCamera() { calcProjection(getFar()); diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index 2b8a0892bf..01fa86d7c5 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -52,6 +52,9 @@ const F32 OGL_TO_CFR_ROTATION[16] = { 0.f, 0.f, -1.f, 0.f, // -Z becomes X const BOOL FOR_SELECTION = TRUE; const BOOL NOT_FOR_SELECTION = FALSE; +// Build time optimization, generate this once in .cpp file +extern template class LLViewerCamera* LLSingleton::getInstance(); + class LLViewerCamera : public LLCamera, public LLSingleton { public: -- cgit v1.2.3 From 3838a7dfa5340019f29c11f1f690400182c2df8d Mon Sep 17 00:00:00 2001 From: James Cook Date: Sat, 28 Nov 2009 17:15:53 -0800 Subject: Fix build broken by removal of a test floater. --- indra/newview/llviewerfloaterreg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 642df92379..aebc97ab7d 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -224,7 +224,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build); LLFloaterReg::add("test_inspectors", "floater_test_inspectors.xml", &LLFloaterReg::build); - LLFloaterReg::add("test_list_view", "floater_test_list_view.xml",&LLFloaterReg::build); + //LLFloaterReg::add("test_list_view", "floater_test_list_view.xml",&LLFloaterReg::build); LLFloaterReg::add("test_widgets", "floater_test_widgets.xml", &LLFloaterReg::build); LLFloaterReg::add("top_objects", "floater_top_objects.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); -- cgit v1.2.3 From 0e34bc413aa562acf97b77333fb9a1f0ec9b55f0 Mon Sep 17 00:00:00 2001 From: James Cook Date: Sat, 28 Nov 2009 20:56:27 -0800 Subject: Slightly more complex test file --- indra/newview/llfloatertestlistview.cpp | 7 ------- indra/newview/llfloatertestlistview.h | 4 ---- 2 files changed, 11 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloatertestlistview.cpp b/indra/newview/llfloatertestlistview.cpp index ae96dfc0ed..7171449738 100644 --- a/indra/newview/llfloatertestlistview.cpp +++ b/indra/newview/llfloatertestlistview.cpp @@ -31,12 +31,6 @@ */ #include "llviewerprecompiledheaders.h" -int do_foo(int i) -{ - return i + 1; -} - -/* #include "llfloatertestlistview.h" LLFloaterTestListView::LLFloaterTestListView(const LLSD& seed) @@ -45,4 +39,3 @@ LLFloaterTestListView::LLFloaterTestListView(const LLSD& seed) LLFloaterTestListView::~LLFloaterTestListView() {} -*/ diff --git a/indra/newview/llfloatertestlistview.h b/indra/newview/llfloatertestlistview.h index 311bd18bc0..0c47c2ee31 100644 --- a/indra/newview/llfloatertestlistview.h +++ b/indra/newview/llfloatertestlistview.h @@ -32,9 +32,6 @@ #ifndef LLFLOATERTESTLISTVIEW_H #define LLFLOATERTESTLISTVIEW_H -int do_foo(int i); - -/* #include "llfloater.h" class LLSD; @@ -48,6 +45,5 @@ private: LLFloaterTestListView(const LLSD& seed); ~LLFloaterTestListView(); }; -*/ #endif -- cgit v1.2.3 From b50ba67bd8ab329d598ce47e5d3ac09b59fffb63 Mon Sep 17 00:00:00 2001 From: James Cook Date: Sun, 29 Nov 2009 10:19:17 -0800 Subject: Revert extern template link optimization until I can build/test on PC --- indra/newview/llbottomtray.h | 2 +- indra/newview/llselectmgr.h | 2 +- indra/newview/llviewercamera.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 3db5184f6b..30f5f88cce 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -48,7 +48,7 @@ class LLNearbyChatBar; class LLIMChiclet; // Build time optimization, generate this once in .cpp file -extern template class LLBottomTray* LLSingleton::getInstance(); +//extern template class LLBottomTray* LLSingleton::getInstance(); class LLBottomTray : public LLSingleton diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 7a5c583711..57e0ee4e0e 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -324,7 +324,7 @@ private: typedef LLSafeHandle LLObjectSelectionHandle; // Build time optimization, generate this once in .cpp file -extern template class LLSelectMgr* LLSingleton::getInstance(); +//extern template class LLSelectMgr* LLSingleton::getInstance(); class LLSelectMgr : public LLEditMenuHandler, public LLSingleton { diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index 01fa86d7c5..bf561c3e4d 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -53,7 +53,7 @@ const BOOL FOR_SELECTION = TRUE; const BOOL NOT_FOR_SELECTION = FALSE; // Build time optimization, generate this once in .cpp file -extern template class LLViewerCamera* LLSingleton::getInstance(); +//extern template class LLViewerCamera* LLSingleton::getInstance(); class LLViewerCamera : public LLCamera, public LLSingleton { -- cgit v1.2.3 From c83aa5ba6af31a46eaf2b605e469feeb8bc26871 Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Mon, 30 Nov 2009 11:41:00 +0200 Subject: Fixed wrong type for getChild("user_name") to prevent WARNING logging. --HG-- branch : product-engine --- indra/newview/llchathistory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index caf9c08057..c4c046b3c4 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -302,7 +302,7 @@ private: time_box->translate(delta_pos_x, delta_pos_y); //... & change width of the name control - LLTextBox* user_name = getChild("user_name"); + LLView* user_name = getChild("user_name"); const LLRect& user_rect = user_name->getRect(); user_name->reshape(user_rect.getWidth() + delta_pos_x, user_rect.getHeight()); } -- cgit v1.2.3 From 651dfe1f6902fe221bcc0306365e4555c118b15b Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Mon, 30 Nov 2009 11:43:05 +0200 Subject: Work on major sub-task EXT-2790 (Complete Voice Control Panel (floater) started by Lynx (LLVoiceControlPanel)) -- Added initial processing of titles for different calls --HG-- branch : product-engine --- indra/newview/llcallfloater.cpp | 17 +++++++++++++++++ indra/newview/llcallfloater.h | 1 + .../skins/default/xui/en/floater_voice_controls.xml | 12 ++++++++++++ 3 files changed, 30 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index b41f962ffa..46432a4953 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -119,6 +119,7 @@ void LLCallFloater::updateSession() lldebugs << "Set DEFAULT speaker manager" << llendl; } + updateTitle(); refreshPartisipantList(); } @@ -135,4 +136,20 @@ void LLCallFloater::onCurrentChannelChanged(const LLUUID& /*session_id*/) { updateSession(); } + +void LLCallFloater::updateTitle() +{ + LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); + if (NULL == voice_channel) return; + + std::string title = voice_channel->getSessionName(); + + if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager) + { + title = getString("title_nearby"); + } + + // *TODO: mantipov: update code to use title from xml for other chat types + setTitle(title); +} //EOF diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index bfaa1075c4..0cd5fe05c1 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -74,6 +74,7 @@ private: */ void refreshPartisipantList(); void onCurrentChannelChanged(const LLUUID& session_id); + void updateTitle(); private: LLSpeakerMgr* mSpeakerManager; diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml index 4434fe7403..4a5642e5c6 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -8,6 +8,18 @@ save_visibility="true" single_instance="true" width="282"> + + NEARBY VOICE + + + Group Call with [GROUP] + + + Conference Call + Date: Mon, 30 Nov 2009 11:45:00 +0200 Subject: Work on major sub-task EXT-2790 (Complete Voice Control Panel (floater) started by Lynx (LLVoiceControlPanel)) -- Added updating of the speakers list for P2P call --HG-- branch : product-engine --- indra/newview/llimview.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 2f88578739..24092bab98 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -233,6 +233,12 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES break; } } + + // Update speakers list when connected + if (LLVoiceChannel::STATE_CONNECTED == new_state) + { + mSpeakers->update(true); + } } else // group || ad-hoc calls { -- cgit v1.2.3 From 53583548693a03385bab14029b9d0e2a7606d2e9 Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Mon, 30 Nov 2009 11:48:47 +0200 Subject: Fixed Line endings to Unix format --HG-- branch : product-engine --- indra/newview/llchathistory.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index c4c046b3c4..078c2518c6 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -267,20 +267,20 @@ protected: } private: - std::string appendTime(const LLChat& chat) - { - time_t utc_time; - utc_time = time_corrected(); - std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" - +LLTrans::getString("TimeMin")+"] "; - - LLSD substitution; - - substitution["datetime"] = (S32) utc_time; - LLStringUtil::format (timeStr, substitution); - - return timeStr; - } + std::string appendTime(const LLChat& chat) + { + time_t utc_time; + utc_time = time_corrected(); + std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:[" + +LLTrans::getString("TimeMin")+"] "; + + LLSD substitution; + + substitution["datetime"] = (S32) utc_time; + LLStringUtil::format (timeStr, substitution); + + return timeStr; + } void setTimeField(const LLChat& chat) { -- cgit v1.2.3 From 7ea44f8addc8fc7218e7030b11f62ea5a3f99511 Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Mon, 30 Nov 2009 13:51:52 +0200 Subject: Work on major sub-task EXT-2790 (Complete Voice Control Panel (floater) started by Lynx (LLVoiceControlPanel)) -- Excluded Agent's item from the Participant List --HG-- branch : product-engine --- indra/newview/llparticipantlist.cpp | 13 +++++++++++-- indra/newview/llparticipantlist.h | 5 +++++ 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 68dc1b511f..07a1214b4f 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -87,7 +87,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++) { const LLPointer& speakerp = *it; - group_members.push_back(speakerp->mID); + addAvatarIDExceptAgent(group_members, speakerp->mID); if ( speakerp->mIsModerator ) { mModeratorList.insert(speakerp->mID); @@ -192,7 +192,7 @@ bool LLParticipantList::onAddItemEvent(LLPointer event, co return true; } - group_members.push_back(uu_id); + addAvatarIDExceptAgent(group_members, uu_id); // Mark AvatarList as dirty one mAvatarList->setDirty(); sort(); @@ -260,6 +260,15 @@ void LLParticipantList::sort() } } +// static +void LLParticipantList::addAvatarIDExceptAgent(std::vector& existing_list, const LLUUID& avatar_id) +{ + if (gAgent.getID() != avatar_id) + { + existing_list.push_back(avatar_id); + } +} + // // LLParticipantList::SpeakerAddListener // diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index ce61dd9b96..460cf4b9ef 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -132,6 +132,11 @@ class LLParticipantList void onAvatarListDoubleClicked(LLAvatarList* list); void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param); + /** + * Adds specified avatar ID to the existing list if it is not Agent's ID + */ + static void addAvatarIDExceptAgent(std::vector& existing_list, const LLUUID& avatar_id); + LLSpeakerMgr* mSpeakerMgr; LLAvatarList* mAvatarList; -- cgit v1.2.3 From 3284dec5d962993882c1eaeee231e04b46fd4ec7 Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Mon, 30 Nov 2009 15:27:20 +0200 Subject: Work on major sub-task EXT-2790 (Complete Voice Control Panel (floater) started by Lynx (LLVoiceControlPanel)) -- Updated title according to voice chat type --HG-- branch : product-engine --- indra/newview/llcallfloater.cpp | 36 ++++++++++++++++++++++++++++++------ indra/newview/llcallfloater.h | 9 +++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index 46432a4953..b29e6d0574 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -46,6 +46,7 @@ LLCallFloater::LLCallFloater(const LLSD& key) , mSpeakerManager(NULL) , mPaticipants(NULL) , mAvatarList(NULL) +, mVoiceType(VC_LOCAL_CHAT) { } @@ -110,6 +111,19 @@ void LLCallFloater::updateSession() if (im_session) { mSpeakerManager = LLIMModel::getInstance()->getSpeakerManager(session_id); + switch (im_session->mType) + { + case IM_NOTHING_SPECIAL: + case IM_SESSION_P2P_INVITE: + mVoiceType = VC_PEER_TO_PEER; + break; + case IM_SESSION_CONFERENCE_START: + mVoiceType = VC_AD_HOC_CHAT; + break; + default: + mVoiceType = VC_GROUP_CHAT; + break; + } } if (NULL == mSpeakerManager) @@ -117,6 +131,7 @@ void LLCallFloater::updateSession() // by default let show nearby chat participants mSpeakerManager = LLLocalSpeakerMgr::getInstance(); lldebugs << "Set DEFAULT speaker manager" << llendl; + mVoiceType = VC_LOCAL_CHAT; } updateTitle(); @@ -140,16 +155,25 @@ void LLCallFloater::onCurrentChannelChanged(const LLUUID& /*session_id*/) void LLCallFloater::updateTitle() { LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); - if (NULL == voice_channel) return; - - std::string title = voice_channel->getSessionName(); - - if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager) + std::string title; + switch (mVoiceType) { + case VC_LOCAL_CHAT: title = getString("title_nearby"); + break; + case VC_PEER_TO_PEER: + title = voice_channel->getSessionName(); + break; + case VC_AD_HOC_CHAT: + title = getString("title_adhoc"); + break; + case VC_GROUP_CHAT: + LLStringUtil::format_map_t args; + args["[GROUP]"] = voice_channel->getSessionName(); + title = getString("title_group", args); + break; } - // *TODO: mantipov: update code to use title from xml for other chat types setTitle(title); } //EOF diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index 0cd5fe05c1..94a19d92e0 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -61,6 +61,14 @@ public: /*virtual*/ void onOpen(const LLSD& key); private: + typedef enum e_voice_controls_type + { + VC_LOCAL_CHAT, + VC_GROUP_CHAT, + VC_AD_HOC_CHAT, + VC_PEER_TO_PEER + }EVoiceControls; + /** * Updates mSpeakerManager and list according to current Voice Channel * @@ -80,6 +88,7 @@ private: LLSpeakerMgr* mSpeakerManager; LLParticipantList* mPaticipants; LLAvatarList* mAvatarList; + EVoiceControls mVoiceType; }; -- cgit v1.2.3 From 9e0e0e4d54c73288a159beae3a654771a75f3714 Mon Sep 17 00:00:00 2001 From: Yuri Chebotarev Date: Mon, 30 Nov 2009 15:35:48 +0200 Subject: no ticket. addition to "(EXT-2894)- Add support for the viewer 1.23 chat history style (widget-less)" change all messages style when chaning chat style in preference. --HG-- branch : product-engine --- indra/newview/llfloaterpreference.cpp | 3 +++ indra/newview/llnearbychat.cpp | 26 +++++++++++++++++++++++++- indra/newview/llnearbychat.h | 8 +++++++- 3 files changed, 35 insertions(+), 2 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 83c784c1f7..5128a7b861 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -106,6 +106,7 @@ #include "llviewermedia.h" #include "llpluginclassmedia.h" #include "llteleporthistorystorage.h" +#include "llnearbychat.h" #include @@ -361,6 +362,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) BOOL LLFloaterPreference::postBuild() { gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2)); + + gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate, _2)); LLTabContainer* tabcontainer = getChild("pref core"); if (!tabcontainer->selectTab(gSavedSettings.getS32("LastPrefTab"))) diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 8f1dec1431..ee3be0a5e3 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -57,6 +57,7 @@ #include "lltrans.h" #include "llbottomtray.h" #include "llnearbychatbar.h" +#include "llfloaterreg.h" static const S32 RESIZE_BAR_THICKNESS = 3; @@ -145,7 +146,7 @@ std::string appendTime() return timeStr; } -void LLNearbyChat::addMessage(const LLChat& chat) +void LLNearbyChat::addMessage(const LLChat& chat,bool archive) { if (chat.mChatType == CHAT_TYPE_DEBUG_MSG) { @@ -207,6 +208,13 @@ void LLNearbyChat::addMessage(const LLChat& chat) mChatHistory->appendMessage(chat,use_plain_text_chat_history); } } + + if(archive) + { + mMessageArchive.push_back(chat); + if(mMessageArchive.size()>200) + mMessageArchive.erase(mMessageArchive.begin()); + } } void LLNearbyChat::onNearbySpeakers() @@ -256,3 +264,19 @@ void LLNearbyChat::getAllowedRect(LLRect& rect) { rect = gViewerWindow->getWorldViewRectScaled(); } + +void LLNearbyChat::updateChatHistoryStyle() +{ + mChatHistory->clear(); + for(std::vector::iterator it = mMessageArchive.begin();it!=mMessageArchive.end();++it) + { + addMessage(*it,false); + } +} +//static +void LLNearbyChat::processChatHistoryStyleUpdate(const LLSD& newvalue) +{ + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat", LLSD()); + if(nearby_chat) + nearby_chat->updateChatHistoryStyle(); +} diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index efcaf4263b..1cbc2a3478 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -47,7 +47,7 @@ public: ~LLNearbyChat(); BOOL postBuild (); - void addMessage (const LLChat& message); + void addMessage (const LLChat& message,bool archive = true); void onNearbyChatContextMenuItemClicked(const LLSD& userdata); bool onNearbyChatCheckContextMenuItem(const LLSD& userdata); @@ -57,6 +57,10 @@ public: virtual void setRect (const LLRect &rect); + virtual void updateChatHistoryStyle(); + + static void processChatHistoryStyleUpdate(const LLSD& newvalue); + private: virtual void applySavedVariables(); @@ -68,6 +72,8 @@ private: private: LLHandle mPopupMenuHandle; LLChatHistory* mChatHistory; + + std::vector mMessageArchive; }; #endif -- cgit v1.2.3 From 62e775288ca50e37edbdb3dc7dc55dbf61a546e3 Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Mon, 30 Nov 2009 15:38:18 +0200 Subject: Work on major sub-task EXT-2790 (Complete Voice Control Panel (floater) started by Lynx (LLVoiceControlPanel)) -- Changed text for empty nearby list to "No one near" --HG-- branch : product-engine --- indra/newview/llcallfloater.cpp | 5 +++++ indra/newview/skins/default/xui/en/floater_voice_controls.xml | 4 ++++ 2 files changed, 9 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index b29e6d0574..0c6d3d2d54 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -145,6 +145,11 @@ void LLCallFloater::refreshPartisipantList() bool do_not_use_context_menu_in_local_chat = LLLocalSpeakerMgr::getInstance() != mSpeakerManager; mPaticipants = new LLParticipantList(mSpeakerManager, mAvatarList, do_not_use_context_menu_in_local_chat); + + if (!do_not_use_context_menu_in_local_chat) + { + mAvatarList->setNoItemsCommentText(getString("no_one_near")); + } } void LLCallFloater::onCurrentChannelChanged(const LLUUID& /*session_id*/) diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml index 4a5642e5c6..3c12aed3a0 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -20,6 +20,10 @@ name="title_adhoc"> Conference Call + + No one near + Date: Mon, 30 Nov 2009 16:02:22 +0200 Subject: Work on major sub-task EXT-2790 (Complete Voice Control Panel (floater) started by Lynx (LLVoiceControlPanel)) -- Enabled "Voice Controls" button in P2P voice chat --HG-- branch : product-engine --- indra/newview/skins/default/xui/en/panel_im_control_panel.xml | 1 - 1 file changed, 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml index 0a5812882d..0a3fd1699f 100644 --- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml +++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml @@ -76,7 +76,6 @@ visible="false" width="100" /> + +Warning: the home URL specified in the General tab +fails to pass this whitelist. It has been disabled +until a valid entry has been added. + + -- cgit v1.2.3 From 93ab50efd2f009a48bc06e4491beb0c55596d3fc Mon Sep 17 00:00:00 2001 From: James Cook Date: Mon, 30 Nov 2009 17:36:10 -0800 Subject: Bump Parabuild --- indra/newview/skins/default/xui/en/floater_aaa.xml | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml index 30eacec060..d2d92b46d4 100644 --- a/indra/newview/skins/default/xui/en/floater_aaa.xml +++ b/indra/newview/skins/default/xui/en/floater_aaa.xml @@ -5,6 +5,7 @@ name="floater_aaa" can_resize="true" width="500"> + 1 Date: Mon, 30 Nov 2009 17:36:37 -0800 Subject: Clean up test XML --- .../newview/skins/default/xui/en/floater_test_textbox.xml | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/floater_test_textbox.xml b/indra/newview/skins/default/xui/en/floater_test_textbox.xml index 3aeb7c93e7..22787d029d 100644 --- a/indra/newview/skins/default/xui/en/floater_test_textbox.xml +++ b/indra/newview/skins/default/xui/en/floater_test_textbox.xml @@ -94,11 +94,7 @@ The 华文细黑 brown fox ヒラキjumped over the lazy dog. SansSerif BOLD UNDERLINE Date: Mon, 30 Nov 2009 17:55:19 -0800 Subject: Simple fix for Hg merge tool shittiness.. --- indra/newview/llfloatermediasettings.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp index 1446b828c9..16a76723eb 100644 --- a/indra/newview/llfloatermediasettings.cpp +++ b/indra/newview/llfloatermediasettings.cpp @@ -268,8 +268,6 @@ const std::string LLFloaterMediaSettings::getHomeUrl() return std::string( "" ); } -} - //////////////////////////////////////////////////////////////////////////////// // virtual void LLFloaterMediaSettings::draw() @@ -300,4 +298,6 @@ void LLFloaterMediaSettings::draw() enableOkApplyBtns(values_changed); - LLFloater::draw(); \ No newline at end of file + LLFloater::draw(); +} + -- cgit v1.2.3 From d3ae1d909eba60471e79ae7e44eff0c3ce34b64a Mon Sep 17 00:00:00 2001 From: Alexei Arabadji Date: Tue, 1 Dec 2009 12:24:46 +0200 Subject: =?UTF-8?q?fixed=20EXT-2958=20=E2=80=9CThe=20states=20of=20checkbo?= =?UTF-8?q?xes=20from=20Notes&Privacy=20tab=20are=20not=20saved=20after=20?= =?UTF-8?q?having=20been=20modified=E2=80=9D;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --HG-- branch : product-engine --- indra/newview/llpanelavatar.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 97c1e96175..125d9c3934 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -254,11 +254,19 @@ void LLPanelAvatarNotes::onCommitRights() const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); bool allow_modify_objects = childGetValue("objects_check").asBoolean(); + + // if modify objects checkbox clicked if (buddy_relationship->isRightGrantedTo( LLRelationship::GRANT_MODIFY_OBJECTS) != allow_modify_objects) { confirmModifyRights(allow_modify_objects, rights); } + // only one checkbox can trigger commit, so store the rest of rights + else + { + LLAvatarPropertiesProcessor::getInstance()->sendFriendRights( + getAvatarId(), rights); + } } void LLPanelAvatarNotes::processProperties(void* data, EAvatarProcessorType type) -- cgit v1.2.3 From bd4c1fa8d8ade4a97d5afa8aa98419038c2286f9 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Tue, 1 Dec 2009 10:52:04 +0000 Subject: DEV-40702: Internationalize the unknown Vivox version string rather than hardcode it in llvoiceclient.cpp. Also rename the string from "Unknown" to "Not connected", to better reflect the fact that we get the Vivox version once voice is connected. --- indra/newview/llvoiceclient.cpp | 6 ++++-- indra/newview/skins/default/xui/en/strings.xml | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index d677634be6..7e1e7c940f 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -63,6 +63,7 @@ #include "llparcel.h" #include "llviewerparcelmgr.h" #include "llfirstuse.h" +#include "lltrans.h" #include "llviewerwindow.h" #include "llviewercamera.h" #include "llvoavatarself.h" @@ -1161,11 +1162,12 @@ LLVoiceClient::LLVoiceClient() : mVoiceEnabled(false), mWriteInProgress(false), - mLipSyncEnabled(false), - mAPIVersion("Unknown") + mLipSyncEnabled(false) { gVoiceClient = this; + mAPIVersion = LLTrans::getString("NotConnected"); + #if LL_DARWIN || LL_LINUX || LL_SOLARIS // HACK: THIS DOES NOT BELONG HERE // When the vivox daemon dies, the next write attempt on our socket generates a SIGPIPE, which kills us. diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 4b727e36ab..e47ec1ebda 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -267,6 +267,7 @@ Change its permissions Track your camera Control your camera + Not Connected PG -- cgit v1.2.3 From 3a2fcad0cb06c493f63771f6ca62dea2f4de2374 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Tue, 1 Dec 2009 13:07:41 +0000 Subject: DEV-41358: pass localization information to the Search web pages via a new ?lang= query parameter. --- indra/newview/llfloatersearch.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index e2df2ffdf7..c8ff36b4f4 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -37,6 +37,7 @@ #include "lllogininstance.h" #include "lluri.h" #include "llagent.h" +#include "llui.h" LLFloaterSearch::LLFloaterSearch(const LLSD& key) : LLFloater(key), @@ -139,6 +140,9 @@ void LLFloaterSearch::search(const LLSD &key) } url += "&r=" + maturity; + // add the current localization information + url += "&lang=" + LLUI::getLanguage(); + // and load the URL in the web view mBrowser->navigateTo(url); } -- cgit v1.2.3 From f0808dbf0f386553b11814ff632c205f554c3059 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Tue, 1 Dec 2009 13:08:04 +0000 Subject: version number tweakery in About dialog. vivox 'Unknown' is the more-descriptive '(Not Connected)' now. plus, we admit that our Qt version number is hard-coded right into the viewer instead of asking Qt. --- indra/newview/llfloaterabout.cpp | 4 ++-- indra/newview/llvoiceclient.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 80b0a430e0..e6cae6ccce 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -269,10 +269,10 @@ LLSD LLFloaterAbout::getInfo() info["J2C_VERSION"] = LLImageJ2C::getEngineInfo(); bool want_fullname = true; info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD(); - info["VIVOX_VERSION"] = gVoiceClient ? gVoiceClient->getAPIVersion() : "Unknown"; + info["VIVOX_VERSION"] = gVoiceClient ? gVoiceClient->getAPIVersion() : "(Not Connected)"; // TODO: Implement media plugin version query - info["QT_WEBKIT_VERSION"] = "4.5.2"; + info["QT_WEBKIT_VERSION"] = "4.5.2 (version number hard-coded)"; if (gPacketsIn > 0) { diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index d677634be6..b39bd44263 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -1162,7 +1162,7 @@ LLVoiceClient::LLVoiceClient() : mWriteInProgress(false), mLipSyncEnabled(false), - mAPIVersion("Unknown") + mAPIVersion("(Not Connected)") { gVoiceClient = this; -- cgit v1.2.3 From ab5e6c93c927935943b7135a8e70dd50256e3c2e Mon Sep 17 00:00:00 2001 From: Alexei Arabadji Date: Tue, 1 Dec 2009 15:16:12 +0200 Subject: =?UTF-8?q?implemented=20EXT-2799=20=E2=80=9CRecord=20to=20IM=20hi?= =?UTF-8?q?story=20notification=20about=20L$=20payments=20by=20other=20ava?= =?UTF-8?q?tar=E2=80=9D;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --HG-- branch : product-engine --- indra/newview/llnotificationhandlerutil.cpp | 5 +++-- indra/newview/llviewermessage.cpp | 23 +++++++++++++++++++++- .../newview/skins/default/xui/en/notifications.xml | 7 +++++++ 3 files changed, 32 insertions(+), 3 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 05da338513..857b7e9796 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -43,13 +43,14 @@ using namespace LLNotificationsUI; const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"), REVOKED_MODIFY_RIGHTS("RevokedModifyRights"), OBJECT_GIVE_ITEM( "ObjectGiveItem"), OBJECT_GIVE_ITEM_UNKNOWN_USER( - "ObjectGiveItemUnknownUser"); + "ObjectGiveItemUnknownUser"), PAYMENT_RECIVED("PaymentRecived"); // static bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) { return GRANTED_MODIFY_RIGHTS == notification->getName() - || REVOKED_MODIFY_RIGHTS == notification->getName(); + || REVOKED_MODIFY_RIGHTS == notification->getName() + || PAYMENT_RECIVED == notification->getName(); } // static diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 9fc818e1ff..a5e06e7cff 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -4347,7 +4347,28 @@ void process_money_balance_reply( LLMessageSystem* msg, void** ) // *TODO: Translate LLSD args; args["MESSAGE"] = desc; - LLNotificationsUtil::add("SystemMessage", args); + + // this is a marker to retrieve avatar name from server message: + // " paid you L$" + const std::string marker = "paid you L$"; + + // extract avatar name from system message + std::string name = desc.substr(0, desc.find(marker, 0)); + LLStringUtil::trim(name); + + // if name extracted and name cache contains avatar id send loggable notification + LLUUID from_id; + if(name.size() > 0 && gCacheName->getUUID(name, from_id)) + { + args["NAME"] = name; + LLSD payload; + payload["from_id"] = from_id; + LLNotificationsUtil::add("PaymentRecived", args, payload); + } + else + { + LLNotificationsUtil::add("SystemMessage", args); + } // Once the 'recent' container gets large enough, chop some // off the beginning. diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index cb0614797a..254c8a0f21 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4609,6 +4609,13 @@ Please select at least one type of content to search (PG, Mature, or Adult). [MESSAGE] + +[MESSAGE] + + Date: Tue, 1 Dec 2009 13:17:31 +0000 Subject: EXT-2765: Added help IDs for tabs in the Places sidebar. The issue was that the widgets for this panel are not built solely from XUI. There's code in LLPanelPlaces::changeInventory() that creates the actual My Inventory and Teleport History panels. Adding help_topic strings to the relevant XUI files for the LLLandmarksPanel and LLTeleportHistoryPanel classes fixes this issue. --- indra/newview/skins/default/xui/en/panel_landmarks.xml | 1 + indra/newview/skins/default/xui/en/panel_teleport_history.xml | 1 + 2 files changed, 2 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index 4b91dc6294..c52b0c83d0 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -6,6 +6,7 @@ layout="topleft" left="0" width="380" + help_topic="panel_landmarks" border="true" background_visible="true" bg_alpha_color="DkGray2" diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history.xml b/indra/newview/skins/default/xui/en/panel_teleport_history.xml index 01204ba779..32fc9fce01 100644 --- a/indra/newview/skins/default/xui/en/panel_teleport_history.xml +++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml @@ -1,5 +1,6 @@ Date: Tue, 1 Dec 2009 15:55:24 +0200 Subject: fix for normal EXT-2820 [BSI] Functionality loss: Can't open groups from Resident's profile --HG-- branch : product-engine --- indra/newview/llgroupactions.cpp | 6 +++--- indra/newview/llpanelavatar.cpp | 11 +++++------ indra/newview/llpanelavatar.h | 4 ++-- 3 files changed, 10 insertions(+), 11 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index 6fe8ed0e4d..99b58f2170 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -100,9 +100,9 @@ public: } if (tokens[1].asString() == "inspect") { - LLSD key; - key["group_id"] = group_id; - LLFloaterReg::showInstance("inspect_group", key); + if (group_id.isNull()) + return true; + LLGroupActions::show(group_id); return true; } return false; diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 97c1e96175..c2bf881a60 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -522,20 +522,19 @@ void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_g for(; it_end != it; ++it) { LLAvatarGroups::LLGroupData group_data = *it; - - // Check if there is no duplicates for this group - if (std::find(mGroups.begin(), mGroups.end(), group_data.group_name) == mGroups.end()) - mGroups.push_back(group_data.group_name); + mGroups[group_data.group_name] = group_data.group_id; } // Creating string, containing group list std::string groups = ""; - for (group_list_t::const_iterator it = mGroups.begin(); it != mGroups.end(); ++it) + for (group_map_t::iterator it = mGroups.begin(); it != mGroups.end(); ++it) { if (it != mGroups.begin()) groups += ", "; - groups += *it; + + std::string group_url="[secondlife:///app/group/" + it->second.asString() + "/about " + it->first + "]"; + groups += group_url; } childSetValue("sl_groups", groups); diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index f54aeee4eb..b19c5cca49 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -192,8 +192,8 @@ protected: private: - typedef std::list group_list_t; - group_list_t mGroups; + typedef std::map< std::string,LLUUID> group_map_t; + group_map_t mGroups; LLToggleableMenu* mProfileMenu; }; -- cgit v1.2.3 From 176f29106de904433d62530b00df05a23c21eb8c Mon Sep 17 00:00:00 2001 From: Dmitry Zaporozhan Date: Tue, 1 Dec 2009 16:16:21 +0200 Subject: Workaround for major bug EXT-2879 - Only 'Online' accordion is present in the People panel / Friends tab. --HG-- branch : product-engine --- indra/newview/llviewerinventory.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d0ae5d1e38..f9e1a94def 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -509,7 +509,10 @@ bool LLViewerInventoryCategory::fetchDescendents() // This comes from LLInventoryFilter from llfolderview.h U32 sort_order = gSavedSettings.getU32("InventorySortOrder") & 0x1; - std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents"); + // *NOTE + // Temporary workaround for bug EXT-2879, see ticket for details. + // Commented gAgent.getRegion()->getCapability in order to use the old system. + std::string url;//= gAgent.getRegion()->getCapability("WebFetchInventoryDescendents"); if (!url.empty()) //Capability found. Build up LLSD and use it. { -- cgit v1.2.3 From cf3d40462e3c0421884a098505413c00f9004e6a Mon Sep 17 00:00:00 2001 From: Yuri Chebotarev Date: Tue, 1 Dec 2009 16:53:15 +0200 Subject: fix for normal EXT-1713 Nearby Chat: Objects have tooltips (???)(???) --HG-- branch : product-engine --- indra/newview/llavatariconctrl.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 8f3eba98a6..44cbbbb6b2 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -303,5 +303,9 @@ void LLAvatarIconCtrl::nameUpdatedCallback( { setToolTip(mFirstName + " " + mLastName); } + else + { + setToolTip(std::string("")); + } } } -- cgit v1.2.3 From f5e64315e27877e994b755d0de9d35dde0ccc674 Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Tue, 1 Dec 2009 17:04:47 +0200 Subject: Work on EXT-2985 (Implement Avaline calls processing in Voice Control Panel) -- updated reaction to accepting incoming call: added session URI argument. For now avaline caller is shown in the voice controls. --HG-- branch : product-engine --- indra/newview/llimview.cpp | 3 ++- indra/newview/llimview.h | 9 +++++++-- indra/newview/llvoicechannel.cpp | 6 ++++++ 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index be719c0a78..c5c412d4ee 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -1348,7 +1348,8 @@ void LLIncomingCallDialog::processCallResponse(S32 response) session_id = gIMMgr->addP2PSession( mPayload["session_name"].asString(), mPayload["caller_id"].asUUID(), - mPayload["session_handle"].asString()); + mPayload["session_handle"].asString(), + mPayload["session_uri"].asString()); if (voice) { diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 40e3a8fb69..b2d3c6b921 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -277,11 +277,16 @@ public: const LLUUID& other_participant_id, const LLDynamicArray& ids); - // Creates a P2P session with the requisite handle for responding to voice calls + /** + * Creates a P2P session with the requisite handle for responding to voice calls. + * + * @param caller_uri - sip URI of caller. It should be always be passed into the method to avoid + * incorrect working of LLVoiceChannel instances. See EXT-2985. + */ LLUUID addP2PSession(const std::string& name, const LLUUID& other_participant_id, const std::string& voice_session_handle, - const std::string& caller_uri = LLStringUtil::null); + const std::string& caller_uri); /** * Leave the session with session id. Send leave session notification diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 3554528d19..a0396bc790 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -750,6 +750,8 @@ LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const std::string mReceivedCall(FALSE) { // make sure URI reflects encoded version of other user's agent id + // *NOTE: in case of Avaline call generated SIP URL will be incorrect. + // But it will be overridden in LLVoiceChannelP2P::setSessionHandle() called when agent accepts call setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id)); } @@ -867,6 +869,10 @@ void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::s } else { + LL_WARNS("Voice") << "incoming SIP URL is not provided. Channel may not work properly." << LL_ENDL; + // In case of incoming AvaLine call generated URI will be differ from original one. + // This is because Avatar-2-Avatar URI is based on avatar UUID but Avaline is not. + // See LLVoiceClient::sessionAddedEvent() -> setUUIDFromStringHash() setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID)); } -- cgit v1.2.3 From 32887cdc5407c7ced2d030cc8423fb0ab688170f Mon Sep 17 00:00:00 2001 From: Sergey Borushevsky Date: Tue, 1 Dec 2009 17:13:35 +0200 Subject: Implemented normal task EXT-2750 (Add context menu for group and ad-hoc chiclet) Added menu to ad-hoc chiclet, which contains one 'End Session' item. --HG-- branch : product-engine --- indra/newview/llchiclet.cpp | 41 ++++++++++++++++++++++ indra/newview/llchiclet.h | 11 ++++++ .../skins/default/xui/en/menu_imchiclet_adhoc.xml | 19 ++++++++++ 3 files changed, 71 insertions(+) create mode 100644 indra/newview/skins/default/xui/en/menu_imchiclet_adhoc.xml (limited to 'indra/newview') diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index f41e326dd0..d533743cfc 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -595,8 +595,49 @@ void LLAdHocChiclet::setCounter(S32 counter) setShowNewMessagesIcon(counter); } +void LLAdHocChiclet::createPopupMenu() +{ + if(mPopupMenu) + { + llwarns << "Menu already exists" << llendl; + return; + } + if(getSessionId().isNull()) + { + return; + } + + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + registrar.add("IMChicletMenu.Action", boost::bind(&LLAdHocChiclet::onMenuItemClicked, this, _2)); + + mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile + ("menu_imchiclet_adhoc.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +} + +void LLAdHocChiclet::onMenuItemClicked(const LLSD& user_data) +{ + std::string level = user_data.asString(); + LLUUID group_id = getSessionId(); + + if("end" == level) + { + LLGroupActions::endIM(group_id); + } +} + BOOL LLAdHocChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) { + if(!mPopupMenu) + { + createPopupMenu(); + } + + if (mPopupMenu) + { + mPopupMenu->arrangeAndClear(); + LLMenuGL::showPopup(this, mPopupMenu, x, y); + } + return TRUE; } diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 1ea141e6c4..ed4bcbc6ac 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -517,6 +517,17 @@ protected: LLAdHocChiclet(const Params& p); friend class LLUICtrlFactory; + /** + * Creates chiclet popup menu. Will create AdHoc Chat menu + * based on other participant's id. + */ + virtual void createPopupMenu(); + + /** + * Processes clicks on chiclet popup menu. + */ + virtual void onMenuItemClicked(const LLSD& user_data); + /** * Displays popup menu. */ diff --git a/indra/newview/skins/default/xui/en/menu_imchiclet_adhoc.xml b/indra/newview/skins/default/xui/en/menu_imchiclet_adhoc.xml new file mode 100644 index 0000000000..eb5e31b57d --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_imchiclet_adhoc.xml @@ -0,0 +1,19 @@ + + + + + + -- cgit v1.2.3 From 4c8b40a8f39645834ef3547dd903cfc9d0449bf5 Mon Sep 17 00:00:00 2001 From: "Justin C. Rounds (Chuck)" Date: Tue, 1 Dec 2009 10:54:00 -0500 Subject: Changed UISpinctrlBtnHeight to match art. http://jira.secondlife.com/browse/EXT-1621 http://jira.secondlife.com/browse/EXT-1669 http://jira.secondlife.com/browse/EXT-1671 --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b0f782622c..63e17058e8 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9722,7 +9722,7 @@ Type S32 Value - 8 + 11 UISpinctrlBtnWidth -- cgit v1.2.3 From 573f146b7b69e70cd1e509cf50a6253355aa70be Mon Sep 17 00:00:00 2001 From: Yuri Chebotarev Date: Tue, 1 Dec 2009 17:54:38 +0200 Subject: fix normal EXT-2937 Nearby Chat window has layout issues --HG-- branch : product-engine --- indra/newview/skins/default/xui/en/floater_nearby_chat.xml | 8 +++++--- indra/newview/skins/default/xui/en/panel_chat_header.xml | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml index d8534bfe0b..0856049374 100644 --- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml @@ -22,13 +22,15 @@ bg_readonly_color="ChatHistoryBgColor" bg_writeable_color="ChatHistoryBgColor" follows="all" - left="1" + left="5" top="20" layout="topleft" - height="280" + height="275" name="chat_history" parse_highlights="true" text_color="ChatHistoryTextColor" text_readonly_color="ChatHistoryTextColor" - width="320" /> + right_widget_pad="5" + left_widget_pad="0" + width="315" /> diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml index c1090a1686..9cb765ae93 100644 --- a/indra/newview/skins/default/xui/en/panel_chat_header.xml +++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml @@ -8,7 +8,7 @@ label="im_header" layout="topleft" name="im_header" - width="300"> + width="310"> Date: Tue, 1 Dec 2009 18:17:38 +0200 Subject: implemented normal task EXT-2471 llLoadURL should be handled also by Chiclet subsystem along with Notificaton subsystem --HG-- branch : product-engine --- indra/newview/llscriptfloater.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index c58caf9c60..7c4f3d3608 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -41,6 +41,7 @@ #include "llscreenchannel.h" #include "lltoastnotifypanel.h" #include "llviewerwindow.h" +#include "llimfloater.h" ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -212,6 +213,8 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) mNotifications.insert(std::make_pair(object_id, nd)); LLBottomTray::getInstance()->getChicletPanel()->createChiclet(object_id); + + toggleScriptFloater(object_id); } void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id) -- cgit v1.2.3 From dd262a7a3682c80d67908ab4b8f31660699e85e9 Mon Sep 17 00:00:00 2001 From: Igor Borovkov Date: Tue, 1 Dec 2009 19:01:42 +0200 Subject: implemented EXT-2582 (Save IM chat history as plain text file) updated 1.23 chat log format - in multilined messages subsequent lines are prepended with a space multilined messages of an old format are not supported, each line is considered as a separate message the parser depends on current used date and time format --HG-- branch : product-engine --- indra/newview/llimview.cpp | 45 ++++++-- indra/newview/llimview.h | 2 + indra/newview/lllogchat.cpp | 250 ++++++++++++++++++++++++++++++++++++++++++-- indra/newview/lllogchat.h | 55 ++++++++++ 4 files changed, 336 insertions(+), 16 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index c5c412d4ee..5481ca97cd 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -83,19 +83,16 @@ #include "llfirstuse.h" #include "llagentui.h" +const static std::string IM_TIME("time"); +const static std::string IM_TEXT("message"); +const static std::string IM_FROM("from"); +const static std::string IM_FROM_ID("from_id"); + // // Globals // LLIMMgr* gIMMgr = NULL; -// -// Statics -// -// *FIXME: make these all either UIStrings or Strings - -const static std::string IM_SEPARATOR(": "); - - void toast_callback(const LLSD& msg){ // do not show toast in busy mode or it goes from agent if (gAgent.getBusy() || gAgent.getID() == msg["from_id"]) @@ -193,7 +190,13 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& } if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) - LLLogChat::loadHistory(mName, &chatFromLogFile, (void *)this); + { + std::list chat_history; + + //involves parsing of a chat history + LLLogChat::loadAllHistory(mName, chat_history); + addMessagesFromHistory(chat_history); + } } void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) @@ -303,6 +306,30 @@ void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& f } } +void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list& history) +{ + std::list::const_iterator it = history.begin(); + while (it != history.end()) + { + const LLSD& msg = *it; + + std::string from = msg[IM_FROM]; + LLUUID from_id = LLUUID::null; + if (msg[IM_FROM_ID].isUndefined()) + { + gCacheName->getUUID(from, from_id); + } + + + std::string timestamp = msg[IM_TIME]; + std::string text = msg[IM_TEXT]; + + addMessage(from, from_id, text, timestamp); + + it++; + } +} + void LLIMModel::LLIMSession::chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata) { if (!userdata) return; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index b2d3c6b921..66f92c83a5 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -60,6 +60,8 @@ public: virtual ~LLIMSession(); void sessionInitReplyReceived(const LLUUID& new_session_id); + + void addMessagesFromHistory(const std::list& history); void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time); void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 9caa863bd8..33fd3e3bf1 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -32,15 +32,59 @@ #include "llviewerprecompiledheaders.h" +#include "llagent.h" +#include "llagentui.h" #include "lllogchat.h" -#include "llappviewer.h" #include "llfloaterchat.h" #include "lltrans.h" #include "llviewercontrol.h" -#include "llsdserialize.h" + +#include +#include +#include +#include const S32 LOG_RECALL_SIZE = 2048; +const static std::string IM_TIME("time"); +const static std::string IM_TEXT("message"); +const static std::string IM_FROM("from"); +const static std::string IM_FROM_ID("from_id"); +const static std::string IM_SEPARATOR(": "); + +const static std::string NEW_LINE("\n"); +const static std::string NEW_LINE_SPACE_PREFIX("\n "); +const static std::string TWO_SPACES(" "); +const static std::string MULTI_LINE_PREFIX(" "); + +//viewer 1.23 may have used "You" for Agent's entries +const static std::string YOU("You"); + +/** + * Chat log lines - timestamp and name are optional but message text is mandatory. + * + * Typical plain text chat log lines: + * + * SuperCar: You aren't the owner + * [2:59] SuperCar: You aren't the owner + * [2009/11/20 3:00] SuperCar: You aren't the owner + * Katar Ivercourt is Offline + * [3:00] Katar Ivercourt is Offline + * [2009/11/20 3:01] Corba ProductEngine is Offline + */ +const static boost::regex TIMESTAMP_AND_STUFF("^(\\[\\d{4}/\\d{1,2}/\\d{1,2}\\s+\\d{1,2}:\\d{2}\\]\\s+|\\[\\d{1,2}:\\d{2}\\]\\s+)?(.*)$"); + +/** + * Regular expression suitable to match names like + * "You", "Second Life", "Igor ProductEngine", "Object", "Mega House" + */ +const static boost::regex NAME_AND_TEXT("(You:|Second Life:|[^\\s:]+\\s*[:]{1}|\\S+\\s+[^\\s:]+[:]{1})?(\\s*)(.*)"); + +const static int IDX_TIMESTAMP = 1; +const static int IDX_STUFF = 2; +const static int IDX_NAME = 1; +const static int IDX_TEXT = 3; + //static std::string LLLogChat::makeLogFileName(std::string filename) { @@ -118,7 +162,7 @@ void LLLogChat::saveHistory(const std::string& filename, item["from_id"] = from_id; item["message"] = line; - file << LLSDOStreamer (item) << std::endl; + file << LLChatLogFormatter(item) << std::endl; file.close(); } @@ -154,9 +198,6 @@ void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLi } } - // the parser's destructor is protected so we cannot create in the stack. - LLPointer parser = new LLSDNotationParser(); - while ( fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr) ) { len = strlen(buffer) - 1; /*Flawfinder: ignore*/ @@ -167,7 +208,8 @@ void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLi LLSD item; std::string line(buffer); std::istringstream iss(line); - if (parser->parse(iss, item, line.length()) == LLSDParser::PARSE_FAILURE) + + if (!LLChatLogParser::parse(line, item)) { item["message"] = line; callback(LOG_LINE, item, userdata); @@ -187,3 +229,197 @@ void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLi fclose(fptr); } } + +void append_to_last_message(std::list& messages, const std::string& line) +{ + if (!messages.size()) return; + + std::string im_text = messages.back()[IM_TEXT].asString(); + im_text.append(line); + messages.back()[IM_TEXT] = im_text; +} + +void LLLogChat::loadAllHistory(const std::string& session_name, std::list& messages) +{ + if (session_name.empty()) + { + llwarns << "Session name is Empty!" << llendl; + return ; + } + + LLFILE* fptr = LLFile::fopen(makeLogFileName(session_name), "r"); /*Flawfinder: ignore*/ + if (!fptr) return; //No previous conversation with this name. + + char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/ + char *bptr; + S32 len; + bool firstline = TRUE; + + if (fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END)) + { //File is smaller than recall size. Get it all. + firstline = FALSE; + if (fseek(fptr, 0, SEEK_SET)) + { + fclose(fptr); + return; + } + } + + while (fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr)) + { + len = strlen(buffer) - 1; /*Flawfinder: ignore*/ + for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--) *bptr='\0'; + + if (firstline) + { + firstline = FALSE; + continue; + } + + std::string line(buffer); + + //updated 1.23 plaint text log format requires a space added before subsequent lines in a multilined message + if (' ' == line[0]) + { + line.erase(0, MULTI_LINE_PREFIX.length()); + append_to_last_message(messages, '\n' + line); + } + else if (0 == len && ('\n' == line[0] || '\r' == line[0])) + { + //to support old format's multilined messages with new lines used to divide paragraphs + append_to_last_message(messages, line); + } + else + { + LLSD item; + if (!LLChatLogParser::parse(line, item)) + { + item[IM_TEXT] = line; + } + messages.push_back(item); + } + } + fclose(fptr); +} + +//*TODO mark object's names in a special way so that they will be distinguishable form avatar name +//which are more strict by its nature (only firstname and secondname) +//Example, an object's name can be writen like "Object " +void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const +{ + if (!im.isMap()) + { + llwarning("invalid LLSD type of an instant message", 0); + return; + } + + if (im[IM_TIME].isDefined()) + { + std::string timestamp = im[IM_TIME].asString(); + boost::trim(timestamp); + ostr << '[' << timestamp << ']' << TWO_SPACES; + } + + //*TODO mark object's names in a special way so that they will be distinguishable form avatar name + //which are more strict by its nature (only firstname and secondname) + //Example, an object's name can be writen like "Object " + if (im[IM_FROM].isDefined()) + { + std::string from = im[IM_FROM].asString(); + boost::trim(from); + if (from.size()) + { + ostr << from << IM_SEPARATOR; + } + } + + if (im[IM_TEXT].isDefined()) + { + std::string im_text = im[IM_TEXT].asString(); + + //multilined text will be saved with prepended spaces + boost::replace_all(im_text, NEW_LINE, NEW_LINE_SPACE_PREFIX); + ostr << im_text; + } +} + +bool LLChatLogParser::parse(std::string& raw, LLSD& im) +{ + if (!raw.length()) return false; + + im = LLSD::emptyMap(); + + //matching a timestamp + boost::match_results matches; + if (!boost::regex_match(raw, matches, TIMESTAMP_AND_STUFF)) return false; + + bool has_timestamp = matches[IDX_TIMESTAMP].matched; + if (has_timestamp) + { + //timestamp was successfully parsed + std::string timestamp = matches[IDX_TIMESTAMP]; + boost::trim(timestamp); + timestamp.erase(0, 1); + timestamp.erase(timestamp.length()-1, 1); + im[IM_TIME] = timestamp; + } + else + { + //timestamp is optional + im[IM_TIME] = ""; + } + + bool has_stuff = matches[IDX_STUFF].matched; + if (!has_stuff) + { + return false; //*TODO should return false or not? + } + + //matching a name and a text + std::string stuff = matches[IDX_STUFF]; + boost::match_results name_and_text; + if (!boost::regex_match(stuff, name_and_text, NAME_AND_TEXT)) return false; + + bool has_name = name_and_text[IDX_NAME].matched; + std::string name = name_and_text[IDX_NAME]; + + //we don't need a name/text separator + if (has_name && name.length() && name[name.length()-1] == ':') + { + name.erase(name.length()-1, 1); + } + + if (!has_name || name == SYSTEM_FROM) + { + //name is optional too + im[IM_FROM] = SYSTEM_FROM; + im[IM_FROM_ID] = LLUUID::null; + } + + if (!has_name) + { + //text is mandatory + im[IM_TEXT] = stuff; + return true; //parse as a message from Second Life + } + + bool has_text = name_and_text[IDX_TEXT].matched; + if (!has_text) return false; + + //for parsing logs created in very old versions of a viewer + if (name == "You") + { + std::string agent_name; + LLAgentUI::buildFullname(agent_name); + im[IM_FROM] = agent_name; + im[IM_FROM_ID] = gAgentID; + } + else + { + im[IM_FROM] = name; + } + + + im[IM_TEXT] = name_and_text[IDX_TEXT]; + return true; //parsed name and message text, maybe have a timestamp too +} diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index e252cd7d41..3d3f5c4458 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -51,11 +51,66 @@ public: const LLUUID& from_id, const std::string& line); + /** @deprecated @see loadAllHistory() */ static void loadHistory(const std::string& filename, void (*callback)(ELogLineType, const LLSD&, void*), void* userdata); + + static void loadAllHistory(const std::string& session_name, std::list& messages); private: static std::string cleanFileName(std::string filename); }; +/** + * Formatter for the plain text chat log files + */ +class LLChatLogFormatter +{ +public: + LLChatLogFormatter(const LLSD& im) : mIM(im) {} + virtual ~LLChatLogFormatter() {}; + + friend std::ostream& operator<<(std::ostream& str, const LLChatLogFormatter& formatter) + { + formatter.format(formatter.mIM, str); + return str; + } + +protected: + + /** + * Format an instant message to a stream + * Timestamps and sender names are required + * New lines of multilined messages are prepended with a space + */ + void format(const LLSD& im, std::ostream& ostr) const; + + LLSD mIM; +}; + +/** + * Parser for the plain text chat log files + */ +class LLChatLogParser +{ +public: + + /** + * Parse a line from the plain text chat log file + * General plain text log format is like: "[timestamp] [name]: [message]" + * [timestamp] and [name] are optional + * Examples of plain text chat log lines: + * "[2009/11/20 2:53] Igor ProductEngine: howdy" + * "Igor ProductEngine: howdy" + * "Dserduk ProductEngine is Online" + * + * @return false if failed to parse mandatory data - message text + */ + static bool parse(std::string& raw, LLSD& im); + +protected: + LLChatLogParser(); + virtual ~LLChatLogParser() {}; +}; + #endif -- cgit v1.2.3 From e8ec98c3075bf1086e872fdd24788de34ff4ad45 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 1 Dec 2009 12:06:31 -0500 Subject: line ending fixes --HG-- branch : avatar-pipeline --- indra/newview/llimfloatercontainer.cpp | 192 +- indra/newview/llimfloatercontainer.h | 122 +- indra/newview/llinventorybridge.cpp | 10410 +++++++++++++++---------------- 3 files changed, 5362 insertions(+), 5362 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 6e4b3ae214..2d7333f7e4 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -1,96 +1,96 @@ -/** - * @file llimfloatercontainer.cpp - * @brief Multifloater containing active IM sessions in separate tab container tabs - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - - -#include "llviewerprecompiledheaders.h" - -#include "llimfloatercontainer.h" - -// -// LLIMFloaterContainer -// -LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) -: LLMultiFloater(seed), - mActiveVoiceFloater(NULL) -{ - mAutoResize = FALSE; -} - -LLIMFloaterContainer::~LLIMFloaterContainer() -{ -} - -BOOL LLIMFloaterContainer::postBuild() -{ - // Do not call base postBuild to not connect to mCloseSignal to not close all floaters via Close button - // mTabContainer will be initialized in LLMultiFloater::addChild() - return TRUE; -} - -void LLIMFloaterContainer::onOpen(const LLSD& key) -{ - LLMultiFloater::onOpen(key); -/* - if (key.isDefined()) - { - LLIMFloater* im_floater = LLIMFloater::findInstance(key.asUUID()); - if (im_floater) - { - im_floater->openFloater(); - } - } -*/ -} - -void LLIMFloaterContainer::addFloater(LLFloater* floaterp, - BOOL select_added_floater, - LLTabContainer::eInsertionPoint insertion_point) -{ - if(!floaterp) return; - - // already here - if (floaterp->getHost() == this) - { - openFloater(floaterp->getKey()); - return; - } - - LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); - - // make sure active voice icon shows up for new tab - if (floaterp == mActiveVoiceFloater) - { - mTabContainer->setTabImage(floaterp, "active_voice_tab.tga"); - } -} - -// EOF +/** + * @file llimfloatercontainer.cpp + * @brief Multifloater containing active IM sessions in separate tab container tabs + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" + +#include "llimfloatercontainer.h" + +// +// LLIMFloaterContainer +// +LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) +: LLMultiFloater(seed), + mActiveVoiceFloater(NULL) +{ + mAutoResize = FALSE; +} + +LLIMFloaterContainer::~LLIMFloaterContainer() +{ +} + +BOOL LLIMFloaterContainer::postBuild() +{ + // Do not call base postBuild to not connect to mCloseSignal to not close all floaters via Close button + // mTabContainer will be initialized in LLMultiFloater::addChild() + return TRUE; +} + +void LLIMFloaterContainer::onOpen(const LLSD& key) +{ + LLMultiFloater::onOpen(key); +/* + if (key.isDefined()) + { + LLIMFloater* im_floater = LLIMFloater::findInstance(key.asUUID()); + if (im_floater) + { + im_floater->openFloater(); + } + } +*/ +} + +void LLIMFloaterContainer::addFloater(LLFloater* floaterp, + BOOL select_added_floater, + LLTabContainer::eInsertionPoint insertion_point) +{ + if(!floaterp) return; + + // already here + if (floaterp->getHost() == this) + { + openFloater(floaterp->getKey()); + return; + } + + LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); + + // make sure active voice icon shows up for new tab + if (floaterp == mActiveVoiceFloater) + { + mTabContainer->setTabImage(floaterp, "active_voice_tab.tga"); + } +} + +// EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 10cde56c6e..ead7cf4730 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -1,61 +1,61 @@ -/** - * @file llimfloatercontainer.h - * @brief Multifloater containing active IM sessions in separate tab container tabs - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLIMFLOATERCONTAINER_H -#define LL_LLIMFLOATERCONTAINER_H - -#include "llfloater.h" -#include "llmultifloater.h" - -class LLTabContainer; - -class LLIMFloaterContainer : public LLMultiFloater -{ -public: - LLIMFloaterContainer(const LLSD& seed); - virtual ~LLIMFloaterContainer(); - - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onOpen(const LLSD& key); - - /*virtual*/ void addFloater(LLFloater* floaterp, - BOOL select_added_floater, - LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); - - static LLFloater* getCurrentVoiceFloater(); - -protected: - - LLFloater* mActiveVoiceFloater; -}; - -#endif // LL_LLIMFLOATERCONTAINER_H +/** + * @file llimfloatercontainer.h + * @brief Multifloater containing active IM sessions in separate tab container tabs + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLIMFLOATERCONTAINER_H +#define LL_LLIMFLOATERCONTAINER_H + +#include "llfloater.h" +#include "llmultifloater.h" + +class LLTabContainer; + +class LLIMFloaterContainer : public LLMultiFloater +{ +public: + LLIMFloaterContainer(const LLSD& seed); + virtual ~LLIMFloaterContainer(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + + /*virtual*/ void addFloater(LLFloater* floaterp, + BOOL select_added_floater, + LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); + + static LLFloater* getCurrentVoiceFloater(); + +protected: + + LLFloater* mActiveVoiceFloater; +}; + +#endif // LL_LLIMFLOATERCONTAINER_H diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index fedc45b1fb..5b49ccb5df 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1,5205 +1,5205 @@ -/** - * @file llinventorybridge.cpp - * @brief Implementation of the Inventory-Folder-View-Bridge classes. - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llinventorybridge.h" - -#include "llagent.h" -#include "llagentwearables.h" -#include "llappearancemgr.h" -#include "llavataractions.h" -#include "llfloatercustomize.h" -#include "llfloaterinventory.h" -#include "llfloateropenobject.h" -#include "llfloaterreg.h" -#include "llfloaterworldmap.h" -#include "llfriendcard.h" -#include "llgesturemgr.h" -#include "llimfloater.h" -#include "llimview.h" -#include "llinventoryclipboard.h" -#include "llinventoryfunctions.h" -#include "llinventorymodel.h" -#include "llinventorypanel.h" -#include "llpreviewanim.h" -#include "llpreviewgesture.h" -#include "llpreviewtexture.h" -#include "llselectmgr.h" -#include "llsidetray.h" -#include "lltrans.h" -#include "llviewerassettype.h" -#include "llviewermessage.h" -#include "llviewerobjectlist.h" -#include "llviewerwindow.h" -#include "llvoavatarself.h" -#include "llwearablelist.h" -#include "llpaneloutfitsinventory.h" - -using namespace LLOldEvents; - -// Helpers -// bug in busy count inc/dec right now, logic is complex... do we really need it? -void inc_busy_count() -{ -// gViewerWindow->getWindow()->incBusyCount(); -// check balance of these calls if this code is changed to ever actually -// *do* something! -} -void dec_busy_count() -{ -// gViewerWindow->getWindow()->decBusyCount(); -// check balance of these calls if this code is changed to ever actually -// *do* something! -} - -// Function declarations -void wear_add_inventory_item_on_avatar(LLInventoryItem* item); -void remove_inventory_category_from_avatar(LLInventoryCategory* category); -void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id); -bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*); -bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response); - -std::string ICON_NAME[ICON_NAME_COUNT] = -{ - "Inv_Texture", - "Inv_Sound", - "Inv_CallingCard", - "Inv_CallingCard", - "Inv_Landmark", - "Inv_Landmark", - "Inv_Script", - "Inv_Clothing", - "Inv_Object", - "Inv_Object", - "Inv_Notecard", - "Inv_Skin", - "Inv_Snapshot", - - "Inv_BodyShape", - "Inv_Skin", - "Inv_Hair", - "Inv_Eye", - "Inv_Shirt", - "Inv_Pants", - "Inv_Shoe", - "Inv_Socks", - "Inv_Jacket", - "Inv_Gloves", - "Inv_Undershirt", - "Inv_Underpants", - "Inv_Skirt", - "Inv_Alpha", - "Inv_Tattoo", - - "Inv_Animation", - "Inv_Gesture", - - "inv_item_linkitem.tga", - "inv_item_linkfolder.tga" -}; - -// +=================================================+ -// | LLInvFVBridge | -// +=================================================+ - -LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) : -mUUID(uuid), mInvType(LLInventoryType::IT_NONE) -{ - mInventoryPanel = inventory->getHandle(); -} - -const std::string& LLInvFVBridge::getName() const -{ - LLInventoryObject* obj = getInventoryObject(); - if(obj) - { - return obj->getName(); - } - return LLStringUtil::null; -} - -const std::string& LLInvFVBridge::getDisplayName() const -{ - return getName(); -} - -// Folders have full perms -PermissionMask LLInvFVBridge::getPermissionMask() const -{ - - return PERM_ALL; -} - -// virtual -LLFolderType::EType LLInvFVBridge::getPreferredType() const -{ - return LLFolderType::FT_NONE; -} - - -// Folders don't have creation dates. -time_t LLInvFVBridge::getCreationDate() const -{ - return 0; -} - -// Can be destroyed (or moved to trash) -BOOL LLInvFVBridge::isItemRemovable() -{ - const LLInventoryModel* model = getInventoryModel(); - if(!model) - { - return FALSE; - } - if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) - { - return FALSE; - } - const LLInventoryObject *obj = model->getItem(mUUID); - if (obj && obj->getIsLinkType()) - { - return TRUE; - } - if (gAgentWearables.isWearingItem(mUUID)) - { - return FALSE; - } - const LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if (avatar && avatar->isWearingAttachment(mUUID)) - { - return FALSE; - } - return TRUE; -} - -// Can be moved to another folder -BOOL LLInvFVBridge::isItemMovable() const -{ - return TRUE; -} - -/*virtual*/ -/** - * @brief Adds this item into clipboard storage - */ -void LLInvFVBridge::cutToClipboard() -{ - if(isItemMovable()) - { - LLInventoryClipboard::instance().cut(mUUID); - } -} -// *TODO: make sure this does the right thing -void LLInvFVBridge::showProperties() -{ - LLSD key; - key["id"] = mUUID; - LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); - - // Disable old properties floater; this is replaced by the sidepanel. - /* - LLFloaterReg::showInstance("properties", mUUID); - */ -} - -void LLInvFVBridge::removeBatch(LLDynamicArray& batch) -{ - // Deactivate gestures when moving them into Trash - LLInvFVBridge* bridge; - LLInventoryModel* model = getInventoryModel(); - LLViewerInventoryItem* item = NULL; - LLViewerInventoryCategory* cat = NULL; - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - S32 count = batch.count(); - S32 i,j; - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); - if (item) - { - if(LLAssetType::AT_GESTURE == item->getType()) - { - LLGestureManager::instance().deactivateGesture(item->getUUID()); - } - } - } - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); - if (cat) - { - gInventory.collectDescendents( cat->getUUID(), descendent_categories, descendent_items, FALSE ); - for (j=0; jgetType()) - { - LLGestureManager::instance().deactivateGesture(descendent_items[j]->getUUID()); - } - } - } - } - removeBatchNoCheck(batch); -} - -void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray& batch) -{ - // this method moves a bunch of items and folders to the trash. As - // per design guidelines for the inventory model, the message is - // built and the accounting is performed first. After all of that, - // we call LLInventoryModel::moveObject() to move everything - // around. - LLInvFVBridge* bridge; - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLMessageSystem* msg = gMessageSystem; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - LLViewerInventoryItem* item = NULL; - LLViewerInventoryCategory* cat = NULL; - std::vector move_ids; - LLInventoryModel::update_map_t update; - bool start_new_message = true; - S32 count = batch.count(); - S32 i; - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); - if(item) - { - if(item->getParentUUID() == trash_id) continue; - move_ids.push_back(item->getUUID()); - LLPreview::hide(item->getUUID()); - --update[item->getParentUUID()]; - ++update[trash_id]; - if(start_new_message) - { - start_new_message = false; - msg->newMessageFast(_PREHASH_MoveInventoryItem); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addBOOLFast(_PREHASH_Stamp, TRUE); - } - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_ItemID, item->getUUID()); - msg->addUUIDFast(_PREHASH_FolderID, trash_id); - msg->addString("NewName", NULL); - if(msg->isSendFullFast(_PREHASH_InventoryData)) - { - start_new_message = true; - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - update.clear(); - } - } - } - if(!start_new_message) - { - start_new_message = true; - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - update.clear(); - } - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); - if(cat) - { - if(cat->getParentUUID() == trash_id) continue; - move_ids.push_back(cat->getUUID()); - --update[cat->getParentUUID()]; - ++update[trash_id]; - if(start_new_message) - { - start_new_message = false; - msg->newMessageFast(_PREHASH_MoveInventoryFolder); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addBOOL("Stamp", TRUE); - } - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID()); - msg->addUUIDFast(_PREHASH_ParentID, trash_id); - if(msg->isSendFullFast(_PREHASH_InventoryData)) - { - start_new_message = true; - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - update.clear(); - } - } - } - if(!start_new_message) - { - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - } - - // move everything. - std::vector::iterator it = move_ids.begin(); - std::vector::iterator end = move_ids.end(); - for(; it != end; ++it) - { - gInventory.moveObject((*it), trash_id); - } - - // notify inventory observers. - model->notifyObservers(); -} - -BOOL LLInvFVBridge::isClipboardPasteable() const -{ - if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) - { - return FALSE; - } - LLInventoryModel* model = getInventoryModel(); - if (!model) - { - return FALSE; - } - - const LLUUID &agent_id = gAgent.getID(); - - LLDynamicArray objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - for(S32 i = 0; i < count; i++) - { - const LLUUID &item_id = objects.get(i); - - // Can't paste folders - const LLInventoryCategory *cat = model->getCategory(item_id); - if (cat) - { - return FALSE; - } - - const LLInventoryItem *item = model->getItem(item_id); - if (item) - { - if (!item->getPermissions().allowCopyBy(agent_id)) - { - return FALSE; - } - } - } - return TRUE; -} - -BOOL LLInvFVBridge::isClipboardPasteableAsLink() const -{ - if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) - { - return FALSE; - } - const LLInventoryModel* model = getInventoryModel(); - if (!model) - { - return FALSE; - } - - LLDynamicArray objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - for(S32 i = 0; i < count; i++) - { - const LLInventoryItem *item = model->getItem(objects.get(i)); - if (item) - { - if (!LLAssetType::lookupCanLink(item->getActualType())) - { - return FALSE; - } - } - const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i)); - if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())) - { - return FALSE; - } - } - return TRUE; -} - -void hide_context_entries(LLMenuGL& menu, - const std::vector &entries_to_show, - const std::vector &disabled_entries) -{ - const LLView::child_list_t *list = menu.getChildList(); - - LLView::child_list_t::const_iterator itor; - for (itor = list->begin(); itor != list->end(); ++itor) - { - std::string name = (*itor)->getName(); - - // descend into split menus: - LLMenuItemBranchGL* branchp = dynamic_cast(*itor); - if ((name == "More") && branchp) - { - hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries); - } - - - bool found = false; - std::vector::const_iterator itor2; - for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2) - { - if (*itor2 == name) - { - found = true; - } - } - if (!found) - { - (*itor)->setVisible(FALSE); - } - else - { - (*itor)->setVisible(TRUE); - for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2) - { - if (*itor2 == name) - { - (*itor)->setEnabled(FALSE); - } - } - } - } -} - -// Helper for commonly-used entries -void LLInvFVBridge::getClipboardEntries(bool show_asset_id, - std::vector &items, - std::vector &disabled_items, U32 flags) -{ - const LLInventoryObject *obj = getInventoryObject(); - if (obj && obj->getIsLinkType()) - { - items.push_back(std::string("Find Original")); - if (LLAssetType::lookupIsLinkType(obj->getType())) - { - disabled_items.push_back(std::string("Find Original")); - } - } - else - { - items.push_back(std::string("Rename")); - if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Rename")); - } - - if (show_asset_id) - { - items.push_back(std::string("Copy Asset UUID")); - if ( (! ( isItemPermissive() || gAgent.isGodlike() ) ) - || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Copy Asset UUID")); - } - } - items.push_back(std::string("Copy Separator")); - - items.push_back(std::string("Copy")); - if (!isItemCopyable()) - { - disabled_items.push_back(std::string("Copy")); - } - } - - items.push_back(std::string("Paste")); - if (!isClipboardPasteable() || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Paste")); - } - - items.push_back(std::string("Paste As Link")); - if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Paste As Link")); - } - items.push_back(std::string("Paste Separator")); - - items.push_back(std::string("Delete")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Delete")); - } - - // If multiple items are selected, disable properties (if it exists). - if ((flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Properties")); - } -} - -void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl; - std::vector items; - std::vector disabled_items; - if(isInTrash()) - { - items.push_back(std::string("PurgeItem")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("PurgeItem")); - } - items.push_back(std::string("RestoreItem")); - } - else - { - items.push_back(std::string("Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - hide_context_entries(menu, items, disabled_items); -} - -// *TODO: remove this -BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const -{ - BOOL rv = FALSE; - - const LLInventoryObject* obj = getInventoryObject(); - - if(obj) - { - *type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType()); - if(*type == DAD_NONE) - { - return FALSE; - } - - *id = obj->getUUID(); - //object_ids.put(obj->getUUID()); - - if (*type == DAD_CATEGORY) - { - gInventory.startBackgroundFetch(obj->getUUID()); - } - - rv = TRUE; - } - - return rv; -} - -LLInventoryObject* LLInvFVBridge::getInventoryObject() const -{ - LLInventoryObject* obj = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - obj = (LLInventoryObject*)model->getObject(mUUID); - } - return obj; -} - -LLInventoryModel* LLInvFVBridge::getInventoryModel() const -{ - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); - return panel ? panel->getModel() : NULL; -} - -BOOL LLInvFVBridge::isInTrash() const -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - return model->isObjectDescendentOf(mUUID, trash_id); -} - -BOOL LLInvFVBridge::isLinkedObjectInTrash() const -{ - if (isInTrash()) return TRUE; - - const LLInventoryObject *obj = getInventoryObject(); - if (obj && obj->getIsLinkType()) - { - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id); - } - return FALSE; -} - -BOOL LLInvFVBridge::isAgentInventory() const -{ - const LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - if(gInventory.getRootFolderID() == mUUID) return TRUE; - return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); -} - -BOOL LLInvFVBridge::isCOFFolder() const -{ - const LLInventoryModel* model = getInventoryModel(); - if(!model) return TRUE; - const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id)) - { - return TRUE; - } - return FALSE; -} - -BOOL LLInvFVBridge::isItemPermissive() const -{ - return FALSE; -} - -// static -void LLInvFVBridge::changeItemParent(LLInventoryModel* model, - LLViewerInventoryItem* item, - const LLUUID& new_parent, - BOOL restamp) -{ - if(item->getParentUUID() != new_parent) - { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1); - update.push_back(new_folder); - gInventory.accountForUpdate(update); - - LLPointer new_item = new LLViewerInventoryItem(item); - new_item->setParent(new_parent); - new_item->updateParentOnServer(restamp); - model->updateItem(new_item); - model->notifyObservers(); - } -} - -// static -void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model, - LLViewerInventoryCategory* cat, - const LLUUID& new_parent, - BOOL restamp) -{ - if(cat->getParentUUID() != new_parent) - { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1); - update.push_back(new_folder); - gInventory.accountForUpdate(update); - - LLPointer new_cat = new LLViewerInventoryCategory(cat); - new_cat->setParent(new_parent); - new_cat->updateParentOnServer(restamp); - model->updateCategory(new_cat); - model->notifyObservers(); - } -} - - -const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type) -{ - const std::string rv= LLInventoryType::lookup(inv_type); - if(rv.empty()) - { - return std::string(""); - } - return rv; -} - -LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, - LLAssetType::EType actual_asset_type, - LLInventoryType::EType inv_type, - LLInventoryPanel* inventory, - const LLUUID& uuid, - U32 flags) -{ - LLInvFVBridge* new_listener = NULL; - switch(asset_type) - { - case LLAssetType::AT_TEXTURE: - if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLTextureBridge(inventory, uuid, inv_type); - break; - - case LLAssetType::AT_SOUND: - if(!(inv_type == LLInventoryType::IT_SOUND)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLSoundBridge(inventory, uuid); - break; - - case LLAssetType::AT_LANDMARK: - if(!(inv_type == LLInventoryType::IT_LANDMARK)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLLandmarkBridge(inventory, uuid, flags); - break; - - case LLAssetType::AT_CALLINGCARD: - if(!(inv_type == LLInventoryType::IT_CALLINGCARD)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLCallingCardBridge(inventory, uuid); - break; - - case LLAssetType::AT_SCRIPT: - if(!(inv_type == LLInventoryType::IT_LSL)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLScriptBridge(inventory, uuid); - break; - - case LLAssetType::AT_OBJECT: - if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags); - break; - - case LLAssetType::AT_NOTECARD: - if(!(inv_type == LLInventoryType::IT_NOTECARD)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLNotecardBridge(inventory, uuid); - break; - - case LLAssetType::AT_ANIMATION: - if(!(inv_type == LLInventoryType::IT_ANIMATION)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLAnimationBridge(inventory, uuid); - break; - - case LLAssetType::AT_GESTURE: - if(!(inv_type == LLInventoryType::IT_GESTURE)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLGestureBridge(inventory, uuid); - break; - - case LLAssetType::AT_LSL_TEXT: - if(!(inv_type == LLInventoryType::IT_LSL)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLLSLTextBridge(inventory, uuid); - break; - - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - if(!(inv_type == LLInventoryType::IT_WEARABLE)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags); - break; - case LLAssetType::AT_CATEGORY: - if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) - { - // Create a link folder handler instead. - new_listener = new LLLinkFolderBridge(inventory, uuid); - break; - } - new_listener = new LLFolderBridge(inventory, uuid); - break; - case LLAssetType::AT_LINK: - // Only should happen for broken links. - new_listener = new LLLinkItemBridge(inventory, uuid); - break; - case LLAssetType::AT_LINK_FOLDER: - // Only should happen for broken links. - new_listener = new LLLinkItemBridge(inventory, uuid); - break; - default: - llinfos << "Unhandled asset type (llassetstorage.h): " - << (S32)asset_type << llendl; - break; - } - - if (new_listener) - { - new_listener->mInvType = inv_type; - } - - return new_listener; -} - -void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) -{ - LLInventoryCategory* cat = model->getCategory(uuid); - if (cat) - { - model->purgeDescendentsOf(uuid); - model->notifyObservers(); - } - LLInventoryObject* obj = model->getObject(uuid); - if (obj) - { - model->purgeObject(uuid); - model->notifyObservers(); - } -} - -// +=================================================+ -// | InventoryFVBridgeBuilder | -// +=================================================+ -LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type, - LLAssetType::EType actual_asset_type, - LLInventoryType::EType inv_type, - LLInventoryPanel* inventory, - const LLUUID& uuid, - U32 flags /* = 0x00 */) const -{ - return LLInvFVBridge::createBridge(asset_type, - actual_asset_type, - inv_type, - inventory, - uuid, - flags); -} - -// +=================================================+ -// | LLItemBridge | -// +=================================================+ - -void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("goto" == action) - { - gotoItem(folder); - } - if ("open" == action) - { - openItem(); - return; - } - else if ("properties" == action) - { - showProperties(); - return; - } - else if ("purge" == action) - { - purgeItem(model, mUUID); - return; - } - else if ("restoreToWorld" == action) - { - restoreToWorld(); - return; - } - else if ("restore" == action) - { - restoreItem(); - return; - } - else if ("copy_uuid" == action) - { - // Single item only - LLInventoryItem* item = model->getItem(mUUID); - if(!item) return; - LLUUID asset_id = item->getAssetUUID(); - std::string buffer; - asset_id.toString(buffer); - - gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer)); - return; - } - else if ("copy" == action) - { - copyToClipboard(); - return; - } - else if ("paste" == action) - { - // Single item only - LLInventoryItem* itemp = model->getItem(mUUID); - if (!itemp) return; - - LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID()); - if (!folder_view_itemp) return; - - folder_view_itemp->getListener()->pasteFromClipboard(); - return; - } - else if ("paste_link" == action) - { - // Single item only - LLInventoryItem* itemp = model->getItem(mUUID); - if (!itemp) return; - - LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID()); - if (!folder_view_itemp) return; - - folder_view_itemp->getListener()->pasteLinkFromClipboard(); - return; - } -} - -void LLItemBridge::selectItem() -{ - LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); - if(item && !item->isComplete()) - { - item->fetchFromServer(); - } -} - -void LLItemBridge::restoreItem() -{ - LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); - if(item) - { - LLInventoryModel* model = getInventoryModel(); - const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType())); - // do not restamp on restore. - LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE); - } -} - -void LLItemBridge::restoreToWorld() -{ - LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)getItem(); - if (itemp) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("RezRestoreToWorld"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - - msg->nextBlockFast(_PREHASH_InventoryData); - itemp->packMessage(msg); - msg->sendReliable(gAgent.getRegion()->getHost()); - } - - //Similar functionality to the drag and drop rez logic - BOOL remove_from_inventory = FALSE; - - //remove local inventory copy, sim will deal with permissions and removing the item - //from the actual inventory if its a no-copy etc - if(!itemp->getPermissions().allowCopyBy(gAgent.getID())) - { - remove_from_inventory = TRUE; - } - - // Check if it's in the trash. (again similar to the normal rez logic) - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id)) - { - remove_from_inventory = TRUE; - } - - if(remove_from_inventory) - { - gInventory.deleteObject(itemp->getUUID()); - gInventory.notifyObservers(); - } -} - -void LLItemBridge::gotoItem(LLFolderView *folder) -{ - LLInventoryObject *obj = getInventoryObject(); - if (obj && obj->getIsLinkType()) - { - LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel(); - if (active_panel) - { - active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO); - } - } -} - -LLUIImagePtr LLItemBridge::getIcon() const -{ - return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]); -} - -PermissionMask LLItemBridge::getPermissionMask() const -{ - LLViewerInventoryItem* item = getItem(); - PermissionMask perm_mask = 0; - if(item) - { - BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); - BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); - BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, - gAgent.getID()); - - if (copy) perm_mask |= PERM_COPY; - if (mod) perm_mask |= PERM_MODIFY; - if (xfer) perm_mask |= PERM_TRANSFER; - - } - return perm_mask; -} - -const std::string& LLItemBridge::getDisplayName() const -{ - if(mDisplayName.empty()) - { - buildDisplayName(getItem(), mDisplayName); - } - return mDisplayName; -} - -void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) -{ - if(item) - { - name.assign(item->getName()); - } - else - { - name.assign(LLStringUtil::null); - } -} - -LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const -{ - U8 font = LLFontGL::NORMAL; - - if( gAgentWearables.isWearingItem( mUUID ) ) - { - // llinfos << "BOLD" << llendl; - font |= LLFontGL::BOLD; - } - - const LLViewerInventoryItem* item = getItem(); - if (item && item->getIsLinkType()) - { - font |= LLFontGL::ITALIC; - } - return (LLFontGL::StyleFlags)font; -} - -std::string LLItemBridge::getLabelSuffix() const -{ - // String table is loaded before login screen and inventory items are - // loaded after login, so LLTrans should be ready. - static std::string NO_COPY =LLTrans::getString("no_copy"); - static std::string NO_MOD = LLTrans::getString("no_modify"); - static std::string NO_XFER = LLTrans::getString("no_transfer"); - static std::string LINK = LLTrans::getString("link"); - static std::string BROKEN_LINK = LLTrans::getString("broken_link"); - std::string suffix; - LLInventoryItem* item = getItem(); - if(item) - { - // it's a bit confusing to put nocopy/nomod/etc on calling cards. - if(LLAssetType::AT_CALLINGCARD != item->getType() - && item->getPermissions().getOwner() == gAgent.getID()) - { - BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType()); - if (broken_link) return BROKEN_LINK; - - BOOL link = item->getIsLinkType(); - if (link) return LINK; - - BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); - if (!copy) - { - suffix += NO_COPY; - } - BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); - if (!mod) - { - suffix += NO_MOD; - } - BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, - gAgent.getID()); - if (!xfer) - { - suffix += NO_XFER; - } - } - } - return suffix; -} - -time_t LLItemBridge::getCreationDate() const -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - return item->getCreationDate(); - } - return 0; -} - - -BOOL LLItemBridge::isItemRenameable() const -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - // (For now) Don't allow calling card rename since that may confuse users as to - // what the calling card points to. - if (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD) - { - return FALSE; - } - return (item->getPermissions().allowModifyBy(gAgent.getID())); - } - return FALSE; -} - -BOOL LLItemBridge::renameItem(const std::string& new_name) -{ - if(!isItemRenameable()) - return FALSE; - LLPreview::dirty(mUUID); - LLInventoryModel* model = getInventoryModel(); - if(!model) - return FALSE; - LLViewerInventoryItem* item = getItem(); - if(item && (item->getName() != new_name)) - { - LLPointer new_item = new LLViewerInventoryItem(item); - new_item->rename(new_name); - buildDisplayName(new_item, mDisplayName); - new_item->updateServer(FALSE); - model->updateItem(new_item); - - model->notifyObservers(); - } - // return FALSE because we either notified observers (& therefore - // rebuilt) or we didn't update. - return FALSE; -} - - -BOOL LLItemBridge::removeItem() -{ - if(!isItemRemovable()) - { - return FALSE; - } - // move it to the trash - LLPreview::hide(mUUID, TRUE); - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - LLViewerInventoryItem* item = getItem(); - - // if item is not already in trash - if(item && !model->isObjectDescendentOf(mUUID, trash_id)) - { - // move to trash, and restamp - LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE); - // delete was successful - return TRUE; - } - else - { - // tried to delete already item in trash (should purge?) - return FALSE; - } -} - -BOOL LLItemBridge::isItemCopyable() const -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - // can't copy worn objects. DEV-15183 - LLVOAvatarSelf *avatarp = gAgent.getAvatarObject(); - if( !avatarp ) - { - return FALSE; - } - - if(avatarp->isWearingAttachment(mUUID)) - { - return FALSE; - } - - // All items can be copied, not all can be pasted. - // The only time an item can't be copied is if it's a link - // return (item->getPermissions().allowCopyBy(gAgent.getID())); - if (item->getIsLinkType()) - { - return FALSE; - } - return TRUE; - } - return FALSE; -} -BOOL LLItemBridge::copyToClipboard() const -{ - if(isItemCopyable()) - { - LLInventoryClipboard::instance().add(mUUID); - return TRUE; - } - return FALSE; -} - -LLViewerInventoryItem* LLItemBridge::getItem() const -{ - LLViewerInventoryItem* item = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - item = (LLViewerInventoryItem*)model->getItem(mUUID); - } - return item; -} - -BOOL LLItemBridge::isItemPermissive() const -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - U32 mask = item->getPermissions().getMaskBase(); - if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) - { - return TRUE; - } - } - return FALSE; -} - -// +=================================================+ -// | LLFolderBridge | -// +=================================================+ - -LLFolderBridge* LLFolderBridge::sSelf=NULL; - -// Can be moved to another folder -BOOL LLFolderBridge::isItemMovable() const -{ - LLInventoryObject* obj = getInventoryObject(); - if(obj) - { - return (!LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType())); - } - return FALSE; -} - -void LLFolderBridge::selectItem() -{ -} - - -// Iterate through a folder's children to determine if -// all the children are removable. -class LLIsItemRemovable : public LLFolderViewFunctor -{ -public: - LLIsItemRemovable() : mPassed(TRUE) {} - virtual void doFolder(LLFolderViewFolder* folder) - { - mPassed &= folder->getListener()->isItemRemovable(); - } - virtual void doItem(LLFolderViewItem* item) - { - mPassed &= item->getListener()->isItemRemovable(); - } - BOOL mPassed; -}; - -// Can be destroyed (or moved to trash) -BOOL LLFolderBridge::isItemRemovable() -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) - { - return FALSE; - } - - if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) - { - return FALSE; - } - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( !avatar ) - { - return FALSE; - } - - LLInventoryCategory* category = model->getCategory(mUUID); - if( !category ) - { - return FALSE; - } - // Allow protected types to be removed, but issue a warning. - /* - if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) - { - return FALSE; - } - */ - - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); - LLFolderViewFolder* folderp = dynamic_cast(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL); - if (folderp) - { - LLIsItemRemovable folder_test; - folderp->applyFunctorToChildren(folder_test); - if (!folder_test.mPassed) - { - return FALSE; - } - } - return TRUE; -} - -BOOL LLFolderBridge::isUpToDate() const -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); - if( !category ) - { - return FALSE; - } - - return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN; -} - -BOOL LLFolderBridge::isItemCopyable() const -{ - return TRUE; -} - -BOOL LLFolderBridge::copyToClipboard() const -{ - if(isItemCopyable()) - { - LLInventoryClipboard::instance().add(mUUID); - return TRUE; - } - return FALSE; -} - -BOOL LLFolderBridge::isClipboardPasteable() const -{ - if ( ! LLInvFVBridge::isClipboardPasteable() ) - return FALSE; - - // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 - if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) ) - { - LLInventoryModel* model = getInventoryModel(); - if ( !model ) - { - return FALSE; - } - - LLDynamicArray objects; - LLInventoryClipboard::instance().retrieve(objects); - const LLViewerInventoryCategory *current_cat = getCategory(); - - // Search for the direct descendent of current Friends subfolder among all pasted items, - // and return false if is found. - for(S32 i = objects.count() - 1; i >= 0; --i) - { - const LLUUID &obj_id = objects.get(i); - if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) - { - return FALSE; - } - } - - } - return TRUE; -} - -BOOL LLFolderBridge::isClipboardPasteableAsLink() const -{ - // Check normal paste-as-link permissions - if (!LLInvFVBridge::isClipboardPasteableAsLink()) - { - return FALSE; - } - - const LLInventoryModel* model = getInventoryModel(); - if (!model) - { - return FALSE; - } - - const LLViewerInventoryCategory *current_cat = getCategory(); - if (current_cat) - { - const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat ); - const LLUUID ¤t_cat_id = current_cat->getUUID(); - LLDynamicArray objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - for(S32 i = 0; i < count; i++) - { - const LLUUID &obj_id = objects.get(i); - const LLInventoryCategory *cat = model->getCategory(obj_id); - if (cat) - { - const LLUUID &cat_id = cat->getUUID(); - // Don't allow recursive pasting - if ((cat_id == current_cat_id) || - model->isObjectDescendentOf(current_cat_id, cat_id)) - { - return FALSE; - } - } - // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 - if ( is_in_friend_folder ) - { - // If object is direct descendent of current Friends subfolder than return false. - // Note: We can't use 'const LLInventoryCategory *cat', because it may be null - // in case type of obj_id is LLInventoryItem. - if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) - { - return FALSE; - } - } - } - } - return TRUE; - -} - -BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, - BOOL drop) -{ - // This should never happen, but if an inventory item is incorrectly parented, - // the UI will get confused and pass in a NULL. - if(!inv_cat) return FALSE; - - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if(!avatar) return FALSE; - - // cannot drag categories into library - if(!isAgentInventory()) - { - return FALSE; - } - - // check to make sure source is agent inventory, and is represented there. - LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); - BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL) - && (LLToolDragAndDrop::SOURCE_AGENT == source); - - BOOL accept = FALSE; - S32 i; - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - if(is_agent_inventory) - { - const LLUUID& cat_id = inv_cat->getUUID(); - - // Is the destination the trash? - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - BOOL move_is_into_trash = (mUUID == trash_id) - || model->isObjectDescendentOf(mUUID, trash_id); - BOOL is_movable = (!LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())); - const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); - if (move_is_into_current_outfit || move_is_into_outfit) - { - // BAP - restrictions? - is_movable = true; - } - - if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)) - { - is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604 - } - - if( is_movable ) - { - gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE ); - - for( i = 0; i < descendent_categories.count(); i++ ) - { - LLInventoryCategory* category = descendent_categories[i]; - if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) - { - // ...can't move "special folders" like Textures - is_movable = FALSE; - break; - } - } - - if( is_movable ) - { - if( move_is_into_trash ) - { - for( i = 0; i < descendent_items.count(); i++ ) - { - LLInventoryItem* item = descendent_items[i]; - if( (item->getType() == LLAssetType::AT_CLOTHING) || - (item->getType() == LLAssetType::AT_BODYPART) ) - { - if( gAgentWearables.isWearingItem( item->getUUID() ) ) - { - is_movable = FALSE; // It's generally movable, but not into the trash! - break; - } - } - else - if( item->getType() == LLAssetType::AT_OBJECT ) - { - if( avatar->isWearingAttachment( item->getUUID() ) ) - { - is_movable = FALSE; // It's generally movable, but not into the trash! - break; - } - } - } - } - } - } - - - accept = is_movable - && (mUUID != cat_id) // Can't move a folder into itself - && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing - && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity - if(accept && drop) - { - // Look for any gestures and deactivate them - if (move_is_into_trash) - { - for (i = 0; i < descendent_items.count(); i++) - { - LLInventoryItem* item = descendent_items[i]; - if (item->getType() == LLAssetType::AT_GESTURE - && LLGestureManager::instance().isGestureActive(item->getUUID())) - { - LLGestureManager::instance().deactivateGesture(item->getUUID()); - } - } - } - // if target is an outfit or current outfit folder we use link - if (move_is_into_current_outfit || move_is_into_outfit) - { - if (inv_cat->getPreferredType() == LLFolderType::FT_NONE) - { - if (move_is_into_current_outfit) - { - // traverse category and add all contents to currently worn. - BOOL append = true; - LLAppearanceManager::instance().wearInventoryCategory(inv_cat, false, append); - } - else - { - // Recursively create links in target outfit. - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - gInventory.collectDescendents(inv_cat->getUUID(), cats, items, LLInventoryModel::EXCLUDE_TRASH); - LLAppearanceManager::instance().linkAll(mUUID,items,NULL); - } - } - else - { -#if SUPPORT_ENSEMBLES - // BAP - should skip if dup. - if (move_is_into_current_outfit) - { - LLAppearanceManager::instance().addEnsembleLink(inv_cat); - } - else - { - LLPointer cb = NULL; - link_inventory_item( - gAgent.getID(), - inv_cat->getUUID(), - mUUID, - inv_cat->getName(), - LLAssetType::AT_LINK_FOLDER, - cb); - } -#endif - } - } - else - { - - // Reparent the folder and restamp children if it's moving - // into trash. - LLInvFVBridge::changeCategoryParent( - model, - (LLViewerInventoryCategory*)inv_cat, - mUUID, - move_is_into_trash); - } - } - } - else if(LLToolDragAndDrop::SOURCE_WORLD == source) - { - // content category has same ID as object itself - LLUUID object_id = inv_cat->getUUID(); - LLUUID category_id = mUUID; - accept = move_inv_category_world_to_agent(object_id, category_id, drop); - } - return accept; -} - -void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv) -{ - const char* dialog = NULL; - if (object->flagScripted()) - { - dialog = "MoveInventoryFromScriptedObject"; - } - else - { - dialog = "MoveInventoryFromObject"; - } - LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv)); -} - -// Move/copy all inventory items from the Contents folder of an in-world -// object to the agent's inventory, inside a given category. -BOOL move_inv_category_world_to_agent(const LLUUID& object_id, - const LLUUID& category_id, - BOOL drop, - void (*callback)(S32, void*), - void* user_data) -{ - // Make sure the object exists. If we allowed dragging from - // anonymous objects, it would be possible to bypass - // permissions. - // content category has same ID as object itself - LLViewerObject* object = gObjectList.findObject(object_id); - if(!object) - { - llinfos << "Object not found for drop." << llendl; - return FALSE; - } - - // this folder is coming from an object, as there is only one folder in an object, the root, - // we need to collect the entire contents and handle them as a group - InventoryObjectList inventory_objects; - object->getInventoryContents(inventory_objects); - - if (inventory_objects.empty()) - { - llinfos << "Object contents not found for drop." << llendl; - return FALSE; - } - - BOOL accept = TRUE; - BOOL is_move = FALSE; - - // coming from a task. Need to figure out if the person can - // move/copy this item. - InventoryObjectList::iterator it = inventory_objects.begin(); - InventoryObjectList::iterator end = inventory_objects.end(); - for ( ; it != end; ++it) - { - // coming from a task. Need to figure out if the person can - // move/copy this item. - LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions()); - if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) - && perm.allowTransferTo(gAgent.getID()))) -// || gAgent.isGodlike()) - { - accept = TRUE; - } - else if(object->permYouOwner()) - { - // If the object cannot be copied, but the object the - // inventory is owned by the agent, then the item can be - // moved from the task to agent inventory. - is_move = TRUE; - accept = TRUE; - } - else - { - accept = FALSE; - break; - } - } - - if(drop && accept) - { - it = inventory_objects.begin(); - InventoryObjectList::iterator first_it = inventory_objects.begin(); - LLMoveInv* move_inv = new LLMoveInv; - move_inv->mObjectID = object_id; - move_inv->mCategoryID = category_id; - move_inv->mCallback = callback; - move_inv->mUserData = user_data; - - for ( ; it != end; ++it) - { - two_uuids_t two(category_id, (*it)->getUUID()); - move_inv->mMoveList.push_back(two); - } - - if(is_move) - { - // Callback called from within here. - warn_move_inventory(object, move_inv); - } - else - { - LLNotification::Params params("MoveInventoryFromObject"); - params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); - LLNotifications::instance().forceResponse(params, 0); - } - } - return accept; -} - -bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat, - LLInventoryItem* item) -{ - // Valid COF items are: - // - links to wearables (body parts or clothing) - // - links to attachments - // - links to gestures - // - links to ensemble folders - LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); // BAP - safe? - if (linked_item) - { - LLAssetType::EType type = linked_item->getType(); - return (type == LLAssetType::AT_CLOTHING || - type == LLAssetType::AT_BODYPART || - type == LLAssetType::AT_GESTURE || - type == LLAssetType::AT_OBJECT); - } - else - { - LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe? - // BAP remove AT_NONE support after ensembles are fully working? - return (linked_category && - ((linked_category->getPreferredType() == LLFolderType::FT_NONE) || - (LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType())))); - } -} - - -bool LLFindWearables::operator()(LLInventoryCategory* cat, - LLInventoryItem* item) -{ - if(item) - { - if((item->getType() == LLAssetType::AT_CLOTHING) - || (item->getType() == LLAssetType::AT_BODYPART)) - { - return TRUE; - } - } - return FALSE; -} - - - -//Used by LLFolderBridge as callback for directory recursion. -class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver -{ -public: - LLRightClickInventoryFetchObserver() : - mCopyItems(false) - { }; - LLRightClickInventoryFetchObserver(const LLUUID& cat_id, bool copy_items) : - mCatID(cat_id), - mCopyItems(copy_items) - { }; - virtual void done() - { - // we've downloaded all the items, so repaint the dialog - LLFolderBridge::staticFolderOptionsMenu(); - - gInventory.removeObserver(this); - delete this; - } - - -protected: - LLUUID mCatID; - bool mCopyItems; - -}; - -//Used by LLFolderBridge as callback for directory recursion. -class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver -{ -public: - LLRightClickInventoryFetchDescendentsObserver(bool copy_items) : mCopyItems(copy_items) {} - ~LLRightClickInventoryFetchDescendentsObserver() {} - virtual void done(); -protected: - bool mCopyItems; -}; - -void LLRightClickInventoryFetchDescendentsObserver::done() -{ - // Avoid passing a NULL-ref as mCompleteFolders.front() down to - // gInventory.collectDescendents() - if( mCompleteFolders.empty() ) - { - llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl; - dec_busy_count(); - gInventory.removeObserver(this); - delete this; - return; - } - - // What we do here is get the complete information on the items in - // the library, and set up an observer that will wait for that to - // happen. - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(mCompleteFolders.front(), - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH); - S32 count = item_array.count(); -#if 0 // HACK/TODO: Why? - // This early causes a giant menu to get produced, and doesn't seem to be needed. - if(!count) - { - llwarns << "Nothing fetched in category " << mCompleteFolders.front() - << llendl; - dec_busy_count(); - gInventory.removeObserver(this); - delete this; - return; - } -#endif - - LLRightClickInventoryFetchObserver* outfit; - outfit = new LLRightClickInventoryFetchObserver(mCompleteFolders.front(), mCopyItems); - LLInventoryFetchObserver::item_ref_t ids; - for(S32 i = 0; i < count; ++i) - { - ids.push_back(item_array.get(i)->getUUID()); - } - - // clean up, and remove this as an observer since the call to the - // outfit could notify observers and throw us into an infinite - // loop. - dec_busy_count(); - gInventory.removeObserver(this); - delete this; - - // increment busy count and either tell the inventory to check & - // call done, or add this object to the inventory for observation. - inc_busy_count(); - - // do the fetch - outfit->fetchItems(ids); - outfit->done(); //Not interested in waiting and this will be right 99% of the time. -//Uncomment the following code for laggy Inventory UI. -/* if(outfit->isEverythingComplete()) - { - // everything is already here - call done. - outfit->done(); - } - else - { - // it's all on it's way - add an observer, and the inventory - // will call done for us when everything is here. - gInventory.addObserver(outfit); - }*/ -} - - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInventoryWearObserver -// -// Observer for "copy and wear" operation to support knowing -// when the all of the contents have been added to inventory. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryCopyAndWearObserver : public LLInventoryObserver -{ -public: - LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) :mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {} - virtual ~LLInventoryCopyAndWearObserver() {} - virtual void changed(U32 mask); - -protected: - LLUUID mCatID; - int mContentsCount; - BOOL mFolderAdded; -}; - - - -void LLInventoryCopyAndWearObserver::changed(U32 mask) -{ - if((mask & (LLInventoryObserver::ADD)) != 0) - { - if (!mFolderAdded) - { - const std::set& changed_items = gInventory.getChangedIDs(); - - std::set::const_iterator id_it = changed_items.begin(); - std::set::const_iterator id_end = changed_items.end(); - for (;id_it != id_end; ++id_it) - { - if ((*id_it) == mCatID) - { - mFolderAdded = TRUE; - break; - } - } - } - - if (mFolderAdded) - { - LLViewerInventoryCategory* category = gInventory.getCategory(mCatID); - - if (NULL == category) - { - llwarns << "gInventory.getCategory(" << mCatID - << ") was NULL" << llendl; - } - else - { - if (category->getDescendentCount() == - mContentsCount) - { - gInventory.removeObserver(this); - LLAppearanceManager::instance().wearInventoryCategory(category, FALSE, TRUE); - delete this; - } - } - } - - } -} - - - -void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("open" == action) - { - openItem(); - return; - } - else if ("paste" == action) - { - pasteFromClipboard(); - return; - } - else if ("paste_link" == action) - { - pasteLinkFromClipboard(); - return; - } - else if ("properties" == action) - { - showProperties(); - return; - } - else if ("replaceoutfit" == action) - { - modifyOutfit(FALSE); - return; - } -#if SUPPORT_ENSEMBLES - else if ("wearasensemble" == action) - { - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLViewerInventoryCategory* cat = getCategory(); - if(!cat) return; - LLAppearanceManager::instance().addEnsembleLink(cat,true); - return; - } -#endif - else if ("addtooutfit" == action) - { - modifyOutfit(TRUE); - return; - } - else if ("copy" == action) - { - copyToClipboard(); - return; - } - else if ("removefromoutfit" == action) - { - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLViewerInventoryCategory* cat = getCategory(); - if(!cat) return; - - remove_inventory_category_from_avatar ( cat ); - return; - } - else if ("purge" == action) - { - purgeItem(model, mUUID); - return; - } - else if ("restore" == action) - { - restoreItem(); - return; - } -} - -void LLFolderBridge::openItem() -{ - lldebugs << "LLFolderBridge::openItem()" << llendl; - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - if(mUUID.isNull()) return; - bool fetching_inventory = model->fetchDescendentsOf(mUUID); - // Only change folder type if we have the folder contents. - if (!fetching_inventory) - { - // Disabling this for now, it's causing crash when new items are added to folders - // since folder type may change before new item item has finished processing. - // determineFolderType(); - } -} - -void LLFolderBridge::closeItem() -{ - determineFolderType(); -} - -void LLFolderBridge::determineFolderType() -{ - if (isUpToDate()) - { - LLInventoryModel* model = getInventoryModel(); - LLViewerInventoryCategory* category = model->getCategory(mUUID); - category->determineFolderType(); - } -} - -BOOL LLFolderBridge::isItemRenameable() const -{ - LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory(); - if(cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) - && (cat->getOwnerID() == gAgent.getID())) - { - return TRUE; - } - return FALSE; -} - -void LLFolderBridge::restoreItem() -{ - LLViewerInventoryCategory* cat; - cat = (LLViewerInventoryCategory*)getCategory(); - if(cat) - { - LLInventoryModel* model = getInventoryModel(); - const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType())); - // do not restamp children on restore - LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE); - } -} - -LLFolderType::EType LLFolderBridge::getPreferredType() const -{ - LLFolderType::EType preferred_type = LLFolderType::FT_NONE; - LLViewerInventoryCategory* cat = getCategory(); - if(cat) - { - preferred_type = cat->getPreferredType(); - } - - return preferred_type; -} - -// Icons for folders are based on the preferred type -LLUIImagePtr LLFolderBridge::getIcon() const -{ - LLFolderType::EType preferred_type = LLFolderType::FT_NONE; - LLViewerInventoryCategory* cat = getCategory(); - if(cat) - { - preferred_type = cat->getPreferredType(); - } - return getIcon(preferred_type); -} - -LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type) -{ - // we only have one folder image now - return LLUI::getUIImage("Inv_FolderClosed"); -} - -BOOL LLFolderBridge::renameItem(const std::string& new_name) -{ - if(!isItemRenameable()) - return FALSE; - LLInventoryModel* model = getInventoryModel(); - if(!model) - return FALSE; - LLViewerInventoryCategory* cat = getCategory(); - if(cat && (cat->getName() != new_name)) - { - LLPointer new_cat = new LLViewerInventoryCategory(cat); - new_cat->rename(new_name); - new_cat->updateServer(FALSE); - model->updateCategory(new_cat); - - model->notifyObservers(); - } - // return FALSE because we either notified observers (& therefore - // rebuilt) or we didn't update. - return FALSE; -} - -BOOL LLFolderBridge::removeItem() -{ - if(!isItemRemovable()) - { - return FALSE; - } - const LLViewerInventoryCategory *cat = getCategory(); - - LLSD payload; - LLSD args; - args["FOLDERNAME"] = cat->getName(); - - LLNotification::Params params("ConfirmDeleteProtectedCategory"); - params.payload(payload).substitutions(args).functor.function(boost::bind(&LLFolderBridge::removeItemResponse, this, _1, _2)); - //params.functor.function(boost::bind(&LLFolderBridge::removeItemResponse, this, _1, _2)); - /* - LLNotification::Params params("ChangeLindenEstate"); - params.functor.function(boost::bind(&LLPanelEstateInfo::callbackChangeLindenEstate, this, _1, _2)); - */ - if (LLFolderType::lookupIsProtectedType(cat->getPreferredType())) - { - LLNotifications::instance().add(params); - } - else - { - LLNotifications::instance().forceResponse(params, 0); - } - return TRUE; -} - -bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - - // if they choose delete, do it. Otherwise, don't do anything - if(option == 0) - { - // move it to the trash - LLPreview::hide(mUUID); - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - - // Look for any gestures and deactivate them - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE ); - - S32 i; - for (i = 0; i < descendent_items.count(); i++) - { - LLInventoryItem* item = descendent_items[i]; - if (item->getType() == LLAssetType::AT_GESTURE - && LLGestureManager::instance().isGestureActive(item->getUUID())) - { - LLGestureManager::instance().deactivateGesture(item->getUUID()); - } - } - - // go ahead and do the normal remove if no 'last calling - // cards' are being removed. - LLViewerInventoryCategory* cat = getCategory(); - if(cat) - { - LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE); - } - return TRUE; - } - return FALSE; -} - -void LLFolderBridge::pasteFromClipboard() -{ - LLInventoryModel* model = getInventoryModel(); - if(model && isClipboardPasteable()) - { - LLInventoryItem* item = NULL; - LLDynamicArray objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - const LLUUID parent_id(mUUID); - for(S32 i = 0; i < count; i++) - { - item = model->getItem(objects.get(i)); - if (item) - { - if(LLInventoryClipboard::instance().isCutMode()) - { - // move_inventory_item() is not enough, - //we have to update inventory locally too - changeItemParent(model, dynamic_cast(item), parent_id, FALSE); - } - else - { - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - parent_id, - std::string(), - LLPointer(NULL)); - } - } - } - } -} - -void LLFolderBridge::pasteLinkFromClipboard() -{ - const LLInventoryModel* model = getInventoryModel(); - if(model) - { - LLDynamicArray objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - LLUUID parent_id(mUUID); - for(S32 i = 0; i < count; i++) - { - const LLUUID &object_id = objects.get(i); -#if SUPPORT_ENSEMBLES - if (LLInventoryCategory *cat = model->getCategory(object_id)) - { - link_inventory_item( - gAgent.getID(), - cat->getUUID(), - parent_id, - cat->getName(), - LLAssetType::AT_LINK_FOLDER, - LLPointer(NULL)); - } - else -#endif - if (LLInventoryItem *item = model->getItem(object_id)) - { - link_inventory_item( - gAgent.getID(), - item->getLinkedUUID(), - parent_id, - item->getName(), - LLAssetType::AT_LINK, - LLPointer(NULL)); - } - } - } -} - -void LLFolderBridge::staticFolderOptionsMenu() -{ - if (!sSelf) return; - sSelf->folderOptionsMenu(); -} - -bool isInOutfitsSidePanel(LLPanel *panel) -{ - LLInventoryPanel *my_panel = dynamic_cast(panel); - LLPanelOutfitsInventory *outfit_panel = - dynamic_cast(LLSideTray::getInstance()->getPanel("panel_outfits_inventory")); - if (!outfit_panel) - return false; - return outfit_panel->isAccordionPanel(my_panel); - - //LLInventoryPanel *outfit_inv_panel = outfit_panel ? outfit_panel->getActivePanel(): NULL; - //return (my_panel && (my_panel == outfit_inv_panel)); -} - -void LLFolderBridge::folderOptionsMenu() -{ - std::vector disabled_items; - - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - - const LLInventoryCategory* category = model->getCategory(mUUID); - LLFolderType::EType type = category->getPreferredType(); - const bool is_default_folder = category && LLFolderType::lookupIsProtectedType(type); - // BAP change once we're no longer treating regular categories as ensembles. - const bool is_ensemble = category && (type == LLFolderType::FT_NONE || - LLFolderType::lookupIsEnsembleType(type)); - const bool is_sidepanel = isInOutfitsSidePanel(mInventoryPanel.get()); - - // calling card related functionality for folders. - - if (is_sidepanel) - { - mItems.clear(); - mItems.push_back("Rename"); - mItems.push_back("Delete"); - } - - // Only enable calling-card related options for non-default folders. - if (!is_sidepanel && !is_default_folder) - { - LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); - if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) - { - mItems.push_back(std::string("Calling Card Separator")); - mItems.push_back(std::string("Conference Chat Folder")); - mItems.push_back(std::string("IM All Contacts In Folder")); - } - } - - // wearables related functionality for folders. - //is_wearable - LLFindWearables is_wearable; - LLIsType is_object( LLAssetType::AT_OBJECT ); - LLIsType is_gesture( LLAssetType::AT_GESTURE ); - - if (mWearables || - checkFolderForContentsOfType(model, is_wearable) || - checkFolderForContentsOfType(model, is_object) || - checkFolderForContentsOfType(model, is_gesture) ) - { - mItems.push_back(std::string("Folder Wearables Separator")); - - // Only enable add/replace outfit for non-default folders. - if (!is_default_folder) - { - mItems.push_back(std::string("Add To Outfit")); - mItems.push_back(std::string("Replace Outfit")); - } - if (is_ensemble) - { - mItems.push_back(std::string("Wear As Ensemble")); - } - mItems.push_back(std::string("Remove From Outfit")); - } - hide_context_entries(*mMenu, mItems, disabled_items); - - // Reposition the menu, in case we're adding items to an existing menu. - mMenu->needsArrange(); - mMenu->arrangeAndClear(); -} - -BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type) -{ - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - model->collectDescendentsIf(mUUID, - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_type); - return ((item_array.count() > 0) ? TRUE : FALSE ); -} - -// Flags unused -void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - mItems.clear(); - mDisabledItems.clear(); - - lldebugs << "LLFolderBridge::buildContextMenu()" << llendl; -// std::vector disabled_items; - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); - - mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point) - mDisabledItems.clear(); //adding code to clear out disabled members from previous - if (lost_and_found_id == mUUID) - { - // This is the lost+found folder. - mItems.push_back(std::string("Empty Lost And Found")); - } - - if(trash_id == mUUID) - { - // This is the trash. - mItems.push_back(std::string("Empty Trash")); - } - else if(model->isObjectDescendentOf(mUUID, trash_id)) - { - // This is a folder in the trash. - mItems.clear(); // clear any items that used to exist - mItems.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - mDisabledItems.push_back(std::string("Purge Item")); - } - - mItems.push_back(std::string("Restore Item")); - } - else if(isAgentInventory()) // do not allow creating in library - { - LLViewerInventoryCategory *cat = getCategory(); - // BAP removed protected check to re-enable standard ops in untyped folders. - // Not sure what the right thing is to do here. - if (!isCOFFolder() && cat /*&& - LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/) - { - // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. - if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) - mItems.push_back(std::string("New Folder")); - mItems.push_back(std::string("New Script")); - mItems.push_back(std::string("New Note")); - mItems.push_back(std::string("New Gesture")); - mItems.push_back(std::string("New Clothes")); - mItems.push_back(std::string("New Body Parts")); - mItems.push_back(std::string("Change Type")); - - LLViewerInventoryCategory *cat = getCategory(); - if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) - { - mDisabledItems.push_back(std::string("Change Type")); - } - - getClipboardEntries(false, mItems, mDisabledItems, flags); - } - else - { - // Want some but not all of the items from getClipboardEntries for outfits. - if (cat && cat->getPreferredType()==LLFolderType::FT_OUTFIT) - { - mItems.push_back(std::string("Rename")); - mItems.push_back(std::string("Delete")); - } - } - - //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06 - mCallingCards = mWearables = FALSE; - - LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); - if (checkFolderForContentsOfType(model, is_callingcard)) - { - mCallingCards=TRUE; - } - - LLFindWearables is_wearable; - LLIsType is_object( LLAssetType::AT_OBJECT ); - LLIsType is_gesture( LLAssetType::AT_GESTURE ); - - if (checkFolderForContentsOfType(model, is_wearable) || - checkFolderForContentsOfType(model, is_object) || - checkFolderForContentsOfType(model, is_gesture) ) - { - mWearables=TRUE; - } - - mMenu = &menu; - sSelf = this; - LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE); - - LLInventoryFetchDescendentsObserver::folder_ref_t folders; - LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); - if (category) - { - folders.push_back(category->getUUID()); - } - fetch->fetchDescendents(folders); - inc_busy_count(); - if(fetch->isEverythingComplete()) - { - // everything is already here - call done. - fetch->done(); - } - else - { - // it's all on it's way - add an observer, and the inventory - // will call done for us when everything is here. - gInventory.addObserver(fetch); - } - } - else - { - mItems.push_back(std::string("--no options--")); - mDisabledItems.push_back(std::string("--no options--")); - } - hide_context_entries(menu, mItems, mDisabledItems); -} - -BOOL LLFolderBridge::hasChildren() const -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - LLInventoryModel::EHasChildren has_children; - has_children = gInventory.categoryHasChildren(mUUID); - return has_children != LLInventoryModel::CHILDREN_NO; -} - -BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data) -{ - //llinfos << "LLFolderBridge::dragOrDrop()" << llendl; - BOOL accept = FALSE; - switch(cargo_type) - { - case DAD_TEXTURE: - case DAD_SOUND: - case DAD_CALLINGCARD: - case DAD_LANDMARK: - case DAD_SCRIPT: - case DAD_OBJECT: - case DAD_NOTECARD: - case DAD_CLOTHING: - case DAD_BODYPART: - case DAD_ANIMATION: - case DAD_GESTURE: - case DAD_LINK: - accept = dragItemIntoFolder((LLInventoryItem*)cargo_data, - drop); - break; - case DAD_CATEGORY: - if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID)) - { - accept = FALSE; - } - else - { - accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop); - } - break; - default: - break; - } - return accept; -} - -LLViewerInventoryCategory* LLFolderBridge::getCategory() const -{ - LLViewerInventoryCategory* cat = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - cat = (LLViewerInventoryCategory*)model->getCategory(mUUID); - } - return cat; -} - - -// static -void LLFolderBridge::pasteClipboard(void* user_data) -{ - LLFolderBridge* self = (LLFolderBridge*)user_data; - if(self) self->pasteFromClipboard(); -} - -void LLFolderBridge::createNewCategory(void* user_data) -{ - LLFolderBridge* bridge = (LLFolderBridge*)user_data; - if(!bridge) return; - LLInventoryPanel* panel = dynamic_cast(bridge->mInventoryPanel.get()); - if (!panel) return; - LLInventoryModel* model = panel->getModel(); - if(!model) return; - LLUUID id; - id = model->createNewCategory(bridge->getUUID(), - LLFolderType::FT_NONE, - LLStringUtil::null); - model->notifyObservers(); - - // At this point, the bridge has probably been deleted, but the - // view is still there. - panel->setSelection(id, TAKE_FOCUS_YES); -} - -void LLFolderBridge::createNewShirt(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHIRT); -} - -void LLFolderBridge::createNewPants(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_PANTS); -} - -void LLFolderBridge::createNewShoes(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHOES); -} - -void LLFolderBridge::createNewSocks(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SOCKS); -} - -void LLFolderBridge::createNewJacket(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_JACKET); -} - -void LLFolderBridge::createNewSkirt(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIRT); -} - -void LLFolderBridge::createNewGloves(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_GLOVES); -} - -void LLFolderBridge::createNewUndershirt(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERSHIRT); -} - -void LLFolderBridge::createNewUnderpants(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERPANTS); -} - -void LLFolderBridge::createNewShape(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHAPE); -} - -void LLFolderBridge::createNewSkin(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIN); -} - -void LLFolderBridge::createNewHair(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_HAIR); -} - -void LLFolderBridge::createNewEyes(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_EYES); -} - -// static -void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type) -{ - if(!bridge) return; - LLUUID parent_id = bridge->getUUID(); - createWearable(parent_id, type); -} - -// Separate function so can be called by global menu as well as right-click -// menu. -// static -void LLFolderBridge::createWearable(const LLUUID &parent_id, EWearableType type) -{ - LLWearable* wearable = LLWearableList::instance().createNewWearable(type); - LLAssetType::EType asset_type = wearable->getAssetType(); - LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE; - create_inventory_item(gAgent.getID(), gAgent.getSessionID(), - parent_id, wearable->getTransactionID(), wearable->getName(), - wearable->getDescription(), asset_type, inv_type, wearable->getType(), - wearable->getPermissions().getMaskNextOwner(), - LLPointer(NULL)); -} - -void LLFolderBridge::modifyOutfit(BOOL append) -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLViewerInventoryCategory* cat = getCategory(); - if(!cat) return; - - // BAP - was: - // wear_inventory_category_on_avatar( cat, append ); - LLAppearanceManager::instance().wearInventoryCategory( cat, FALSE, append ); -} - -// helper stuff -bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv) -{ - LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData; - LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID); - S32 option = LLNotification::getSelectedOption(notification, response); - - if(option == 0 && object) - { - if (cat_and_wear && cat_and_wear->mWear) - { - InventoryObjectList inventory_objects; - object->getInventoryContents(inventory_objects); - int contents_count = inventory_objects.size()-1; //subtract one for containing folder - - LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count); - gInventory.addObserver(inventoryObserver); - } - - two_uuids_list_t::iterator move_it; - for (move_it = move_inv->mMoveList.begin(); - move_it != move_inv->mMoveList.end(); - ++move_it) - { - object->moveInventory(move_it->first, move_it->second); - } - - // update the UI. - dialog_refresh_all(); - } - - if (move_inv->mCallback) - { - move_inv->mCallback(option, move_inv->mUserData); - } - - delete move_inv; - return false; -} - -/* -Next functions intended to reorder items in the inventory folder and save order on server -Is now used for Favorites folder. - -*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel -*/ -void saveItemsOrder(LLInventoryModel::item_array_t& items) -{ - int sortField = 0; - - // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field - for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) - { - LLViewerInventoryItem* item = *i; - - item->setSortField(++sortField); - item->setComplete(TRUE); - item->updateServer(FALSE); - - gInventory.updateItem(item); - } - - gInventory.notifyObservers(); -} - -LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id) -{ - LLInventoryModel::item_array_t::iterator result = items.end(); - - for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) - { - if ((*i)->getUUID() == id) - { - result = i; - break; - } - } - - return result; -} - -void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId) -{ - LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId); - LLViewerInventoryItem* destItem = gInventory.getItem(destItemId); - - items.erase(findItemByUUID(items, srcItem->getUUID())); - items.insert(findItemByUUID(items, destItem->getUUID()), srcItem); -} - -BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, - BOOL drop) -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - - // cannot drag into library - if(!isAgentInventory()) - { - return FALSE; - } - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if(!avatar) return FALSE; - - LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); - BOOL accept = FALSE; - LLViewerObject* object = NULL; - if(LLToolDragAndDrop::SOURCE_AGENT == source) - { - - BOOL is_movable = TRUE; - switch( inv_item->getActualType() ) - { - case LLAssetType::AT_CATEGORY: - is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType()); - break; - default: - break; - } - - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); - const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); - - if(is_movable && move_is_into_trash) - { - switch(inv_item->getType()) - { - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID()); - break; - - case LLAssetType::AT_OBJECT: - is_movable = !avatar->isWearingAttachment(inv_item->getUUID()); - break; - default: - break; - } - } - - if ( is_movable ) - { - // Don't allow creating duplicates in the Calling Card/Friends - // subfolders, see bug EXT-1599. Check is item direct descendent - // of target folder and forbid item's movement if it so. - // Note: isItemDirectDescendentOfCategory checks if - // passed category is in the Calling Card/Friends folder - is_movable = ! LLFriendCardsManager::instance() - .isObjDirectDescendentOfCategory (inv_item, getCategory()); - } - - const LLUUID& favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - const LLUUID& landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK); - const BOOL folder_allows_reorder = ((mUUID == landmarks_id) || (mUUID == favorites_id)); - - // we can move item inside a folder only if this folder is Favorites. See EXT-719 - accept = is_movable && ((mUUID != inv_item->getParentUUID()) || folder_allows_reorder); - if(accept && drop) - { - if (inv_item->getType() == LLAssetType::AT_GESTURE - && LLGestureManager::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash) - { - LLGestureManager::instance().deactivateGesture(inv_item->getUUID()); - } - // If an item is being dragged between windows, unselect - // everything in the active window so that we don't follow - // the selection to its new location (which is very - // annoying). - if (LLFloaterInventory::getActiveInventory()) - { - LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel(); - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); - if (active_panel && (panel != active_panel)) - { - active_panel->unSelectAll(); - } - } - - // if dragging from/into favorites folder only reorder items - if ((mUUID == inv_item->getParentUUID()) && folder_allows_reorder) - { - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLIsType is_type(LLAssetType::AT_LANDMARK); - model->collectDescendentsIf(mUUID, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); - - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); - LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; - if (itemp) - { - LLUUID srcItemId = inv_item->getUUID(); - LLUUID destItemId = itemp->getListener()->getUUID(); - - // update order - updateItemsOrder(items, srcItemId, destItemId); - - saveItemsOrder(items); - } - } - else if (favorites_id == mUUID) // if target is the favorites folder we use copy - { - copy_inventory_item( - gAgent.getID(), - inv_item->getPermissions().getOwner(), - inv_item->getUUID(), - mUUID, - std::string(), - LLPointer(NULL)); - } - else if (move_is_into_current_outfit || move_is_into_outfit) - { - // BAP - should skip if dup. - if (move_is_into_current_outfit) - { - LLAppearanceManager::instance().addCOFItemLink(inv_item); - } - else - { - LLPointer cb = NULL; - link_inventory_item( - gAgent.getID(), - inv_item->getLinkedUUID(), - mUUID, - inv_item->getName(), - LLAssetType::AT_LINK, - cb); - } - } - else - { - // restamp if the move is into the trash. - LLInvFVBridge::changeItemParent( - model, - (LLViewerInventoryItem*)inv_item, - mUUID, - move_is_into_trash); - } - } - } - else if(LLToolDragAndDrop::SOURCE_WORLD == source) - { - // Make sure the object exists. If we allowed dragging from - // anonymous objects, it would be possible to bypass - // permissions. - object = gObjectList.findObject(inv_item->getParentUUID()); - if(!object) - { - llinfos << "Object not found for drop." << llendl; - return FALSE; - } - - // coming from a task. Need to figure out if the person can - // move/copy this item. - LLPermissions perm(inv_item->getPermissions()); - BOOL is_move = FALSE; - if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) - && perm.allowTransferTo(gAgent.getID()))) -// || gAgent.isGodlike()) - - { - accept = TRUE; - } - else if(object->permYouOwner()) - { - // If the object cannot be copied, but the object the - // inventory is owned by the agent, then the item can be - // moved from the task to agent inventory. - is_move = TRUE; - accept = TRUE; - } - if(drop && accept) - { - LLMoveInv* move_inv = new LLMoveInv; - move_inv->mObjectID = inv_item->getParentUUID(); - two_uuids_t item_pair(mUUID, inv_item->getUUID()); - move_inv->mMoveList.push_back(item_pair); - move_inv->mCallback = NULL; - move_inv->mUserData = NULL; - if(is_move) - { - warn_move_inventory(object, move_inv); - } - else - { - LLNotification::Params params("MoveInventoryFromObject"); - params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); - LLNotifications::instance().forceResponse(params, 0); - } - } - - } - else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) - { - accept = TRUE; - if(drop) - { - copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(), - LLToolDragAndDrop::getInstance()->getSourceID(), inv_item); - } - } - else if(LLToolDragAndDrop::SOURCE_LIBRARY == source) - { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item; - if(item && item->isComplete()) - { - accept = TRUE; - if(drop) - { - copy_inventory_item( - gAgent.getID(), - inv_item->getPermissions().getOwner(), - inv_item->getUUID(), - mUUID, - std::string(), - LLPointer(NULL)); - } - } - } - else - { - llwarns << "unhandled drag source" << llendl; - } - return accept; -} - -// +=================================================+ -// | LLScriptBridge (DEPRECTED) | -// +=================================================+ - -LLUIImagePtr LLScriptBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE); -} - -// +=================================================+ -// | LLTextureBridge | -// +=================================================+ - -LLUIImagePtr LLTextureBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE); -} - -void LLTextureBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -} - -void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLTextureBridge::buildContextMenu()" << llendl; - std::vector items; - std::vector disabled_items; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - items.push_back(std::string("Texture Separator")); - items.push_back(std::string("Save As")); - } - hide_context_entries(menu, items, disabled_items); -} - -// virtual -void LLTextureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("save_as" == action) - { - LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); - LLPreviewTexture* preview_texture = LLFloaterReg::findTypedInstance("preview_texture", mUUID); - if (preview_texture) - { - preview_texture->openToSave(); - } - } - else LLItemBridge::performAction(folder, model, action); -} - -// +=================================================+ -// | LLSoundBridge | -// +=================================================+ - -LLUIImagePtr LLSoundBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE); -} - -void LLSoundBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* -// Changed this back to the way it USED to work: -// only open the preview dialog through the contextual right-click menu -// double-click just plays the sound - - LLViewerInventoryItem* item = getItem(); - if(item) - { - openSoundPreview((void*)this); - //send_uuid_sound_trigger(item->getAssetUUID(), 1.0); - } -*/ -} - -void LLSoundBridge::previewItem() -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - send_sound_trigger(item->getAssetUUID(), 1.0); - } -} - -void LLSoundBridge::openSoundPreview(void* which) -{ - LLSoundBridge *me = (LLSoundBridge *)which; - LLFloaterReg::showInstance("preview_sound", LLSD(me->mUUID), TAKE_FOCUS_YES); -} - -void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLSoundBridge::buildContextMenu()" << llendl; - std::vector items; - std::vector disabled_items; - - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Sound Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - - items.push_back(std::string("Sound Separator")); - items.push_back(std::string("Sound Play")); - - hide_context_entries(menu, items, disabled_items); -} - -// +=================================================+ -// | LLLandmarkBridge | -// +=================================================+ - -LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) : -LLItemBridge(inventory, uuid) -{ - mVisited = FALSE; - if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED) - { - mVisited = TRUE; - } -} - -LLUIImagePtr LLLandmarkBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE); -} - -void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - std::vector items; - std::vector disabled_items; - - lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Landmark Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - - items.push_back(std::string("Landmark Separator")); - items.push_back(std::string("About Landmark")); - - // Disable "About Landmark" menu item for - // multiple landmarks selected. Only one landmark - // info panel can be shown at a time. - if ((flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("About Landmark")); - } - - hide_context_entries(menu, items, disabled_items); -} - -// Convenience function for the two functions below. -void teleport_via_landmark(const LLUUID& asset_id) -{ - gAgent.teleportViaLandmark( asset_id ); - - // we now automatically track the landmark you're teleporting to - // because you'll probably arrive at a telehub instead - LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); - if( floater_world_map ) - { - floater_world_map->trackLandmark( asset_id ); - } -} - -// virtual -void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("teleport" == action) - { - LLViewerInventoryItem* item = getItem(); - if(item) - { - teleport_via_landmark(item->getAssetUUID()); - } - } - else if ("about" == action) - { - LLViewerInventoryItem* item = getItem(); - if(item) - { - LLSD key; - key["type"] = "landmark"; - key["id"] = item->getUUID(); - - LLSideTray::getInstance()->showPanel("panel_places", key); - } - } - else - { - LLItemBridge::performAction(folder, model, action); - } -} - -static bool open_landmark_callback(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - - LLUUID asset_id = notification["payload"]["asset_id"].asUUID(); - if (option == 0) - { - teleport_via_landmark(asset_id); - } - - return false; -} -static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFromLandmark", open_landmark_callback); - - -void LLLandmarkBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if( item ) - { - // Opening (double-clicking) a landmark immediately teleports, - // but warns you the first time. - // open_landmark(item); - LLSD payload; - payload["asset_id"] = item->getAssetUUID(); - LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); - } -*/ -} - - -// +=================================================+ -// | LLCallingCardObserver | -// +=================================================+ -void LLCallingCardObserver::changed(U32 mask) -{ - mBridgep->refreshFolderViewItem(); -} - -// +=================================================+ -// | LLCallingCardBridge | -// +=================================================+ - -LLCallingCardBridge::LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ) : - LLItemBridge(inventory, uuid) -{ - mObserver = new LLCallingCardObserver(this); - LLAvatarTracker::instance().addObserver(mObserver); -} - -LLCallingCardBridge::~LLCallingCardBridge() -{ - LLAvatarTracker::instance().removeObserver(mObserver); - delete mObserver; -} - -void LLCallingCardBridge::refreshFolderViewItem() -{ - LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); - LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL; - if (itemp) - { - itemp->refresh(); - } -} - -// virtual -void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("begin_im" == action) - { - LLViewerInventoryItem *item = getItem(); - if (item && (item->getCreatorUUID() != gAgent.getID()) && - (!item->getCreatorUUID().isNull())) - { - std::string callingcard_name; - gCacheName->getFullName(item->getCreatorUUID(), callingcard_name); - LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID()); - if (session_id != LLUUID::null) - { - LLIMFloater::show(session_id); - } - } - } - else if ("lure" == action) - { - LLViewerInventoryItem *item = getItem(); - if (item && (item->getCreatorUUID() != gAgent.getID()) && - (!item->getCreatorUUID().isNull())) - { - LLAvatarActions::offerTeleport(item->getCreatorUUID()); - } - } - else LLItemBridge::performAction(folder, model, action); -} - -LLUIImagePtr LLCallingCardBridge::getIcon() const -{ - BOOL online = FALSE; - LLViewerInventoryItem* item = getItem(); - if(item) - { - online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()); - } - return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE); -} - -std::string LLCallingCardBridge::getLabelSuffix() const -{ - LLViewerInventoryItem* item = getItem(); - if( item && LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()) ) - { - return LLItemBridge::getLabelSuffix() + " (online)"; - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -void LLCallingCardBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if(item && !item->getCreatorUUID().isNull()) - { - LLAvatarActions::showProfile(item->getCreatorUUID()); - } -*/ -} - -void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl; - std::vector items; - std::vector disabled_items; - - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - LLInventoryItem* item = getItem(); - BOOL good_card = (item - && (LLUUID::null != item->getCreatorUUID()) - && (item->getCreatorUUID() != gAgent.getID())); - BOOL user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID())); - items.push_back(std::string("Send Instant Message Separator")); - items.push_back(std::string("Send Instant Message")); - items.push_back(std::string("Offer Teleport...")); - items.push_back(std::string("Conference Chat")); - - if (!good_card) - { - disabled_items.push_back(std::string("Send Instant Message")); - } - if (!good_card || !user_online) - { - disabled_items.push_back(std::string("Offer Teleport...")); - disabled_items.push_back(std::string("Conference Chat")); - } - } - hide_context_entries(menu, items, disabled_items); -} - -BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data) -{ - LLViewerInventoryItem* item = getItem(); - BOOL rv = FALSE; - if(item) - { - // check the type - switch(cargo_type) - { - case DAD_TEXTURE: - case DAD_SOUND: - case DAD_LANDMARK: - case DAD_SCRIPT: - case DAD_CLOTHING: - case DAD_OBJECT: - case DAD_NOTECARD: - case DAD_BODYPART: - case DAD_ANIMATION: - case DAD_GESTURE: - { - LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; - const LLPermissions& perm = inv_item->getPermissions(); - if(gInventory.getItem(inv_item->getUUID()) - && perm.allowOperationBy(PERM_TRANSFER, gAgent.getID())) - { - rv = TRUE; - if(drop) - { - LLToolDragAndDrop::giveInventory(item->getCreatorUUID(), - (LLInventoryItem*)cargo_data); - } - } - else - { - // It's not in the user's inventory (it's probably in - // an object's contents), so disallow dragging it here. - // You can't give something you don't yet have. - rv = FALSE; - } - break; - } - case DAD_CATEGORY: - { - LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data; - if( gInventory.getCategory( inv_cat->getUUID() ) ) - { - rv = TRUE; - if(drop) - { - LLToolDragAndDrop::giveInventoryCategory( - item->getCreatorUUID(), - inv_cat); - } - } - else - { - // It's not in the user's inventory (it's probably in - // an object's contents), so disallow dragging it here. - // You can't give something you don't yet have. - rv = FALSE; - } - break; - } - default: - break; - } - } - return rv; -} - -BOOL LLCallingCardBridge::removeItem() -{ - if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem())) - { - LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID()); - return FALSE; - } - else - { - return LLItemBridge::removeItem(); - } -} -// +=================================================+ -// | LLNotecardBridge | -// +=================================================+ - -LLUIImagePtr LLNotecardBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE); -} - -void LLNotecardBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } - -/* - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES); - } -*/ -} - - -// +=================================================+ -// | LLGestureBridge | -// +=================================================+ - -LLUIImagePtr LLGestureBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE); -} - -LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const -{ - if( LLGestureManager::instance().isGestureActive(mUUID) ) - { - return LLFontGL::BOLD; - } - else - { - return LLFontGL::NORMAL; - } -} - -std::string LLGestureBridge::getLabelSuffix() const -{ - if( LLGestureManager::instance().isGestureActive(mUUID) ) - { - return LLItemBridge::getLabelSuffix() + " (active)"; - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -// virtual -void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("activate" == action) - { - LLGestureManager::instance().activateGesture(mUUID); - - LLViewerInventoryItem* item = gInventory.getItem(mUUID); - if (!item) return; - - // Since we just changed the suffix to indicate (active) - // the server doesn't need to know, just the viewer. - gInventory.updateItem(item); - gInventory.notifyObservers(); - } - else if ("deactivate" == action) - { - LLGestureManager::instance().deactivateGesture(mUUID); - - LLViewerInventoryItem* item = gInventory.getItem(mUUID); - if (!item) return; - - // Since we just changed the suffix to indicate (active) - // the server doesn't need to know, just the viewer. - gInventory.updateItem(item); - gInventory.notifyObservers(); - } - else LLItemBridge::performAction(folder, model, action); -} - -void LLGestureBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null); - preview->setFocus(TRUE); - } -*/ -} - -BOOL LLGestureBridge::removeItem() -{ - // Force close the preview window, if it exists - LLGestureManager::instance().deactivateGesture(mUUID); - return LLItemBridge::removeItem(); -} - -void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLGestureBridge::buildContextMenu()" << llendl; - std::vector items; - std::vector disabled_items; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - items.push_back(std::string("Gesture Separator")); - items.push_back(std::string("Activate")); - items.push_back(std::string("Deactivate")); - } - hide_context_entries(menu, items, disabled_items); -} - -// +=================================================+ -// | LLAnimationBridge | -// +=================================================+ - -LLUIImagePtr LLAnimationBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE); -} - -void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - std::vector items; - std::vector disabled_items; - - lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Animation Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - - items.push_back(std::string("Animation Separator")); - items.push_back(std::string("Animation Play")); - items.push_back(std::string("Animation Audition")); - - hide_context_entries(menu, items, disabled_items); - -} - -// virtual -void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ((action == "playworld") || (action == "playlocal")) - { - if (getItem()) - { - LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE; - if ("playworld" == action) activate = LLPreviewAnim::PLAY; - if ("playlocal" == action) activate = LLPreviewAnim::AUDITION; - - LLPreviewAnim* preview = LLFloaterReg::showTypedInstance("preview_anim", LLSD(mUUID)); - if (preview) - { - preview->activate(activate); - } - } - } - else - { - LLItemBridge::performAction(folder, model, action); - } -} - -void LLAnimationBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); - } -*/ -} - -// +=================================================+ -// | LLObjectBridge | -// +=================================================+ - -// static -LLUUID LLObjectBridge::sContextMenuItemID; - -LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) : -LLItemBridge(inventory, uuid), mInvType(type) -{ - mAttachPt = (flags & 0xff); // low bye of inventory flags - - mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE; -} - -LLUIImagePtr LLObjectBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject ); -} - -LLInventoryObject* LLObjectBridge::getObject() const -{ - LLInventoryObject* object = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - object = (LLInventoryObject*)model->getObject(mUUID); - } - return object; -} - -// virtual -void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("attach" == action) - { - LLUUID object_id = mUUID; - LLViewerInventoryItem* item; - item = (LLViewerInventoryItem*)gInventory.getItem(object_id); - if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID())) - { - rez_attachment(item, NULL); - } - else if(item && item->isComplete()) - { - // must be in library. copy it to our inventory and put it on. - LLPointer cb = new RezAttachmentCallback(0); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - gFocusMgr.setKeyboardFocus(NULL); - } - else if ("detach" == action) - { - LLInventoryItem* item = gInventory.getItem(mUUID); - if(item) - { - gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); - gMessageSystem->sendReliable( gAgent.getRegion()->getHost()); - } - // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = gObjectList.findObject(item->getLinkedUUID()); - if (found_obj) - { - LLSelectMgr::getInstance()->remove(found_obj); - } - } - else LLItemBridge::performAction(folder, model, action); -} - -void LLObjectBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } - - LLSD key; - key["id"] = mUUID; - LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); - - // Disable old properties floater; this is replaced by the sidepanel. - /* - LLFloaterReg::showInstance("properties", mUUID); - */ -} - -LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const -{ - U8 font = LLFontGL::NORMAL; - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( avatar && avatar->isWearingAttachment( mUUID ) ) - { - font |= LLFontGL::BOLD; - } - - LLInventoryItem* item = getItem(); - if (item && item->getIsLinkType()) - { - font |= LLFontGL::ITALIC; - } - - return (LLFontGL::StyleFlags)font; -} - -std::string LLObjectBridge::getLabelSuffix() const -{ - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( avatar && avatar->isWearingAttachment( mUUID ) ) - { - std::string attachment_point_name = avatar->getAttachedPointName(mUUID); - - // e.g. "(worn on ...)" / "(attached to ...)" - LLStringUtil::format_map_t args; - args["[ATTACHMENT_POINT]"] = attachment_point_name.c_str(); - return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args); - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment) -{ - LLSD payload; - payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link. - - S32 attach_pt = 0; - if (gAgent.getAvatarObject() && attachment) - { - for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin(); - iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter) - { - if (iter->second == attachment) - { - attach_pt = iter->first; - break; - } - } - } - - payload["attachment_point"] = attach_pt; - -#if !ENABLE_MULTIATTACHMENTS - if (attachment && attachment->getNumObjects() > 0) - { - LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez); - } - else -#endif - { - LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/); - } -} - -bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response) -{ - LLVOAvatar *avatarp = gAgent.getAvatarObject(); - - if (!avatarp->canAttachMoreObjects()) - { - LLSD args; - args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS); - LLNotifications::instance().add("MaxAttachmentsOnOutfit", args); - return false; - } - - S32 option = LLNotification::getSelectedOption(notification, response); - if (option == 0/*YES*/) - { - LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID()); - - if (itemp) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID()); - msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner()); - U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); -#if ENABLE_MULTIATTACHMENTS - attachment_pt |= ATTACHMENT_ADD; -#endif - msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); - pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions()); - msg->addStringFast(_PREHASH_Name, itemp->getName()); - msg->addStringFast(_PREHASH_Description, itemp->getDescription()); - msg->sendReliable(gAgent.getRegion()->getHost()); - } - } - return false; -} -static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_replace_attachment_rez); - -void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - std::vector items; - std::vector disabled_items; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Properties")); - - LLInventoryItem *item = getItem(); - getClipboardEntries(true, items, disabled_items, flags); - - LLObjectBridge::sContextMenuItemID = mUUID; - - if(item) - { - LLVOAvatarSelf* avatarp = gAgent.getAvatarObject(); - if( !avatarp ) - { - return; - } - - if( avatarp->isWearingAttachment( mUUID ) ) - { - items.push_back(std::string("Detach From Yourself")); - } - else - if( !isInTrash() && !isLinkedObjectInTrash() ) - { - items.push_back(std::string("Attach Separator")); - items.push_back(std::string("Object Wear")); - items.push_back(std::string("Attach To")); - items.push_back(std::string("Attach To HUD")); - // commented out for DEV-32347 - //items.push_back(std::string("Restore to Last Position")); - - if (!avatarp->canAttachMoreObjects()) - { - disabled_items.push_back(std::string("Object Wear")); - disabled_items.push_back(std::string("Attach To")); - disabled_items.push_back(std::string("Attach To HUD")); - } - LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE); - LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE); - LLVOAvatar *avatarp = gAgent.getAvatarObject(); - if (attach_menu - && (attach_menu->getChildCount() == 0) - && attach_hud_menu - && (attach_hud_menu->getChildCount() == 0) - && avatarp) - { - for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); - iter != avatarp->mAttachmentPoints.end(); ) - { - LLVOAvatar::attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; - LLMenuItemCallGL::Params p; - std::string submenu_name = attachment->getName(); - if (LLTrans::getString(submenu_name) != "") - { - p.name = (" ")+LLTrans::getString(submenu_name)+" "; - } - else - { - p.name = submenu_name; - } - LLSD cbparams; - cbparams["index"] = curiter->first; - cbparams["label"] = attachment->getName(); - p.on_click.function_name = "Inventory.AttachObject"; - p.on_click.parameter = LLSD(attachment->getName()); - p.on_enable.function_name = "Attachment.Label"; - p.on_enable.parameter = cbparams; - LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu; - LLUICtrlFactory::create(p, parent); - } - } - } - } - } - hide_context_entries(menu, items, disabled_items); -} - -BOOL LLObjectBridge::renameItem(const std::string& new_name) -{ - if(!isItemRenameable()) - return FALSE; - LLPreview::dirty(mUUID); - LLInventoryModel* model = getInventoryModel(); - if(!model) - return FALSE; - LLViewerInventoryItem* item = getItem(); - if(item && (item->getName() != new_name)) - { - LLPointer new_item = new LLViewerInventoryItem(item); - new_item->rename(new_name); - buildDisplayName(new_item, mDisplayName); - new_item->updateServer(FALSE); - model->updateItem(new_item); - - model->notifyObservers(); - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( avatar ) - { - LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() ); - if( obj ) - { - LLSelectMgr::getInstance()->deselectAll(); - LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE ); - LLSelectMgr::getInstance()->selectionSetObjectName( new_name ); - LLSelectMgr::getInstance()->deselectAll(); - } - } - } - // return FALSE because we either notified observers (& therefore - // rebuilt) or we didn't update. - return FALSE; -} - -// +=================================================+ -// | LLLSLTextBridge | -// +=================================================+ - -LLUIImagePtr LLLSLTextBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE); -} - -void LLLSLTextBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } - /* - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES); - } - */ -} - -// +=================================================+ -// | LLWearableBridge | -// +=================================================+ - -// *NOTE: hack to get from avatar inventory to avatar -void wear_inventory_item_on_avatar( LLInventoryItem* item ) -{ - if(item) - { - lldebugs << "wear_inventory_item_on_avatar( " << item->getName() - << " )" << llendl; - - LLAppearanceManager::instance().addCOFItemLink(item); - } -} - -void wear_add_inventory_item_on_avatar( LLInventoryItem* item ) -{ - if(item) - { - lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName() - << " )" << llendl; - - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - LLWearableBridge::onWearAddOnAvatarArrived, - new LLUUID(item->getUUID())); - } -} - -void remove_inventory_category_from_avatar( LLInventoryCategory* category ) -{ - if(!category) return; - lldebugs << "remove_inventory_category_from_avatar( " << category->getName() - << " )" << llendl; - - - if( gFloaterCustomize ) - { - gFloaterCustomize->askToSaveIfDirty( - boost::bind(remove_inventory_category_from_avatar_step2, _1, category->getUUID())); - } - else - { - remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() ); - } -} - -struct OnRemoveStruct -{ - LLUUID mUUID; - OnRemoveStruct(const LLUUID& uuid): - mUUID(uuid) - { - } -}; - -void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id) -{ - - // Find all the wearables that are in the category's subtree. - lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl; - if(proceed) - { - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - LLFindWearables is_wearable; - gInventory.collectDescendentsIf(category_id, - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_wearable); - S32 i; - S32 wearable_count = item_array.count(); - - LLInventoryModel::cat_array_t obj_cat_array; - LLInventoryModel::item_array_t obj_item_array; - LLIsType is_object( LLAssetType::AT_OBJECT ); - gInventory.collectDescendentsIf(category_id, - obj_cat_array, - obj_item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_object); - S32 obj_count = obj_item_array.count(); - - // Find all gestures in this folder - LLInventoryModel::cat_array_t gest_cat_array; - LLInventoryModel::item_array_t gest_item_array; - LLIsType is_gesture( LLAssetType::AT_GESTURE ); - gInventory.collectDescendentsIf(category_id, - gest_cat_array, - gest_item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_gesture); - S32 gest_count = gest_item_array.count(); - - if (wearable_count > 0) //Loop through wearables. If worn, remove. - { - for(i = 0; i < wearable_count; ++i) - { - LLViewerInventoryItem *item = item_array.get(i); - if (item->getType() == LLAssetType::AT_BODYPART) - continue; - if (gAgent.isTeen() && item->isWearableType() && - (item->getWearableType() == WT_UNDERPANTS || item->getWearableType() == WT_UNDERSHIRT)) - continue; - if( gAgentWearables.isWearingItem (item->getLinkedUUID()) ) - { - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - LLWearableBridge::onRemoveFromAvatarArrived, - new OnRemoveStruct(item->getLinkedUUID())); - } - } - } - - if (obj_count > 0) - { - for(i = 0; i < obj_count; ++i) - { - LLViewerInventoryItem *obj_item = obj_item_array.get(i); - gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item->getLinkedUUID() ); - - gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); - - // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = gObjectList.findObject( obj_item->getLinkedUUID()); - if (found_obj) - { - LLSelectMgr::getInstance()->remove(found_obj); - } - } - } - - if (gest_count > 0) - { - for(i = 0; i < gest_count; ++i) - { - LLViewerInventoryItem *gest_item = gest_item_array.get(i); - if ( LLGestureManager::instance().isGestureActive( gest_item->getLinkedUUID()) ) - { - LLGestureManager::instance().deactivateGesture( gest_item->getLinkedUUID() ); - gInventory.updateItem( gest_item ); - gInventory.notifyObservers(); - } - - } - } - } -} - -BOOL LLWearableBridge::renameItem(const std::string& new_name) -{ - if( gAgentWearables.isWearingItem( mUUID ) ) - { - gAgentWearables.setWearableName( mUUID, new_name ); - } - return LLItemBridge::renameItem(new_name); -} - -std::string LLWearableBridge::getLabelSuffix() const -{ - if( gAgentWearables.isWearingItem( mUUID ) ) - { - // e.g. "(worn)" - return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -LLUIImagePtr LLWearableBridge::getIcon() const -{ - return get_item_icon(mAssetType, mInvType, mWearableType, FALSE); -} - -// virtual -void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("wear" == action) - { - wearOnAvatar(); - } - else if ("wear_add" == action) - { - wearAddOnAvatar(); - } - else if ("edit" == action) - { - editOnAvatar(); - return; - } - else if ("take_off" == action) - { - if(gAgentWearables.isWearingItem(mUUID)) - { - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - LLWearableBridge::onRemoveFromAvatarArrived, - new OnRemoveStruct(mUUID)); - } - } - } - else LLItemBridge::performAction(folder, model, action); -} - -void LLWearableBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } - /* - if( isInTrash() ) - { - LLNotifications::instance().add("CannotWearTrash"); - } - else if(isAgentInventory()) - { - if( !gAgentWearables.isWearingItem( mUUID ) ) - { - wearOnAvatar(); - } - } - else - { - // must be in the inventory library. copy it to our inventory - // and put it on right away. - LLViewerInventoryItem* item = getItem(); - if(item && item->isComplete()) - { - LLPointer cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else if(item) - { - // *TODO: We should fetch the item details, and then do - // the operation above. - LLNotifications::instance().add("CannotWearInfoNotComplete"); - } - } - */ -} - -void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLWearableBridge::buildContextMenu()" << llendl; - std::vector items; - std::vector disabled_items; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere - BOOL no_open = ((flags & SUPPRESS_OPEN_ITEM) == SUPPRESS_OPEN_ITEM); - - // If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976 - LLViewerInventoryItem* item = getItem(); - if( !no_open && item ) - { - no_open = (item->getType() == LLAssetType::AT_CLOTHING) || - (item->getType() == LLAssetType::AT_BODYPART); - } - if (!no_open) - { - items.push_back(std::string("Open")); - } - - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - items.push_back(std::string("Wearable Separator")); - - items.push_back(std::string("Wearable Wear")); - items.push_back(std::string("Wearable Add")); - items.push_back(std::string("Wearable Edit")); - - if ((flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Wearable Edit")); - } - // Don't allow items to be worn if their baseobj is in the trash. - if (isLinkedObjectInTrash()) - { - disabled_items.push_back(std::string("Wearable Wear")); - disabled_items.push_back(std::string("Wearable Add")); - disabled_items.push_back(std::string("Wearable Edit")); - } - - // Disable wear and take off based on whether the item is worn. - if(item) - { - switch (item->getType()) - { - case LLAssetType::AT_CLOTHING: - items.push_back(std::string("Take Off")); - case LLAssetType::AT_BODYPART: - if (gAgentWearables.isWearingItem(item->getUUID())) - { - disabled_items.push_back(std::string("Wearable Wear")); - disabled_items.push_back(std::string("Wearable Add")); - } - else - { - disabled_items.push_back(std::string("Take Off")); - } - break; - default: - break; - } - } - } - hide_context_entries(menu, items, disabled_items); -} - -// Called from menus -// static -BOOL LLWearableBridge::canWearOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return FALSE; - if(!self->isAgentInventory()) - { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem(); - if(!item || !item->isComplete()) return FALSE; - } - return (!gAgentWearables.isWearingItem(self->mUUID)); -} - -// Called from menus -// static -void LLWearableBridge::onWearOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return; - self->wearOnAvatar(); -} - -void LLWearableBridge::wearOnAvatar() -{ - // Don't wear anything until initial wearables are loaded, can - // destroy clothing items. - if (!gAgentWearables.areWearablesLoaded()) - { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); - return; - } - - LLViewerInventoryItem* item = getItem(); - if(item) - { - if(!isAgentInventory()) - { - LLPointer cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else - { - wear_inventory_item_on_avatar(item); - } - } -} - -void LLWearableBridge::wearAddOnAvatar() -{ - // Don't wear anything until initial wearables are loaded, can - // destroy clothing items. - if (!gAgentWearables.areWearablesLoaded()) - { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); - return; - } - - LLViewerInventoryItem* item = getItem(); - if(item) - { - if(!isAgentInventory()) - { - LLPointer cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else - { - wear_add_inventory_item_on_avatar(item); - } - } -} - -// static -void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata ) -{ - LLUUID* item_id = (LLUUID*) userdata; - if(wearable) - { - LLViewerInventoryItem* item = NULL; - item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); - if(item) - { - if(item->getAssetUUID() == wearable->getAssetID()) - { - gAgentWearables.setWearableItem(item, wearable); - gInventory.notifyObservers(); - //self->getFolderItem()->refreshFromRoot(); - } - else - { - llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl; - } - } - } - delete item_id; -} - -// static -// BAP remove the "add" code path once everything is fully COF-ified. -void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata ) -{ - LLUUID* item_id = (LLUUID*) userdata; - if(wearable) - { - LLViewerInventoryItem* item = NULL; - item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); - if(item) - { - if(item->getAssetUUID() == wearable->getAssetID()) - { - bool do_append = true; - gAgentWearables.setWearableItem(item, wearable, do_append); - gInventory.notifyObservers(); - //self->getFolderItem()->refreshFromRoot(); - } - else - { - llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl; - } - } - } - delete item_id; -} - -// static -BOOL LLWearableBridge::canEditOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return FALSE; - - return (gAgentWearables.isWearingItem(self->mUUID)); -} - -// static -void LLWearableBridge::onEditOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(self) - { - self->editOnAvatar(); - } -} - -void LLWearableBridge::editOnAvatar() -{ - const LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID); - if( wearable ) - { - // Set the tab to the right wearable. - if (gFloaterCustomize) - gFloaterCustomize->setCurrentWearableType( wearable->getType() ); - - if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() ) - { - // Start Avatar Customization - gAgent.changeCameraToCustomizeAvatar(); - } - } -} - -// static -BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if( self && (LLAssetType::AT_BODYPART != self->mAssetType) ) - { - return gAgentWearables.isWearingItem( self->mUUID ); - } - return FALSE; -} - -// static -void LLWearableBridge::onRemoveFromAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return; - if(gAgentWearables.isWearingItem(self->mUUID)) - { - LLViewerInventoryItem* item = self->getItem(); - if (item) - { - LLUUID parent_id = item->getParentUUID(); - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - onRemoveFromAvatarArrived, - new OnRemoveStruct(LLUUID(self->mUUID))); - } - } -} - -// static -void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, - void* userdata) -{ - OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata; - const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID); - if(wearable) - { - if( gAgentWearables.isWearingItem( item_id ) ) - { - EWearableType type = wearable->getType(); - - if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&& - //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) ) - { - // MULTI_WEARABLE: FIXME HACK - always remove all - bool do_remove_all = false; - gAgentWearables.removeWearable( type, do_remove_all, 0 ); - } - } - } - - // Find and remove this item from the COF. - LLInventoryModel::item_array_t items = gInventory.collectLinkedItems(item_id, LLAppearanceManager::instance().getCOF()); - llassert(items.size() == 1); // Should always have one and only one item linked to this in the COF. - for (LLInventoryModel::item_array_t::const_iterator iter = items.begin(); - iter != items.end(); - ++iter) - { - const LLViewerInventoryItem *linked_item = (*iter); - const LLUUID &item_id = linked_item->getUUID(); - gInventory.purgeObject(item_id); - } - gInventory.notifyObservers(); - - delete on_remove_struct; -} - -LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type, - const LLUUID& uuid,LLInventoryModel* model) -{ - LLInvFVBridgeAction* action = NULL; - switch(asset_type) - { - case LLAssetType::AT_TEXTURE: - action = new LLTextureBridgeAction(uuid,model); - break; - - case LLAssetType::AT_SOUND: - action = new LLSoundBridgeAction(uuid,model); - break; - - case LLAssetType::AT_LANDMARK: - action = new LLLandmarkBridgeAction(uuid,model); - break; - - case LLAssetType::AT_CALLINGCARD: - action = new LLCallingCardBridgeAction(uuid,model); - break; - - case LLAssetType::AT_OBJECT: - action = new LLObjectBridgeAction(uuid,model); - break; - - case LLAssetType::AT_NOTECARD: - action = new LLNotecardBridgeAction(uuid,model); - break; - - case LLAssetType::AT_ANIMATION: - action = new LLAnimationBridgeAction(uuid,model); - break; - - case LLAssetType::AT_GESTURE: - action = new LLGestureBridgeAction(uuid,model); - break; - - case LLAssetType::AT_LSL_TEXT: - action = new LLLSLTextBridgeAction(uuid,model); - break; - - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - action = new LLWearableBridgeAction(uuid,model); - - break; - - default: - break; - } - return action; -} - -//static -void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type, - const LLUUID& uuid,LLInventoryModel* model) -{ - LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); - if(action) - { - action->doIt(); - delete action; - } -} - -//static -void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model) -{ - LLAssetType::EType asset_type = model->getItem(uuid)->getType(); - LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); - if(action) - { - action->doIt(); - delete action; - } -} - -LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const -{ - if(mModel) - return (LLViewerInventoryItem*)mModel->getItem(mUUID); - return NULL; -} - -//virtual -void LLTextureBridgeAction::doIt() -{ - if (getItem()) - { - LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - -//virtual -void LLSoundBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - - -//virtual -void LLLandmarkBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if( item ) - { - // Opening (double-clicking) a landmark immediately teleports, - // but warns you the first time. - LLSD payload; - payload["asset_id"] = item->getAssetUUID(); - LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); - } - - LLInvFVBridgeAction::doIt(); -} - - -//virtual -void LLCallingCardBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if(item && item->getCreatorUUID().notNull()) - { - LLAvatarActions::showProfile(item->getCreatorUUID()); - } - - LLInvFVBridgeAction::doIt(); -} - -//virtual -void -LLNotecardBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - -//virtual -void LLGestureBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null); - preview->setFocus(TRUE); - } - - LLInvFVBridgeAction::doIt(); -} - -//virtual -void LLAnimationBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - - -//virtual -void LLObjectBridgeAction::doIt() -{ - LLFloaterReg::showInstance("properties", mUUID); - - LLInvFVBridgeAction::doIt(); -} - - -//virtual -void LLLSLTextBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - - -BOOL LLWearableBridgeAction::isInTrash() const -{ - if(!mModel) return FALSE; - const LLUUID trash_id = mModel->findCategoryUUIDForType(LLFolderType::FT_TRASH); - return mModel->isObjectDescendentOf(mUUID, trash_id); -} - -BOOL LLWearableBridgeAction::isAgentInventory() const -{ - if(!mModel) return FALSE; - if(gInventory.getRootFolderID() == mUUID) return TRUE; - return mModel->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); -} - -void LLWearableBridgeAction::wearOnAvatar() -{ - // Don't wear anything until initial wearables are loaded, can - // destroy clothing items. - if (!gAgentWearables.areWearablesLoaded()) - { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); - return; - } - - LLViewerInventoryItem* item = getItem(); - if(item) - { - if(!isAgentInventory()) - { - LLPointer cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else - { - wear_inventory_item_on_avatar(item); - } - } -} - -//virtual -void LLWearableBridgeAction::doIt() -{ - if(isInTrash()) - { - LLNotifications::instance().add("CannotWearTrash"); - } - else if(isAgentInventory()) - { - if(!gAgentWearables.isWearingItem(mUUID)) - { - wearOnAvatar(); - } - } - else - { - // must be in the inventory library. copy it to our inventory - // and put it on right away. - LLViewerInventoryItem* item = getItem(); - if(item && item->isComplete()) - { - LLPointer cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else if(item) - { - // *TODO: We should fetch the item details, and then do - // the operation above. - LLNotifications::instance().add("CannotWearInfoNotComplete"); - } - } - - LLInvFVBridgeAction::doIt(); -} - -// +=================================================+ -// | LLLinkItemBridge | -// +=================================================+ -// For broken links - -std::string LLLinkItemBridge::sPrefix("Link: "); - - -LLUIImagePtr LLLinkItemBridge::getIcon() const -{ - if (LLViewerInventoryItem *item = getItem()) - { - return get_item_icon(item->getActualType(), LLInventoryType::IT_NONE, 0, FALSE); - } - return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE); -} - -void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - // *TODO: Translate - lldebugs << "LLLink::buildContextMenu()" << llendl; - std::vector items; - std::vector disabled_items; - - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Delete")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Delete")); - } - } - hide_context_entries(menu, items, disabled_items); -} - - -// +=================================================+ -// | LLLinkBridge | -// +=================================================+ -// For broken links. - -std::string LLLinkFolderBridge::sPrefix("Link: "); - - -LLUIImagePtr LLLinkFolderBridge::getIcon() const -{ - LLFolderType::EType preferred_type = LLFolderType::FT_NONE; - if (LLViewerInventoryItem *item = getItem()) - { - if (const LLViewerInventoryCategory* cat = item->getLinkedCategory()) - { - preferred_type = cat->getPreferredType(); - } - } - return LLFolderBridge::getIcon(preferred_type); -} - -void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - // *TODO: Translate - lldebugs << "LLLink::buildContextMenu()" << llendl; - std::vector items; - std::vector disabled_items; - - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Find Original")); - items.push_back(std::string("Delete")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Delete")); - } - } - hide_context_entries(menu, items, disabled_items); -} - -void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("goto" == action) - { - gotoItem(folder); - return; - } - LLItemBridge::performAction(folder,model,action); -} - -void LLLinkFolderBridge::gotoItem(LLFolderView *folder) -{ - const LLUUID &cat_uuid = getFolderID(); - if (!cat_uuid.isNull()) - { - if (LLFolderViewItem *base_folder = folder->getItemByID(cat_uuid)) - { - if (LLInventoryModel* model = getInventoryModel()) - { - model->fetchDescendentsOf(cat_uuid); - } - base_folder->setOpen(TRUE); - folder->setSelectionFromRoot(base_folder,TRUE); - folder->scrollToShowSelection(); - } - } -} - -const LLUUID &LLLinkFolderBridge::getFolderID() const -{ - if (LLViewerInventoryItem *link_item = getItem()) - { - if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory()) - { - const LLUUID& cat_uuid = cat->getUUID(); - return cat_uuid; - } - } - return LLUUID::null; -} +/** + * @file llinventorybridge.cpp + * @brief Implementation of the Inventory-Folder-View-Bridge classes. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llinventorybridge.h" + +#include "llagent.h" +#include "llagentwearables.h" +#include "llappearancemgr.h" +#include "llavataractions.h" +#include "llfloatercustomize.h" +#include "llfloaterinventory.h" +#include "llfloateropenobject.h" +#include "llfloaterreg.h" +#include "llfloaterworldmap.h" +#include "llfriendcard.h" +#include "llgesturemgr.h" +#include "llimfloater.h" +#include "llimview.h" +#include "llinventoryclipboard.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "llinventorypanel.h" +#include "llpreviewanim.h" +#include "llpreviewgesture.h" +#include "llpreviewtexture.h" +#include "llselectmgr.h" +#include "llsidetray.h" +#include "lltrans.h" +#include "llviewerassettype.h" +#include "llviewermessage.h" +#include "llviewerobjectlist.h" +#include "llviewerwindow.h" +#include "llvoavatarself.h" +#include "llwearablelist.h" +#include "llpaneloutfitsinventory.h" + +using namespace LLOldEvents; + +// Helpers +// bug in busy count inc/dec right now, logic is complex... do we really need it? +void inc_busy_count() +{ +// gViewerWindow->getWindow()->incBusyCount(); +// check balance of these calls if this code is changed to ever actually +// *do* something! +} +void dec_busy_count() +{ +// gViewerWindow->getWindow()->decBusyCount(); +// check balance of these calls if this code is changed to ever actually +// *do* something! +} + +// Function declarations +void wear_add_inventory_item_on_avatar(LLInventoryItem* item); +void remove_inventory_category_from_avatar(LLInventoryCategory* category); +void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id); +bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*); +bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response); + +std::string ICON_NAME[ICON_NAME_COUNT] = +{ + "Inv_Texture", + "Inv_Sound", + "Inv_CallingCard", + "Inv_CallingCard", + "Inv_Landmark", + "Inv_Landmark", + "Inv_Script", + "Inv_Clothing", + "Inv_Object", + "Inv_Object", + "Inv_Notecard", + "Inv_Skin", + "Inv_Snapshot", + + "Inv_BodyShape", + "Inv_Skin", + "Inv_Hair", + "Inv_Eye", + "Inv_Shirt", + "Inv_Pants", + "Inv_Shoe", + "Inv_Socks", + "Inv_Jacket", + "Inv_Gloves", + "Inv_Undershirt", + "Inv_Underpants", + "Inv_Skirt", + "Inv_Alpha", + "Inv_Tattoo", + + "Inv_Animation", + "Inv_Gesture", + + "inv_item_linkitem.tga", + "inv_item_linkfolder.tga" +}; + +// +=================================================+ +// | LLInvFVBridge | +// +=================================================+ + +LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) : +mUUID(uuid), mInvType(LLInventoryType::IT_NONE) +{ + mInventoryPanel = inventory->getHandle(); +} + +const std::string& LLInvFVBridge::getName() const +{ + LLInventoryObject* obj = getInventoryObject(); + if(obj) + { + return obj->getName(); + } + return LLStringUtil::null; +} + +const std::string& LLInvFVBridge::getDisplayName() const +{ + return getName(); +} + +// Folders have full perms +PermissionMask LLInvFVBridge::getPermissionMask() const +{ + + return PERM_ALL; +} + +// virtual +LLFolderType::EType LLInvFVBridge::getPreferredType() const +{ + return LLFolderType::FT_NONE; +} + + +// Folders don't have creation dates. +time_t LLInvFVBridge::getCreationDate() const +{ + return 0; +} + +// Can be destroyed (or moved to trash) +BOOL LLInvFVBridge::isItemRemovable() +{ + const LLInventoryModel* model = getInventoryModel(); + if(!model) + { + return FALSE; + } + if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) + { + return FALSE; + } + const LLInventoryObject *obj = model->getItem(mUUID); + if (obj && obj->getIsLinkType()) + { + return TRUE; + } + if (gAgentWearables.isWearingItem(mUUID)) + { + return FALSE; + } + const LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if (avatar && avatar->isWearingAttachment(mUUID)) + { + return FALSE; + } + return TRUE; +} + +// Can be moved to another folder +BOOL LLInvFVBridge::isItemMovable() const +{ + return TRUE; +} + +/*virtual*/ +/** + * @brief Adds this item into clipboard storage + */ +void LLInvFVBridge::cutToClipboard() +{ + if(isItemMovable()) + { + LLInventoryClipboard::instance().cut(mUUID); + } +} +// *TODO: make sure this does the right thing +void LLInvFVBridge::showProperties() +{ + LLSD key; + key["id"] = mUUID; + LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); + + // Disable old properties floater; this is replaced by the sidepanel. + /* + LLFloaterReg::showInstance("properties", mUUID); + */ +} + +void LLInvFVBridge::removeBatch(LLDynamicArray& batch) +{ + // Deactivate gestures when moving them into Trash + LLInvFVBridge* bridge; + LLInventoryModel* model = getInventoryModel(); + LLViewerInventoryItem* item = NULL; + LLViewerInventoryCategory* cat = NULL; + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + S32 count = batch.count(); + S32 i,j; + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); + if (item) + { + if(LLAssetType::AT_GESTURE == item->getType()) + { + LLGestureManager::instance().deactivateGesture(item->getUUID()); + } + } + } + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); + if (cat) + { + gInventory.collectDescendents( cat->getUUID(), descendent_categories, descendent_items, FALSE ); + for (j=0; jgetType()) + { + LLGestureManager::instance().deactivateGesture(descendent_items[j]->getUUID()); + } + } + } + } + removeBatchNoCheck(batch); +} + +void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray& batch) +{ + // this method moves a bunch of items and folders to the trash. As + // per design guidelines for the inventory model, the message is + // built and the accounting is performed first. After all of that, + // we call LLInventoryModel::moveObject() to move everything + // around. + LLInvFVBridge* bridge; + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLMessageSystem* msg = gMessageSystem; + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + LLViewerInventoryItem* item = NULL; + LLViewerInventoryCategory* cat = NULL; + std::vector move_ids; + LLInventoryModel::update_map_t update; + bool start_new_message = true; + S32 count = batch.count(); + S32 i; + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); + if(item) + { + if(item->getParentUUID() == trash_id) continue; + move_ids.push_back(item->getUUID()); + LLPreview::hide(item->getUUID()); + --update[item->getParentUUID()]; + ++update[trash_id]; + if(start_new_message) + { + start_new_message = false; + msg->newMessageFast(_PREHASH_MoveInventoryItem); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addBOOLFast(_PREHASH_Stamp, TRUE); + } + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_ItemID, item->getUUID()); + msg->addUUIDFast(_PREHASH_FolderID, trash_id); + msg->addString("NewName", NULL); + if(msg->isSendFullFast(_PREHASH_InventoryData)) + { + start_new_message = true; + gAgent.sendReliableMessage(); + gInventory.accountForUpdate(update); + update.clear(); + } + } + } + if(!start_new_message) + { + start_new_message = true; + gAgent.sendReliableMessage(); + gInventory.accountForUpdate(update); + update.clear(); + } + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); + if(cat) + { + if(cat->getParentUUID() == trash_id) continue; + move_ids.push_back(cat->getUUID()); + --update[cat->getParentUUID()]; + ++update[trash_id]; + if(start_new_message) + { + start_new_message = false; + msg->newMessageFast(_PREHASH_MoveInventoryFolder); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addBOOL("Stamp", TRUE); + } + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID()); + msg->addUUIDFast(_PREHASH_ParentID, trash_id); + if(msg->isSendFullFast(_PREHASH_InventoryData)) + { + start_new_message = true; + gAgent.sendReliableMessage(); + gInventory.accountForUpdate(update); + update.clear(); + } + } + } + if(!start_new_message) + { + gAgent.sendReliableMessage(); + gInventory.accountForUpdate(update); + } + + // move everything. + std::vector::iterator it = move_ids.begin(); + std::vector::iterator end = move_ids.end(); + for(; it != end; ++it) + { + gInventory.moveObject((*it), trash_id); + } + + // notify inventory observers. + model->notifyObservers(); +} + +BOOL LLInvFVBridge::isClipboardPasteable() const +{ + if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) + { + return FALSE; + } + LLInventoryModel* model = getInventoryModel(); + if (!model) + { + return FALSE; + } + + const LLUUID &agent_id = gAgent.getID(); + + LLDynamicArray objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.count(); + for(S32 i = 0; i < count; i++) + { + const LLUUID &item_id = objects.get(i); + + // Can't paste folders + const LLInventoryCategory *cat = model->getCategory(item_id); + if (cat) + { + return FALSE; + } + + const LLInventoryItem *item = model->getItem(item_id); + if (item) + { + if (!item->getPermissions().allowCopyBy(agent_id)) + { + return FALSE; + } + } + } + return TRUE; +} + +BOOL LLInvFVBridge::isClipboardPasteableAsLink() const +{ + if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) + { + return FALSE; + } + const LLInventoryModel* model = getInventoryModel(); + if (!model) + { + return FALSE; + } + + LLDynamicArray objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.count(); + for(S32 i = 0; i < count; i++) + { + const LLInventoryItem *item = model->getItem(objects.get(i)); + if (item) + { + if (!LLAssetType::lookupCanLink(item->getActualType())) + { + return FALSE; + } + } + const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i)); + if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())) + { + return FALSE; + } + } + return TRUE; +} + +void hide_context_entries(LLMenuGL& menu, + const std::vector &entries_to_show, + const std::vector &disabled_entries) +{ + const LLView::child_list_t *list = menu.getChildList(); + + LLView::child_list_t::const_iterator itor; + for (itor = list->begin(); itor != list->end(); ++itor) + { + std::string name = (*itor)->getName(); + + // descend into split menus: + LLMenuItemBranchGL* branchp = dynamic_cast(*itor); + if ((name == "More") && branchp) + { + hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries); + } + + + bool found = false; + std::vector::const_iterator itor2; + for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2) + { + if (*itor2 == name) + { + found = true; + } + } + if (!found) + { + (*itor)->setVisible(FALSE); + } + else + { + (*itor)->setVisible(TRUE); + for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2) + { + if (*itor2 == name) + { + (*itor)->setEnabled(FALSE); + } + } + } + } +} + +// Helper for commonly-used entries +void LLInvFVBridge::getClipboardEntries(bool show_asset_id, + std::vector &items, + std::vector &disabled_items, U32 flags) +{ + const LLInventoryObject *obj = getInventoryObject(); + if (obj && obj->getIsLinkType()) + { + items.push_back(std::string("Find Original")); + if (LLAssetType::lookupIsLinkType(obj->getType())) + { + disabled_items.push_back(std::string("Find Original")); + } + } + else + { + items.push_back(std::string("Rename")); + if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Rename")); + } + + if (show_asset_id) + { + items.push_back(std::string("Copy Asset UUID")); + if ( (! ( isItemPermissive() || gAgent.isGodlike() ) ) + || (flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Copy Asset UUID")); + } + } + items.push_back(std::string("Copy Separator")); + + items.push_back(std::string("Copy")); + if (!isItemCopyable()) + { + disabled_items.push_back(std::string("Copy")); + } + } + + items.push_back(std::string("Paste")); + if (!isClipboardPasteable() || (flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Paste")); + } + + items.push_back(std::string("Paste As Link")); + if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Paste As Link")); + } + items.push_back(std::string("Paste Separator")); + + items.push_back(std::string("Delete")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Delete")); + } + + // If multiple items are selected, disable properties (if it exists). + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Properties")); + } +} + +void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl; + std::vector items; + std::vector disabled_items; + if(isInTrash()) + { + items.push_back(std::string("PurgeItem")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("PurgeItem")); + } + items.push_back(std::string("RestoreItem")); + } + else + { + items.push_back(std::string("Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + } + hide_context_entries(menu, items, disabled_items); +} + +// *TODO: remove this +BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const +{ + BOOL rv = FALSE; + + const LLInventoryObject* obj = getInventoryObject(); + + if(obj) + { + *type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType()); + if(*type == DAD_NONE) + { + return FALSE; + } + + *id = obj->getUUID(); + //object_ids.put(obj->getUUID()); + + if (*type == DAD_CATEGORY) + { + gInventory.startBackgroundFetch(obj->getUUID()); + } + + rv = TRUE; + } + + return rv; +} + +LLInventoryObject* LLInvFVBridge::getInventoryObject() const +{ + LLInventoryObject* obj = NULL; + LLInventoryModel* model = getInventoryModel(); + if(model) + { + obj = (LLInventoryObject*)model->getObject(mUUID); + } + return obj; +} + +LLInventoryModel* LLInvFVBridge::getInventoryModel() const +{ + LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + return panel ? panel->getModel() : NULL; +} + +BOOL LLInvFVBridge::isInTrash() const +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + return model->isObjectDescendentOf(mUUID, trash_id); +} + +BOOL LLInvFVBridge::isLinkedObjectInTrash() const +{ + if (isInTrash()) return TRUE; + + const LLInventoryObject *obj = getInventoryObject(); + if (obj && obj->getIsLinkType()) + { + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id); + } + return FALSE; +} + +BOOL LLInvFVBridge::isAgentInventory() const +{ + const LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + if(gInventory.getRootFolderID() == mUUID) return TRUE; + return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); +} + +BOOL LLInvFVBridge::isCOFFolder() const +{ + const LLInventoryModel* model = getInventoryModel(); + if(!model) return TRUE; + const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id)) + { + return TRUE; + } + return FALSE; +} + +BOOL LLInvFVBridge::isItemPermissive() const +{ + return FALSE; +} + +// static +void LLInvFVBridge::changeItemParent(LLInventoryModel* model, + LLViewerInventoryItem* item, + const LLUUID& new_parent, + BOOL restamp) +{ + if(item->getParentUUID() != new_parent) + { + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); + update.push_back(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1); + update.push_back(new_folder); + gInventory.accountForUpdate(update); + + LLPointer new_item = new LLViewerInventoryItem(item); + new_item->setParent(new_parent); + new_item->updateParentOnServer(restamp); + model->updateItem(new_item); + model->notifyObservers(); + } +} + +// static +void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model, + LLViewerInventoryCategory* cat, + const LLUUID& new_parent, + BOOL restamp) +{ + if(cat->getParentUUID() != new_parent) + { + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1); + update.push_back(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1); + update.push_back(new_folder); + gInventory.accountForUpdate(update); + + LLPointer new_cat = new LLViewerInventoryCategory(cat); + new_cat->setParent(new_parent); + new_cat->updateParentOnServer(restamp); + model->updateCategory(new_cat); + model->notifyObservers(); + } +} + + +const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type) +{ + const std::string rv= LLInventoryType::lookup(inv_type); + if(rv.empty()) + { + return std::string(""); + } + return rv; +} + +LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, + LLAssetType::EType actual_asset_type, + LLInventoryType::EType inv_type, + LLInventoryPanel* inventory, + const LLUUID& uuid, + U32 flags) +{ + LLInvFVBridge* new_listener = NULL; + switch(asset_type) + { + case LLAssetType::AT_TEXTURE: + if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLTextureBridge(inventory, uuid, inv_type); + break; + + case LLAssetType::AT_SOUND: + if(!(inv_type == LLInventoryType::IT_SOUND)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLSoundBridge(inventory, uuid); + break; + + case LLAssetType::AT_LANDMARK: + if(!(inv_type == LLInventoryType::IT_LANDMARK)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLLandmarkBridge(inventory, uuid, flags); + break; + + case LLAssetType::AT_CALLINGCARD: + if(!(inv_type == LLInventoryType::IT_CALLINGCARD)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLCallingCardBridge(inventory, uuid); + break; + + case LLAssetType::AT_SCRIPT: + if(!(inv_type == LLInventoryType::IT_LSL)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLScriptBridge(inventory, uuid); + break; + + case LLAssetType::AT_OBJECT: + if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags); + break; + + case LLAssetType::AT_NOTECARD: + if(!(inv_type == LLInventoryType::IT_NOTECARD)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLNotecardBridge(inventory, uuid); + break; + + case LLAssetType::AT_ANIMATION: + if(!(inv_type == LLInventoryType::IT_ANIMATION)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLAnimationBridge(inventory, uuid); + break; + + case LLAssetType::AT_GESTURE: + if(!(inv_type == LLInventoryType::IT_GESTURE)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLGestureBridge(inventory, uuid); + break; + + case LLAssetType::AT_LSL_TEXT: + if(!(inv_type == LLInventoryType::IT_LSL)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLLSLTextBridge(inventory, uuid); + break; + + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + if(!(inv_type == LLInventoryType::IT_WEARABLE)) + { + llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; + } + new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags); + break; + case LLAssetType::AT_CATEGORY: + if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) + { + // Create a link folder handler instead. + new_listener = new LLLinkFolderBridge(inventory, uuid); + break; + } + new_listener = new LLFolderBridge(inventory, uuid); + break; + case LLAssetType::AT_LINK: + // Only should happen for broken links. + new_listener = new LLLinkItemBridge(inventory, uuid); + break; + case LLAssetType::AT_LINK_FOLDER: + // Only should happen for broken links. + new_listener = new LLLinkItemBridge(inventory, uuid); + break; + default: + llinfos << "Unhandled asset type (llassetstorage.h): " + << (S32)asset_type << llendl; + break; + } + + if (new_listener) + { + new_listener->mInvType = inv_type; + } + + return new_listener; +} + +void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) +{ + LLInventoryCategory* cat = model->getCategory(uuid); + if (cat) + { + model->purgeDescendentsOf(uuid); + model->notifyObservers(); + } + LLInventoryObject* obj = model->getObject(uuid); + if (obj) + { + model->purgeObject(uuid); + model->notifyObservers(); + } +} + +// +=================================================+ +// | InventoryFVBridgeBuilder | +// +=================================================+ +LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type, + LLAssetType::EType actual_asset_type, + LLInventoryType::EType inv_type, + LLInventoryPanel* inventory, + const LLUUID& uuid, + U32 flags /* = 0x00 */) const +{ + return LLInvFVBridge::createBridge(asset_type, + actual_asset_type, + inv_type, + inventory, + uuid, + flags); +} + +// +=================================================+ +// | LLItemBridge | +// +=================================================+ + +void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("goto" == action) + { + gotoItem(folder); + } + if ("open" == action) + { + openItem(); + return; + } + else if ("properties" == action) + { + showProperties(); + return; + } + else if ("purge" == action) + { + purgeItem(model, mUUID); + return; + } + else if ("restoreToWorld" == action) + { + restoreToWorld(); + return; + } + else if ("restore" == action) + { + restoreItem(); + return; + } + else if ("copy_uuid" == action) + { + // Single item only + LLInventoryItem* item = model->getItem(mUUID); + if(!item) return; + LLUUID asset_id = item->getAssetUUID(); + std::string buffer; + asset_id.toString(buffer); + + gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer)); + return; + } + else if ("copy" == action) + { + copyToClipboard(); + return; + } + else if ("paste" == action) + { + // Single item only + LLInventoryItem* itemp = model->getItem(mUUID); + if (!itemp) return; + + LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID()); + if (!folder_view_itemp) return; + + folder_view_itemp->getListener()->pasteFromClipboard(); + return; + } + else if ("paste_link" == action) + { + // Single item only + LLInventoryItem* itemp = model->getItem(mUUID); + if (!itemp) return; + + LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID()); + if (!folder_view_itemp) return; + + folder_view_itemp->getListener()->pasteLinkFromClipboard(); + return; + } +} + +void LLItemBridge::selectItem() +{ + LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); + if(item && !item->isComplete()) + { + item->fetchFromServer(); + } +} + +void LLItemBridge::restoreItem() +{ + LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); + if(item) + { + LLInventoryModel* model = getInventoryModel(); + const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType())); + // do not restamp on restore. + LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE); + } +} + +void LLItemBridge::restoreToWorld() +{ + LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)getItem(); + if (itemp) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("RezRestoreToWorld"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlockFast(_PREHASH_InventoryData); + itemp->packMessage(msg); + msg->sendReliable(gAgent.getRegion()->getHost()); + } + + //Similar functionality to the drag and drop rez logic + BOOL remove_from_inventory = FALSE; + + //remove local inventory copy, sim will deal with permissions and removing the item + //from the actual inventory if its a no-copy etc + if(!itemp->getPermissions().allowCopyBy(gAgent.getID())) + { + remove_from_inventory = TRUE; + } + + // Check if it's in the trash. (again similar to the normal rez logic) + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id)) + { + remove_from_inventory = TRUE; + } + + if(remove_from_inventory) + { + gInventory.deleteObject(itemp->getUUID()); + gInventory.notifyObservers(); + } +} + +void LLItemBridge::gotoItem(LLFolderView *folder) +{ + LLInventoryObject *obj = getInventoryObject(); + if (obj && obj->getIsLinkType()) + { + LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel(); + if (active_panel) + { + active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO); + } + } +} + +LLUIImagePtr LLItemBridge::getIcon() const +{ + return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]); +} + +PermissionMask LLItemBridge::getPermissionMask() const +{ + LLViewerInventoryItem* item = getItem(); + PermissionMask perm_mask = 0; + if(item) + { + BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); + BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); + BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, + gAgent.getID()); + + if (copy) perm_mask |= PERM_COPY; + if (mod) perm_mask |= PERM_MODIFY; + if (xfer) perm_mask |= PERM_TRANSFER; + + } + return perm_mask; +} + +const std::string& LLItemBridge::getDisplayName() const +{ + if(mDisplayName.empty()) + { + buildDisplayName(getItem(), mDisplayName); + } + return mDisplayName; +} + +void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) +{ + if(item) + { + name.assign(item->getName()); + } + else + { + name.assign(LLStringUtil::null); + } +} + +LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const +{ + U8 font = LLFontGL::NORMAL; + + if( gAgentWearables.isWearingItem( mUUID ) ) + { + // llinfos << "BOLD" << llendl; + font |= LLFontGL::BOLD; + } + + const LLViewerInventoryItem* item = getItem(); + if (item && item->getIsLinkType()) + { + font |= LLFontGL::ITALIC; + } + return (LLFontGL::StyleFlags)font; +} + +std::string LLItemBridge::getLabelSuffix() const +{ + // String table is loaded before login screen and inventory items are + // loaded after login, so LLTrans should be ready. + static std::string NO_COPY =LLTrans::getString("no_copy"); + static std::string NO_MOD = LLTrans::getString("no_modify"); + static std::string NO_XFER = LLTrans::getString("no_transfer"); + static std::string LINK = LLTrans::getString("link"); + static std::string BROKEN_LINK = LLTrans::getString("broken_link"); + std::string suffix; + LLInventoryItem* item = getItem(); + if(item) + { + // it's a bit confusing to put nocopy/nomod/etc on calling cards. + if(LLAssetType::AT_CALLINGCARD != item->getType() + && item->getPermissions().getOwner() == gAgent.getID()) + { + BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType()); + if (broken_link) return BROKEN_LINK; + + BOOL link = item->getIsLinkType(); + if (link) return LINK; + + BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); + if (!copy) + { + suffix += NO_COPY; + } + BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); + if (!mod) + { + suffix += NO_MOD; + } + BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, + gAgent.getID()); + if (!xfer) + { + suffix += NO_XFER; + } + } + } + return suffix; +} + +time_t LLItemBridge::getCreationDate() const +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { + return item->getCreationDate(); + } + return 0; +} + + +BOOL LLItemBridge::isItemRenameable() const +{ + LLViewerInventoryItem* item = getItem(); + if(item) + { + // (For now) Don't allow calling card rename since that may confuse users as to + // what the calling card points to. + if (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD) + { + return FALSE; + } + return (item->getPermissions().allowModifyBy(gAgent.getID())); + } + return FALSE; +} + +BOOL LLItemBridge::renameItem(const std::string& new_name) +{ + if(!isItemRenameable()) + return FALSE; + LLPreview::dirty(mUUID); + LLInventoryModel* model = getInventoryModel(); + if(!model) + return FALSE; + LLViewerInventoryItem* item = getItem(); + if(item && (item->getName() != new_name)) + { + LLPointer new_item = new LLViewerInventoryItem(item); + new_item->rename(new_name); + buildDisplayName(new_item, mDisplayName); + new_item->updateServer(FALSE); + model->updateItem(new_item); + + model->notifyObservers(); + } + // return FALSE because we either notified observers (& therefore + // rebuilt) or we didn't update. + return FALSE; +} + + +BOOL LLItemBridge::removeItem() +{ + if(!isItemRemovable()) + { + return FALSE; + } + // move it to the trash + LLPreview::hide(mUUID, TRUE); + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + LLViewerInventoryItem* item = getItem(); + + // if item is not already in trash + if(item && !model->isObjectDescendentOf(mUUID, trash_id)) + { + // move to trash, and restamp + LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE); + // delete was successful + return TRUE; + } + else + { + // tried to delete already item in trash (should purge?) + return FALSE; + } +} + +BOOL LLItemBridge::isItemCopyable() const +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { + // can't copy worn objects. DEV-15183 + LLVOAvatarSelf *avatarp = gAgent.getAvatarObject(); + if( !avatarp ) + { + return FALSE; + } + + if(avatarp->isWearingAttachment(mUUID)) + { + return FALSE; + } + + // All items can be copied, not all can be pasted. + // The only time an item can't be copied is if it's a link + // return (item->getPermissions().allowCopyBy(gAgent.getID())); + if (item->getIsLinkType()) + { + return FALSE; + } + return TRUE; + } + return FALSE; +} +BOOL LLItemBridge::copyToClipboard() const +{ + if(isItemCopyable()) + { + LLInventoryClipboard::instance().add(mUUID); + return TRUE; + } + return FALSE; +} + +LLViewerInventoryItem* LLItemBridge::getItem() const +{ + LLViewerInventoryItem* item = NULL; + LLInventoryModel* model = getInventoryModel(); + if(model) + { + item = (LLViewerInventoryItem*)model->getItem(mUUID); + } + return item; +} + +BOOL LLItemBridge::isItemPermissive() const +{ + LLViewerInventoryItem* item = getItem(); + if(item) + { + U32 mask = item->getPermissions().getMaskBase(); + if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) + { + return TRUE; + } + } + return FALSE; +} + +// +=================================================+ +// | LLFolderBridge | +// +=================================================+ + +LLFolderBridge* LLFolderBridge::sSelf=NULL; + +// Can be moved to another folder +BOOL LLFolderBridge::isItemMovable() const +{ + LLInventoryObject* obj = getInventoryObject(); + if(obj) + { + return (!LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType())); + } + return FALSE; +} + +void LLFolderBridge::selectItem() +{ +} + + +// Iterate through a folder's children to determine if +// all the children are removable. +class LLIsItemRemovable : public LLFolderViewFunctor +{ +public: + LLIsItemRemovable() : mPassed(TRUE) {} + virtual void doFolder(LLFolderViewFolder* folder) + { + mPassed &= folder->getListener()->isItemRemovable(); + } + virtual void doItem(LLFolderViewItem* item) + { + mPassed &= item->getListener()->isItemRemovable(); + } + BOOL mPassed; +}; + +// Can be destroyed (or moved to trash) +BOOL LLFolderBridge::isItemRemovable() +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) + { + return FALSE; + } + + if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) + { + return FALSE; + } + + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if( !avatar ) + { + return FALSE; + } + + LLInventoryCategory* category = model->getCategory(mUUID); + if( !category ) + { + return FALSE; + } + // Allow protected types to be removed, but issue a warning. + /* + if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) + { + return FALSE; + } + */ + + LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLFolderViewFolder* folderp = dynamic_cast(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL); + if (folderp) + { + LLIsItemRemovable folder_test; + folderp->applyFunctorToChildren(folder_test); + if (!folder_test.mPassed) + { + return FALSE; + } + } + return TRUE; +} + +BOOL LLFolderBridge::isUpToDate() const +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); + if( !category ) + { + return FALSE; + } + + return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN; +} + +BOOL LLFolderBridge::isItemCopyable() const +{ + return TRUE; +} + +BOOL LLFolderBridge::copyToClipboard() const +{ + if(isItemCopyable()) + { + LLInventoryClipboard::instance().add(mUUID); + return TRUE; + } + return FALSE; +} + +BOOL LLFolderBridge::isClipboardPasteable() const +{ + if ( ! LLInvFVBridge::isClipboardPasteable() ) + return FALSE; + + // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 + if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) ) + { + LLInventoryModel* model = getInventoryModel(); + if ( !model ) + { + return FALSE; + } + + LLDynamicArray objects; + LLInventoryClipboard::instance().retrieve(objects); + const LLViewerInventoryCategory *current_cat = getCategory(); + + // Search for the direct descendent of current Friends subfolder among all pasted items, + // and return false if is found. + for(S32 i = objects.count() - 1; i >= 0; --i) + { + const LLUUID &obj_id = objects.get(i); + if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) + { + return FALSE; + } + } + + } + return TRUE; +} + +BOOL LLFolderBridge::isClipboardPasteableAsLink() const +{ + // Check normal paste-as-link permissions + if (!LLInvFVBridge::isClipboardPasteableAsLink()) + { + return FALSE; + } + + const LLInventoryModel* model = getInventoryModel(); + if (!model) + { + return FALSE; + } + + const LLViewerInventoryCategory *current_cat = getCategory(); + if (current_cat) + { + const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat ); + const LLUUID ¤t_cat_id = current_cat->getUUID(); + LLDynamicArray objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.count(); + for(S32 i = 0; i < count; i++) + { + const LLUUID &obj_id = objects.get(i); + const LLInventoryCategory *cat = model->getCategory(obj_id); + if (cat) + { + const LLUUID &cat_id = cat->getUUID(); + // Don't allow recursive pasting + if ((cat_id == current_cat_id) || + model->isObjectDescendentOf(current_cat_id, cat_id)) + { + return FALSE; + } + } + // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 + if ( is_in_friend_folder ) + { + // If object is direct descendent of current Friends subfolder than return false. + // Note: We can't use 'const LLInventoryCategory *cat', because it may be null + // in case type of obj_id is LLInventoryItem. + if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) + { + return FALSE; + } + } + } + } + return TRUE; + +} + +BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, + BOOL drop) +{ + // This should never happen, but if an inventory item is incorrectly parented, + // the UI will get confused and pass in a NULL. + if(!inv_cat) return FALSE; + + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if(!avatar) return FALSE; + + // cannot drag categories into library + if(!isAgentInventory()) + { + return FALSE; + } + + // check to make sure source is agent inventory, and is represented there. + LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); + BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL) + && (LLToolDragAndDrop::SOURCE_AGENT == source); + + BOOL accept = FALSE; + S32 i; + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + if(is_agent_inventory) + { + const LLUUID& cat_id = inv_cat->getUUID(); + + // Is the destination the trash? + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + BOOL move_is_into_trash = (mUUID == trash_id) + || model->isObjectDescendentOf(mUUID, trash_id); + BOOL is_movable = (!LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())); + const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); + if (move_is_into_current_outfit || move_is_into_outfit) + { + // BAP - restrictions? + is_movable = true; + } + + if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)) + { + is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604 + } + + if( is_movable ) + { + gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE ); + + for( i = 0; i < descendent_categories.count(); i++ ) + { + LLInventoryCategory* category = descendent_categories[i]; + if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) + { + // ...can't move "special folders" like Textures + is_movable = FALSE; + break; + } + } + + if( is_movable ) + { + if( move_is_into_trash ) + { + for( i = 0; i < descendent_items.count(); i++ ) + { + LLInventoryItem* item = descendent_items[i]; + if( (item->getType() == LLAssetType::AT_CLOTHING) || + (item->getType() == LLAssetType::AT_BODYPART) ) + { + if( gAgentWearables.isWearingItem( item->getUUID() ) ) + { + is_movable = FALSE; // It's generally movable, but not into the trash! + break; + } + } + else + if( item->getType() == LLAssetType::AT_OBJECT ) + { + if( avatar->isWearingAttachment( item->getUUID() ) ) + { + is_movable = FALSE; // It's generally movable, but not into the trash! + break; + } + } + } + } + } + } + + + accept = is_movable + && (mUUID != cat_id) // Can't move a folder into itself + && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing + && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity + if(accept && drop) + { + // Look for any gestures and deactivate them + if (move_is_into_trash) + { + for (i = 0; i < descendent_items.count(); i++) + { + LLInventoryItem* item = descendent_items[i]; + if (item->getType() == LLAssetType::AT_GESTURE + && LLGestureManager::instance().isGestureActive(item->getUUID())) + { + LLGestureManager::instance().deactivateGesture(item->getUUID()); + } + } + } + // if target is an outfit or current outfit folder we use link + if (move_is_into_current_outfit || move_is_into_outfit) + { + if (inv_cat->getPreferredType() == LLFolderType::FT_NONE) + { + if (move_is_into_current_outfit) + { + // traverse category and add all contents to currently worn. + BOOL append = true; + LLAppearanceManager::instance().wearInventoryCategory(inv_cat, false, append); + } + else + { + // Recursively create links in target outfit. + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(inv_cat->getUUID(), cats, items, LLInventoryModel::EXCLUDE_TRASH); + LLAppearanceManager::instance().linkAll(mUUID,items,NULL); + } + } + else + { +#if SUPPORT_ENSEMBLES + // BAP - should skip if dup. + if (move_is_into_current_outfit) + { + LLAppearanceManager::instance().addEnsembleLink(inv_cat); + } + else + { + LLPointer cb = NULL; + link_inventory_item( + gAgent.getID(), + inv_cat->getUUID(), + mUUID, + inv_cat->getName(), + LLAssetType::AT_LINK_FOLDER, + cb); + } +#endif + } + } + else + { + + // Reparent the folder and restamp children if it's moving + // into trash. + LLInvFVBridge::changeCategoryParent( + model, + (LLViewerInventoryCategory*)inv_cat, + mUUID, + move_is_into_trash); + } + } + } + else if(LLToolDragAndDrop::SOURCE_WORLD == source) + { + // content category has same ID as object itself + LLUUID object_id = inv_cat->getUUID(); + LLUUID category_id = mUUID; + accept = move_inv_category_world_to_agent(object_id, category_id, drop); + } + return accept; +} + +void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv) +{ + const char* dialog = NULL; + if (object->flagScripted()) + { + dialog = "MoveInventoryFromScriptedObject"; + } + else + { + dialog = "MoveInventoryFromObject"; + } + LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv)); +} + +// Move/copy all inventory items from the Contents folder of an in-world +// object to the agent's inventory, inside a given category. +BOOL move_inv_category_world_to_agent(const LLUUID& object_id, + const LLUUID& category_id, + BOOL drop, + void (*callback)(S32, void*), + void* user_data) +{ + // Make sure the object exists. If we allowed dragging from + // anonymous objects, it would be possible to bypass + // permissions. + // content category has same ID as object itself + LLViewerObject* object = gObjectList.findObject(object_id); + if(!object) + { + llinfos << "Object not found for drop." << llendl; + return FALSE; + } + + // this folder is coming from an object, as there is only one folder in an object, the root, + // we need to collect the entire contents and handle them as a group + InventoryObjectList inventory_objects; + object->getInventoryContents(inventory_objects); + + if (inventory_objects.empty()) + { + llinfos << "Object contents not found for drop." << llendl; + return FALSE; + } + + BOOL accept = TRUE; + BOOL is_move = FALSE; + + // coming from a task. Need to figure out if the person can + // move/copy this item. + InventoryObjectList::iterator it = inventory_objects.begin(); + InventoryObjectList::iterator end = inventory_objects.end(); + for ( ; it != end; ++it) + { + // coming from a task. Need to figure out if the person can + // move/copy this item. + LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions()); + if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) + && perm.allowTransferTo(gAgent.getID()))) +// || gAgent.isGodlike()) + { + accept = TRUE; + } + else if(object->permYouOwner()) + { + // If the object cannot be copied, but the object the + // inventory is owned by the agent, then the item can be + // moved from the task to agent inventory. + is_move = TRUE; + accept = TRUE; + } + else + { + accept = FALSE; + break; + } + } + + if(drop && accept) + { + it = inventory_objects.begin(); + InventoryObjectList::iterator first_it = inventory_objects.begin(); + LLMoveInv* move_inv = new LLMoveInv; + move_inv->mObjectID = object_id; + move_inv->mCategoryID = category_id; + move_inv->mCallback = callback; + move_inv->mUserData = user_data; + + for ( ; it != end; ++it) + { + two_uuids_t two(category_id, (*it)->getUUID()); + move_inv->mMoveList.push_back(two); + } + + if(is_move) + { + // Callback called from within here. + warn_move_inventory(object, move_inv); + } + else + { + LLNotification::Params params("MoveInventoryFromObject"); + params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); + LLNotifications::instance().forceResponse(params, 0); + } + } + return accept; +} + +bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat, + LLInventoryItem* item) +{ + // Valid COF items are: + // - links to wearables (body parts or clothing) + // - links to attachments + // - links to gestures + // - links to ensemble folders + LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); // BAP - safe? + if (linked_item) + { + LLAssetType::EType type = linked_item->getType(); + return (type == LLAssetType::AT_CLOTHING || + type == LLAssetType::AT_BODYPART || + type == LLAssetType::AT_GESTURE || + type == LLAssetType::AT_OBJECT); + } + else + { + LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe? + // BAP remove AT_NONE support after ensembles are fully working? + return (linked_category && + ((linked_category->getPreferredType() == LLFolderType::FT_NONE) || + (LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType())))); + } +} + + +bool LLFindWearables::operator()(LLInventoryCategory* cat, + LLInventoryItem* item) +{ + if(item) + { + if((item->getType() == LLAssetType::AT_CLOTHING) + || (item->getType() == LLAssetType::AT_BODYPART)) + { + return TRUE; + } + } + return FALSE; +} + + + +//Used by LLFolderBridge as callback for directory recursion. +class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver +{ +public: + LLRightClickInventoryFetchObserver() : + mCopyItems(false) + { }; + LLRightClickInventoryFetchObserver(const LLUUID& cat_id, bool copy_items) : + mCatID(cat_id), + mCopyItems(copy_items) + { }; + virtual void done() + { + // we've downloaded all the items, so repaint the dialog + LLFolderBridge::staticFolderOptionsMenu(); + + gInventory.removeObserver(this); + delete this; + } + + +protected: + LLUUID mCatID; + bool mCopyItems; + +}; + +//Used by LLFolderBridge as callback for directory recursion. +class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver +{ +public: + LLRightClickInventoryFetchDescendentsObserver(bool copy_items) : mCopyItems(copy_items) {} + ~LLRightClickInventoryFetchDescendentsObserver() {} + virtual void done(); +protected: + bool mCopyItems; +}; + +void LLRightClickInventoryFetchDescendentsObserver::done() +{ + // Avoid passing a NULL-ref as mCompleteFolders.front() down to + // gInventory.collectDescendents() + if( mCompleteFolders.empty() ) + { + llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl; + dec_busy_count(); + gInventory.removeObserver(this); + delete this; + return; + } + + // What we do here is get the complete information on the items in + // the library, and set up an observer that will wait for that to + // happen. + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(mCompleteFolders.front(), + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH); + S32 count = item_array.count(); +#if 0 // HACK/TODO: Why? + // This early causes a giant menu to get produced, and doesn't seem to be needed. + if(!count) + { + llwarns << "Nothing fetched in category " << mCompleteFolders.front() + << llendl; + dec_busy_count(); + gInventory.removeObserver(this); + delete this; + return; + } +#endif + + LLRightClickInventoryFetchObserver* outfit; + outfit = new LLRightClickInventoryFetchObserver(mCompleteFolders.front(), mCopyItems); + LLInventoryFetchObserver::item_ref_t ids; + for(S32 i = 0; i < count; ++i) + { + ids.push_back(item_array.get(i)->getUUID()); + } + + // clean up, and remove this as an observer since the call to the + // outfit could notify observers and throw us into an infinite + // loop. + dec_busy_count(); + gInventory.removeObserver(this); + delete this; + + // increment busy count and either tell the inventory to check & + // call done, or add this object to the inventory for observation. + inc_busy_count(); + + // do the fetch + outfit->fetchItems(ids); + outfit->done(); //Not interested in waiting and this will be right 99% of the time. +//Uncomment the following code for laggy Inventory UI. +/* if(outfit->isEverythingComplete()) + { + // everything is already here - call done. + outfit->done(); + } + else + { + // it's all on it's way - add an observer, and the inventory + // will call done for us when everything is here. + gInventory.addObserver(outfit); + }*/ +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryWearObserver +// +// Observer for "copy and wear" operation to support knowing +// when the all of the contents have been added to inventory. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLInventoryCopyAndWearObserver : public LLInventoryObserver +{ +public: + LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) :mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {} + virtual ~LLInventoryCopyAndWearObserver() {} + virtual void changed(U32 mask); + +protected: + LLUUID mCatID; + int mContentsCount; + BOOL mFolderAdded; +}; + + + +void LLInventoryCopyAndWearObserver::changed(U32 mask) +{ + if((mask & (LLInventoryObserver::ADD)) != 0) + { + if (!mFolderAdded) + { + const std::set& changed_items = gInventory.getChangedIDs(); + + std::set::const_iterator id_it = changed_items.begin(); + std::set::const_iterator id_end = changed_items.end(); + for (;id_it != id_end; ++id_it) + { + if ((*id_it) == mCatID) + { + mFolderAdded = TRUE; + break; + } + } + } + + if (mFolderAdded) + { + LLViewerInventoryCategory* category = gInventory.getCategory(mCatID); + + if (NULL == category) + { + llwarns << "gInventory.getCategory(" << mCatID + << ") was NULL" << llendl; + } + else + { + if (category->getDescendentCount() == + mContentsCount) + { + gInventory.removeObserver(this); + LLAppearanceManager::instance().wearInventoryCategory(category, FALSE, TRUE); + delete this; + } + } + } + + } +} + + + +void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("open" == action) + { + openItem(); + return; + } + else if ("paste" == action) + { + pasteFromClipboard(); + return; + } + else if ("paste_link" == action) + { + pasteLinkFromClipboard(); + return; + } + else if ("properties" == action) + { + showProperties(); + return; + } + else if ("replaceoutfit" == action) + { + modifyOutfit(FALSE); + return; + } +#if SUPPORT_ENSEMBLES + else if ("wearasensemble" == action) + { + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLViewerInventoryCategory* cat = getCategory(); + if(!cat) return; + LLAppearanceManager::instance().addEnsembleLink(cat,true); + return; + } +#endif + else if ("addtooutfit" == action) + { + modifyOutfit(TRUE); + return; + } + else if ("copy" == action) + { + copyToClipboard(); + return; + } + else if ("removefromoutfit" == action) + { + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLViewerInventoryCategory* cat = getCategory(); + if(!cat) return; + + remove_inventory_category_from_avatar ( cat ); + return; + } + else if ("purge" == action) + { + purgeItem(model, mUUID); + return; + } + else if ("restore" == action) + { + restoreItem(); + return; + } +} + +void LLFolderBridge::openItem() +{ + lldebugs << "LLFolderBridge::openItem()" << llendl; + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + if(mUUID.isNull()) return; + bool fetching_inventory = model->fetchDescendentsOf(mUUID); + // Only change folder type if we have the folder contents. + if (!fetching_inventory) + { + // Disabling this for now, it's causing crash when new items are added to folders + // since folder type may change before new item item has finished processing. + // determineFolderType(); + } +} + +void LLFolderBridge::closeItem() +{ + determineFolderType(); +} + +void LLFolderBridge::determineFolderType() +{ + if (isUpToDate()) + { + LLInventoryModel* model = getInventoryModel(); + LLViewerInventoryCategory* category = model->getCategory(mUUID); + category->determineFolderType(); + } +} + +BOOL LLFolderBridge::isItemRenameable() const +{ + LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory(); + if(cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) + && (cat->getOwnerID() == gAgent.getID())) + { + return TRUE; + } + return FALSE; +} + +void LLFolderBridge::restoreItem() +{ + LLViewerInventoryCategory* cat; + cat = (LLViewerInventoryCategory*)getCategory(); + if(cat) + { + LLInventoryModel* model = getInventoryModel(); + const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType())); + // do not restamp children on restore + LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE); + } +} + +LLFolderType::EType LLFolderBridge::getPreferredType() const +{ + LLFolderType::EType preferred_type = LLFolderType::FT_NONE; + LLViewerInventoryCategory* cat = getCategory(); + if(cat) + { + preferred_type = cat->getPreferredType(); + } + + return preferred_type; +} + +// Icons for folders are based on the preferred type +LLUIImagePtr LLFolderBridge::getIcon() const +{ + LLFolderType::EType preferred_type = LLFolderType::FT_NONE; + LLViewerInventoryCategory* cat = getCategory(); + if(cat) + { + preferred_type = cat->getPreferredType(); + } + return getIcon(preferred_type); +} + +LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type) +{ + // we only have one folder image now + return LLUI::getUIImage("Inv_FolderClosed"); +} + +BOOL LLFolderBridge::renameItem(const std::string& new_name) +{ + if(!isItemRenameable()) + return FALSE; + LLInventoryModel* model = getInventoryModel(); + if(!model) + return FALSE; + LLViewerInventoryCategory* cat = getCategory(); + if(cat && (cat->getName() != new_name)) + { + LLPointer new_cat = new LLViewerInventoryCategory(cat); + new_cat->rename(new_name); + new_cat->updateServer(FALSE); + model->updateCategory(new_cat); + + model->notifyObservers(); + } + // return FALSE because we either notified observers (& therefore + // rebuilt) or we didn't update. + return FALSE; +} + +BOOL LLFolderBridge::removeItem() +{ + if(!isItemRemovable()) + { + return FALSE; + } + const LLViewerInventoryCategory *cat = getCategory(); + + LLSD payload; + LLSD args; + args["FOLDERNAME"] = cat->getName(); + + LLNotification::Params params("ConfirmDeleteProtectedCategory"); + params.payload(payload).substitutions(args).functor.function(boost::bind(&LLFolderBridge::removeItemResponse, this, _1, _2)); + //params.functor.function(boost::bind(&LLFolderBridge::removeItemResponse, this, _1, _2)); + /* + LLNotification::Params params("ChangeLindenEstate"); + params.functor.function(boost::bind(&LLPanelEstateInfo::callbackChangeLindenEstate, this, _1, _2)); + */ + if (LLFolderType::lookupIsProtectedType(cat->getPreferredType())) + { + LLNotifications::instance().add(params); + } + else + { + LLNotifications::instance().forceResponse(params, 0); + } + return TRUE; +} + +bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + + // if they choose delete, do it. Otherwise, don't do anything + if(option == 0) + { + // move it to the trash + LLPreview::hide(mUUID); + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + + // Look for any gestures and deactivate them + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE ); + + S32 i; + for (i = 0; i < descendent_items.count(); i++) + { + LLInventoryItem* item = descendent_items[i]; + if (item->getType() == LLAssetType::AT_GESTURE + && LLGestureManager::instance().isGestureActive(item->getUUID())) + { + LLGestureManager::instance().deactivateGesture(item->getUUID()); + } + } + + // go ahead and do the normal remove if no 'last calling + // cards' are being removed. + LLViewerInventoryCategory* cat = getCategory(); + if(cat) + { + LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE); + } + return TRUE; + } + return FALSE; +} + +void LLFolderBridge::pasteFromClipboard() +{ + LLInventoryModel* model = getInventoryModel(); + if(model && isClipboardPasteable()) + { + LLInventoryItem* item = NULL; + LLDynamicArray objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.count(); + const LLUUID parent_id(mUUID); + for(S32 i = 0; i < count; i++) + { + item = model->getItem(objects.get(i)); + if (item) + { + if(LLInventoryClipboard::instance().isCutMode()) + { + // move_inventory_item() is not enough, + //we have to update inventory locally too + changeItemParent(model, dynamic_cast(item), parent_id, FALSE); + } + else + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + parent_id, + std::string(), + LLPointer(NULL)); + } + } + } + } +} + +void LLFolderBridge::pasteLinkFromClipboard() +{ + const LLInventoryModel* model = getInventoryModel(); + if(model) + { + LLDynamicArray objects; + LLInventoryClipboard::instance().retrieve(objects); + S32 count = objects.count(); + LLUUID parent_id(mUUID); + for(S32 i = 0; i < count; i++) + { + const LLUUID &object_id = objects.get(i); +#if SUPPORT_ENSEMBLES + if (LLInventoryCategory *cat = model->getCategory(object_id)) + { + link_inventory_item( + gAgent.getID(), + cat->getUUID(), + parent_id, + cat->getName(), + LLAssetType::AT_LINK_FOLDER, + LLPointer(NULL)); + } + else +#endif + if (LLInventoryItem *item = model->getItem(object_id)) + { + link_inventory_item( + gAgent.getID(), + item->getLinkedUUID(), + parent_id, + item->getName(), + LLAssetType::AT_LINK, + LLPointer(NULL)); + } + } + } +} + +void LLFolderBridge::staticFolderOptionsMenu() +{ + if (!sSelf) return; + sSelf->folderOptionsMenu(); +} + +bool isInOutfitsSidePanel(LLPanel *panel) +{ + LLInventoryPanel *my_panel = dynamic_cast(panel); + LLPanelOutfitsInventory *outfit_panel = + dynamic_cast(LLSideTray::getInstance()->getPanel("panel_outfits_inventory")); + if (!outfit_panel) + return false; + return outfit_panel->isAccordionPanel(my_panel); + + //LLInventoryPanel *outfit_inv_panel = outfit_panel ? outfit_panel->getActivePanel(): NULL; + //return (my_panel && (my_panel == outfit_inv_panel)); +} + +void LLFolderBridge::folderOptionsMenu() +{ + std::vector disabled_items; + + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + + const LLInventoryCategory* category = model->getCategory(mUUID); + LLFolderType::EType type = category->getPreferredType(); + const bool is_default_folder = category && LLFolderType::lookupIsProtectedType(type); + // BAP change once we're no longer treating regular categories as ensembles. + const bool is_ensemble = category && (type == LLFolderType::FT_NONE || + LLFolderType::lookupIsEnsembleType(type)); + const bool is_sidepanel = isInOutfitsSidePanel(mInventoryPanel.get()); + + // calling card related functionality for folders. + + if (is_sidepanel) + { + mItems.clear(); + mItems.push_back("Rename"); + mItems.push_back("Delete"); + } + + // Only enable calling-card related options for non-default folders. + if (!is_sidepanel && !is_default_folder) + { + LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); + if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) + { + mItems.push_back(std::string("Calling Card Separator")); + mItems.push_back(std::string("Conference Chat Folder")); + mItems.push_back(std::string("IM All Contacts In Folder")); + } + } + + // wearables related functionality for folders. + //is_wearable + LLFindWearables is_wearable; + LLIsType is_object( LLAssetType::AT_OBJECT ); + LLIsType is_gesture( LLAssetType::AT_GESTURE ); + + if (mWearables || + checkFolderForContentsOfType(model, is_wearable) || + checkFolderForContentsOfType(model, is_object) || + checkFolderForContentsOfType(model, is_gesture) ) + { + mItems.push_back(std::string("Folder Wearables Separator")); + + // Only enable add/replace outfit for non-default folders. + if (!is_default_folder) + { + mItems.push_back(std::string("Add To Outfit")); + mItems.push_back(std::string("Replace Outfit")); + } + if (is_ensemble) + { + mItems.push_back(std::string("Wear As Ensemble")); + } + mItems.push_back(std::string("Remove From Outfit")); + } + hide_context_entries(*mMenu, mItems, disabled_items); + + // Reposition the menu, in case we're adding items to an existing menu. + mMenu->needsArrange(); + mMenu->arrangeAndClear(); +} + +BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + model->collectDescendentsIf(mUUID, + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_type); + return ((item_array.count() > 0) ? TRUE : FALSE ); +} + +// Flags unused +void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + mItems.clear(); + mDisabledItems.clear(); + + lldebugs << "LLFolderBridge::buildContextMenu()" << llendl; +// std::vector disabled_items; + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); + + mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point) + mDisabledItems.clear(); //adding code to clear out disabled members from previous + if (lost_and_found_id == mUUID) + { + // This is the lost+found folder. + mItems.push_back(std::string("Empty Lost And Found")); + } + + if(trash_id == mUUID) + { + // This is the trash. + mItems.push_back(std::string("Empty Trash")); + } + else if(model->isObjectDescendentOf(mUUID, trash_id)) + { + // This is a folder in the trash. + mItems.clear(); // clear any items that used to exist + mItems.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + mDisabledItems.push_back(std::string("Purge Item")); + } + + mItems.push_back(std::string("Restore Item")); + } + else if(isAgentInventory()) // do not allow creating in library + { + LLViewerInventoryCategory *cat = getCategory(); + // BAP removed protected check to re-enable standard ops in untyped folders. + // Not sure what the right thing is to do here. + if (!isCOFFolder() && cat /*&& + LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/) + { + // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. + if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) + mItems.push_back(std::string("New Folder")); + mItems.push_back(std::string("New Script")); + mItems.push_back(std::string("New Note")); + mItems.push_back(std::string("New Gesture")); + mItems.push_back(std::string("New Clothes")); + mItems.push_back(std::string("New Body Parts")); + mItems.push_back(std::string("Change Type")); + + LLViewerInventoryCategory *cat = getCategory(); + if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) + { + mDisabledItems.push_back(std::string("Change Type")); + } + + getClipboardEntries(false, mItems, mDisabledItems, flags); + } + else + { + // Want some but not all of the items from getClipboardEntries for outfits. + if (cat && cat->getPreferredType()==LLFolderType::FT_OUTFIT) + { + mItems.push_back(std::string("Rename")); + mItems.push_back(std::string("Delete")); + } + } + + //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06 + mCallingCards = mWearables = FALSE; + + LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); + if (checkFolderForContentsOfType(model, is_callingcard)) + { + mCallingCards=TRUE; + } + + LLFindWearables is_wearable; + LLIsType is_object( LLAssetType::AT_OBJECT ); + LLIsType is_gesture( LLAssetType::AT_GESTURE ); + + if (checkFolderForContentsOfType(model, is_wearable) || + checkFolderForContentsOfType(model, is_object) || + checkFolderForContentsOfType(model, is_gesture) ) + { + mWearables=TRUE; + } + + mMenu = &menu; + sSelf = this; + LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE); + + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); + if (category) + { + folders.push_back(category->getUUID()); + } + fetch->fetchDescendents(folders); + inc_busy_count(); + if(fetch->isEverythingComplete()) + { + // everything is already here - call done. + fetch->done(); + } + else + { + // it's all on it's way - add an observer, and the inventory + // will call done for us when everything is here. + gInventory.addObserver(fetch); + } + } + else + { + mItems.push_back(std::string("--no options--")); + mDisabledItems.push_back(std::string("--no options--")); + } + hide_context_entries(menu, mItems, mDisabledItems); +} + +BOOL LLFolderBridge::hasChildren() const +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + LLInventoryModel::EHasChildren has_children; + has_children = gInventory.categoryHasChildren(mUUID); + return has_children != LLInventoryModel::CHILDREN_NO; +} + +BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data) +{ + //llinfos << "LLFolderBridge::dragOrDrop()" << llendl; + BOOL accept = FALSE; + switch(cargo_type) + { + case DAD_TEXTURE: + case DAD_SOUND: + case DAD_CALLINGCARD: + case DAD_LANDMARK: + case DAD_SCRIPT: + case DAD_OBJECT: + case DAD_NOTECARD: + case DAD_CLOTHING: + case DAD_BODYPART: + case DAD_ANIMATION: + case DAD_GESTURE: + case DAD_LINK: + accept = dragItemIntoFolder((LLInventoryItem*)cargo_data, + drop); + break; + case DAD_CATEGORY: + if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID)) + { + accept = FALSE; + } + else + { + accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop); + } + break; + default: + break; + } + return accept; +} + +LLViewerInventoryCategory* LLFolderBridge::getCategory() const +{ + LLViewerInventoryCategory* cat = NULL; + LLInventoryModel* model = getInventoryModel(); + if(model) + { + cat = (LLViewerInventoryCategory*)model->getCategory(mUUID); + } + return cat; +} + + +// static +void LLFolderBridge::pasteClipboard(void* user_data) +{ + LLFolderBridge* self = (LLFolderBridge*)user_data; + if(self) self->pasteFromClipboard(); +} + +void LLFolderBridge::createNewCategory(void* user_data) +{ + LLFolderBridge* bridge = (LLFolderBridge*)user_data; + if(!bridge) return; + LLInventoryPanel* panel = dynamic_cast(bridge->mInventoryPanel.get()); + if (!panel) return; + LLInventoryModel* model = panel->getModel(); + if(!model) return; + LLUUID id; + id = model->createNewCategory(bridge->getUUID(), + LLFolderType::FT_NONE, + LLStringUtil::null); + model->notifyObservers(); + + // At this point, the bridge has probably been deleted, but the + // view is still there. + panel->setSelection(id, TAKE_FOCUS_YES); +} + +void LLFolderBridge::createNewShirt(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHIRT); +} + +void LLFolderBridge::createNewPants(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_PANTS); +} + +void LLFolderBridge::createNewShoes(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHOES); +} + +void LLFolderBridge::createNewSocks(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SOCKS); +} + +void LLFolderBridge::createNewJacket(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_JACKET); +} + +void LLFolderBridge::createNewSkirt(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIRT); +} + +void LLFolderBridge::createNewGloves(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_GLOVES); +} + +void LLFolderBridge::createNewUndershirt(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERSHIRT); +} + +void LLFolderBridge::createNewUnderpants(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERPANTS); +} + +void LLFolderBridge::createNewShape(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHAPE); +} + +void LLFolderBridge::createNewSkin(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIN); +} + +void LLFolderBridge::createNewHair(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_HAIR); +} + +void LLFolderBridge::createNewEyes(void* user_data) +{ + LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_EYES); +} + +// static +void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type) +{ + if(!bridge) return; + LLUUID parent_id = bridge->getUUID(); + createWearable(parent_id, type); +} + +// Separate function so can be called by global menu as well as right-click +// menu. +// static +void LLFolderBridge::createWearable(const LLUUID &parent_id, EWearableType type) +{ + LLWearable* wearable = LLWearableList::instance().createNewWearable(type); + LLAssetType::EType asset_type = wearable->getAssetType(); + LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE; + create_inventory_item(gAgent.getID(), gAgent.getSessionID(), + parent_id, wearable->getTransactionID(), wearable->getName(), + wearable->getDescription(), asset_type, inv_type, wearable->getType(), + wearable->getPermissions().getMaskNextOwner(), + LLPointer(NULL)); +} + +void LLFolderBridge::modifyOutfit(BOOL append) +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLViewerInventoryCategory* cat = getCategory(); + if(!cat) return; + + // BAP - was: + // wear_inventory_category_on_avatar( cat, append ); + LLAppearanceManager::instance().wearInventoryCategory( cat, FALSE, append ); +} + +// helper stuff +bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv) +{ + LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData; + LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID); + S32 option = LLNotification::getSelectedOption(notification, response); + + if(option == 0 && object) + { + if (cat_and_wear && cat_and_wear->mWear) + { + InventoryObjectList inventory_objects; + object->getInventoryContents(inventory_objects); + int contents_count = inventory_objects.size()-1; //subtract one for containing folder + + LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count); + gInventory.addObserver(inventoryObserver); + } + + two_uuids_list_t::iterator move_it; + for (move_it = move_inv->mMoveList.begin(); + move_it != move_inv->mMoveList.end(); + ++move_it) + { + object->moveInventory(move_it->first, move_it->second); + } + + // update the UI. + dialog_refresh_all(); + } + + if (move_inv->mCallback) + { + move_inv->mCallback(option, move_inv->mUserData); + } + + delete move_inv; + return false; +} + +/* +Next functions intended to reorder items in the inventory folder and save order on server +Is now used for Favorites folder. + +*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel +*/ +void saveItemsOrder(LLInventoryModel::item_array_t& items) +{ + int sortField = 0; + + // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field + for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) + { + LLViewerInventoryItem* item = *i; + + item->setSortField(++sortField); + item->setComplete(TRUE); + item->updateServer(FALSE); + + gInventory.updateItem(item); + } + + gInventory.notifyObservers(); +} + +LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id) +{ + LLInventoryModel::item_array_t::iterator result = items.end(); + + for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) + { + if ((*i)->getUUID() == id) + { + result = i; + break; + } + } + + return result; +} + +void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId) +{ + LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId); + LLViewerInventoryItem* destItem = gInventory.getItem(destItemId); + + items.erase(findItemByUUID(items, srcItem->getUUID())); + items.insert(findItemByUUID(items, destItem->getUUID()), srcItem); +} + +BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, + BOOL drop) +{ + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + + // cannot drag into library + if(!isAgentInventory()) + { + return FALSE; + } + + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if(!avatar) return FALSE; + + LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); + BOOL accept = FALSE; + LLViewerObject* object = NULL; + if(LLToolDragAndDrop::SOURCE_AGENT == source) + { + + BOOL is_movable = TRUE; + switch( inv_item->getActualType() ) + { + case LLAssetType::AT_CATEGORY: + is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType()); + break; + default: + break; + } + + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); + const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); + + if(is_movable && move_is_into_trash) + { + switch(inv_item->getType()) + { + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID()); + break; + + case LLAssetType::AT_OBJECT: + is_movable = !avatar->isWearingAttachment(inv_item->getUUID()); + break; + default: + break; + } + } + + if ( is_movable ) + { + // Don't allow creating duplicates in the Calling Card/Friends + // subfolders, see bug EXT-1599. Check is item direct descendent + // of target folder and forbid item's movement if it so. + // Note: isItemDirectDescendentOfCategory checks if + // passed category is in the Calling Card/Friends folder + is_movable = ! LLFriendCardsManager::instance() + .isObjDirectDescendentOfCategory (inv_item, getCategory()); + } + + const LLUUID& favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + const LLUUID& landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK); + const BOOL folder_allows_reorder = ((mUUID == landmarks_id) || (mUUID == favorites_id)); + + // we can move item inside a folder only if this folder is Favorites. See EXT-719 + accept = is_movable && ((mUUID != inv_item->getParentUUID()) || folder_allows_reorder); + if(accept && drop) + { + if (inv_item->getType() == LLAssetType::AT_GESTURE + && LLGestureManager::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash) + { + LLGestureManager::instance().deactivateGesture(inv_item->getUUID()); + } + // If an item is being dragged between windows, unselect + // everything in the active window so that we don't follow + // the selection to its new location (which is very + // annoying). + if (LLFloaterInventory::getActiveInventory()) + { + LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel(); + LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + if (active_panel && (panel != active_panel)) + { + active_panel->unSelectAll(); + } + } + + // if dragging from/into favorites folder only reorder items + if ((mUUID == inv_item->getParentUUID()) && folder_allows_reorder) + { + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLIsType is_type(LLAssetType::AT_LANDMARK); + model->collectDescendentsIf(mUUID, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + + LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; + if (itemp) + { + LLUUID srcItemId = inv_item->getUUID(); + LLUUID destItemId = itemp->getListener()->getUUID(); + + // update order + updateItemsOrder(items, srcItemId, destItemId); + + saveItemsOrder(items); + } + } + else if (favorites_id == mUUID) // if target is the favorites folder we use copy + { + copy_inventory_item( + gAgent.getID(), + inv_item->getPermissions().getOwner(), + inv_item->getUUID(), + mUUID, + std::string(), + LLPointer(NULL)); + } + else if (move_is_into_current_outfit || move_is_into_outfit) + { + // BAP - should skip if dup. + if (move_is_into_current_outfit) + { + LLAppearanceManager::instance().addCOFItemLink(inv_item); + } + else + { + LLPointer cb = NULL; + link_inventory_item( + gAgent.getID(), + inv_item->getLinkedUUID(), + mUUID, + inv_item->getName(), + LLAssetType::AT_LINK, + cb); + } + } + else + { + // restamp if the move is into the trash. + LLInvFVBridge::changeItemParent( + model, + (LLViewerInventoryItem*)inv_item, + mUUID, + move_is_into_trash); + } + } + } + else if(LLToolDragAndDrop::SOURCE_WORLD == source) + { + // Make sure the object exists. If we allowed dragging from + // anonymous objects, it would be possible to bypass + // permissions. + object = gObjectList.findObject(inv_item->getParentUUID()); + if(!object) + { + llinfos << "Object not found for drop." << llendl; + return FALSE; + } + + // coming from a task. Need to figure out if the person can + // move/copy this item. + LLPermissions perm(inv_item->getPermissions()); + BOOL is_move = FALSE; + if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) + && perm.allowTransferTo(gAgent.getID()))) +// || gAgent.isGodlike()) + + { + accept = TRUE; + } + else if(object->permYouOwner()) + { + // If the object cannot be copied, but the object the + // inventory is owned by the agent, then the item can be + // moved from the task to agent inventory. + is_move = TRUE; + accept = TRUE; + } + if(drop && accept) + { + LLMoveInv* move_inv = new LLMoveInv; + move_inv->mObjectID = inv_item->getParentUUID(); + two_uuids_t item_pair(mUUID, inv_item->getUUID()); + move_inv->mMoveList.push_back(item_pair); + move_inv->mCallback = NULL; + move_inv->mUserData = NULL; + if(is_move) + { + warn_move_inventory(object, move_inv); + } + else + { + LLNotification::Params params("MoveInventoryFromObject"); + params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); + LLNotifications::instance().forceResponse(params, 0); + } + } + + } + else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) + { + accept = TRUE; + if(drop) + { + copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(), + LLToolDragAndDrop::getInstance()->getSourceID(), inv_item); + } + } + else if(LLToolDragAndDrop::SOURCE_LIBRARY == source) + { + LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item; + if(item && item->isComplete()) + { + accept = TRUE; + if(drop) + { + copy_inventory_item( + gAgent.getID(), + inv_item->getPermissions().getOwner(), + inv_item->getUUID(), + mUUID, + std::string(), + LLPointer(NULL)); + } + } + } + else + { + llwarns << "unhandled drag source" << llendl; + } + return accept; +} + +// +=================================================+ +// | LLScriptBridge (DEPRECTED) | +// +=================================================+ + +LLUIImagePtr LLScriptBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE); +} + +// +=================================================+ +// | LLTextureBridge | +// +=================================================+ + +LLUIImagePtr LLTextureBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE); +} + +void LLTextureBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +} + +void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLTextureBridge::buildContextMenu()" << llendl; + std::vector items; + std::vector disabled_items; + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + + items.push_back(std::string("Texture Separator")); + items.push_back(std::string("Save As")); + } + hide_context_entries(menu, items, disabled_items); +} + +// virtual +void LLTextureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("save_as" == action) + { + LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); + LLPreviewTexture* preview_texture = LLFloaterReg::findTypedInstance("preview_texture", mUUID); + if (preview_texture) + { + preview_texture->openToSave(); + } + } + else LLItemBridge::performAction(folder, model, action); +} + +// +=================================================+ +// | LLSoundBridge | +// +=================================================+ + +LLUIImagePtr LLSoundBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE); +} + +void LLSoundBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +/* +// Changed this back to the way it USED to work: +// only open the preview dialog through the contextual right-click menu +// double-click just plays the sound + + LLViewerInventoryItem* item = getItem(); + if(item) + { + openSoundPreview((void*)this); + //send_uuid_sound_trigger(item->getAssetUUID(), 1.0); + } +*/ +} + +void LLSoundBridge::previewItem() +{ + LLViewerInventoryItem* item = getItem(); + if(item) + { + send_sound_trigger(item->getAssetUUID(), 1.0); + } +} + +void LLSoundBridge::openSoundPreview(void* which) +{ + LLSoundBridge *me = (LLSoundBridge *)which; + LLFloaterReg::showInstance("preview_sound", LLSD(me->mUUID), TAKE_FOCUS_YES); +} + +void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLSoundBridge::buildContextMenu()" << llendl; + std::vector items; + std::vector disabled_items; + + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Sound Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + } + + items.push_back(std::string("Sound Separator")); + items.push_back(std::string("Sound Play")); + + hide_context_entries(menu, items, disabled_items); +} + +// +=================================================+ +// | LLLandmarkBridge | +// +=================================================+ + +LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) : +LLItemBridge(inventory, uuid) +{ + mVisited = FALSE; + if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED) + { + mVisited = TRUE; + } +} + +LLUIImagePtr LLLandmarkBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE); +} + +void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + std::vector items; + std::vector disabled_items; + + lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl; + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Landmark Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + } + + items.push_back(std::string("Landmark Separator")); + items.push_back(std::string("About Landmark")); + + // Disable "About Landmark" menu item for + // multiple landmarks selected. Only one landmark + // info panel can be shown at a time. + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("About Landmark")); + } + + hide_context_entries(menu, items, disabled_items); +} + +// Convenience function for the two functions below. +void teleport_via_landmark(const LLUUID& asset_id) +{ + gAgent.teleportViaLandmark( asset_id ); + + // we now automatically track the landmark you're teleporting to + // because you'll probably arrive at a telehub instead + LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); + if( floater_world_map ) + { + floater_world_map->trackLandmark( asset_id ); + } +} + +// virtual +void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("teleport" == action) + { + LLViewerInventoryItem* item = getItem(); + if(item) + { + teleport_via_landmark(item->getAssetUUID()); + } + } + else if ("about" == action) + { + LLViewerInventoryItem* item = getItem(); + if(item) + { + LLSD key; + key["type"] = "landmark"; + key["id"] = item->getUUID(); + + LLSideTray::getInstance()->showPanel("panel_places", key); + } + } + else + { + LLItemBridge::performAction(folder, model, action); + } +} + +static bool open_landmark_callback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + + LLUUID asset_id = notification["payload"]["asset_id"].asUUID(); + if (option == 0) + { + teleport_via_landmark(asset_id); + } + + return false; +} +static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFromLandmark", open_landmark_callback); + + +void LLLandmarkBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +/* + LLViewerInventoryItem* item = getItem(); + if( item ) + { + // Opening (double-clicking) a landmark immediately teleports, + // but warns you the first time. + // open_landmark(item); + LLSD payload; + payload["asset_id"] = item->getAssetUUID(); + LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); + } +*/ +} + + +// +=================================================+ +// | LLCallingCardObserver | +// +=================================================+ +void LLCallingCardObserver::changed(U32 mask) +{ + mBridgep->refreshFolderViewItem(); +} + +// +=================================================+ +// | LLCallingCardBridge | +// +=================================================+ + +LLCallingCardBridge::LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ) : + LLItemBridge(inventory, uuid) +{ + mObserver = new LLCallingCardObserver(this); + LLAvatarTracker::instance().addObserver(mObserver); +} + +LLCallingCardBridge::~LLCallingCardBridge() +{ + LLAvatarTracker::instance().removeObserver(mObserver); + delete mObserver; +} + +void LLCallingCardBridge::refreshFolderViewItem() +{ + LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL; + if (itemp) + { + itemp->refresh(); + } +} + +// virtual +void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("begin_im" == action) + { + LLViewerInventoryItem *item = getItem(); + if (item && (item->getCreatorUUID() != gAgent.getID()) && + (!item->getCreatorUUID().isNull())) + { + std::string callingcard_name; + gCacheName->getFullName(item->getCreatorUUID(), callingcard_name); + LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID()); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } + } + } + else if ("lure" == action) + { + LLViewerInventoryItem *item = getItem(); + if (item && (item->getCreatorUUID() != gAgent.getID()) && + (!item->getCreatorUUID().isNull())) + { + LLAvatarActions::offerTeleport(item->getCreatorUUID()); + } + } + else LLItemBridge::performAction(folder, model, action); +} + +LLUIImagePtr LLCallingCardBridge::getIcon() const +{ + BOOL online = FALSE; + LLViewerInventoryItem* item = getItem(); + if(item) + { + online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()); + } + return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE); +} + +std::string LLCallingCardBridge::getLabelSuffix() const +{ + LLViewerInventoryItem* item = getItem(); + if( item && LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()) ) + { + return LLItemBridge::getLabelSuffix() + " (online)"; + } + else + { + return LLItemBridge::getLabelSuffix(); + } +} + +void LLCallingCardBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +/* + LLViewerInventoryItem* item = getItem(); + if(item && !item->getCreatorUUID().isNull()) + { + LLAvatarActions::showProfile(item->getCreatorUUID()); + } +*/ +} + +void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl; + std::vector items; + std::vector disabled_items; + + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + + LLInventoryItem* item = getItem(); + BOOL good_card = (item + && (LLUUID::null != item->getCreatorUUID()) + && (item->getCreatorUUID() != gAgent.getID())); + BOOL user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID())); + items.push_back(std::string("Send Instant Message Separator")); + items.push_back(std::string("Send Instant Message")); + items.push_back(std::string("Offer Teleport...")); + items.push_back(std::string("Conference Chat")); + + if (!good_card) + { + disabled_items.push_back(std::string("Send Instant Message")); + } + if (!good_card || !user_online) + { + disabled_items.push_back(std::string("Offer Teleport...")); + disabled_items.push_back(std::string("Conference Chat")); + } + } + hide_context_entries(menu, items, disabled_items); +} + +BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data) +{ + LLViewerInventoryItem* item = getItem(); + BOOL rv = FALSE; + if(item) + { + // check the type + switch(cargo_type) + { + case DAD_TEXTURE: + case DAD_SOUND: + case DAD_LANDMARK: + case DAD_SCRIPT: + case DAD_CLOTHING: + case DAD_OBJECT: + case DAD_NOTECARD: + case DAD_BODYPART: + case DAD_ANIMATION: + case DAD_GESTURE: + { + LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; + const LLPermissions& perm = inv_item->getPermissions(); + if(gInventory.getItem(inv_item->getUUID()) + && perm.allowOperationBy(PERM_TRANSFER, gAgent.getID())) + { + rv = TRUE; + if(drop) + { + LLToolDragAndDrop::giveInventory(item->getCreatorUUID(), + (LLInventoryItem*)cargo_data); + } + } + else + { + // It's not in the user's inventory (it's probably in + // an object's contents), so disallow dragging it here. + // You can't give something you don't yet have. + rv = FALSE; + } + break; + } + case DAD_CATEGORY: + { + LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data; + if( gInventory.getCategory( inv_cat->getUUID() ) ) + { + rv = TRUE; + if(drop) + { + LLToolDragAndDrop::giveInventoryCategory( + item->getCreatorUUID(), + inv_cat); + } + } + else + { + // It's not in the user's inventory (it's probably in + // an object's contents), so disallow dragging it here. + // You can't give something you don't yet have. + rv = FALSE; + } + break; + } + default: + break; + } + } + return rv; +} + +BOOL LLCallingCardBridge::removeItem() +{ + if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem())) + { + LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID()); + return FALSE; + } + else + { + return LLItemBridge::removeItem(); + } +} +// +=================================================+ +// | LLNotecardBridge | +// +=================================================+ + +LLUIImagePtr LLNotecardBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE); +} + +void LLNotecardBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } + +/* + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES); + } +*/ +} + + +// +=================================================+ +// | LLGestureBridge | +// +=================================================+ + +LLUIImagePtr LLGestureBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE); +} + +LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const +{ + if( LLGestureManager::instance().isGestureActive(mUUID) ) + { + return LLFontGL::BOLD; + } + else + { + return LLFontGL::NORMAL; + } +} + +std::string LLGestureBridge::getLabelSuffix() const +{ + if( LLGestureManager::instance().isGestureActive(mUUID) ) + { + return LLItemBridge::getLabelSuffix() + " (active)"; + } + else + { + return LLItemBridge::getLabelSuffix(); + } +} + +// virtual +void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("activate" == action) + { + LLGestureManager::instance().activateGesture(mUUID); + + LLViewerInventoryItem* item = gInventory.getItem(mUUID); + if (!item) return; + + // Since we just changed the suffix to indicate (active) + // the server doesn't need to know, just the viewer. + gInventory.updateItem(item); + gInventory.notifyObservers(); + } + else if ("deactivate" == action) + { + LLGestureManager::instance().deactivateGesture(mUUID); + + LLViewerInventoryItem* item = gInventory.getItem(mUUID); + if (!item) return; + + // Since we just changed the suffix to indicate (active) + // the server doesn't need to know, just the viewer. + gInventory.updateItem(item); + gInventory.notifyObservers(); + } + else LLItemBridge::performAction(folder, model, action); +} + +void LLGestureBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +/* + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null); + preview->setFocus(TRUE); + } +*/ +} + +BOOL LLGestureBridge::removeItem() +{ + // Force close the preview window, if it exists + LLGestureManager::instance().deactivateGesture(mUUID); + return LLItemBridge::removeItem(); +} + +void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLGestureBridge::buildContextMenu()" << llendl; + std::vector items; + std::vector disabled_items; + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + + items.push_back(std::string("Gesture Separator")); + items.push_back(std::string("Activate")); + items.push_back(std::string("Deactivate")); + } + hide_context_entries(menu, items, disabled_items); +} + +// +=================================================+ +// | LLAnimationBridge | +// +=================================================+ + +LLUIImagePtr LLAnimationBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE); +} + +void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + std::vector items; + std::vector disabled_items; + + lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl; + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Animation Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + } + + items.push_back(std::string("Animation Separator")); + items.push_back(std::string("Animation Play")); + items.push_back(std::string("Animation Audition")); + + hide_context_entries(menu, items, disabled_items); + +} + +// virtual +void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ((action == "playworld") || (action == "playlocal")) + { + if (getItem()) + { + LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE; + if ("playworld" == action) activate = LLPreviewAnim::PLAY; + if ("playlocal" == action) activate = LLPreviewAnim::AUDITION; + + LLPreviewAnim* preview = LLFloaterReg::showTypedInstance("preview_anim", LLSD(mUUID)); + if (preview) + { + preview->activate(activate); + } + } + } + else + { + LLItemBridge::performAction(folder, model, action); + } +} + +void LLAnimationBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } +/* + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); + } +*/ +} + +// +=================================================+ +// | LLObjectBridge | +// +=================================================+ + +// static +LLUUID LLObjectBridge::sContextMenuItemID; + +LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) : +LLItemBridge(inventory, uuid), mInvType(type) +{ + mAttachPt = (flags & 0xff); // low bye of inventory flags + + mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE; +} + +LLUIImagePtr LLObjectBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject ); +} + +LLInventoryObject* LLObjectBridge::getObject() const +{ + LLInventoryObject* object = NULL; + LLInventoryModel* model = getInventoryModel(); + if(model) + { + object = (LLInventoryObject*)model->getObject(mUUID); + } + return object; +} + +// virtual +void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("attach" == action) + { + LLUUID object_id = mUUID; + LLViewerInventoryItem* item; + item = (LLViewerInventoryItem*)gInventory.getItem(object_id); + if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID())) + { + rez_attachment(item, NULL); + } + else if(item && item->isComplete()) + { + // must be in library. copy it to our inventory and put it on. + LLPointer cb = new RezAttachmentCallback(0); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + gFocusMgr.setKeyboardFocus(NULL); + } + else if ("detach" == action) + { + LLInventoryItem* item = gInventory.getItem(mUUID); + if(item) + { + gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); + gMessageSystem->sendReliable( gAgent.getRegion()->getHost()); + } + // this object might have been selected, so let the selection manager know it's gone now + LLViewerObject *found_obj = gObjectList.findObject(item->getLinkedUUID()); + if (found_obj) + { + LLSelectMgr::getInstance()->remove(found_obj); + } + } + else LLItemBridge::performAction(folder, model, action); +} + +void LLObjectBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } + + LLSD key; + key["id"] = mUUID; + LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); + + // Disable old properties floater; this is replaced by the sidepanel. + /* + LLFloaterReg::showInstance("properties", mUUID); + */ +} + +LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const +{ + U8 font = LLFontGL::NORMAL; + + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if( avatar && avatar->isWearingAttachment( mUUID ) ) + { + font |= LLFontGL::BOLD; + } + + LLInventoryItem* item = getItem(); + if (item && item->getIsLinkType()) + { + font |= LLFontGL::ITALIC; + } + + return (LLFontGL::StyleFlags)font; +} + +std::string LLObjectBridge::getLabelSuffix() const +{ + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if( avatar && avatar->isWearingAttachment( mUUID ) ) + { + std::string attachment_point_name = avatar->getAttachedPointName(mUUID); + + // e.g. "(worn on ...)" / "(attached to ...)" + LLStringUtil::format_map_t args; + args["[ATTACHMENT_POINT]"] = attachment_point_name.c_str(); + return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args); + } + else + { + return LLItemBridge::getLabelSuffix(); + } +} + +void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment) +{ + LLSD payload; + payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link. + + S32 attach_pt = 0; + if (gAgent.getAvatarObject() && attachment) + { + for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin(); + iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter) + { + if (iter->second == attachment) + { + attach_pt = iter->first; + break; + } + } + } + + payload["attachment_point"] = attach_pt; + +#if !ENABLE_MULTIATTACHMENTS + if (attachment && attachment->getNumObjects() > 0) + { + LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez); + } + else +#endif + { + LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/); + } +} + +bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response) +{ + LLVOAvatar *avatarp = gAgent.getAvatarObject(); + + if (!avatarp->canAttachMoreObjects()) + { + LLSD args; + args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS); + LLNotifications::instance().add("MaxAttachmentsOnOutfit", args); + return false; + } + + S32 option = LLNotification::getSelectedOption(notification, response); + if (option == 0/*YES*/) + { + LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID()); + + if (itemp) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID()); + msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner()); + U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); +#if ENABLE_MULTIATTACHMENTS + attachment_pt |= ATTACHMENT_ADD; +#endif + msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); + pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions()); + msg->addStringFast(_PREHASH_Name, itemp->getName()); + msg->addStringFast(_PREHASH_Description, itemp->getDescription()); + msg->sendReliable(gAgent.getRegion()->getHost()); + } + } + return false; +} +static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_replace_attachment_rez); + +void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + std::vector items; + std::vector disabled_items; + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Properties")); + + LLInventoryItem *item = getItem(); + getClipboardEntries(true, items, disabled_items, flags); + + LLObjectBridge::sContextMenuItemID = mUUID; + + if(item) + { + LLVOAvatarSelf* avatarp = gAgent.getAvatarObject(); + if( !avatarp ) + { + return; + } + + if( avatarp->isWearingAttachment( mUUID ) ) + { + items.push_back(std::string("Detach From Yourself")); + } + else + if( !isInTrash() && !isLinkedObjectInTrash() ) + { + items.push_back(std::string("Attach Separator")); + items.push_back(std::string("Object Wear")); + items.push_back(std::string("Attach To")); + items.push_back(std::string("Attach To HUD")); + // commented out for DEV-32347 + //items.push_back(std::string("Restore to Last Position")); + + if (!avatarp->canAttachMoreObjects()) + { + disabled_items.push_back(std::string("Object Wear")); + disabled_items.push_back(std::string("Attach To")); + disabled_items.push_back(std::string("Attach To HUD")); + } + LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE); + LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE); + LLVOAvatar *avatarp = gAgent.getAvatarObject(); + if (attach_menu + && (attach_menu->getChildCount() == 0) + && attach_hud_menu + && (attach_hud_menu->getChildCount() == 0) + && avatarp) + { + for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); + iter != avatarp->mAttachmentPoints.end(); ) + { + LLVOAvatar::attachment_map_t::iterator curiter = iter++; + LLViewerJointAttachment* attachment = curiter->second; + LLMenuItemCallGL::Params p; + std::string submenu_name = attachment->getName(); + if (LLTrans::getString(submenu_name) != "") + { + p.name = (" ")+LLTrans::getString(submenu_name)+" "; + } + else + { + p.name = submenu_name; + } + LLSD cbparams; + cbparams["index"] = curiter->first; + cbparams["label"] = attachment->getName(); + p.on_click.function_name = "Inventory.AttachObject"; + p.on_click.parameter = LLSD(attachment->getName()); + p.on_enable.function_name = "Attachment.Label"; + p.on_enable.parameter = cbparams; + LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu; + LLUICtrlFactory::create(p, parent); + } + } + } + } + } + hide_context_entries(menu, items, disabled_items); +} + +BOOL LLObjectBridge::renameItem(const std::string& new_name) +{ + if(!isItemRenameable()) + return FALSE; + LLPreview::dirty(mUUID); + LLInventoryModel* model = getInventoryModel(); + if(!model) + return FALSE; + LLViewerInventoryItem* item = getItem(); + if(item && (item->getName() != new_name)) + { + LLPointer new_item = new LLViewerInventoryItem(item); + new_item->rename(new_name); + buildDisplayName(new_item, mDisplayName); + new_item->updateServer(FALSE); + model->updateItem(new_item); + + model->notifyObservers(); + + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if( avatar ) + { + LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() ); + if( obj ) + { + LLSelectMgr::getInstance()->deselectAll(); + LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE ); + LLSelectMgr::getInstance()->selectionSetObjectName( new_name ); + LLSelectMgr::getInstance()->deselectAll(); + } + } + } + // return FALSE because we either notified observers (& therefore + // rebuilt) or we didn't update. + return FALSE; +} + +// +=================================================+ +// | LLLSLTextBridge | +// +=================================================+ + +LLUIImagePtr LLLSLTextBridge::getIcon() const +{ + return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE); +} + +void LLLSLTextBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } + /* + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES); + } + */ +} + +// +=================================================+ +// | LLWearableBridge | +// +=================================================+ + +// *NOTE: hack to get from avatar inventory to avatar +void wear_inventory_item_on_avatar( LLInventoryItem* item ) +{ + if(item) + { + lldebugs << "wear_inventory_item_on_avatar( " << item->getName() + << " )" << llendl; + + LLAppearanceManager::instance().addCOFItemLink(item); + } +} + +void wear_add_inventory_item_on_avatar( LLInventoryItem* item ) +{ + if(item) + { + lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName() + << " )" << llendl; + + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), + LLWearableBridge::onWearAddOnAvatarArrived, + new LLUUID(item->getUUID())); + } +} + +void remove_inventory_category_from_avatar( LLInventoryCategory* category ) +{ + if(!category) return; + lldebugs << "remove_inventory_category_from_avatar( " << category->getName() + << " )" << llendl; + + + if( gFloaterCustomize ) + { + gFloaterCustomize->askToSaveIfDirty( + boost::bind(remove_inventory_category_from_avatar_step2, _1, category->getUUID())); + } + else + { + remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() ); + } +} + +struct OnRemoveStruct +{ + LLUUID mUUID; + OnRemoveStruct(const LLUUID& uuid): + mUUID(uuid) + { + } +}; + +void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id) +{ + + // Find all the wearables that are in the category's subtree. + lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl; + if(proceed) + { + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + LLFindWearables is_wearable; + gInventory.collectDescendentsIf(category_id, + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_wearable); + S32 i; + S32 wearable_count = item_array.count(); + + LLInventoryModel::cat_array_t obj_cat_array; + LLInventoryModel::item_array_t obj_item_array; + LLIsType is_object( LLAssetType::AT_OBJECT ); + gInventory.collectDescendentsIf(category_id, + obj_cat_array, + obj_item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_object); + S32 obj_count = obj_item_array.count(); + + // Find all gestures in this folder + LLInventoryModel::cat_array_t gest_cat_array; + LLInventoryModel::item_array_t gest_item_array; + LLIsType is_gesture( LLAssetType::AT_GESTURE ); + gInventory.collectDescendentsIf(category_id, + gest_cat_array, + gest_item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_gesture); + S32 gest_count = gest_item_array.count(); + + if (wearable_count > 0) //Loop through wearables. If worn, remove. + { + for(i = 0; i < wearable_count; ++i) + { + LLViewerInventoryItem *item = item_array.get(i); + if (item->getType() == LLAssetType::AT_BODYPART) + continue; + if (gAgent.isTeen() && item->isWearableType() && + (item->getWearableType() == WT_UNDERPANTS || item->getWearableType() == WT_UNDERSHIRT)) + continue; + if( gAgentWearables.isWearingItem (item->getLinkedUUID()) ) + { + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), + LLWearableBridge::onRemoveFromAvatarArrived, + new OnRemoveStruct(item->getLinkedUUID())); + } + } + } + + if (obj_count > 0) + { + for(i = 0; i < obj_count; ++i) + { + LLViewerInventoryItem *obj_item = obj_item_array.get(i); + gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item->getLinkedUUID() ); + + gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); + + // this object might have been selected, so let the selection manager know it's gone now + LLViewerObject *found_obj = gObjectList.findObject( obj_item->getLinkedUUID()); + if (found_obj) + { + LLSelectMgr::getInstance()->remove(found_obj); + } + } + } + + if (gest_count > 0) + { + for(i = 0; i < gest_count; ++i) + { + LLViewerInventoryItem *gest_item = gest_item_array.get(i); + if ( LLGestureManager::instance().isGestureActive( gest_item->getLinkedUUID()) ) + { + LLGestureManager::instance().deactivateGesture( gest_item->getLinkedUUID() ); + gInventory.updateItem( gest_item ); + gInventory.notifyObservers(); + } + + } + } + } +} + +BOOL LLWearableBridge::renameItem(const std::string& new_name) +{ + if( gAgentWearables.isWearingItem( mUUID ) ) + { + gAgentWearables.setWearableName( mUUID, new_name ); + } + return LLItemBridge::renameItem(new_name); +} + +std::string LLWearableBridge::getLabelSuffix() const +{ + if( gAgentWearables.isWearingItem( mUUID ) ) + { + // e.g. "(worn)" + return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); + } + else + { + return LLItemBridge::getLabelSuffix(); + } +} + +LLUIImagePtr LLWearableBridge::getIcon() const +{ + return get_item_icon(mAssetType, mInvType, mWearableType, FALSE); +} + +// virtual +void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("wear" == action) + { + wearOnAvatar(); + } + else if ("wear_add" == action) + { + wearAddOnAvatar(); + } + else if ("edit" == action) + { + editOnAvatar(); + return; + } + else if ("take_off" == action) + { + if(gAgentWearables.isWearingItem(mUUID)) + { + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), + LLWearableBridge::onRemoveFromAvatarArrived, + new OnRemoveStruct(mUUID)); + } + } + } + else LLItemBridge::performAction(folder, model, action); +} + +void LLWearableBridge::openItem() +{ + LLViewerInventoryItem* item = getItem(); + + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); + } + /* + if( isInTrash() ) + { + LLNotifications::instance().add("CannotWearTrash"); + } + else if(isAgentInventory()) + { + if( !gAgentWearables.isWearingItem( mUUID ) ) + { + wearOnAvatar(); + } + } + else + { + // must be in the inventory library. copy it to our inventory + // and put it on right away. + LLViewerInventoryItem* item = getItem(); + if(item && item->isComplete()) + { + LLPointer cb = new WearOnAvatarCallback(); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + else if(item) + { + // *TODO: We should fetch the item details, and then do + // the operation above. + LLNotifications::instance().add("CannotWearInfoNotComplete"); + } + } + */ +} + +void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLWearableBridge::buildContextMenu()" << llendl; + std::vector items; + std::vector disabled_items; + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere + BOOL no_open = ((flags & SUPPRESS_OPEN_ITEM) == SUPPRESS_OPEN_ITEM); + + // If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976 + LLViewerInventoryItem* item = getItem(); + if( !no_open && item ) + { + no_open = (item->getType() == LLAssetType::AT_CLOTHING) || + (item->getType() == LLAssetType::AT_BODYPART); + } + if (!no_open) + { + items.push_back(std::string("Open")); + } + + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + + items.push_back(std::string("Wearable Separator")); + + items.push_back(std::string("Wearable Wear")); + items.push_back(std::string("Wearable Add")); + items.push_back(std::string("Wearable Edit")); + + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Wearable Edit")); + } + // Don't allow items to be worn if their baseobj is in the trash. + if (isLinkedObjectInTrash()) + { + disabled_items.push_back(std::string("Wearable Wear")); + disabled_items.push_back(std::string("Wearable Add")); + disabled_items.push_back(std::string("Wearable Edit")); + } + + // Disable wear and take off based on whether the item is worn. + if(item) + { + switch (item->getType()) + { + case LLAssetType::AT_CLOTHING: + items.push_back(std::string("Take Off")); + case LLAssetType::AT_BODYPART: + if (gAgentWearables.isWearingItem(item->getUUID())) + { + disabled_items.push_back(std::string("Wearable Wear")); + disabled_items.push_back(std::string("Wearable Add")); + } + else + { + disabled_items.push_back(std::string("Take Off")); + } + break; + default: + break; + } + } + } + hide_context_entries(menu, items, disabled_items); +} + +// Called from menus +// static +BOOL LLWearableBridge::canWearOnAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(!self) return FALSE; + if(!self->isAgentInventory()) + { + LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem(); + if(!item || !item->isComplete()) return FALSE; + } + return (!gAgentWearables.isWearingItem(self->mUUID)); +} + +// Called from menus +// static +void LLWearableBridge::onWearOnAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(!self) return; + self->wearOnAvatar(); +} + +void LLWearableBridge::wearOnAvatar() +{ + // Don't wear anything until initial wearables are loaded, can + // destroy clothing items. + if (!gAgentWearables.areWearablesLoaded()) + { + LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); + return; + } + + LLViewerInventoryItem* item = getItem(); + if(item) + { + if(!isAgentInventory()) + { + LLPointer cb = new WearOnAvatarCallback(); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + else + { + wear_inventory_item_on_avatar(item); + } + } +} + +void LLWearableBridge::wearAddOnAvatar() +{ + // Don't wear anything until initial wearables are loaded, can + // destroy clothing items. + if (!gAgentWearables.areWearablesLoaded()) + { + LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); + return; + } + + LLViewerInventoryItem* item = getItem(); + if(item) + { + if(!isAgentInventory()) + { + LLPointer cb = new WearOnAvatarCallback(); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + else + { + wear_add_inventory_item_on_avatar(item); + } + } +} + +// static +void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata ) +{ + LLUUID* item_id = (LLUUID*) userdata; + if(wearable) + { + LLViewerInventoryItem* item = NULL; + item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); + if(item) + { + if(item->getAssetUUID() == wearable->getAssetID()) + { + gAgentWearables.setWearableItem(item, wearable); + gInventory.notifyObservers(); + //self->getFolderItem()->refreshFromRoot(); + } + else + { + llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl; + } + } + } + delete item_id; +} + +// static +// BAP remove the "add" code path once everything is fully COF-ified. +void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata ) +{ + LLUUID* item_id = (LLUUID*) userdata; + if(wearable) + { + LLViewerInventoryItem* item = NULL; + item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); + if(item) + { + if(item->getAssetUUID() == wearable->getAssetID()) + { + bool do_append = true; + gAgentWearables.setWearableItem(item, wearable, do_append); + gInventory.notifyObservers(); + //self->getFolderItem()->refreshFromRoot(); + } + else + { + llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl; + } + } + } + delete item_id; +} + +// static +BOOL LLWearableBridge::canEditOnAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(!self) return FALSE; + + return (gAgentWearables.isWearingItem(self->mUUID)); +} + +// static +void LLWearableBridge::onEditOnAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(self) + { + self->editOnAvatar(); + } +} + +void LLWearableBridge::editOnAvatar() +{ + const LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID); + if( wearable ) + { + // Set the tab to the right wearable. + if (gFloaterCustomize) + gFloaterCustomize->setCurrentWearableType( wearable->getType() ); + + if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() ) + { + // Start Avatar Customization + gAgent.changeCameraToCustomizeAvatar(); + } + } +} + +// static +BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if( self && (LLAssetType::AT_BODYPART != self->mAssetType) ) + { + return gAgentWearables.isWearingItem( self->mUUID ); + } + return FALSE; +} + +// static +void LLWearableBridge::onRemoveFromAvatar(void* user_data) +{ + LLWearableBridge* self = (LLWearableBridge*)user_data; + if(!self) return; + if(gAgentWearables.isWearingItem(self->mUUID)) + { + LLViewerInventoryItem* item = self->getItem(); + if (item) + { + LLUUID parent_id = item->getParentUUID(); + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), + onRemoveFromAvatarArrived, + new OnRemoveStruct(LLUUID(self->mUUID))); + } + } +} + +// static +void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, + void* userdata) +{ + OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata; + const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID); + if(wearable) + { + if( gAgentWearables.isWearingItem( item_id ) ) + { + EWearableType type = wearable->getType(); + + if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&& + //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) ) + { + // MULTI_WEARABLE: FIXME HACK - always remove all + bool do_remove_all = false; + gAgentWearables.removeWearable( type, do_remove_all, 0 ); + } + } + } + + // Find and remove this item from the COF. + LLInventoryModel::item_array_t items = gInventory.collectLinkedItems(item_id, LLAppearanceManager::instance().getCOF()); + llassert(items.size() == 1); // Should always have one and only one item linked to this in the COF. + for (LLInventoryModel::item_array_t::const_iterator iter = items.begin(); + iter != items.end(); + ++iter) + { + const LLViewerInventoryItem *linked_item = (*iter); + const LLUUID &item_id = linked_item->getUUID(); + gInventory.purgeObject(item_id); + } + gInventory.notifyObservers(); + + delete on_remove_struct; +} + +LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type, + const LLUUID& uuid,LLInventoryModel* model) +{ + LLInvFVBridgeAction* action = NULL; + switch(asset_type) + { + case LLAssetType::AT_TEXTURE: + action = new LLTextureBridgeAction(uuid,model); + break; + + case LLAssetType::AT_SOUND: + action = new LLSoundBridgeAction(uuid,model); + break; + + case LLAssetType::AT_LANDMARK: + action = new LLLandmarkBridgeAction(uuid,model); + break; + + case LLAssetType::AT_CALLINGCARD: + action = new LLCallingCardBridgeAction(uuid,model); + break; + + case LLAssetType::AT_OBJECT: + action = new LLObjectBridgeAction(uuid,model); + break; + + case LLAssetType::AT_NOTECARD: + action = new LLNotecardBridgeAction(uuid,model); + break; + + case LLAssetType::AT_ANIMATION: + action = new LLAnimationBridgeAction(uuid,model); + break; + + case LLAssetType::AT_GESTURE: + action = new LLGestureBridgeAction(uuid,model); + break; + + case LLAssetType::AT_LSL_TEXT: + action = new LLLSLTextBridgeAction(uuid,model); + break; + + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + action = new LLWearableBridgeAction(uuid,model); + + break; + + default: + break; + } + return action; +} + +//static +void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type, + const LLUUID& uuid,LLInventoryModel* model) +{ + LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); + if(action) + { + action->doIt(); + delete action; + } +} + +//static +void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model) +{ + LLAssetType::EType asset_type = model->getItem(uuid)->getType(); + LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); + if(action) + { + action->doIt(); + delete action; + } +} + +LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const +{ + if(mModel) + return (LLViewerInventoryItem*)mModel->getItem(mUUID); + return NULL; +} + +//virtual +void LLTextureBridgeAction::doIt() +{ + if (getItem()) + { + LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); + } + + LLInvFVBridgeAction::doIt(); +} + +//virtual +void LLSoundBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if(item) + { + LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES); + } + + LLInvFVBridgeAction::doIt(); +} + + +//virtual +void LLLandmarkBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if( item ) + { + // Opening (double-clicking) a landmark immediately teleports, + // but warns you the first time. + LLSD payload; + payload["asset_id"] = item->getAssetUUID(); + LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); + } + + LLInvFVBridgeAction::doIt(); +} + + +//virtual +void LLCallingCardBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if(item && item->getCreatorUUID().notNull()) + { + LLAvatarActions::showProfile(item->getCreatorUUID()); + } + + LLInvFVBridgeAction::doIt(); +} + +//virtual +void +LLNotecardBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES); + } + + LLInvFVBridgeAction::doIt(); +} + +//virtual +void LLGestureBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null); + preview->setFocus(TRUE); + } + + LLInvFVBridgeAction::doIt(); +} + +//virtual +void LLAnimationBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); + } + + LLInvFVBridgeAction::doIt(); +} + + +//virtual +void LLObjectBridgeAction::doIt() +{ + LLFloaterReg::showInstance("properties", mUUID); + + LLInvFVBridgeAction::doIt(); +} + + +//virtual +void LLLSLTextBridgeAction::doIt() +{ + LLViewerInventoryItem* item = getItem(); + if (item) + { + LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES); + } + + LLInvFVBridgeAction::doIt(); +} + + +BOOL LLWearableBridgeAction::isInTrash() const +{ + if(!mModel) return FALSE; + const LLUUID trash_id = mModel->findCategoryUUIDForType(LLFolderType::FT_TRASH); + return mModel->isObjectDescendentOf(mUUID, trash_id); +} + +BOOL LLWearableBridgeAction::isAgentInventory() const +{ + if(!mModel) return FALSE; + if(gInventory.getRootFolderID() == mUUID) return TRUE; + return mModel->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); +} + +void LLWearableBridgeAction::wearOnAvatar() +{ + // Don't wear anything until initial wearables are loaded, can + // destroy clothing items. + if (!gAgentWearables.areWearablesLoaded()) + { + LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); + return; + } + + LLViewerInventoryItem* item = getItem(); + if(item) + { + if(!isAgentInventory()) + { + LLPointer cb = new WearOnAvatarCallback(); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + else + { + wear_inventory_item_on_avatar(item); + } + } +} + +//virtual +void LLWearableBridgeAction::doIt() +{ + if(isInTrash()) + { + LLNotifications::instance().add("CannotWearTrash"); + } + else if(isAgentInventory()) + { + if(!gAgentWearables.isWearingItem(mUUID)) + { + wearOnAvatar(); + } + } + else + { + // must be in the inventory library. copy it to our inventory + // and put it on right away. + LLViewerInventoryItem* item = getItem(); + if(item && item->isComplete()) + { + LLPointer cb = new WearOnAvatarCallback(); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + else if(item) + { + // *TODO: We should fetch the item details, and then do + // the operation above. + LLNotifications::instance().add("CannotWearInfoNotComplete"); + } + } + + LLInvFVBridgeAction::doIt(); +} + +// +=================================================+ +// | LLLinkItemBridge | +// +=================================================+ +// For broken links + +std::string LLLinkItemBridge::sPrefix("Link: "); + + +LLUIImagePtr LLLinkItemBridge::getIcon() const +{ + if (LLViewerInventoryItem *item = getItem()) + { + return get_item_icon(item->getActualType(), LLInventoryType::IT_NONE, 0, FALSE); + } + return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE); +} + +void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + // *TODO: Translate + lldebugs << "LLLink::buildContextMenu()" << llendl; + std::vector items; + std::vector disabled_items; + + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Delete")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Delete")); + } + } + hide_context_entries(menu, items, disabled_items); +} + + +// +=================================================+ +// | LLLinkBridge | +// +=================================================+ +// For broken links. + +std::string LLLinkFolderBridge::sPrefix("Link: "); + + +LLUIImagePtr LLLinkFolderBridge::getIcon() const +{ + LLFolderType::EType preferred_type = LLFolderType::FT_NONE; + if (LLViewerInventoryItem *item = getItem()) + { + if (const LLViewerInventoryCategory* cat = item->getLinkedCategory()) + { + preferred_type = cat->getPreferredType(); + } + } + return LLFolderBridge::getIcon(preferred_type); +} + +void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + // *TODO: Translate + lldebugs << "LLLink::buildContextMenu()" << llendl; + std::vector items; + std::vector disabled_items; + + if(isInTrash()) + { + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + + items.push_back(std::string("Restore Item")); + } + else + { + items.push_back(std::string("Find Original")); + items.push_back(std::string("Delete")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Delete")); + } + } + hide_context_entries(menu, items, disabled_items); +} + +void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("goto" == action) + { + gotoItem(folder); + return; + } + LLItemBridge::performAction(folder,model,action); +} + +void LLLinkFolderBridge::gotoItem(LLFolderView *folder) +{ + const LLUUID &cat_uuid = getFolderID(); + if (!cat_uuid.isNull()) + { + if (LLFolderViewItem *base_folder = folder->getItemByID(cat_uuid)) + { + if (LLInventoryModel* model = getInventoryModel()) + { + model->fetchDescendentsOf(cat_uuid); + } + base_folder->setOpen(TRUE); + folder->setSelectionFromRoot(base_folder,TRUE); + folder->scrollToShowSelection(); + } + } +} + +const LLUUID &LLLinkFolderBridge::getFolderID() const +{ + if (LLViewerInventoryItem *link_item = getItem()) + { + if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory()) + { + const LLUUID& cat_uuid = cat->getUUID(); + return cat_uuid; + } + } + return LLUUID::null; +} -- cgit v1.2.3 From aa1cbd144fcfe4dce7a95a2b8259f149b92380e7 Mon Sep 17 00:00:00 2001 From: "Justin C. Rounds (Chuck)" Date: Tue, 1 Dec 2009 12:23:53 -0500 Subject: Increased height on object content inventory panel. http://jira.secondlife.com/browse/EXT-2906 --- indra/newview/skins/default/xui/en/floater_tools.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 636e9d465a..b6996fdb10 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2780,7 +2780,7 @@ even though the user gets a free copy. width="130" /> Date: Tue, 1 Dec 2009 12:41:13 -0500 Subject: EXT-2922 : 2nd inventroy shouldn't list "New Window" as an option, since it silently fails Fixed the behavior so that New Window brings up a new floater inventory window instead of doing nothing. --HG-- branch : avatar-pipeline --- indra/newview/llfloaterinventory.cpp | 6 +++++- indra/newview/skins/default/xui/en/floater_inventory.xml | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp index db38fc0fb3..4a2e1913cd 100644 --- a/indra/newview/llfloaterinventory.cpp +++ b/indra/newview/llfloaterinventory.cpp @@ -107,10 +107,14 @@ LLInventoryPanel* LLFloaterInventory::getPanel() // static LLFloaterInventory* LLFloaterInventory::showAgentInventory() { + // Hack to generate semi-unique key for each inventory floater. + static S32 instance_num = 0; + instance_num = (instance_num + 1) % S32_MAX; + LLFloaterInventory* iv = NULL; if (!gAgent.cameraMouselook()) { - iv = LLFloaterReg::showTypedInstance("inventory", LLSD()); + iv = LLFloaterReg::showTypedInstance("inventory", LLSD(instance_num)); } return iv; } diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml index dca1692e4a..ff9f0daee6 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory.xml @@ -11,7 +11,7 @@ help_topic="inventory" save_rect="true" save_visibility="true" - single_instance="true" + single_instance="false" title="INVENTORY" width="467"> Date: Tue, 1 Dec 2009 19:42:42 +0200 Subject: Fixed critical bug EXT-2990 (Viewer crashes after openning "Voice Control" on IM floater) -- added disconnecting from subscribed signals while destroying participant list -- added disconnecting from subscribed signals while destroying Voice controls -- added nullifying of the pointer to speaker manager when channel is changed --HG-- branch : product-engine --- indra/newview/llcallfloater.cpp | 5 ++++- indra/newview/llcallfloater.h | 2 ++ indra/newview/llparticipantlist.cpp | 10 +++++++--- indra/newview/llparticipantlist.h | 5 +++++ 4 files changed, 18 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index 1b929eca0e..7db709086f 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -54,6 +54,7 @@ LLCallFloater::LLCallFloater(const LLSD& key) LLCallFloater::~LLCallFloater() { + mChannelChangedConnection.disconnect(); delete mPaticipants; mPaticipants = NULL; } @@ -77,7 +78,7 @@ BOOL LLCallFloater::postBuild() updateSession(); // subscribe to to be notified Voice Channel is changed - LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::onCurrentChannelChanged, this, _1)); + mChannelChangedConnection = LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::onCurrentChannelChanged, this, _1)); return TRUE; } @@ -157,6 +158,8 @@ void LLCallFloater::refreshPartisipantList() void LLCallFloater::onCurrentChannelChanged(const LLUUID& /*session_id*/) { + // Forget speaker manager from the previous session to avoid using it after session was destroyed. + mSpeakerManager = NULL; updateSession(); } diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index 8a440873ff..3112b8e81b 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -90,6 +90,8 @@ private: LLParticipantList* mPaticipants; LLAvatarList* mAvatarList; EVoiceControls mVoiceType; + + boost::signals2::connection mChannelChangedConnection; }; diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 07a1214b4f..13f195a1be 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -64,10 +64,10 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator"); mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData")); - mAvatarList->setDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); - mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2)); + mAvatarListDoubleClickConnection = mAvatarList->setDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); + mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2)); // Set onAvatarListDoubleClicked as default on_return action. - mAvatarList->setReturnCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); + mAvatarListReturnConnection = mAvatarList->setReturnCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); if (use_context_menu) { @@ -99,6 +99,10 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av LLParticipantList::~LLParticipantList() { + mAvatarListDoubleClickConnection.disconnect(); + mAvatarListRefreshConnection.disconnect(); + mAvatarListReturnConnection.disconnect(); + delete mParticipantListMenu; mParticipantListMenu = NULL; } diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 460cf4b9ef..86b38f5f1e 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -151,4 +151,9 @@ class LLParticipantList LLParticipantListMenu* mParticipantListMenu; EParticipantSortOrder mSortOrder; + + // boost::connections + boost::signals2::connection mAvatarListDoubleClickConnection; + boost::signals2::connection mAvatarListRefreshConnection; + boost::signals2::connection mAvatarListReturnConnection; }; -- cgit v1.2.3 From f0f0572868c3ea08014395cb5e757654cc0eb7dc Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Tue, 1 Dec 2009 12:43:36 -0500 Subject: EXT-2964 : Can drag-and-drop a folder with links onto an object EXT-3012 : Cleanup LLToolDragAndDrop Now checking if folder contents have links before allowing object drop. Did some superficial cleanup of lltooldraganddrop files. --HG-- branch : avatar-pipeline --- indra/newview/lltooldraganddrop.cpp | 85 +++++++++++++++++++++++-------------- indra/newview/lltooldraganddrop.h | 4 -- 2 files changed, 52 insertions(+), 37 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 93910ce4a5..0790838d3d 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -383,6 +383,7 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary() addEntry(DAD_GESTURE, new DragAndDropEntry(&dad3dNULL, &dad3dActivateGesture, &dad3dGiveInventory, &dad3dUpdateInventory, &dad3dNULL)); addEntry(DAD_LINK, new DragAndDropEntry(&dad3dNULL, &dad3dNULL, &dad3dNULL, &dad3dNULL, &dad3dNULL)); // TODO: animation on self could play it? edit it? + // TODO: gesture on self could play it? edit it? }; LLToolDragAndDrop::LLToolDragAndDrop() @@ -1826,10 +1827,11 @@ BOOL LLToolDragAndDrop::isInventoryGroupGiveAcceptable(LLInventoryItem* item) EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item) { // check the basics - if(!item || !obj) return ACCEPT_NO; + if (!item || !obj) return ACCEPT_NO; // HACK: downcast LLViewerInventoryItem* vitem = (LLViewerInventoryItem*)item; - if(!vitem->isComplete()) return ACCEPT_NO; + if (!vitem->isComplete()) return ACCEPT_NO; + if (vitem->getIsLinkType()) return ACCEPT_NO; // No giving away links // deny attempts to drop from an object onto itself. This is to // help make sure that drops that are from an object to an object @@ -1839,7 +1841,7 @@ EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LL { return ACCEPT_NO; } - + //BOOL copy = (perm.allowCopyBy(gAgent.getID(), // gAgent.getGroupID()) // && (obj->mPermModify || obj->mFlagAllowInventoryAdd)); @@ -2478,24 +2480,30 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( LLViewerObject* obj, S32 face, MASK mask, BOOL drop) { lldebugs << "LLToolDragAndDrop::dad3dUpdateInventoryCategory()" << llendl; - if (NULL==obj) + if (obj == NULL) { llwarns << "obj is NULL; aborting func with ACCEPT_NO" << llendl; return ACCEPT_NO; } - if (mSource != SOURCE_AGENT && mSource != SOURCE_LIBRARY) + if ((mSource != SOURCE_AGENT) && (mSource != SOURCE_LIBRARY)) { return ACCEPT_NO; } - if(obj->isAttachment()) return ACCEPT_NO_LOCKED; - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; + if (obj->isAttachment()) + { + return ACCEPT_NO_LOCKED; + } + + LLViewerInventoryItem* item = NULL; + LLViewerInventoryCategory* cat = NULL; locateInventory(item, cat); - if(!cat) return ACCEPT_NO; - EAcceptance rv = ACCEPT_NO; + if (!cat) + { + return ACCEPT_NO; + } - // find all the items in the category + // Find all the items in the category LLDroppableItem droppable(!obj->permYouOwner()); LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; @@ -2505,7 +2513,7 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( LLInventoryModel::EXCLUDE_TRASH, droppable); cats.put(cat); - if(droppable.countNoCopy() > 0) + if (droppable.countNoCopy() > 0) { llwarns << "*** Need to confirm this step" << llendl; } @@ -2519,46 +2527,57 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( } } + EAcceptance rv = ACCEPT_NO; + // Check for accept - S32 i; - S32 count = cats.count(); - for(i = 0; i < count; ++i) + for (LLInventoryModel::cat_array_t::const_iterator cat_iter = cats.begin(); + cat_iter != cats.end(); + ++cat_iter) { - rv = gInventory.isCategoryComplete(cats.get(i)->getUUID()) ? ACCEPT_YES_MULTI : ACCEPT_NO; + const LLViewerInventoryCategory *cat = (*cat_iter); + rv = gInventory.isCategoryComplete(cat->getUUID()) ? ACCEPT_YES_MULTI : ACCEPT_NO; if(rv < ACCEPT_YES_SINGLE) { - lldebugs << "Category " << cats.get(i)->getUUID() - << "is not complete." << llendl; + lldebugs << "Category " << cat->getUUID() << "is not complete." << llendl; break; } } - if(ACCEPT_YES_COPY_SINGLE <= rv) + if (ACCEPT_YES_COPY_SINGLE <= rv) { - count = items.count(); - for(i = 0; i < count; ++i) + for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin(); + item_iter != items.end(); + ++item_iter) { - rv = willObjectAcceptInventory(root_object, items.get(i)); - if(rv < ACCEPT_YES_COPY_SINGLE) + LLViewerInventoryItem *item = (*item_iter); + /* + // Pass the base objects, not the links. + if (item && item->getIsLinkType()) + { + item = item->getLinkedItem(); + (*item_iter) = item; + } + */ + rv = willObjectAcceptInventory(root_object, item); + if (rv < ACCEPT_YES_COPY_SINGLE) { - lldebugs << "Object will not accept " - << items.get(i)->getUUID() << llendl; + lldebugs << "Object will not accept " << item->getUUID() << llendl; break; } } } - // if every item is accepted, go ahead and send it on. - if(drop && (ACCEPT_YES_COPY_SINGLE <= rv)) + // If every item is accepted, send it on + if (drop && (ACCEPT_YES_COPY_SINGLE <= rv)) { - S32 count = items.count(); LLInventoryFetchObserver::item_ref_t ids; - for(i = 0; i < count; ++i) + for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin(); + item_iter != items.end(); + ++item_iter) { - //dropInventory(root_object, items.get(i), mSource, mSourceID); - ids.push_back(items.get(i)->getUUID()); + const LLViewerInventoryItem *item = (*item_iter); + ids.push_back(item->getUUID()); } - LLCategoryDropObserver* dropper; - dropper = new LLCategoryDropObserver(obj->getID(), mSource); + LLCategoryDropObserver* dropper = new LLCategoryDropObserver(obj->getID(), mSource); dropper->fetchItems(ids); if(dropper->isEverythingComplete()) { diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 7f352db15f..79b2bc32a3 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -141,10 +141,6 @@ protected: enddrag_signal_t mEndDragSignal; - // array of pointers to functions that implement the logic to - // dragging and dropping into the simulator. - static dragOrDrop3dImpl sDragAndDrop3d[DAD_COUNT][DT_COUNT]; - protected: // 3d drop functions. these call down into the static functions // named drop if drop is TRUE and permissions allow -- cgit v1.2.3 From 3b340326cb72a2724709d9c073f068b3644e7732 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Tue, 1 Dec 2009 18:06:36 +0000 Subject: EXT-332: Hide international billing features until enabled. The international billing links and labels in the Buy L$ floater are now hidden by default. They will only be displayed once we get an estimate from the server that includes an "estimatedLocalCost" token, i.e., we are connected to a server that has the international billing functionality enabled. This is done so that the new functionality in Viewer 2.0 is not exposed to the user until the international billing features are live (which is scheduled to happen after the Viewer 2.0 release date). --- indra/newview/llcurrencyuimanager.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp index 319cbf8209..544711a862 100644 --- a/indra/newview/llcurrencyuimanager.cpp +++ b/indra/newview/llcurrencyuimanager.cpp @@ -85,6 +85,7 @@ public: S32 mUSDCurrencyEstimatedCost; bool mLocalCurrencyEstimated; std::string mLocalCurrencyEstimatedCost; + bool mSupportsInternationalBilling; std::string mSiteConfirm; bool mBought; @@ -137,6 +138,7 @@ LLCurrencyUIManager::Impl::Impl(LLPanel& dialog) mError(false), mUserCurrencyBuy(2000), // note, this is a default, real value set in llfloaterbuycurrency.cpp mUserEnteredCurrencyBuy(false), + mSupportsInternationalBilling(false), mBought(false), mTransactionType(TransactionNone), mTransaction(0), mCurrencyChanged(false) @@ -207,6 +209,7 @@ void LLCurrencyUIManager::Impl::finishCurrencyInfo() if (mLocalCurrencyEstimated) { mLocalCurrencyEstimatedCost = currency["estimatedLocalCost"].asString(); + mSupportsInternationalBilling = true; } S32 newCurrencyBuy = currency["currencyBuy"].asInt(); @@ -464,6 +467,9 @@ void LLCurrencyUIManager::Impl::updateUI() mPanel.childSetTextArg("currency_est", "[LOCALAMOUNT]", getLocalEstimate()); mPanel.childSetVisible("currency_est", hasEstimate() && mUserCurrencyBuy > 0); + mPanel.childSetVisible("currency_links", mSupportsInternationalBilling); + mPanel.childSetVisible("exchange_rate_note", mSupportsInternationalBilling); + if (mPanel.childIsEnabled("buy_btn") ||mPanel.childIsVisible("currency_est") || mPanel.childIsVisible("error_web")) -- cgit v1.2.3 From 3385ce87f14f71d739a3834fbf3436a962fbdd9d Mon Sep 17 00:00:00 2001 From: Andrew Dyukov Date: Tue, 1 Dec 2009 20:10:18 +0200 Subject: Implemented major task EXT-2986 (Add "Leave Call" button in Voice Control Panel for all voice chats except nearby). --HG-- branch : product-engine --- indra/newview/llcallfloater.cpp | 14 +++++++++++ indra/newview/llcallfloater.h | 6 +++-- .../default/xui/en/floater_voice_controls.xml | 27 ++++++++++++++++++++-- 3 files changed, 43 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index 7db709086f..d6ae4603b4 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -64,6 +64,7 @@ BOOL LLCallFloater::postBuild() { LLDockableFloater::postBuild(); mAvatarList = getChild("speakers_list"); + childSetAction("leave_call_btn", boost::bind(&LLCallFloater::leaveCall, this)); LLView *anchor_panel = LLBottomTray::getInstance()->getChild("speak_panel"); @@ -90,6 +91,14 @@ void LLCallFloater::onOpen(const LLSD& /*key*/) ////////////////////////////////////////////////////////////////////////// /// PRIVATE SECTION ////////////////////////////////////////////////////////////////////////// + +void LLCallFloater::leaveCall() +{ + LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); + if (voice_channel && voice_channel->isActive()) + voice_channel->deactivate(); +} + void LLCallFloater::updateSession() { LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel(); @@ -139,6 +148,11 @@ void LLCallFloater::updateSession() } updateTitle(); + + //hide "Leave Call" button for nearby chat + bool isLocalChat = mVoiceType == VC_LOCAL_CHAT; + childSetVisible("leave_btn_panel", !isLocalChat); + refreshPartisipantList(); } diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index 3112b8e81b..d0a2ca5303 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -48,8 +48,8 @@ class LLSpeakerMgr; * the Resident's own microphone input volume, the audible volume of each of the other participants, * the Resident's own Voice Morphing settings (if she has subscribed to enable the feature), and Voice Recording. * - * When the Resident is engaged in Group Voice Chat, the Voice Control Panel also provides an - * 'End Call' button to allow the Resident to leave that voice channel. + * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel also provides an + * 'Leave Call' button to allow the Resident to leave that voice channel. */ class LLCallFloater : public LLDockableFloater { @@ -69,6 +69,8 @@ private: VC_PEER_TO_PEER }EVoiceControls; + void leaveCall(); + /** * Updates mSpeakerManager and list according to current Voice Channel * diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml index 04696ca2e7..c59d97457e 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -74,6 +74,7 @@ width="20" /> @@ -98,9 +101,11 @@ + width="138"> + width="138" /> + + + + + + + + + + -- cgit v1.2.3 From c8fd78466155760d34bec75f415d4879f565663c Mon Sep 17 00:00:00 2001 From: Ramzi Linden Date: Wed, 2 Dec 2009 14:57:32 -0800 Subject: DEV-43687 commit translations - Dutch(NL) set3 This adds new, raw translations to the viewer; they will not yet be formatted to fit cleanly to the user. --- .../newview/skins/default/xui/nl/role_actions.xml | 76 ++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 indra/newview/skins/default/xui/nl/role_actions.xml (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/nl/role_actions.xml b/indra/newview/skins/default/xui/nl/role_actions.xml new file mode 100644 index 0000000000..1f0a6e4235 --- /dev/null +++ b/indra/newview/skins/default/xui/nl/role_actions.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From 9779e6f55a5cfd2846f7fba685e4143666e05d62 Mon Sep 17 00:00:00 2001 From: Ramzi Linden Date: Wed, 2 Dec 2009 14:58:25 -0800 Subject: DEV-43687 commit translations - Danish(DA) set1, set2 This adds new, raw translations to the viewer; they will not yet be formatted to fit cleanly to the user. --- .../newview/skins/default/xui/da/floater_about.xml | 125 +- .../skins/default/xui/da/floater_mute_object.xml | 26 +- .../skins/default/xui/da/floater_report_abuse.xml | 206 +- .../newview/skins/default/xui/da/floater_stats.xml | 71 + .../skins/default/xui/da/menu_inventory.xml | 148 +- .../skins/default/xui/da/menu_inventory_add.xml | 32 + indra/newview/skins/default/xui/da/menu_picks.xml | 8 + .../default/xui/da/menu_places_gear_landmark.xml | 18 + .../default/xui/da/panel_block_list_sidetray.xml | 10 + .../skins/default/xui/da/panel_edit_profile.xml | 3 +- .../skins/default/xui/da/panel_group_roles.xml | 282 +- indra/newview/skins/default/xui/da/panel_login.xml | 75 +- .../skins/default/xui/da/panel_main_inventory.xml | 64 + .../default/xui/da/panel_preferences_advanced.xml | 60 +- .../default/xui/da/panel_preferences_alerts.xml | 34 +- .../default/xui/da/panel_preferences_chat.xml | 103 +- .../default/xui/da/panel_preferences_sound.xml | 78 +- .../skins/default/xui/da/panel_world_map.xml | 108 +- indra/newview/skins/default/xui/da/strings.xml | 3896 ++++++++++++++++---- .../skins/default/xui/da/teleport_strings.xml | 160 +- 20 files changed, 4164 insertions(+), 1343 deletions(-) create mode 100644 indra/newview/skins/default/xui/da/floater_stats.xml create mode 100644 indra/newview/skins/default/xui/da/menu_inventory_add.xml create mode 100644 indra/newview/skins/default/xui/da/menu_picks.xml create mode 100644 indra/newview/skins/default/xui/da/menu_places_gear_landmark.xml create mode 100644 indra/newview/skins/default/xui/da/panel_block_list_sidetray.xml create mode 100644 indra/newview/skins/default/xui/da/panel_main_inventory.xml (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml index f0c9c45d04..cdf1915d5e 100644 --- a/indra/newview/skins/default/xui/da/floater_about.xml +++ b/indra/newview/skins/default/xui/da/floater_about.xml @@ -1,44 +1,81 @@ - - - - - - Second Life er gjort muligt for dig af Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl and many others. - -Tak til følgende beboerne for at bidrage til at sikre, at dette er den bedste version til dato: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar - - - -I get by with a little help from my friends. --Richard Starkey - - - - - 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion - APR Copyright (C) 2000-2004 The Apache Software Foundation - cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) - DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc. - expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. - FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org). - GL Copyright (C) 1999-2004 Brian Paul. - Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. - jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) - jpeglib Copyright (C) 1991-1998, Thomas G. Lane. - ogg/vorbis Copyright (C) 2001, Xiphophorus - OpenSSL Copyright (C) 1998-2002 The OpenSSL Project. - SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga - SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - xmlrpc-epi Copyright (C) 2000 Epinions, Inc. - zlib Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler. - google-perftools Copyright (c) 2005, Google Inc. - -Alle rettigheder forbeholdes. Se licenses.txt for detaljer. - -Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - - - - - Du er ved [POSITION] - - + + + + [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL]) +[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] + + + Bygget med [COMPILER] version [COMPILER_VERSION] + + + Du er ved [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] i [REGION] lokaliseret på [HOSTNAME] ([HOSTIP]) +[SERVER_VERSION] +[[SERVER_RELEASE_NOTES_URL] [ReleaseNotes]] + + + CPU: [CPU] +Memory: [MEMORY_MB] MB +OS Version: [OS_VERSION] +Grafik kort mærke: [GRAPHICS_CARD_VENDOR] +Grafik kort: [GRAPHICS_CARD] + + + Windows Graphics Driver Version: [GRAPHICS_DRIVER_VERSION] + + + OpenGL Version: [OPENGL_VERSION] + +libcurl Version: [LIBCURL_VERSION] +J2C Decoder Version: [J2C_VERSION] +Audio Driver Version: [AUDIO_DRIVER_VERSION] +Qt Webkit Version: [QT_WEBKIT_VERSION] +Vivox Version: [VIVOX_VERSION] + + + (ingen) + + + Pakker tabt: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) + + + +